diff --git a/src/actix_web/inbox.rs b/src/actix_web/inbox.rs index 97249a9..b441055 100644 --- a/src/actix_web/inbox.rs +++ b/src/actix_web/inbox.rs @@ -1,7 +1,5 @@ //! Handles incoming activities, verifying HTTP signatures and other checks -use std::future::Future; - use super::http_compat; use crate::{ config::Data, @@ -35,12 +33,31 @@ where do_more_stuff(activity, data).await } +/// Workaround required so we can use references for the hook, instead of cloning data. +pub trait ReceiveActivityHook +where + Activity: ActivityHandler + DeserializeOwned + Send + Clone + 'static, + ActorT: Object + Actor + Send + Clone + 'static, + for<'de2> ::Kind: serde::Deserialize<'de2>, + ::Error: From + From<::Error>, + ::Error: From, + Datatype: Clone, +{ + /// Called when a new activity is recived + fn hook( + self, + activity: &Activity, + actor: &ActorT, + data: &Data, + ) -> impl std::future::Future::Error>>; +} + /// Same as [receive_activity], only that it calls the provided hook function before /// calling activity verify and receive functions. -pub async fn receive_activity_with_hook( +pub async fn receive_activity_with_hook( request: HttpRequest, body: Bytes, - hook: impl FnOnce(Activity, ActorT, Data) -> Fut, + hook: impl ReceiveActivityHook, data: &Data, ) -> Result::Error> where @@ -50,11 +67,10 @@ where ::Error: From + From<::Error>, ::Error: From, Datatype: Clone, - Fut: Future::Error>>, { let (activity, actor) = do_stuff::(request, body, data).await?; - hook(activity.clone(), actor.clone(), data.clone()).await?; + hook.hook(&activity, &actor, data).await?; do_more_stuff(activity, data).await } @@ -132,23 +148,36 @@ mod test { #[tokio::test] async fn test_receive_activity_hook() { let (body, incoming_request, config) = setup_receive_test().await; - let res = receive_activity_with_hook::( + let res = receive_activity_with_hook::( incoming_request.to_http_request(), body, - inbox_activity_hook, + Dummy, &config.to_request_data(), ) .await; assert_eq!(res.err(), Some(Error::Other("test-error".to_string()))); } - async fn inbox_activity_hook( - _activity: Activity, - _actor: ActorT, - _context: Data, - ) -> Result<(), Error> { - // ensure that hook gets called by returning this value - Err(Error::Other("test-error".to_string())) + struct Dummy; + + impl ReceiveActivityHook for Dummy + where + Activity: ActivityHandler + DeserializeOwned + Send + Clone + 'static, + ActorT: Object + Actor + Send + Clone + 'static, + for<'de2> ::Kind: serde::Deserialize<'de2>, + ::Error: From + From<::Error>, + ::Error: From, + Datatype: Clone, + { + async fn hook( + self, + _activity: &Activity, + _actor: &ActorT, + _data: &Data, + ) -> Result<(), ::Error> { + // ensure that hook gets called by returning this value + Err(Error::Other("test-error".to_string()).into()) + } } #[tokio::test]