2021-11-17 21:35:17 +00:00
|
|
|
use actix_web::http::Method;
|
2021-10-30 22:35:18 +00:00
|
|
|
use rsa::RsaPrivateKey;
|
2022-07-13 23:40:33 +00:00
|
|
|
use serde::Serialize;
|
2021-10-30 22:35:18 +00:00
|
|
|
|
2022-07-14 10:18:03 +00:00
|
|
|
use crate::config::Instance;
|
2021-04-09 00:22:17 +00:00
|
|
|
use crate::http_signatures::create::{create_http_signature, SignatureError};
|
|
|
|
use crate::models::users::types::User;
|
|
|
|
use crate::utils::crypto::deserialize_private_key;
|
|
|
|
use super::actor::Actor;
|
2022-05-02 23:29:04 +00:00
|
|
|
use super::constants::{ACTIVITY_CONTENT_TYPE, ACTOR_KEY_SUFFIX};
|
2022-07-15 17:31:02 +00:00
|
|
|
use super::identifiers::local_actor_id;
|
2021-04-09 00:22:17 +00:00
|
|
|
|
|
|
|
#[derive(thiserror::Error, Debug)]
|
|
|
|
pub enum DelivererError {
|
|
|
|
#[error("key error")]
|
|
|
|
KeyDeserializationError(#[from] rsa::pkcs8::Error),
|
|
|
|
|
|
|
|
#[error(transparent)]
|
|
|
|
SignatureError(#[from] SignatureError),
|
|
|
|
|
|
|
|
#[error("activity serialization error")]
|
|
|
|
SerializationError(#[from] serde_json::Error),
|
|
|
|
|
|
|
|
#[error(transparent)]
|
|
|
|
RequestError(#[from] reqwest::Error),
|
|
|
|
|
|
|
|
#[error("http error {0:?}")]
|
|
|
|
HttpError(reqwest::StatusCode),
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn send_activity(
|
2021-11-18 14:56:52 +00:00
|
|
|
instance: &Instance,
|
2021-10-30 22:35:18 +00:00
|
|
|
actor_key: &RsaPrivateKey,
|
|
|
|
actor_key_id: &str,
|
|
|
|
activity_json: &str,
|
2021-04-09 00:22:17 +00:00
|
|
|
inbox_url: &str,
|
|
|
|
) -> Result<(), DelivererError> {
|
|
|
|
let headers = create_http_signature(
|
2021-11-17 21:35:17 +00:00
|
|
|
Method::POST,
|
2021-10-30 22:35:18 +00:00
|
|
|
inbox_url,
|
|
|
|
activity_json,
|
2021-04-09 00:22:17 +00:00
|
|
|
actor_key,
|
|
|
|
actor_key_id,
|
|
|
|
)?;
|
|
|
|
|
2021-11-17 21:35:17 +00:00
|
|
|
let client = reqwest::Client::new();
|
|
|
|
let request = client.post(inbox_url)
|
|
|
|
.header("Host", headers.host)
|
|
|
|
.header("Date", headers.date)
|
|
|
|
.header("Digest", headers.digest.unwrap())
|
|
|
|
.header("Signature", headers.signature)
|
2022-02-08 19:51:40 +00:00
|
|
|
.header(reqwest::header::CONTENT_TYPE, ACTIVITY_CONTENT_TYPE)
|
|
|
|
.header(reqwest::header::USER_AGENT, instance.agent())
|
2021-11-17 21:35:17 +00:00
|
|
|
.body(activity_json.to_owned());
|
|
|
|
|
2021-11-18 14:56:52 +00:00
|
|
|
if instance.is_private {
|
2021-12-31 15:29:44 +00:00
|
|
|
log::info!(
|
2021-11-18 14:56:52 +00:00
|
|
|
"private mode: not sending activity to {}",
|
|
|
|
inbox_url,
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
let response = request.send().await?;
|
|
|
|
let response_status = response.status();
|
|
|
|
let response_text = response.text().await?;
|
|
|
|
log::info!(
|
2021-12-24 00:44:01 +00:00
|
|
|
"response from {}: {}",
|
|
|
|
inbox_url,
|
2021-11-18 14:56:52 +00:00
|
|
|
response_text,
|
|
|
|
);
|
|
|
|
if response_status.is_client_error() || response_status.is_server_error() {
|
|
|
|
return Err(DelivererError::HttpError(response_status));
|
|
|
|
};
|
2021-04-09 00:22:17 +00:00
|
|
|
};
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-10-30 22:35:18 +00:00
|
|
|
async fn deliver_activity_worker(
|
2021-11-18 14:56:52 +00:00
|
|
|
instance: Instance,
|
2021-10-30 22:35:18 +00:00
|
|
|
sender: User,
|
2022-07-13 23:40:33 +00:00
|
|
|
activity: impl Serialize,
|
2021-04-09 00:22:17 +00:00
|
|
|
recipients: Vec<Actor>,
|
2021-10-30 22:35:18 +00:00
|
|
|
) -> Result<(), DelivererError> {
|
|
|
|
let actor_key = deserialize_private_key(&sender.private_key)?;
|
|
|
|
let actor_key_id = format!(
|
2022-05-02 23:29:04 +00:00
|
|
|
"{}{}",
|
2022-07-15 17:31:02 +00:00
|
|
|
local_actor_id(
|
2021-11-18 14:56:52 +00:00
|
|
|
&instance.url(),
|
2021-10-30 22:35:18 +00:00
|
|
|
&sender.profile.username,
|
|
|
|
),
|
2022-05-02 23:29:04 +00:00
|
|
|
ACTOR_KEY_SUFFIX,
|
2021-10-30 22:35:18 +00:00
|
|
|
);
|
|
|
|
let activity_json = serde_json::to_string(&activity)?;
|
2022-06-01 00:53:35 +00:00
|
|
|
if recipients.is_empty() {
|
|
|
|
return Ok(());
|
|
|
|
};
|
2021-11-01 00:23:02 +00:00
|
|
|
let mut inboxes: Vec<String> = recipients.into_iter()
|
|
|
|
.map(|actor| actor.inbox)
|
|
|
|
.collect();
|
|
|
|
inboxes.sort();
|
|
|
|
inboxes.dedup();
|
2021-12-21 00:14:12 +00:00
|
|
|
log::info!("sending activity to {} inboxes: {}", inboxes.len(), activity_json);
|
2021-11-01 00:23:02 +00:00
|
|
|
for inbox_url in inboxes {
|
2021-04-09 00:22:17 +00:00
|
|
|
// TODO: retry on error
|
2021-10-30 22:35:18 +00:00
|
|
|
if let Err(err) = send_activity(
|
2021-11-18 14:56:52 +00:00
|
|
|
&instance,
|
2021-10-30 22:35:18 +00:00
|
|
|
&actor_key,
|
|
|
|
&actor_key_id,
|
|
|
|
&activity_json,
|
2021-11-01 00:23:02 +00:00
|
|
|
&inbox_url,
|
2021-10-30 22:35:18 +00:00
|
|
|
).await {
|
2021-12-21 00:14:12 +00:00
|
|
|
log::error!("failed to deliver activity to {}: {}", inbox_url, err);
|
|
|
|
};
|
2021-04-09 00:22:17 +00:00
|
|
|
};
|
2021-10-30 22:35:18 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-07-13 23:40:33 +00:00
|
|
|
pub struct OutgoingActivity<A: Serialize> {
|
2022-06-01 00:53:35 +00:00
|
|
|
pub instance: Instance,
|
|
|
|
pub sender: User,
|
2022-07-13 23:40:33 +00:00
|
|
|
pub activity: A,
|
2022-06-01 00:53:35 +00:00
|
|
|
pub recipients: Vec<Actor>,
|
|
|
|
}
|
|
|
|
|
2022-07-17 00:00:35 +00:00
|
|
|
impl<A: Serialize + Send + 'static> OutgoingActivity<A> {
|
2022-06-01 00:53:35 +00:00
|
|
|
pub async fn deliver(self) -> Result<(), DelivererError> {
|
|
|
|
deliver_activity_worker(
|
|
|
|
self.instance,
|
|
|
|
self.sender,
|
|
|
|
self.activity,
|
|
|
|
self.recipients,
|
|
|
|
).await
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn spawn_deliver(self) -> () {
|
2022-07-17 00:00:35 +00:00
|
|
|
tokio::spawn(async move {
|
2022-06-01 00:53:35 +00:00
|
|
|
self.deliver().await.unwrap_or_else(|err| {
|
|
|
|
log::error!("{}", err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|