From 06272364b77e2304b09da0cb63e20df678b9f49a Mon Sep 17 00:00:00 2001 From: Mathias Mogensen <42929161+Xazin@users.noreply.github.com> Date: Thu, 30 May 2024 01:50:58 +0200 Subject: [PATCH] feat: get workspace member by user id (#588) * feat: get workspace member by user id * chore: remove unneccessary arg --- libs/client-api-test/src/test_client.rs | 23 ++++++++++++++++++++ libs/client-api/src/http_member.rs | 22 ++++++++++++++++++- libs/database-entity/src/dto.rs | 8 +++++++ src/api/workspace.rs | 29 +++++++++++++++++++++---- src/biz/workspace/ops.rs | 10 ++++++++- tests/workspace/member_crud.rs | 24 ++++++++++++++++++++ 6 files changed, 110 insertions(+), 6 deletions(-) diff --git a/libs/client-api-test/src/test_client.rs b/libs/client-api-test/src/test_client.rs index e50191b1..12318960 100644 --- a/libs/client-api-test/src/test_client.rs +++ b/libs/client-api-test/src/test_client.rs @@ -6,6 +6,7 @@ use assert_json_diff::{ use bytes::Bytes; #[cfg(feature = "collab-sync")] use client_api::collab_sync::{SinkConfig, SyncObject, SyncPlugin}; +use client_api::entity::QueryWorkspaceMember; use client_api::ws::{WSClient, WSClientConfig}; use collab::core::collab::{DataSource, MutexCollab}; use collab::core::collab_state::SyncState; @@ -257,6 +258,7 @@ impl TestClient { .await .unwrap() } + pub async fn try_get_workspace_members( &self, workspace_id: &str, @@ -264,6 +266,27 @@ impl TestClient { self.api_client.get_workspace_members(workspace_id).await } + pub async fn get_workspace_member(&self, workspace_id: &str, user_id: i64) -> AFWorkspaceMember { + let params = QueryWorkspaceMember { + workspace_id: workspace_id.to_string(), + uid: user_id, + }; + self.api_client.get_workspace_member(params).await.unwrap() + } + + pub async fn try_get_workspace_member( + &self, + workspace_id: &str, + user_id: i64, + ) -> Result { + let params = QueryWorkspaceMember { + workspace_id: workspace_id.to_string(), + uid: user_id, + }; + + self.api_client.get_workspace_member(params).await + } + pub async fn add_collab_member( &self, workspace_id: &str, diff --git a/libs/client-api/src/http_member.rs b/libs/client-api/src/http_member.rs index b23cf9cd..ebb20652 100644 --- a/libs/client-api/src/http_member.rs +++ b/libs/client-api/src/http_member.rs @@ -3,7 +3,7 @@ use crate::Client; use database_entity::dto::{ AFCollabMember, AFCollabMembers, AFWorkspaceInvitation, AFWorkspaceInvitationStatus, AFWorkspaceMember, CollabMemberIdentify, InsertCollabMemberParams, QueryCollabMembers, - UpdateCollabMemberParams, + QueryWorkspaceMember, UpdateCollabMemberParams, }; use reqwest::Method; use shared_entity::dto::workspace_dto::{ @@ -267,4 +267,24 @@ impl Client { .await? .into_data() } + + #[instrument(level = "info", skip_all, err)] + pub async fn get_workspace_member( + &self, + params: QueryWorkspaceMember, + ) -> Result { + let url = format!( + "{}/api/workspace/{}/member/user/{}", + self.base_url, params.workspace_id, params.uid, + ); + let resp = self + .http_client_with_auth(Method::GET, &url) + .await? + .send() + .await?; + log_request_id(&resp); + AppResponse::::from_response(resp) + .await? + .into_data() + } } diff --git a/libs/database-entity/src/dto.rs b/libs/database-entity/src/dto.rs index 2126b395..912625a5 100644 --- a/libs/database-entity/src/dto.rs +++ b/libs/database-entity/src/dto.rs @@ -286,6 +286,14 @@ pub struct QueryCollabMembers { pub object_id: String, } +#[derive(Debug, Clone, Validate, Serialize, Deserialize)] +pub struct QueryWorkspaceMember { + #[validate(custom = "validate_not_empty_str")] + pub workspace_id: String, + + pub uid: i64, +} + #[derive(Serialize, Deserialize)] pub struct AFCollabMember { pub uid: i64, diff --git a/src/api/workspace.rs b/src/api/workspace.rs index a2014890..f9e6e644 100644 --- a/src/api/workspace.rs +++ b/src/api/workspace.rs @@ -73,10 +73,13 @@ pub fn workspace_scope() -> Scope { .service(web::resource("/{workspace_id}/leave").route(web::post().to(leave_workspace_handler))) .service( web::resource("/{workspace_id}/member") - .route(web::get().to(get_workspace_members_handler)) - .route(web::post().to(create_workspace_members_handler)) // deprecated, use invite flow instead - .route(web::put().to(update_workspace_member_handler)) - .route(web::delete().to(remove_workspace_member_handler)) + .route(web::get().to(get_workspace_members_handler)) + .route(web::post().to(create_workspace_members_handler)) // deprecated, use invite flow instead + .route(web::put().to(update_workspace_member_handler)) + .route(web::delete().to(remove_workspace_member_handler)) + ) + .service( + web::resource("/{workspace_id}/member/user/{user_id}").route(web::get().to(get_workspace_member_handler)) ) .service( web::resource("/{workspace_id}/collab/{object_id}") @@ -338,6 +341,24 @@ async fn remove_workspace_member_handler( Ok(AppResponse::Ok().into()) } +#[instrument(skip_all, err)] +async fn get_workspace_member_handler( + state: Data, + path: web::Path<(Uuid, i64)>, +) -> Result> { + let (workspace_id, user_id) = path.into_inner(); + let member_row = + workspace::ops::get_workspace_member(&user_id, &state.pg_pool, &workspace_id).await?; + let member = AFWorkspaceMember { + name: member_row.name, + email: member_row.email, + role: member_row.role, + avatar_url: None, + }; + + Ok(AppResponse::Ok().with_data(member).into()) +} + #[instrument(level = "debug", skip_all, err)] async fn open_workspace_handler( user_uuid: UserUuid, diff --git a/src/biz/workspace/ops.rs b/src/biz/workspace/ops.rs index 1f5fa30b..5064d164 100644 --- a/src/biz/workspace/ops.rs +++ b/src/biz/workspace/ops.rs @@ -20,7 +20,7 @@ use database::workspace::{ change_workspace_icon, delete_from_workspace, delete_workspace_members, get_invitation_by_id, insert_user_workspace, insert_workspace_invitation, rename_workspace, select_all_user_workspaces, select_user_is_workspace_owner, select_workspace, select_workspace_invitations_for_user, - select_workspace_member_list, select_workspace_total_collab_bytes, + select_workspace_member, select_workspace_member_list, select_workspace_total_collab_bytes, update_updated_at_of_workspace, update_workspace_invitation_set_status_accepted, upsert_workspace_member, upsert_workspace_member_with_txn, }; @@ -422,6 +422,14 @@ pub async fn get_workspace_members( Ok(select_workspace_member_list(pg_pool, workspace_id).await?) } +pub async fn get_workspace_member( + uid: &i64, + pg_pool: &PgPool, + workspace_id: &Uuid, +) -> Result { + Ok(select_workspace_member(pg_pool, uid, workspace_id).await?) +} + pub async fn update_workspace_member( uid: &i64, pg_pool: &PgPool, diff --git a/tests/workspace/member_crud.rs b/tests/workspace/member_crud.rs index a05072d3..adec5df6 100644 --- a/tests/workspace/member_crud.rs +++ b/tests/workspace/member_crud.rs @@ -476,3 +476,27 @@ async fn add_workspace_member_and_then_member_get_member_list() { .unwrap_err(); assert_eq!(error.code, ErrorCode::NotEnoughPermissions); } + +#[tokio::test] +async fn workspace_member_through_user_id() { + let owner = TestClient::new_user_without_ws_conn().await; + let member_1 = TestClient::new_user_without_ws_conn().await; + let workspace_id = owner.workspace_id().await; + + let owner_member = owner + .get_workspace_member(&workspace_id, owner.uid().await) + .await; + assert_eq!(owner_member.role, AFRole::Owner); + + owner + .invite_and_accepted_workspace_member(&workspace_id, &member_1, AFRole::Member) + .await + .unwrap(); + + let member_1_member = member_1 + .get_workspace_member(&workspace_id, member_1.uid().await) + .await; + assert_eq!(member_1_member.role, AFRole::Member); + + assert_ne!(owner_member.role, member_1_member.role); +}