mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-12-23 19:31:33 +00:00
When receiving activity, dont read community from cc (for pleroma compat and better verification)
This commit is contained in:
parent
74523fb534
commit
271785b7fb
28 changed files with 386 additions and 185 deletions
|
@ -2,8 +2,10 @@ use crate::{
|
|||
activities::{
|
||||
check_community_deleted_or_removed,
|
||||
comment::{collect_non_local_mentions, get_notif_recipients},
|
||||
community::{announce::AnnouncableActivities, send_to_community},
|
||||
extract_community,
|
||||
community::{
|
||||
announce::{AnnouncableActivities, GetCommunity},
|
||||
send_to_community,
|
||||
},
|
||||
generate_activity_id,
|
||||
verify_activity,
|
||||
verify_is_public,
|
||||
|
@ -108,12 +110,11 @@ impl ActivityHandler for CreateOrUpdateComment {
|
|||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
let community = extract_community(&self.cc, context, request_counter).await?;
|
||||
let community_id = ObjectId::new(community.actor_id());
|
||||
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_person_in_community(&self.actor, &community_id, context, request_counter).await?;
|
||||
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
|
||||
verify_domains_match(self.actor.inner(), self.object.id_unchecked())?;
|
||||
check_community_deleted_or_removed(&community)?;
|
||||
check_post_deleted_or_removed(&post)?;
|
||||
|
@ -144,6 +145,22 @@ impl ActivityHandler for CreateOrUpdateComment {
|
|||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for CreateOrUpdateComment {
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError> {
|
||||
let post = self.object.get_parents(context, request_counter).await?.0;
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read(conn, post.community_id)
|
||||
})
|
||||
.await??;
|
||||
Ok(community.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
use crate::{
|
||||
activities::{
|
||||
community::{announce::AnnouncableActivities, send_to_community},
|
||||
community::{
|
||||
announce::{AnnouncableActivities, GetCommunity},
|
||||
get_community_from_moderators_url,
|
||||
send_to_community,
|
||||
},
|
||||
generate_activity_id,
|
||||
verify_activity,
|
||||
verify_add_remove_moderator_target,
|
||||
|
@ -91,7 +95,8 @@ impl ActivityHandler for AddMod {
|
|||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||
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, &self.cc[0], context, request_counter).await?;
|
||||
verify_add_remove_moderator_target(&self.target, &self.cc[0])?;
|
||||
Ok(())
|
||||
|
@ -102,7 +107,7 @@ impl ActivityHandler for AddMod {
|
|||
context: &Data<LemmyContext>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let community = self.cc[0].dereference(context, request_counter).await?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
let new_mod = self.object.dereference(context, request_counter).await?;
|
||||
|
||||
// If we had to refetch the community while parsing the activity, then the new mod has already
|
||||
|
@ -126,3 +131,14 @@ impl ActivityHandler for AddMod {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for AddMod {
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError> {
|
||||
get_community_from_moderators_url(&self.target, context, request_counter).await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ use crate::{
|
|||
generate_activity_id,
|
||||
post::create_or_update::CreateOrUpdatePost,
|
||||
verify_activity,
|
||||
verify_community,
|
||||
verify_is_public,
|
||||
voting::{undo_vote::UndoVote, vote::Vote},
|
||||
},
|
||||
|
@ -23,7 +22,6 @@ use crate::{
|
|||
insert_activity,
|
||||
objects::community::ApubCommunity,
|
||||
send_lemmy_activity,
|
||||
CommunityType,
|
||||
};
|
||||
use activitystreams::{
|
||||
activity::kind::AnnounceType,
|
||||
|
@ -35,6 +33,7 @@ use activitystreams::{
|
|||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||
verify::verify_urls_match,
|
||||
};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
|
@ -58,6 +57,41 @@ pub enum AnnouncableActivities {
|
|||
RemoveMod(RemoveMod),
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
pub(crate) trait GetCommunity {
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError>;
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for AnnouncableActivities {
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError> {
|
||||
use AnnouncableActivities::*;
|
||||
let community = match self {
|
||||
CreateOrUpdateComment(a) => a.get_community(context, request_counter).await?,
|
||||
CreateOrUpdatePost(a) => a.get_community(context, request_counter).await?,
|
||||
Vote(a) => a.get_community(context, request_counter).await?,
|
||||
UndoVote(a) => a.get_community(context, request_counter).await?,
|
||||
Delete(a) => a.get_community(context, request_counter).await?,
|
||||
UndoDelete(a) => a.get_community(context, request_counter).await?,
|
||||
UpdateCommunity(a) => a.get_community(context, request_counter).await?,
|
||||
BlockUserFromCommunity(a) => a.get_community(context, request_counter).await?,
|
||||
UndoBlockUserFromCommunity(a) => a.get_community(context, request_counter).await?,
|
||||
AddMod(a) => a.get_community(context, request_counter).await?,
|
||||
RemoveMod(a) => a.get_community(context, request_counter).await?,
|
||||
};
|
||||
verify_urls_match(self.actor(), &community.actor_id())?;
|
||||
Ok(community)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AnnounceActivity {
|
||||
|
@ -85,7 +119,7 @@ impl AnnounceActivity {
|
|||
actor: ObjectId::new(community.actor_id()),
|
||||
to: vec![public()],
|
||||
object,
|
||||
cc: vec![community.followers_url()],
|
||||
cc: vec![community.followers_url.clone().into_inner()],
|
||||
kind: AnnounceType::Announce,
|
||||
id: generate_activity_id(
|
||||
&AnnounceType::Announce,
|
||||
|
@ -109,7 +143,6 @@ impl ActivityHandler for AnnounceActivity {
|
|||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_community(&self.actor, context, request_counter).await?;
|
||||
self.object.verify(context, request_counter).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use crate::{
|
||||
activities::{
|
||||
community::{announce::AnnouncableActivities, send_to_community},
|
||||
community::{
|
||||
announce::{AnnouncableActivities, GetCommunity},
|
||||
send_to_community,
|
||||
},
|
||||
generate_activity_id,
|
||||
verify_activity,
|
||||
verify_is_public,
|
||||
|
@ -44,6 +47,7 @@ pub struct BlockUserFromCommunity {
|
|||
to: Vec<Url>,
|
||||
pub(in crate::activities::community) object: ObjectId<ApubPerson>,
|
||||
cc: [ObjectId<ApubCommunity>; 1],
|
||||
target: ObjectId<ApubCommunity>,
|
||||
#[serde(rename = "type")]
|
||||
kind: BlockType,
|
||||
id: Url,
|
||||
|
@ -65,6 +69,7 @@ impl BlockUserFromCommunity {
|
|||
to: vec![public()],
|
||||
object: ObjectId::new(target.actor_id()),
|
||||
cc: [ObjectId::new(community.actor_id())],
|
||||
target: ObjectId::new(community.actor_id()),
|
||||
kind: BlockType::Block,
|
||||
id: generate_activity_id(
|
||||
BlockType::Block,
|
||||
|
@ -100,7 +105,8 @@ impl ActivityHandler for BlockUserFromCommunity {
|
|||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||
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, &self.cc[0], context, request_counter).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -110,7 +116,7 @@ impl ActivityHandler for BlockUserFromCommunity {
|
|||
context: &Data<LemmyContext>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let community = self.cc[0].dereference(context, request_counter).await?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
let blocked_user = self.object.dereference(context, request_counter).await?;
|
||||
|
||||
let community_user_ban_form = CommunityPersonBanForm {
|
||||
|
@ -138,3 +144,14 @@ impl ActivityHandler for BlockUserFromCommunity {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for BlockUserFromCommunity {
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError> {
|
||||
self.target.dereference(context, request_counter).await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use crate::{
|
||||
activities::community::announce::{AnnouncableActivities, AnnounceActivity},
|
||||
check_is_apub_id_valid,
|
||||
fetcher::object_id::ObjectId,
|
||||
insert_activity,
|
||||
objects::community::ApubCommunity,
|
||||
send_lemmy_activity,
|
||||
CommunityType,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use lemmy_apub_lib::traits::ActorType;
|
||||
|
@ -61,3 +61,14 @@ pub(crate) async fn send_to_community<T: ActorType>(
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_community_from_moderators_url(
|
||||
moderators: &Url,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError> {
|
||||
let community_id = Url::parse(&moderators.to_string().replace("/moderators", ""))?;
|
||||
ObjectId::new(community_id)
|
||||
.dereference(context, request_counter)
|
||||
.await
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
use crate::{
|
||||
activities::{
|
||||
community::{announce::AnnouncableActivities, send_to_community},
|
||||
community::{
|
||||
announce::{AnnouncableActivities, GetCommunity},
|
||||
get_community_from_moderators_url,
|
||||
send_to_community,
|
||||
},
|
||||
generate_activity_id,
|
||||
verify_activity,
|
||||
verify_add_remove_moderator_target,
|
||||
|
@ -43,7 +47,6 @@ pub struct RemoveMod {
|
|||
cc: [ObjectId<ApubCommunity>; 1],
|
||||
#[serde(rename = "type")]
|
||||
kind: RemoveType,
|
||||
// if target is set, this is means remove mod from community
|
||||
pub(in crate::activities) target: Url,
|
||||
id: Url,
|
||||
#[serde(rename = "@context")]
|
||||
|
@ -91,7 +94,8 @@ impl ActivityHandler for RemoveMod {
|
|||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||
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, &self.cc[0], context, request_counter).await?;
|
||||
verify_add_remove_moderator_target(&self.target, &self.cc[0])?;
|
||||
Ok(())
|
||||
|
@ -102,7 +106,7 @@ impl ActivityHandler for RemoveMod {
|
|||
context: &Data<LemmyContext>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let community = self.cc[0].dereference(context, request_counter).await?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
let remove_mod = self.object.dereference(context, request_counter).await?;
|
||||
|
||||
let form = CommunityModeratorForm {
|
||||
|
@ -117,3 +121,14 @@ impl ActivityHandler for RemoveMod {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for RemoveMod {
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError> {
|
||||
get_community_from_moderators_url(&self.target, context, request_counter).await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
activities::{
|
||||
community::{
|
||||
announce::AnnouncableActivities,
|
||||
announce::{AnnouncableActivities, GetCommunity},
|
||||
block_user::BlockUserFromCommunity,
|
||||
send_to_community,
|
||||
},
|
||||
|
@ -92,7 +92,8 @@ impl ActivityHandler for UndoBlockUserFromCommunity {
|
|||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||
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, &self.cc[0], context, request_counter).await?;
|
||||
self.object.verify(context, request_counter).await?;
|
||||
Ok(())
|
||||
|
@ -103,7 +104,7 @@ impl ActivityHandler for UndoBlockUserFromCommunity {
|
|||
context: &Data<LemmyContext>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let community = self.cc[0].dereference(context, request_counter).await?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
let blocked_user = self
|
||||
.object
|
||||
.object
|
||||
|
@ -123,3 +124,14 @@ impl ActivityHandler for UndoBlockUserFromCommunity {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for UndoBlockUserFromCommunity {
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError> {
|
||||
self.object.get_community(context, request_counter).await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use crate::{
|
||||
activities::{
|
||||
community::{announce::AnnouncableActivities, send_to_community},
|
||||
community::{
|
||||
announce::{AnnouncableActivities, GetCommunity},
|
||||
send_to_community,
|
||||
},
|
||||
generate_activity_id,
|
||||
verify_activity,
|
||||
verify_is_public,
|
||||
|
@ -90,7 +93,8 @@ impl ActivityHandler for UpdateCommunity {
|
|||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||
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, &self.cc[0], context, request_counter).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -100,8 +104,7 @@ impl ActivityHandler for UpdateCommunity {
|
|||
context: &Data<LemmyContext>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let cc = self.cc[0].clone();
|
||||
let community = cc.dereference(context, request_counter).await?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
|
||||
let updated_community = Group::from_apub_to_form(
|
||||
&self.object,
|
||||
|
@ -135,3 +138,15 @@ impl ActivityHandler for UpdateCommunity {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for UpdateCommunity {
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError> {
|
||||
let cid = ObjectId::new(self.object.id.clone());
|
||||
cid.dereference(context, request_counter).await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use crate::{
|
||||
activities::{
|
||||
community::{announce::AnnouncableActivities, send_to_community},
|
||||
community::{
|
||||
announce::{AnnouncableActivities, GetCommunity},
|
||||
send_to_community,
|
||||
},
|
||||
deletion::{
|
||||
receive_delete_action,
|
||||
verify_delete_activity,
|
||||
|
@ -245,3 +248,26 @@ pub(in crate::activities) async fn receive_remove_action(
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for Delete {
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
_request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError> {
|
||||
let community_id = match DeletableObjects::read_from_db(&self.object, context).await? {
|
||||
DeletableObjects::Community(c) => c.id,
|
||||
DeletableObjects::Comment(c) => {
|
||||
let post = blocking(context.pool(), move |conn| Post::read(conn, c.post_id)).await??;
|
||||
post.community_id
|
||||
}
|
||||
DeletableObjects::Post(p) => p.community_id,
|
||||
};
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read(conn, community_id)
|
||||
})
|
||||
.await??;
|
||||
Ok(community.into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ pub(in crate::activities) async fn verify_delete_activity(
|
|||
if c.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_id, context, request_counter).await?;
|
||||
verify_person_in_community(&actor, &c, context, request_counter).await?;
|
||||
}
|
||||
// community deletion is always a mod (or admin) action
|
||||
verify_mod_action(
|
||||
|
@ -140,7 +140,8 @@ async fn verify_delete_activity_post_or_comment(
|
|||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let actor = ObjectId::new(activity.actor().clone());
|
||||
verify_person_in_community(&actor, community_id, context, request_counter).await?;
|
||||
let community = community_id.dereference(context, request_counter).await?;
|
||||
verify_person_in_community(&actor, &community, context, request_counter).await?;
|
||||
if is_mod_action {
|
||||
verify_mod_action(&actor, community_id, context, request_counter).await?;
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use crate::{
|
||||
activities::{
|
||||
community::{announce::AnnouncableActivities, send_to_community},
|
||||
community::{
|
||||
announce::{AnnouncableActivities, GetCommunity},
|
||||
send_to_community,
|
||||
},
|
||||
deletion::{
|
||||
delete::Delete,
|
||||
receive_delete_action,
|
||||
|
@ -166,3 +169,14 @@ impl UndoDelete {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for UndoDelete {
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError> {
|
||||
self.object.get_community(context, request_counter).await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
use crate::{
|
||||
activities::{
|
||||
following::follow::FollowCommunity,
|
||||
generate_activity_id,
|
||||
verify_activity,
|
||||
verify_community,
|
||||
},
|
||||
activities::{following::follow::FollowCommunity, generate_activity_id, verify_activity},
|
||||
context::lemmy_context,
|
||||
fetcher::object_id::ObjectId,
|
||||
objects::{community::ApubCommunity, person::ApubPerson},
|
||||
|
@ -84,7 +79,6 @@ impl ActivityHandler for AcceptFollowCommunity {
|
|||
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_community(&self.actor, context, request_counter).await?;
|
||||
self.object.verify(context, request_counter).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::{
|
|||
generate_activity_id,
|
||||
verify_activity,
|
||||
verify_person,
|
||||
verify_person_in_community,
|
||||
},
|
||||
context::lemmy_context,
|
||||
fetcher::object_id::ObjectId,
|
||||
|
@ -97,6 +98,8 @@ impl ActivityHandler for FollowCommunity {
|
|||
verify_activity(self, &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?;
|
||||
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use crate::{
|
||||
check_community_or_site_ban,
|
||||
check_is_apub_id_valid,
|
||||
fetcher::object_id::ObjectId,
|
||||
generate_moderators_url,
|
||||
|
@ -10,11 +9,13 @@ use anyhow::anyhow;
|
|||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{traits::ActivityFields, verify::verify_domains_match};
|
||||
use lemmy_db_schema::source::community::Community;
|
||||
use lemmy_db_views_actor::community_view::CommunityView;
|
||||
use lemmy_db_views_actor::{
|
||||
community_person_ban_view::CommunityPersonBanView,
|
||||
community_view::CommunityView,
|
||||
};
|
||||
use lemmy_utils::{settings::structs::Settings, LemmyError};
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ops::Deref;
|
||||
use strum_macros::ToString;
|
||||
use url::{ParseError, Url};
|
||||
use uuid::Uuid;
|
||||
|
@ -48,44 +49,26 @@ async fn verify_person(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn extract_community(
|
||||
cc: &[Url],
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError> {
|
||||
let mut cc_iter = cc.iter();
|
||||
loop {
|
||||
if let Some(cid) = cc_iter.next() {
|
||||
let cid = ObjectId::new(cid.clone());
|
||||
if let Ok(c) = cid.dereference(context, request_counter).await {
|
||||
break Ok(c);
|
||||
}
|
||||
} else {
|
||||
return Err(anyhow!("No community found in cc").into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetches the person and community to verify their type, then checks if person is banned from site
|
||||
/// or community.
|
||||
pub(crate) async fn verify_person_in_community(
|
||||
person_id: &ObjectId<ApubPerson>,
|
||||
community_id: &ObjectId<ApubCommunity>,
|
||||
community: &ApubCommunity,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let community = community_id.dereference(context, request_counter).await?;
|
||||
let person = person_id.dereference(context, request_counter).await?;
|
||||
check_community_or_site_ban(person.deref(), community.id, context.pool()).await
|
||||
}
|
||||
if person.banned {
|
||||
return Err(anyhow!("Person is banned from site").into());
|
||||
}
|
||||
let person_id = person.id;
|
||||
let community_id = community.id;
|
||||
let is_banned =
|
||||
move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
|
||||
if blocking(context.pool(), is_banned).await? {
|
||||
return Err(anyhow!("Person is banned from community").into());
|
||||
}
|
||||
|
||||
/// Simply check that the url actually refers to a valid group.
|
||||
async fn verify_community(
|
||||
community_id: &ObjectId<ApubCommunity>,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
community_id.dereference(context, request_counter).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
use crate::{
|
||||
activities::{
|
||||
check_community_deleted_or_removed,
|
||||
community::{announce::AnnouncableActivities, send_to_community},
|
||||
community::{
|
||||
announce::{AnnouncableActivities, GetCommunity},
|
||||
send_to_community,
|
||||
},
|
||||
generate_activity_id,
|
||||
verify_activity,
|
||||
verify_is_public,
|
||||
|
@ -99,8 +102,8 @@ impl ActivityHandler for CreateOrUpdatePost {
|
|||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
let community = self.cc[0].dereference(context, request_counter).await?;
|
||||
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||
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)?;
|
||||
|
||||
match self.kind {
|
||||
|
@ -148,3 +151,17 @@ impl ActivityHandler for CreateOrUpdatePost {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for CreateOrUpdatePost {
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError> {
|
||||
self
|
||||
.object
|
||||
.extract_community(context, request_counter)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
|||
fetcher::object_id::ObjectId,
|
||||
objects::{
|
||||
person::ApubPerson,
|
||||
private_message::{ApubPrivateMessage, Note},
|
||||
private_message::{ApubPrivateMessage, ChatMessage},
|
||||
},
|
||||
send_lemmy_activity,
|
||||
};
|
||||
|
@ -29,7 +29,7 @@ pub struct CreateOrUpdatePrivateMessage {
|
|||
id: Url,
|
||||
actor: ObjectId<ApubPerson>,
|
||||
to: [ObjectId<ApubPerson>; 1],
|
||||
object: Note,
|
||||
object: ChatMessage,
|
||||
#[serde(rename = "type")]
|
||||
kind: CreateOrUpdateType,
|
||||
#[serde(flatten)]
|
||||
|
|
|
@ -91,7 +91,8 @@ impl ActivityHandler for Report {
|
|||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_person_in_community(&self.actor, &self.to[0], context, request_counter).await?;
|
||||
let community = self.to[0].dereference(context, request_counter).await?;
|
||||
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use crate::{
|
||||
activities::{
|
||||
community::{announce::AnnouncableActivities, send_to_community},
|
||||
community::{
|
||||
announce::{AnnouncableActivities, GetCommunity},
|
||||
send_to_community,
|
||||
},
|
||||
generate_activity_id,
|
||||
verify_activity,
|
||||
verify_is_public,
|
||||
|
@ -96,7 +99,8 @@ impl ActivityHandler for UndoVote {
|
|||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||
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())?;
|
||||
self.object.verify(context, request_counter).await?;
|
||||
Ok(())
|
||||
|
@ -119,3 +123,14 @@ impl ActivityHandler for UndoVote {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for UndoVote {
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError> {
|
||||
self.object.get_community(context, request_counter).await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use crate::{
|
||||
activities::{
|
||||
community::{announce::AnnouncableActivities, send_to_community},
|
||||
community::{
|
||||
announce::{AnnouncableActivities, GetCommunity},
|
||||
send_to_community,
|
||||
},
|
||||
generate_activity_id,
|
||||
verify_activity,
|
||||
verify_is_public,
|
||||
|
@ -19,7 +22,11 @@ use lemmy_apub_lib::{
|
|||
data::Data,
|
||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||
};
|
||||
use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::CommunityId,
|
||||
source::{community::Community, post::Post},
|
||||
traits::Crud,
|
||||
};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -120,7 +127,8 @@ impl ActivityHandler for Vote {
|
|||
) -> Result<(), LemmyError> {
|
||||
verify_is_public(&self.to)?;
|
||||
verify_activity(self, &context.settings())?;
|
||||
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||
let community = self.get_community(context, request_counter).await?;
|
||||
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -137,3 +145,24 @@ impl ActivityHandler for Vote {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for Vote {
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError> {
|
||||
let object = self.object.dereference(context, request_counter).await?;
|
||||
let cid = match object {
|
||||
PostOrComment::Post(p) => p.community_id,
|
||||
PostOrComment::Comment(c) => {
|
||||
blocking(context.pool(), move |conn| Post::read(conn, c.post_id))
|
||||
.await??
|
||||
.community_id
|
||||
}
|
||||
};
|
||||
let community = blocking(context.pool(), move |conn| Community::read(conn, cid)).await??;
|
||||
Ok(community.into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,11 @@ use crate::{
|
|||
objects::{person::ApubPerson, post::ApubPost},
|
||||
};
|
||||
use activitystreams::{
|
||||
base::AnyBase, chrono::NaiveDateTime, collection::kind::OrderedCollectionType,
|
||||
primitives::OneOrMany, url::Url,
|
||||
base::AnyBase,
|
||||
chrono::NaiveDateTime,
|
||||
collection::kind::OrderedCollectionType,
|
||||
primitives::OneOrMany,
|
||||
url::Url,
|
||||
};
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use crate::{
|
||||
activities::{
|
||||
community::announce::{AnnouncableActivities, AnnounceActivity},
|
||||
extract_community,
|
||||
community::announce::{AnnouncableActivities, AnnounceActivity, GetCommunity},
|
||||
following::{follow::FollowCommunity, undo::UndoFollowCommunity},
|
||||
report::Report,
|
||||
verify_person_in_community,
|
||||
},
|
||||
collections::{
|
||||
community_moderators::ApubCommunityModerators,
|
||||
|
@ -27,7 +27,10 @@ use activitystreams::{
|
|||
};
|
||||
use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse};
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler, ApubObject};
|
||||
use lemmy_apub_lib::{
|
||||
traits::{ActivityFields, ActivityHandler, ActorType, ApubObject},
|
||||
verify::verify_domains_match,
|
||||
};
|
||||
use lemmy_db_schema::source::community::Community;
|
||||
use lemmy_db_views_actor::community_follower_view::CommunityFollowerView;
|
||||
use lemmy_utils::LemmyError;
|
||||
|
@ -92,12 +95,17 @@ pub(in crate::http) async fn receive_group_inbox(
|
|||
context: &LemmyContext,
|
||||
) -> Result<HttpResponse, LemmyError> {
|
||||
let res = receive_activity(request, activity.clone(), context).await;
|
||||
if let GroupInboxActivities::AnnouncableActivities(announcable) = activity.clone() {
|
||||
let community = extract_community(&announcable.cc(), context, &mut 0).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_domains_match(&community.actor_id(), announcable.id_unchecked())?;
|
||||
verify_person_in_community(&actor_id, &community, context, &mut 0).await?;
|
||||
if community.local {
|
||||
AnnounceActivity::send(announcable, &community, vec![], context).await?;
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
|
|
|
@ -17,12 +17,7 @@ use lemmy_apub_lib::{
|
|||
traits::ActorType,
|
||||
webfinger::{webfinger_resolve_actor, WebfingerType},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::{CommunityId, DbUrl},
|
||||
source::{activity::Activity, person::Person},
|
||||
DbPool,
|
||||
};
|
||||
use lemmy_db_views_actor::community_person_ban_view::CommunityPersonBanView;
|
||||
use lemmy_db_schema::{newtypes::DbUrl, source::activity::Activity, DbPool};
|
||||
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use log::info;
|
||||
|
@ -96,16 +91,6 @@ pub(crate) fn check_is_apub_id_valid(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
pub trait CommunityType {
|
||||
fn followers_url(&self) -> Url;
|
||||
async fn get_follower_inboxes(
|
||||
&self,
|
||||
pool: &DbPool,
|
||||
settings: &Settings,
|
||||
) -> Result<Vec<Url>, LemmyError>;
|
||||
}
|
||||
|
||||
pub enum EndpointType {
|
||||
Community,
|
||||
Person,
|
||||
|
@ -211,24 +196,6 @@ where
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn check_community_or_site_ban(
|
||||
person: &Person,
|
||||
community_id: CommunityId,
|
||||
pool: &DbPool,
|
||||
) -> Result<(), LemmyError> {
|
||||
if person.banned {
|
||||
return Err(anyhow!("Person is banned from site").into());
|
||||
}
|
||||
let person_id = person.id;
|
||||
let is_banned =
|
||||
move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
|
||||
if blocking(pool, is_banned).await? {
|
||||
return Err(anyhow!("Person is banned from community").into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn send_lemmy_activity<T: Serialize>(
|
||||
context: &LemmyContext,
|
||||
activity: &T,
|
||||
|
|
|
@ -2,7 +2,13 @@ use crate::{
|
|||
activities::{verify_is_public, verify_person_in_community},
|
||||
context::lemmy_context,
|
||||
fetcher::object_id::ObjectId,
|
||||
objects::{person::ApubPerson, post::ApubPost, tombstone::Tombstone, Source},
|
||||
objects::{
|
||||
community::ApubCommunity,
|
||||
person::ApubPerson,
|
||||
post::ApubPost,
|
||||
tombstone::Tombstone,
|
||||
Source,
|
||||
},
|
||||
PostOrComment,
|
||||
};
|
||||
use activitystreams::{
|
||||
|
@ -121,22 +127,17 @@ impl Note {
|
|||
) -> Result<(), LemmyError> {
|
||||
let (post, _parent_comment_id) = self.get_parents(context, request_counter).await?;
|
||||
let community_id = post.community_id;
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
let community: ApubCommunity = blocking(context.pool(), move |conn| {
|
||||
Community::read(conn, community_id)
|
||||
})
|
||||
.await??;
|
||||
.await??
|
||||
.into();
|
||||
|
||||
if post.locked {
|
||||
return Err(anyhow!("Post is locked").into());
|
||||
}
|
||||
verify_domains_match(self.attributed_to.inner(), &self.id)?;
|
||||
verify_person_in_community(
|
||||
&self.attributed_to,
|
||||
&ObjectId::new(community.actor_id),
|
||||
context,
|
||||
request_counter,
|
||||
)
|
||||
.await?;
|
||||
verify_person_in_community(&self.attributed_to, &community, context, request_counter).await?;
|
||||
verify_is_public(&self.to)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -247,6 +248,18 @@ impl ApubObject for ApubComment {
|
|||
.dereference(context, request_counter)
|
||||
.await?;
|
||||
let (post, parent_comment_id) = note.get_parents(context, request_counter).await?;
|
||||
let community_id = post.community_id;
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read(conn, community_id)
|
||||
})
|
||||
.await??;
|
||||
verify_person_in_community(
|
||||
¬e.attributed_to,
|
||||
&community.into(),
|
||||
context,
|
||||
request_counter,
|
||||
)
|
||||
.await?;
|
||||
if post.locked {
|
||||
return Err(anyhow!("Post is locked").into());
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ use crate::{
|
|||
generate_moderators_url,
|
||||
generate_outbox_url,
|
||||
objects::{get_summary_from_string_or_source, tombstone::Tombstone, ImageObject, Source},
|
||||
CommunityType,
|
||||
};
|
||||
use activitystreams::{
|
||||
actor::{kind::GroupType, Endpoints},
|
||||
|
@ -55,7 +54,7 @@ pub struct Group {
|
|||
context: OneOrMany<AnyBase>,
|
||||
#[serde(rename = "type")]
|
||||
kind: GroupType,
|
||||
id: Url,
|
||||
pub(crate) id: Url,
|
||||
/// username, set at account creation and can never be changed
|
||||
preferred_username: String,
|
||||
/// title (can be changed at any time)
|
||||
|
@ -81,16 +80,12 @@ pub struct Group {
|
|||
}
|
||||
|
||||
impl Group {
|
||||
pub(crate) fn id(&self, expected_domain: &Url) -> Result<&Url, LemmyError> {
|
||||
verify_domains_match(&self.id, expected_domain)?;
|
||||
Ok(&self.id)
|
||||
}
|
||||
pub(crate) async fn from_apub_to_form(
|
||||
group: &Group,
|
||||
expected_domain: &Url,
|
||||
settings: &Settings,
|
||||
) -> Result<CommunityForm, LemmyError> {
|
||||
let actor_id = Some(group.id(expected_domain)?.clone().into());
|
||||
verify_domains_match(expected_domain, &group.id)?;
|
||||
let name = group.preferred_username.clone();
|
||||
let title = group.name.clone();
|
||||
let description = get_summary_from_string_or_source(&group.summary, &group.source);
|
||||
|
@ -110,7 +105,7 @@ impl Group {
|
|||
updated: group.updated.map(|u| u.naive_local()),
|
||||
deleted: None,
|
||||
nsfw: Some(group.sensitive.unwrap_or(false)),
|
||||
actor_id,
|
||||
actor_id: Some(group.id.clone().into()),
|
||||
local: Some(false),
|
||||
private_key: None,
|
||||
public_key: Some(group.public_key.public_key_pem.clone()),
|
||||
|
@ -283,14 +278,9 @@ impl ActorType for ApubCommunity {
|
|||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl CommunityType for Community {
|
||||
fn followers_url(&self) -> Url {
|
||||
self.followers_url.clone().into()
|
||||
}
|
||||
|
||||
impl ApubCommunity {
|
||||
/// For a given community, returns the inboxes of all followers.
|
||||
async fn get_follower_inboxes(
|
||||
pub(crate) async fn get_follower_inboxes(
|
||||
&self,
|
||||
pool: &DbPool,
|
||||
settings: &Settings,
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
use crate::{
|
||||
activities::{extract_community, verify_is_public, verify_person_in_community},
|
||||
activities::{verify_is_public, verify_person_in_community},
|
||||
context::lemmy_context,
|
||||
fetcher::object_id::ObjectId,
|
||||
objects::{person::ApubPerson, tombstone::Tombstone, ImageObject, Source},
|
||||
objects::{
|
||||
community::ApubCommunity,
|
||||
person::ApubPerson,
|
||||
tombstone::Tombstone,
|
||||
ImageObject,
|
||||
Source,
|
||||
},
|
||||
};
|
||||
use activitystreams::{
|
||||
base::AnyBase,
|
||||
|
@ -11,10 +17,11 @@ use activitystreams::{
|
|||
public,
|
||||
unparsed::Unparsed,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use chrono::{DateTime, FixedOffset, NaiveDateTime};
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
traits::{ActorType, ApubObject},
|
||||
traits::ApubObject,
|
||||
values::{MediaTypeHtml, MediaTypeMarkdown},
|
||||
verify::verify_domains_match,
|
||||
};
|
||||
|
@ -94,20 +101,32 @@ impl Page {
|
|||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let community = extract_community(&self.to, context, request_counter).await?;
|
||||
let community = self.extract_community(context, request_counter).await?;
|
||||
|
||||
check_slurs(&self.name, &context.settings().slur_regex())?;
|
||||
verify_domains_match(self.attributed_to.inner(), &self.id.clone())?;
|
||||
verify_person_in_community(
|
||||
&self.attributed_to,
|
||||
&ObjectId::new(community.actor_id()),
|
||||
context,
|
||||
request_counter,
|
||||
)
|
||||
.await?;
|
||||
verify_person_in_community(&self.attributed_to, &community, context, request_counter).await?;
|
||||
verify_is_public(&self.to.clone())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn extract_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<ApubCommunity, LemmyError> {
|
||||
let mut to_iter = self.to.iter();
|
||||
loop {
|
||||
if let Some(cid) = to_iter.next() {
|
||||
let cid = ObjectId::new(cid.clone());
|
||||
if let Ok(c) = cid.dereference(context, request_counter).await {
|
||||
break Ok(c);
|
||||
}
|
||||
} else {
|
||||
return Err(anyhow!("No community found in cc").into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -223,7 +242,8 @@ impl ApubObject for ApubPost {
|
|||
.attributed_to
|
||||
.dereference(context, request_counter)
|
||||
.await?;
|
||||
let community = extract_community(&page.to, context, request_counter).await?;
|
||||
let community = page.extract_community(context, request_counter).await?;
|
||||
verify_person_in_community(&page.attributed_to, &community, context, request_counter).await?;
|
||||
|
||||
let thumbnail_url: Option<Url> = page.image.clone().map(|i| i.url);
|
||||
let (metadata_res, pictrs_thumbnail) = if let Some(url) = &page.url {
|
||||
|
|
|
@ -36,7 +36,7 @@ use url::Url;
|
|||
#[skip_serializing_none]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Note {
|
||||
pub struct ChatMessage {
|
||||
#[serde(rename = "@context")]
|
||||
context: OneOrMany<AnyBase>,
|
||||
r#type: ChatMessageType,
|
||||
|
@ -58,7 +58,7 @@ pub enum ChatMessageType {
|
|||
ChatMessage,
|
||||
}
|
||||
|
||||
impl Note {
|
||||
impl ChatMessage {
|
||||
pub(crate) fn id_unchecked(&self) -> &Url {
|
||||
&self.id
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ impl From<PrivateMessage> for ApubPrivateMessage {
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ApubObject for ApubPrivateMessage {
|
||||
type DataType = LemmyContext;
|
||||
type ApubType = Note;
|
||||
type ApubType = ChatMessage;
|
||||
type TombstoneType = Tombstone;
|
||||
|
||||
fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
|
||||
|
@ -128,7 +128,7 @@ impl ApubObject for ApubPrivateMessage {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn to_apub(&self, context: &LemmyContext) -> Result<Note, LemmyError> {
|
||||
async fn to_apub(&self, context: &LemmyContext) -> Result<ChatMessage, LemmyError> {
|
||||
let creator_id = self.creator_id;
|
||||
let creator = blocking(context.pool(), move |conn| Person::read(conn, creator_id)).await??;
|
||||
|
||||
|
@ -136,7 +136,7 @@ impl ApubObject for ApubPrivateMessage {
|
|||
let recipient =
|
||||
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
|
||||
|
||||
let note = Note {
|
||||
let note = ChatMessage {
|
||||
context: lemmy_context(),
|
||||
r#type: ChatMessageType::ChatMessage,
|
||||
id: self.ap_id.clone().into(),
|
||||
|
@ -160,7 +160,7 @@ impl ApubObject for ApubPrivateMessage {
|
|||
}
|
||||
|
||||
async fn from_apub(
|
||||
note: &Note,
|
||||
note: &ChatMessage,
|
||||
context: &LemmyContext,
|
||||
expected_domain: &Url,
|
||||
request_counter: &mut i32,
|
||||
|
|
|
@ -8,7 +8,6 @@ use url::Url;
|
|||
pub trait ActivityFields {
|
||||
fn id_unchecked(&self) -> &Url;
|
||||
fn actor(&self) -> &Url;
|
||||
fn cc(&self) -> Vec<Url>;
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
|
|
|
@ -145,36 +145,18 @@ pub fn derive_activity_fields(input: proc_macro::TokenStream) -> proc_macro::Tok
|
|||
let impl_actor = variants
|
||||
.iter()
|
||||
.map(|v| generate_match_arm(&name, v, "e! {a.actor()}));
|
||||
let impl_cc = variants
|
||||
.iter()
|
||||
.map(|v| generate_match_arm(&name, v, "e! {a.cc()}));
|
||||
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)* } }
|
||||
fn cc(&self) -> Vec<url::Url> { match self { #(#impl_cc)* } }
|
||||
}
|
||||
}
|
||||
}
|
||||
Data::Struct(s) => {
|
||||
// check if the struct has a field "cc", and generate impl for cc() function depending on that
|
||||
let has_cc = if let syn::Fields::Named(n) = s.fields {
|
||||
n.named
|
||||
.iter()
|
||||
.any(|i| format!("{}", i.ident.as_ref().unwrap()) == "cc")
|
||||
} else {
|
||||
unimplemented!()
|
||||
};
|
||||
let cc_impl = if has_cc {
|
||||
quote! {self.cc.iter().map(|i| i.clone().into()).collect()}
|
||||
} else {
|
||||
quote! {vec![]}
|
||||
};
|
||||
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() }
|
||||
fn cc(&self) -> Vec<url::Url> { #cc_impl }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue