diff --git a/extensions/warp-ipfs/src/shuttle/identity.rs b/extensions/warp-ipfs/src/shuttle/identity.rs index 75dc619e8..b8e4477b4 100644 --- a/extensions/warp-ipfs/src/shuttle/identity.rs +++ b/extensions/warp-ipfs/src/shuttle/identity.rs @@ -1,9 +1,5 @@ -use crate::store::DidExt; -use chrono::{DateTime, Utc}; use ipld_core::cid::Cid; -use rust_ipfs::Keypair; use serde::{Deserialize, Serialize}; -use warp::crypto::DID; use crate::store::document::identity::IdentityDocument; @@ -17,75 +13,3 @@ pub struct IdentityDag { #[serde(skip_serializing_if = "Option::is_none")] pub mailbox: Option, } - -#[derive(Deserialize, Serialize, Debug, Clone, Copy, PartialEq, Hash, Eq)] -#[serde(rename_all = "lowercase")] -pub enum RequestEvent { - /// Event indicating a friend request - Request, - /// Event accepting the request - Accept, - /// Remove identity as a friend - Remove, - /// Reject friend request, if any - Reject, - /// Retract a sent friend request - Retract, - /// Block user - Block, - /// Unblock user - Unblock, -} - -#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)] -pub struct RequestPayload { - pub sender: DID, - pub event: RequestEvent, - pub created: DateTime, - #[serde(skip_serializing_if = "Vec::is_empty")] - pub original_signature: Vec, - #[serde(skip_serializing_if = "Vec::is_empty")] - pub signature: Vec, -} - -impl std::hash::Hash for RequestPayload { - fn hash(&self, state: &mut H) { - self.sender.hash(state); - } -} - -impl PartialOrd for RequestPayload { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for RequestPayload { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.created.cmp(&other.created) - } -} - -impl RequestPayload { - pub fn sign(mut self, keypair: &Keypair) -> Result> { - if !self.signature.is_empty() { - return Err(Box::new(warp::error::Error::InvalidSignature)); - } - - let bytes = serde_json::to_vec(&self)?; - let signature = keypair.sign(&bytes)?; - self.signature = signature; - Ok(self) - } - - pub fn verify(&self) -> Result<(), Box> { - let pk = self.sender.to_public_key()?; - let mut doc = self.clone(); - let signature = std::mem::take(&mut doc.signature); - let bytes = serde_json::to_vec(&doc)?; - if !pk.verify(&bytes, &signature) { - return Err(Box::new(warp::error::Error::InvalidSignature)); - } - Ok(()) - } -} diff --git a/extensions/warp-ipfs/src/shuttle/identity/protocol.rs b/extensions/warp-ipfs/src/shuttle/identity/protocol.rs index 373594fc4..c52c4aec6 100644 --- a/extensions/warp-ipfs/src/shuttle/identity/protocol.rs +++ b/extensions/warp-ipfs/src/shuttle/identity/protocol.rs @@ -3,13 +3,12 @@ use rust_ipfs::Keypair; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use warp::{crypto::DID, multipass::identity::ShortId}; +use crate::store::identity::RequestResponsePayload; use crate::store::{ document::identity::IdentityDocument, payload::{PayloadBuilder, PayloadMessage}, }; -use super::RequestPayload; - pub fn payload_message_construct( keypair: &Keypair, cosigner: Option<&Keypair>, @@ -98,15 +97,20 @@ impl From for Response { #[serde(rename_all = "snake_case")] pub enum Mailbox { FetchAll, - FetchFrom { did: DID }, - Send { did: DID, request: RequestPayload }, + FetchFrom { + did: DID, + }, + Send { + did: DID, + request: RequestResponsePayload, + }, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum MailboxResponse { Receive { - list: Vec, + list: Vec, remaining: usize, }, Removed, diff --git a/extensions/warp-ipfs/src/shuttle/store/identity.rs b/extensions/warp-ipfs/src/shuttle/store/identity.rs index 8843f1ad2..e1f2b900d 100644 --- a/extensions/warp-ipfs/src/shuttle/store/identity.rs +++ b/extensions/warp-ipfs/src/shuttle/store/identity.rs @@ -9,16 +9,16 @@ use rust_ipfs::{Ipfs, IpfsPath}; use tokio::sync::RwLock; use warp::{crypto::DID, error::Error}; +use super::root::RootStorage; +use crate::store::identity::RequestResponsePayload; use crate::{ - shuttle::identity::{protocol::Lookup, RequestPayload}, + shuttle::identity::protocol::Lookup, store::{ document::{identity::IdentityDocument, RootDocument}, DidExt, }, }; -use super::root::RootStorage; - #[derive(Debug, Clone)] pub struct IdentityStorage { inner: Arc>, @@ -56,12 +56,19 @@ impl IdentityStorage { inner.contains(did).await } - pub async fn fetch_mailbox(&self, did: DID) -> Result<(Vec, usize), Error> { + pub async fn fetch_mailbox( + &self, + did: DID, + ) -> Result<(Vec, usize), Error> { let inner = &mut *self.inner.write().await; inner.fetch_requests(did).await } - pub async fn deliver_request(&self, to: &DID, request: &RequestPayload) -> Result<(), Error> { + pub async fn deliver_request( + &self, + to: &DID, + request: &RequestResponsePayload, + ) -> Result<(), Error> { let inner = &mut *self.inner.write().await; inner.deliver_request(to, request).await } @@ -374,7 +381,10 @@ impl IdentityStorageInner { Ok(list) } - async fn fetch_requests(&mut self, did: DID) -> Result<(Vec, usize), Error> { + async fn fetch_requests( + &mut self, + did: DID, + ) -> Result<(Vec, usize), Error> { let key_str = did.to_string(); let mut list: BTreeMap = match self.mailbox { Some(cid) => self @@ -392,7 +402,7 @@ impl IdentityStorageInner { .ipfs .get_dag(*cid) .local() - .deserialized::>() + .deserialized::>() .await .unwrap_or_default(), None => return Ok((Vec::new(), 0)), @@ -432,7 +442,11 @@ impl IdentityStorageInner { Ok((requests, remaining)) } - async fn deliver_request(&mut self, to: &DID, request: &RequestPayload) -> Result<(), Error> { + async fn deliver_request( + &mut self, + to: &DID, + request: &RequestResponsePayload, + ) -> Result<(), Error> { if !self.contains(to).await { return Err(Error::IdentityDoesntExist); } @@ -455,7 +469,7 @@ impl IdentityStorageInner { .ipfs .get_dag(*cid) .local() - .deserialized::>() + .deserialized::>() .await .unwrap_or_default(), None => Vec::new(), diff --git a/extensions/warp-ipfs/src/store/identity.rs b/extensions/warp-ipfs/src/store/identity.rs index 557fc9e14..08f40b68f 100644 --- a/extensions/warp-ipfs/src/store/identity.rs +++ b/extensions/warp-ipfs/src/store/identity.rs @@ -19,7 +19,6 @@ use tokio::sync::RwLock; use tracing::Span; use web_time::Instant; -use crate::shuttle::identity::{RequestEvent, RequestPayload}; use warp::multipass::identity::{FriendRequest, Identifier, ShortId}; use warp::multipass::GetIdentity; use warp::{ @@ -188,56 +187,15 @@ pub struct RequestResponsePayload { pub signature: Option>, } -impl TryFrom for RequestPayload { - type Error = Error; - fn try_from(req: RequestResponsePayload) -> Result { - req.verify()?; - let event = match req.event { - Event::Request => RequestEvent::Request, - Event::Accept => RequestEvent::Accept, - Event::Remove => RequestEvent::Remove, - Event::Reject => RequestEvent::Reject, - Event::Retract => RequestEvent::Retract, - Event::Block => RequestEvent::Block, - Event::Unblock => RequestEvent::Unblock, - Event::Response => return Err(Error::OtherWithContext("Invalid event type".into())), - }; - - let payload = RequestPayload { - sender: req.sender, - event, - created: req.created.ok_or(Error::InvalidConversion)?, - original_signature: req.signature.ok_or(Error::InvalidSignature)?, - signature: vec![], - }; - - Ok(payload) +impl PartialOrd for RequestResponsePayload { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) } } -impl TryFrom for RequestResponsePayload { - type Error = Box; - fn try_from(req: RequestPayload) -> Result { - req.verify()?; - let event = match req.event { - RequestEvent::Request => Event::Request, - RequestEvent::Accept => Event::Accept, - RequestEvent::Remove => Event::Remove, - RequestEvent::Reject => Event::Reject, - RequestEvent::Retract => Event::Retract, - RequestEvent::Block => Event::Block, - RequestEvent::Unblock => Event::Unblock, - }; - - let payload = RequestResponsePayload { - version: RequestResponsePayloadVersion::V1, - sender: req.sender, - event, - created: Some(req.created), - signature: Some(req.original_signature), - }; - - Ok(payload) +impl Ord for RequestResponsePayload { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.created.cmp(&other.created) } } @@ -2083,8 +2041,6 @@ impl IdentityStore { request: RequestResponsePayload, ) -> Result<(), Error> { if let DiscoveryConfig::Shuttle { addresses } = self.discovery.discovery_config() { - let request: RequestPayload = request.try_into()?; - let request = request .sign(self.root_document().keypair()) .map_err(|e| anyhow::anyhow!("{e}"))?;