fix post/comment create/update, rework voting

This commit is contained in:
Felix Ableitner 2021-07-10 04:11:21 +02:00
parent ddf480d6e2
commit 99f55a4627
31 changed files with 462 additions and 523 deletions

View file

@ -1,4 +1,10 @@
use crate::{fetcher::fetch::fetch_remote_object, objects::FromApub, NoteExt, PageExt};
use crate::{
fetcher::fetch::fetch_remote_object,
objects::FromApub,
NoteExt,
PageExt,
PostOrComment,
};
use anyhow::anyhow;
use diesel::result::Error::NotFound;
use lemmy_api_common::blocking;
@ -89,3 +95,19 @@ pub async fn get_or_fetch_and_insert_comment(
Err(e) => Err(e.into()),
}
}
pub async fn get_or_fetch_and_insert_post_or_comment(
ap_id: &Url,
context: &LemmyContext,
recursion_counter: &mut i32,
) -> Result<PostOrComment, LemmyError> {
Ok(
match get_or_fetch_and_insert_post(ap_id, context, recursion_counter).await {
Ok(p) => PostOrComment::Post(Box::new(p)),
Err(_) => {
let c = get_or_fetch_and_insert_comment(ap_id, context, recursion_counter).await?;
PostOrComment::Comment(Box::new(c))
}
},
)
}

View file

@ -123,18 +123,8 @@ impl FromApub for Comment {
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
check_object_for_community_or_site_ban(note, post.community_id, context, request_counter)
.await?;
if post.locked {
// This is not very efficient because a comment gets inserted just to be deleted right
// afterwards, but it seems to be the easiest way to implement it.
blocking(context.pool(), move |conn| {
Comment::delete(conn, comment.id)
})
.await??;
Err(anyhow!("Post is locked").into())
} else {
Ok(comment)
}
}
}
#[async_trait::async_trait(?Send)]
@ -174,6 +164,9 @@ impl FromApubToForm<NoteExt> for CommentForm {
request_counter,
))
.await?;
if post.locked {
return Err(anyhow!("Post is locked").into());
}
// The 2nd item, if it exists, is the parent comment apub_id
// For deeply nested comments, FromApub automatically gets called recursively

View file

@ -1,7 +1,16 @@
use crate::activities::comment::{get_notif_recipients, send_websocket_message};
use crate::activities::{
comment::{get_notif_recipients, send_websocket_message},
verify_activity,
verify_person_in_community,
};
use activitystreams::{activity::kind::CreateType, base::BaseExt};
use lemmy_apub::{check_is_apub_id_valid, objects::FromApub, NoteExt};
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_apub::{objects::FromApub, NoteExt};
use lemmy_apub_lib::{
verify_domains_match_opt,
ActivityCommonFields,
ActivityHandlerNew,
PublicUrl,
};
use lemmy_db_schema::source::comment::Comment;
use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
@ -21,10 +30,21 @@ pub struct CreateComment {
#[async_trait::async_trait(?Send)]
impl ActivityHandlerNew for CreateComment {
async fn verify(&self, _context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
self.object.id(self.common.actor.as_str())?;
check_is_apub_id_valid(&self.common.actor, false)
async fn verify(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
dbg!("1");
verify_activity(self.common())?;
dbg!("2");
verify_person_in_community(&self.common.actor, &self.cc, context, request_counter).await?;
dbg!("3");
verify_domains_match_opt(&self.common.actor, self.object.id_unchecked())?;
dbg!("4");
// TODO: should add a check that the correct community is in cc (probably needs changes to
// comment deserialization)
Ok(())
}
async fn receive(
@ -32,6 +52,7 @@ impl ActivityHandlerNew for CreateComment {
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
dbg!("5");
let comment = Comment::from_apub(
&self.object,
context,
@ -40,6 +61,7 @@ impl ActivityHandlerNew for CreateComment {
false,
)
.await?;
dbg!("6");
let recipients =
get_notif_recipients(&self.common.actor, &comment, context, request_counter).await?;
send_websocket_message(

View file

@ -1,46 +0,0 @@
use crate::activities::comment::like_or_dislike_comment;
use activitystreams::activity::kind::LikeType;
use lemmy_apub::check_is_apub_id_valid;
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LikeComment {
to: PublicUrl,
pub(in crate::activities::comment) object: Url,
cc: [Url; 1],
#[serde(rename = "type")]
kind: LikeType,
#[serde(flatten)]
common: ActivityCommonFields,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandlerNew for LikeComment {
async fn verify(&self, _context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
check_is_apub_id_valid(&self.common.actor, false)
}
async fn receive(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
like_or_dislike_comment(
1,
&self.common.actor,
&self.object,
context,
request_counter,
)
.await
}
fn common(&self) -> &ActivityCommonFields {
&self.common
}
}

View file

@ -1,30 +1,20 @@
use lemmy_api_common::{blocking, comment::CommentResponse, send_local_notifs};
use lemmy_apub::fetcher::{
objects::get_or_fetch_and_insert_comment,
person::get_or_fetch_and_upsert_person,
};
use lemmy_db_queries::{Crud, Likeable};
use lemmy_apub::fetcher::person::get_or_fetch_and_upsert_person;
use lemmy_db_queries::Crud;
use lemmy_db_schema::{
source::{
comment::{Comment, CommentLike, CommentLikeForm},
post::Post,
},
source::{comment::Comment, post::Post},
CommentId,
LocalUserId,
};
use lemmy_db_views::comment_view::CommentView;
use lemmy_utils::{utils::scrape_text_for_mentions, LemmyError};
use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperation};
use lemmy_websocket::{messages::SendComment, LemmyContext};
use url::Url;
pub mod create;
pub mod delete;
pub mod dislike;
pub mod like;
pub mod remove;
pub mod undo_delete;
pub mod undo_dislike;
pub mod undo_like;
pub mod undo_remove;
pub mod update;
@ -49,7 +39,9 @@ async fn get_notif_recipients(
// TODO: in many call sites we are setting an empty vec for recipient_ids, we should get the actual
// recipient actors from somewhere
async fn send_websocket_message<OP: ToString + Send + lemmy_websocket::OperationType + 'static>(
pub(crate) async fn send_websocket_message<
OP: ToString + Send + lemmy_websocket::OperationType + 'static,
>(
comment_id: CommentId,
recipient_ids: Vec<LocalUserId>,
op: OP,
@ -75,61 +67,3 @@ async fn send_websocket_message<OP: ToString + Send + lemmy_websocket::Operation
Ok(())
}
async fn like_or_dislike_comment(
score: i16,
actor: &Url,
object: &Url,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let actor = get_or_fetch_and_upsert_person(actor, context, request_counter).await?;
let comment = get_or_fetch_and_insert_comment(object, context, request_counter).await?;
let comment_id = comment.id;
let like_form = CommentLikeForm {
comment_id,
post_id: comment.post_id,
person_id: actor.id,
score,
};
let person_id = actor.id;
blocking(context.pool(), move |conn| {
CommentLike::remove(conn, person_id, comment_id)?;
CommentLike::like(conn, &like_form)
})
.await??;
send_websocket_message(
comment_id,
vec![],
UserOperation::CreateCommentLike,
context,
)
.await
}
async fn undo_like_or_dislike_comment(
actor: &Url,
object: &Url,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let actor = get_or_fetch_and_upsert_person(actor, context, request_counter).await?;
let comment = get_or_fetch_and_insert_comment(object, context, request_counter).await?;
let comment_id = comment.id;
let person_id = actor.id;
blocking(context.pool(), move |conn| {
CommentLike::remove(conn, person_id, comment_id)
})
.await??;
send_websocket_message(
comment.id,
vec![],
UserOperation::CreateCommentLike,
context,
)
.await
}

View file

@ -26,7 +26,7 @@ impl ActivityHandlerNew for RemoveComment {
async fn verify(&self, context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
check_is_apub_id_valid(&self.common.actor, false)?;
verify_mod_action(self.common.actor.clone(), self.cc[0].clone(), context).await
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await
}
async fn receive(

View file

@ -1,51 +0,0 @@
use crate::activities::comment::{dislike::DislikeComment, undo_like_or_dislike_comment};
use activitystreams::activity::kind::UndoType;
use lemmy_apub::check_is_apub_id_valid;
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoDislikeComment {
to: PublicUrl,
object: DislikeComment,
cc: [Url; 1],
#[serde(rename = "type")]
kind: UndoType,
#[serde(flatten)]
common: ActivityCommonFields,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandlerNew for UndoDislikeComment {
async fn verify(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
verify_domains_match(&self.common.actor, &self.object.object)?;
check_is_apub_id_valid(&self.common.actor, false)?;
self.object.verify(context, request_counter).await
}
async fn receive(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
undo_like_or_dislike_comment(
&self.common.actor,
&self.object.object,
context,
request_counter,
)
.await
}
fn common(&self) -> &ActivityCommonFields {
&self.common
}
}

View file

@ -33,7 +33,7 @@ impl ActivityHandlerNew for UndoRemoveComment {
) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
check_is_apub_id_valid(&self.common.actor, false)?;
verify_mod_action(self.common.actor.clone(), self.cc[0].clone(), context).await?;
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
self.object.verify(context, request_counter).await
}

View file

@ -1,7 +1,16 @@
use crate::activities::comment::{get_notif_recipients, send_websocket_message};
use crate::activities::{
comment::{get_notif_recipients, send_websocket_message},
verify_activity,
verify_person_in_community,
};
use activitystreams::{activity::kind::UpdateType, base::BaseExt};
use lemmy_apub::{check_is_apub_id_valid, objects::FromApub, NoteExt};
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_apub::{objects::FromApub, NoteExt};
use lemmy_apub_lib::{
verify_domains_match_opt,
ActivityCommonFields,
ActivityHandlerNew,
PublicUrl,
};
use lemmy_db_schema::source::comment::Comment;
use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
@ -21,10 +30,15 @@ pub struct UpdateComment {
#[async_trait::async_trait(?Send)]
impl ActivityHandlerNew for UpdateComment {
async fn verify(&self, _context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
self.object.id(self.common.actor.as_str())?;
check_is_apub_id_valid(&self.common.actor, false)
async fn verify(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_activity(self.common())?;
verify_person_in_community(&self.common.actor, &self.cc, context, request_counter).await?;
verify_domains_match_opt(&self.common.actor, self.object.id_unchecked())?;
Ok(())
}
async fn receive(

View file

@ -32,7 +32,7 @@ impl ActivityHandlerNew for AddMod {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
verify_domains_match(&self.target, &self.cc[0])?;
check_is_apub_id_valid(&self.common.actor, false)?;
verify_mod_action(self.common.actor.clone(), self.cc[0].clone(), context).await?;
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
verify_add_remove_moderator_target(&self.target, self.cc[0].clone())
}

View file

@ -1,14 +1,17 @@
use activitystreams::activity::kind::AnnounceType;
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use serde::{Deserialize, Serialize};
use url::Url;
use crate::{
activities::{
comment::{
create::CreateComment,
delete::DeleteComment,
dislike::DislikeComment,
like::LikeComment,
remove::RemoveComment,
undo_delete::UndoDeleteComment,
undo_dislike::UndoDislikeComment,
undo_like::UndoLikeComment,
undo_remove::UndoRemoveComment,
update::UpdateComment,
},
@ -16,48 +19,42 @@ use crate::{
post::{
create::CreatePost,
delete::DeletePost,
dislike::DislikePost,
like::LikePost,
remove::RemovePost,
undo_delete::UndoDeletePost,
undo_dislike::UndoDislikePost,
undo_like::UndoLikePost,
undo_remove::UndoRemovePost,
update::UpdatePost,
},
post_or_comment::{
dislike::DislikePostOrComment,
like::LikePostOrComment,
undo_dislike::UndoDislikePostOrComment,
undo_like::UndoLikePostOrComment,
},
verify_activity,
verify_community,
},
http::is_activity_already_known,
};
use activitystreams::activity::kind::RemoveType;
use lemmy_apub::check_is_apub_id_valid;
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use serde::{Deserialize, Serialize};
use url::Url;
#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandlerNew)]
#[serde(untagged)]
pub enum AnnouncableActivities {
CreateComment(CreateComment),
UpdateComment(UpdateComment),
LikeComment(LikeComment),
DislikeComment(DislikeComment),
UndoLikeComment(UndoLikeComment),
UndoDislikeComment(UndoDislikeComment),
DeleteComment(DeleteComment),
UndoDeleteComment(UndoDeleteComment),
RemoveComment(RemoveComment),
UndoRemoveComment(UndoRemoveComment),
CreatePost(CreatePost),
UpdatePost(UpdatePost),
LikePost(LikePost),
DislikePost(DislikePost),
DeletePost(DeletePost),
UndoDeletePost(UndoDeletePost),
RemovePost(RemovePost),
UndoRemovePost(UndoRemovePost),
UndoLikePost(UndoLikePost),
UndoDislikePost(UndoDislikePost),
LikePostOrComment(LikePostOrComment),
DislikePostOrComment(DislikePostOrComment),
UndoLikePostOrComment(UndoLikePostOrComment),
UndoDislikePostOrComment(UndoDislikePostOrComment),
BlockUserFromCommunity(BlockUserFromCommunity),
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
}
@ -69,7 +66,7 @@ pub struct AnnounceActivity {
object: AnnouncableActivities,
cc: [Url; 1],
#[serde(rename = "type")]
kind: RemoveType,
kind: AnnounceType,
#[serde(flatten)]
common: ActivityCommonFields,
}
@ -81,10 +78,9 @@ impl ActivityHandlerNew for AnnounceActivity {
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
verify_domains_match(&self.common.actor, &self.cc[0])?;
check_is_apub_id_valid(&self.common.actor, false)?;
self.object.verify(context, request_counter).await
verify_activity(self.common())?;
verify_community(&self.common.actor, context, request_counter).await?;
Ok(())
}
async fn receive(

View file

@ -34,7 +34,7 @@ impl ActivityHandlerNew for BlockUserFromCommunity {
async fn verify(&self, context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
check_is_apub_id_valid(&self.common.actor, false)?;
verify_mod_action(self.common.actor.clone(), self.cc[0].clone(), context).await
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await
}
async fn receive(

View file

@ -32,7 +32,7 @@ impl ActivityHandlerNew for RemoveMod {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
verify_domains_match(&self.target, &self.cc[0])?;
check_is_apub_id_valid(&self.common.actor, false)?;
verify_mod_action(self.common.actor.clone(), self.cc[0].clone(), context).await?;
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
verify_add_remove_moderator_target(&self.target, self.cc[0].clone())
}

View file

@ -33,7 +33,7 @@ impl ActivityHandlerNew for UndoBlockUserFromCommunity {
) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
check_is_apub_id_valid(&self.common.actor, false)?;
verify_mod_action(self.common.actor.clone(), self.cc[0].clone(), context).await?;
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
self.object.verify(context, request_counter).await
}

View file

@ -1,12 +1,16 @@
use anyhow::anyhow;
use lemmy_api_common::blocking;
use lemmy_apub::{
check_community_or_site_ban,
check_is_apub_id_valid,
fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person},
};
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields};
use lemmy_db_queries::ApubObject;
use lemmy_db_schema::source::{community::Community, person::Person};
use lemmy_db_schema::{
source::{community::Community, person::Person},
DbUrl,
};
use lemmy_db_views_actor::community_view::CommunityView;
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
@ -16,6 +20,7 @@ pub mod comment;
pub mod community;
pub mod following;
pub mod post;
pub mod post_or_comment;
pub mod private_message;
/// Checks that the specified Url actually identifies a Person (by fetching it), and that the person
@ -32,6 +37,29 @@ async fn verify_person(
Ok(())
}
/// Fetches the person and community to verify their type, then checks if person is banned from site
/// or community.
async fn verify_person_in_community(
person_id: &Url,
cc: &[Url],
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<Community, LemmyError> {
let person = get_or_fetch_and_upsert_person(person_id, context, request_counter).await?;
let mut cc_iter = cc.iter();
let community: Community = loop {
if let Some(cid) = cc_iter.next() {
if let Ok(c) = get_or_fetch_and_upsert_community(cid, context, request_counter).await {
break c;
}
} else {
return Err(anyhow!("No community found in cc").into());
}
};
check_community_or_site_ban(&person, community.id, context.pool()).await?;
Ok(community)
}
/// Simply check that the url actually refers to a valid group.
async fn verify_community(
community_id: &Url,
@ -49,7 +77,7 @@ fn verify_activity(common: &ActivityCommonFields) -> Result<(), LemmyError> {
}
async fn verify_mod_action(
actor_id: Url,
actor_id: &Url,
activity_cc: Url,
context: &LemmyContext,
) -> Result<(), LemmyError> {
@ -59,8 +87,9 @@ async fn verify_mod_action(
.await??;
if community.local {
let actor_id: DbUrl = actor_id.clone().into();
let actor = blocking(context.pool(), move |conn| {
Person::read_from_apub_id(conn, &actor_id.into())
Person::read_from_apub_id(conn, &actor_id)
})
.await??;

View file

@ -1,13 +1,21 @@
use crate::activities::post::send_websocket_message;
use crate::activities::{
post::send_websocket_message,
verify_activity,
verify_person_in_community,
};
use activitystreams::{activity::kind::CreateType, base::BaseExt};
use lemmy_apub::{
check_is_apub_id_valid,
fetcher::person::get_or_fetch_and_upsert_person,
objects::FromApub,
ActorType,
PageExt,
};
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_apub_lib::{
verify_domains_match_opt,
ActivityCommonFields,
ActivityHandlerNew,
PublicUrl,
};
use lemmy_db_schema::source::post::Post;
use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
@ -27,10 +35,15 @@ pub struct CreatePost {
#[async_trait::async_trait(?Send)]
impl ActivityHandlerNew for CreatePost {
async fn verify(&self, _context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
verify_domains_match(self.common.id_unchecked(), &self.common.actor)?;
self.object.id(self.common.actor.as_str())?;
check_is_apub_id_valid(&self.common.actor, false)
async fn verify(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_activity(self.common())?;
verify_person_in_community(&self.common.actor, &self.cc, context, request_counter).await?;
verify_domains_match_opt(&self.common.actor, self.object.id_unchecked())?;
Ok(())
}
async fn receive(

View file

@ -1,46 +0,0 @@
use crate::activities::post::like_or_dislike_post;
use activitystreams::activity::kind::DislikeType;
use lemmy_apub::check_is_apub_id_valid;
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DislikePost {
to: PublicUrl,
pub(in crate::activities::post) object: Url,
cc: [Url; 1],
#[serde(rename = "type")]
kind: DislikeType,
#[serde(flatten)]
common: ActivityCommonFields,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandlerNew for DislikePost {
async fn verify(&self, _context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
check_is_apub_id_valid(&self.common.actor, false)
}
async fn receive(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
like_or_dislike_post(
-1,
&self.common.actor,
&self.object,
context,
request_counter,
)
.await
}
fn common(&self) -> &ActivityCommonFields {
&self.common
}
}

View file

@ -1,30 +1,19 @@
use lemmy_api_common::{blocking, post::PostResponse};
use lemmy_apub::fetcher::{
objects::get_or_fetch_and_insert_post,
person::get_or_fetch_and_upsert_person,
};
use lemmy_db_queries::Likeable;
use lemmy_db_schema::{
source::post::{PostLike, PostLikeForm},
PostId,
};
use lemmy_db_schema::PostId;
use lemmy_db_views::post_view::PostView;
use lemmy_utils::LemmyError;
use lemmy_websocket::{messages::SendPost, LemmyContext, UserOperation};
use url::Url;
use lemmy_websocket::{messages::SendPost, LemmyContext};
pub mod create;
pub mod delete;
pub mod dislike;
pub mod like;
pub mod remove;
pub mod undo_delete;
pub mod undo_dislike;
pub mod undo_like;
pub mod undo_remove;
pub mod update;
async fn send_websocket_message<OP: ToString + Send + lemmy_websocket::OperationType + 'static>(
pub(crate) async fn send_websocket_message<
OP: ToString + Send + lemmy_websocket::OperationType + 'static,
>(
post_id: PostId,
op: OP,
context: &LemmyContext,
@ -44,47 +33,3 @@ async fn send_websocket_message<OP: ToString + Send + lemmy_websocket::Operation
Ok(())
}
async fn like_or_dislike_post(
score: i16,
actor: &Url,
object: &Url,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let actor = get_or_fetch_and_upsert_person(actor, context, request_counter).await?;
let post = get_or_fetch_and_insert_post(object, context, request_counter).await?;
let post_id = post.id;
let like_form = PostLikeForm {
post_id: post.id,
person_id: actor.id,
score,
};
let person_id = actor.id;
blocking(context.pool(), move |conn| {
PostLike::remove(conn, person_id, post_id)?;
PostLike::like(conn, &like_form)
})
.await??;
send_websocket_message(post.id, UserOperation::CreatePostLike, context).await
}
async fn undo_like_or_dislike_post(
actor: &Url,
object: &Url,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let actor = get_or_fetch_and_upsert_person(actor, context, request_counter).await?;
let post = get_or_fetch_and_insert_post(object, context, request_counter).await?;
let post_id = post.id;
let person_id = actor.id;
blocking(context.pool(), move |conn| {
PostLike::remove(conn, person_id, post_id)
})
.await??;
send_websocket_message(post.id, UserOperation::CreatePostLike, context).await
}

View file

@ -26,7 +26,7 @@ impl ActivityHandlerNew for RemovePost {
async fn verify(&self, context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
check_is_apub_id_valid(&self.common.actor, false)?;
verify_mod_action(self.common.actor.clone(), self.cc[0].clone(), context).await
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await
}
async fn receive(

View file

@ -1,50 +0,0 @@
use crate::activities::post::{like::LikePost, undo_like_or_dislike_post};
use activitystreams::activity::kind::UndoType;
use lemmy_apub::check_is_apub_id_valid;
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoLikePost {
to: PublicUrl,
object: LikePost,
cc: [Url; 1],
#[serde(rename = "type")]
kind: UndoType,
#[serde(flatten)]
common: ActivityCommonFields,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandlerNew for UndoLikePost {
async fn verify(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
verify_domains_match(&self.common.actor, &self.object.object)?;
check_is_apub_id_valid(&self.common.actor, false)?;
self.object.verify(context, request_counter).await
}
async fn receive(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
undo_like_or_dislike_post(
&self.common.actor,
&self.object.object,
context,
request_counter,
)
.await
}
fn common(&self) -> &ActivityCommonFields {
&self.common
}
}

View file

@ -33,7 +33,7 @@ impl ActivityHandlerNew for UndoRemovePost {
) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
check_is_apub_id_valid(&self.common.actor, false)?;
verify_mod_action(self.common.actor.clone(), self.cc[0].clone(), context).await?;
verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
self.object.verify(context, request_counter).await
}

View file

@ -1,19 +1,26 @@
use crate::activities::post::send_websocket_message;
use crate::activities::{
post::send_websocket_message,
verify_activity,
verify_mod_action,
verify_person_in_community,
};
use activitystreams::{activity::kind::UpdateType, base::BaseExt};
use anyhow::Context;
use lemmy_api_common::blocking;
use lemmy_apub::{
check_is_apub_id_valid,
objects::{FromApub, FromApubToForm},
ActorType,
PageExt,
};
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_db_queries::{ApubObject, Crud};
use lemmy_apub_lib::{
verify_domains_match_opt,
ActivityCommonFields,
ActivityHandlerNew,
PublicUrl,
};
use lemmy_db_queries::ApubObject;
use lemmy_db_schema::{
source::{
community::Community,
post::{Post, PostForm},
},
source::post::{Post, PostForm},
DbUrl,
};
use lemmy_utils::{location_info, LemmyError};
@ -34,17 +41,16 @@ pub struct UpdatePost {
#[async_trait::async_trait(?Send)]
impl ActivityHandlerNew for UpdatePost {
async fn verify(&self, _context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
self.object.id(self.common.actor.as_str())?;
check_is_apub_id_valid(&self.common.actor, false)
}
async fn receive(
async fn verify(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_activity(self.common())?;
let community =
verify_person_in_community(&self.common.actor, &self.cc, context, request_counter).await?;
verify_domains_match_opt(&self.common.actor, self.object.id_unchecked())?;
let temp_post = PostForm::from_apub(
&self.object,
context,
@ -53,36 +59,32 @@ impl ActivityHandlerNew for UpdatePost {
false,
)
.await?;
let post_id: DbUrl = temp_post.ap_id.context(location_info!())?;
let old_post = blocking(context.pool(), move |conn| {
Post::read_from_apub_id(conn, &post_id)
})
.await??;
// If sticked or locked state was changed, make sure the actor is a mod
let stickied = temp_post.stickied.context(location_info!())?;
let locked = temp_post.locked.context(location_info!())?;
let mut mod_action_allowed = false;
if (stickied != old_post.stickied) || (locked != old_post.locked) {
let community = blocking(context.pool(), move |conn| {
Community::read(conn, old_post.community_id)
})
.await??;
// Only check mod status if the community is local, otherwise we trust that it was sent correctly.
if community.local {
// TODO
//verify_mod_activity(&update, announce, &community, context).await?;
}
mod_action_allowed = true;
verify_mod_action(&self.common.actor, community.actor_id(), context).await?;
}
Ok(())
}
async fn receive(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let post = Post::from_apub(
&self.object,
context,
self.common.actor.clone(),
request_counter,
mod_action_allowed,
// TODO: we already check here if the mod action is valid, can remove that check param
true,
)
.await?;

View file

@ -1,16 +1,19 @@
use crate::activities::comment::like_or_dislike_comment;
use crate::activities::{
post_or_comment::voting::receive_like_or_dislike,
verify_activity,
verify_person_in_community,
};
use activitystreams::activity::kind::DislikeType;
use lemmy_apub::check_is_apub_id_valid;
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DislikeComment {
pub struct DislikePostOrComment {
to: PublicUrl,
pub(in crate::activities::comment) object: Url,
pub(in crate::activities) object: Url,
cc: [Url; 1],
#[serde(rename = "type")]
kind: DislikeType,
@ -19,10 +22,15 @@ pub struct DislikeComment {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandlerNew for DislikeComment {
async fn verify(&self, _context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
check_is_apub_id_valid(&self.common.actor, false)
impl ActivityHandlerNew for DislikePostOrComment {
async fn verify(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_activity(self.common())?;
verify_person_in_community(&self.common.actor, &self.cc, context, request_counter).await?;
Ok(())
}
async fn receive(
@ -30,7 +38,7 @@ impl ActivityHandlerNew for DislikeComment {
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
like_or_dislike_comment(
receive_like_or_dislike(
-1,
&self.common.actor,
&self.object,

View file

@ -1,16 +1,19 @@
use crate::activities::post::like_or_dislike_post;
use crate::activities::{
post_or_comment::voting::receive_like_or_dislike,
verify_activity,
verify_person_in_community,
};
use activitystreams::activity::kind::LikeType;
use lemmy_apub::check_is_apub_id_valid;
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LikePost {
pub struct LikePostOrComment {
to: PublicUrl,
pub(in crate::activities::post) object: Url,
pub(in crate::activities::post_or_comment) object: Url,
cc: [Url; 1],
#[serde(rename = "type")]
kind: LikeType,
@ -19,10 +22,15 @@ pub struct LikePost {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandlerNew for LikePost {
async fn verify(&self, _context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
check_is_apub_id_valid(&self.common.actor, false)
impl ActivityHandlerNew for LikePostOrComment {
async fn verify(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_activity(self.common())?;
verify_person_in_community(&self.common.actor, &self.cc, context, request_counter).await?;
Ok(())
}
async fn receive(
@ -30,7 +38,7 @@ impl ActivityHandlerNew for LikePost {
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
like_or_dislike_post(
receive_like_or_dislike(
1,
&self.common.actor,
&self.object,

View file

@ -0,0 +1,5 @@
pub mod dislike;
pub mod like;
pub mod undo_dislike;
pub mod undo_like;
mod voting;

View file

@ -1,16 +1,19 @@
use crate::activities::post::{dislike::DislikePost, undo_like_or_dislike_post};
use crate::activities::{
post_or_comment::{dislike::DislikePostOrComment, voting::receive_undo_like_or_dislike},
verify_activity,
verify_person_in_community,
};
use activitystreams::activity::kind::UndoType;
use lemmy_apub::check_is_apub_id_valid;
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_apub_lib::{verify_urls_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoDislikePost {
pub struct UndoDislikePostOrComment {
to: PublicUrl,
object: DislikePost,
object: DislikePostOrComment,
cc: [Url; 1],
#[serde(rename = "type")]
kind: UndoType,
@ -19,16 +22,17 @@ pub struct UndoDislikePost {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandlerNew for UndoDislikePost {
impl ActivityHandlerNew for UndoDislikePostOrComment {
async fn verify(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
verify_domains_match(&self.common.actor, &self.object.object)?;
check_is_apub_id_valid(&self.common.actor, false)?;
self.object.verify(context, request_counter).await
verify_activity(self.common())?;
verify_person_in_community(&self.common.actor, &self.cc, context, request_counter).await?;
verify_urls_match(&self.common.actor, &self.object.common().actor)?;
self.object.verify(context, request_counter).await?;
Ok(())
}
async fn receive(
@ -36,7 +40,7 @@ impl ActivityHandlerNew for UndoDislikePost {
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
undo_like_or_dislike_post(
receive_undo_like_or_dislike(
&self.common.actor,
&self.object.object,
context,

View file

@ -1,16 +1,19 @@
use crate::activities::comment::{like::LikeComment, undo_like_or_dislike_comment};
use crate::activities::{
post_or_comment::{like::LikePostOrComment, voting::receive_undo_like_or_dislike},
verify_activity,
verify_person_in_community,
};
use activitystreams::activity::kind::UndoType;
use lemmy_apub::check_is_apub_id_valid;
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_apub_lib::{verify_urls_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoLikeComment {
pub struct UndoLikePostOrComment {
to: PublicUrl,
object: LikeComment,
object: LikePostOrComment,
cc: [Url; 1],
#[serde(rename = "type")]
kind: UndoType,
@ -19,16 +22,17 @@ pub struct UndoLikeComment {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandlerNew for UndoLikeComment {
impl ActivityHandlerNew for UndoLikePostOrComment {
async fn verify(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_domains_match(&self.common.actor, self.common.id_unchecked())?;
verify_domains_match(&self.common.actor, &self.object.object)?;
check_is_apub_id_valid(&self.common.actor, false)?;
self.object.verify(context, request_counter).await
verify_activity(self.common())?;
verify_person_in_community(&self.common.actor, &self.cc, context, request_counter).await?;
verify_urls_match(&self.common.actor, &self.object.common().actor)?;
self.object.verify(context, request_counter).await?;
Ok(())
}
async fn receive(
@ -36,7 +40,7 @@ impl ActivityHandlerNew for UndoLikeComment {
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
undo_like_or_dislike_comment(
receive_undo_like_or_dislike(
&self.common.actor,
&self.object.object,
context,

View file

@ -0,0 +1,152 @@
use crate::activities::{
comment::send_websocket_message as send_comment_websocket_message,
post::send_websocket_message as send_post_websocket_message,
};
use lemmy_api_common::blocking;
use lemmy_apub::{
fetcher::{
objects::get_or_fetch_and_insert_post_or_comment,
person::get_or_fetch_and_upsert_person,
},
PostOrComment,
};
use lemmy_db_queries::Likeable;
use lemmy_db_schema::source::{
comment::{Comment, CommentLike, CommentLikeForm},
post::{Post, PostLike, PostLikeForm},
};
use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperation};
use std::ops::Deref;
use url::Url;
pub(in crate::activities::post_or_comment) async fn receive_like_or_dislike(
score: i16,
actor: &Url,
object: &Url,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
match get_or_fetch_and_insert_post_or_comment(object, context, request_counter).await? {
PostOrComment::Post(p) => {
like_or_dislike_post(score, actor, p.deref(), context, request_counter).await
}
PostOrComment::Comment(c) => {
like_or_dislike_comment(score, actor, c.deref(), context, request_counter).await
}
}
}
async fn like_or_dislike_comment(
score: i16,
actor: &Url,
comment: &Comment,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let actor = get_or_fetch_and_upsert_person(actor, context, request_counter).await?;
let comment_id = comment.id;
let like_form = CommentLikeForm {
comment_id,
post_id: comment.post_id,
person_id: actor.id,
score,
};
let person_id = actor.id;
blocking(context.pool(), move |conn| {
CommentLike::remove(conn, person_id, comment_id)?;
CommentLike::like(conn, &like_form)
})
.await??;
send_comment_websocket_message(
comment_id,
vec![],
UserOperation::CreateCommentLike,
context,
)
.await
}
async fn like_or_dislike_post(
score: i16,
actor: &Url,
post: &Post,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let actor = get_or_fetch_and_upsert_person(actor, context, request_counter).await?;
let post_id = post.id;
let like_form = PostLikeForm {
post_id: post.id,
person_id: actor.id,
score,
};
let person_id = actor.id;
blocking(context.pool(), move |conn| {
PostLike::remove(conn, person_id, post_id)?;
PostLike::like(conn, &like_form)
})
.await??;
send_post_websocket_message(post.id, UserOperation::CreatePostLike, context).await
}
pub(in crate::activities::post_or_comment) async fn receive_undo_like_or_dislike(
actor: &Url,
object: &Url,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
match get_or_fetch_and_insert_post_or_comment(object, context, request_counter).await? {
PostOrComment::Post(p) => {
undo_like_or_dislike_post(actor, p.deref(), context, request_counter).await
}
PostOrComment::Comment(c) => {
undo_like_or_dislike_comment(actor, c.deref(), context, request_counter).await
}
}
}
async fn undo_like_or_dislike_comment(
actor: &Url,
comment: &Comment,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let actor = get_or_fetch_and_upsert_person(actor, context, request_counter).await?;
let comment_id = comment.id;
let person_id = actor.id;
blocking(context.pool(), move |conn| {
CommentLike::remove(conn, person_id, comment_id)
})
.await??;
send_comment_websocket_message(
comment.id,
vec![],
UserOperation::CreateCommentLike,
context,
)
.await
}
async fn undo_like_or_dislike_post(
actor: &Url,
post: &Post,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let actor = get_or_fetch_and_upsert_person(actor, context, request_counter).await?;
let post_id = post.id;
let person_id = actor.id;
blocking(context.pool(), move |conn| {
PostLike::remove(conn, person_id, post_id)
})
.await??;
send_post_websocket_message(post.id, UserOperation::CreatePostLike, context).await
}

View file

@ -2,12 +2,8 @@ use crate::activities::{
comment::{
create::CreateComment,
delete::DeleteComment,
dislike::DislikeComment,
like::LikeComment,
remove::RemoveComment,
undo_delete::UndoDeleteComment,
undo_dislike::UndoDislikeComment,
undo_like::UndoLikeComment,
undo_remove::UndoRemoveComment,
update::UpdateComment,
},
@ -27,15 +23,17 @@ use crate::activities::{
post::{
create::CreatePost,
delete::DeletePost,
dislike::DislikePost,
like::LikePost,
remove::RemovePost,
undo_delete::UndoDeletePost,
undo_dislike::UndoDislikePost,
undo_like::UndoLikePost,
undo_remove::UndoRemovePost,
update::UpdatePost,
},
post_or_comment::{
dislike::DislikePostOrComment,
like::LikePostOrComment,
undo_dislike::UndoDislikePostOrComment,
undo_like::UndoLikePostOrComment,
},
private_message::{
create::CreatePrivateMessage,
delete::DeletePrivateMessage,
@ -66,24 +64,20 @@ pub enum GroupInboxActivities {
UndoFollowCommunity(UndoFollowCommunity),
CreateComment(CreateComment),
UpdateComment(UpdateComment),
LikeComment(LikeComment),
DislikeComment(DislikeComment),
UndoLikeComment(UndoLikeComment),
UndoDislikeComment(UndoDislikeComment),
DeleteComment(DeleteComment),
UndoDeleteComment(UndoDeleteComment),
RemoveComment(RemoveComment),
UndoRemoveComment(UndoRemoveComment),
CreatePost(CreatePost),
UpdatePost(UpdatePost),
LikePost(LikePost),
DislikePost(DislikePost),
DeletePost(DeletePost),
UndoDeletePost(UndoDeletePost),
RemovePost(RemovePost),
UndoRemovePost(UndoRemovePost),
UndoLikePost(UndoLikePost),
UndoDislikePost(UndoDislikePost),
LikePostOrComment(LikePostOrComment),
DislikePostOrComment(DislikePostOrComment),
UndoLikePostOrComment(UndoLikePostOrComment),
UndoDislikePostOrComment(UndoDislikePostOrComment),
UpdateCommunity(Box<UpdateCommunity>),
DeleteCommunity(DeleteCommunity),
RemoveCommunity(RemoveCommunity),
@ -98,36 +92,25 @@ pub enum GroupInboxActivities {
#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandlerNew)]
#[serde(untagged)]
pub enum SharedInboxActivities {
// received by person
AcceptFollowCommunity(AcceptFollowCommunity),
CreatePrivateMessage(CreatePrivateMessage),
UpdatePrivateMessage(UpdatePrivateMessage),
DeletePrivateMessage(DeletePrivateMessage),
UndoDeletePrivateMessage(UndoDeletePrivateMessage),
AnnounceActivity(Box<AnnounceActivity>),
// received by group
FollowCommunity(FollowCommunity),
UndoFollowCommunity(UndoFollowCommunity),
CreateComment(CreateComment),
UpdateComment(UpdateComment),
LikeComment(LikeComment),
DislikeComment(DislikeComment),
UndoLikeComment(UndoLikeComment),
UndoDislikeComment(UndoDislikeComment),
DeleteComment(DeleteComment),
UndoDeleteComment(UndoDeleteComment),
RemoveComment(RemoveComment),
UndoRemoveComment(UndoRemoveComment),
CreatePost(CreatePost),
UpdatePost(UpdatePost),
LikePost(LikePost),
DislikePost(DislikePost),
DeletePost(DeletePost),
UndoDeletePost(UndoDeletePost),
RemovePost(RemovePost),
UndoRemovePost(UndoRemovePost),
UndoLikePost(UndoLikePost),
UndoDislikePost(UndoDislikePost),
LikePostOrComment(LikePostOrComment),
DislikePostOrComment(DislikePostOrComment),
UndoDislikePostOrComment(UndoDislikePostOrComment),
UndoLikePostOrComment(UndoLikePostOrComment),
UpdateCommunity(Box<UpdateCommunity>),
DeleteCommunity(DeleteCommunity),
RemoveCommunity(RemoveCommunity),
@ -137,4 +120,13 @@ pub enum SharedInboxActivities {
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
AddMod(AddMod),
RemoveMod(RemoveMod),
// received by person
AcceptFollowCommunity(AcceptFollowCommunity),
// Note, pm activities need to be at the end, otherwise comments will end up here. We can probably
// avoid this problem by replacing createpm.object with our own struct, instead of NoteExt.
CreatePrivateMessage(CreatePrivateMessage),
UpdatePrivateMessage(UpdatePrivateMessage),
DeletePrivateMessage(DeletePrivateMessage),
UndoDeletePrivateMessage(UndoDeletePrivateMessage),
AnnounceActivity(Box<AnnounceActivity>),
}

View file

@ -1,7 +1,4 @@
use crate::activities::{
following::accept::AcceptFollowCommunity,
post::{create::CreatePost, like::LikePost},
};
use crate::http::inbox_enums::SharedInboxActivities;
use actix_web::{
body::Body,
web,
@ -20,12 +17,11 @@ use lemmy_apub::{
insert_activity,
APUB_JSON_CONTENT_TYPE,
};
use lemmy_apub_lib::{ActivityCommonFields, ActivityHandlerNew};
use lemmy_apub_lib::ActivityHandlerNew;
use lemmy_db_queries::{source::activity::Activity_, DbPool};
use lemmy_db_schema::source::activity::Activity;
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
use lemmy_websocket::LemmyContext;
use log::debug;
use serde::{Deserialize, Serialize};
use std::{fmt::Debug, io::Read};
use url::Url;
@ -36,21 +32,13 @@ pub mod inbox_enums;
pub mod person;
pub mod post;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ActivityHandlerNew)]
#[serde(untagged)]
enum Ac {
CreatePost(CreatePost),
LikePost(LikePost),
AcceptFollowCommunity(AcceptFollowCommunity),
}
pub async fn shared_inbox(
request: HttpRequest,
payload: Payload,
context: web::Data<LemmyContext>,
) -> Result<HttpResponse, LemmyError> {
let unparsed = payload_to_string(payload).await?;
receive_activity::<Ac>(request, &unparsed, context).await
receive_activity::<SharedInboxActivities>(request, &unparsed, context).await
}
async fn payload_to_string(mut payload: Payload) -> Result<String, LemmyError> {
@ -70,22 +58,23 @@ async fn receive_activity<'a, T>(
where
T: ActivityHandlerNew + Clone + Deserialize<'a> + Serialize + std::fmt::Debug + Send + 'static,
{
debug!("Received activity {}", activity);
let activity = serde_json::from_str::<T>(activity)?;
let activity = serde_json::from_str::<T>(activity);
dbg!(&activity);
let activity = activity?;
let activity_data = activity.common();
// TODO: which order to check things?
// Do nothing if we received the same activity before
if is_activity_already_known(context.pool(), activity_data.id_unchecked()).await? {
return Ok(HttpResponse::Ok().finish());
}
assert_activity_not_local(&activity)?;
check_is_apub_id_valid(&activity_data.actor, false)?;
let request_counter = &mut 0;
let actor =
get_or_fetch_and_upsert_actor(&activity_data.actor, &context, request_counter).await?;
verify_signature(&request, &actor.public_key().context(location_info!())?)?;
activity.verify(&context, request_counter).await?;
assert_activity_not_local(&activity)?;
check_is_apub_id_valid(&activity_data.actor, false)?;
// Log the activity, so we avoid receiving and parsing it twice. Note that this could still happen
// if we receive the same activity twice in very quick succession.

View file

@ -8,8 +8,8 @@ for ((i=0; i < times; i++)) ; do
echo "cargo clean"
# to benchmark incremental compilation time, do a full build with the same compiler version first,
# and use the following clean command:
#cargo clean -p lemmy_utils
cargo clean
cargo clean -p lemmy_utils
#cargo clean
echo "cargo build"
start=$(date +%s.%N)
RUSTC_WRAPPER='' cargo build -q