mirror of
				https://github.com/nitnelave/lldap.git
				synced 2023-04-12 14:25:13 +00:00 
			
		
		
		
	server: Update permission checks for strict_readonly
This commit is contained in:
		
							parent
							
								
									1325ad80b6
								
							
						
					
					
						commit
						1535b991b6
					
				@ -430,7 +430,7 @@ async fn opaque_register_start<Backend>(
 | 
				
			|||||||
    data: web::Data<AppState<Backend>>,
 | 
					    data: web::Data<AppState<Backend>>,
 | 
				
			||||||
) -> TcpResult<registration::ServerRegistrationStartResponse>
 | 
					) -> TcpResult<registration::ServerRegistrationStartResponse>
 | 
				
			||||||
where
 | 
					where
 | 
				
			||||||
    Backend: OpaqueHandler + 'static,
 | 
					    Backend: BackendHandler + OpaqueHandler + 'static,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    use actix_web::FromRequest;
 | 
					    use actix_web::FromRequest;
 | 
				
			||||||
    let validation_result = BearerAuth::from_request(&request, &mut payload.0)
 | 
					    let validation_result = BearerAuth::from_request(&request, &mut payload.0)
 | 
				
			||||||
@ -448,8 +448,14 @@ where
 | 
				
			|||||||
        .await
 | 
					        .await
 | 
				
			||||||
        .map_err(|e| TcpError::BadRequest(format!("{:#?}", e)))?
 | 
					        .map_err(|e| TcpError::BadRequest(format!("{:#?}", e)))?
 | 
				
			||||||
        .into_inner();
 | 
					        .into_inner();
 | 
				
			||||||
    let user_id = ®istration_start_request.username;
 | 
					    let user_id = UserId::new(®istration_start_request.username);
 | 
				
			||||||
    if !validation_result.can_write(user_id) {
 | 
					    let user_is_admin = data
 | 
				
			||||||
 | 
					        .backend_handler
 | 
				
			||||||
 | 
					        .get_user_groups(&user_id)
 | 
				
			||||||
 | 
					        .await?
 | 
				
			||||||
 | 
					        .iter()
 | 
				
			||||||
 | 
					        .any(|g| g.display_name == "lldap_admin");
 | 
				
			||||||
 | 
					    if !validation_result.can_change_password(&user_id, user_is_admin) {
 | 
				
			||||||
        return Err(TcpError::UnauthorizedError(
 | 
					        return Err(TcpError::UnauthorizedError(
 | 
				
			||||||
            "Not authorized to change the user's password".to_string(),
 | 
					            "Not authorized to change the user's password".to_string(),
 | 
				
			||||||
        ));
 | 
					        ));
 | 
				
			||||||
@ -466,7 +472,7 @@ async fn opaque_register_start_handler<Backend>(
 | 
				
			|||||||
    data: web::Data<AppState<Backend>>,
 | 
					    data: web::Data<AppState<Backend>>,
 | 
				
			||||||
) -> ApiResult<registration::ServerRegistrationStartResponse>
 | 
					) -> ApiResult<registration::ServerRegistrationStartResponse>
 | 
				
			||||||
where
 | 
					where
 | 
				
			||||||
    Backend: OpaqueHandler + 'static,
 | 
					    Backend: BackendHandler + OpaqueHandler + 'static,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    opaque_register_start(request, payload, data)
 | 
					    opaque_register_start(request, payload, data)
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
@ -559,13 +565,14 @@ where
 | 
				
			|||||||
#[derive(Clone, Copy, PartialEq, Debug)]
 | 
					#[derive(Clone, Copy, PartialEq, Debug)]
 | 
				
			||||||
pub enum Permission {
 | 
					pub enum Permission {
 | 
				
			||||||
    Admin,
 | 
					    Admin,
 | 
				
			||||||
 | 
					    PasswordManager,
 | 
				
			||||||
    Readonly,
 | 
					    Readonly,
 | 
				
			||||||
    Regular,
 | 
					    Regular,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug, Clone, PartialEq)]
 | 
				
			||||||
pub struct ValidationResults {
 | 
					pub struct ValidationResults {
 | 
				
			||||||
    pub user: String,
 | 
					    pub user: UserId,
 | 
				
			||||||
    pub permission: Permission,
 | 
					    pub permission: Permission,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -573,7 +580,7 @@ impl ValidationResults {
 | 
				
			|||||||
    #[cfg(test)]
 | 
					    #[cfg(test)]
 | 
				
			||||||
    pub fn admin() -> Self {
 | 
					    pub fn admin() -> Self {
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            user: "admin".to_string(),
 | 
					            user: UserId::new("admin"),
 | 
				
			||||||
            permission: Permission::Admin,
 | 
					            permission: Permission::Admin,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -585,19 +592,29 @@ impl ValidationResults {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    #[must_use]
 | 
					    #[must_use]
 | 
				
			||||||
    pub fn is_admin_or_readonly(&self) -> bool {
 | 
					    pub fn is_admin_or_readonly(&self) -> bool {
 | 
				
			||||||
        self.permission == Permission::Admin || self.permission == Permission::Readonly
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[must_use]
 | 
					 | 
				
			||||||
    pub fn can_read(&self, user: &str) -> bool {
 | 
					 | 
				
			||||||
        self.permission == Permission::Admin
 | 
					        self.permission == Permission::Admin
 | 
				
			||||||
            || self.permission == Permission::Readonly
 | 
					            || self.permission == Permission::Readonly
 | 
				
			||||||
            || self.user == user
 | 
					            || self.permission == Permission::PasswordManager
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[must_use]
 | 
					    #[must_use]
 | 
				
			||||||
    pub fn can_write(&self, user: &str) -> bool {
 | 
					    pub fn can_read(&self, user: &UserId) -> bool {
 | 
				
			||||||
        self.permission == Permission::Admin || self.user == user
 | 
					        self.permission == Permission::Admin
 | 
				
			||||||
 | 
					            || self.permission == Permission::PasswordManager
 | 
				
			||||||
 | 
					            || self.permission == Permission::Readonly
 | 
				
			||||||
 | 
					            || &self.user == user
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[must_use]
 | 
				
			||||||
 | 
					    pub fn can_change_password(&self, user: &UserId, user_is_admin: bool) -> bool {
 | 
				
			||||||
 | 
					        self.permission == Permission::Admin
 | 
				
			||||||
 | 
					            || (self.permission == Permission::PasswordManager && !user_is_admin)
 | 
				
			||||||
 | 
					            || &self.user == user
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[must_use]
 | 
				
			||||||
 | 
					    pub fn can_write(&self, user: &UserId) -> bool {
 | 
				
			||||||
 | 
					        self.permission == Permission::Admin || &self.user == user
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -627,10 +644,12 @@ pub(crate) fn check_if_token_is_valid<Backend>(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    let is_in_group = |name| token.claims().groups.contains(name);
 | 
					    let is_in_group = |name| token.claims().groups.contains(name);
 | 
				
			||||||
    Ok(ValidationResults {
 | 
					    Ok(ValidationResults {
 | 
				
			||||||
        user: token.claims().user.clone(),
 | 
					        user: UserId::new(&token.claims().user),
 | 
				
			||||||
        permission: if is_in_group("lldap_admin") {
 | 
					        permission: if is_in_group("lldap_admin") {
 | 
				
			||||||
            Permission::Admin
 | 
					            Permission::Admin
 | 
				
			||||||
        } else if is_in_group("lldap_readonly") {
 | 
					        } else if is_in_group("lldap_password_manager") {
 | 
				
			||||||
 | 
					            Permission::PasswordManager
 | 
				
			||||||
 | 
					        } else if is_in_group("lldap_strict_readonly") {
 | 
				
			||||||
            Permission::Readonly
 | 
					            Permission::Readonly
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            Permission::Regular
 | 
					            Permission::Regular
 | 
				
			||||||
 | 
				
			|||||||
@ -121,14 +121,15 @@ impl<Handler: BackendHandler + Sync> Mutation<Handler> {
 | 
				
			|||||||
        span.in_scope(|| {
 | 
					        span.in_scope(|| {
 | 
				
			||||||
            debug!(?user.id);
 | 
					            debug!(?user.id);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        if !context.validation_result.can_write(&user.id) {
 | 
					        let user_id = UserId::new(&user.id);
 | 
				
			||||||
 | 
					        if !context.validation_result.can_write(&user_id) {
 | 
				
			||||||
            span.in_scope(|| debug!("Unauthorized"));
 | 
					            span.in_scope(|| debug!("Unauthorized"));
 | 
				
			||||||
            return Err("Unauthorized user update".into());
 | 
					            return Err("Unauthorized user update".into());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        context
 | 
					        context
 | 
				
			||||||
            .handler
 | 
					            .handler
 | 
				
			||||||
            .update_user(UpdateUserRequest {
 | 
					            .update_user(UpdateUserRequest {
 | 
				
			||||||
                user_id: UserId::new(&user.id),
 | 
					                user_id,
 | 
				
			||||||
                email: user.email,
 | 
					                email: user.email,
 | 
				
			||||||
                display_name: user.display_name,
 | 
					                display_name: user.display_name,
 | 
				
			||||||
                first_name: user.first_name,
 | 
					                first_name: user.first_name,
 | 
				
			||||||
@ -200,13 +201,14 @@ impl<Handler: BackendHandler + Sync> Mutation<Handler> {
 | 
				
			|||||||
            span.in_scope(|| debug!("Unauthorized"));
 | 
					            span.in_scope(|| debug!("Unauthorized"));
 | 
				
			||||||
            return Err("Unauthorized group membership modification".into());
 | 
					            return Err("Unauthorized group membership modification".into());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        let user_id = UserId::new(&user_id);
 | 
				
			||||||
        if context.validation_result.user == user_id && group_id == 1 {
 | 
					        if context.validation_result.user == user_id && group_id == 1 {
 | 
				
			||||||
            span.in_scope(|| debug!("Cannot remove admin rights for current user"));
 | 
					            span.in_scope(|| debug!("Cannot remove admin rights for current user"));
 | 
				
			||||||
            return Err("Cannot remove admin rights for current user".into());
 | 
					            return Err("Cannot remove admin rights for current user".into());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        context
 | 
					        context
 | 
				
			||||||
            .handler
 | 
					            .handler
 | 
				
			||||||
            .remove_user_from_group(&UserId::new(&user_id), GroupId(group_id))
 | 
					            .remove_user_from_group(&user_id, GroupId(group_id))
 | 
				
			||||||
            .instrument(span)
 | 
					            .instrument(span)
 | 
				
			||||||
            .await?;
 | 
					            .await?;
 | 
				
			||||||
        Ok(Success::new())
 | 
					        Ok(Success::new())
 | 
				
			||||||
@ -217,6 +219,7 @@ impl<Handler: BackendHandler + Sync> Mutation<Handler> {
 | 
				
			|||||||
        span.in_scope(|| {
 | 
					        span.in_scope(|| {
 | 
				
			||||||
            debug!(?user_id);
 | 
					            debug!(?user_id);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					        let user_id = UserId::new(&user_id);
 | 
				
			||||||
        if !context.validation_result.is_admin() {
 | 
					        if !context.validation_result.is_admin() {
 | 
				
			||||||
            span.in_scope(|| debug!("Unauthorized"));
 | 
					            span.in_scope(|| debug!("Unauthorized"));
 | 
				
			||||||
            return Err("Unauthorized user deletion".into());
 | 
					            return Err("Unauthorized user deletion".into());
 | 
				
			||||||
@ -227,7 +230,7 @@ impl<Handler: BackendHandler + Sync> Mutation<Handler> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        context
 | 
					        context
 | 
				
			||||||
            .handler
 | 
					            .handler
 | 
				
			||||||
            .delete_user(&UserId::new(&user_id))
 | 
					            .delete_user(&user_id)
 | 
				
			||||||
            .instrument(span)
 | 
					            .instrument(span)
 | 
				
			||||||
            .await?;
 | 
					            .await?;
 | 
				
			||||||
        Ok(Success::new())
 | 
					        Ok(Success::new())
 | 
				
			||||||
 | 
				
			|||||||
@ -113,13 +113,14 @@ impl<Handler: BackendHandler + Sync> Query<Handler> {
 | 
				
			|||||||
        span.in_scope(|| {
 | 
					        span.in_scope(|| {
 | 
				
			||||||
            debug!(?user_id);
 | 
					            debug!(?user_id);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					        let user_id = UserId::new(&user_id);
 | 
				
			||||||
        if !context.validation_result.can_read(&user_id) {
 | 
					        if !context.validation_result.can_read(&user_id) {
 | 
				
			||||||
            span.in_scope(|| debug!("Unauthorized"));
 | 
					            span.in_scope(|| debug!("Unauthorized"));
 | 
				
			||||||
            return Err("Unauthorized access to user data".into());
 | 
					            return Err("Unauthorized access to user data".into());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Ok(context
 | 
					        Ok(context
 | 
				
			||||||
            .handler
 | 
					            .handler
 | 
				
			||||||
            .get_user_details(&UserId::new(&user_id))
 | 
					            .get_user_details(&user_id)
 | 
				
			||||||
            .instrument(span)
 | 
					            .instrument(span)
 | 
				
			||||||
            .await
 | 
					            .await
 | 
				
			||||||
            .map(Into::into)?)
 | 
					            .map(Into::into)?)
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@ use crate::{
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        opaque_handler::OpaqueHandler,
 | 
					        opaque_handler::OpaqueHandler,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    infra::auth_service::Permission,
 | 
					    infra::auth_service::{Permission, ValidationResults},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use anyhow::{bail, Context, Result};
 | 
					use anyhow::{bail, Context, Result};
 | 
				
			||||||
use itertools::Itertools;
 | 
					use itertools::Itertools;
 | 
				
			||||||
@ -450,7 +450,7 @@ fn root_dse_response(base_dn: &str) -> LdapOp {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct LdapHandler<Backend: BackendHandler + LoginHandler + OpaqueHandler> {
 | 
					pub struct LdapHandler<Backend: BackendHandler + LoginHandler + OpaqueHandler> {
 | 
				
			||||||
    user_info: Option<(UserId, Permission)>,
 | 
					    user_info: Option<ValidationResults>,
 | 
				
			||||||
    backend_handler: Backend,
 | 
					    backend_handler: Backend,
 | 
				
			||||||
    pub base_dn: Vec<(String, String)>,
 | 
					    pub base_dn: Vec<(String, String)>,
 | 
				
			||||||
    base_dn_str: String,
 | 
					    base_dn_str: String,
 | 
				
			||||||
@ -509,16 +509,18 @@ impl<Backend: BackendHandler + LoginHandler + OpaqueHandler> LdapHandler<Backend
 | 
				
			|||||||
                        .map(|groups| groups.iter().any(|g| g.display_name == name))
 | 
					                        .map(|groups| groups.iter().any(|g| g.display_name == name))
 | 
				
			||||||
                        .unwrap_or(false)
 | 
					                        .unwrap_or(false)
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
                self.user_info = Some((
 | 
					                self.user_info = Some(ValidationResults {
 | 
				
			||||||
                    user_id,
 | 
					                    user: user_id,
 | 
				
			||||||
                    if is_in_group("lldap_admin") {
 | 
					                    permission: if is_in_group("lldap_admin") {
 | 
				
			||||||
                        Permission::Admin
 | 
					                        Permission::Admin
 | 
				
			||||||
                    } else if is_in_group("lldap_readonly") {
 | 
					                    } else if is_in_group("lldap_password_manager") {
 | 
				
			||||||
 | 
					                        Permission::PasswordManager
 | 
				
			||||||
 | 
					                    } else if is_in_group("lldap_strict_readonly") {
 | 
				
			||||||
                        Permission::Readonly
 | 
					                        Permission::Readonly
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        Permission::Regular
 | 
					                        Permission::Regular
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                ));
 | 
					                });
 | 
				
			||||||
                debug!("Success!");
 | 
					                debug!("Success!");
 | 
				
			||||||
                (LdapResultCode::Success, "".to_string())
 | 
					                (LdapResultCode::Success, "".to_string())
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -553,7 +555,7 @@ impl<Backend: BackendHandler + LoginHandler + OpaqueHandler> LdapHandler<Backend
 | 
				
			|||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        request: &LdapPasswordModifyRequest,
 | 
					        request: &LdapPasswordModifyRequest,
 | 
				
			||||||
    ) -> Vec<LdapOp> {
 | 
					    ) -> Vec<LdapOp> {
 | 
				
			||||||
        let (user_id, permission) = match &self.user_info {
 | 
					        let credentials = match &self.user_info {
 | 
				
			||||||
            Some(info) => info,
 | 
					            Some(info) => info,
 | 
				
			||||||
            _ => {
 | 
					            _ => {
 | 
				
			||||||
                return vec![make_search_error(
 | 
					                return vec![make_search_error(
 | 
				
			||||||
@ -578,15 +580,12 @@ impl<Backend: BackendHandler + LoginHandler + OpaqueHandler> LdapHandler<Backend
 | 
				
			|||||||
                                )]
 | 
					                                )]
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        };
 | 
					                        };
 | 
				
			||||||
                        if !(*permission == Permission::Admin
 | 
					                        if !credentials.can_change_password(&uid, user_is_admin) {
 | 
				
			||||||
                            || user_id == &uid
 | 
					 | 
				
			||||||
                            || (*permission == Permission::Readonly && !user_is_admin))
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            return vec![make_extended_response(
 | 
					                            return vec![make_extended_response(
 | 
				
			||||||
                                LdapResultCode::InsufficentAccessRights,
 | 
					                                LdapResultCode::InsufficentAccessRights,
 | 
				
			||||||
                                format!(
 | 
					                                format!(
 | 
				
			||||||
                                    r#"User `{}` cannot modify the password of user `{}`"#,
 | 
					                                    r#"User `{}` cannot modify the password of user `{}`"#,
 | 
				
			||||||
                                    &user_id, &uid
 | 
					                                    &credentials.user, &uid
 | 
				
			||||||
                                ),
 | 
					                                ),
 | 
				
			||||||
                            )];
 | 
					                            )];
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
@ -626,15 +625,14 @@ impl<Backend: BackendHandler + LoginHandler + OpaqueHandler> LdapHandler<Backend
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub async fn do_search_or_dse(&mut self, request: &LdapSearchRequest) -> Vec<LdapOp> {
 | 
					    pub async fn do_search_or_dse(&mut self, request: &LdapSearchRequest) -> Vec<LdapOp> {
 | 
				
			||||||
        let user_filter = match self.user_info.clone() {
 | 
					        let user_info = match &self.user_info {
 | 
				
			||||||
            Some((_, Permission::Admin)) | Some((_, Permission::Readonly)) => None,
 | 
					 | 
				
			||||||
            Some((user_id, Permission::Regular)) => Some(user_id),
 | 
					 | 
				
			||||||
            None => {
 | 
					            None => {
 | 
				
			||||||
                return vec![make_search_error(
 | 
					                return vec![make_search_error(
 | 
				
			||||||
                    LdapResultCode::InsufficentAccessRights,
 | 
					                    LdapResultCode::InsufficentAccessRights,
 | 
				
			||||||
                    "No user currently bound".to_string(),
 | 
					                    "No user currently bound".to_string(),
 | 
				
			||||||
                )];
 | 
					                )]
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            Some(u) => u,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        if request.base.is_empty()
 | 
					        if request.base.is_empty()
 | 
				
			||||||
            && request.scope == LdapSearchScope::Base
 | 
					            && request.scope == LdapSearchScope::Base
 | 
				
			||||||
@ -643,6 +641,11 @@ impl<Backend: BackendHandler + LoginHandler + OpaqueHandler> LdapHandler<Backend
 | 
				
			|||||||
            debug!("rootDSE request");
 | 
					            debug!("rootDSE request");
 | 
				
			||||||
            return vec![root_dse_response(&self.base_dn_str), make_search_success()];
 | 
					            return vec![root_dse_response(&self.base_dn_str), make_search_success()];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        let user_filter = if user_info.is_admin_or_readonly() {
 | 
				
			||||||
 | 
					            None
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Some(user_info.user.clone())
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
        self.do_search(request, user_filter).await
 | 
					        self.do_search(request, user_filter).await
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1135,7 +1138,13 @@ mod tests {
 | 
				
			|||||||
    async fn setup_bound_readonly_handler(
 | 
					    async fn setup_bound_readonly_handler(
 | 
				
			||||||
        mock: MockTestBackendHandler,
 | 
					        mock: MockTestBackendHandler,
 | 
				
			||||||
    ) -> LdapHandler<MockTestBackendHandler> {
 | 
					    ) -> LdapHandler<MockTestBackendHandler> {
 | 
				
			||||||
        setup_bound_handler_with_group(mock, "lldap_readonly").await
 | 
					        setup_bound_handler_with_group(mock, "lldap_strict_readonly").await
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async fn setup_bound_password_manager_handler(
 | 
				
			||||||
 | 
					        mock: MockTestBackendHandler,
 | 
				
			||||||
 | 
					    ) -> LdapHandler<MockTestBackendHandler> {
 | 
				
			||||||
 | 
					        setup_bound_handler_with_group(mock, "lldap_password_manager").await
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async fn setup_bound_admin_handler(
 | 
					    async fn setup_bound_admin_handler(
 | 
				
			||||||
@ -2312,7 +2321,7 @@ mod tests {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[tokio::test]
 | 
					    #[tokio::test]
 | 
				
			||||||
    async fn test_password_change_readonly() {
 | 
					    async fn test_password_change_password_manager() {
 | 
				
			||||||
        let mut mock = MockTestBackendHandler::new();
 | 
					        let mut mock = MockTestBackendHandler::new();
 | 
				
			||||||
        mock.expect_get_user_groups()
 | 
					        mock.expect_get_user_groups()
 | 
				
			||||||
            .with(eq(UserId::new("bob")))
 | 
					            .with(eq(UserId::new("bob")))
 | 
				
			||||||
@ -2340,7 +2349,7 @@ mod tests {
 | 
				
			|||||||
        mock.expect_registration_finish()
 | 
					        mock.expect_registration_finish()
 | 
				
			||||||
            .times(1)
 | 
					            .times(1)
 | 
				
			||||||
            .return_once(|_| Ok(()));
 | 
					            .return_once(|_| Ok(()));
 | 
				
			||||||
        let mut ldap_handler = setup_bound_readonly_handler(mock).await;
 | 
					        let mut ldap_handler = setup_bound_password_manager_handler(mock).await;
 | 
				
			||||||
        let request = LdapOp::ExtendedRequest(
 | 
					        let request = LdapOp::ExtendedRequest(
 | 
				
			||||||
            LdapPasswordModifyRequest {
 | 
					            LdapPasswordModifyRequest {
 | 
				
			||||||
                user_identity: Some("uid=bob,ou=people,dc=example,dc=com".to_string()),
 | 
					                user_identity: Some("uid=bob,ou=people,dc=example,dc=com".to_string()),
 | 
				
			||||||
@ -2409,7 +2418,7 @@ mod tests {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[tokio::test]
 | 
					    #[tokio::test]
 | 
				
			||||||
    async fn test_password_change_unauthorized_readonly() {
 | 
					    async fn test_password_change_unauthorized_password_manager() {
 | 
				
			||||||
        let mut mock = MockTestBackendHandler::new();
 | 
					        let mut mock = MockTestBackendHandler::new();
 | 
				
			||||||
        let mut groups = HashSet::new();
 | 
					        let mut groups = HashSet::new();
 | 
				
			||||||
        groups.insert(GroupDetails {
 | 
					        groups.insert(GroupDetails {
 | 
				
			||||||
@ -2422,6 +2431,31 @@ mod tests {
 | 
				
			|||||||
            .with(eq(UserId::new("bob")))
 | 
					            .with(eq(UserId::new("bob")))
 | 
				
			||||||
            .times(1)
 | 
					            .times(1)
 | 
				
			||||||
            .return_once(|_| Ok(groups));
 | 
					            .return_once(|_| Ok(groups));
 | 
				
			||||||
 | 
					        let mut ldap_handler = setup_bound_password_manager_handler(mock).await;
 | 
				
			||||||
 | 
					        let request = LdapOp::ExtendedRequest(
 | 
				
			||||||
 | 
					            LdapPasswordModifyRequest {
 | 
				
			||||||
 | 
					                user_identity: Some("uid=bob,ou=people,dc=example,dc=com".to_string()),
 | 
				
			||||||
 | 
					                old_password: Some("pass".to_string()),
 | 
				
			||||||
 | 
					                new_password: Some("password".to_string()),
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            .into(),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        assert_eq!(
 | 
				
			||||||
 | 
					            ldap_handler.handle_ldap_message(request).await,
 | 
				
			||||||
 | 
					            Some(vec![make_extended_response(
 | 
				
			||||||
 | 
					                LdapResultCode::InsufficentAccessRights,
 | 
				
			||||||
 | 
					                "User `test` cannot modify the password of user `bob`".to_string(),
 | 
				
			||||||
 | 
					            )])
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[tokio::test]
 | 
				
			||||||
 | 
					    async fn test_password_change_unauthorized_readonly() {
 | 
				
			||||||
 | 
					        let mut mock = MockTestBackendHandler::new();
 | 
				
			||||||
 | 
					        mock.expect_get_user_groups()
 | 
				
			||||||
 | 
					            .with(eq(UserId::new("bob")))
 | 
				
			||||||
 | 
					            .times(1)
 | 
				
			||||||
 | 
					            .return_once(|_| Ok(HashSet::new()));
 | 
				
			||||||
        let mut ldap_handler = setup_bound_readonly_handler(mock).await;
 | 
					        let mut ldap_handler = setup_bound_readonly_handler(mock).await;
 | 
				
			||||||
        let request = LdapOp::ExtendedRequest(
 | 
					        let request = LdapOp::ExtendedRequest(
 | 
				
			||||||
            LdapPasswordModifyRequest {
 | 
					            LdapPasswordModifyRequest {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user