mirror of
https://github.com/AppFlowy-IO/AppFlowy-Cloud.git
synced 2025-04-19 03:24:42 -04:00
feat: batch unpublish
This commit is contained in:
parent
31f5c786a6
commit
b525e333f0
11 changed files with 96 additions and 106 deletions
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n DELETE FROM af_published_collab\n WHERE workspace_id = $1 AND view_id = $2\n ",
|
||||
"query": "\n DELETE FROM af_published_collab\n WHERE workspace_id = $1\n AND view_id = ANY($2)\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Uuid"
|
||||
"UuidArray"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "cb7c6555f1c837748cf0c7706000b28026c3dcdb7305f8c3a49082e1067f1fd8"
|
||||
"hash": "02eab22805a4cba99dc7fc554f63f6a16f89a5160d1095e1906985b9ec2123ec"
|
||||
}
|
24
.sqlx/query-87628d6739441a22229d08832d09cbf4598c36204a6885b2e279c848cedcfa75.json
generated
Normal file
24
.sqlx/query-87628d6739441a22229d08832d09cbf4598c36204a6885b2e279c848cedcfa75.json
generated
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT COUNT(*)\n FROM af_published_collab\n WHERE workspace_id = $1\n AND view_id = ANY($2)\n AND published_by = (SELECT uid FROM af_user WHERE uuid = $3)\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "count",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"UuidArray",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "87628d6739441a22229d08832d09cbf4598c36204a6885b2e279c848cedcfa75"
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n UPDATE af_published_collab\n SET blob = $1\n WHERE workspace_id = $2\n AND view_id = $3\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Bytea",
|
||||
"Uuid",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "c51b2030045bd58b1b3ac2ed12c24fedd32b19b456f2a865860cad597903fa5b"
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO af_published_collab (workspace_id, view_id, doc_name, published_by, metadata)\n SELECT * FROM UNNEST(\n (SELECT array_agg((SELECT $1::uuid)) FROM generate_series(1, $6))::uuid[],\n $2::uuid[],\n $3::text[],\n (SELECT array_agg((SELECT uid FROM af_user WHERE uuid = $4)) FROM generate_series(1, $6))::bigint[],\n $5::jsonb[]\n )\n ON CONFLICT (workspace_id, view_id) DO UPDATE\n SET metadata = EXCLUDED.metadata\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"UuidArray",
|
||||
"TextArray",
|
||||
"Uuid",
|
||||
"JsonbArray",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "d979dc9b4db36e59e4eda6b9643c034e89a684d739333653bea51a402226076e"
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT EXISTS(\n SELECT 1\n FROM af_published_collab\n WHERE workspace_id = $1\n AND view_id = $2\n AND published_by = (SELECT uid FROM af_user WHERE uuid = $3)\n );\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "exists",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Uuid",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "dd6ff315461ec898e43bc4624b51b10ef73fd1f87f94ce4f2e9f32136a1b4f67"
|
||||
}
|
20
.sqlx/query-fa640accaba3655cd842ebc4838d65fcd003c6a645876f7aa8e677eaad59517c.json
generated
Normal file
20
.sqlx/query-fa640accaba3655cd842ebc4838d65fcd003c6a645876f7aa8e677eaad59517c.json
generated
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO af_published_collab (workspace_id, view_id, doc_name, published_by, metadata, blob)\n SELECT * FROM UNNEST(\n (SELECT array_agg((SELECT $1::uuid)) FROM generate_series(1, $7))::uuid[],\n $2::uuid[],\n $3::text[],\n (SELECT array_agg((SELECT uid FROM af_user WHERE uuid = $4)) FROM generate_series(1, $7))::bigint[],\n $5::jsonb[],\n $6::bytea[]\n )\n ON CONFLICT (workspace_id, view_id) DO UPDATE\n SET metadata = EXCLUDED.metadata\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"UuidArray",
|
||||
"TextArray",
|
||||
"Uuid",
|
||||
"JsonbArray",
|
||||
"ByteaArray",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "fa640accaba3655cd842ebc4838d65fcd003c6a645876f7aa8e677eaad59517c"
|
||||
}
|
|
@ -76,18 +76,16 @@ impl Client {
|
|||
AppResponse::<()>::from_response(resp).await?.into_error()
|
||||
}
|
||||
|
||||
pub async fn delete_published_collab(
|
||||
pub async fn unpublish_collabs(
|
||||
&self,
|
||||
workspace_id: &str,
|
||||
view_id: &uuid::Uuid,
|
||||
view_ids: &[uuid::Uuid],
|
||||
) -> Result<(), AppResponseError> {
|
||||
let url = format!(
|
||||
"{}/api/workspace/{}/publish/{}",
|
||||
self.base_url, workspace_id, view_id
|
||||
);
|
||||
let url = format!("{}/api/workspace/{}/publish", self.base_url, workspace_id);
|
||||
let resp = self
|
||||
.http_client_with_auth(Method::DELETE, &url)
|
||||
.await?
|
||||
.json(view_ids)
|
||||
.send()
|
||||
.await?;
|
||||
AppResponse::<()>::from_response(resp).await?.into_error()
|
||||
|
|
|
@ -144,30 +144,31 @@ pub async fn select_user_is_workspace_owner(
|
|||
Ok(exists.unwrap_or(false))
|
||||
}
|
||||
|
||||
pub async fn select_user_is_collab_publisher(
|
||||
pub async fn select_user_is_collab_publisher_for_all_views(
|
||||
pg_pool: &PgPool,
|
||||
user_uuid: &Uuid,
|
||||
workspace_uuid: &Uuid,
|
||||
view_id: &Uuid,
|
||||
view_ids: &[Uuid],
|
||||
) -> Result<bool, AppError> {
|
||||
let exists = sqlx::query_scalar!(
|
||||
let count = sqlx::query_scalar!(
|
||||
r#"
|
||||
SELECT EXISTS(
|
||||
SELECT 1
|
||||
FROM af_published_collab
|
||||
WHERE workspace_id = $1
|
||||
AND view_id = $2
|
||||
AND published_by = (SELECT uid FROM af_user WHERE uuid = $3)
|
||||
);
|
||||
SELECT COUNT(*)
|
||||
FROM af_published_collab
|
||||
WHERE workspace_id = $1
|
||||
AND view_id = ANY($2)
|
||||
AND published_by = (SELECT uid FROM af_user WHERE uuid = $3)
|
||||
"#,
|
||||
workspace_uuid,
|
||||
view_id,
|
||||
view_ids,
|
||||
user_uuid,
|
||||
)
|
||||
.fetch_one(pg_pool)
|
||||
.await?;
|
||||
|
||||
Ok(exists.unwrap_or(false))
|
||||
match count {
|
||||
Some(c) => Ok(c == view_ids.len() as i64),
|
||||
None => Ok(false),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -963,27 +964,28 @@ pub async fn select_publish_collab_meta<'a, E: Executor<'a, Database = Postgres>
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub async fn delete_published_collab<'a, E: Executor<'a, Database = Postgres>>(
|
||||
pub async fn delete_published_collabs<'a, E: Executor<'a, Database = Postgres>>(
|
||||
executor: E,
|
||||
workspace_id: &Uuid,
|
||||
view_id: &Uuid,
|
||||
view_ids: &[Uuid],
|
||||
) -> Result<(), AppError> {
|
||||
let res = sqlx::query!(
|
||||
r#"
|
||||
DELETE FROM af_published_collab
|
||||
WHERE workspace_id = $1 AND view_id = $2
|
||||
WHERE workspace_id = $1
|
||||
AND view_id = ANY($2)
|
||||
"#,
|
||||
workspace_id,
|
||||
view_id,
|
||||
view_ids,
|
||||
)
|
||||
.execute(executor)
|
||||
.await?;
|
||||
|
||||
if res.rows_affected() != 1 {
|
||||
if res.rows_affected() != view_ids.len() as u64 {
|
||||
tracing::error!(
|
||||
"Failed to delete published collab, workspace_id: {}, view_id: {}, rows_affected: {}",
|
||||
"Failed to delete published collabs, workspace_id: {}, view_ids: {:?}, rows_affected: {}",
|
||||
workspace_id,
|
||||
view_id,
|
||||
view_ids,
|
||||
res.rows_affected()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -148,11 +148,8 @@ pub fn workspace_scope() -> Scope {
|
|||
)
|
||||
.service(
|
||||
web::resource("/{workspace_id}/publish")
|
||||
.route(web::post().to(post_publish_collab_handler))
|
||||
)
|
||||
.service(
|
||||
web::resource("/{workspace_id}/publish/{view_id}")
|
||||
.route(web::delete().to(delete_publish_collab_handler))
|
||||
.route(web::post().to(post_publish_collabs_handler))
|
||||
.route(web::delete().to(delete_published_collabs_handler))
|
||||
)
|
||||
.service(
|
||||
web::resource("/{workspace_id}/collab/{object_id}/member/list")
|
||||
|
@ -1003,7 +1000,7 @@ async fn get_published_collab_info_handler(
|
|||
Ok(Json(AppResponse::Ok().with_data(collab_data)))
|
||||
}
|
||||
|
||||
async fn post_publish_collab_handler(
|
||||
async fn post_publish_collabs_handler(
|
||||
workspace_id: web::Path<Uuid>,
|
||||
user_uuid: UserUuid,
|
||||
mut payload: Payload,
|
||||
|
@ -1015,7 +1012,6 @@ async fn post_publish_collab_handler(
|
|||
let mut accumulator = Vec::<PublishCollabItem<serde_json::Value, Vec<u8>>>::new();
|
||||
|
||||
while let Some(item) = payload.try_next().await? {
|
||||
println!("Publishing collab item: {:#?}", item);
|
||||
let item_len = item.len();
|
||||
|
||||
let mut cursor = Cursor::new(item);
|
||||
|
@ -1044,21 +1040,29 @@ async fn post_publish_collab_handler(
|
|||
);
|
||||
}
|
||||
|
||||
if accumulator.is_empty() {
|
||||
return Ok(Json(AppResponse::Ok()));
|
||||
}
|
||||
biz::workspace::ops::publish_collabs(&state.pg_pool, &workspace_id, &user_uuid, &accumulator)
|
||||
.await?;
|
||||
Ok(Json(AppResponse::Ok()))
|
||||
}
|
||||
|
||||
async fn delete_publish_collab_handler(
|
||||
path_param: web::Path<(Uuid, Uuid)>,
|
||||
async fn delete_published_collabs_handler(
|
||||
workspace_id: web::Path<Uuid>,
|
||||
user_uuid: UserUuid,
|
||||
state: Data<AppState>,
|
||||
view_ids: Json<Vec<Uuid>>,
|
||||
) -> Result<Json<AppResponse<()>>> {
|
||||
let (workspace_id, view_id) = path_param.into_inner();
|
||||
let workspace_id = workspace_id.into_inner();
|
||||
let view_ids = view_ids.into_inner();
|
||||
if view_ids.is_empty() {
|
||||
return Ok(Json(AppResponse::Ok()));
|
||||
}
|
||||
biz::workspace::ops::delete_published_workspace_collab(
|
||||
&state.pg_pool,
|
||||
&workspace_id,
|
||||
&view_id,
|
||||
&view_ids,
|
||||
&user_uuid,
|
||||
)
|
||||
.await?;
|
||||
|
|
|
@ -19,11 +19,11 @@ use database::pg_row::{AFWorkspaceMemberRow, AFWorkspaceRow};
|
|||
|
||||
use database::user::select_uid_from_email;
|
||||
use database::workspace::{
|
||||
change_workspace_icon, delete_from_workspace, delete_published_collab, delete_workspace_members,
|
||||
change_workspace_icon, delete_from_workspace, delete_published_collabs, delete_workspace_members,
|
||||
get_invitation_by_id, insert_or_replace_publish_collab_metas, insert_user_workspace,
|
||||
insert_workspace_invitation, rename_workspace, select_all_user_workspaces,
|
||||
select_publish_collab_meta, select_published_collab_blob, select_published_collab_info,
|
||||
select_user_is_collab_publisher, select_user_is_workspace_owner, select_workspace,
|
||||
select_user_is_collab_publisher_for_all_views, select_user_is_workspace_owner, select_workspace,
|
||||
select_workspace_invitations_for_user, select_workspace_member, select_workspace_member_list,
|
||||
select_workspace_publish_namespace, select_workspace_publish_namespace_exists,
|
||||
select_workspace_settings, select_workspace_total_collab_bytes, update_updated_at_of_workspace,
|
||||
|
@ -184,11 +184,11 @@ pub async fn get_published_collab_info(
|
|||
pub async fn delete_published_workspace_collab(
|
||||
pg_pool: &PgPool,
|
||||
workspace_id: &Uuid,
|
||||
view_id: &Uuid,
|
||||
view_ids: &[Uuid],
|
||||
user_uuid: &Uuid,
|
||||
) -> Result<(), AppError> {
|
||||
check_workspace_owner_or_publisher(pg_pool, user_uuid, workspace_id, view_id).await?;
|
||||
delete_published_collab(pg_pool, workspace_id, view_id).await?;
|
||||
check_workspace_owner_or_publisher(pg_pool, user_uuid, workspace_id, view_ids).await?;
|
||||
delete_published_collabs(pg_pool, workspace_id, view_ids).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -573,12 +573,13 @@ async fn check_workspace_owner_or_publisher(
|
|||
pg_pool: &PgPool,
|
||||
user_uuid: &Uuid,
|
||||
workspace_id: &Uuid,
|
||||
view_id: &Uuid,
|
||||
view_id: &[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, view_id).await?;
|
||||
select_user_is_collab_publisher_for_all_views(pg_pool, user_uuid, workspace_id, view_id)
|
||||
.await?;
|
||||
if !is_publisher {
|
||||
return Err(AppError::UserUnAuthorized(
|
||||
"User is not the owner of the workspace or the publisher of the document".to_string(),
|
||||
|
|
|
@ -129,7 +129,7 @@ async fn test_publish_doc() {
|
|||
assert_eq!(blob, "yrs_encoded_data_1");
|
||||
}
|
||||
|
||||
c.delete_published_collab(&workspace_id, &view_id_1)
|
||||
c.unpublish_collabs(&workspace_id, &[view_id_1])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue