fix: delete user should only remove owned workspaces
This commit is contained in:
parent
40017ee497
commit
6d0a7cc95b
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "\n SELECT workspace_id\n FROM af_workspace\n where OWNER_UID = (SELECT uid FROM public.af_user WHERE uuid = $1)\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "workspace_id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "57ef3a6399630ec23dd238a97eb4cce9a0dabccfff03bea125dfb729a9de2033"
|
||||||
|
}
|
||||||
|
|
@ -691,6 +691,25 @@ pub async fn select_all_user_workspaces<'a, E: Executor<'a, Database = Postgres>
|
||||||
Ok(workspaces)
|
Ok(workspaces)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a list of workspace ids that the user is owner of.
|
||||||
|
#[inline]
|
||||||
|
pub async fn select_user_owned_workspaces_id<'a, E: Executor<'a, Database = Postgres>>(
|
||||||
|
executor: E,
|
||||||
|
user_uuid: &Uuid,
|
||||||
|
) -> Result<Vec<Uuid>, AppError> {
|
||||||
|
let workspace_ids = sqlx::query_scalar!(
|
||||||
|
r#"
|
||||||
|
SELECT workspace_id
|
||||||
|
FROM af_workspace
|
||||||
|
where OWNER_UID = (SELECT uid FROM public.af_user WHERE uuid = $1)
|
||||||
|
"#,
|
||||||
|
user_uuid
|
||||||
|
)
|
||||||
|
.fetch_all(executor)
|
||||||
|
.await?;
|
||||||
|
Ok(workspace_ids)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn select_member_count_for_workspaces<'a, E: Executor<'a, Database = Postgres>>(
|
pub async fn select_member_count_for_workspaces<'a, E: Executor<'a, Database = Postgres>>(
|
||||||
executor: E,
|
executor: E,
|
||||||
workspace_ids: &[Uuid],
|
workspace_ids: &[Uuid],
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::biz::workspace::ops::get_all_user_workspaces;
|
|
||||||
use crate::state::GoTrueAdmin;
|
use crate::state::GoTrueAdmin;
|
||||||
use crate::{biz::workspace::ops::delete_workspace_for_user, config::config::AppleOAuthSetting};
|
use crate::{biz::workspace::ops::delete_workspace_for_user, config::config::AppleOAuthSetting};
|
||||||
use app_error::ErrorCode;
|
use app_error::ErrorCode;
|
||||||
use authentication::jwt::Authorization;
|
use authentication::jwt::Authorization;
|
||||||
use database::file::s3_client_impl::S3BucketStorage;
|
use database::file::s3_client_impl::S3BucketStorage;
|
||||||
|
use database::workspace::select_user_owned_workspaces_id;
|
||||||
use gotrue::params::AdminDeleteUserParams;
|
use gotrue::params::AdminDeleteUserParams;
|
||||||
use secrecy::{ExposeSecret, Secret};
|
use secrecy::{ExposeSecret, Secret};
|
||||||
use shared_entity::response::AppResponseError;
|
use shared_entity::response::AppResponseError;
|
||||||
|
|
@ -48,14 +48,14 @@ pub async fn delete_user(
|
||||||
.await
|
.await
|
||||||
.map_err(AppResponseError::from)?;
|
.map_err(AppResponseError::from)?;
|
||||||
|
|
||||||
// spawn tasks to delete all user workspace and object storage
|
// spawn tasks to delete all workspaces owned by the user
|
||||||
let user_workspaces = get_all_user_workspaces(pg_pool, &user_uuid, false).await?;
|
let workspace_ids = select_user_owned_workspaces_id(pg_pool, &user_uuid).await?;
|
||||||
let mut tasks = vec![];
|
let mut tasks = vec![];
|
||||||
for workspace in user_workspaces {
|
for workspace_id in workspace_ids {
|
||||||
let cloned_pg_pool = pg_pool.clone();
|
let cloned_pg_pool = pg_pool.clone();
|
||||||
tasks.push(tokio::spawn(delete_workspace_for_user(
|
tasks.push(tokio::spawn(delete_workspace_for_user(
|
||||||
cloned_pg_pool,
|
cloned_pg_pool,
|
||||||
workspace.workspace_id,
|
workspace_id,
|
||||||
bucket_storage.clone(),
|
bucket_storage.clone(),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use client_api::entity::AFRole;
|
||||||
use client_api_test::*;
|
use client_api_test::*;
|
||||||
use gotrue::params::{AdminDeleteUserParams, AdminUserParams};
|
use gotrue::params::{AdminDeleteUserParams, AdminUserParams};
|
||||||
|
|
||||||
|
|
@ -30,6 +31,28 @@ async fn user_delete_self() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Scenario:
|
||||||
|
/// - User1 owns WorkspaceA
|
||||||
|
/// - User1 invites User2 to WorkspaceA
|
||||||
|
/// - User2 deletes itself
|
||||||
|
/// - WorkspaceA should still exist
|
||||||
|
#[tokio::test]
|
||||||
|
async fn user_delete_self_shared_workspace() {
|
||||||
|
let user_1 = TestClient::new_user_without_ws_conn().await;
|
||||||
|
let workspace_a = user_1.workspace_id().await;
|
||||||
|
let user_2 = TestClient::new_user_without_ws_conn().await;
|
||||||
|
user_1
|
||||||
|
.invite_and_accepted_workspace_member(&workspace_a, &user_2, AFRole::Member)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
user_2.api_client.delete_user().await.unwrap();
|
||||||
|
let user_1_workspaces = user_1.api_client.get_workspaces().await.unwrap();
|
||||||
|
let _workspace_a = user_1_workspaces
|
||||||
|
.into_iter()
|
||||||
|
.find(|w| w.workspace_id.to_string() == workspace_a)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn admin_delete_create_same_user_hard() {
|
async fn admin_delete_create_same_user_hard() {
|
||||||
let (client, user) = generate_unique_registered_user_client().await;
|
let (client, user) = generate_unique_registered_user_client().await;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue