use std::collections::HashSet;
use serde::{Deserialize, Serialize};
use signer_core::{SignerSigned, SignerUserPublic};
use crate::{
model::viewobject::{Envelope, MessageVO, UserVO},
reqwest_auth::ReqwestAuth as _,
};
use super::SignerDaemon;
impl SignerDaemon {
pub async fn remote_pull_message(&self, addr: &str) -> anyhow::Result<()> {
let user = self.user.lock().await.clone();
let client = reqwest::Client::new();
let r = client
.get(&format!("{}/envelopes", addr))
.with_signer_auth(&user)
.send()
.await?
.error_for_status()?;
let json = r.json::<GetEnvelopesResponse>().await?;
let mut success_set: HashSet<i32> = HashSet::new();
for e in json.data {
let message = match e.envelope.open(&user) {
Ok(val) => val.message,
Err(_) => continue,
};
self.put_message(message).await?;
success_set.insert(e.id);
}
client
.patch(&format!("{}/envelopes/check", addr))
.with_signer_auth(&user)
.json(&serde_json::json!({
"ids": success_set.into_iter().collect::<Vec<i32>>()
}))
.send()
.await?
.error_for_status()?;
Ok(())
}
pub async fn remote_push_message(
&self,
destinations: Vec<String>,
data: Vec<MessageVO>,
) -> anyhow::Result<()> {
let mut envelopes = Vec::new();
for i in data {
let envelope = Envelope::create(&self, &i, destinations.clone()).await?;
envelopes.push(envelope);
}
let user = self.user.lock().await.clone();
for e in envelopes {
e.send(&user).await?;
}
Ok(())
}
pub async fn remote_pull_user(
&self,
addr: &str,
user_key: &str,
) -> anyhow::Result<()> {
let user = self.user.lock().await.clone();
let client = reqwest::Client::new();
let r = client
.get(&format!("{}/users/{}", addr, user_key))
.with_signer_auth(&user)
.send()
.await?
.error_for_status()?;
let json = r.json::<SignerSigned<SignerUserPublic>>().await?;
let up = json.verify_to_value()?;
let user_vo = UserVO {
pub_key: up.pub_key.clone(),
user_public: serde_json::to_string(&up)?,
signed_user_public: serde_json::to_string(&json)?,
};
self.put_user(user_vo).await?;
self.wait_apply().await?;
Ok(())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct GetEnvelopesResponse {
data: Vec<EnvelopeBox>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct EnvelopeBox {
id: i32,
envelope: Envelope,
}
#[cfg(test)]
mod tests {
use signer_core::SignerUser;
use crate::SignerDaemon;
#[tokio::test]
async fn test_pull_user() -> anyhow::Result<()> {
let u = SignerUser::generete("alice")?;
let peer = uuid::Uuid::new_v4().to_string();
let daemon = SignerDaemon::from_memory(&u, &peer).await?;
daemon
.ping_server("http://localhost:8080/api/signer")
.await?;
let target_key = "flNGOqa6fbJ67M8EKunes6P88zB09gcr6nRFFs-lJDs=";
daemon
.remote_pull_user("http://localhost:8080/api/signer", target_key)
.await?;
let target = daemon.get_user(target_key).await?;
assert!(target.is_some());
Ok(())
}
}