feat: use view id

This commit is contained in:
Zack Fu Zi Xiang 2024-06-18 18:20:05 +08:00
parent 31b3275d8d
commit 18e9d0abae
No known key found for this signature in database
7 changed files with 75 additions and 52 deletions

View file

@ -1,7 +1,10 @@
use bytes::Bytes;
use database_entity::dto::UpdatePublishNamespace;
use reqwest::{Body, Method};
use shared_entity::response::{AppResponse, AppResponseError};
use shared_entity::{
dto::workspace_dto::PublishInfo,
response::{AppResponse, AppResponseError},
};
use crate::Client;
@ -112,23 +115,13 @@ impl Client {
}
}
#[derive(Debug, serde::Deserialize)]
pub struct PublishInfo {
pub namespace: String,
pub doc_name: String,
pub view_id: uuid::Uuid,
}
// Guest API (no login required)
impl Client {
pub async fn get_published_info(
&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)

View file

@ -147,7 +147,7 @@ pub async fn select_user_is_collab_publisher(
pg_pool: &PgPool,
user_uuid: &Uuid,
workspace_uuid: &Uuid,
doc_name: &str,
view_id: &Uuid,
) -> Result<bool, AppError> {
let exists = sqlx::query_scalar!(
r#"
@ -155,12 +155,12 @@ pub async fn select_user_is_collab_publisher(
SELECT 1
FROM af_published_collab
WHERE workspace_id = $1
AND doc_name = $2
AND view_id = $2
AND published_by = (SELECT uid FROM af_user WHERE uuid = $3)
);
"#,
workspace_uuid,
doc_name,
view_id,
user_uuid,
)
.fetch_one(pg_pool)
@ -890,20 +890,22 @@ pub async fn select_workspace_publish_namespace<'a, E: Executor<'a, Database = P
pub async fn insert_or_replace_publish_collab_meta<'a, E: Executor<'a, Database = Postgres>>(
executor: E,
workspace_id: &Uuid,
view_id: &Uuid,
doc_name: &str,
publisher_uuid: &Uuid,
metadata: &serde_json::Value,
) -> Result<(), AppError> {
let res = sqlx::query!(
r#"
INSERT INTO af_published_collab (doc_name, published_by, workspace_id, metadata)
VALUES ($1, (SELECT uid FROM af_user WHERE uuid = $2), $3, $4)
ON CONFLICT (workspace_id, doc_name) DO UPDATE
SET metadata = $4
INSERT INTO af_published_collab (workspace_id, view_id, doc_name, published_by, metadata)
VALUES ($1, $2, $3, (SELECT uid FROM af_user WHERE uuid = $4), $5)
ON CONFLICT (workspace_id, view_id) DO UPDATE
SET metadata = $5
"#,
workspace_id,
view_id,
doc_name,
publisher_uuid,
workspace_id,
metadata,
)
.execute(executor)
@ -945,24 +947,24 @@ pub async fn select_publish_collab_meta<'a, E: Executor<'a, Database = Postgres>
pub async fn delete_published_collab<'a, E: Executor<'a, Database = Postgres>>(
executor: E,
workspace_id: &Uuid,
doc_name: &str,
view_id: &Uuid,
) -> Result<(), AppError> {
let res = sqlx::query!(
r#"
DELETE FROM af_published_collab
WHERE workspace_id = $1 AND doc_name = $2
WHERE workspace_id = $1 AND view_id = $2
"#,
workspace_id,
doc_name,
view_id,
)
.execute(executor)
.await?;
if res.rows_affected() != 1 {
tracing::error!(
"Failed to delete published collab, workspace_id: {}, doc_name: {}, rows_affected: {}",
"Failed to delete published collab, workspace_id: {}, view_id: {}, rows_affected: {}",
workspace_id,
doc_name,
view_id,
res.rows_affected()
);
}
@ -974,18 +976,19 @@ pub async fn delete_published_collab<'a, E: Executor<'a, Database = Postgres>>(
pub async fn insert_or_replace_published_collab_blob<'a, E: Executor<'a, Database = Postgres>>(
executor: E,
workspace_id: &Uuid,
doc_name: &str,
view_id: &Uuid,
blob: &[u8],
) -> Result<(), AppError> {
let res = sqlx::query!(
r#"
UPDATE af_published_collab
SET blob = $1
WHERE workspace_id = $2 AND doc_name = $3
WHERE workspace_id = $2
AND view_id = $3
"#,
blob,
workspace_id,
doc_name,
view_id,
)
.execute(executor)
.await?;
@ -993,7 +996,7 @@ pub async fn insert_or_replace_published_collab_blob<'a, E: Executor<'a, Databas
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()
workspace_id, view_id, res.rows_affected()
);
}

View file

@ -120,3 +120,10 @@ pub struct CollabResponse {
#[serde(default)]
pub object_id: String,
}
#[derive(Debug, serde::Deserialize)]
pub struct PublishInfo {
pub namespace: String,
pub doc_name: String,
pub view_id: uuid::Uuid,
}

View file

@ -0,0 +1,6 @@
ALTER TABLE af_published_collab ADD COLUMN view_id UUID NOT NULL DEFAULT gen_random_uuid();
ALTER TABLE af_published_collab DROP CONSTRAINT af_published_collab_pkey;
ALTER TABLE af_published_collab ADD PRIMARY KEY (workspace_id, view_id);
CREATE INDEX IF NOT EXISTS idx_workspace_id_on_af_published_collab ON af_published_collab (workspace_id);
CREATE INDEX IF NOT EXISTS idx_published_by_on_af_published_collab ON af_published_collab (published_by);

View file

@ -138,12 +138,15 @@ pub fn workspace_scope() -> Scope {
.route(web::get().to(get_publish_namespace_handler))
)
.service(
web::resource("/{workspace_id}/publish/{doc_name}/blob")
web::resource("/{workspace_id}/publish/{view_id}/blob")
.route(web::put().to(put_publish_collab_blob_handler))
)
.service(
web::resource("/{workspace_id}/publish/{doc_name}")
web::resource("/{workspace_id}/publish/{view_id}/{doc_name}")
.route(web::put().to(put_publish_collab_handler))
)
.service(
web::resource("/{workspace_id}/publish/{view_id}")
.route(web::delete().to(delete_publish_collab_handler))
)
.service(
@ -986,15 +989,16 @@ async fn get_published_collab_blob_handler(
}
async fn put_publish_collab_handler(
path_param: web::Path<(Uuid, String)>,
path_param: web::Path<(Uuid, Uuid, String)>,
user_uuid: UserUuid,
metadata: Json<serde_json::Value>,
state: Data<AppState>,
) -> Result<Json<AppResponse<()>>> {
let (workspace_id, doc_name) = path_param.into_inner();
let (workspace_id, view_id, doc_name) = path_param.into_inner();
biz::workspace::ops::publish_collab(
&state.pg_pool,
&workspace_id,
&view_id,
&doc_name,
&user_uuid,
&metadata,
@ -1004,16 +1008,16 @@ async fn put_publish_collab_handler(
}
async fn put_publish_collab_blob_handler(
path_param: web::Path<(Uuid, String)>,
path_param: web::Path<(Uuid, Uuid)>,
user_uuid: UserUuid,
collab_data: Bytes,
state: Data<AppState>,
) -> Result<Json<AppResponse<()>>> {
let (workspace_id, doc_name) = path_param.into_inner();
let (workspace_id, view_id) = path_param.into_inner();
biz::workspace::ops::put_published_collab_blob(
&state.pg_pool,
&workspace_id,
&doc_name,
&view_id,
&user_uuid,
&collab_data,
)
@ -1022,15 +1026,15 @@ async fn put_publish_collab_blob_handler(
}
async fn delete_publish_collab_handler(
path_param: web::Path<(Uuid, String)>,
path_param: web::Path<(Uuid, Uuid)>,
user_uuid: UserUuid,
state: Data<AppState>,
) -> Result<Json<AppResponse<()>>> {
let (workspace_id, doc_name) = path_param.into_inner();
let (workspace_id, view_id) = path_param.into_inner();
biz::workspace::ops::delete_published_workspace_collab(
&state.pg_pool,
&workspace_id,
&doc_name,
&view_id,
&user_uuid,
)
.await?;

View file

@ -153,26 +153,34 @@ pub async fn get_workspace_publish_namespace(
pub async fn publish_collab(
pg_pool: &PgPool,
workspace_id: &Uuid,
view_id: &Uuid,
doc_name: &str,
publisher_uuid: &Uuid,
metadata: &serde_json::Value,
) -> Result<(), AppError> {
check_workspace_owner_or_publisher(pg_pool, publisher_uuid, workspace_id, doc_name).await?;
check_workspace_owner_or_publisher(pg_pool, publisher_uuid, workspace_id, view_id).await?;
check_collab_doc_name(doc_name).await?;
insert_or_replace_publish_collab_meta(pg_pool, workspace_id, doc_name, publisher_uuid, metadata)
.await?;
insert_or_replace_publish_collab_meta(
pg_pool,
workspace_id,
view_id,
doc_name,
publisher_uuid,
metadata,
)
.await?;
Ok(())
}
pub async fn put_published_collab_blob(
pg_pool: &PgPool,
workspace_id: &Uuid,
doc_name: &str,
view_id: &Uuid,
publisher_uuid: &Uuid,
collab_data: &[u8],
) -> Result<(), AppError> {
check_workspace_owner_or_publisher(pg_pool, publisher_uuid, workspace_id, doc_name).await?;
insert_or_replace_published_collab_blob(pg_pool, workspace_id, doc_name, collab_data).await?;
check_workspace_owner_or_publisher(pg_pool, publisher_uuid, workspace_id, view_id).await?;
insert_or_replace_published_collab_blob(pg_pool, workspace_id, view_id, collab_data).await?;
Ok(())
}
@ -196,11 +204,11 @@ pub async fn get_published_collab_blob(
pub async fn delete_published_workspace_collab(
pg_pool: &PgPool,
workspace_id: &Uuid,
doc_name: &str,
view_id: &Uuid,
user_uuid: &Uuid,
) -> Result<(), AppError> {
check_workspace_owner_or_publisher(pg_pool, user_uuid, workspace_id, doc_name).await?;
delete_published_collab(pg_pool, workspace_id, doc_name).await?;
check_workspace_owner_or_publisher(pg_pool, user_uuid, workspace_id, view_id).await?;
delete_published_collab(pg_pool, workspace_id, view_id).await?;
Ok(())
}
@ -585,12 +593,12 @@ async fn check_workspace_owner_or_publisher(
pg_pool: &PgPool,
user_uuid: &Uuid,
workspace_id: &Uuid,
doc_name: &str,
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, doc_name).await?;
select_user_is_collab_publisher(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(),

View file

@ -73,8 +73,10 @@ async fn test_publish_doc() {
.unwrap();
let my_doc_name = "my-doc";
let view_id = uuid::Uuid::new_v4();
c.publish_collab(
&workspace_id,
&view_id,
my_doc_name,
Metadata {
title: "my_title".to_string(),
@ -99,7 +101,7 @@ async fn test_publish_doc() {
assert!(collab_data.is_empty()); // empty data because publisher need to set it
}
c.put_published_collab_blob(&workspace_id, my_doc_name, "some_collab_data")
c.put_published_collab_blob(&workspace_id, &view_id, "some_collab_data")
.await
.unwrap();
@ -113,7 +115,7 @@ async fn test_publish_doc() {
assert!(collab_data == "some_collab_data");
}
c.delete_published_collab(&workspace_id, my_doc_name)
c.delete_published_collab(&workspace_id, &view_id)
.await
.unwrap();