mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-12-23 11:21:32 +00:00
Remove ActivityFields trait, deserialize into another struct instead
This commit is contained in:
parent
969a7f2d1b
commit
bd3352423a
49 changed files with 344 additions and 340 deletions
|
@ -1,18 +1,3 @@
|
|||
use activitystreams::public;
|
||||
|
||||
use lemmy_api_common::{blocking, check_post_deleted_or_removed};
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
traits::{ActivityHandler, ActorType, ApubObject},
|
||||
verify::verify_domains_match,
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{community::Community, post::Post},
|
||||
traits::Crud,
|
||||
};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
|
||||
|
||||
use crate::{
|
||||
activities::{
|
||||
check_community_deleted_or_removed,
|
||||
|
@ -28,6 +13,19 @@ use crate::{
|
|||
objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson},
|
||||
protocol::activities::{create_or_update::comment::CreateOrUpdateComment, CreateOrUpdateType},
|
||||
};
|
||||
use activitystreams::public;
|
||||
use lemmy_api_common::{blocking, check_post_deleted_or_removed};
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
traits::{ActivityHandler, ActorType, ApubObject},
|
||||
verify::verify_domains_match,
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{community::Community, post::Post},
|
||||
traits::Crud,
|
||||
};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
|
||||
|
||||
impl CreateOrUpdateComment {
|
||||
pub async fn send(
|
||||
|
@ -81,7 +79,7 @@ impl ActivityHandler for CreateOrUpdateComment {
|
|||
let post = self.object.get_parents(context, request_counter).await?.0;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
|
||||
verify_domains_match(self.actor.inner(), self.object.id.inner())?;
|
||||
check_community_deleted_or_removed(&community)?;
|
||||
|
|
|
@ -65,7 +65,7 @@ impl ActivityHandler for AddMod {
|
|||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
|
||||
verify_mod_action(&self.actor, &community, context, request_counter).await?;
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
activities::{generate_activity_id, send_lemmy_activity, verify_activity, verify_is_public},
|
||||
activity_lists::AnnouncableActivities,
|
||||
fetcher::object_id::ObjectId,
|
||||
http::is_activity_already_known,
|
||||
http::{is_activity_already_known, ActivityCommonFields},
|
||||
insert_activity,
|
||||
objects::community::ApubCommunity,
|
||||
protocol::activities::community::announce::AnnounceActivity,
|
||||
|
@ -10,7 +10,7 @@ use crate::{
|
|||
use activitystreams::{activity::kind::AnnounceType, public};
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||
traits::{ActivityHandler, ActorType},
|
||||
};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
|
@ -60,7 +60,7 @@ impl ActivityHandler for AnnounceActivity {
|
|||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
self.object.verify(context, request_counter).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -70,11 +70,15 @@ impl ActivityHandler for AnnounceActivity {
|
|||
context: &Data<LemmyContext>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
if is_activity_already_known(context.pool(), self.object.id_unchecked()).await? {
|
||||
// TODO: this is pretty ugly, but i cant think of a much better way
|
||||
let object = serde_json::to_string(&self.object)?;
|
||||
let object_data: ActivityCommonFields = serde_json::from_str(&object)?;
|
||||
|
||||
if is_activity_already_known(context.pool(), &object_data.id).await? {
|
||||
return Ok(());
|
||||
}
|
||||
insert_activity(
|
||||
self.object.id_unchecked(),
|
||||
&object_data.id,
|
||||
self.object.clone(),
|
||||
false,
|
||||
true,
|
||||
|
|
|
@ -76,7 +76,7 @@ impl ActivityHandler for BlockUserFromCommunity {
|
|||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
|
||||
verify_mod_action(&self.actor, &community, context, request_counter).await?;
|
||||
|
|
|
@ -64,7 +64,7 @@ impl ActivityHandler for RemoveMod {
|
|||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
|
||||
verify_mod_action(&self.actor, &community, context, request_counter).await?;
|
||||
|
|
|
@ -1,5 +1,16 @@
|
|||
use crate::{
|
||||
activities::{
|
||||
generate_activity_id,
|
||||
send_lemmy_activity,
|
||||
verify_activity,
|
||||
verify_person_in_community,
|
||||
},
|
||||
fetcher::object_id::ObjectId,
|
||||
objects::{community::ApubCommunity, person::ApubPerson},
|
||||
protocol::activities::community::report::Report,
|
||||
PostOrComment,
|
||||
};
|
||||
use activitystreams::activity::kind::FlagType;
|
||||
|
||||
use lemmy_api_common::{blocking, comment::CommentReportResponse, post::PostReportResponse};
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
|
@ -16,19 +27,6 @@ use lemmy_db_views::{comment_report_view::CommentReportView, post_report_view::P
|
|||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};
|
||||
|
||||
use crate::{
|
||||
activities::{
|
||||
generate_activity_id,
|
||||
send_lemmy_activity,
|
||||
verify_activity,
|
||||
verify_person_in_community,
|
||||
},
|
||||
fetcher::object_id::ObjectId,
|
||||
objects::{community::ApubCommunity, person::ApubPerson},
|
||||
protocol::activities::community::report::Report,
|
||||
PostOrComment,
|
||||
};
|
||||
|
||||
impl Report {
|
||||
pub async fn send(
|
||||
object_id: ObjectId<PostOrComment>,
|
||||
|
@ -72,7 +70,7 @@ impl ActivityHandler for Report {
|
|||
context: &Data<LemmyContext>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
let community = self.to[0].dereference(context, request_counter).await?;
|
||||
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
|
||||
Ok(())
|
||||
|
|
|
@ -66,7 +66,7 @@ impl ActivityHandler for UndoBlockUserFromCommunity {
|
|||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
|
||||
verify_mod_action(&self.actor, &community, context, request_counter).await?;
|
||||
|
|
|
@ -59,7 +59,7 @@ impl ActivityHandler for UpdateCommunity {
|
|||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
|
||||
verify_mod_action(&self.actor, &community, context, request_counter).await?;
|
||||
|
|
|
@ -1,7 +1,22 @@
|
|||
use crate::{
|
||||
activities::{
|
||||
community::{announce::GetCommunity, send_to_community},
|
||||
deletion::{
|
||||
receive_delete_action,
|
||||
verify_delete_activity,
|
||||
DeletableObjects,
|
||||
},
|
||||
generate_activity_id,
|
||||
verify_activity,
|
||||
verify_is_public,
|
||||
},
|
||||
activity_lists::AnnouncableActivities,
|
||||
fetcher::object_id::ObjectId,
|
||||
objects::{community::ApubCommunity, person::ApubPerson},
|
||||
protocol::activities::deletion::delete::Delete,
|
||||
};
|
||||
use activitystreams::{activity::kind::DeleteType, public};
|
||||
use anyhow::anyhow;
|
||||
use url::Url;
|
||||
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
|
@ -29,20 +44,7 @@ use lemmy_websocket::{
|
|||
LemmyContext,
|
||||
UserOperationCrud,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
activities::{
|
||||
community::{announce::GetCommunity, send_to_community},
|
||||
deletion::{receive_delete_action, verify_delete_activity, DeletableObjects},
|
||||
generate_activity_id,
|
||||
verify_activity,
|
||||
verify_is_public,
|
||||
},
|
||||
activity_lists::AnnouncableActivities,
|
||||
fetcher::object_id::ObjectId,
|
||||
objects::{community::ApubCommunity, person::ApubPerson},
|
||||
protocol::activities::deletion::delete::Delete,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for Delete {
|
||||
|
@ -53,11 +55,11 @@ impl ActivityHandler for Delete {
|
|||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
verify_delete_activity(
|
||||
&self.object,
|
||||
self,
|
||||
&self.actor,
|
||||
&community,
|
||||
self.summary.is_some(),
|
||||
context,
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
activities::{verify_mod_action, verify_person_in_community},
|
||||
fetcher::object_id::ObjectId,
|
||||
objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost},
|
||||
protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete},
|
||||
};
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
traits::{ActivityFields, ActorType, ApubObject},
|
||||
traits::{ActorType, ApubObject},
|
||||
verify::verify_domains_match,
|
||||
};
|
||||
use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post};
|
||||
|
@ -12,13 +16,7 @@ use lemmy_websocket::{
|
|||
LemmyContext,
|
||||
UserOperationCrud,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
activities::{verify_mod_action, verify_person_in_community},
|
||||
fetcher::object_id::ObjectId,
|
||||
objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost},
|
||||
protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete},
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
pub mod delete;
|
||||
pub mod undo_delete;
|
||||
|
@ -80,27 +78,26 @@ impl DeletableObjects {
|
|||
|
||||
pub(in crate::activities) async fn verify_delete_activity(
|
||||
object: &Url,
|
||||
activity: &dyn ActivityFields,
|
||||
actor: &ObjectId<ApubPerson>,
|
||||
community: &ApubCommunity,
|
||||
is_mod_action: bool,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let object = DeletableObjects::read_from_db(object, context).await?;
|
||||
let actor = ObjectId::new(activity.actor().clone());
|
||||
match object {
|
||||
DeletableObjects::Community(community) => {
|
||||
if community.local {
|
||||
// can only do this check for local community, in remote case it would try to fetch the
|
||||
// deleted community (which fails)
|
||||
verify_person_in_community(&actor, &community, context, request_counter).await?;
|
||||
verify_person_in_community(actor, &community, context, request_counter).await?;
|
||||
}
|
||||
// community deletion is always a mod (or admin) action
|
||||
verify_mod_action(&actor, &community, context, request_counter).await?;
|
||||
verify_mod_action(actor, &community, context, request_counter).await?;
|
||||
}
|
||||
DeletableObjects::Post(p) => {
|
||||
verify_delete_activity_post_or_comment(
|
||||
activity,
|
||||
actor,
|
||||
&p.ap_id.clone().into(),
|
||||
community,
|
||||
is_mod_action,
|
||||
|
@ -111,7 +108,7 @@ pub(in crate::activities) async fn verify_delete_activity(
|
|||
}
|
||||
DeletableObjects::Comment(c) => {
|
||||
verify_delete_activity_post_or_comment(
|
||||
activity,
|
||||
actor,
|
||||
&c.ap_id.clone().into(),
|
||||
community,
|
||||
is_mod_action,
|
||||
|
@ -125,20 +122,19 @@ pub(in crate::activities) async fn verify_delete_activity(
|
|||
}
|
||||
|
||||
async fn verify_delete_activity_post_or_comment(
|
||||
activity: &dyn ActivityFields,
|
||||
actor: &ObjectId<ApubPerson>,
|
||||
object_id: &Url,
|
||||
community: &ApubCommunity,
|
||||
is_mod_action: bool,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let actor = ObjectId::new(activity.actor().clone());
|
||||
verify_person_in_community(&actor, community, context, request_counter).await?;
|
||||
verify_person_in_community(actor, community, context, request_counter).await?;
|
||||
if is_mod_action {
|
||||
verify_mod_action(&actor, community, context, request_counter).await?;
|
||||
verify_mod_action(actor, community, context, request_counter).await?;
|
||||
} else {
|
||||
// domain of post ap_id and post.creator ap_id are identical, so we just check the former
|
||||
verify_domains_match(activity.actor(), object_id)?;
|
||||
verify_domains_match(actor.inner(), object_id)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,20 +1,3 @@
|
|||
use activitystreams::{activity::kind::UndoType, public};
|
||||
use anyhow::anyhow;
|
||||
use url::Url;
|
||||
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
traits::{ActivityHandler, ActorType},
|
||||
};
|
||||
use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::{
|
||||
send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
|
||||
LemmyContext,
|
||||
UserOperationCrud,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
activities::{
|
||||
community::{announce::GetCommunity, send_to_community},
|
||||
|
@ -28,6 +11,21 @@ use crate::{
|
|||
objects::{community::ApubCommunity, person::ApubPerson},
|
||||
protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete},
|
||||
};
|
||||
use activitystreams::{activity::kind::UndoType, public};
|
||||
use anyhow::anyhow;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
traits::{ActivityHandler, ActorType},
|
||||
};
|
||||
use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::{
|
||||
send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
|
||||
LemmyContext,
|
||||
UserOperationCrud,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for UndoDelete {
|
||||
|
@ -38,12 +36,12 @@ impl ActivityHandler for UndoDelete {
|
|||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
self.object.verify(context, request_counter).await?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
verify_delete_activity(
|
||||
&self.object.object,
|
||||
self,
|
||||
&self.actor,
|
||||
&community,
|
||||
self.object.summary.is_some(),
|
||||
context,
|
||||
|
|
|
@ -7,7 +7,7 @@ use activitystreams::activity::kind::AcceptType;
|
|||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||
traits::{ActivityHandler, ActorType},
|
||||
verify::verify_urls_match,
|
||||
};
|
||||
use lemmy_db_schema::{source::community::CommunityFollower, traits::Followable};
|
||||
|
@ -51,9 +51,9 @@ impl ActivityHandler for AcceptFollowCommunity {
|
|||
context: &Data<LemmyContext>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_urls_match(self.to[0].inner(), self.object.actor())?;
|
||||
verify_urls_match(self.actor(), self.object.to[0].inner())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
verify_urls_match(self.to[0].inner(), self.object.actor.inner())?;
|
||||
verify_urls_match(self.actor.inner(), self.object.to[0].inner())?;
|
||||
self.object.verify(context, request_counter).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ impl ActivityHandler for FollowCommunity {
|
|||
context: &Data<LemmyContext>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
verify_urls_match(self.to[0].inner(), self.object.inner())?;
|
||||
verify_person(&self.actor, context, request_counter).await?;
|
||||
let community = self.to[0].dereference(context, request_counter).await?;
|
||||
|
|
|
@ -8,7 +8,7 @@ use activitystreams::activity::kind::UndoType;
|
|||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||
traits::{ActivityHandler, ActorType},
|
||||
verify::verify_urls_match,
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
|
@ -49,9 +49,9 @@ impl ActivityHandler for UndoFollowCommunity {
|
|||
context: &Data<LemmyContext>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
verify_urls_match(self.to[0].inner(), self.object.object.inner())?;
|
||||
verify_urls_match(self.actor(), self.object.actor())?;
|
||||
verify_urls_match(self.actor.inner(), self.object.actor.inner())?;
|
||||
verify_person(&self.actor, context, request_counter).await?;
|
||||
self.object.verify(context, request_counter).await?;
|
||||
Ok(())
|
||||
|
|
|
@ -11,7 +11,7 @@ use anyhow::anyhow;
|
|||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
activity_queue::send_activity,
|
||||
traits::{ActivityFields, ActorType},
|
||||
traits::ActorType,
|
||||
verify::verify_domains_match,
|
||||
};
|
||||
use lemmy_db_schema::source::community::Community;
|
||||
|
@ -71,9 +71,9 @@ pub(crate) async fn verify_person_in_community(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn verify_activity(activity: &dyn ActivityFields, settings: &Settings) -> Result<(), LemmyError> {
|
||||
check_is_apub_id_valid(activity.actor(), false, settings)?;
|
||||
verify_domains_match(activity.id_unchecked(), activity.actor())?;
|
||||
fn verify_activity(id: &Url, actor: &Url, settings: &Settings) -> Result<(), LemmyError> {
|
||||
check_is_apub_id_valid(actor, false, settings)?;
|
||||
verify_domains_match(id, actor)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,3 @@
|
|||
use activitystreams::public;
|
||||
use anyhow::anyhow;
|
||||
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
traits::{ActivityFields, ActivityHandler, ActorType, ApubObject},
|
||||
verify::{verify_domains_match, verify_urls_match},
|
||||
};
|
||||
use lemmy_db_schema::{source::community::Community, traits::Crud};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
|
||||
|
||||
use crate::{
|
||||
activities::{
|
||||
check_community_deleted_or_removed,
|
||||
|
@ -26,6 +13,17 @@ use crate::{
|
|||
objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost},
|
||||
protocol::activities::{create_or_update::post::CreateOrUpdatePost, CreateOrUpdateType},
|
||||
};
|
||||
use activitystreams::public;
|
||||
use anyhow::anyhow;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
traits::{ActivityHandler, ActorType, ApubObject},
|
||||
verify::{verify_domains_match, verify_urls_match},
|
||||
};
|
||||
use lemmy_db_schema::{source::community::Community, traits::Crud};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
|
||||
|
||||
impl CreateOrUpdatePost {
|
||||
pub(crate) async fn new(
|
||||
|
@ -77,7 +75,7 @@ impl ActivityHandler for CreateOrUpdatePost {
|
|||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
|
||||
check_community_deleted_or_removed(&community)?;
|
||||
|
@ -85,7 +83,7 @@ impl ActivityHandler for CreateOrUpdatePost {
|
|||
match self.kind {
|
||||
CreateOrUpdateType::Create => {
|
||||
verify_domains_match(self.actor.inner(), self.object.id.inner())?;
|
||||
verify_urls_match(self.actor(), self.object.attributed_to.inner())?;
|
||||
verify_urls_match(self.actor.inner(), self.object.attributed_to.inner())?;
|
||||
// Check that the post isnt locked or stickied, as that isnt possible for newly created posts.
|
||||
// However, when fetching a remote post we generate a new create activity with the current
|
||||
// locked/stickied value, so this check may fail. So only check if its a local community,
|
||||
|
@ -102,7 +100,7 @@ impl ActivityHandler for CreateOrUpdatePost {
|
|||
verify_mod_action(&self.actor, &community, context, request_counter).await?;
|
||||
} else {
|
||||
verify_domains_match(self.actor.inner(), self.object.id.inner())?;
|
||||
verify_urls_match(self.actor(), self.object.attributed_to.inner())?;
|
||||
verify_urls_match(self.actor.inner(), self.object.attributed_to.inner())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage {
|
|||
context: &Data<LemmyContext>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
verify_person(&self.actor, context, request_counter).await?;
|
||||
verify_domains_match(self.actor.inner(), self.object.id.inner())?;
|
||||
self.object.verify(context, request_counter).await?;
|
||||
|
|
|
@ -62,7 +62,7 @@ impl ActivityHandler for DeletePrivateMessage {
|
|||
context: &Data<LemmyContext>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
verify_person(&self.actor, context, request_counter).await?;
|
||||
verify_domains_match(self.actor.inner(), self.object.inner())?;
|
||||
Ok(())
|
||||
|
|
|
@ -11,7 +11,7 @@ use activitystreams::activity::kind::UndoType;
|
|||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||
traits::{ActivityHandler, ActorType},
|
||||
verify::{verify_domains_match, verify_urls_match},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
|
@ -59,10 +59,10 @@ impl ActivityHandler for UndoDeletePrivateMessage {
|
|||
context: &Data<LemmyContext>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
verify_person(&self.actor, context, request_counter).await?;
|
||||
verify_urls_match(self.actor(), self.object.actor())?;
|
||||
verify_domains_match(self.actor(), self.object.object.inner())?;
|
||||
verify_urls_match(self.actor.inner(), self.object.actor.inner())?;
|
||||
verify_domains_match(self.actor.inner(), self.object.object.inner())?;
|
||||
self.object.verify(context, request_counter).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,17 +1,3 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use activitystreams::{activity::kind::UndoType, public};
|
||||
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||
verify::verify_urls_match,
|
||||
};
|
||||
use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
use crate::{
|
||||
activities::{
|
||||
community::{announce::GetCommunity, send_to_community},
|
||||
|
@ -30,6 +16,17 @@ use crate::{
|
|||
},
|
||||
PostOrComment,
|
||||
};
|
||||
use activitystreams::{activity::kind::UndoType, public};
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
traits::{ActivityHandler, ActorType},
|
||||
verify::verify_urls_match,
|
||||
};
|
||||
use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use std::ops::Deref;
|
||||
|
||||
impl UndoVote {
|
||||
pub async fn send(
|
||||
|
@ -73,10 +70,10 @@ impl ActivityHandler for UndoVote {
|
|||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
|
||||
verify_urls_match(self.actor(), self.object.actor())?;
|
||||
verify_urls_match(self.actor.inner(), self.object.actor.inner())?;
|
||||
self.object.verify(context, request_counter).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,20 +1,3 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use activitystreams::public;
|
||||
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
traits::{ActivityHandler, ActorType},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::CommunityId,
|
||||
source::{community::Community, post::Post},
|
||||
traits::Crud,
|
||||
};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
use crate::{
|
||||
activities::{
|
||||
community::{announce::GetCommunity, send_to_community},
|
||||
|
@ -30,6 +13,20 @@ use crate::{
|
|||
protocol::activities::voting::vote::{Vote, VoteType},
|
||||
PostOrComment,
|
||||
};
|
||||
use activitystreams::public;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
traits::{ActivityHandler, ActorType},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::CommunityId,
|
||||
source::{community::Community, post::Post},
|
||||
traits::Crud,
|
||||
};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use std::ops::Deref;
|
||||
|
||||
impl Vote {
|
||||
pub(in crate::activities::voting) fn new(
|
||||
|
@ -79,7 +76,7 @@ impl ActivityHandler for Vote {
|
|||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
|
||||
Ok(())
|
||||
|
|
|
@ -26,12 +26,12 @@ use crate::{
|
|||
voting::{undo_vote::UndoVote, vote::Vote},
|
||||
},
|
||||
};
|
||||
use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler};
|
||||
use lemmy_apub_lib::traits::ActivityHandler;
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
|
||||
#[serde(untagged)]
|
||||
#[activity_handler(LemmyContext)]
|
||||
pub enum SharedInboxActivities {
|
||||
|
@ -41,7 +41,7 @@ pub enum SharedInboxActivities {
|
|||
PersonInboxActivities(PersonInboxActivities),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
|
||||
#[serde(untagged)]
|
||||
#[activity_handler(LemmyContext)]
|
||||
pub enum GroupInboxActivities {
|
||||
|
@ -51,7 +51,7 @@ pub enum GroupInboxActivities {
|
|||
Report(Report),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
|
||||
#[serde(untagged)]
|
||||
#[activity_handler(LemmyContext)]
|
||||
pub enum PersonInboxActivities {
|
||||
|
@ -64,7 +64,7 @@ pub enum PersonInboxActivities {
|
|||
AnnounceActivity(Box<AnnounceActivity>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
|
||||
#[serde(untagged)]
|
||||
#[activity_handler(LemmyContext)]
|
||||
pub enum AnnouncableActivities {
|
||||
|
|
|
@ -1,44 +1,14 @@
|
|||
pub mod object_id;
|
||||
pub mod post_or_comment;
|
||||
pub mod search;
|
||||
pub mod user_or_community;
|
||||
|
||||
use crate::{
|
||||
fetcher::object_id::ObjectId,
|
||||
objects::{community::ApubCommunity, person::ApubPerson},
|
||||
};
|
||||
use chrono::NaiveDateTime;
|
||||
use lemmy_apub_lib::traits::ActorType;
|
||||
use lemmy_db_schema::naive_now;
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use url::Url;
|
||||
|
||||
static ACTOR_REFETCH_INTERVAL_SECONDS: i64 = 24 * 60 * 60;
|
||||
static ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG: i64 = 10;
|
||||
|
||||
/// Get a remote actor from its apub ID (either a person or a community). Thin wrapper around
|
||||
/// `get_or_fetch_and_upsert_person()` and `get_or_fetch_and_upsert_community()`.
|
||||
///
|
||||
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
|
||||
/// Otherwise it is fetched from the remote instance, stored and returned.
|
||||
pub(crate) async fn get_or_fetch_and_upsert_actor(
|
||||
apub_id: Url,
|
||||
context: &LemmyContext,
|
||||
recursion_counter: &mut i32,
|
||||
) -> Result<Box<dyn ActorType>, LemmyError> {
|
||||
let community_id = ObjectId::<ApubCommunity>::new(apub_id.clone());
|
||||
let community = community_id.dereference(context, recursion_counter).await;
|
||||
let actor: Box<dyn ActorType> = match community {
|
||||
Ok(c) => Box::new(c),
|
||||
Err(_) => {
|
||||
let person_id = ObjectId::new(apub_id);
|
||||
let person: ApubPerson = person_id.dereference(context, recursion_counter).await?;
|
||||
Box::new(person)
|
||||
}
|
||||
};
|
||||
Ok(actor)
|
||||
}
|
||||
|
||||
/// Determines when a remote actor should be refetched from its instance. In release builds, this is
|
||||
/// `ACTOR_REFETCH_INTERVAL_SECONDS` after the last refetch, in debug builds
|
||||
/// `ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG`.
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
use chrono::NaiveDateTime;
|
||||
use serde::Deserialize;
|
||||
use url::Url;
|
||||
|
||||
use lemmy_apub_lib::traits::ApubObject;
|
||||
use lemmy_db_schema::source::{comment::CommentForm, post::PostForm};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
use crate::{
|
||||
objects::{comment::ApubComment, post::ApubPost},
|
||||
protocol::objects::{note::Note, page::Page},
|
||||
};
|
||||
use chrono::NaiveDateTime;
|
||||
use lemmy_apub_lib::traits::ApubObject;
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use serde::Deserialize;
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum PostOrComment {
|
||||
|
@ -18,11 +15,6 @@ pub enum PostOrComment {
|
|||
Comment(ApubComment),
|
||||
}
|
||||
|
||||
pub enum PostOrCommentForm {
|
||||
PostForm(Box<PostForm>),
|
||||
CommentForm(CommentForm),
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum PageOrNote {
|
||||
|
@ -44,10 +36,7 @@ impl ApubObject for PostOrComment {
|
|||
async fn read_from_apub_id(
|
||||
object_id: Url,
|
||||
data: &Self::DataType,
|
||||
) -> Result<Option<Self>, LemmyError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
) -> Result<Option<Self>, LemmyError> {
|
||||
let post = ApubPost::read_from_apub_id(object_id.clone(), data).await?;
|
||||
Ok(match post {
|
||||
Some(o) => Some(PostOrComment::Post(Box::new(o))),
|
||||
|
@ -77,10 +66,7 @@ impl ApubObject for PostOrComment {
|
|||
context: &LemmyContext,
|
||||
expected_domain: &Url,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<Self, LemmyError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
) -> Result<Self, LemmyError> {
|
||||
Ok(match apub {
|
||||
PageOrNote::Page(p) => PostOrComment::Post(Box::new(
|
||||
ApubPost::from_apub(p, context, expected_domain, request_counter).await?,
|
||||
|
|
113
crates/apub/src/fetcher/user_or_community.rs
Normal file
113
crates/apub/src/fetcher/user_or_community.rs
Normal file
|
@ -0,0 +1,113 @@
|
|||
use crate::{
|
||||
objects::{community::ApubCommunity, person::ApubPerson},
|
||||
protocol::objects::{group::Group, person::Person},
|
||||
};
|
||||
use activitystreams::{chrono::NaiveDateTime, url::Url};
|
||||
use lemmy_apub_lib::traits::{ActorType, ApubObject};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum UserOrCommunity {
|
||||
User(ApubPerson),
|
||||
Community(ApubCommunity),
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum PersonOrGroup {
|
||||
Person(Person),
|
||||
Group(Group),
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ApubObject for UserOrCommunity {
|
||||
type DataType = LemmyContext;
|
||||
type ApubType = PersonOrGroup;
|
||||
type TombstoneType = ();
|
||||
|
||||
fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
|
||||
Some(match self {
|
||||
UserOrCommunity::User(p) => p.last_refreshed_at,
|
||||
UserOrCommunity::Community(p) => p.last_refreshed_at,
|
||||
})
|
||||
}
|
||||
|
||||
async fn read_from_apub_id(
|
||||
object_id: Url,
|
||||
data: &Self::DataType,
|
||||
) -> Result<Option<Self>, LemmyError> {
|
||||
let person = ApubPerson::read_from_apub_id(object_id.clone(), data).await?;
|
||||
Ok(match person {
|
||||
Some(o) => Some(UserOrCommunity::User(o)),
|
||||
None => ApubCommunity::read_from_apub_id(object_id, data)
|
||||
.await?
|
||||
.map(UserOrCommunity::Community),
|
||||
})
|
||||
}
|
||||
|
||||
async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError> {
|
||||
match self {
|
||||
UserOrCommunity::User(p) => p.delete(data).await,
|
||||
UserOrCommunity::Community(p) => p.delete(data).await,
|
||||
}
|
||||
}
|
||||
|
||||
async fn to_apub(&self, _data: &Self::DataType) -> Result<Self::ApubType, LemmyError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn from_apub(
|
||||
apub: &Self::ApubType,
|
||||
data: &Self::DataType,
|
||||
expected_domain: &Url,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<Self, LemmyError> {
|
||||
Ok(match apub {
|
||||
PersonOrGroup::Person(p) => UserOrCommunity::User(
|
||||
ApubPerson::from_apub(p, data, expected_domain, request_counter).await?,
|
||||
),
|
||||
PersonOrGroup::Group(p) => UserOrCommunity::Community(
|
||||
ApubCommunity::from_apub(p, data, expected_domain, request_counter).await?,
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ActorType for UserOrCommunity {
|
||||
fn is_local(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn actor_id(&self) -> Url {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn public_key(&self) -> Option<String> {
|
||||
match self {
|
||||
UserOrCommunity::User(p) => p.public_key(),
|
||||
UserOrCommunity::Community(p) => p.public_key(),
|
||||
}
|
||||
}
|
||||
|
||||
fn private_key(&self) -> Option<String> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn inbox_url(&self) -> Url {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn shared_inbox_url(&self) -> Option<Url> {
|
||||
todo!()
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ use crate::{
|
|||
create_apub_tombstone_response,
|
||||
payload_to_string,
|
||||
receive_activity,
|
||||
ActivityCommonFields,
|
||||
},
|
||||
objects::community::ApubCommunity,
|
||||
protocol::{
|
||||
|
@ -23,7 +24,7 @@ use crate::{
|
|||
};
|
||||
use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse};
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::traits::{ActivityFields, ApubObject};
|
||||
use lemmy_apub_lib::traits::ApubObject;
|
||||
use lemmy_db_schema::source::community::Community;
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
|
@ -64,23 +65,25 @@ pub async fn community_inbox(
|
|||
) -> Result<HttpResponse, LemmyError> {
|
||||
let unparsed = payload_to_string(payload).await?;
|
||||
info!("Received community inbox activity {}", unparsed);
|
||||
let activity_data: ActivityCommonFields = serde_json::from_str(&unparsed)?;
|
||||
let activity = serde_json::from_str::<WithContext<GroupInboxActivities>>(&unparsed)?;
|
||||
|
||||
receive_group_inbox(activity.inner(), request, &context).await?;
|
||||
receive_group_inbox(activity.inner(), activity_data, request, &context).await?;
|
||||
|
||||
Ok(HttpResponse::Ok().finish())
|
||||
}
|
||||
|
||||
pub(in crate::http) async fn receive_group_inbox(
|
||||
activity: GroupInboxActivities,
|
||||
activity_data: ActivityCommonFields,
|
||||
request: HttpRequest,
|
||||
context: &LemmyContext,
|
||||
) -> Result<HttpResponse, LemmyError> {
|
||||
let res = receive_activity(request, activity.clone(), context).await;
|
||||
let actor_id = ObjectId::new(activity_data.actor.clone());
|
||||
let res = receive_activity(request, activity.clone(), activity_data, context).await;
|
||||
|
||||
if let GroupInboxActivities::AnnouncableActivities(announcable) = activity {
|
||||
let community = announcable.get_community(context, &mut 0).await?;
|
||||
let actor_id = ObjectId::new(announcable.actor().clone());
|
||||
verify_person_in_community(&actor_id, &community, context, &mut 0).await?;
|
||||
if community.local {
|
||||
AnnounceActivity::send(announcable, &community, vec![], context).await?;
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
activity_lists::SharedInboxActivities,
|
||||
check_is_apub_id_valid,
|
||||
context::WithContext,
|
||||
fetcher::get_or_fetch_and_upsert_actor,
|
||||
fetcher::{object_id::ObjectId, user_or_community::UserOrCommunity},
|
||||
http::{community::receive_group_inbox, person::receive_person_inbox},
|
||||
insert_activity,
|
||||
};
|
||||
|
@ -20,7 +20,7 @@ use lemmy_api_common::blocking;
|
|||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
signatures::verify_signature,
|
||||
traits::{ActivityFields, ActivityHandler},
|
||||
traits::{ActivityHandler, ActorType},
|
||||
APUB_JSON_CONTENT_TYPE,
|
||||
};
|
||||
use lemmy_db_schema::{source::activity::Activity, DbPool};
|
||||
|
@ -44,13 +44,14 @@ pub async fn shared_inbox(
|
|||
) -> Result<HttpResponse, LemmyError> {
|
||||
let unparsed = payload_to_string(payload).await?;
|
||||
info!("Received shared inbox activity {}", unparsed);
|
||||
let activity_data: ActivityCommonFields = serde_json::from_str(&unparsed)?;
|
||||
let activity = serde_json::from_str::<WithContext<SharedInboxActivities>>(&unparsed)?;
|
||||
match activity.inner() {
|
||||
SharedInboxActivities::GroupInboxActivities(g) => {
|
||||
receive_group_inbox(g, request, &context).await
|
||||
receive_group_inbox(g, activity_data, request, &context).await
|
||||
}
|
||||
SharedInboxActivities::PersonInboxActivities(p) => {
|
||||
receive_person_inbox(p, request, &context).await
|
||||
receive_person_inbox(p, activity_data, request, &context).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,15 +66,22 @@ async fn payload_to_string(mut payload: Payload) -> Result<String, LemmyError> {
|
|||
Ok(unparsed)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct ActivityCommonFields {
|
||||
pub(crate) id: Url,
|
||||
pub(crate) actor: Url,
|
||||
}
|
||||
|
||||
// TODO: move most of this code to library
|
||||
async fn receive_activity<'a, T>(
|
||||
request: HttpRequest,
|
||||
activity: T,
|
||||
activity_data: ActivityCommonFields,
|
||||
context: &LemmyContext,
|
||||
) -> Result<HttpResponse, LemmyError>
|
||||
where
|
||||
T: ActivityHandler<DataType = LemmyContext>
|
||||
+ ActivityFields
|
||||
+ Clone
|
||||
+ Deserialize<'a>
|
||||
+ Serialize
|
||||
|
@ -81,26 +89,27 @@ where
|
|||
+ Send
|
||||
+ 'static,
|
||||
{
|
||||
check_is_apub_id_valid(&activity_data.actor, false, &context.settings())?;
|
||||
let request_counter = &mut 0;
|
||||
let actor =
|
||||
get_or_fetch_and_upsert_actor(activity.actor().clone(), context, request_counter).await?;
|
||||
let actor = ObjectId::<UserOrCommunity>::new(activity_data.actor)
|
||||
.dereference(context, request_counter)
|
||||
.await?;
|
||||
verify_signature(&request, &actor.public_key().context(location_info!())?)?;
|
||||
|
||||
// Do nothing if we received the same activity before
|
||||
if is_activity_already_known(context.pool(), activity.id_unchecked()).await? {
|
||||
if is_activity_already_known(context.pool(), &activity_data.id).await? {
|
||||
return Ok(HttpResponse::Ok().finish());
|
||||
}
|
||||
check_is_apub_id_valid(activity.actor(), false, &context.settings())?;
|
||||
info!("Verifying activity {}", activity.id_unchecked().to_string());
|
||||
info!("Verifying activity {}", activity_data.id.to_string());
|
||||
activity
|
||||
.verify(&Data::new(context.clone()), request_counter)
|
||||
.await?;
|
||||
assert_activity_not_local(&activity, &context.settings().hostname)?;
|
||||
assert_activity_not_local(&activity_data.id, &context.settings().hostname)?;
|
||||
|
||||
// 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.
|
||||
insert_activity(
|
||||
activity.id_unchecked(),
|
||||
&activity_data.id,
|
||||
activity.clone(),
|
||||
false,
|
||||
true,
|
||||
|
@ -108,7 +117,7 @@ where
|
|||
)
|
||||
.await?;
|
||||
|
||||
info!("Receiving activity {}", activity.id_unchecked().to_string());
|
||||
info!("Receiving activity {}", activity_data.id.to_string());
|
||||
activity
|
||||
.receive(&Data::new(context.clone()), request_counter)
|
||||
.await?;
|
||||
|
@ -183,17 +192,14 @@ pub(crate) async fn is_activity_already_known(
|
|||
}
|
||||
}
|
||||
|
||||
fn assert_activity_not_local<T: Debug + ActivityFields>(
|
||||
activity: &T,
|
||||
hostname: &str,
|
||||
) -> Result<(), LemmyError> {
|
||||
let activity_domain = activity.id_unchecked().domain().context(location_info!())?;
|
||||
fn assert_activity_not_local(id: &Url, hostname: &str) -> Result<(), LemmyError> {
|
||||
let activity_domain = id.domain().context(location_info!())?;
|
||||
|
||||
if activity_domain == hostname {
|
||||
return Err(
|
||||
anyhow!(
|
||||
"Error: received activity which was sent by local instance: {:?}",
|
||||
activity
|
||||
id
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::{
|
|||
create_apub_tombstone_response,
|
||||
payload_to_string,
|
||||
receive_activity,
|
||||
ActivityCommonFields,
|
||||
},
|
||||
objects::person::ApubPerson,
|
||||
protocol::collections::person_outbox::PersonOutbox,
|
||||
|
@ -54,16 +55,18 @@ pub async fn person_inbox(
|
|||
) -> Result<HttpResponse, LemmyError> {
|
||||
let unparsed = payload_to_string(payload).await?;
|
||||
info!("Received person inbox activity {}", unparsed);
|
||||
let activity_data: ActivityCommonFields = serde_json::from_str(&unparsed)?;
|
||||
let activity = serde_json::from_str::<WithContext<PersonInboxActivities>>(&unparsed)?;
|
||||
receive_person_inbox(activity.inner(), request, &context).await
|
||||
receive_person_inbox(activity.inner(), activity_data, request, &context).await
|
||||
}
|
||||
|
||||
pub(in crate::http) async fn receive_person_inbox(
|
||||
activity: PersonInboxActivities,
|
||||
activity_data: ActivityCommonFields,
|
||||
request: HttpRequest,
|
||||
context: &LemmyContext,
|
||||
) -> Result<HttpResponse, LemmyError> {
|
||||
receive_activity(request, activity, context).await
|
||||
receive_activity(request, activity, activity_data, context).await
|
||||
}
|
||||
|
||||
pub(crate) async fn get_apub_person_outbox(
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use crate::{fetcher::object_id::ObjectId, objects::person::ApubPerson};
|
||||
use activitystreams::{activity::kind::AddType, unparsed::Unparsed};
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AddMod {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -4,11 +4,10 @@ use crate::{
|
|||
objects::community::ApubCommunity,
|
||||
};
|
||||
use activitystreams::{activity::kind::AnnounceType, unparsed::Unparsed};
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AnnounceActivity {
|
||||
pub(crate) actor: ObjectId<ApubCommunity>,
|
||||
|
|
|
@ -3,11 +3,10 @@ use crate::{
|
|||
objects::{community::ApubCommunity, person::ApubPerson},
|
||||
};
|
||||
use activitystreams::{activity::kind::BlockType, unparsed::Unparsed};
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BlockUserFromCommunity {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use crate::{fetcher::object_id::ObjectId, objects::person::ApubPerson};
|
||||
use activitystreams::{activity::kind::RemoveType, unparsed::Unparsed};
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RemoveMod {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -3,11 +3,10 @@ use crate::{
|
|||
objects::{community::ApubCommunity, person::ApubPerson},
|
||||
};
|
||||
use activitystreams::{activity::kind::FlagType, unparsed::Unparsed};
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Report {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -4,11 +4,10 @@ use crate::{
|
|||
protocol::activities::community::block_user::BlockUserFromCommunity,
|
||||
};
|
||||
use activitystreams::{activity::kind::UndoType, unparsed::Unparsed};
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UndoBlockUserFromCommunity {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -4,13 +4,12 @@ use crate::{
|
|||
protocol::objects::group::Group,
|
||||
};
|
||||
use activitystreams::{activity::kind::UpdateType, unparsed::Unparsed};
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
/// This activity is received from a remote community mod, and updates the description or other
|
||||
/// fields of a local community.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UpdateCommunity {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -4,11 +4,10 @@ use crate::{
|
|||
protocol::{activities::CreateOrUpdateType, objects::note::Note},
|
||||
};
|
||||
use activitystreams::{link::Mention, unparsed::Unparsed};
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CreateOrUpdateComment {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -4,11 +4,10 @@ use crate::{
|
|||
protocol::{activities::CreateOrUpdateType, objects::page::Page},
|
||||
};
|
||||
use activitystreams::unparsed::Unparsed;
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CreateOrUpdatePost {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use crate::{fetcher::object_id::ObjectId, objects::person::ApubPerson};
|
||||
use activitystreams::{activity::kind::DeleteType, unparsed::Unparsed};
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::skip_serializing_none;
|
||||
use url::Url;
|
||||
|
||||
#[skip_serializing_none]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Delete {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
use activitystreams::{activity::kind::UndoType, unparsed::Unparsed};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
|
||||
use crate::{
|
||||
fetcher::object_id::ObjectId,
|
||||
objects::person::ApubPerson,
|
||||
protocol::activities::deletion::delete::Delete,
|
||||
};
|
||||
use activitystreams::{activity::kind::UndoType, unparsed::Unparsed};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UndoDelete {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -4,11 +4,10 @@ use crate::{
|
|||
protocol::activities::following::follow::FollowCommunity,
|
||||
};
|
||||
use activitystreams::{activity::kind::AcceptType, unparsed::Unparsed};
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AcceptFollowCommunity {
|
||||
pub(crate) actor: ObjectId<ApubCommunity>,
|
||||
|
|
|
@ -3,11 +3,10 @@ use crate::{
|
|||
objects::{community::ApubCommunity, person::ApubPerson},
|
||||
};
|
||||
use activitystreams::{activity::kind::FollowType, unparsed::Unparsed};
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FollowCommunity {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -4,11 +4,10 @@ use crate::{
|
|||
protocol::activities::following::follow::FollowCommunity,
|
||||
};
|
||||
use activitystreams::{activity::kind::UndoType, unparsed::Unparsed};
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UndoFollowCommunity {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -4,11 +4,10 @@ use crate::{
|
|||
protocol::{activities::CreateOrUpdateType, objects::chat_message::ChatMessage},
|
||||
};
|
||||
use activitystreams::unparsed::Unparsed;
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CreateOrUpdatePrivateMessage {
|
||||
pub(crate) id: Url,
|
||||
|
|
|
@ -3,11 +3,10 @@ use crate::{
|
|||
objects::{person::ApubPerson, private_message::ApubPrivateMessage},
|
||||
};
|
||||
use activitystreams::{activity::kind::DeleteType, unparsed::Unparsed};
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DeletePrivateMessage {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -4,11 +4,10 @@ use crate::{
|
|||
protocol::activities::private_message::delete::DeletePrivateMessage,
|
||||
};
|
||||
use activitystreams::{activity::kind::UndoType, unparsed::Unparsed};
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UndoDeletePrivateMessage {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
use activitystreams::{activity::kind::UndoType, unparsed::Unparsed};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
|
||||
use crate::{
|
||||
fetcher::object_id::ObjectId,
|
||||
objects::person::ApubPerson,
|
||||
protocol::activities::voting::vote::Vote,
|
||||
};
|
||||
use activitystreams::{activity::kind::UndoType, unparsed::Unparsed};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UndoVote {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -4,14 +4,13 @@ use crate::{
|
|||
};
|
||||
use activitystreams::unparsed::Unparsed;
|
||||
use anyhow::anyhow;
|
||||
use lemmy_apub_lib::traits::ActivityFields;
|
||||
use lemmy_utils::LemmyError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::TryFrom;
|
||||
use strum_macros::ToString;
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Vote {
|
||||
pub(crate) actor: ObjectId<ApubPerson>,
|
||||
|
|
|
@ -5,11 +5,6 @@ pub use lemmy_apub_lib_derive::*;
|
|||
use lemmy_utils::{location_info, LemmyError};
|
||||
use url::Url;
|
||||
|
||||
pub trait ActivityFields {
|
||||
fn id_unchecked(&self) -> &Url;
|
||||
fn actor(&self) -> &Url;
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
pub trait ActivityHandler {
|
||||
type DataType;
|
||||
|
|
|
@ -127,40 +127,3 @@ fn generate_match_arm(enum_name: &Ident, variant: &Variant, body: &TokenStream)
|
|||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[proc_macro_derive(ActivityFields)]
|
||||
pub fn derive_activity_fields(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
let name = input.ident;
|
||||
|
||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
|
||||
let expanded = match input.data {
|
||||
Data::Enum(e) => {
|
||||
let variants = e.variants;
|
||||
let impl_id = variants
|
||||
.iter()
|
||||
.map(|v| generate_match_arm(&name, v, "e! {a.id_unchecked()}));
|
||||
let impl_actor = variants
|
||||
.iter()
|
||||
.map(|v| generate_match_arm(&name, v, "e! {a.actor()}));
|
||||
quote! {
|
||||
impl #impl_generics lemmy_apub_lib::traits::ActivityFields for #name #ty_generics #where_clause {
|
||||
fn id_unchecked(&self) -> &url::Url { match self { #(#impl_id)* } }
|
||||
fn actor(&self) -> &url::Url { match self { #(#impl_actor)* } }
|
||||
}
|
||||
}
|
||||
}
|
||||
Data::Struct(_) => {
|
||||
quote! {
|
||||
impl #impl_generics lemmy_apub_lib::traits::ActivityFields for #name #ty_generics #where_clause {
|
||||
fn id_unchecked(&self) -> &url::Url { &self.id }
|
||||
fn actor(&self) -> &url::Url { &self.actor.inner() }
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
expanded.into()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue