feat: patching of publish name
This commit is contained in:
parent
e738508d79
commit
b775aa9d4c
|
|
@ -3,7 +3,8 @@ use client_api_entity::workspace_dto::PublishInfoView;
|
|||
use client_api_entity::{workspace_dto::PublishedDuplicate, PublishInfo, UpdatePublishNamespace};
|
||||
use client_api_entity::{
|
||||
CreateGlobalCommentParams, CreateReactionParams, DeleteGlobalCommentParams, DeleteReactionParams,
|
||||
GetReactionQueryParams, GlobalComments, PublishInfoMeta, Reactions, UpdateDefaultPublishView,
|
||||
GetReactionQueryParams, GlobalComments, PatchPublishedCollab, PublishInfoMeta, Reactions,
|
||||
UpdateDefaultPublishView,
|
||||
};
|
||||
use reqwest::Method;
|
||||
use shared_entity::response::{AppResponse, AppResponseError};
|
||||
|
|
@ -75,6 +76,22 @@ impl Client {
|
|||
.into_data()
|
||||
}
|
||||
|
||||
pub async fn patch_published_collabs(
|
||||
&self,
|
||||
workspace_id: &str,
|
||||
patches: &[PatchPublishedCollab],
|
||||
) -> Result<(), AppResponseError> {
|
||||
let url = format!("{}/api/workspace/{}/publish", self.base_url, workspace_id);
|
||||
let resp = self
|
||||
.http_client_with_auth(Method::PATCH, &url)
|
||||
.await?
|
||||
.json(patches)
|
||||
.send()
|
||||
.await?;
|
||||
log_request_id(&resp);
|
||||
AppResponse::<()>::from_response(resp).await?.into_error()
|
||||
}
|
||||
|
||||
pub async fn unpublish_collabs(
|
||||
&self,
|
||||
workspace_id: &str,
|
||||
|
|
@ -251,7 +268,7 @@ impl Client {
|
|||
&self,
|
||||
view_id: &uuid::Uuid,
|
||||
) -> Result<PublishInfo, AppResponseError> {
|
||||
let url = format!("{}/api/workspace/published-info/{}", self.base_url, view_id,);
|
||||
let url = format!("{}/api/workspace/published-info/{}", self.base_url, view_id);
|
||||
|
||||
let resp = self.cloud_client.get(&url).send().await?;
|
||||
AppResponse::<PublishInfo>::from_response(resp)
|
||||
|
|
|
|||
|
|
@ -1133,6 +1133,12 @@ pub struct PublishCollabItem<Meta, Data> {
|
|||
pub data: Data,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct PatchPublishedCollab {
|
||||
pub view_id: Uuid,
|
||||
pub publish_name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct GlobalComments {
|
||||
pub comments: Vec<GlobalComment>,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use app_error::AppError;
|
||||
use database_entity::dto::{PublishCollabItem, PublishCollabKey, PublishInfo};
|
||||
use database_entity::dto::{
|
||||
PatchPublishedCollab, PublishCollabItem, PublishCollabKey, PublishInfo,
|
||||
};
|
||||
use sqlx::{Executor, PgPool, Postgres};
|
||||
use uuid::Uuid;
|
||||
|
||||
|
|
@ -238,6 +240,46 @@ pub async fn delete_published_collabs<'a, E: Executor<'a, Database = Postgres>>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub async fn update_published_collabs(
|
||||
txn: &mut sqlx::Transaction<'_, Postgres>,
|
||||
workspace_id: &Uuid,
|
||||
patches: &[PatchPublishedCollab],
|
||||
) -> Result<(), AppError> {
|
||||
for patch in patches {
|
||||
let new_publish_name = match &patch.publish_name {
|
||||
Some(new_publish_name) => new_publish_name,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
let res = sqlx::query!(
|
||||
r#"
|
||||
UPDATE af_published_collab
|
||||
SET publish_name = $1
|
||||
WHERE workspace_id = $2
|
||||
AND view_id = $3
|
||||
"#,
|
||||
patch.publish_name,
|
||||
workspace_id,
|
||||
patch.view_id,
|
||||
)
|
||||
.execute(txn.as_mut())
|
||||
.await?;
|
||||
|
||||
if res.rows_affected() != 1 {
|
||||
tracing::error!(
|
||||
"Failed to update published collab publish name, workspace_id: {}, view_id: {}, new_publish_name: {}, rows_affected: {}",
|
||||
workspace_id,
|
||||
patch.view_id,
|
||||
new_publish_name,
|
||||
res.rows_affected()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub async fn select_published_metadata_for_view_id(
|
||||
pg_pool: &PgPool,
|
||||
|
|
|
|||
|
|
@ -204,7 +204,8 @@ pub fn workspace_scope() -> Scope {
|
|||
.service(
|
||||
web::resource("/{workspace_id}/publish")
|
||||
.route(web::post().to(post_publish_collabs_handler))
|
||||
.route(web::delete().to(delete_published_collabs_handler)),
|
||||
.route(web::delete().to(delete_published_collabs_handler))
|
||||
.route(web::patch().to(patch_published_collabs_handler)),
|
||||
)
|
||||
.service(
|
||||
web::resource("/{workspace_id}/folder").route(web::get().to(get_workspace_folder_handler)),
|
||||
|
|
@ -1440,6 +1441,23 @@ async fn post_publish_collabs_handler(
|
|||
Ok(Json(AppResponse::Ok()))
|
||||
}
|
||||
|
||||
async fn patch_published_collabs_handler(
|
||||
workspace_id: web::Path<Uuid>,
|
||||
user_uuid: UserUuid,
|
||||
state: Data<AppState>,
|
||||
patches: Json<Vec<PatchPublishedCollab>>,
|
||||
) -> Result<Json<AppResponse<()>>> {
|
||||
let workspace_id = workspace_id.into_inner();
|
||||
if patches.is_empty() {
|
||||
return Err(AppError::InvalidRequest("No patches provided".to_string()).into());
|
||||
}
|
||||
state
|
||||
.published_collab_store
|
||||
.patch_collabs(&workspace_id, &user_uuid, &patches)
|
||||
.await?;
|
||||
Ok(Json(AppResponse::Ok()))
|
||||
}
|
||||
|
||||
async fn delete_published_collabs_handler(
|
||||
workspace_id: web::Path<Uuid>,
|
||||
user_uuid: UserUuid,
|
||||
|
|
@ -1449,11 +1467,11 @@ async fn delete_published_collabs_handler(
|
|||
let workspace_id = workspace_id.into_inner();
|
||||
let view_ids = view_ids.into_inner();
|
||||
if view_ids.is_empty() {
|
||||
return Ok(Json(AppResponse::Ok()));
|
||||
return Err(AppError::InvalidRequest("No view_ids provided".to_string()).into());
|
||||
}
|
||||
state
|
||||
.published_collab_store
|
||||
.delete_collab(&workspace_id, &view_ids, &user_uuid)
|
||||
.delete_collabs(&workspace_id, &view_ids, &user_uuid)
|
||||
.await?;
|
||||
Ok(Json(AppResponse::Ok()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@ use database::{
|
|||
collab::GetCollabOrigin,
|
||||
publish::{
|
||||
select_all_published_collab_info, select_default_published_view_id,
|
||||
select_default_published_view_id_for_namespace, update_workspace_default_publish_view,
|
||||
select_default_published_view_id_for_namespace, update_published_collabs,
|
||||
update_workspace_default_publish_view,
|
||||
},
|
||||
};
|
||||
use database_entity::dto::PatchPublishedCollab;
|
||||
use std::sync::Arc;
|
||||
|
||||
use app_error::AppError;
|
||||
|
|
@ -251,12 +253,19 @@ pub trait PublishedCollabStore: Sync + Send + 'static {
|
|||
publish_name: &str,
|
||||
) -> Result<Vec<u8>, AppError>;
|
||||
|
||||
async fn delete_collab(
|
||||
async fn delete_collabs(
|
||||
&self,
|
||||
workspace_id: &Uuid,
|
||||
view_ids: &[Uuid],
|
||||
user_uuid: &Uuid,
|
||||
) -> Result<(), AppError>;
|
||||
|
||||
async fn patch_collabs(
|
||||
&self,
|
||||
workspace_id: &Uuid,
|
||||
user_uuid: &Uuid,
|
||||
patches: &[PatchPublishedCollab],
|
||||
) -> Result<(), AppError>;
|
||||
}
|
||||
|
||||
pub struct PublishedCollabPostgresStore {
|
||||
|
|
@ -351,7 +360,7 @@ impl PublishedCollabStore for PublishedCollabPostgresStore {
|
|||
result
|
||||
}
|
||||
|
||||
async fn delete_collab(
|
||||
async fn delete_collabs(
|
||||
&self,
|
||||
workspace_id: &Uuid,
|
||||
view_ids: &[Uuid],
|
||||
|
|
@ -361,6 +370,15 @@ impl PublishedCollabStore for PublishedCollabPostgresStore {
|
|||
delete_published_collabs(&self.pg_pool, workspace_id, view_ids).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn patch_collabs(
|
||||
&self,
|
||||
workspace_id: &Uuid,
|
||||
user_uuid: &Uuid,
|
||||
patches: &[PatchPublishedCollab],
|
||||
) -> Result<(), AppError> {
|
||||
patch_collabs(&self.pg_pool, workspace_id, user_uuid, patches).await
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PublishedCollabS3StoreWithPostgresFallback {
|
||||
|
|
@ -519,7 +537,7 @@ impl PublishedCollabStore for PublishedCollabS3StoreWithPostgresFallback {
|
|||
}
|
||||
}
|
||||
|
||||
async fn delete_collab(
|
||||
async fn delete_collabs(
|
||||
&self,
|
||||
workspace_id: &Uuid,
|
||||
view_ids: &[Uuid],
|
||||
|
|
@ -534,4 +552,36 @@ impl PublishedCollabStore for PublishedCollabS3StoreWithPostgresFallback {
|
|||
delete_published_collabs(&self.pg_pool, workspace_id, view_ids).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn patch_collabs(
|
||||
&self,
|
||||
workspace_id: &Uuid,
|
||||
user_uuid: &Uuid,
|
||||
patches: &[PatchPublishedCollab],
|
||||
) -> Result<(), AppError> {
|
||||
patch_collabs(&self.pg_pool, workspace_id, user_uuid, patches).await
|
||||
}
|
||||
}
|
||||
|
||||
async fn patch_collabs(
|
||||
pg_pool: &PgPool,
|
||||
workspace_id: &Uuid,
|
||||
user_uuid: &Uuid,
|
||||
patches: &[PatchPublishedCollab],
|
||||
) -> Result<(), AppError> {
|
||||
let view_ids = patches
|
||||
.iter()
|
||||
.map(|patch| patch.view_id)
|
||||
.collect::<Vec<Uuid>>();
|
||||
for patch in patches {
|
||||
if let Some(new_publish_name) = patch.publish_name.as_deref() {
|
||||
check_collab_publish_name(new_publish_name)?;
|
||||
}
|
||||
}
|
||||
check_workspace_owner_or_publisher(pg_pool, user_uuid, workspace_id, &view_ids).await?;
|
||||
|
||||
let mut txn = pg_pool.begin().await?;
|
||||
update_published_collabs(&mut txn, workspace_id, patches).await?;
|
||||
txn.commit().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ use app_error::ErrorCode;
|
|||
use appflowy_cloud::biz::collab::folder_view::collab_folder_to_folder_view;
|
||||
use appflowy_cloud::biz::workspace::ops::collab_from_doc_state;
|
||||
use client_api::entity::{
|
||||
AFRole, GlobalComment, PublishCollabItem, PublishCollabMetadata, PublishInfoMeta,
|
||||
AFRole, GlobalComment, PatchPublishedCollab, PublishCollabItem, PublishCollabMetadata,
|
||||
PublishInfoMeta,
|
||||
};
|
||||
use client_api_test::TestClient;
|
||||
use client_api_test::{generate_unique_registered_user_client, localhost_client};
|
||||
|
|
@ -255,6 +256,55 @@ async fn test_publish_doc() {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let new_publish_name_1 = "new-publish-name-1".to_string();
|
||||
|
||||
// User change publish name
|
||||
c.patch_published_collabs(
|
||||
&workspace_id,
|
||||
&[PatchPublishedCollab {
|
||||
view_id: view_id_1,
|
||||
publish_name: Some(new_publish_name_1.to_string()),
|
||||
}],
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Guest now cannot access the collab using old publish name
|
||||
let guest_client = localhost_client();
|
||||
let err = guest_client
|
||||
.get_published_collab::<MyCustomMetadata>(&my_namespace, publish_name_1)
|
||||
.await
|
||||
.err()
|
||||
.unwrap();
|
||||
assert_eq!(err.code, ErrorCode::RecordNotFound, "{:?}", err);
|
||||
|
||||
// Guest now access the collab using new publish name
|
||||
let guest_client = localhost_client();
|
||||
let _ = guest_client
|
||||
.get_published_collab::<MyCustomMetadata>(&my_namespace, &new_publish_name_1)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Switch back to old publish name
|
||||
c.patch_published_collabs(
|
||||
&workspace_id,
|
||||
&[PatchPublishedCollab {
|
||||
view_id: view_id_1,
|
||||
publish_name: Some(publish_name_1.to_string()),
|
||||
}],
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Guest can access the collab using the orginal publish name
|
||||
let guest_client = localhost_client();
|
||||
let _ = guest_client
|
||||
.get_published_collab::<MyCustomMetadata>(&my_namespace, publish_name_1)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
{
|
||||
// Deleted collab should not be accessible
|
||||
let guest_client = localhost_client();
|
||||
|
|
|
|||
Loading…
Reference in New Issue