diff --git a/.sqlx/query-21195760ea7ed2dc4eda1dc2bd0eed9afcc63651ba6e67e7db675307e3b87821.json b/.sqlx/query-21195760ea7ed2dc4eda1dc2bd0eed9afcc63651ba6e67e7db675307e3b87821.json new file mode 100644 index 00000000..5bbf5d99 --- /dev/null +++ b/.sqlx/query-21195760ea7ed2dc4eda1dc2bd0eed9afcc63651ba6e67e7db675307e3b87821.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE public.af_workspace\n SET workspace_name = $1\n WHERE workspace_id = $2\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Uuid" + ] + }, + "nullable": [] + }, + "hash": "21195760ea7ed2dc4eda1dc2bd0eed9afcc63651ba6e67e7db675307e3b87821" +} diff --git a/libs/client-api/src/http.rs b/libs/client-api/src/http.rs index 538042b9..0596db73 100644 --- a/libs/client-api/src/http.rs +++ b/libs/client-api/src/http.rs @@ -2,7 +2,7 @@ use crate::notify::{ClientToken, TokenStateReceiver}; use anyhow::Context; use brotli::CompressorReader; use gotrue_entity::dto::AuthProvider; -use shared_entity::dto::workspace_dto::CreateWorkspaceParam; +use shared_entity::dto::workspace_dto::{CreateWorkspaceParam, PatchWorkspaceParam}; use std::fmt::{Display, Formatter}; use std::io::Read; @@ -552,6 +552,22 @@ impl Client { .into_data() } + #[instrument(level = "debug", skip_all, err)] + pub async fn rename_workspace( + &self, + params: PatchWorkspaceParam, + ) -> Result<(), AppResponseError> { + let url = format!("{}/api/workspace", self.base_url); + let resp = self + .http_client_with_auth(Method::PATCH, &url) + .await? + .json(¶ms) + .send() + .await?; + log_request_id(&resp); + AppResponse::<()>::from_response(resp).await?.into_error() + } + #[instrument(level = "debug", skip_all, err)] pub async fn get_workspaces(&self) -> Result { let url = format!("{}/api/workspace", self.base_url); diff --git a/libs/database/src/workspace.rs b/libs/database/src/workspace.rs index 24594a83..4ca10707 100644 --- a/libs/database/src/workspace.rs +++ b/libs/database/src/workspace.rs @@ -49,6 +49,30 @@ pub async fn insert_user_workspace( Ok(workspace) } +#[inline] +pub async fn rename_workspace( + tx: &mut Transaction<'_, sqlx::Postgres>, + workspace_id: &Uuid, + new_workspace_name: &str, +) -> Result<(), AppError> { + let res = sqlx::query!( + r#" + UPDATE public.af_workspace + SET workspace_name = $1 + WHERE workspace_id = $2 + "#, + new_workspace_name, + workspace_id, + ) + .execute(tx.deref_mut()) + .await?; + + if res.rows_affected() != 1 { + tracing::error!("Failed to rename workspace, workspace_id: {}", workspace_id); + } + Ok(()) +} + /// Checks whether a user, identified by a UUID, is an 'Owner' of a workspace, identified by its /// workspace_id. #[inline] diff --git a/libs/shared-entity/src/dto/workspace_dto.rs b/libs/shared-entity/src/dto/workspace_dto.rs index e25655d3..68b815b0 100644 --- a/libs/shared-entity/src/dto/workspace_dto.rs +++ b/libs/shared-entity/src/dto/workspace_dto.rs @@ -82,3 +82,9 @@ pub struct BlobMetadata { pub struct CreateWorkspaceParam { pub workspace_name: Option, } + +#[derive(Serialize, Deserialize)] +pub struct PatchWorkspaceParam { + pub workspace_id: Uuid, + pub workspace_name: Option, +} diff --git a/src/api/workspace.rs b/src/api/workspace.rs index a3a37913..59598046 100644 --- a/src/api/workspace.rs +++ b/src/api/workspace.rs @@ -50,6 +50,7 @@ pub fn workspace_scope() -> Scope { .service(web::resource("") .route(web::get().to(list_workspace_handler)) .route(web::post().to(create_workpace_handler)) + .route(web::patch().to(patch_workpace_handler)) ) .service(web::resource("/{workspace_id}") .route(web::delete().to(delete_workspace_handler)) @@ -134,6 +135,23 @@ async fn create_workpace_handler( Ok(AppResponse::Ok().with_data(new_workspace).into()) } +// Adds a workspace for user, if success, return the workspace id +#[instrument(skip_all, err)] +async fn patch_workpace_handler( + _uuid: UserUuid, + state: Data, + params: Json, +) -> Result>> { + let params = params.into_inner(); + workspace::ops::patch_workspace( + &state.pg_pool, + ¶ms.workspace_id, + params.workspace_name.as_deref(), + ) + .await?; + Ok(AppResponse::Ok().into()) +} + async fn delete_workspace_handler( _user_id: UserUuid, workspace_id: web::Path, diff --git a/src/biz/workspace/ops.rs b/src/biz/workspace/ops.rs index 18ba7bc5..ea3016fa 100644 --- a/src/biz/workspace/ops.rs +++ b/src/biz/workspace/ops.rs @@ -5,7 +5,7 @@ use database::pg_row::{AFWorkspaceMemberRow, AFWorkspaceRow}; use database::user::select_uid_from_email; use database::workspace::{ delete_from_workspace, delete_workspace_members, insert_user_workspace, - insert_workspace_member_with_txn, select_all_user_workspaces, select_workspace, + insert_workspace_member_with_txn, rename_workspace, 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}; @@ -40,6 +40,19 @@ pub async fn create_workspace_for_user( Ok(new_workspace) } +pub async fn patch_workspace( + pg_pool: &PgPool, + workspace_id: &Uuid, + workspace_name: Option<&str>, +) -> Result<(), AppResponseError> { + let mut tx = pg_pool.begin().await?; + if let Some(workspace_name) = workspace_name { + rename_workspace(&mut tx, workspace_id, workspace_name).await?; + } + tx.commit().await?; + Ok(()) +} + pub async fn get_all_user_workspaces( pg_pool: &PgPool, user_uuid: &Uuid,