diff --git a/libs/access-control/src/adapter.rs b/libs/access-control/src/adapter.rs index 751952d1..8f9b7f01 100644 --- a/libs/access-control/src/adapter.rs +++ b/libs/access-control/src/adapter.rs @@ -12,6 +12,7 @@ use database::collab::select_collab_member_access_level; use database::pg_row::AFCollabMemberAccessLevelRow; use database::pg_row::AFWorkspaceMemberPermRow; use database::workspace::select_workspace_member_perm_stream; +use database_entity::dto::AFRole; use futures_util::stream::BoxStream; use sqlx::PgPool; use std::sync::Arc; @@ -72,6 +73,36 @@ async fn load_workspace_policies( ] .to_vec(); policies.push(policy); + + match member_permission.role { + AFRole::Owner => { + // when the member is owner, also add the member/guest policy + // when enforcing Member/Guest, then if the user is owner, it also can pass the access control. + for role in [AFRole::Member, AFRole::Guest].iter() { + let action = role.to_action(); + let policy = [ + uid.to_string(), + object_type.policy_object(), + action.to_string(), + ] + .to_vec(); + policies.push(policy); + } + }, + AFRole::Member => { + // when the member is member, also add the guest policy. it's used when enforcing role. + // when enforcing Guest, then if the user is member, it also can pass the access control. + let action = AFRole::Guest.to_action(); + let policy = [ + uid.to_string(), + object_type.policy_object(), + action.to_string(), + ] + .to_vec(); + policies.push(policy); + }, + AFRole::Guest => {}, + } } Ok(policies) diff --git a/libs/client-api-test-util/src/test_client.rs b/libs/client-api-test-util/src/test_client.rs index 21e7a0bd..9f3c7228 100644 --- a/libs/client-api-test-util/src/test_client.rs +++ b/libs/client-api-test-util/src/test_client.rs @@ -270,6 +270,12 @@ impl TestClient { .await .unwrap() } + pub async fn try_get_workspace_members( + &self, + workspace_id: &str, + ) -> Result, AppResponseError> { + self.api_client.get_workspace_members(workspace_id).await + } pub async fn add_collab_member( &self, diff --git a/src/biz/workspace/access_control.rs b/src/biz/workspace/access_control.rs index c9dc6547..fd2eb782 100644 --- a/src/biz/workspace/access_control.rs +++ b/src/biz/workspace/access_control.rs @@ -73,7 +73,7 @@ where (Method::POST, AFRole::Owner), (Method::DELETE, AFRole::Owner), (Method::PUT, AFRole::Owner), - (Method::GET, AFRole::Owner), + (Method::GET, AFRole::Member), ] .into(), ), diff --git a/tests/workspace/member_crud.rs b/tests/workspace/member_crud.rs index 6a170b00..8df8c667 100644 --- a/tests/workspace/member_crud.rs +++ b/tests/workspace/member_crud.rs @@ -408,3 +408,29 @@ async fn owner_leave_workspace_test() { // owner of workspace cannot leave the workspace assert_eq!(err.code, ErrorCode::NotEnoughPermissions); } + +#[tokio::test] +async fn add_workspace_member_and_then_member_get_member_list() { + let owner = TestClient::new_user_without_ws_conn().await; + let member = TestClient::new_user_without_ws_conn().await; + let guest = TestClient::new_user_without_ws_conn().await; + + let workspace_id = owner.workspace_id().await; + owner + .add_workspace_member(&workspace_id, &member, AFRole::Member) + .await; + owner + .add_workspace_member(&workspace_id, &guest, AFRole::Guest) + .await; + + // member should be able to get the member list of the workspace + let members = member.get_workspace_members(&workspace_id).await; + assert_eq!(members.len(), 3); + + // guest should not be able to get the member list of the workspace + let error = guest + .try_get_workspace_members(&workspace_id) + .await + .unwrap_err(); + assert_eq!(error.code, ErrorCode::NotEnoughPermissions); +}