Skip to content

Commit c61110a

Browse files
authored
Merge pull request #1544 from AppFlowy-IO/endpoint-to-check-whether-row-document-collab-exists
feat: endpoint to check whether row document collab exists
2 parents a948c8b + 1e1dcdd commit c61110a

File tree

7 files changed

+114
-5
lines changed

7 files changed

+114
-5
lines changed

.sqlx/query-6fbcd1c32c638530461c74f8c8195a5b1e1e6f7a389a6a60d889c88c5f47302a.json

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/client-api/src/http_collab.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ use client_api_entity::workspace_dto::{
1212
ListDatabaseRowUpdatedParam, UpsertDatatabaseRow,
1313
};
1414
use client_api_entity::{
15-
AFCollabEmbedInfo, BatchQueryCollabParams, BatchQueryCollabResult, CollabParams,
16-
CreateCollabData, CreateCollabParams, DeleteCollabParams, PublishCollabItem, QueryCollab,
17-
QueryCollabParams, RepeatedAFCollabEmbedInfo, UpdateCollabWebParams,
15+
AFCollabEmbedInfo, AFDatabaseRowDocumentCollabExistenceInfo, BatchQueryCollabParams,
16+
BatchQueryCollabResult, CollabParams, CreateCollabData, CreateCollabParams, DeleteCollabParams,
17+
PublishCollabItem, QueryCollab, QueryCollabParams, RepeatedAFCollabEmbedInfo,
18+
UpdateCollabWebParams,
1819
};
1920
use collab_rt_entity::collab_proto::{CollabDocStateParams, PayloadCompressionType};
2021
use collab_rt_entity::HttpRealtimeMessage;
@@ -430,6 +431,24 @@ impl Client {
430431
process_response_error(resp).await
431432
}
432433

434+
pub async fn check_if_row_document_collab_exists(
435+
&self,
436+
workspace_id: &Uuid,
437+
object_id: &Uuid,
438+
) -> Result<bool, AppResponseError> {
439+
let url = format!(
440+
"{}/api/workspace/{workspace_id}/collab/{object_id}/row-document-collab-exists",
441+
self.base_url
442+
);
443+
let resp = self
444+
.http_client_with_auth(Method::GET, &url)
445+
.await?
446+
.send()
447+
.await?;
448+
let info = process_response_data::<AFDatabaseRowDocumentCollabExistenceInfo>(resp).await?;
449+
Ok(info.exists)
450+
}
451+
433452
pub async fn get_collab_embed_info(
434453
&self,
435454
workspace_id: &Uuid,

libs/database-entity/src/dto.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,11 @@ pub struct QueryWorkspaceMember {
452452
pub uid: i64,
453453
}
454454

455+
#[derive(Debug, Serialize, Deserialize)]
456+
pub struct AFDatabaseRowDocumentCollabExistenceInfo {
457+
pub exists: bool,
458+
}
459+
455460
#[derive(Debug, Serialize, Deserialize)]
456461
pub struct AFCollabEmbedInfo {
457462
pub object_id: Uuid,

libs/database/src/collab/collab_db_ops.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,24 @@ where
230230
Ok(records)
231231
}
232232

233+
pub async fn select_collab_id_exists<'a, E>(conn: E, object_id: &Uuid) -> Result<bool, sqlx::Error>
234+
where
235+
E: Executor<'a, Database = Postgres>,
236+
{
237+
let exists = sqlx::query_scalar!(
238+
r#"
239+
SELECT EXISTS (
240+
SELECT 1 FROM af_collab
241+
WHERE oid = $1 AND deleted_at IS NULL
242+
)
243+
"#,
244+
object_id,
245+
)
246+
.fetch_one(conn)
247+
.await?;
248+
Ok(exists.unwrap_or(false))
249+
}
250+
233251
#[inline]
234252
pub async fn select_blob_from_af_collab<'a, E>(
235253
conn: E,

src/api/workspace.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::api::util::{compress_type_from_header_value, device_id_from_headers};
33
use crate::api::ws::RealtimeServerAddr;
44
use crate::biz;
55
use crate::biz::authentication::jwt::{Authorization, OptionalUserUuid, UserUuid};
6+
use crate::biz::collab::database::check_if_row_document_collab_exists;
67
use crate::biz::collab::ops::{
78
get_user_favorite_folder_views, get_user_recent_folder_views, get_user_trash_folder_views,
89
};
@@ -184,6 +185,10 @@ pub fn workspace_scope() -> Scope {
184185
web::resource("/v1/{workspace_id}/collab/{object_id}/web-update")
185186
.route(web::post().to(post_web_update_handler)),
186187
)
188+
.service(
189+
web::resource("/{workspace_id}/collab/{object_id}/row-document-collab-exists")
190+
.route(web::get().to(get_row_document_collab_exists_handler)),
191+
)
187192
.service(
188193
web::resource("/{workspace_id}/collab/{object_id}/embed-info")
189194
.route(web::get().to(get_collab_embed_info_handler)),
@@ -1350,6 +1355,28 @@ async fn post_web_update_handler(
13501355
Ok(Json(AppResponse::Ok()))
13511356
}
13521357

1358+
#[instrument(level = "debug", skip_all)]
1359+
async fn get_row_document_collab_exists_handler(
1360+
user_uuid: UserUuid,
1361+
path: web::Path<(Uuid, Uuid)>,
1362+
state: Data<AppState>,
1363+
) -> Result<Json<AppResponse<AFDatabaseRowDocumentCollabExistenceInfo>>> {
1364+
let uid = state
1365+
.user_cache
1366+
.get_user_uid(&user_uuid)
1367+
.await
1368+
.map_err(AppResponseError::from)?;
1369+
let (workspace_id, object_id) = path.into_inner();
1370+
state
1371+
.collab_access_control
1372+
.enforce_action(&workspace_id, &uid, &object_id, Action::Read)
1373+
.await?;
1374+
let exists = check_if_row_document_collab_exists(&state.pg_pool, &object_id).await?;
1375+
Ok(Json(AppResponse::Ok().with_data(
1376+
AFDatabaseRowDocumentCollabExistenceInfo { exists },
1377+
)))
1378+
}
1379+
13531380
async fn post_space_handler(
13541381
user_uuid: UserUuid,
13551382
path: web::Path<Uuid>,

src/biz/collab/database.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use app_error::AppError;
55
use async_trait::async_trait;
66
use collab::lock::RwLock;
77
use collab_database::database_trait::{DatabaseCollabReader, EncodeCollabByOid};
8-
use collab_database::rows::{DatabaseRow, RowId};
8+
use collab_database::rows::{meta_id_from_row_id, DatabaseRow, RowId, RowMetaKey};
99
use collab_database::{
1010
database::{gen_database_group_id, gen_field_id},
1111
entity::FieldType,
@@ -21,7 +21,8 @@ use collab_database::{
2121
};
2222
use collab_entity::{CollabType, EncodedCollab};
2323
use dashmap::DashMap;
24-
use database::collab::{CollabStore, GetCollabOrigin};
24+
use database::collab::{select_collab_id_exists, CollabStore, GetCollabOrigin};
25+
use sqlx::PgPool;
2526
use uuid::Uuid;
2627
use yrs::block::ClientID;
2728

@@ -167,6 +168,17 @@ fn create_card_status_field() -> Field {
167168
.with_type_option_data(field_type, default_select_type_option.into())
168169
}
169170

171+
pub async fn check_if_row_document_collab_exists(
172+
pg_pool: &PgPool,
173+
row_id: &Uuid,
174+
) -> Result<bool, AppError> {
175+
let row_document_collab_id = meta_id_from_row_id(row_id, RowMetaKey::DocumentId);
176+
let row_document_collab_id = Uuid::parse_str(&row_document_collab_id)
177+
.map_err(|_| AppError::Internal(anyhow::anyhow!("Invalid row document collab ID")))?;
178+
let exists = select_collab_id_exists(pg_pool, &row_document_collab_id).await?;
179+
Ok(exists)
180+
}
181+
170182
#[derive(Clone)]
171183
pub struct PostgresDatabaseCollabService {
172184
pub workspace_id: Uuid,

tests/collab/database_crud.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ async fn database_row_upsert_with_doc() {
3737
row_detail.doc,
3838
Some(String::from("This is a document of a database row"))
3939
);
40+
let row_uuid = uuid::Uuid::parse_str(&row_id).unwrap();
41+
let row_collab_doc_exists = &c
42+
.check_if_row_document_collab_exists(&workspace_id, &row_uuid)
43+
.await
44+
.unwrap();
45+
assert!(row_collab_doc_exists)
4046
}
4147
// Upsert row with another doc
4248
let _ = c

0 commit comments

Comments
 (0)