diff --git a/src/activitypub/handlers/accept.rs b/src/activitypub/handlers/accept.rs index 1bafc1d..427f272 100644 --- a/src/activitypub/handlers/accept.rs +++ b/src/activitypub/handlers/accept.rs @@ -1,3 +1,4 @@ +use serde_json::Value; use tokio_postgres::GenericClient; use crate::activitypub::{ @@ -19,9 +20,11 @@ use super::HandlerResult; pub async fn handle_accept( config: &Config, db_client: &mut impl GenericClient, - activity: Activity, + activity: Value, ) -> HandlerResult { // Accept(Follow) + let activity: Activity = serde_json::from_value(activity) + .map_err(|_| ValidationError("unexpected activity structure"))?; let actor_profile = get_profile_by_remote_actor_id( db_client, &activity.actor, diff --git a/src/activitypub/handlers/add.rs b/src/activitypub/handlers/add.rs index de80b42..a822383 100644 --- a/src/activitypub/handlers/add.rs +++ b/src/activitypub/handlers/add.rs @@ -1,3 +1,4 @@ +use serde_json::Value; use tokio_postgres::GenericClient; use crate::activitypub::{ @@ -16,8 +17,10 @@ use super::{HandlerError, HandlerResult}; pub async fn handle_add( config: &Config, db_client: &mut impl GenericClient, - activity: Activity, + activity: Value, ) -> HandlerResult { + let activity: Activity = serde_json::from_value(activity) + .map_err(|_| ValidationError("unexpected activity structure"))?; let actor_profile = get_profile_by_remote_actor_id( db_client, &activity.actor, diff --git a/src/activitypub/handlers/announce.rs b/src/activitypub/handlers/announce.rs index 3b897b6..91b0f21 100644 --- a/src/activitypub/handlers/announce.rs +++ b/src/activitypub/handlers/announce.rs @@ -1,3 +1,4 @@ +use serde_json::Value; use tokio_postgres::GenericClient; use crate::activitypub::{ @@ -9,6 +10,7 @@ use crate::activitypub::{ }; use crate::config::Config; use crate::database::DatabaseError; +use crate::errors::ValidationError; use crate::models::posts::queries::{ create_post, get_post_by_remote_object_id, @@ -19,8 +21,10 @@ use super::HandlerResult; pub async fn handle_announce( config: &Config, db_client: &mut impl GenericClient, - activity: Activity, + activity: Value, ) -> HandlerResult { + let activity: Activity = serde_json::from_value(activity) + .map_err(|_| ValidationError("unexpected activity structure"))?; let repost_object_id = activity.id; match get_post_by_remote_object_id( db_client, diff --git a/src/activitypub/handlers/create.rs b/src/activitypub/handlers/create.rs index 9c4a7df..6c53b2f 100644 --- a/src/activitypub/handlers/create.rs +++ b/src/activitypub/handlers/create.rs @@ -7,7 +7,7 @@ use tokio_postgres::GenericClient; use uuid::Uuid; use crate::activitypub::{ - activity::{Activity, Attachment, Link, Object, Tag}, + activity::{Attachment, Link, Object, Tag}, constants::{AP_MEDIA_TYPE, AP_PUBLIC, AS_MEDIA_TYPE}, fetcher::fetchers::fetch_file, fetcher::helpers::{ @@ -391,10 +391,10 @@ pub async fn handle_note( pub async fn handle_create( config: &Config, db_client: &mut impl GenericClient, - activity: Activity, + activity: JsonValue, is_authenticated: bool, ) -> HandlerResult { - let object: Object = serde_json::from_value(activity.object) + let object: Object = serde_json::from_value(activity["object"].to_owned()) .map_err(|_| ValidationError("invalid object"))?; let object_id = object.id.clone(); let object_received = if is_authenticated { diff --git a/src/activitypub/handlers/delete.rs b/src/activitypub/handlers/delete.rs index 034299e..175ea7b 100644 --- a/src/activitypub/handlers/delete.rs +++ b/src/activitypub/handlers/delete.rs @@ -1,3 +1,4 @@ +use serde_json::Value; use tokio_postgres::GenericClient; use crate::activitypub::{ @@ -21,8 +22,10 @@ use super::HandlerResult; pub async fn handle_delete( config: &Config, db_client: &mut impl GenericClient, - activity: Activity, + activity: Value, ) -> HandlerResult { + let activity: Activity = serde_json::from_value(activity) + .map_err(|_| ValidationError("unexpected activity structure"))?; let object_id = find_object_id(&activity.object)?; if object_id == activity.actor { // Self-delete diff --git a/src/activitypub/handlers/follow.rs b/src/activitypub/handlers/follow.rs index b35a3d7..d2cdbcb 100644 --- a/src/activitypub/handlers/follow.rs +++ b/src/activitypub/handlers/follow.rs @@ -1,3 +1,4 @@ +use serde_json::Value; use tokio_postgres::GenericClient; use crate::activitypub::{ @@ -10,6 +11,7 @@ use crate::activitypub::{ }; use crate::config::Config; use crate::database::DatabaseError; +use crate::errors::ValidationError; use crate::models::relationships::queries::follow; use crate::models::users::queries::get_user_by_name; use super::{HandlerError, HandlerResult}; @@ -17,8 +19,10 @@ use super::{HandlerError, HandlerResult}; pub async fn handle_follow( config: &Config, db_client: &mut impl GenericClient, - activity: Activity, + activity: Value, ) -> HandlerResult { + let activity: Activity = serde_json::from_value(activity) + .map_err(|_| ValidationError("unexpected activity structure"))?; let source_profile = get_or_import_profile_by_actor_id( db_client, &config.instance(), diff --git a/src/activitypub/handlers/like.rs b/src/activitypub/handlers/like.rs index 13e883a..e1988a4 100644 --- a/src/activitypub/handlers/like.rs +++ b/src/activitypub/handlers/like.rs @@ -1,3 +1,4 @@ +use serde_json::Value; use tokio_postgres::GenericClient; use crate::activitypub::{ @@ -9,6 +10,7 @@ use crate::activitypub::{ }; use crate::config::Config; use crate::database::DatabaseError; +use crate::errors::ValidationError; use crate::models::reactions::queries::create_reaction; use crate::models::posts::queries::get_post_by_remote_object_id; use super::HandlerResult; @@ -16,8 +18,10 @@ use super::HandlerResult; pub async fn handle_like( config: &Config, db_client: &mut impl GenericClient, - activity: Activity, + activity: Value, ) -> HandlerResult { + let activity: Activity = serde_json::from_value(activity) + .map_err(|_| ValidationError("unexpected activity structure"))?; let author = get_or_import_profile_by_actor_id( db_client, &config.instance(), diff --git a/src/activitypub/handlers/move.rs b/src/activitypub/handlers/move.rs index 1ee41bc..37c3c91 100644 --- a/src/activitypub/handlers/move.rs +++ b/src/activitypub/handlers/move.rs @@ -1,3 +1,4 @@ +use serde_json::Value; use tokio_postgres::GenericClient; use crate::activitypub::{ @@ -29,9 +30,11 @@ use super::HandlerResult; pub async fn handle_move( config: &Config, db_client: &mut impl GenericClient, - activity: Activity, + activity: Value, ) -> HandlerResult { // Move(Person) + let activity: Activity = serde_json::from_value(activity) + .map_err(|_| ValidationError("unexpected activity structure"))?; let object_id = find_object_id(&activity.object)?; let target_value = activity.target .ok_or(ValidationError("target is missing"))?; diff --git a/src/activitypub/handlers/reject.rs b/src/activitypub/handlers/reject.rs index d8cc634..18c1673 100644 --- a/src/activitypub/handlers/reject.rs +++ b/src/activitypub/handlers/reject.rs @@ -1,3 +1,4 @@ +use serde_json::Value; use tokio_postgres::GenericClient; use crate::activitypub::{ @@ -19,9 +20,11 @@ use super::HandlerResult; pub async fn handle_reject( config: &Config, db_client: &impl GenericClient, - activity: Activity, + activity: Value, ) -> HandlerResult { // Reject(Follow) + let activity: Activity = serde_json::from_value(activity) + .map_err(|_| ValidationError("unexpected activity structure"))?; let actor_profile = get_profile_by_remote_actor_id( db_client, &activity.actor, diff --git a/src/activitypub/handlers/remove.rs b/src/activitypub/handlers/remove.rs index 2685e0b..a403c7c 100644 --- a/src/activitypub/handlers/remove.rs +++ b/src/activitypub/handlers/remove.rs @@ -1,3 +1,4 @@ +use serde_json::Value; use tokio_postgres::GenericClient; use crate::activitypub::{ @@ -20,8 +21,10 @@ use super::{HandlerError, HandlerResult}; pub async fn handle_remove( config: &Config, db_client: &mut impl GenericClient, - activity: Activity, + activity: Value, ) -> HandlerResult { + let activity: Activity = serde_json::from_value(activity) + .map_err(|_| ValidationError("unexpected activity structure"))?; let actor_profile = get_profile_by_remote_actor_id( db_client, &activity.actor, diff --git a/src/activitypub/handlers/undo.rs b/src/activitypub/handlers/undo.rs index 3081b9e..59c8c6f 100644 --- a/src/activitypub/handlers/undo.rs +++ b/src/activitypub/handlers/undo.rs @@ -1,3 +1,4 @@ +use serde_json::Value; use tokio_postgres::GenericClient; use crate::activitypub::{ @@ -54,8 +55,10 @@ async fn handle_undo_follow( pub async fn handle_undo( config: &Config, db_client: &mut impl GenericClient, - activity: Activity, + activity: Value, ) -> HandlerResult { + let activity: Activity = serde_json::from_value(activity) + .map_err(|_| ValidationError("unexpected activity structure"))?; if let Some(FOLLOW) = activity.object["type"].as_str() { // Object type is currently required for processing Undo(Follow) // because activity IDs of remote follow requests are not stored. diff --git a/src/activitypub/handlers/update.rs b/src/activitypub/handlers/update.rs index 0ca9325..e1a8ab4 100644 --- a/src/activitypub/handlers/update.rs +++ b/src/activitypub/handlers/update.rs @@ -1,6 +1,7 @@ use std::path::Path; use chrono::Utc; +use serde_json::Value; use tokio_postgres::GenericClient; use crate::activitypub::{ @@ -122,8 +123,10 @@ async fn handle_update_person( pub async fn handle_update( config: &Config, db_client: &mut impl GenericClient, - activity: Activity, + activity: Value, ) -> HandlerResult { + let activity: Activity = serde_json::from_value(activity) + .map_err(|_| ValidationError("unexpected activity structure"))?; let object_type = activity.object["type"].as_str() .ok_or(ValidationError("unknown object type"))?; match object_type { diff --git a/src/activitypub/receiver.rs b/src/activitypub/receiver.rs index c4e04fb..f6d52c2 100644 --- a/src/activitypub/receiver.rs +++ b/src/activitypub/receiver.rs @@ -10,7 +10,6 @@ use crate::errors::{ HttpError, ValidationError, }; -use super::activity::Activity; use super::authentication::{ verify_signed_activity, verify_signed_request, @@ -131,15 +130,15 @@ pub async fn receive_activity( config: &Config, db_client: &mut impl GenericClient, request: &HttpRequest, - activity_raw: &Value, + activity: &Value, ) -> Result<(), HandlerError> { - let activity_type = activity_raw["type"].as_str() + let activity_type = activity["type"].as_str() .ok_or(ValidationError("type property is missing"))?; - let activity_actor = activity_raw["actor"].as_str() + let activity_actor = activity["actor"].as_str() .ok_or(ValidationError("actor property is missing"))?; let is_self_delete = if activity_type == DELETE { - let object_id = find_object_id(&activity_raw["object"])?; + let object_id = find_object_id(&activity["object"])?; object_id == activity_actor } else { false }; @@ -174,7 +173,7 @@ pub async fn receive_activity( match verify_signed_activity( config, db_client, - activity_raw, + activity, // Don't fetch actor if this is Delete(Person) activity is_self_delete, ).await { @@ -200,7 +199,7 @@ pub async fn receive_activity( if config.blocked_instances.iter() .any(|instance| signer.hostname.as_ref() == Some(instance)) { - log::warn!("ignoring activity from blocked instance: {}", activity_raw); + log::warn!("ignoring activity from blocked instance: {}", activity); return Ok(()); }; @@ -225,8 +224,7 @@ pub async fn receive_activity( }; }; - let activity: Activity = serde_json::from_value(activity_raw.clone()) - .map_err(|_| ValidationError("invalid activity"))?; + let activity = activity.clone(); let maybe_object_type = match activity_type { ACCEPT => { handle_accept(config, db_client, activity).await? @@ -265,7 +263,7 @@ pub async fn receive_activity( handle_update(config, db_client, activity).await? }, _ => { - log::warn!("activity type is not supported: {}", activity_raw); + log::warn!("activity type is not supported: {}", activity); return Ok(()); }, };