From de413844dc14252121fbb41bb2f24052ba7dd7de Mon Sep 17 00:00:00 2001 From: Zack Fu Zi Xiang Date: Sat, 15 Jun 2024 14:59:18 +0800 Subject: [PATCH] feat: put and get published collab data --- libs/database/src/workspace.rs | 51 +++++++++++++++++++++++++++ src/api/workspace.rs | 36 ++++++++++++++++++- src/biz/workspace/ops.rs | 64 +++++++++++++++++++++++----------- 3 files changed, 129 insertions(+), 22 deletions(-) diff --git a/libs/database/src/workspace.rs b/libs/database/src/workspace.rs index 5d67256f..0d2c2bdc 100644 --- a/libs/database/src/workspace.rs +++ b/libs/database/src/workspace.rs @@ -906,3 +906,54 @@ pub async fn delete_published_collab<'a, E: Executor<'a, Database = Postgres>>( Ok(()) } + +#[inline] +pub async fn insert_or_replace_published_collab_blob<'a, E: Executor<'a, Database = Postgres>>( + executor: E, + workspace_id: &Uuid, + doc_name: &str, + blob: &[u8], +) -> Result<(), AppError> { + let res = sqlx::query!( + r#" + UPDATE af_published_collab + SET blob = $1 + WHERE workspace_id = $2 AND doc_name = $3 + "#, + blob, + workspace_id, + doc_name, + ) + .execute(executor) + .await?; + + if res.rows_affected() != 1 { + tracing::error!( + "Failed to insert or replace published collab blob, workspace_id: {}, doc_name: {}, rows_affected: {}", + workspace_id, doc_name, res.rows_affected() + ); + } + + Ok(()) +} + +#[inline] +pub async fn select_published_collab_blob<'a, E: Executor<'a, Database = Postgres>>( + executor: E, + workspace_id: &Uuid, + doc_name: &str, +) -> Result, AppError> { + let res = sqlx::query_scalar!( + r#" + SELECT blob + FROM af_published_collab + WHERE workspace_id = $1 AND doc_name = $2 + "#, + workspace_id, + doc_name, + ) + .fetch_one(executor) + .await?; + + Ok(res) +} diff --git a/src/api/workspace.rs b/src/api/workspace.rs index e5738ff9..1152af73 100644 --- a/src/api/workspace.rs +++ b/src/api/workspace.rs @@ -133,7 +133,12 @@ pub fn workspace_scope() -> Scope { .route(web::put().to(put_publish_namespace_handler)) ) .service( - web::resource("/{workspace_id}/collab/{object_id}/publish") + web::resource("/{workspace_id}/publish/{doc_name}/blob") + .route(web::put().to(put_publish_collab_blob_handler)) + .route(web::get().to(get_publish_collab_blob_handler)) + ) + .service( + web::resource("/{workspace_id}/publish/{doc_name}") .route(web::put().to(put_publish_collab_handler)) .route(web::delete().to(delete_publish_collab_handler)) ) @@ -983,6 +988,35 @@ async fn put_publish_collab_handler( Ok(Json(AppResponse::Ok())) } +async fn put_publish_collab_blob_handler( + path_param: web::Path<(Uuid, String)>, + user_uuid: UserUuid, + collab_data: Bytes, + state: Data, +) -> Result>> { + let (workspace_id, doc_name) = path_param.into_inner(); + biz::workspace::ops::put_published_collab_blob( + &state.pg_pool, + &workspace_id, + &doc_name, + &user_uuid, + &collab_data, + ) + .await?; + Ok(Json(AppResponse::Ok())) +} + +async fn get_publish_collab_blob_handler( + path_param: web::Path<(Uuid, String)>, + state: Data, +) -> Result> { + let (workspace_id, doc_name) = path_param.into_inner(); + let collab_data = + biz::workspace::ops::get_published_collab_blob(&state.pg_pool, &workspace_id, &doc_name) + .await?; + Ok(collab_data) +} + async fn delete_publish_collab_handler( path_param: web::Path<(Uuid, String)>, user_uuid: UserUuid, diff --git a/src/biz/workspace/ops.rs b/src/biz/workspace/ops.rs index 3846e789..b6c6d8b0 100644 --- a/src/biz/workspace/ops.rs +++ b/src/biz/workspace/ops.rs @@ -18,8 +18,9 @@ use database::resource_usage::get_all_workspace_blob_metadata; use database::user::select_uid_from_email; use database::workspace::{ change_workspace_icon, delete_from_workspace, delete_published_collab, delete_workspace_members, - get_invitation_by_id, insert_or_replace_publish_collab_meta, insert_user_workspace, - insert_workspace_invitation, rename_workspace, select_all_user_workspaces, + get_invitation_by_id, insert_or_replace_publish_collab_meta, + insert_or_replace_published_collab_blob, insert_user_workspace, insert_workspace_invitation, + rename_workspace, select_all_user_workspaces, select_published_collab_blob, select_user_is_collab_publisher, select_user_is_workspace_owner, select_workspace, select_workspace_invitations_for_user, select_workspace_member, select_workspace_member_list, select_workspace_settings, select_workspace_total_collab_bytes, update_updated_at_of_workspace, @@ -139,35 +140,37 @@ pub async fn publish_workspace_collab( Ok(()) } +pub async fn put_published_collab_blob( + pg_pool: &PgPool, + workspace_id: &Uuid, + doc_name: &str, + user_uuid: &Uuid, + collab_data: &[u8], +) -> Result<(), AppError> { + check_workspace_owner_or_publisher(pg_pool, user_uuid, workspace_id, doc_name).await?; + insert_or_replace_published_collab_blob(pg_pool, workspace_id, doc_name, collab_data).await?; + Ok(()) +} + +pub async fn get_published_collab_blob( + pg_pool: &PgPool, + workspace_id: &Uuid, + doc_name: &str, +) -> Result, AppError> { + select_published_collab_blob(pg_pool, workspace_id, doc_name).await +} + pub async fn delete_published_workspace_collab( pg_pool: &PgPool, workspace_id: &Uuid, doc_name: &str, user_uuid: &Uuid, ) -> Result<(), AppError> { - let is_owner = select_user_is_workspace_owner(pg_pool, user_uuid, workspace_id).await?; - if !is_owner { - let is_publisher = - select_user_is_collab_publisher(pg_pool, user_uuid, workspace_id, doc_name).await?; - if !is_publisher { - return Err(AppError::UserUnAuthorized( - "User is not the owner of the workspace or the publisher of the document".to_string(), - )); - } - } - + check_workspace_owner_or_publisher(pg_pool, user_uuid, workspace_id, doc_name).await?; delete_published_collab(pg_pool, workspace_id, doc_name).await?; Ok(()) } -pub async fn publish_workspace_collab_data( - _pg_pool: &PgPool, - _workspace_id: &Uuid, - _view_id: &Uuid, -) -> Result<(), AppError> { - Ok(()) -} - pub async fn get_all_user_workspaces( pg_pool: &PgPool, user_uuid: &Uuid, @@ -592,3 +595,22 @@ async fn check_workspace_namespace(new_namespace: &str) -> Result<(), AppError> Ok(()) } + +async fn check_workspace_owner_or_publisher( + pg_pool: &PgPool, + user_uuid: &Uuid, + workspace_id: &Uuid, + doc_name: &str, +) -> Result<(), AppError> { + let is_owner = select_user_is_workspace_owner(pg_pool, user_uuid, workspace_id).await?; + if !is_owner { + let is_publisher = + select_user_is_collab_publisher(pg_pool, user_uuid, workspace_id, doc_name).await?; + if !is_publisher { + return Err(AppError::UserUnAuthorized( + "User is not the owner of the workspace or the publisher of the document".to_string(), + )); + } + } + Ok(()) +}