Better type safety for activity parsing

This commit is contained in:
Felix Ableitner 2021-02-24 20:37:27 +01:00
parent 6499709221
commit 3ae62573b7
2 changed files with 63 additions and 19 deletions

View file

@ -48,8 +48,15 @@ use lemmy_db_schema::source::site::Site;
use lemmy_structs::blocking; use lemmy_structs::blocking;
use lemmy_utils::{location_info, LemmyError}; use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use strum_macros::EnumString;
use url::Url; use url::Url;
#[derive(EnumString)]
enum PageOrNote {
Page,
Note,
}
/// This file is for post/comment activities received by the community, and for post/comment /// 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. /// 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)?; verify_activity_domains_valid(&create, &expected_domain, true)?;
is_addressed_to_public(&create)?; is_addressed_to_public(&create)?;
match create.object().as_single_kind_str() { let kind = create
Some("Page") => receive_create_post(create, context, request_counter).await, .object()
Some("Note") => receive_create_comment(create, context, request_counter).await, .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), _ => 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)?; verify_activity_domains_valid(&update, &expected_domain, true)?;
is_addressed_to_public(&update)?; is_addressed_to_public(&update)?;
match update.object().as_single_kind_str() { let kind = update
Some("Page") => receive_update_post(update, context, request_counter).await, .object()
Some("Note") => receive_update_comment(update, context, request_counter).await, .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), _ => 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) /// A post/comment action being reverted (either a delete, remove, upvote or downvote)
pub(in crate::inbox) async fn receive_undo_for_community( pub(in crate::inbox) async fn receive_undo_for_community(
context: &LemmyContext, 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)?; verify_activity_domains_valid(&undo, &expected_domain.to_owned(), true)?;
is_addressed_to_public(&undo)?; is_addressed_to_public(&undo)?;
match undo.object().as_single_kind_str() { use UndoableActivities::*;
Some("Delete") => receive_undo_delete_for_community(context, undo, expected_domain).await, match undo
Some("Remove") => receive_undo_remove_for_community(context, undo, expected_domain).await, .object()
Some("Like") => { .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 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_undo_dislike_for_community(context, undo, expected_domain, request_counter).await
} }
_ => receive_unhandled_activity(undo), _ => receive_unhandled_activity(undo),

View file

@ -60,6 +60,7 @@ use lemmy_websocket::LemmyContext;
use log::debug; use log::debug;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Debug; use std::fmt::Debug;
use strum_macros::EnumString;
use url::Url; use url::Url;
/// Allowed activities for user inbox. /// Allowed activities for user inbox.
@ -235,6 +236,17 @@ async fn receive_accept(
Ok(()) Ok(())
} }
#[derive(EnumString)]
enum AnnouncableActivities {
Create,
Update,
Like,
Dislike,
Delete,
Remove,
Undo,
}
/// Takes an announce and passes the inner activity to the appropriate handler. /// Takes an announce and passes the inner activity to the appropriate handler.
pub async fn receive_announce( pub async fn receive_announce(
context: &LemmyContext, context: &LemmyContext,
@ -246,7 +258,10 @@ pub async fn receive_announce(
verify_activity_domains_valid(&announce, &actor.actor_id(), false)?; verify_activity_domains_valid(&announce, &actor.actor_id(), false)?;
is_addressed_to_public(&announce)?; 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 let inner_activity = announce
.object() .object()
.to_owned() .to_owned()
@ -259,22 +274,23 @@ pub async fn receive_announce(
return Ok(()); return Ok(());
} }
use AnnouncableActivities::*;
match kind { match kind {
Some("Create") => { Some(Create) => {
receive_create_for_community(context, inner_activity, &inner_id, request_counter).await 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 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 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 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(Delete) => receive_delete_for_community(context, inner_activity, &inner_id).await,
Some("Remove") => receive_remove_for_community(context, inner_activity, &inner_id).await, Some(Remove) => receive_remove_for_community(context, inner_activity, &inner_id).await,
Some("Undo") => { Some(Undo) => {
receive_undo_for_community(context, inner_activity, &inner_id, request_counter).await receive_undo_for_community(context, inner_activity, &inner_id, request_counter).await
} }
_ => receive_unhandled_activity(inner_activity), _ => receive_unhandled_activity(inner_activity),