Merge pull request #400 from AppFlowy-IO/leave-workspace

Leave workspace
This commit is contained in:
Zack 2024-03-20 14:33:47 +08:00 committed by GitHub
commit 619f5b3370
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 112 additions and 0 deletions

View File

@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT email FROM af_user WHERE uuid = $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "email",
"type_info": "Text"
}
],
"parameters": {
"Left": [
"Uuid"
]
},
"nullable": [
false
]
},
"hash": "bde2b88ffb1b59362c7ae82369892c79131c175924f95e5d48d75931fb846f41"
}

View File

@ -585,6 +585,19 @@ impl Client {
.into_data()
}
#[instrument(level = "debug", skip_all, err)]
pub async fn leave_workspace(&self, workspace_id: &str) -> Result<(), AppResponseError> {
let url = format!("{}/api/workspace/{}/leave", self.base_url, workspace_id);
let resp = self
.http_client_with_auth(Method::POST, &url)
.await?
.json(&())
.send()
.await?;
log_request_id(&resp);
AppResponse::<()>::from_response(resp).await?.into_error()
}
#[instrument(level = "debug", skip_all, err)]
pub async fn get_workspace_members<W: AsRef<str>>(
&self,

View File

@ -196,3 +196,19 @@ pub async fn is_user_exist<'a, E: Executor<'a, Database = Postgres>>(
Ok(exists.unwrap_or(false))
}
#[inline]
pub async fn select_email_from_user_uuid(
pool: &PgPool,
user_uuid: &Uuid,
) -> Result<String, AppError> {
let email = sqlx::query_scalar!(
r#"
SELECT email FROM af_user WHERE uuid = $1
"#,
user_uuid
)
.fetch_one(pool)
.await?;
Ok(email)
}

View File

@ -74,6 +74,7 @@ pub fn workspace_scope() -> Scope {
.route(web::delete().to(delete_workspace_handler))
)
.service(web::resource("/{workspace_id}/open").route(web::put().to(open_workspace_handler)))
.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))
@ -342,6 +343,23 @@ async fn open_workspace_handler(
Ok(AppResponse::Ok().with_data(workspace).into())
}
#[instrument(level = "debug", skip_all, err)]
async fn leave_workspace_handler(
user_uuid: UserUuid,
state: Data<AppState>,
workspace_id: web::Path<Uuid>,
) -> Result<JsonAppResponse<()>> {
let workspace_id = workspace_id.into_inner();
workspace::ops::leave_workspace(
&state.pg_pool,
&workspace_id,
&user_uuid,
&state.workspace_access_control,
)
.await?;
Ok(AppResponse::Ok().into())
}
#[instrument(level = "debug", skip_all, err)]
async fn update_workspace_member_handler(
payload: Json<WorkspaceMemberChangeset>,

View File

@ -43,6 +43,7 @@ pub trait CollabAccessControl: Sync + Send + 'static {
async fn remove_access_level(&self, uid: &i64, oid: &str) -> Result<(), AppError>;
}
#[derive(Clone)]
pub struct CollabMiddlewareAccessControl<AC: CollabAccessControl> {
pub access_control: Arc<AC>,

View File

@ -315,6 +315,16 @@ pub async fn add_workspace_members_db_only(
Ok(())
}
pub async fn leave_workspace(
pg_pool: &PgPool,
workspace_id: &Uuid,
user_uuid: &Uuid,
workspace_access_control: &impl WorkspaceAccessControl,
) -> Result<(), AppResponseError> {
let email = database::user::select_email_from_user_uuid(pg_pool, user_uuid).await?;
remove_workspace_members(pg_pool, workspace_id, &[email], workspace_access_control).await
}
pub async fn remove_workspace_members(
pg_pool: &PgPool,
workspace_id: &Uuid,

View File

@ -352,3 +352,35 @@ async fn get_user_workspace_info_after_open_workspace() {
workspace_id_c1
);
}
#[tokio::test]
async fn member_leave_workspace_test() {
let c1 = TestClient::new_user().await;
let workspace_id_c1 = c1.workspace_id().await;
let c2 = TestClient::new_user().await;
c1.add_workspace_member(&workspace_id_c1, &c2, AFRole::Member)
.await;
c2.api_client
.leave_workspace(&workspace_id_c1)
.await
.unwrap();
let members = c1.get_workspace_members(&workspace_id_c1).await;
assert_eq!(members.len(), 1);
}
#[tokio::test]
async fn owner_leave_workspace_test() {
let c1 = TestClient::new_user().await;
let workspace_id_c1 = c1.workspace_id().await;
let err = c1
.api_client
.leave_workspace(&workspace_id_c1)
.await
.unwrap_err();
// owner of workspace cannot leave the workspace
assert_eq!(err.code, ErrorCode::NotEnoughPermissions);
}