2020-03-18 04:35:20 +00:00
|
|
|
use crate::{apub::AcceptedActors, error::MyError, state::ActorCache};
|
2020-03-17 17:15:16 +00:00
|
|
|
use activitystreams::primitives::XsdAnyUri;
|
2020-03-18 04:35:20 +00:00
|
|
|
use actix::Arbiter;
|
|
|
|
use actix_web::client::Client;
|
|
|
|
use futures::stream::StreamExt;
|
|
|
|
use http_signature_normalization_actix::prelude::*;
|
2020-03-17 17:15:16 +00:00
|
|
|
use log::error;
|
2020-03-18 04:35:20 +00:00
|
|
|
use rsa::{hash::Hashes, padding::PaddingScheme, RSAPrivateKey};
|
|
|
|
use sha2::{Digest, Sha256};
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct Requests {
|
|
|
|
client: Client,
|
|
|
|
key_id: String,
|
|
|
|
private_key: RSAPrivateKey,
|
|
|
|
actor_cache: ActorCache,
|
|
|
|
config: Config,
|
2020-03-19 19:05:16 +00:00
|
|
|
user_agent: String,
|
2020-03-18 04:35:20 +00:00
|
|
|
}
|
2020-03-17 17:15:16 +00:00
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
impl Requests {
|
2020-03-19 19:05:16 +00:00
|
|
|
pub fn new(
|
|
|
|
key_id: String,
|
|
|
|
private_key: RSAPrivateKey,
|
|
|
|
actor_cache: ActorCache,
|
|
|
|
user_agent: String,
|
|
|
|
) -> Self {
|
2020-03-18 04:35:20 +00:00
|
|
|
Requests {
|
|
|
|
client: Client::default(),
|
|
|
|
key_id,
|
|
|
|
private_key,
|
|
|
|
actor_cache,
|
|
|
|
config: Config::default().dont_use_created_field(),
|
2020-03-19 19:05:16 +00:00
|
|
|
user_agent,
|
2020-03-18 04:35:20 +00:00
|
|
|
}
|
2020-03-17 17:15:16 +00:00
|
|
|
}
|
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
pub async fn fetch_actor(&self, actor_id: &XsdAnyUri) -> Result<AcceptedActors, MyError> {
|
|
|
|
if let Some(actor) = self.get_actor(actor_id).await {
|
|
|
|
return Ok(actor);
|
|
|
|
}
|
2020-03-17 21:36:53 +00:00
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
let actor: AcceptedActors = self.fetch(actor_id.as_str()).await?;
|
|
|
|
|
|
|
|
self.cache_actor(actor_id.to_owned(), actor.clone()).await;
|
|
|
|
|
|
|
|
Ok(actor)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn fetch<T>(&self, url: &str) -> Result<T, MyError>
|
|
|
|
where
|
|
|
|
T: serde::de::DeserializeOwned,
|
|
|
|
{
|
|
|
|
let mut res = self
|
|
|
|
.client
|
|
|
|
.get(url)
|
|
|
|
.header("Accept", "application/activity+json")
|
2020-03-19 19:05:16 +00:00
|
|
|
.header("User-Agent", self.user_agent.as_str())
|
2020-03-18 04:35:20 +00:00
|
|
|
.signature(&self.config, &self.key_id, |signing_string| {
|
|
|
|
self.sign(signing_string)
|
|
|
|
})?
|
|
|
|
.send()
|
|
|
|
.await
|
|
|
|
.map_err(|e| {
|
|
|
|
error!("Couldn't send request to {}, {}", url, e);
|
|
|
|
MyError::SendRequest
|
|
|
|
})?;
|
|
|
|
|
|
|
|
if !res.status().is_success() {
|
|
|
|
error!("Invalid status code for fetch, {}", res.status());
|
|
|
|
if let Ok(bytes) = res.body().await {
|
|
|
|
if let Ok(s) = String::from_utf8(bytes.as_ref().to_vec()) {
|
|
|
|
error!("Response, {}", s);
|
|
|
|
}
|
2020-03-17 21:53:31 +00:00
|
|
|
}
|
2020-03-18 04:35:20 +00:00
|
|
|
|
|
|
|
return Err(MyError::Status);
|
2020-03-17 21:53:31 +00:00
|
|
|
}
|
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
res.json().await.map_err(|e| {
|
|
|
|
error!("Coudn't fetch json from {}, {}", url, e);
|
|
|
|
MyError::ReceiveResponse
|
|
|
|
})
|
2020-03-17 21:53:31 +00:00
|
|
|
}
|
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
pub fn deliver_many<T>(&self, inboxes: Vec<XsdAnyUri>, item: T)
|
|
|
|
where
|
|
|
|
T: serde::ser::Serialize + 'static,
|
|
|
|
{
|
|
|
|
let this = self.clone();
|
2020-03-17 21:53:31 +00:00
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
Arbiter::spawn(async move {
|
|
|
|
let mut unordered = futures::stream::FuturesUnordered::new();
|
2020-03-17 17:15:16 +00:00
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
for inbox in inboxes {
|
|
|
|
unordered.push(this.deliver(inbox, &item));
|
|
|
|
}
|
2020-03-17 17:15:16 +00:00
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
while let Some(_) = unordered.next().await {}
|
|
|
|
});
|
|
|
|
}
|
2020-03-17 17:15:16 +00:00
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
pub async fn deliver<T>(&self, inbox: XsdAnyUri, item: &T) -> Result<(), MyError>
|
|
|
|
where
|
|
|
|
T: serde::ser::Serialize,
|
|
|
|
{
|
|
|
|
let mut digest = Sha256::new();
|
|
|
|
|
|
|
|
let item_string = serde_json::to_string(item)?;
|
|
|
|
|
|
|
|
let mut res = self
|
|
|
|
.client
|
|
|
|
.post(inbox.as_str())
|
|
|
|
.header("Accept", "application/activity+json")
|
|
|
|
.header("Content-Type", "application/activity+json")
|
2020-03-19 19:05:16 +00:00
|
|
|
.header("User-Agent", self.user_agent.as_str())
|
2020-03-18 04:35:20 +00:00
|
|
|
.signature_with_digest(
|
|
|
|
&self.config,
|
|
|
|
&self.key_id,
|
|
|
|
&mut digest,
|
|
|
|
item_string,
|
|
|
|
|signing_string| self.sign(signing_string),
|
|
|
|
)?
|
|
|
|
.send()
|
|
|
|
.await
|
|
|
|
.map_err(|e| {
|
|
|
|
error!("Couldn't send deliver request to {}, {}", inbox, e);
|
|
|
|
MyError::SendRequest
|
|
|
|
})?;
|
|
|
|
|
|
|
|
if !res.status().is_success() {
|
|
|
|
error!("Invalid response status from {}, {}", inbox, res.status());
|
|
|
|
if let Ok(bytes) = res.body().await {
|
|
|
|
if let Ok(s) = String::from_utf8(bytes.as_ref().to_vec()) {
|
|
|
|
error!("Response, {}", s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Err(MyError::Status);
|
|
|
|
}
|
2020-03-17 17:15:16 +00:00
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2020-03-17 17:15:16 +00:00
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
fn sign(&self, signing_string: &str) -> Result<String, crate::error::MyError> {
|
|
|
|
let hashed = Sha256::digest(signing_string.as_bytes());
|
|
|
|
let bytes =
|
|
|
|
self.private_key
|
|
|
|
.sign(PaddingScheme::PKCS1v15, Some(&Hashes::SHA2_256), &hashed)?;
|
|
|
|
Ok(base64::encode(bytes))
|
|
|
|
}
|
2020-03-17 17:15:16 +00:00
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
async fn get_actor(&self, actor_id: &XsdAnyUri) -> Option<AcceptedActors> {
|
|
|
|
let cache = self.actor_cache.clone();
|
2020-03-17 17:15:16 +00:00
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
let read_guard = cache.read().await;
|
|
|
|
read_guard.get(actor_id).cloned()
|
2020-03-17 17:15:16 +00:00
|
|
|
}
|
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
async fn cache_actor(&self, actor_id: XsdAnyUri, actor: AcceptedActors) {
|
|
|
|
let cache = self.actor_cache.clone();
|
|
|
|
|
|
|
|
let mut write_guard = cache.write().await;
|
|
|
|
write_guard.insert(actor_id, actor, std::time::Duration::from_secs(3600));
|
|
|
|
}
|
2020-03-17 17:15:16 +00:00
|
|
|
}
|