graphql: Add a filter by group

This commit is contained in:
Valentin Tolmer 2021-09-24 22:35:31 +02:00 committed by nitnelave
parent 09a23a1e59
commit eb974e781c
5 changed files with 31 additions and 10 deletions

View File

@ -29,6 +29,8 @@ input RequestFilter {
all: [RequestFilter!] all: [RequestFilter!]
not: RequestFilter not: RequestFilter
eq: EqualityConstraint eq: EqualityConstraint
memberOf: String
memberOfId: Int
} }
"DateTime" "DateTime"

View File

@ -48,8 +48,10 @@ pub enum RequestFilter {
Or(Vec<RequestFilter>), Or(Vec<RequestFilter>),
Not(Box<RequestFilter>), Not(Box<RequestFilter>),
Equality(String, String), Equality(String, String),
// Check if a user belongs to a group. // Check if a user belongs to a group identified by name.
MemberOf(String), MemberOf(String),
// Same, by id.
MemberOfId(GroupId),
} }
#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone, Default)] #[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone, Default)]

View File

@ -65,6 +65,10 @@ fn get_filter_expr(filter: RequestFilter) -> (RequiresGroup, SimpleExpr) {
RequiresGroup(true), RequiresGroup(true),
Expr::col((Groups::Table, Groups::DisplayName)).eq(group), Expr::col((Groups::Table, Groups::DisplayName)).eq(group),
), ),
MemberOfId(group_id) => (
RequiresGroup(true),
Expr::col((Groups::Table, Groups::GroupId)).eq(group_id),
),
} }
} }

View File

@ -1,4 +1,4 @@
use crate::domain::handler::{BackendHandler, GroupIdAndName}; use crate::domain::handler::{BackendHandler, GroupId, GroupIdAndName};
use juniper::{graphql_object, FieldResult, GraphQLInputObject}; use juniper::{graphql_object, FieldResult, GraphQLInputObject};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::convert::TryInto; use std::convert::TryInto;
@ -16,6 +16,8 @@ pub struct RequestFilter {
all: Option<Vec<RequestFilter>>, all: Option<Vec<RequestFilter>>,
not: Option<Box<RequestFilter>>, not: Option<Box<RequestFilter>>,
eq: Option<EqualityConstraint>, eq: Option<EqualityConstraint>,
member_of: Option<String>,
member_of_id: Option<i32>,
} }
impl TryInto<DomainRequestFilter> for RequestFilter { impl TryInto<DomainRequestFilter> for RequestFilter {
@ -34,6 +36,12 @@ impl TryInto<DomainRequestFilter> for RequestFilter {
if self.eq.is_some() { if self.eq.is_some() {
field_count += 1; field_count += 1;
} }
if self.member_of.is_some() {
field_count += 1;
}
if self.member_of_id.is_some() {
field_count += 1;
}
if field_count == 0 { if field_count == 0 {
return Err("No field specified in request filter".to_string()); return Err("No field specified in request filter".to_string());
} }
@ -60,6 +68,12 @@ impl TryInto<DomainRequestFilter> for RequestFilter {
if let Some(c) = self.not { if let Some(c) = self.not {
return Ok(DomainRequestFilter::Not(Box::new((*c).try_into()?))); return Ok(DomainRequestFilter::Not(Box::new((*c).try_into()?)));
} }
if let Some(group) = self.member_of {
return Ok(DomainRequestFilter::MemberOf(group));
}
if let Some(group_id) = self.member_of_id {
return Ok(DomainRequestFilter::MemberOfId(GroupId(group_id)));
}
unreachable!(); unreachable!();
} }
} }
@ -239,10 +253,7 @@ impl<Handler: BackendHandler> From<DomainGroup> for Group<Handler> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::{ use crate::{domain::handler::MockTestBackendHandler, infra::auth_service::ValidationResults};
domain::handler::{GroupId, GroupIdAndName, MockTestBackendHandler},
infra::auth_service::ValidationResults,
};
use juniper::{ use juniper::{
execute, graphql_value, DefaultScalarValue, EmptyMutation, EmptySubscription, GraphQLType, execute, graphql_value, DefaultScalarValue, EmptyMutation, EmptySubscription, GraphQLType,
RootNode, Variables, RootNode, Variables,

View File

@ -318,8 +318,7 @@ impl<Backend: BackendHandler + LoginHandler> LdapHandler<Backend> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::domain::handler::BindRequest; use crate::domain::handler::{BindRequest, MockTestBackendHandler};
use crate::domain::handler::MockTestBackendHandler;
use mockall::predicate::eq; use mockall::predicate::eq;
use tokio; use tokio;
@ -665,14 +664,17 @@ mod tests {
msgid: 2, msgid: 2,
base: "ou=people,dc=example,dc=com".to_string(), base: "ou=people,dc=example,dc=com".to_string(),
scope: LdapSearchScope::Base, scope: LdapSearchScope::Base,
filter: LdapFilter::Present("uid".to_string()), filter: LdapFilter::Substring(
"uid".to_string(),
ldap3_server::proto::LdapSubstringFilter::default(),
),
attrs: vec!["objectClass".to_string()], attrs: vec!["objectClass".to_string()],
}; };
assert_eq!( assert_eq!(
ldap_handler.do_search(&request).await, ldap_handler.do_search(&request).await,
vec![request.gen_error( vec![request.gen_error(
LdapResultCode::UnwillingToPerform, LdapResultCode::UnwillingToPerform,
"Unsupported filter".to_string() "Unsupported filter: Unsupported filter: Substring(\"uid\", LdapSubstringFilter { initial: None, any: [], final_: None })".to_string()
)] )]
); );
} }