relay/src/inbox.rs

150 lines
3.8 KiB
Rust
Raw Normal View History

2020-03-15 17:49:27 +00:00
use activitystreams::{
activity::apub::{Accept, Follow},
primitives::XsdAnyUri,
};
2020-03-15 02:05:40 +00:00
use actix::Addr;
use actix_web::{client::Client, web, Responder};
2020-03-15 17:49:27 +00:00
use futures::join;
use log::{error, info};
2020-03-15 02:05:40 +00:00
use crate::{
apub::{AcceptedActors, AcceptedObjects, ValidTypes},
2020-03-15 17:49:27 +00:00
db_actor::{DbActor, DbQuery, Pool},
2020-03-15 02:05:40 +00:00
state::State,
};
#[derive(Clone, Debug, thiserror::Error)]
#[error("Something went wrong :(")]
pub struct MyError;
pub async fn inbox(
db_actor: web::Data<Addr<DbActor>>,
state: web::Data<State>,
client: web::Data<Client>,
input: web::Json<AcceptedObjects>,
) -> Result<impl Responder, MyError> {
let input = input.into_inner();
2020-03-15 17:49:27 +00:00
let actor = fetch_actor(state.clone(), client, &input.actor).await?;
2020-03-15 02:05:40 +00:00
match input.kind {
ValidTypes::Announce => (),
ValidTypes::Create => (),
ValidTypes::Delete => (),
2020-03-15 17:49:27 +00:00
ValidTypes::Follow => return handle_follow(db_actor, state, input, actor).await,
2020-03-15 02:05:40 +00:00
ValidTypes::Undo => (),
}
2020-03-15 17:49:27 +00:00
Err(MyError)
}
async fn handle_follow(
db_actor: web::Data<Addr<DbActor>>,
state: web::Data<State>,
input: AcceptedObjects,
actor: AcceptedActors,
) -> Result<web::Json<Accept>, MyError> {
let (is_listener, is_blocked, is_whitelisted) = join!(
state.is_listener(&actor.id),
state.is_blocked(&actor.id),
state.is_whitelisted(&actor.id)
);
if is_blocked {
error!("Follow from blocked listener, {}", actor.id);
return Err(MyError);
}
if !is_whitelisted {
error!("Follow from non-whitelisted listener, {}", actor.id);
return Err(MyError);
}
if !is_listener {
let state = state.into_inner();
let actor = actor.clone();
db_actor.do_send(DbQuery(move |pool: Pool| {
let actor_id = actor.id.clone();
let state = state.clone();
async move {
let conn = pool.get().await?;
state.add_listener(&conn, actor_id).await
}
}));
}
let mut accept = Accept::default();
let mut follow = Follow::default();
follow.object_props.set_id(input.id)?;
follow
.follow_props
.set_object_xsd_any_uri(format!("https://{}/actor", "localhost"))?
.set_actor_xsd_any_uri(actor.id.clone())?;
accept
.object_props
.set_id(format!("https://{}/activities/{}", "localhost", "1"))?
.set_many_to_xsd_any_uris(vec![actor.id])?;
accept
.accept_props
.set_object_object_box(follow)?
.set_actor_xsd_any_uri(format!("https://{}/actor", "localhost"))?;
Ok(web::Json(accept))
2020-03-15 02:05:40 +00:00
}
2020-03-15 16:29:01 +00:00
async fn fetch_actor(
state: web::Data<State>,
client: web::Data<Client>,
actor_id: &XsdAnyUri,
) -> Result<AcceptedActors, MyError> {
if let Some(actor) = state.get_actor(actor_id).await {
return Ok(actor);
}
let actor: AcceptedActors = client
2020-03-15 17:49:27 +00:00
.get(actor_id.as_str())
2020-03-15 02:05:40 +00:00
.header("Accept", "application/activity+json")
.send()
.await
2020-03-15 17:49:27 +00:00
.map_err(|e| {
error!("Couldn't send request for actor, {}", e);
MyError
})?
2020-03-15 02:05:40 +00:00
.json()
.await
2020-03-15 17:49:27 +00:00
.map_err(|e| {
error!("Coudn't fetch actor, {}", e);
MyError
})?;
2020-03-15 16:29:01 +00:00
state.cache_actor(actor_id.to_owned(), actor.clone()).await;
Ok(actor)
2020-03-15 02:05:40 +00:00
}
impl actix_web::error::ResponseError for MyError {}
2020-03-15 17:49:27 +00:00
impl From<std::convert::Infallible> for MyError {
fn from(_: std::convert::Infallible) -> Self {
MyError
}
}
impl From<activitystreams::primitives::XsdAnyUriError> for MyError {
fn from(_: activitystreams::primitives::XsdAnyUriError) -> Self {
error!("Error parsing URI");
MyError
}
}
impl From<std::io::Error> for MyError {
fn from(e: std::io::Error) -> Self {
error!("JSON Error, {}", e);
MyError
}
}