server, refactor: Add a conversion from bool for the filters

This commit is contained in:
Valentin Tolmer 2023-01-17 14:43:37 +01:00 committed by nitnelave
parent 807fd10d13
commit 9018e6fa34
4 changed files with 87 additions and 96 deletions

View File

@ -27,6 +27,16 @@ pub enum UserRequestFilter {
MemberOfId(GroupId), MemberOfId(GroupId),
} }
impl From<bool> for UserRequestFilter {
fn from(val: bool) -> Self {
if val {
Self::And(vec![])
} else {
Self::Not(Box::new(Self::And(vec![])))
}
}
}
#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)] #[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)]
pub enum GroupRequestFilter { pub enum GroupRequestFilter {
And(Vec<GroupRequestFilter>), And(Vec<GroupRequestFilter>),
@ -39,6 +49,16 @@ pub enum GroupRequestFilter {
Member(UserId), Member(UserId),
} }
impl From<bool> for GroupRequestFilter {
fn from(val: bool) -> Self {
if val {
Self::And(vec![])
} else {
Self::Not(Box::new(Self::And(vec![])))
}
}
}
#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone, Default)] #[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone, Default)]
pub struct CreateUserRequest { pub struct CreateUserRequest {
// Same fields as User, but no creation_date, and with password. // Same fields as User, but no creation_date, and with password.

View File

@ -121,25 +121,20 @@ fn convert_group_filter(
)?; )?;
Ok(GroupRequestFilter::Member(user_name)) Ok(GroupRequestFilter::Member(user_name))
} }
"objectclass" => match value.as_str() { "objectclass" => Ok(GroupRequestFilter::from(matches!(
"groupofuniquenames" | "groupofnames" => Ok(GroupRequestFilter::And(vec![])), value.as_str(),
_ => Ok(GroupRequestFilter::Not(Box::new(GroupRequestFilter::And( "groupofuniquenames" | "groupofnames"
vec![], ))),
)))), "dn" => Ok(get_group_id_from_distinguished_name(
}, value.to_ascii_lowercase().as_str(),
"dn" => Ok( &ldap_info.base_dn,
match get_group_id_from_distinguished_name( &ldap_info.base_dn_str,
value.to_ascii_lowercase().as_str(), )
&ldap_info.base_dn, .map(GroupRequestFilter::DisplayName)
&ldap_info.base_dn_str, .unwrap_or_else(|_| {
) { warn!("Invalid dn filter on group: {}", value);
Ok(value) => GroupRequestFilter::DisplayName(value), GroupRequestFilter::from(false)
Err(_) => { })),
warn!("Invalid dn filter on group: {}", value);
GroupRequestFilter::Not(Box::new(GroupRequestFilter::And(vec![])))
}
},
),
_ => match map_group_field(field) { _ => match map_group_field(field) {
Some(GroupColumn::DisplayName) => { Some(GroupColumn::DisplayName) => {
Ok(GroupRequestFilter::DisplayName(value.to_string())) Ok(GroupRequestFilter::DisplayName(value.to_string()))
@ -158,9 +153,7 @@ fn convert_group_filter(
field field
); );
} }
Ok(GroupRequestFilter::Not(Box::new(GroupRequestFilter::And( Ok(GroupRequestFilter::from(false))
vec![],
))))
} }
}, },
} }
@ -174,17 +167,12 @@ fn convert_group_filter(
LdapFilter::Not(filter) => Ok(GroupRequestFilter::Not(Box::new(rec(filter)?))), LdapFilter::Not(filter) => Ok(GroupRequestFilter::Not(Box::new(rec(filter)?))),
LdapFilter::Present(field) => { LdapFilter::Present(field) => {
let field = &field.to_ascii_lowercase(); let field = &field.to_ascii_lowercase();
if field == "objectclass" Ok(GroupRequestFilter::from(
|| field == "dn" field == "objectclass"
|| field == "distinguishedname" || field == "dn"
|| map_group_field(field).is_some() || field == "distinguishedname"
{ || map_group_field(field).is_some(),
Ok(GroupRequestFilter::And(vec![])) ))
} else {
Ok(GroupRequestFilter::Not(Box::new(GroupRequestFilter::And(
vec![],
))))
}
} }
_ => Err(LdapError { _ => Err(LdapError {
code: LdapResultCode::UnwillingToPerform, code: LdapResultCode::UnwillingToPerform,

View File

@ -134,35 +134,27 @@ fn convert_user_filter(ldap_info: &LdapInfo, filter: &LdapFilter) -> LdapResult<
LdapFilter::Equality(field, value) => { LdapFilter::Equality(field, value) => {
let field = &field.to_ascii_lowercase(); let field = &field.to_ascii_lowercase();
match field.as_str() { match field.as_str() {
"memberof" => { "memberof" => Ok(UserRequestFilter::MemberOf(
let group_name = get_group_id_from_distinguished_name( get_group_id_from_distinguished_name(
&value.to_ascii_lowercase(), &value.to_ascii_lowercase(),
&ldap_info.base_dn, &ldap_info.base_dn,
&ldap_info.base_dn_str, &ldap_info.base_dn_str,
)?; )?,
Ok(UserRequestFilter::MemberOf(group_name)) )),
} "objectclass" => Ok(UserRequestFilter::from(matches!(
"objectclass" => match value.to_ascii_lowercase().as_str() { value.to_ascii_lowercase().as_str(),
"person" | "inetorgperson" | "posixaccount" | "mailaccount" => { "person" | "inetorgperson" | "posixaccount" | "mailaccount"
Ok(UserRequestFilter::And(vec![])) ))),
} "dn" => Ok(get_user_id_from_distinguished_name(
_ => Ok(UserRequestFilter::Not(Box::new(UserRequestFilter::And( value.to_ascii_lowercase().as_str(),
vec![], &ldap_info.base_dn,
)))), &ldap_info.base_dn_str,
}, )
"dn" => Ok( .map(UserRequestFilter::UserId)
match get_user_id_from_distinguished_name( .unwrap_or_else(|_| {
value.to_ascii_lowercase().as_str(), warn!("Invalid dn filter on user: {}", value);
&ldap_info.base_dn, UserRequestFilter::from(false)
&ldap_info.base_dn_str, })),
) {
Ok(value) => UserRequestFilter::UserId(value),
Err(_) => {
warn!("Invalid dn filter on user: {}", value);
UserRequestFilter::Not(Box::new(UserRequestFilter::And(vec![])))
}
},
),
_ => match map_user_field(field) { _ => match map_user_field(field) {
Some(UserColumn::UserId) => Ok(UserRequestFilter::UserId(UserId::new(value))), Some(UserColumn::UserId) => Ok(UserRequestFilter::UserId(UserId::new(value))),
Some(field) => Ok(UserRequestFilter::Equality(field, value.clone())), Some(field) => Ok(UserRequestFilter::Equality(field, value.clone())),
@ -174,9 +166,7 @@ fn convert_user_filter(ldap_info: &LdapInfo, filter: &LdapFilter) -> LdapResult<
field field
); );
} }
Ok(UserRequestFilter::Not(Box::new(UserRequestFilter::And( Ok(UserRequestFilter::from(false))
vec![],
))))
} }
}, },
} }
@ -184,17 +174,12 @@ fn convert_user_filter(ldap_info: &LdapInfo, filter: &LdapFilter) -> LdapResult<
LdapFilter::Present(field) => { LdapFilter::Present(field) => {
let field = &field.to_ascii_lowercase(); let field = &field.to_ascii_lowercase();
// Check that it's a field we support. // Check that it's a field we support.
if field == "objectclass" Ok(UserRequestFilter::from(
|| field == "dn" field == "objectclass"
|| field == "distinguishedname" || field == "dn"
|| map_user_field(field).is_some() || field == "distinguishedname"
{ || map_user_field(field).is_some(),
Ok(UserRequestFilter::And(vec![])) ))
} else {
Ok(UserRequestFilter::Not(Box::new(UserRequestFilter::And(
vec![],
))))
}
} }
_ => Err(LdapError { _ => Err(LdapError {
code: LdapResultCode::UnwillingToPerform, code: LdapResultCode::UnwillingToPerform,

View File

@ -778,7 +778,7 @@ mod tests {
mock.expect_list_users() mock.expect_list_users()
.with( .with(
eq(Some(UserRequestFilter::And(vec![ eq(Some(UserRequestFilter::And(vec![
UserRequestFilter::And(vec![]), UserRequestFilter::from(true),
UserRequestFilter::UserId(UserId::new("test")), UserRequestFilter::UserId(UserId::new("test")),
]))), ]))),
eq(false), eq(false),
@ -813,7 +813,7 @@ mod tests {
async fn test_search_readonly_user() { async fn test_search_readonly_user() {
let mut mock = MockTestBackendHandler::new(); let mut mock = MockTestBackendHandler::new();
mock.expect_list_users() mock.expect_list_users()
.with(eq(Some(UserRequestFilter::And(vec![]))), eq(false)) .with(eq(Some(UserRequestFilter::from(true))), eq(false))
.times(1) .times(1)
.return_once(|_, _| Ok(vec![])); .return_once(|_, _| Ok(vec![]));
let mut ldap_handler = setup_bound_readonly_handler(mock).await; let mut ldap_handler = setup_bound_readonly_handler(mock).await;
@ -830,7 +830,7 @@ mod tests {
async fn test_search_member_of() { async fn test_search_member_of() {
let mut mock = MockTestBackendHandler::new(); let mut mock = MockTestBackendHandler::new();
mock.expect_list_users() mock.expect_list_users()
.with(eq(Some(UserRequestFilter::And(vec![]))), eq(true)) .with(eq(Some(UserRequestFilter::from(true))), eq(true))
.times(1) .times(1)
.return_once(|_, _| { .return_once(|_, _| {
Ok(vec![UserAndGroups { Ok(vec![UserAndGroups {
@ -873,7 +873,7 @@ mod tests {
mock.expect_list_users() mock.expect_list_users()
.with( .with(
eq(Some(UserRequestFilter::And(vec![ eq(Some(UserRequestFilter::And(vec![
UserRequestFilter::And(vec![]), UserRequestFilter::from(true),
UserRequestFilter::UserId(UserId::new("bob")), UserRequestFilter::UserId(UserId::new("bob")),
]))), ]))),
eq(false), eq(false),
@ -1131,7 +1131,7 @@ mod tests {
async fn test_search_groups() { async fn test_search_groups() {
let mut mock = MockTestBackendHandler::new(); let mut mock = MockTestBackendHandler::new();
mock.expect_list_groups() mock.expect_list_groups()
.with(eq(Some(GroupRequestFilter::And(vec![])))) .with(eq(Some(GroupRequestFilter::from(true))))
.times(1) .times(1)
.return_once(|_| { .return_once(|_| {
Ok(vec![ Ok(vec![
@ -1218,14 +1218,12 @@ mod tests {
GroupRequestFilter::DisplayName("group_1".to_string()), GroupRequestFilter::DisplayName("group_1".to_string()),
GroupRequestFilter::Member(UserId::new("bob")), GroupRequestFilter::Member(UserId::new("bob")),
GroupRequestFilter::DisplayName("rockstars".to_string()), GroupRequestFilter::DisplayName("rockstars".to_string()),
GroupRequestFilter::And(vec![]), GroupRequestFilter::from(true),
GroupRequestFilter::And(vec![]), GroupRequestFilter::from(true),
GroupRequestFilter::And(vec![]), GroupRequestFilter::from(true),
GroupRequestFilter::And(vec![]), GroupRequestFilter::from(true),
GroupRequestFilter::Not(Box::new(GroupRequestFilter::Not(Box::new( GroupRequestFilter::Not(Box::new(GroupRequestFilter::from(false))),
GroupRequestFilter::And(vec![]), GroupRequestFilter::from(false),
)))),
GroupRequestFilter::Not(Box::new(GroupRequestFilter::And(vec![]))),
])))) ]))))
.times(1) .times(1)
.return_once(|_| { .return_once(|_| {
@ -1321,7 +1319,7 @@ mod tests {
let mut mock = MockTestBackendHandler::new(); let mut mock = MockTestBackendHandler::new();
mock.expect_list_groups() mock.expect_list_groups()
.with(eq(Some(GroupRequestFilter::And(vec![ .with(eq(Some(GroupRequestFilter::And(vec![
GroupRequestFilter::And(vec![]), GroupRequestFilter::from(true),
GroupRequestFilter::DisplayName("rockstars".to_string()), GroupRequestFilter::DisplayName("rockstars".to_string()),
])))) ]))))
.times(1) .times(1)
@ -1409,12 +1407,12 @@ mod tests {
"bob", "bob",
)))), )))),
UserRequestFilter::UserId("bob_1".to_string().into()), UserRequestFilter::UserId("bob_1".to_string().into()),
UserRequestFilter::And(vec![]), UserRequestFilter::from(true),
UserRequestFilter::Not(Box::new(UserRequestFilter::And(vec![]))), UserRequestFilter::from(false),
UserRequestFilter::And(vec![]), UserRequestFilter::from(true),
UserRequestFilter::And(vec![]), UserRequestFilter::from(true),
UserRequestFilter::Not(Box::new(UserRequestFilter::And(vec![]))), UserRequestFilter::from(false),
UserRequestFilter::Not(Box::new(UserRequestFilter::And(vec![]))), UserRequestFilter::from(false),
], ],
)]))), )]))),
eq(false), eq(false),
@ -1562,7 +1560,7 @@ mod tests {
}]) }])
}); });
mock.expect_list_groups() mock.expect_list_groups()
.with(eq(Some(GroupRequestFilter::And(vec![])))) .with(eq(Some(GroupRequestFilter::from(true))))
.times(1) .times(1)
.return_once(|_| { .return_once(|_| {
Ok(vec![Group { Ok(vec![Group {
@ -1637,7 +1635,7 @@ mod tests {
}]) }])
}); });
mock.expect_list_groups() mock.expect_list_groups()
.with(eq(Some(GroupRequestFilter::And(vec![])))) .with(eq(Some(GroupRequestFilter::from(true))))
.returning(|_| { .returning(|_| {
Ok(vec![Group { Ok(vec![Group {
id: GroupId(1), id: GroupId(1),
@ -2093,7 +2091,7 @@ mod tests {
async fn test_search_filter_non_attribute() { async fn test_search_filter_non_attribute() {
let mut mock = MockTestBackendHandler::new(); let mut mock = MockTestBackendHandler::new();
mock.expect_list_users() mock.expect_list_users()
.with(eq(Some(UserRequestFilter::And(vec![]))), eq(false)) .with(eq(Some(UserRequestFilter::from(true))), eq(false))
.times(1) .times(1)
.return_once(|_, _| Ok(vec![])); .return_once(|_, _| Ok(vec![]));
let mut ldap_handler = setup_bound_admin_handler(mock).await; let mut ldap_handler = setup_bound_admin_handler(mock).await;