feat: override collab when create (#234)
* feat: override collab when create * chore: clippy * chore: fmt
This commit is contained in:
parent
a07cc0b903
commit
4d113425fe
|
|
@ -24,6 +24,13 @@ impl CreateCollabParams {
|
||||||
pub fn split(self) -> (CollabParams, String) {
|
pub fn split(self) -> (CollabParams, String) {
|
||||||
(self.inner, self.workspace_id)
|
(self.inner, self.workspace_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new<T: ToString>(workspace_id: T, params: CollabParams) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: params,
|
||||||
|
workspace_id: workspace_id.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for CreateCollabParams {
|
impl Deref for CreateCollabParams {
|
||||||
|
|
@ -41,6 +48,30 @@ pub struct CollabParams {
|
||||||
#[validate(custom = "validate_not_empty_payload")]
|
#[validate(custom = "validate_not_empty_payload")]
|
||||||
pub encoded_collab_v1: Vec<u8>,
|
pub encoded_collab_v1: Vec<u8>,
|
||||||
pub collab_type: CollabType,
|
pub collab_type: CollabType,
|
||||||
|
/// Determine whether to override the collab if it exists. Default is false.
|
||||||
|
#[serde(default)]
|
||||||
|
pub override_if_exist: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CollabParams {
|
||||||
|
pub fn new<T: ToString>(
|
||||||
|
object_id: T,
|
||||||
|
collab_type: CollabType,
|
||||||
|
encoded_collab_v1: Vec<u8>,
|
||||||
|
) -> Self {
|
||||||
|
let object_id = object_id.to_string();
|
||||||
|
Self {
|
||||||
|
object_id,
|
||||||
|
collab_type,
|
||||||
|
encoded_collab_v1,
|
||||||
|
override_if_exist: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn override_collab_if_exist(mut self, override_if_exist: bool) -> Self {
|
||||||
|
self.override_if_exist = override_if_exist;
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Validate, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Validate, Serialize, Deserialize)]
|
||||||
|
|
@ -50,43 +81,6 @@ pub struct BatchCreateCollabParams {
|
||||||
pub params_list: Vec<CollabParams>,
|
pub params_list: Vec<CollabParams>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateCollabParams {
|
|
||||||
pub fn new<T: ToString>(
|
|
||||||
object_id: T,
|
|
||||||
collab_type: CollabType,
|
|
||||||
encoded_collab_v1: Vec<u8>,
|
|
||||||
workspace_id: String,
|
|
||||||
) -> Self {
|
|
||||||
let object_id = object_id.to_string();
|
|
||||||
let params = CollabParams {
|
|
||||||
object_id,
|
|
||||||
collab_type,
|
|
||||||
encoded_collab_v1,
|
|
||||||
};
|
|
||||||
Self {
|
|
||||||
inner: params,
|
|
||||||
workspace_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn from_raw_data(
|
|
||||||
object_id: String,
|
|
||||||
collab_type: CollabType,
|
|
||||||
encoded_collab_v1: Vec<u8>,
|
|
||||||
workspace_id: &str,
|
|
||||||
) -> Self {
|
|
||||||
let workspace_id = workspace_id.to_string();
|
|
||||||
let params = CollabParams {
|
|
||||||
object_id,
|
|
||||||
collab_type,
|
|
||||||
encoded_collab_v1,
|
|
||||||
};
|
|
||||||
Self {
|
|
||||||
inner: params,
|
|
||||||
workspace_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Validate, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Validate, Serialize, Deserialize)]
|
||||||
pub struct DeleteCollabParams {
|
pub struct DeleteCollabParams {
|
||||||
#[validate(custom = "validate_not_empty_str")]
|
#[validate(custom = "validate_not_empty_str")]
|
||||||
|
|
|
||||||
|
|
@ -162,8 +162,11 @@ pub const MSG_SYNC_UPDATE: u8 = 2;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum SyncMessage {
|
pub enum SyncMessage {
|
||||||
|
/// Sync step 1 message contains the [StateVector] from the remote side
|
||||||
SyncStep1(StateVector),
|
SyncStep1(StateVector),
|
||||||
|
/// Sync step 2 message contains the encoded [yrs::Update] from the remote side
|
||||||
SyncStep2(Vec<u8>),
|
SyncStep2(Vec<u8>),
|
||||||
|
/// Update message contains the encoded [yrs::Update] from the remote side
|
||||||
Update(Vec<u8>),
|
Update(Vec<u8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ use collab::preclude::{CollabPlugin, Doc, TransactionMut};
|
||||||
use collab_entity::CollabType;
|
use collab_entity::CollabType;
|
||||||
use database::collab::CollabStorage;
|
use database::collab::CollabStorage;
|
||||||
use database_entity::dto::{
|
use database_entity::dto::{
|
||||||
AFAccessLevel, CreateCollabParams, InsertSnapshotParams, QueryCollabParams,
|
AFAccessLevel, CollabParams, CreateCollabParams, InsertSnapshotParams, QueryCollabParams,
|
||||||
};
|
};
|
||||||
use std::sync::atomic::{AtomicBool, AtomicI64, AtomicU32, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicI64, AtomicU32, Ordering};
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
|
@ -84,11 +84,9 @@ where
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let params = CreateCollabParams::from_raw_data(
|
let params = CreateCollabParams::new(
|
||||||
object_id.to_string(),
|
|
||||||
self.collab_type.clone(),
|
|
||||||
encoded_collab_v1,
|
|
||||||
&self.workspace_id,
|
&self.workspace_id,
|
||||||
|
CollabParams::new(object_id, self.collab_type.clone(), encoded_collab_v1),
|
||||||
);
|
);
|
||||||
|
|
||||||
self
|
self
|
||||||
|
|
@ -266,11 +264,9 @@ where
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let params = CreateCollabParams::from_raw_data(
|
let params = CreateCollabParams::new(
|
||||||
object_id.to_string(),
|
|
||||||
self.collab_type.clone(),
|
|
||||||
encoded_collab_v1,
|
|
||||||
&self.workspace_id,
|
&self.workspace_id,
|
||||||
|
CollabParams::new(object_id, self.collab_type.clone(), encoded_collab_v1),
|
||||||
);
|
);
|
||||||
|
|
||||||
let storage = self.storage.clone();
|
let storage = self.storage.clone();
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,14 @@ impl CollabSyncProtocol for ServerSyncProtocol {
|
||||||
sv: StateVector,
|
sv: StateVector,
|
||||||
) -> Result<Option<Vec<u8>>, Error> {
|
) -> Result<Option<Vec<u8>>, Error> {
|
||||||
let txn = awareness.doc().transact();
|
let txn = awareness.doc().transact();
|
||||||
let step2_update = txn.encode_state_as_update_v1(&sv);
|
let client_step2_update = txn.encode_state_as_update_v1(&sv);
|
||||||
let step1_update = txn.state_vector();
|
|
||||||
|
// Retrieve the latest document state from the client after they return online from offline editing.
|
||||||
|
let server_step1_update = txn.state_vector();
|
||||||
|
|
||||||
let mut encoder = EncoderV1::new();
|
let mut encoder = EncoderV1::new();
|
||||||
Message::Sync(SyncMessage::SyncStep2(step2_update)).encode(&mut encoder);
|
Message::Sync(SyncMessage::SyncStep2(client_step2_update)).encode(&mut encoder);
|
||||||
Message::Sync(SyncMessage::SyncStep1(step1_update)).encode(&mut encoder);
|
Message::Sync(SyncMessage::SyncStep1(server_step1_update)).encode(&mut encoder);
|
||||||
Ok(Some(encoder.to_vec()))
|
Ok(Some(encoder.to_vec()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,9 @@ where
|
||||||
C: CollabAccessControl,
|
C: CollabAccessControl,
|
||||||
{
|
{
|
||||||
for params in params_list {
|
for params in params_list {
|
||||||
if database::collab::collab_exists(pg_pool, ¶ms.object_id).await? {
|
if !params.override_if_exist
|
||||||
|
&& database::collab::collab_exists(pg_pool, ¶ms.object_id).await?
|
||||||
|
{
|
||||||
// When calling this function, the caller should have already checked if the collab exists.
|
// When calling this function, the caller should have already checked if the collab exists.
|
||||||
return Err(AppError::RecordAlreadyExists(format!(
|
return Err(AppError::RecordAlreadyExists(format!(
|
||||||
"Collab with object_id {} already exists",
|
"Collab with object_id {} already exists",
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,7 @@ where
|
||||||
object_id,
|
object_id,
|
||||||
encoded_collab_v1,
|
encoded_collab_v1,
|
||||||
collab_type: template.object_type,
|
collab_type: template.object_type,
|
||||||
|
override_if_exist: false,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::util::test_client::TestClient;
|
use crate::util::test_client::TestClient;
|
||||||
use app_error::ErrorCode;
|
use app_error::ErrorCode;
|
||||||
|
use assert_json_diff::assert_json_include;
|
||||||
use collab_entity::CollabType;
|
use collab_entity::CollabType;
|
||||||
use database_entity::dto::{CollabParams, CreateCollabParams, QueryCollab};
|
use database_entity::dto::{CollabParams, CreateCollabParams, QueryCollab};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
@ -30,6 +31,7 @@ async fn batch_insert_collab_success_test() {
|
||||||
object_id: Uuid::new_v4().to_string(),
|
object_id: Uuid::new_v4().to_string(),
|
||||||
encoded_collab_v1: vec![0, 200],
|
encoded_collab_v1: vec![0, 200],
|
||||||
collab_type: CollabType::Document,
|
collab_type: CollabType::Document,
|
||||||
|
override_if_exist: false,
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
|
@ -68,7 +70,7 @@ async fn create_collab_params_compatibility_serde_test() {
|
||||||
serde_json::from_value::<CreateCollabParams>(old_version_value.clone()).unwrap();
|
serde_json::from_value::<CreateCollabParams>(old_version_value.clone()).unwrap();
|
||||||
|
|
||||||
let new_version_value = serde_json::to_value(new_version_create_params.clone()).unwrap();
|
let new_version_value = serde_json::to_value(new_version_create_params.clone()).unwrap();
|
||||||
assert_eq!(old_version_value, new_version_value);
|
assert_json_include!(actual: new_version_value.clone(), expected: old_version_value.clone());
|
||||||
|
|
||||||
assert_eq!(new_version_create_params.object_id, "object_id".to_string());
|
assert_eq!(new_version_create_params.object_id, "object_id".to_string());
|
||||||
assert_eq!(new_version_create_params.encoded_collab_v1, vec![0, 200]);
|
assert_eq!(new_version_create_params.encoded_collab_v1, vec![0, 200]);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use crate::collab::workspace_id_from_client;
|
||||||
use crate::user::utils::generate_unique_registered_user_client;
|
use crate::user::utils::generate_unique_registered_user_client;
|
||||||
use collab_entity::CollabType;
|
use collab_entity::CollabType;
|
||||||
use database_entity::dto::{
|
use database_entity::dto::{
|
||||||
AFAccessLevel, CollabMemberIdentify, CreateCollabParams, InsertCollabMemberParams,
|
AFAccessLevel, CollabMemberIdentify, CollabParams, CreateCollabParams, InsertCollabMemberParams,
|
||||||
QueryCollabMembers, UpdateCollabMemberParams,
|
QueryCollabMembers, UpdateCollabMemberParams,
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
@ -16,10 +16,8 @@ async fn collab_owner_permission_test() {
|
||||||
let uid = c.get_profile().await.unwrap().uid;
|
let uid = c.get_profile().await.unwrap().uid;
|
||||||
|
|
||||||
c.create_collab(CreateCollabParams::new(
|
c.create_collab(CreateCollabParams::new(
|
||||||
&object_id,
|
|
||||||
CollabType::Document,
|
|
||||||
raw_data.clone(),
|
|
||||||
workspace_id.clone(),
|
workspace_id.clone(),
|
||||||
|
CollabParams::new(&object_id, CollabType::Document, raw_data.clone()),
|
||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -45,10 +43,8 @@ async fn update_collab_member_permission_test() {
|
||||||
let uid = c.get_profile().await.unwrap().uid;
|
let uid = c.get_profile().await.unwrap().uid;
|
||||||
|
|
||||||
c.create_collab(CreateCollabParams::new(
|
c.create_collab(CreateCollabParams::new(
|
||||||
&object_id,
|
|
||||||
CollabType::Document,
|
|
||||||
raw_data.clone(),
|
|
||||||
workspace_id.clone(),
|
workspace_id.clone(),
|
||||||
|
CollabParams::new(&object_id, CollabType::Document, raw_data.clone()),
|
||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -81,10 +77,8 @@ async fn add_collab_member_test() {
|
||||||
let object_id = Uuid::new_v4().to_string();
|
let object_id = Uuid::new_v4().to_string();
|
||||||
c_1
|
c_1
|
||||||
.create_collab(CreateCollabParams::new(
|
.create_collab(CreateCollabParams::new(
|
||||||
&object_id,
|
|
||||||
CollabType::Document,
|
|
||||||
vec![0; 10],
|
|
||||||
workspace_id.clone(),
|
workspace_id.clone(),
|
||||||
|
CollabParams::new(&object_id, CollabType::Document, vec![0; 10]),
|
||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -126,10 +120,8 @@ async fn add_collab_member_then_remove_test() {
|
||||||
let object_id = Uuid::new_v4().to_string();
|
let object_id = Uuid::new_v4().to_string();
|
||||||
c_1
|
c_1
|
||||||
.create_collab(CreateCollabParams::new(
|
.create_collab(CreateCollabParams::new(
|
||||||
&object_id,
|
|
||||||
CollabType::Document,
|
|
||||||
vec![0; 10],
|
|
||||||
workspace_id.clone(),
|
workspace_id.clone(),
|
||||||
|
CollabParams::new(&object_id, CollabType::Document, vec![0; 10]),
|
||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@ use std::collections::HashMap;
|
||||||
use app_error::ErrorCode;
|
use app_error::ErrorCode;
|
||||||
use collab_entity::CollabType;
|
use collab_entity::CollabType;
|
||||||
use database_entity::dto::{
|
use database_entity::dto::{
|
||||||
CreateCollabParams, DeleteCollabParams, QueryCollab, QueryCollabParams, QueryCollabResult,
|
CollabParams, CreateCollabParams, DeleteCollabParams, QueryCollab, QueryCollabParams,
|
||||||
|
QueryCollabResult,
|
||||||
};
|
};
|
||||||
use sqlx::types::Uuid;
|
use sqlx::types::Uuid;
|
||||||
|
|
||||||
|
|
@ -21,10 +22,8 @@ async fn success_insert_collab_test() {
|
||||||
let workspace_id = workspace_id_from_client(&c).await;
|
let workspace_id = workspace_id_from_client(&c).await;
|
||||||
let object_id = Uuid::new_v4().to_string();
|
let object_id = Uuid::new_v4().to_string();
|
||||||
c.create_collab(CreateCollabParams::new(
|
c.create_collab(CreateCollabParams::new(
|
||||||
&object_id,
|
|
||||||
CollabType::Document,
|
|
||||||
encoded_collab_v1,
|
|
||||||
workspace_id.clone(),
|
workspace_id.clone(),
|
||||||
|
CollabParams::new(&object_id, CollabType::Document, encoded_collab_v1),
|
||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -75,10 +74,8 @@ async fn success_batch_get_collab_test() {
|
||||||
);
|
);
|
||||||
|
|
||||||
c.create_collab(CreateCollabParams::new(
|
c.create_collab(CreateCollabParams::new(
|
||||||
&object_id,
|
|
||||||
collab_type,
|
|
||||||
raw_data.clone(),
|
|
||||||
workspace_id.clone(),
|
workspace_id.clone(),
|
||||||
|
CollabParams::new(&object_id, collab_type, raw_data.clone()),
|
||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -130,10 +127,8 @@ async fn success_part_batch_get_collab_test() {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
c.create_collab(CreateCollabParams::new(
|
c.create_collab(CreateCollabParams::new(
|
||||||
&object_id,
|
|
||||||
collab_type,
|
|
||||||
raw_data.clone(),
|
|
||||||
workspace_id.clone(),
|
workspace_id.clone(),
|
||||||
|
CollabParams::new(&object_id, collab_type, raw_data.clone()),
|
||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -153,10 +148,8 @@ async fn success_delete_collab_test() {
|
||||||
let workspace_id = workspace_id_from_client(&c).await;
|
let workspace_id = workspace_id_from_client(&c).await;
|
||||||
let object_id = Uuid::new_v4().to_string();
|
let object_id = Uuid::new_v4().to_string();
|
||||||
c.create_collab(CreateCollabParams::new(
|
c.create_collab(CreateCollabParams::new(
|
||||||
object_id.clone(),
|
|
||||||
CollabType::Document,
|
|
||||||
raw_data.clone(),
|
|
||||||
workspace_id.clone(),
|
workspace_id.clone(),
|
||||||
|
CollabParams::new(&object_id, CollabType::Document, raw_data.clone()),
|
||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -186,10 +179,8 @@ async fn fail_insert_collab_with_empty_payload_test() {
|
||||||
let workspace_id = workspace_id_from_client(&c).await;
|
let workspace_id = workspace_id_from_client(&c).await;
|
||||||
let error = c
|
let error = c
|
||||||
.create_collab(CreateCollabParams::new(
|
.create_collab(CreateCollabParams::new(
|
||||||
Uuid::new_v4().to_string(),
|
|
||||||
CollabType::Document,
|
|
||||||
vec![],
|
|
||||||
workspace_id,
|
workspace_id,
|
||||||
|
CollabParams::new(Uuid::new_v4(), CollabType::Document, vec![]),
|
||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
|
|
@ -204,10 +195,8 @@ async fn fail_insert_collab_with_invalid_workspace_id_test() {
|
||||||
let raw_data = "hello world".to_string().as_bytes().to_vec();
|
let raw_data = "hello world".to_string().as_bytes().to_vec();
|
||||||
let error = c
|
let error = c
|
||||||
.create_collab(CreateCollabParams::new(
|
.create_collab(CreateCollabParams::new(
|
||||||
Uuid::new_v4().to_string(),
|
|
||||||
CollabType::Document,
|
|
||||||
raw_data.clone(),
|
|
||||||
workspace_id,
|
workspace_id,
|
||||||
|
CollabParams::new(Uuid::new_v4(), CollabType::Document, raw_data.clone()),
|
||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
|
|
|
||||||
|
|
@ -418,10 +418,8 @@ impl TestClient {
|
||||||
self
|
self
|
||||||
.api_client
|
.api_client
|
||||||
.create_collab(CreateCollabParams::new(
|
.create_collab(CreateCollabParams::new(
|
||||||
&object_id,
|
|
||||||
collab_type.clone(),
|
|
||||||
encoded_collab_v1,
|
|
||||||
workspace_id.to_string(),
|
workspace_id.to_string(),
|
||||||
|
CollabParams::new(&object_id, collab_type.clone(), encoded_collab_v1),
|
||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue