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_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),

View file

@ -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),