diff --git a/.sqlx/query-12dcf313d0e4c0c0da2569f3326e49e1a78fa54537cb8826a20bef2769d04dd1.json b/.sqlx/query-15613595695e2e722c45712931ce0eb8d2a3deb1bb665d1f091f354a3ad96b92.json similarity index 72% rename from .sqlx/query-12dcf313d0e4c0c0da2569f3326e49e1a78fa54537cb8826a20bef2769d04dd1.json rename to .sqlx/query-15613595695e2e722c45712931ce0eb8d2a3deb1bb665d1f091f354a3ad96b92.json index 4b670cff..6525089b 100644 --- a/.sqlx/query-12dcf313d0e4c0c0da2569f3326e49e1a78fa54537cb8826a20bef2769d04dd1.json +++ b/.sqlx/query-15613595695e2e722c45712931ce0eb8d2a3deb1bb665d1f091f354a3ad96b92.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT EXISTS(\n SELECT 1\n FROM af_published_collab\n WHERE workspace_id = $1\n AND publish_name = $2\n )\n ", + "query": "\n SELECT EXISTS(\n SELECT 1\n FROM af_published_collab\n WHERE workspace_id = $1\n AND publish_name = $2\n AND unpublished_at IS NULL\n )\n ", "describe": { "columns": [ { @@ -19,5 +19,5 @@ null ] }, - "hash": "12dcf313d0e4c0c0da2569f3326e49e1a78fa54537cb8826a20bef2769d04dd1" + "hash": "15613595695e2e722c45712931ce0eb8d2a3deb1bb665d1f091f354a3ad96b92" } diff --git a/.sqlx/query-2ba7fdabdd71d2e3ac6dc1b67af17e8dcb59d13b644bc336da5351184ec4c9e1.json b/.sqlx/query-a98cb855107a0641979d3a7fecaf01df960e3fe5abd841752c05782c7203ff12.json similarity index 60% rename from .sqlx/query-2ba7fdabdd71d2e3ac6dc1b67af17e8dcb59d13b644bc336da5351184ec4c9e1.json rename to .sqlx/query-a98cb855107a0641979d3a7fecaf01df960e3fe5abd841752c05782c7203ff12.json index 926c6e56..f6ce671a 100644 --- a/.sqlx/query-2ba7fdabdd71d2e3ac6dc1b67af17e8dcb59d13b644bc336da5351184ec4c9e1.json +++ b/.sqlx/query-a98cb855107a0641979d3a7fecaf01df960e3fe5abd841752c05782c7203ff12.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n UPDATE af_published_collab\n SET publish_name = $1\n WHERE workspace_id = $2\n AND view_id = $3\n ", + "query": "\n UPDATE af_published_collab\n SET publish_name = $1\n WHERE workspace_id = $2\n AND view_id = $3\n ", "describe": { "columns": [], "parameters": { @@ -12,5 +12,5 @@ }, "nullable": [] }, - "hash": "2ba7fdabdd71d2e3ac6dc1b67af17e8dcb59d13b644bc336da5351184ec4c9e1" + "hash": "a98cb855107a0641979d3a7fecaf01df960e3fe5abd841752c05782c7203ff12" } diff --git a/libs/database/src/publish.rs b/libs/database/src/publish.rs index 0b8fb3be..61d0a36c 100644 --- a/libs/database/src/publish.rs +++ b/libs/database/src/publish.rs @@ -213,6 +213,32 @@ pub async fn select_workspace_publish_namespace( Ok(res) } +async fn delete_published_collabs( + txn: &mut sqlx::Transaction<'_, Postgres>, + workspace_id: &Uuid, + publish_names: &[String], +) -> Result<(), AppError> { + let delete_publish_names = sqlx::query_scalar!( + r#" + DELETE FROM af_published_collab + WHERE workspace_id = $1 + AND publish_name = ANY($2::text[]) + RETURNING publish_name + "#, + workspace_id, + &publish_names, + ) + .fetch_all(txn.as_mut()) + .await?; + if !delete_publish_names.is_empty() { + tracing::info!( + "Deleted existing published collab record with publish names: {:?}", + delete_publish_names + ); + } + Ok(()) +} + #[inline] pub async fn insert_or_replace_publish_collabs( pg_pool: &PgPool, @@ -233,25 +259,7 @@ pub async fn insert_or_replace_publish_collabs( }); let mut txn = pg_pool.begin().await?; - - let delete_publish_names = sqlx::query_scalar!( - r#" - DELETE FROM af_published_collab - WHERE workspace_id = $1 - AND publish_name = ANY($2::text[]) - RETURNING publish_name - "#, - workspace_id, - &publish_names, - ) - .fetch_all(txn.as_mut()) - .await?; - if !delete_publish_names.is_empty() { - tracing::info!( - "Deleted existing published collab record with publish names: {:?}", - delete_publish_names - ); - } + delete_published_collabs(&mut txn, workspace_id, &publish_names).await?; let res = sqlx::query!( r#" @@ -354,6 +362,15 @@ pub async fn update_published_collabs( workspace_id: &Uuid, patches: &[PatchPublishedCollab], ) -> Result<(), AppError> { + { + // Delete existing published collab records with the same publish names + let publish_names: Vec = patches + .iter() + .filter_map(|patch| patch.publish_name.clone()) + .collect(); + delete_published_collabs(txn, workspace_id, &publish_names).await?; + } + for patch in patches { let new_publish_name = match &patch.publish_name { Some(new_publish_name) => new_publish_name, @@ -365,7 +382,7 @@ pub async fn update_published_collabs( UPDATE af_published_collab SET publish_name = $1 WHERE workspace_id = $2 - AND view_id = $3 + AND view_id = $3 "#, patch.publish_name, workspace_id, diff --git a/libs/database/src/workspace.rs b/libs/database/src/workspace.rs index a494d656..7d30c7be 100644 --- a/libs/database/src/workspace.rs +++ b/libs/database/src/workspace.rs @@ -1491,7 +1491,8 @@ pub async fn select_publish_name_exists( SELECT 1 FROM af_published_collab WHERE workspace_id = $1 - AND publish_name = $2 + AND publish_name = $2 + AND unpublished_at IS NULL ) "#, workspace_uuid, diff --git a/tests/workspace/publish.rs b/tests/workspace/publish.rs index ce760560..5296a50b 100644 --- a/tests/workspace/publish.rs +++ b/tests/workspace/publish.rs @@ -1709,3 +1709,69 @@ async fn test_republish_doc() { assert_eq!(err.code, ErrorCode::RecordNotFound, "{:?}", err); } } + +#[tokio::test] +async fn test_republish_patch() { + let (c, _user) = generate_unique_registered_user_client().await; + let workspace_id = get_first_workspace_string(&c).await; + let my_namespace = uuid::Uuid::new_v4().to_string(); + c.set_workspace_publish_namespace(&workspace_id.to_string(), my_namespace.clone()) + .await + .unwrap(); + + let publish_name = "my-publish-name"; + let view_id = uuid::Uuid::new_v4(); + + // User publishes 1 doc + c.publish_collabs::( + &workspace_id, + vec![PublishCollabItem { + meta: PublishCollabMetadata { + view_id, + publish_name: publish_name.to_string(), + metadata: MyCustomMetadata { + title: "my_title_1".to_string(), + }, + }, + data: "yrs_encoded_data_1".as_bytes(), + }], + ) + .await + .unwrap(); + + // user unpublishes the doc + c.unpublish_collabs(&workspace_id, &[view_id]) + .await + .unwrap(); + + // User publish another doc + let publish_name_2 = "my-publish-name-2"; + let view_id_2 = uuid::Uuid::new_v4(); + c.publish_collabs::( + &workspace_id, + vec![PublishCollabItem { + meta: PublishCollabMetadata { + view_id: view_id_2, + publish_name: publish_name_2.to_string(), + metadata: MyCustomMetadata { + title: "my_title_1".to_string(), + }, + }, + data: "yrs_encoded_data_1".as_bytes(), + }], + ) + .await + .unwrap(); + + // User change the publish name of the document to publish_name + // which should be allowed since the original document is already unpublished + c.patch_published_collabs( + &workspace_id, + &[PatchPublishedCollab { + view_id: view_id_2, + publish_name: Some(publish_name.to_string()), + }], + ) + .await + .unwrap(); +}