use serde::{Deserialize, Serialize};
use signer_core::{SignerCrypted, SignerKeys, SignerUser};
use signer_crdt::{view::CrdtEventVO, errors::ViewError};
use crate::{
error::{RemoteError, RemoteResult},
remote::{HttpClient, HttpClientConfig},
};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrdtCryptedEventVO {
pub clock: i32,
pub peer: String,
pub data: SignerCrypted<CrdtEventVO>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PostCrdtEventsRequest {
pub data: Vec<CrdtCryptedEventVO>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetCrdtEventsResponse {
pub data: Vec<CrdtCryptedEventVO>,
}
impl CrdtCryptedEventVO {
pub fn encrypt(
keys: &SignerKeys,
data: &CrdtEventVO,
) -> Result<Self, ViewError> {
let data = CrdtEventVO {
revert: None,
..data.clone()
};
Ok(Self {
clock: data.clock,
peer: data.peer.clone(),
data: SignerCrypted::create(keys, &keys.pub_key, data)?,
})
}
pub fn decrypt(
&self,
keys: &SignerKeys,
) -> Result<CrdtEventVO, ViewError> {
let data = self.data.decrypt(keys)?;
Ok(CrdtEventVO {
revert: None,
..data
})
}
pub async fn push(
events: Vec<CrdtCryptedEventVO>,
addr: &str,
keys: &SignerKeys,
user: &SignerUser,
) -> RemoteResult<()> {
if events.is_empty() {
return Ok(());
}
let req = PostCrdtEventsRequest { data: events };
let config = HttpClientConfig::new(keys.clone(), user.clone(), addr.to_string());
let client = HttpClient::new(config);
let _: serde_json::Value = client
.post("/api/crdt-events", &req)
.await
.map_err(|e| RemoteError::Internal(format!("推送 CRDT 事件失败: {}", e)))?;
Ok(())
}
pub async fn pull(
addr: &str,
keys: &SignerKeys,
user: &SignerUser,
frontiers: &str, ) -> RemoteResult<Vec<CrdtCryptedEventVO>> {
let config = HttpClientConfig::new(keys.clone(), user.clone(), addr.to_string());
let client = HttpClient::new(config);
#[derive(serde::Serialize)]
struct QueryParams {
frontiers: Option<String>,
}
let query = QueryParams {
frontiers: Some(frontiers.to_string()),
};
let r: GetCrdtEventsResponse = client
.get_with_query("/api/crdt-events", &query)
.await
.map_err(|e| RemoteError::Internal(format!("拉取 CRDT 事件失败: {}", e)))?;
Ok(r.data)
}
}