feat: add workspace and delete workspace
This commit is contained in:
parent
ee3abdb27a
commit
27b7b8b5b8
|
|
@ -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"
|
||||||
|
}
|
||||||
|
|
@ -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"
|
||||||
|
}
|
||||||
|
|
@ -489,9 +489,23 @@ impl Client {
|
||||||
.into_data()
|
.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)]
|
#[instrument(level = "debug", skip_all, err)]
|
||||||
pub async fn get_workspaces(&self) -> Result<AFWorkspaces, AppResponseError> {
|
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
|
let resp = self
|
||||||
.http_client_with_auth(Method::GET, &url)
|
.http_client_with_auth(Method::GET, &url)
|
||||||
.await?
|
.await?
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,41 @@ use crate::pg_row::{AFPermissionRow, AFUserProfileRow, AFWorkspaceMemberRow, AFW
|
||||||
use crate::user::select_uid_from_email;
|
use crate::user::select_uid_from_email;
|
||||||
use app_error::AppError;
|
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
|
/// Checks whether a user, identified by a UUID, is an 'Owner' of a workspace, identified by its
|
||||||
/// workspace_id.
|
/// workspace_id.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
||||||
|
|
@ -39,17 +39,28 @@ pub const COLLAB_OBJECT_ID_PATH: &str = "object_id";
|
||||||
|
|
||||||
pub fn workspace_scope() -> Scope {
|
pub fn workspace_scope() -> Scope {
|
||||||
web::scope("/api/workspace")
|
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(
|
.service(
|
||||||
web::resource("{workspace_id}/member")
|
web::resource("/{workspace_id}/member")
|
||||||
.route(web::get().to(get_workspace_members_handler))
|
.route(web::get().to(get_workspace_members_handler))
|
||||||
.route(web::post().to(add_workspace_members_handler))
|
.route(web::post().to(add_workspace_members_handler))
|
||||||
.route(web::put().to(update_workspace_member_handler))
|
.route(web::put().to(update_workspace_member_handler))
|
||||||
.route(web::delete().to(remove_workspace_member_handler)),
|
.route(web::delete().to(remove_workspace_member_handler)),
|
||||||
)
|
)
|
||||||
.service(
|
.service(
|
||||||
web::resource("{workspace_id}/collab/{object_id}")
|
web::resource("/{workspace_id}/collab/{object_id}")
|
||||||
.app_data(
|
.app_data(
|
||||||
PayloadConfig::new(5 * 1024 * 1024), // 5 MB
|
PayloadConfig::new(5 * 1024 * 1024), // 5 MB
|
||||||
)
|
)
|
||||||
|
|
@ -59,37 +70,37 @@ pub fn workspace_scope() -> Scope {
|
||||||
.route(web::delete().to(delete_collab_handler)),
|
.route(web::delete().to(delete_collab_handler)),
|
||||||
)
|
)
|
||||||
.service(
|
.service(
|
||||||
web::resource("{workspace_id}/batch/collab")
|
web::resource("/{workspace_id}/batch/collab")
|
||||||
.route(web::post().to(create_collab_list_handler)),
|
.route(web::post().to(create_collab_list_handler)),
|
||||||
)
|
)
|
||||||
// will be deprecated
|
// will be deprecated
|
||||||
.service(
|
.service(
|
||||||
web::resource("{workspace_id}/collabs")
|
web::resource("/{workspace_id}/collabs")
|
||||||
.app_data(PayloadConfig::new(10 * 1024 * 1024))
|
.app_data(PayloadConfig::new(10 * 1024 * 1024))
|
||||||
.route(web::post().to(batch_create_collab_handler)),
|
.route(web::post().to(batch_create_collab_handler)),
|
||||||
)
|
)
|
||||||
.service(
|
.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::get().to(get_collab_snapshot_handler))
|
||||||
.route(web::post().to(create_collab_snapshot_handler)),
|
.route(web::post().to(create_collab_snapshot_handler)),
|
||||||
)
|
)
|
||||||
.service(
|
.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)),
|
.route(web::get().to(get_all_collab_snapshot_list_handler)),
|
||||||
)
|
)
|
||||||
.service(
|
.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::post().to(add_collab_member_handler))
|
||||||
.route(web::get().to(get_collab_member_handler))
|
.route(web::get().to(get_collab_member_handler))
|
||||||
.route(web::put().to(update_collab_member_handler))
|
.route(web::put().to(update_collab_member_handler))
|
||||||
.route(web::delete().to(remove_collab_member_handler)),
|
.route(web::delete().to(remove_collab_member_handler)),
|
||||||
)
|
)
|
||||||
.service(
|
.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)),
|
.route(web::get().to(get_collab_member_list_handler)),
|
||||||
)
|
)
|
||||||
.service(
|
.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)]
|
#[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,
|
uuid: UserUuid,
|
||||||
state: Data<AppState>,
|
state: Data<AppState>,
|
||||||
) -> Result<JsonAppResponse<AFWorkspaces>> {
|
) -> Result<JsonAppResponse<AFWorkspaces>> {
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ use database::collab::upsert_collab_member_with_txn;
|
||||||
use database::pg_row::{AFWorkspaceMemberRow, AFWorkspaceRow};
|
use database::pg_row::{AFWorkspaceMemberRow, AFWorkspaceRow};
|
||||||
use database::user::select_uid_from_email;
|
use database::user::select_uid_from_email;
|
||||||
use database::workspace::{
|
use database::workspace::{
|
||||||
delete_workspace_members, insert_workspace_member_with_txn, select_all_user_workspaces,
|
delete_from_workspace, delete_workspace_members, insert_user_workspace,
|
||||||
select_workspace, select_workspace_member_list, update_updated_at_of_workspace,
|
insert_workspace_member_with_txn, select_all_user_workspaces, select_workspace,
|
||||||
upsert_workspace_member,
|
select_workspace_member_list, update_updated_at_of_workspace, upsert_workspace_member,
|
||||||
};
|
};
|
||||||
use database_entity::dto::{AFAccessLevel, AFRole, AFWorkspace};
|
use database_entity::dto::{AFAccessLevel, AFRole, AFWorkspace};
|
||||||
use shared_entity::dto::workspace_dto::{CreateWorkspaceMember, WorkspaceMemberChangeset};
|
use shared_entity::dto::workspace_dto::{CreateWorkspaceMember, WorkspaceMemberChangeset};
|
||||||
|
|
@ -17,6 +17,23 @@ use std::ops::DerefMut;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
use uuid::Uuid;
|
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(
|
pub async fn get_all_user_workspaces(
|
||||||
pg_pool: &PgPool,
|
pg_pool: &PgPool,
|
||||||
user_uuid: &Uuid,
|
user_uuid: &Uuid,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
mod blob;
|
mod blob;
|
||||||
mod member_crud;
|
mod member_crud;
|
||||||
mod template_test;
|
mod template_test;
|
||||||
|
mod workspace_crud;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
|
||||||
Loading…
Reference in New Issue