feat: add workspace and delete workspace

This commit is contained in:
Fu Zi Xiang 2024-01-23 12:10:55 +08:00
parent ee3abdb27a
commit 27b7b8b5b8
No known key found for this signature in database
8 changed files with 187 additions and 16 deletions

View File

@ -0,0 +1,14 @@
{
"db_name": "PostgreSQL",
"query": "\n DELETE FROM public.af_workspace where workspace_id = $1\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Uuid"
]
},
"nullable": []
},
"hash": "0eae8461a1caa6a609bfc4f329a4768ca0372a7b8cac54d83e3277ea0ad5ed9d"
}

View File

@ -0,0 +1,58 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO public.af_workspace (owner_uid)\n SELECT uid FROM public.af_user WHERE uuid = $1\n RETURNING *;\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "workspace_id",
"type_info": "Uuid"
},
{
"ordinal": 1,
"name": "database_storage_id",
"type_info": "Uuid"
},
{
"ordinal": 2,
"name": "owner_uid",
"type_info": "Int8"
},
{
"ordinal": 3,
"name": "created_at",
"type_info": "Timestamptz"
},
{
"ordinal": 4,
"name": "workspace_type",
"type_info": "Int4"
},
{
"ordinal": 5,
"name": "deleted_at",
"type_info": "Timestamptz"
},
{
"ordinal": 6,
"name": "workspace_name",
"type_info": "Text"
}
],
"parameters": {
"Left": [
"Uuid"
]
},
"nullable": [
false,
false,
false,
true,
false,
true,
true
]
},
"hash": "c08e9c86c0877ed54499e47dbf83ffe12c16dfedea5b826e2becb0d65d6c61b1"
}

View File

@ -489,9 +489,23 @@ impl Client {
.into_data()
}
#[instrument(level = "debug", skip_all, err)]
pub async fn add_workspace(&self) -> Result<AFWorkspace, AppResponseError> {
let url = format!("{}/api/workspace", self.base_url);
let resp = self
.http_client_with_auth(Method::POST, &url)
.await?
.send()
.await?;
log_request_id(&resp);
AppResponse::<AFWorkspace>::from_response(resp)
.await?
.into_data()
}
#[instrument(level = "debug", skip_all, err)]
pub async fn get_workspaces(&self) -> Result<AFWorkspaces, AppResponseError> {
let url = format!("{}/api/workspace/list", self.base_url);
let url = format!("{}/api/workspace", self.base_url);
let resp = self
.http_client_with_auth(Method::GET, &url)
.await?

View File

@ -12,6 +12,41 @@ use crate::pg_row::{AFPermissionRow, AFUserProfileRow, AFWorkspaceMemberRow, AFW
use crate::user::select_uid_from_email;
use app_error::AppError;
#[inline]
pub async fn delete_from_workspace(pg_pool: &PgPool, workspace_id: &Uuid) -> Result<(), AppError> {
let pg_row = sqlx::query!(
r#"
DELETE FROM public.af_workspace where workspace_id = $1
"#,
workspace_id
)
.execute(pg_pool)
.await?;
assert!(pg_row.rows_affected() == 1);
Ok(())
}
#[inline]
pub async fn insert_user_workspace(
pg_pool: &PgPool,
user_uuid: &Uuid,
) -> Result<AFWorkspaceRow, AppError> {
let workspace = sqlx::query_as!(
AFWorkspaceRow,
r#"
INSERT INTO public.af_workspace (owner_uid)
SELECT uid FROM public.af_user WHERE uuid = $1
RETURNING *;
"#,
user_uuid
)
.fetch_one(pg_pool)
.await?;
Ok(workspace)
}
/// Checks whether a user, identified by a UUID, is an 'Owner' of a workspace, identified by its
/// workspace_id.
#[inline]

View File

@ -39,17 +39,28 @@ pub const COLLAB_OBJECT_ID_PATH: &str = "object_id";
pub fn workspace_scope() -> Scope {
web::scope("/api/workspace")
.service(web::resource("list").route(web::get().to(list_handler)))
.service(web::resource("{workspace_id}/open").route(web::put().to(open_workspace_handler)))
// deprecated, use `/` instead
.service(web::resource("/list").route(web::get().to(list_workspace_handler)))
.service(web::resource("/")
.route(web::get().to(list_workspace_handler))
.route(web::post().to(add_workpace_handler))
)
.service(web::resource("/{workspace_id}")
.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}/member")
web::resource("/{workspace_id}/member")
.route(web::get().to(get_workspace_members_handler))
.route(web::post().to(add_workspace_members_handler))
.route(web::put().to(update_workspace_member_handler))
.route(web::delete().to(remove_workspace_member_handler)),
)
.service(
web::resource("{workspace_id}/collab/{object_id}")
web::resource("/{workspace_id}/collab/{object_id}")
.app_data(
PayloadConfig::new(5 * 1024 * 1024), // 5 MB
)
@ -59,37 +70,37 @@ pub fn workspace_scope() -> Scope {
.route(web::delete().to(delete_collab_handler)),
)
.service(
web::resource("{workspace_id}/batch/collab")
web::resource("/{workspace_id}/batch/collab")
.route(web::post().to(create_collab_list_handler)),
)
// will be deprecated
.service(
web::resource("{workspace_id}/collabs")
web::resource("/{workspace_id}/collabs")
.app_data(PayloadConfig::new(10 * 1024 * 1024))
.route(web::post().to(batch_create_collab_handler)),
)
.service(
web::resource("{workspace_id}/{object_id}/snapshot")
web::resource("/{workspace_id}/{object_id}/snapshot")
.route(web::get().to(get_collab_snapshot_handler))
.route(web::post().to(create_collab_snapshot_handler)),
)
.service(
web::resource("{workspace_id}/{object_id}/snapshot/list")
web::resource("/{workspace_id}/{object_id}/snapshot/list")
.route(web::get().to(get_all_collab_snapshot_list_handler)),
)
.service(
web::resource("{workspace_id}/collab/{object_id}/member")
web::resource("/{workspace_id}/collab/{object_id}/member")
.route(web::post().to(add_collab_member_handler))
.route(web::get().to(get_collab_member_handler))
.route(web::put().to(update_collab_member_handler))
.route(web::delete().to(remove_collab_member_handler)),
)
.service(
web::resource("{workspace_id}/collab/{object_id}/member/list")
web::resource("/{workspace_id}/collab/{object_id}/member/list")
.route(web::get().to(get_collab_member_list_handler)),
)
.service(
web::resource("{workspace_id}/collab_list").route(web::get().to(batch_get_collab_handler)),
web::resource("/{workspace_id}/collab_list").route(web::get().to(batch_get_collab_handler)),
)
}
@ -103,8 +114,28 @@ pub fn collab_scope() -> Scope {
)
}
// Adds a workspace for user, if success, return the workspace id
#[instrument(skip_all, err)]
async fn list_handler(
async fn add_workpace_handler(
uuid: UserUuid,
state: Data<AppState>,
) -> Result<Json<AppResponse<AFWorkspace>>> {
let new_workspace = workspace::ops::add_workspace_for_user(&state.pg_pool, &uuid).await?;
Ok(AppResponse::Ok().with_data(new_workspace).into())
}
async fn delete_workspace_handler(
_user_id: UserUuid,
workspace_id: web::Path<Uuid>,
state: Data<AppState>,
) -> Result<Json<AppResponse<()>>> {
// TODO: add permission for workspace deletion
workspace::ops::delete_workspace_for_user(&state.pg_pool, &workspace_id).await?;
Ok(AppResponse::Ok().into())
}
#[instrument(skip_all, err)]
async fn list_workspace_handler(
uuid: UserUuid,
state: Data<AppState>,
) -> Result<JsonAppResponse<AFWorkspaces>> {

View File

@ -4,9 +4,9 @@ use database::collab::upsert_collab_member_with_txn;
use database::pg_row::{AFWorkspaceMemberRow, AFWorkspaceRow};
use database::user::select_uid_from_email;
use database::workspace::{
delete_workspace_members, insert_workspace_member_with_txn, select_all_user_workspaces,
select_workspace, select_workspace_member_list, update_updated_at_of_workspace,
upsert_workspace_member,
delete_from_workspace, delete_workspace_members, insert_user_workspace,
insert_workspace_member_with_txn, select_all_user_workspaces, select_workspace,
select_workspace_member_list, update_updated_at_of_workspace, upsert_workspace_member,
};
use database_entity::dto::{AFAccessLevel, AFRole, AFWorkspace};
use shared_entity::dto::workspace_dto::{CreateWorkspaceMember, WorkspaceMemberChangeset};
@ -17,6 +17,23 @@ use std::ops::DerefMut;
use tracing::instrument;
use uuid::Uuid;
pub async fn delete_workspace_for_user(
pg_pool: &PgPool,
workspace_id: &Uuid,
) -> Result<(), AppResponseError> {
delete_from_workspace(pg_pool, workspace_id).await?;
Ok(())
}
pub async fn add_workspace_for_user(
pg_pool: &PgPool,
user_uuid: &Uuid,
) -> Result<AFWorkspace, AppResponseError> {
let new_workspace_row = insert_user_workspace(pg_pool, user_uuid).await?;
let new_workspace = AFWorkspace::try_from(new_workspace_row)?;
Ok(new_workspace)
}
pub async fn get_all_user_workspaces(
pg_pool: &PgPool,
user_uuid: &Uuid,

View File

@ -1,3 +1,4 @@
mod blob;
mod member_crud;
mod template_test;
mod workspace_crud;

View File

@ -0,0 +1 @@