Rename ActivityHandler to Activity
This commit is contained in:
parent
ffdb202a72
commit
f0e5149922
16 changed files with 91 additions and 94 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
## Sending and receiving activities
|
## Sending and receiving activities
|
||||||
|
|
||||||
Activitypub propagates actions across servers using `Activities`. For this each actor has an inbox and a public/private key pair. We already defined a `Person` actor with keypair. Whats left is to define an activity. This is similar to the way we defined `Person` and `Note` structs before. In this case we need to implement the [ActivityHandler](trait@crate::traits::ActivityHandler) trait.
|
Activitypub propagates actions across servers using `Activities`. For this each actor has an inbox and a public/private key pair. We already defined a `Person` actor with keypair. Whats left is to define an activity. This is similar to the way we defined `Person` and `Note` structs before. In this case we need to implement the [Activity](trait@crate::traits::Activity) trait.
|
||||||
|
|
||||||
```
|
```
|
||||||
# use serde::{Deserialize, Serialize};
|
# use serde::{Deserialize, Serialize};
|
||||||
|
|
@ -10,7 +10,7 @@ Activitypub propagates actions across servers using `Activities`. For this each
|
||||||
# use activitypub_federation::fetch::object_id::ObjectId;
|
# use activitypub_federation::fetch::object_id::ObjectId;
|
||||||
# use activitypub_federation::traits::tests::{DbConnection, DbUser};
|
# use activitypub_federation::traits::tests::{DbConnection, DbUser};
|
||||||
# use activitystreams_kinds::activity::FollowType;
|
# use activitystreams_kinds::activity::FollowType;
|
||||||
# use activitypub_federation::traits::ActivityHandler;
|
# use activitypub_federation::traits::Activity;
|
||||||
# use activitypub_federation::config::Data;
|
# use activitypub_federation::config::Data;
|
||||||
# async fn send_accept() -> Result<(), Error> { Ok(()) }
|
# async fn send_accept() -> Result<(), Error> { Ok(()) }
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@ pub struct Follow {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl ActivityHandler for Follow {
|
impl Activity for Follow {
|
||||||
type DataType = DbConnection;
|
type DataType = DbConnection;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
|
|
@ -59,14 +59,14 @@ Next its time to setup the actual HTTP handler for the inbox. For this we first
|
||||||
# use activitypub_federation::axum::inbox::{ActivityData, receive_activity};
|
# use activitypub_federation::axum::inbox::{ActivityData, receive_activity};
|
||||||
# use activitypub_federation::config::Data;
|
# use activitypub_federation::config::Data;
|
||||||
# use activitypub_federation::protocol::context::WithContext;
|
# use activitypub_federation::protocol::context::WithContext;
|
||||||
# use activitypub_federation::traits::ActivityHandler;
|
# use activitypub_federation::traits::Activity;
|
||||||
# use activitypub_federation::traits::tests::{DbConnection, DbUser, Follow};
|
# use activitypub_federation::traits::tests::{DbConnection, DbUser, Follow};
|
||||||
# use serde::{Deserialize, Serialize};
|
# use serde::{Deserialize, Serialize};
|
||||||
# use url::Url;
|
# use url::Url;
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
#[enum_delegate::implement(ActivityHandler)]
|
#[enum_delegate::implement(Activity)]
|
||||||
pub enum PersonAcceptedActivities {
|
pub enum PersonAcceptedActivities {
|
||||||
Follow(Follow),
|
Follow(Follow),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use activitypub_federation::{
|
||||||
fetch::object_id::ObjectId,
|
fetch::object_id::ObjectId,
|
||||||
kinds::activity::CreateType,
|
kinds::activity::CreateType,
|
||||||
protocol::{context::WithContext, helpers::deserialize_one_or_many},
|
protocol::{context::WithContext, helpers::deserialize_one_or_many},
|
||||||
traits::{ActivityHandler, Object},
|
traits::{Activity, Object},
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
@ -50,7 +50,7 @@ impl CreatePost {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActivityHandler for CreatePost {
|
impl Activity for CreatePost {
|
||||||
type DataType = DatabaseHandle;
|
type DataType = DatabaseHandle;
|
||||||
type Error = crate::error::Error;
|
type Error = crate::error::Error;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use activitypub_federation::{
|
||||||
http_signatures::generate_actor_keypair,
|
http_signatures::generate_actor_keypair,
|
||||||
kinds::actor::PersonType,
|
kinds::actor::PersonType,
|
||||||
protocol::{public_key::PublicKey, verification::verify_domains_match},
|
protocol::{public_key::PublicKey, verification::verify_domains_match},
|
||||||
traits::{ActivityHandler, Actor, Object},
|
traits::{Activity, Actor, Object},
|
||||||
};
|
};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
@ -29,7 +29,7 @@ pub struct DbUser {
|
||||||
/// List of all activities which this actor can receive.
|
/// List of all activities which this actor can receive.
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
#[enum_delegate::implement(ActivityHandler)]
|
#[enum_delegate::implement(Activity)]
|
||||||
pub enum PersonAcceptedActivities {
|
pub enum PersonAcceptedActivities {
|
||||||
CreateNote(CreatePost),
|
CreateNote(CreatePost),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
fetch::object_id::ObjectId,
|
fetch::object_id::ObjectId,
|
||||||
kinds::activity::AcceptType,
|
kinds::activity::AcceptType,
|
||||||
traits::ActivityHandler,
|
traits::Activity,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
@ -30,7 +30,7 @@ impl Accept {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActivityHandler for Accept {
|
impl Activity for Accept {
|
||||||
type DataType = DatabaseHandle;
|
type DataType = DatabaseHandle;
|
||||||
type Error = crate::error::Error;
|
type Error = crate::error::Error;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use activitypub_federation::{
|
||||||
fetch::object_id::ObjectId,
|
fetch::object_id::ObjectId,
|
||||||
kinds::activity::CreateType,
|
kinds::activity::CreateType,
|
||||||
protocol::helpers::deserialize_one_or_many,
|
protocol::helpers::deserialize_one_or_many,
|
||||||
traits::{ActivityHandler, Object},
|
traits::{Activity, Object},
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
@ -38,7 +38,7 @@ impl CreatePost {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActivityHandler for CreatePost {
|
impl Activity for CreatePost {
|
||||||
type DataType = DatabaseHandle;
|
type DataType = DatabaseHandle;
|
||||||
type Error = crate::error::Error;
|
type Error = crate::error::Error;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use activitypub_federation::{
|
||||||
config::Data,
|
config::Data,
|
||||||
fetch::object_id::ObjectId,
|
fetch::object_id::ObjectId,
|
||||||
kinds::activity::FollowType,
|
kinds::activity::FollowType,
|
||||||
traits::{ActivityHandler, Actor},
|
traits::{Activity, Actor},
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
@ -35,7 +35,7 @@ impl Follow {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl ActivityHandler for Follow {
|
impl Activity for Follow {
|
||||||
type DataType = DatabaseHandle;
|
type DataType = DatabaseHandle;
|
||||||
type Error = crate::error::Error;
|
type Error = crate::error::Error;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use activitypub_federation::{
|
||||||
http_signatures::generate_actor_keypair,
|
http_signatures::generate_actor_keypair,
|
||||||
kinds::actor::PersonType,
|
kinds::actor::PersonType,
|
||||||
protocol::{context::WithContext, public_key::PublicKey, verification::verify_domains_match},
|
protocol::{context::WithContext, public_key::PublicKey, verification::verify_domains_match},
|
||||||
traits::{ActivityHandler, Actor, Object},
|
traits::{Activity, Actor, Object},
|
||||||
};
|
};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
@ -37,7 +37,7 @@ pub struct DbUser {
|
||||||
/// List of all activities which this actor can receive.
|
/// List of all activities which this actor can receive.
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
#[enum_delegate::implement(ActivityHandler)]
|
#[enum_delegate::implement(Activity)]
|
||||||
pub enum PersonAcceptedActivities {
|
pub enum PersonAcceptedActivities {
|
||||||
Follow(Follow),
|
Follow(Follow),
|
||||||
Accept(Accept),
|
Accept(Accept),
|
||||||
|
|
@ -103,16 +103,16 @@ impl DbUser {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn send<Activity>(
|
pub(crate) async fn send<A>(
|
||||||
&self,
|
&self,
|
||||||
activity: Activity,
|
activity: A,
|
||||||
recipients: Vec<Url>,
|
recipients: Vec<Url>,
|
||||||
use_queue: bool,
|
use_queue: bool,
|
||||||
data: &Data<DatabaseHandle>,
|
data: &Data<DatabaseHandle>,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
Activity: ActivityHandler + Serialize + Debug + Send + Sync,
|
A: Activity + Serialize + Debug + Send + Sync,
|
||||||
<Activity as ActivityHandler>::Error: From<anyhow::Error> + From<serde_json::Error>,
|
<A as Activity>::Error: From<anyhow::Error> + From<serde_json::Error>,
|
||||||
{
|
{
|
||||||
let activity = WithContext::new_default(activity);
|
let activity = WithContext::new_default(activity);
|
||||||
// Send through queue in some cases and bypass it in others to test both code paths
|
// Send through queue in some cases and bypass it in others to test both code paths
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
activity_sending::{build_tasks, SendActivityTask},
|
activity_sending::{build_tasks, SendActivityTask},
|
||||||
config::Data,
|
config::Data,
|
||||||
error::Error,
|
error::Error,
|
||||||
traits::{ActivityHandler, Actor},
|
traits::{Activity, Actor},
|
||||||
};
|
};
|
||||||
|
|
||||||
use futures_core::Future;
|
use futures_core::Future;
|
||||||
|
|
@ -37,14 +37,14 @@ use url::Url;
|
||||||
/// - `inboxes`: List of remote actor inboxes that should receive the activity. Ignores local actor
|
/// - `inboxes`: List of remote actor inboxes that should receive the activity. Ignores local actor
|
||||||
/// inboxes. Should be built by calling [crate::traits::Actor::shared_inbox_or_inbox]
|
/// inboxes. Should be built by calling [crate::traits::Actor::shared_inbox_or_inbox]
|
||||||
/// for each target actor.
|
/// for each target actor.
|
||||||
pub async fn queue_activity<Activity, Datatype, ActorType>(
|
pub async fn queue_activity<A, Datatype, ActorType>(
|
||||||
activity: &Activity,
|
activity: &A,
|
||||||
actor: &ActorType,
|
actor: &ActorType,
|
||||||
inboxes: Vec<Url>,
|
inboxes: Vec<Url>,
|
||||||
data: &Data<Datatype>,
|
data: &Data<Datatype>,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
Activity: ActivityHandler + Serialize + Debug,
|
A: Activity + Serialize + Debug,
|
||||||
Datatype: Clone,
|
Datatype: Clone,
|
||||||
ActorType: Actor,
|
ActorType: Actor,
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
error::Error,
|
error::Error,
|
||||||
http_signatures::sign_request,
|
http_signatures::sign_request,
|
||||||
reqwest_shim::ResponseExt,
|
reqwest_shim::ResponseExt,
|
||||||
traits::{ActivityHandler, Actor},
|
traits::{Activity, Actor},
|
||||||
FEDERATION_CONTENT_TYPE,
|
FEDERATION_CONTENT_TYPE,
|
||||||
};
|
};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
|
@ -54,14 +54,14 @@ impl SendActivityTask {
|
||||||
/// - `inboxes`: List of remote actor inboxes that should receive the activity. Ignores local actor
|
/// - `inboxes`: List of remote actor inboxes that should receive the activity. Ignores local actor
|
||||||
/// inboxes. Should be built by calling [crate::traits::Actor::shared_inbox_or_inbox]
|
/// inboxes. Should be built by calling [crate::traits::Actor::shared_inbox_or_inbox]
|
||||||
/// for each target actor.
|
/// for each target actor.
|
||||||
pub async fn prepare<Activity, Datatype, ActorType>(
|
pub async fn prepare<A, Datatype, ActorType>(
|
||||||
activity: &Activity,
|
activity: &A,
|
||||||
actor: &ActorType,
|
actor: &ActorType,
|
||||||
inboxes: Vec<Url>,
|
inboxes: Vec<Url>,
|
||||||
data: &Data<Datatype>,
|
data: &Data<Datatype>,
|
||||||
) -> Result<Vec<SendActivityTask>, Error>
|
) -> Result<Vec<SendActivityTask>, Error>
|
||||||
where
|
where
|
||||||
Activity: ActivityHandler + Serialize + Debug,
|
A: Activity + Serialize + Debug,
|
||||||
Datatype: Clone,
|
Datatype: Clone,
|
||||||
ActorType: Actor,
|
ActorType: Actor,
|
||||||
{
|
{
|
||||||
|
|
@ -136,14 +136,14 @@ impl SendActivityTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn build_tasks<Activity, Datatype, ActorType>(
|
pub(crate) async fn build_tasks<A, Datatype, ActorType>(
|
||||||
activity: &Activity,
|
activity: &A,
|
||||||
actor: &ActorType,
|
actor: &ActorType,
|
||||||
inboxes: Vec<Url>,
|
inboxes: Vec<Url>,
|
||||||
data: &Data<Datatype>,
|
data: &Data<Datatype>,
|
||||||
) -> Result<Vec<SendActivityTask>, Error>
|
) -> Result<Vec<SendActivityTask>, Error>
|
||||||
where
|
where
|
||||||
Activity: ActivityHandler + Serialize + Debug,
|
A: Activity + Serialize + Debug,
|
||||||
Datatype: Clone,
|
Datatype: Clone,
|
||||||
ActorType: Actor,
|
ActorType: Actor,
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
error::Error,
|
error::Error,
|
||||||
http_signatures::{verify_body_hash, verify_signature},
|
http_signatures::{verify_body_hash, verify_signature},
|
||||||
parse_received_activity,
|
parse_received_activity,
|
||||||
traits::{ActivityHandler, Actor, Object},
|
traits::{Activity, Actor, Object},
|
||||||
};
|
};
|
||||||
use actix_web::{web::Bytes, HttpRequest, HttpResponse};
|
use actix_web::{web::Bytes, HttpRequest, HttpResponse};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
|
@ -14,77 +14,77 @@ use tracing::debug;
|
||||||
|
|
||||||
/// Handles incoming activities, verifying HTTP signatures and other checks
|
/// Handles incoming activities, verifying HTTP signatures and other checks
|
||||||
///
|
///
|
||||||
/// After successful validation, activities are passed to respective [trait@ActivityHandler].
|
/// After successful validation, activities are passed to respective [trait@Activity].
|
||||||
pub async fn receive_activity<Activity, ActorT, Datatype>(
|
pub async fn receive_activity<A, ActorT, Datatype>(
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
body: Bytes,
|
body: Bytes,
|
||||||
data: &Data<Datatype>,
|
data: &Data<Datatype>,
|
||||||
) -> Result<HttpResponse, <Activity as ActivityHandler>::Error>
|
) -> Result<HttpResponse, <A as Activity>::Error>
|
||||||
where
|
where
|
||||||
Activity: ActivityHandler<DataType = Datatype> + DeserializeOwned + Send + 'static,
|
A: Activity<DataType = Datatype> + DeserializeOwned + Send + 'static,
|
||||||
ActorT: Object<DataType = Datatype> + Actor + Send + 'static,
|
ActorT: Object<DataType = Datatype> + Actor + Send + 'static,
|
||||||
for<'de2> <ActorT as Object>::Kind: serde::Deserialize<'de2>,
|
for<'de2> <ActorT as Object>::Kind: serde::Deserialize<'de2>,
|
||||||
<Activity as ActivityHandler>::Error: From<Error> + From<<ActorT as Object>::Error>,
|
<A as Activity>::Error: From<Error> + From<<ActorT as Object>::Error>,
|
||||||
<ActorT as Object>::Error: From<Error>,
|
<ActorT as Object>::Error: From<Error>,
|
||||||
Datatype: Clone,
|
Datatype: Clone,
|
||||||
{
|
{
|
||||||
let (activity, _) = do_stuff::<Activity, ActorT, Datatype>(request, body, data).await?;
|
let (activity, _) = do_stuff::<A, ActorT, Datatype>(request, body, data).await?;
|
||||||
|
|
||||||
do_more_stuff(activity, data).await
|
do_more_stuff(activity, data).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Workaround required so we can use references for the hook, instead of cloning data.
|
/// Workaround required so we can use references for the hook, instead of cloning data.
|
||||||
pub trait ReceiveActivityHook<Activity, ActorT, Datatype>
|
pub trait ReceiveActivityHook<A, ActorT, Datatype>
|
||||||
where
|
where
|
||||||
Activity: ActivityHandler<DataType = Datatype> + DeserializeOwned + Send + Clone + 'static,
|
A: Activity<DataType = Datatype> + DeserializeOwned + Send + Clone + 'static,
|
||||||
ActorT: Object<DataType = Datatype> + Actor + Send + Clone + 'static,
|
ActorT: Object<DataType = Datatype> + Actor + Send + Clone + 'static,
|
||||||
for<'de2> <ActorT as Object>::Kind: serde::Deserialize<'de2>,
|
for<'de2> <ActorT as Object>::Kind: serde::Deserialize<'de2>,
|
||||||
<Activity as ActivityHandler>::Error: From<Error> + From<<ActorT as Object>::Error>,
|
<A as Activity>::Error: From<Error> + From<<ActorT as Object>::Error>,
|
||||||
<ActorT as Object>::Error: From<Error>,
|
<ActorT as Object>::Error: From<Error>,
|
||||||
Datatype: Clone,
|
Datatype: Clone,
|
||||||
{
|
{
|
||||||
/// Called when a new activity is recived
|
/// Called when a new activity is recived
|
||||||
fn hook(
|
fn hook(
|
||||||
self,
|
self,
|
||||||
activity: &Activity,
|
activity: &A,
|
||||||
actor: &ActorT,
|
actor: &ActorT,
|
||||||
data: &Data<Datatype>,
|
data: &Data<Datatype>,
|
||||||
) -> impl std::future::Future<Output = Result<(), <Activity as ActivityHandler>::Error>>;
|
) -> impl std::future::Future<Output = Result<(), <A as Activity>::Error>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as [receive_activity], only that it calls the provided hook function before
|
/// Same as [receive_activity], only that it calls the provided hook function before
|
||||||
/// calling activity verify and receive functions.
|
/// calling activity verify and receive functions.
|
||||||
pub async fn receive_activity_with_hook<Activity, ActorT, Datatype>(
|
pub async fn receive_activity_with_hook<A, ActorT, Datatype>(
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
body: Bytes,
|
body: Bytes,
|
||||||
hook: impl ReceiveActivityHook<Activity, ActorT, Datatype>,
|
hook: impl ReceiveActivityHook<A, ActorT, Datatype>,
|
||||||
data: &Data<Datatype>,
|
data: &Data<Datatype>,
|
||||||
) -> Result<HttpResponse, <Activity as ActivityHandler>::Error>
|
) -> Result<HttpResponse, <A as Activity>::Error>
|
||||||
where
|
where
|
||||||
Activity: ActivityHandler<DataType = Datatype> + DeserializeOwned + Send + Clone + 'static,
|
A: Activity<DataType = Datatype> + DeserializeOwned + Send + Clone + 'static,
|
||||||
ActorT: Object<DataType = Datatype> + Actor + Send + Clone + 'static,
|
ActorT: Object<DataType = Datatype> + Actor + Send + Clone + 'static,
|
||||||
for<'de2> <ActorT as Object>::Kind: serde::Deserialize<'de2>,
|
for<'de2> <ActorT as Object>::Kind: serde::Deserialize<'de2>,
|
||||||
<Activity as ActivityHandler>::Error: From<Error> + From<<ActorT as Object>::Error>,
|
<A as Activity>::Error: From<Error> + From<<ActorT as Object>::Error>,
|
||||||
<ActorT as Object>::Error: From<Error>,
|
<ActorT as Object>::Error: From<Error>,
|
||||||
Datatype: Clone,
|
Datatype: Clone,
|
||||||
{
|
{
|
||||||
let (activity, actor) = do_stuff::<Activity, ActorT, Datatype>(request, body, data).await?;
|
let (activity, actor) = do_stuff::<A, ActorT, Datatype>(request, body, data).await?;
|
||||||
|
|
||||||
hook.hook(&activity, &actor, data).await?;
|
hook.hook(&activity, &actor, data).await?;
|
||||||
|
|
||||||
do_more_stuff(activity, data).await
|
do_more_stuff(activity, data).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn do_stuff<Activity, ActorT, Datatype>(
|
async fn do_stuff<A, ActorT, Datatype>(
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
body: Bytes,
|
body: Bytes,
|
||||||
data: &Data<Datatype>,
|
data: &Data<Datatype>,
|
||||||
) -> Result<(Activity, ActorT), <Activity as ActivityHandler>::Error>
|
) -> Result<(A, ActorT), <A as Activity>::Error>
|
||||||
where
|
where
|
||||||
Activity: ActivityHandler<DataType = Datatype> + DeserializeOwned + Send + 'static,
|
A: Activity<DataType = Datatype> + DeserializeOwned + Send + 'static,
|
||||||
ActorT: Object<DataType = Datatype> + Actor + Send + 'static,
|
ActorT: Object<DataType = Datatype> + Actor + Send + 'static,
|
||||||
for<'de2> <ActorT as Object>::Kind: serde::Deserialize<'de2>,
|
for<'de2> <ActorT as Object>::Kind: serde::Deserialize<'de2>,
|
||||||
<Activity as ActivityHandler>::Error: From<Error> + From<<ActorT as Object>::Error>,
|
<A as Activity>::Error: From<Error> + From<<ActorT as Object>::Error>,
|
||||||
<ActorT as Object>::Error: From<Error>,
|
<ActorT as Object>::Error: From<Error>,
|
||||||
Datatype: Clone,
|
Datatype: Clone,
|
||||||
{
|
{
|
||||||
|
|
@ -94,7 +94,7 @@ where
|
||||||
.map(http_compat::header_value);
|
.map(http_compat::header_value);
|
||||||
verify_body_hash(digest_header.as_ref(), &body)?;
|
verify_body_hash(digest_header.as_ref(), &body)?;
|
||||||
|
|
||||||
let (activity, actor) = parse_received_activity::<Activity, ActorT, _>(&body, data).await?;
|
let (activity, actor) = parse_received_activity::<A, ActorT, _>(&body, data).await?;
|
||||||
|
|
||||||
let headers = http_compat::header_map(request.headers());
|
let headers = http_compat::header_map(request.headers());
|
||||||
let method = http_compat::method(request.method());
|
let method = http_compat::method(request.method());
|
||||||
|
|
@ -104,12 +104,12 @@ where
|
||||||
Ok((activity, actor))
|
Ok((activity, actor))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn do_more_stuff<Activity, Datatype>(
|
async fn do_more_stuff<A, Datatype>(
|
||||||
activity: Activity,
|
activity: A,
|
||||||
data: &Data<Datatype>,
|
data: &Data<Datatype>,
|
||||||
) -> Result<HttpResponse, <Activity as ActivityHandler>::Error>
|
) -> Result<HttpResponse, <A as Activity>::Error>
|
||||||
where
|
where
|
||||||
Activity: ActivityHandler<DataType = Datatype> + DeserializeOwned + Send + 'static,
|
A: Activity<DataType = Datatype> + DeserializeOwned + Send + 'static,
|
||||||
Datatype: Clone,
|
Datatype: Clone,
|
||||||
{
|
{
|
||||||
debug!("Receiving activity {}", activity.id().to_string());
|
debug!("Receiving activity {}", activity.id().to_string());
|
||||||
|
|
@ -160,21 +160,21 @@ mod test {
|
||||||
|
|
||||||
struct Dummy;
|
struct Dummy;
|
||||||
|
|
||||||
impl<Activity, ActorT, Datatype> ReceiveActivityHook<Activity, ActorT, Datatype> for Dummy
|
impl<A, ActorT, Datatype> ReceiveActivityHook<A, ActorT, Datatype> for Dummy
|
||||||
where
|
where
|
||||||
Activity: ActivityHandler<DataType = Datatype> + DeserializeOwned + Send + Clone + 'static,
|
A: Activity<DataType = Datatype> + DeserializeOwned + Send + Clone + 'static,
|
||||||
ActorT: Object<DataType = Datatype> + Actor + Send + Clone + 'static,
|
ActorT: Object<DataType = Datatype> + Actor + Send + Clone + 'static,
|
||||||
for<'de2> <ActorT as Object>::Kind: serde::Deserialize<'de2>,
|
for<'de2> <ActorT as Object>::Kind: serde::Deserialize<'de2>,
|
||||||
<Activity as ActivityHandler>::Error: From<Error> + From<<ActorT as Object>::Error>,
|
<A as Activity>::Error: From<Error> + From<<ActorT as Object>::Error>,
|
||||||
<ActorT as Object>::Error: From<Error>,
|
<ActorT as Object>::Error: From<Error>,
|
||||||
Datatype: Clone,
|
Datatype: Clone,
|
||||||
{
|
{
|
||||||
async fn hook(
|
async fn hook(
|
||||||
self,
|
self,
|
||||||
_activity: &Activity,
|
_activity: &A,
|
||||||
_actor: &ActorT,
|
_actor: &ActorT,
|
||||||
_data: &Data<Datatype>,
|
_data: &Data<Datatype>,
|
||||||
) -> Result<(), <Activity as ActivityHandler>::Error> {
|
) -> Result<(), <A as Activity>::Error> {
|
||||||
// ensure that hook gets called by returning this value
|
// ensure that hook gets called by returning this value
|
||||||
Err(Error::Other("test-error".to_string()).into())
|
Err(Error::Other("test-error".to_string()).into())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
error::Error,
|
error::Error,
|
||||||
http_signatures::verify_signature,
|
http_signatures::verify_signature,
|
||||||
parse_received_activity,
|
parse_received_activity,
|
||||||
traits::{ActivityHandler, Actor, Object},
|
traits::{Activity, Actor, Object},
|
||||||
};
|
};
|
||||||
use axum::{
|
use axum::{
|
||||||
body::Body,
|
body::Body,
|
||||||
|
|
@ -20,20 +20,20 @@ use serde::de::DeserializeOwned;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
/// Handles incoming activities, verifying HTTP signatures and other checks
|
/// Handles incoming activities, verifying HTTP signatures and other checks
|
||||||
pub async fn receive_activity<Activity, ActorT, Datatype>(
|
pub async fn receive_activity<A, ActorT, Datatype>(
|
||||||
activity_data: ActivityData,
|
activity_data: ActivityData,
|
||||||
data: &Data<Datatype>,
|
data: &Data<Datatype>,
|
||||||
) -> Result<(), <Activity as ActivityHandler>::Error>
|
) -> Result<(), <A as Activity>::Error>
|
||||||
where
|
where
|
||||||
Activity: ActivityHandler<DataType = Datatype> + DeserializeOwned + Send + 'static,
|
A: Activity<DataType = Datatype> + DeserializeOwned + Send + 'static,
|
||||||
ActorT: Object<DataType = Datatype> + Actor + Send + 'static,
|
ActorT: Object<DataType = Datatype> + Actor + Send + 'static,
|
||||||
for<'de2> <ActorT as Object>::Kind: serde::Deserialize<'de2>,
|
for<'de2> <ActorT as Object>::Kind: serde::Deserialize<'de2>,
|
||||||
<Activity as ActivityHandler>::Error: From<Error> + From<<ActorT as Object>::Error>,
|
<A as Activity>::Error: From<Error> + From<<ActorT as Object>::Error>,
|
||||||
<ActorT as Object>::Error: From<Error>,
|
<ActorT as Object>::Error: From<Error>,
|
||||||
Datatype: Clone,
|
Datatype: Clone,
|
||||||
{
|
{
|
||||||
let (activity, actor) =
|
let (activity, actor) =
|
||||||
parse_received_activity::<Activity, ActorT, _>(&activity_data.body, data).await?;
|
parse_received_activity::<A, ActorT, _>(&activity_data.body, data).await?;
|
||||||
|
|
||||||
verify_signature(
|
verify_signature(
|
||||||
&activity_data.headers,
|
&activity_data.headers,
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ use crate::{
|
||||||
error::Error,
|
error::Error,
|
||||||
http_signatures::sign_request,
|
http_signatures::sign_request,
|
||||||
protocol::verification::verify_domains_match,
|
protocol::verification::verify_domains_match,
|
||||||
traits::{ActivityHandler, Actor},
|
traits::{Activity, Actor},
|
||||||
};
|
};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
|
@ -125,12 +125,9 @@ impl<T: Clone> FederationConfig<T> {
|
||||||
FederationConfigBuilder::default()
|
FederationConfigBuilder::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn verify_url_and_domain<Activity, Datatype>(
|
pub(crate) async fn verify_url_and_domain<A, Datatype>(&self, activity: &A) -> Result<(), Error>
|
||||||
&self,
|
|
||||||
activity: &Activity,
|
|
||||||
) -> Result<(), Error>
|
|
||||||
where
|
where
|
||||||
Activity: ActivityHandler<DataType = Datatype> + DeserializeOwned + Send + 'static,
|
A: Activity<DataType = Datatype> + DeserializeOwned + Send + 'static,
|
||||||
{
|
{
|
||||||
verify_domains_match(activity.id(), activity.actor())?;
|
verify_domains_match(activity.id(), activity.actor())?;
|
||||||
self.verify_url_valid(activity.id()).await?;
|
self.verify_url_valid(activity.id()).await?;
|
||||||
|
|
|
||||||
12
src/lib.rs
12
src/lib.rs
|
|
@ -28,7 +28,7 @@ use crate::{
|
||||||
config::Data,
|
config::Data,
|
||||||
error::Error,
|
error::Error,
|
||||||
fetch::object_id::ObjectId,
|
fetch::object_id::ObjectId,
|
||||||
traits::{ActivityHandler, Actor, Object},
|
traits::{Activity, Actor, Object},
|
||||||
};
|
};
|
||||||
pub use activitystreams_kinds as kinds;
|
pub use activitystreams_kinds as kinds;
|
||||||
|
|
||||||
|
|
@ -40,19 +40,19 @@ pub const FEDERATION_CONTENT_TYPE: &str = "application/activity+json";
|
||||||
|
|
||||||
/// Deserialize incoming inbox activity to the given type, perform basic
|
/// Deserialize incoming inbox activity to the given type, perform basic
|
||||||
/// validation and extract the actor.
|
/// validation and extract the actor.
|
||||||
async fn parse_received_activity<Activity, ActorT, Datatype>(
|
async fn parse_received_activity<A, ActorT, Datatype>(
|
||||||
body: &[u8],
|
body: &[u8],
|
||||||
data: &Data<Datatype>,
|
data: &Data<Datatype>,
|
||||||
) -> Result<(Activity, ActorT), <Activity as ActivityHandler>::Error>
|
) -> Result<(A, ActorT), <A as Activity>::Error>
|
||||||
where
|
where
|
||||||
Activity: ActivityHandler<DataType = Datatype> + DeserializeOwned + Send + 'static,
|
A: Activity<DataType = Datatype> + DeserializeOwned + Send + 'static,
|
||||||
ActorT: Object<DataType = Datatype> + Actor + Send + 'static,
|
ActorT: Object<DataType = Datatype> + Actor + Send + 'static,
|
||||||
for<'de2> <ActorT as Object>::Kind: serde::Deserialize<'de2>,
|
for<'de2> <ActorT as Object>::Kind: serde::Deserialize<'de2>,
|
||||||
<Activity as ActivityHandler>::Error: From<Error> + From<<ActorT as Object>::Error>,
|
<A as Activity>::Error: From<Error> + From<<ActorT as Object>::Error>,
|
||||||
<ActorT as Object>::Error: From<Error>,
|
<ActorT as Object>::Error: From<Error>,
|
||||||
Datatype: Clone,
|
Datatype: Clone,
|
||||||
{
|
{
|
||||||
let activity: Activity = serde_json::from_slice(body).map_err(|err| {
|
let activity: A = serde_json::from_slice(body).map_err(|err| {
|
||||||
// Attempt to include activity id in error message
|
// Attempt to include activity id in error message
|
||||||
let id = extract_id(body).ok();
|
let id = extract_id(body).ok();
|
||||||
Error::ParseReceivedActivity { err, id }
|
Error::ParseReceivedActivity { err, id }
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
//! Ok::<(), serde_json::error::Error>(())
|
//! Ok::<(), serde_json::error::Error>(())
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use crate::{config::Data, traits::ActivityHandler};
|
use crate::{config::Data, traits::Activity};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
@ -55,12 +55,12 @@ impl<T> WithContext<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl<T> ActivityHandler for WithContext<T>
|
impl<T> Activity for WithContext<T>
|
||||||
where
|
where
|
||||||
T: ActivityHandler + Send + Sync,
|
T: Activity + Send + Sync,
|
||||||
{
|
{
|
||||||
type DataType = <T as ActivityHandler>::DataType;
|
type DataType = <T as Activity>::DataType;
|
||||||
type Error = <T as ActivityHandler>::Error;
|
type Error = <T as Activity>::Error;
|
||||||
|
|
||||||
fn id(&self) -> &Url {
|
fn id(&self) -> &Url {
|
||||||
self.inner.id()
|
self.inner.id()
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,7 @@ pub trait Object: Sized + Debug {
|
||||||
/// # use url::Url;
|
/// # use url::Url;
|
||||||
/// # use activitypub_federation::fetch::object_id::ObjectId;
|
/// # use activitypub_federation::fetch::object_id::ObjectId;
|
||||||
/// # use activitypub_federation::config::Data;
|
/// # use activitypub_federation::config::Data;
|
||||||
/// # use activitypub_federation::traits::ActivityHandler;
|
/// # use activitypub_federation::traits::Activity;
|
||||||
/// # use activitypub_federation::traits::tests::{DbConnection, DbUser};
|
/// # use activitypub_federation::traits::tests::{DbConnection, DbUser};
|
||||||
/// #[derive(serde::Deserialize)]
|
/// #[derive(serde::Deserialize)]
|
||||||
/// struct Follow {
|
/// struct Follow {
|
||||||
|
|
@ -222,7 +222,7 @@ pub trait Object: Sized + Debug {
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// #[async_trait::async_trait]
|
/// #[async_trait::async_trait]
|
||||||
/// impl ActivityHandler for Follow {
|
/// impl Activity for Follow {
|
||||||
/// type DataType = DbConnection;
|
/// type DataType = DbConnection;
|
||||||
/// type Error = anyhow::Error;
|
/// type Error = anyhow::Error;
|
||||||
///
|
///
|
||||||
|
|
@ -248,7 +248,7 @@ pub trait Object: Sized + Debug {
|
||||||
/// ```
|
/// ```
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
#[enum_delegate::register]
|
#[enum_delegate::register]
|
||||||
pub trait ActivityHandler {
|
pub trait Activity {
|
||||||
/// App data type passed to handlers. Must be identical to
|
/// App data type passed to handlers. Must be identical to
|
||||||
/// [crate::config::FederationConfigBuilder::app_data] type.
|
/// [crate::config::FederationConfigBuilder::app_data] type.
|
||||||
type DataType: Clone + Send + Sync;
|
type DataType: Clone + Send + Sync;
|
||||||
|
|
@ -309,9 +309,9 @@ pub trait Actor: Object + Send + 'static {
|
||||||
|
|
||||||
/// Allow for boxing of enum variants
|
/// Allow for boxing of enum variants
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<T> ActivityHandler for Box<T>
|
impl<T> Activity for Box<T>
|
||||||
where
|
where
|
||||||
T: ActivityHandler + Send + Sync,
|
T: Activity + Send + Sync,
|
||||||
{
|
{
|
||||||
type DataType = T::DataType;
|
type DataType = T::DataType;
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
//!
|
//!
|
||||||
//! TODO: Should be using `cfg[doctest]` but blocked by <https://github.com/rust-lang/rust/issues/67295>
|
//! TODO: Should be using `cfg[doctest]` but blocked by <https://github.com/rust-lang/rust/issues/67295>
|
||||||
|
|
||||||
use super::{async_trait, ActivityHandler, Actor, Data, Debug, Object, PublicKey, Url};
|
use super::{async_trait, Activity, Actor, Data, Debug, Object, PublicKey, Url};
|
||||||
use crate::{
|
use crate::{
|
||||||
error::Error,
|
error::Error,
|
||||||
fetch::object_id::ObjectId,
|
fetch::object_id::ObjectId,
|
||||||
|
|
@ -144,7 +144,7 @@ pub struct Follow {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl ActivityHandler for Follow {
|
impl Activity for Follow {
|
||||||
type DataType = DbConnection;
|
type DataType = DbConnection;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue