2020-03-16 04:15:50 +00:00
use crate ::{
2020-05-21 21:24:56 +00:00
apub ::{ AcceptedActivities , AcceptedUndoObjects , UndoTypes , ValidTypes } ,
2020-03-20 00:55:11 +00:00
config ::{ Config , UrlKind } ,
2021-02-10 04:05:06 +00:00
data ::{ ActorCache , State } ,
db ::Actor ,
2021-09-18 17:55:39 +00:00
error ::{ Error , ErrorKind } ,
2020-03-30 17:10:04 +00:00
jobs ::apub ::{ Announce , Follow , Forward , Reject , Undo } ,
2020-03-21 20:24:05 +00:00
jobs ::JobServer ,
2020-03-18 04:35:20 +00:00
requests ::Requests ,
2020-03-23 17:38:39 +00:00
routes ::accepted ,
2020-03-16 04:15:50 +00:00
} ;
2020-09-07 21:51:02 +00:00
use activitystreams ::{
2022-01-17 22:54:45 +00:00
activity , base ::AnyBase , iri_string ::types ::IriString , prelude ::* , primitives ::OneOrMany ,
public ,
2020-05-21 21:24:56 +00:00
} ;
2020-03-18 04:35:20 +00:00
use actix_web ::{ web , HttpResponse } ;
2020-03-20 03:23:10 +00:00
use http_signature_normalization_actix ::prelude ::{ DigestVerified , SignatureVerified } ;
2020-03-18 04:58:13 +00:00
2022-11-16 03:26:13 +00:00
#[ tracing::instrument(name = " Inbox " , skip_all) ]
2022-12-19 18:23:06 +00:00
#[ allow(clippy::too_many_arguments) ]
2021-02-10 04:17:20 +00:00
pub ( crate ) async fn route (
2020-03-15 02:05:40 +00:00
state : web ::Data < State > ,
2020-03-23 22:17:53 +00:00
actors : web ::Data < ActorCache > ,
2020-03-20 00:55:11 +00:00
config : web ::Data < Config > ,
2020-03-18 04:35:20 +00:00
client : web ::Data < Requests > ,
2020-03-21 20:24:05 +00:00
jobs : web ::Data < JobServer > ,
2020-05-21 21:24:56 +00:00
input : web ::Json < AcceptedActivities > ,
2022-12-19 17:39:30 +00:00
digest_verified : Option < DigestVerified > ,
signature_verified : Option < SignatureVerified > ,
2021-09-18 17:55:39 +00:00
) -> Result < HttpResponse , Error > {
2020-03-15 02:05:40 +00:00
let input = input . into_inner ( ) ;
2022-12-19 17:39:30 +00:00
let kind = input . kind ( ) . ok_or ( ErrorKind ::MissingKind ) ? ;
if digest_verified . is_some ( ) & & signature_verified . is_none ( ) & & * kind = = ValidTypes ::Delete {
return Ok ( accepted ( serde_json ::json! ( { } ) ) ) ;
} else if config . validate_signatures ( )
& & ( digest_verified . is_none ( ) | | signature_verified . is_none ( ) )
{
return Err ( ErrorKind ::NoSignature ( None ) . into ( ) ) ;
}
let actor = actors
2020-05-21 21:24:56 +00:00
. get (
2021-09-18 17:55:39 +00:00
input . actor ( ) ? . as_single_id ( ) . ok_or ( ErrorKind ::MissingId ) ? ,
2020-05-21 21:24:56 +00:00
& client ,
)
2022-12-19 17:39:30 +00:00
. await ?
. into_inner ( ) ;
2020-03-17 20:52:26 +00:00
2022-12-14 05:36:40 +00:00
let is_allowed = state . db . is_allowed ( actor . id . clone ( ) ) . await ? ;
let is_connected = state . db . is_connected ( actor . id . clone ( ) ) . await ? ;
2020-03-18 02:16:09 +00:00
2021-02-10 04:05:06 +00:00
if ! is_allowed {
2021-09-18 17:55:39 +00:00
return Err ( ErrorKind ::NotAllowed ( actor . id . to_string ( ) ) . into ( ) ) ;
2020-03-18 02:16:09 +00:00
}
2021-02-10 04:05:06 +00:00
if ! is_connected & & ! valid_without_listener ( & input ) ? {
2021-09-18 17:55:39 +00:00
return Err ( ErrorKind ::NotSubscribed ( actor . id . to_string ( ) ) . into ( ) ) ;
2020-03-18 04:58:13 +00:00
}
2022-12-19 17:39:30 +00:00
if config . validate_signatures ( ) {
if let Some ( verified ) = signature_verified {
2020-03-23 22:17:53 +00:00
if actor . public_key_id . as_str ( ) ! = verified . key_id ( ) {
2022-12-14 05:36:40 +00:00
tracing ::error! ( " Actor signed with wrong key " ) ;
2021-09-18 17:55:39 +00:00
return Err ( ErrorKind ::BadActor (
2020-03-23 22:17:53 +00:00
actor . public_key_id . to_string ( ) ,
2020-03-20 03:23:10 +00:00
verified . key_id ( ) . to_owned ( ) ,
2021-09-18 17:55:39 +00:00
)
. into ( ) ) ;
2020-03-20 03:23:10 +00:00
}
2022-12-19 17:39:30 +00:00
} else {
tracing ::error! ( " This case should never be reachable, since I handle signature checks earlier in the flow. If you see this in a log it means I did it wrong " ) ;
return Err ( ErrorKind ::NoSignature ( Some ( actor . public_key_id . to_string ( ) ) ) . into ( ) ) ;
2020-03-20 03:23:10 +00:00
}
2020-03-17 19:52:33 +00:00
}
2022-12-19 17:39:30 +00:00
match kind {
2020-03-30 17:10:04 +00:00
ValidTypes ::Accept = > handle_accept ( & config , input ) . await ? ,
ValidTypes ::Reject = > handle_reject ( & config , & jobs , input , actor ) . await ? ,
2020-03-15 22:37:53 +00:00
ValidTypes ::Announce | ValidTypes ::Create = > {
2020-03-30 17:10:04 +00:00
handle_announce ( & state , & jobs , input , actor ) . await ?
2020-03-21 21:01:54 +00:00
}
2021-02-10 06:44:48 +00:00
ValidTypes ::Follow = > handle_follow ( & config , & jobs , input , actor ) . await ? ,
2022-12-19 22:08:39 +00:00
ValidTypes ::Add | ValidTypes ::Delete | ValidTypes ::Remove | ValidTypes ::Update = > {
2022-12-13 16:35:16 +00:00
handle_forward ( & jobs , input , actor ) . await ?
}
2021-02-10 04:05:06 +00:00
ValidTypes ::Undo = > handle_undo ( & config , & jobs , input , actor , is_connected ) . await ? ,
2020-03-30 17:10:04 +00:00
} ;
Ok ( accepted ( serde_json ::json! ( { } ) ) )
2020-03-21 21:01:54 +00:00
}
2021-09-18 17:55:39 +00:00
fn valid_without_listener ( input : & AcceptedActivities ) -> Result < bool , Error > {
2020-05-21 21:24:56 +00:00
match input . kind ( ) {
Some ( ValidTypes ::Follow ) = > Ok ( true ) ,
2022-01-17 22:54:45 +00:00
Some ( ValidTypes ::Undo ) = > Ok ( single_object ( input . object_unchecked ( ) ) ? . is_kind ( " Follow " ) ) ,
2020-05-21 21:24:56 +00:00
_ = > Ok ( false ) ,
2020-03-15 02:05:40 +00:00
}
2020-03-15 22:37:53 +00:00
}
2020-03-15 02:05:40 +00:00
2021-09-18 17:55:39 +00:00
fn kind_str ( base : & AnyBase ) -> Result < & str , Error > {
base . kind_str ( )
. ok_or ( ErrorKind ::MissingKind )
. map_err ( Into ::into )
2020-05-21 21:24:56 +00:00
}
2022-01-17 22:54:45 +00:00
fn id_string ( id : Option < & IriString > ) -> Result < String , Error > {
2021-09-18 17:55:39 +00:00
id . map ( | s | s . to_string ( ) )
. ok_or ( ErrorKind ::MissingId )
. map_err ( Into ::into )
2020-05-21 21:24:56 +00:00
}
2021-09-18 17:55:39 +00:00
fn single_object ( o : & OneOrMany < AnyBase > ) -> Result < & AnyBase , Error > {
o . as_one ( ) . ok_or ( ErrorKind ::ObjectCount ) . map_err ( Into ::into )
2020-05-21 21:24:56 +00:00
}
2021-09-18 17:55:39 +00:00
async fn handle_accept ( config : & Config , input : AcceptedActivities ) -> Result < ( ) , Error > {
2022-01-17 22:54:45 +00:00
let base = single_object ( input . object_unchecked ( ) ) ? . clone ( ) ;
2020-05-22 01:59:14 +00:00
let follow = if let Some ( follow ) = activity ::Follow ::from_any_base ( base ) ? {
2020-05-21 21:24:56 +00:00
follow
} else {
2022-01-17 22:54:45 +00:00
return Err ( ErrorKind ::Kind (
kind_str ( single_object ( input . object_unchecked ( ) ) ? ) ? . to_owned ( ) ,
)
. into ( ) ) ;
2020-05-21 21:24:56 +00:00
} ;
2020-03-21 20:24:05 +00:00
2020-06-03 17:37:36 +00:00
if ! follow . actor_is ( & config . generate_url ( UrlKind ::Actor ) ) {
2021-09-18 17:55:39 +00:00
return Err ( ErrorKind ::WrongActor ( id_string ( follow . actor ( ) ? . as_single_id ( ) ) ? ) . into ( ) ) ;
2020-03-21 20:24:05 +00:00
}
2020-03-30 17:10:04 +00:00
Ok ( ( ) )
2020-03-21 20:24:05 +00:00
}
async fn handle_reject (
config : & Config ,
jobs : & JobServer ,
2020-05-21 21:24:56 +00:00
input : AcceptedActivities ,
2020-03-23 22:17:53 +00:00
actor : Actor ,
2021-09-18 17:55:39 +00:00
) -> Result < ( ) , Error > {
2022-01-17 22:54:45 +00:00
let base = single_object ( input . object_unchecked ( ) ) ? . clone ( ) ;
2020-05-22 01:59:14 +00:00
let follow = if let Some ( follow ) = activity ::Follow ::from_any_base ( base ) ? {
2020-05-21 21:24:56 +00:00
follow
} else {
2022-01-17 22:54:45 +00:00
return Err ( ErrorKind ::Kind (
kind_str ( single_object ( input . object_unchecked ( ) ) ? ) ? . to_owned ( ) ,
)
. into ( ) ) ;
2020-05-21 21:24:56 +00:00
} ;
2020-03-21 20:24:05 +00:00
2020-06-03 17:37:36 +00:00
if ! follow . actor_is ( & config . generate_url ( UrlKind ::Actor ) ) {
2021-09-18 17:55:39 +00:00
return Err ( ErrorKind ::WrongActor ( id_string ( follow . actor ( ) ? . as_single_id ( ) ) ? ) . into ( ) ) ;
2020-03-21 20:24:05 +00:00
}
2021-10-11 19:19:32 +00:00
jobs . queue ( Reject ( actor ) ) . await ? ;
2020-03-21 20:24:05 +00:00
2020-03-30 17:10:04 +00:00
Ok ( ( ) )
2020-03-21 20:24:05 +00:00
}
2020-03-15 22:37:53 +00:00
async fn handle_undo (
2020-03-20 00:55:11 +00:00
config : & Config ,
2020-03-21 20:24:05 +00:00
jobs : & JobServer ,
2020-05-21 21:24:56 +00:00
input : AcceptedActivities ,
2020-03-23 22:17:53 +00:00
actor : Actor ,
2020-03-21 21:01:54 +00:00
is_listener : bool ,
2021-09-18 17:55:39 +00:00
) -> Result < ( ) , Error > {
2022-01-17 22:54:45 +00:00
let any_base = single_object ( input . object_unchecked ( ) ) ? . clone ( ) ;
2020-05-21 21:24:56 +00:00
let undone_object =
2021-09-18 17:55:39 +00:00
AcceptedUndoObjects ::from_any_base ( any_base ) ? . ok_or ( ErrorKind ::ObjectFormat ) ? ;
2020-03-18 05:43:31 +00:00
2020-05-21 21:24:56 +00:00
if ! undone_object . is_kind ( & UndoTypes ::Follow ) {
2020-03-21 21:01:54 +00:00
if is_listener {
2021-10-11 19:19:32 +00:00
jobs . queue ( Forward ::new ( input , actor ) ) . await ? ;
2020-03-30 17:10:04 +00:00
return Ok ( ( ) ) ;
2020-03-21 21:01:54 +00:00
} else {
2021-09-18 17:55:39 +00:00
return Err ( ErrorKind ::NotSubscribed ( actor . id . to_string ( ) ) . into ( ) ) ;
2020-03-21 21:01:54 +00:00
}
2020-03-15 22:37:53 +00:00
}
2022-01-17 22:54:45 +00:00
let my_id : IriString = config . generate_url ( UrlKind ::Actor ) ;
2020-03-18 02:16:09 +00:00
2020-05-21 21:24:56 +00:00
if ! undone_object . object_is ( & my_id ) & & ! undone_object . object_is ( & public ( ) ) {
2022-01-17 22:54:45 +00:00
return Err ( ErrorKind ::WrongActor ( id_string (
undone_object . object_unchecked ( ) . as_single_id ( ) ,
) ? )
. into ( ) ) ;
2020-03-18 02:16:09 +00:00
}
2020-03-21 21:01:54 +00:00
if ! is_listener {
2020-03-30 17:10:04 +00:00
return Ok ( ( ) ) ;
2020-03-23 22:17:53 +00:00
}
2021-10-11 19:19:32 +00:00
jobs . queue ( Undo ::new ( input , actor ) ) . await ? ;
2020-03-30 17:10:04 +00:00
Ok ( ( ) )
2020-03-15 22:37:53 +00:00
}
async fn handle_forward (
2020-03-21 20:24:05 +00:00
jobs : & JobServer ,
2020-05-21 21:24:56 +00:00
input : AcceptedActivities ,
2020-03-23 22:17:53 +00:00
actor : Actor ,
2021-09-18 17:55:39 +00:00
) -> Result < ( ) , Error > {
2021-10-11 19:19:32 +00:00
jobs . queue ( Forward ::new ( input , actor ) ) . await ? ;
2020-03-15 22:37:53 +00:00
2020-03-30 17:10:04 +00:00
Ok ( ( ) )
2020-03-15 22:37:53 +00:00
}
2020-03-18 05:43:31 +00:00
async fn handle_announce (
2020-03-18 04:35:20 +00:00
state : & State ,
2020-03-21 20:24:05 +00:00
jobs : & JobServer ,
2020-05-21 21:24:56 +00:00
input : AcceptedActivities ,
2020-03-23 22:17:53 +00:00
actor : Actor ,
2021-09-18 17:55:39 +00:00
) -> Result < ( ) , Error > {
2022-01-17 22:54:45 +00:00
let object_id = input
. object_unchecked ( )
. as_single_id ( )
. ok_or ( ErrorKind ::MissingId ) ? ;
2020-03-15 22:37:53 +00:00
2022-12-09 23:47:45 +00:00
if state . is_cached ( object_id ) {
2021-09-18 17:55:39 +00:00
return Err ( ErrorKind ::Duplicate . into ( ) ) ;
2020-03-15 22:37:53 +00:00
}
2022-01-17 22:54:45 +00:00
jobs . queue ( Announce ::new ( object_id . to_owned ( ) , actor ) )
. await ? ;
2020-03-15 22:37:53 +00:00
2020-03-30 17:10:04 +00:00
Ok ( ( ) )
2020-03-15 17:49:27 +00:00
}
async fn handle_follow (
2020-03-20 00:55:11 +00:00
config : & Config ,
2020-03-21 20:24:05 +00:00
jobs : & JobServer ,
2020-05-21 21:24:56 +00:00
input : AcceptedActivities ,
2020-03-23 22:17:53 +00:00
actor : Actor ,
2021-09-18 17:55:39 +00:00
) -> Result < ( ) , Error > {
2022-01-17 22:54:45 +00:00
let my_id : IriString = config . generate_url ( UrlKind ::Actor ) ;
2020-03-15 17:49:27 +00:00
2020-05-21 21:24:56 +00:00
if ! input . object_is ( & my_id ) & & ! input . object_is ( & public ( ) ) {
2022-01-17 22:54:45 +00:00
return Err (
ErrorKind ::WrongActor ( id_string ( input . object_unchecked ( ) . as_single_id ( ) ) ? ) . into ( ) ,
) ;
2020-03-15 17:49:27 +00:00
}
2021-10-11 19:19:32 +00:00
jobs . queue ( Follow ::new ( input , actor ) ) . await ? ;
2020-03-15 17:49:27 +00:00
2020-03-30 17:10:04 +00:00
Ok ( ( ) )
2020-03-15 22:37:53 +00:00
}