AppFlowy-Cloud/libs/collab-rt/src/data_validation.rs

53 lines
1.5 KiB
Rust

use crate::error::RealtimeError;
use async_trait::async_trait;
use collab::core::collab::DataSource;
use collab::core::collab_plugin::EncodedCollab;
use collab::core::origin::CollabOrigin;
use collab::preclude::Collab;
use collab_entity::CollabType;
use database_entity::dto::CollabParams;
use tracing::instrument;
#[async_trait]
pub trait CollabValidator {
async fn check_encode_collab(&self) -> Result<(), RealtimeError>;
}
#[async_trait]
impl CollabValidator for CollabParams {
async fn check_encode_collab(&self) -> Result<(), RealtimeError> {
validate_encode_collab(&self.object_id, &self.encoded_collab_v1, &self.collab_type).await
}
}
#[instrument(level = "trace", skip(data), fields(len = %data.len()))]
pub async fn validate_encode_collab(
object_id: &str,
data: &[u8],
collab_type: &CollabType,
) -> Result<(), RealtimeError> {
let collab_type = collab_type.clone();
let object_id = object_id.to_string();
let data = data.to_vec();
tokio::task::spawn_blocking(move || {
let encoded_collab =
EncodedCollab::decode_from_bytes(&data).map_err(|err| RealtimeError::Internal(err.into()))?;
let collab = Collab::new_with_source(
CollabOrigin::Empty,
&object_id,
DataSource::DocStateV1(encoded_collab.doc_state.to_vec()),
vec![],
false,
)
.map_err(|err| RealtimeError::Internal(err.into()))?;
collab_type
.validate(&collab)
.map_err(|err| RealtimeError::NoRequiredCollabData(err.to_string()))?;
Ok::<(), RealtimeError>(())
})
.await?
}