From 3ae62573b700d21c99e3347b393bfdeee0ef5d56 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Wed, 24 Feb 2021 20:37:27 +0100 Subject: [PATCH] Better type safety for activity parsing --- .../apub/src/inbox/receive_for_community.rs | 50 +++++++++++++++---- crates/apub/src/inbox/user_inbox.rs | 32 +++++++++--- 2 files changed, 63 insertions(+), 19 deletions(-) diff --git a/crates/apub/src/inbox/receive_for_community.rs b/crates/apub/src/inbox/receive_for_community.rs index e0248cb6..e3704d97 100644 --- a/crates/apub/src/inbox/receive_for_community.rs +++ b/crates/apub/src/inbox/receive_for_community.rs @@ -48,8 +48,15 @@ use lemmy_db_schema::source::site::Site; use lemmy_structs::blocking; use lemmy_utils::{location_info, LemmyError}; use lemmy_websocket::LemmyContext; +use strum_macros::EnumString; use url::Url; +#[derive(EnumString)] +enum PageOrNote { + Page, + Note, +} + /// This file is for post/comment activities received by the community, and for post/comment /// activities announced by the community and received by the user. @@ -64,9 +71,13 @@ pub(in crate::inbox) async fn receive_create_for_community( verify_activity_domains_valid(&create, &expected_domain, true)?; is_addressed_to_public(&create)?; - match create.object().as_single_kind_str() { - Some("Page") => receive_create_post(create, context, request_counter).await, - Some("Note") => receive_create_comment(create, context, request_counter).await, + let kind = create + .object() + .as_single_kind_str() + .and_then(|s| s.parse().ok()); + match kind { + Some(PageOrNote::Page) => receive_create_post(create, context, request_counter).await, + Some(PageOrNote::Note) => receive_create_comment(create, context, request_counter).await, _ => receive_unhandled_activity(create), } } @@ -82,9 +93,13 @@ pub(in crate::inbox) async fn receive_update_for_community( verify_activity_domains_valid(&update, &expected_domain, true)?; is_addressed_to_public(&update)?; - match update.object().as_single_kind_str() { - Some("Page") => receive_update_post(update, context, request_counter).await, - Some("Note") => receive_update_comment(update, context, request_counter).await, + let kind = update + .object() + .as_single_kind_str() + .and_then(|s| s.parse().ok()); + match kind { + Some(PageOrNote::Page) => receive_update_post(update, context, request_counter).await, + Some(PageOrNote::Note) => receive_update_comment(update, context, request_counter).await, _ => receive_unhandled_activity(update), } } @@ -201,6 +216,14 @@ pub(in crate::inbox) async fn receive_remove_for_community( } } +#[derive(EnumString)] +enum UndoableActivities { + Delete, + Remove, + Like, + Dislike, +} + /// A post/comment action being reverted (either a delete, remove, upvote or downvote) pub(in crate::inbox) async fn receive_undo_for_community( context: &LemmyContext, @@ -212,13 +235,18 @@ pub(in crate::inbox) async fn receive_undo_for_community( verify_activity_domains_valid(&undo, &expected_domain.to_owned(), true)?; is_addressed_to_public(&undo)?; - match undo.object().as_single_kind_str() { - Some("Delete") => receive_undo_delete_for_community(context, undo, expected_domain).await, - Some("Remove") => receive_undo_remove_for_community(context, undo, expected_domain).await, - Some("Like") => { + use UndoableActivities::*; + match undo + .object() + .as_single_kind_str() + .and_then(|s| s.parse().ok()) + { + Some(Delete) => receive_undo_delete_for_community(context, undo, expected_domain).await, + Some(Remove) => receive_undo_remove_for_community(context, undo, expected_domain).await, + Some(Like) => { receive_undo_like_for_community(context, undo, expected_domain, request_counter).await } - Some("Dislike") => { + Some(Dislike) => { receive_undo_dislike_for_community(context, undo, expected_domain, request_counter).await } _ => receive_unhandled_activity(undo), diff --git a/crates/apub/src/inbox/user_inbox.rs b/crates/apub/src/inbox/user_inbox.rs index 7b90fafa..5657faf1 100644 --- a/crates/apub/src/inbox/user_inbox.rs +++ b/crates/apub/src/inbox/user_inbox.rs @@ -60,6 +60,7 @@ use lemmy_websocket::LemmyContext; use log::debug; use serde::{Deserialize, Serialize}; use std::fmt::Debug; +use strum_macros::EnumString; use url::Url; /// Allowed activities for user inbox. @@ -235,6 +236,17 @@ async fn receive_accept( Ok(()) } +#[derive(EnumString)] +enum AnnouncableActivities { + Create, + Update, + Like, + Dislike, + Delete, + Remove, + Undo, +} + /// Takes an announce and passes the inner activity to the appropriate handler. pub async fn receive_announce( context: &LemmyContext, @@ -246,7 +258,10 @@ pub async fn receive_announce( verify_activity_domains_valid(&announce, &actor.actor_id(), false)?; is_addressed_to_public(&announce)?; - let kind = announce.object().as_single_kind_str(); + let kind = announce + .object() + .as_single_kind_str() + .and_then(|s| s.parse().ok()); let inner_activity = announce .object() .to_owned() @@ -259,22 +274,23 @@ pub async fn receive_announce( return Ok(()); } + use AnnouncableActivities::*; match kind { - Some("Create") => { + Some(Create) => { receive_create_for_community(context, inner_activity, &inner_id, request_counter).await } - Some("Update") => { + Some(Update) => { receive_update_for_community(context, inner_activity, &inner_id, request_counter).await } - Some("Like") => { + Some(Like) => { receive_like_for_community(context, inner_activity, &inner_id, request_counter).await } - Some("Dislike") => { + Some(Dislike) => { receive_dislike_for_community(context, inner_activity, &inner_id, request_counter).await } - Some("Delete") => receive_delete_for_community(context, inner_activity, &inner_id).await, - Some("Remove") => receive_remove_for_community(context, inner_activity, &inner_id).await, - Some("Undo") => { + Some(Delete) => receive_delete_for_community(context, inner_activity, &inner_id).await, + Some(Remove) => receive_remove_for_community(context, inner_activity, &inner_id).await, + Some(Undo) => { receive_undo_for_community(context, inner_activity, &inner_id, request_counter).await } _ => receive_unhandled_activity(inner_activity),