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