diff --git a/src/biz/collab/access_control.rs b/src/biz/collab/access_control.rs index 5fa9f688..b040c4ef 100644 --- a/src/biz/collab/access_control.rs +++ b/src/biz/collab/access_control.rs @@ -36,6 +36,7 @@ where } #[instrument(level = "debug", skip_all, err)] + #[allow(clippy::blocks_in_conditions)] async fn check_collab_permission( &self, oid: &str, diff --git a/src/biz/collab/storage.rs b/src/biz/collab/storage.rs index 6720bd35..a877b2e8 100644 --- a/src/biz/collab/storage.rs +++ b/src/biz/collab/storage.rs @@ -73,6 +73,60 @@ where opened_collab_by_object_id: Arc::new(RwLock::new(HashMap::new())), } } + + async fn check_collab_permission( + &self, + workspace_id: &str, + uid: &i64, + params: &CollabParams, + transaction: &mut Transaction<'_, sqlx::Postgres>, + ) -> Result<(), AppError> { + // Check if the user has enough permissions to insert collab + // 1. If the collab already exists, check if the user has enough permissions to update collab + // 2. If the collab doesn't exist, check if the user has enough permissions to create collab. + let collab_exists = is_collab_exists(¶ms.object_id, transaction.deref_mut()).await?; + if collab_exists { + // If the collab already exists, check if the user has enough permissions to update collab + let can_write = self + .access_control + .get_or_refresh_collab_access_level(uid, ¶ms.object_id, transaction.deref_mut()) + .await + .context(format!( + "Can't find the access level when user:{} try to insert collab", + uid + ))? + .can_write(); + if !can_write { + return Err(AppError::NotEnoughPermissions(format!( + "user:{} doesn't have enough permissions to update collab {}", + uid, params.object_id + ))); + } + } else { + // If the collab doesn't exist, check if the user has enough permissions to create collab. + // If the user is the owner or member of the workspace, the user can create collab. + let can_write_workspace = self + .access_control + .get_user_workspace_role(uid, workspace_id, transaction.deref_mut()) + .await? + .can_create_collab(); + + if !can_write_workspace { + return Err(AppError::NotEnoughPermissions(format!( + "user:{} doesn't have enough permissions to insert collab {}", + uid, params.object_id + ))); + } + + // Cache the access level if the user has enough permissions to create collab. + self + .access_control + .cache_collab_access_level(uid, ¶ms.object_id, AFAccessLevel::FullAccess) + .await?; + } + + Ok(()) + } } #[async_trait] @@ -124,6 +178,7 @@ where } #[instrument(level = "trace", skip(self, params), oid = %params.oid, err)] + #[allow(clippy::blocks_in_conditions)] async fn upsert_collab_with_transaction( &self, workspace_id: &str, @@ -132,46 +187,9 @@ where transaction: &mut Transaction<'_, sqlx::Postgres>, ) -> DatabaseResult<()> { params.validate()?; - - // Check if the user has enough permissions to insert collab - // 1. If the collab already exists, check if the user has enough permissions to update collab - // 2. If the collab doesn't exist, check if the user has enough permissions to create collab. - let has_permission = if is_collab_exists(¶ms.object_id, transaction.deref_mut()).await? { - // If the collab already exists, check if the user has enough permissions to update collab - let level = self - .access_control - .get_or_refresh_collab_access_level(uid, ¶ms.object_id, transaction.deref_mut()) - .await - .context(format!( - "Can't find the access level when user:{} try to insert collab", - uid - ))?; - level.can_write() - } else { - // If the collab doesn't exist, check if the user has enough permissions to create collab. - // If the user is the owner or member of the workspace, the user can create collab. - let can_write_workspace = self - .access_control - .get_user_workspace_role(uid, workspace_id, transaction.deref_mut()) - .await? - .can_create_collab(); - - // Cache the access level if the user has enough permissions to create collab. - if can_write_workspace { - self - .access_control - .cache_collab_access_level(uid, ¶ms.object_id, AFAccessLevel::FullAccess) - .await?; - } - can_write_workspace - }; - - if !has_permission { - return Err(AppError::NotEnoughPermissions(format!( - "user:{} doesn't have enough permissions to insert collab {}", - uid, params.object_id - ))); - } + self + .check_collab_permission(workspace_id, uid, ¶ms, transaction) + .await?; let object_id = params.object_id.clone(); let encoded_collab = params.encoded_collab_v1.clone(); self diff --git a/src/biz/workspace/access_control.rs b/src/biz/workspace/access_control.rs index 7559dde2..3d72887d 100644 --- a/src/biz/workspace/access_control.rs +++ b/src/biz/workspace/access_control.rs @@ -201,6 +201,7 @@ where } #[instrument(level = "trace", skip_all, err)] + #[allow(clippy::blocks_in_conditions)] async fn check_workspace_permission( &self, workspace_id: &Uuid, @@ -208,29 +209,28 @@ where method: Method, ) -> Result<(), AppError> { trace!("workspace_id: {:?}, uid: {:?}", workspace_id, uid); - match self + let role = self .access_control .get_role_from_uid(uid, workspace_id, &self.pg_pool) .await - { - Ok(role) => { - if method == Method::DELETE || method == Method::POST || method == Method::PUT { - if matches!(role, AFRole::Owner) { - Ok(()) - } else { - Err(AppError::NotEnoughPermissions(format!( - "User:{:?} doesn't have the enough permission to access workspace:{}", - uid, workspace_id - ))) - } - } else { - Ok(()) - } + .map_err(|err| { + AppError::NotEnoughPermissions(format!( + "Can't find the role of the user:{:?} in the workspace:{:?}. error: {}", + uid, workspace_id, err + )) + })?; + + match method { + Method::DELETE | Method::POST | Method::PUT => match role { + AFRole::Owner => return Ok(()), + _ => { + return Err(AppError::NotEnoughPermissions(format!( + "User:{:?} doesn't have the enough permission to access workspace:{}", + uid, workspace_id + ))) + }, }, - Err(err) => Err(AppError::NotEnoughPermissions(format!( - "Can't find the role of the user:{:?} in the workspace:{:?}. error: {}", - uid, workspace_id, err - ))), + _ => Ok(()), } } diff --git a/src/middleware/access_control_mw.rs b/src/middleware/access_control_mw.rs index 8bec37b1..4603a9e9 100644 --- a/src/middleware/access_control_mw.rs +++ b/src/middleware/access_control_mw.rs @@ -175,12 +175,13 @@ where forward_ready!(service); fn call(&self, mut req: ServiceRequest) -> Self::Future { - match req.match_pattern().map(|pattern| { + let path = req.match_pattern().map(|pattern| { let resource_ref = ResourceDef::new(pattern); let mut path = req.match_info().clone(); resource_ref.capture_match_info(&mut path); path - }) { + }); + match path { None => { let fut = self.service.call(req); Box::pin(fut)