mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-27 03:41:02 +00:00
Add method ApubObject.verify()
This commit is contained in:
parent
02ce7bdc7d
commit
a5a674a270
20 changed files with 284 additions and 191 deletions
|
@ -85,9 +85,7 @@ impl ActivityHandler for CreateOrUpdateComment {
|
||||||
check_community_deleted_or_removed(&community)?;
|
check_community_deleted_or_removed(&community)?;
|
||||||
check_post_deleted_or_removed(&post)?;
|
check_post_deleted_or_removed(&post)?;
|
||||||
|
|
||||||
// TODO: should add a check that the correct community is in cc (probably needs changes to
|
ApubComment::verify(&self.object, self.actor.inner(), context, request_counter).await?;
|
||||||
// comment deserialization)
|
|
||||||
self.object.verify(context, request_counter).await?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,8 +94,7 @@ impl ActivityHandler for CreateOrUpdateComment {
|
||||||
context: &Data<LemmyContext>,
|
context: &Data<LemmyContext>,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let comment =
|
let comment = ApubComment::from_apub(self.object, context, request_counter).await?;
|
||||||
ApubComment::from_apub(self.object, context, self.actor.inner(), request_counter).await?;
|
|
||||||
let recipients = get_notif_recipients(&self.actor, &comment, context, request_counter).await?;
|
let recipients = get_notif_recipients(&self.actor, &comment, context, request_counter).await?;
|
||||||
let notif_type = match self.kind {
|
let notif_type = match self.kind {
|
||||||
CreateOrUpdateType::Create => UserOperationCrud::CreateComment,
|
CreateOrUpdateType::Create => UserOperationCrud::CreateComment,
|
||||||
|
|
|
@ -63,6 +63,13 @@ impl ActivityHandler for UpdateCommunity {
|
||||||
let community = self.get_community(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_person_in_community(&self.actor, &community, context, request_counter).await?;
|
||||||
verify_mod_action(&self.actor, &community, context, request_counter).await?;
|
verify_mod_action(&self.actor, &community, context, request_counter).await?;
|
||||||
|
ApubCommunity::verify(
|
||||||
|
&self.object,
|
||||||
|
&community.actor_id.clone().into(),
|
||||||
|
context,
|
||||||
|
request_counter,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,10 +80,7 @@ impl ActivityHandler for UpdateCommunity {
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let community = self.get_community(context, request_counter).await?;
|
let community = self.get_community(context, request_counter).await?;
|
||||||
|
|
||||||
let updated_community = self
|
let updated_community = self.object.into_form()?;
|
||||||
.object
|
|
||||||
.into_form(&community.actor_id.clone().into(), &context.settings())
|
|
||||||
.await?;
|
|
||||||
let cf = CommunityForm {
|
let cf = CommunityForm {
|
||||||
name: updated_community.name,
|
name: updated_community.name,
|
||||||
title: updated_community.title,
|
title: updated_community.title,
|
||||||
|
|
|
@ -104,7 +104,7 @@ impl ActivityHandler for CreateOrUpdatePost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.object.verify(context, request_counter).await?;
|
ApubPost::verify(&self.object, self.actor.inner(), context, request_counter).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,9 +113,7 @@ impl ActivityHandler for CreateOrUpdatePost {
|
||||||
context: &Data<LemmyContext>,
|
context: &Data<LemmyContext>,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let actor = self.actor.dereference(context, request_counter).await?;
|
let post = ApubPost::from_apub(self.object, context, request_counter).await?;
|
||||||
let post =
|
|
||||||
ApubPost::from_apub(self.object, context, &actor.actor_id(), request_counter).await?;
|
|
||||||
|
|
||||||
let notif_type = match self.kind {
|
let notif_type = match self.kind {
|
||||||
CreateOrUpdateType::Create => UserOperationCrud::CreatePost,
|
CreateOrUpdateType::Create => UserOperationCrud::CreatePost,
|
||||||
|
|
|
@ -57,7 +57,7 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage {
|
||||||
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
verify_activity(&self.id, self.actor.inner(), &context.settings())?;
|
||||||
verify_person(&self.actor, context, request_counter).await?;
|
verify_person(&self.actor, context, request_counter).await?;
|
||||||
verify_domains_match(self.actor.inner(), self.object.id.inner())?;
|
verify_domains_match(self.actor.inner(), self.object.id.inner())?;
|
||||||
self.object.verify(context, request_counter).await?;
|
ApubPrivateMessage::verify(&self.object, self.actor.inner(), context, request_counter).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,8 +67,7 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage {
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let private_message =
|
let private_message =
|
||||||
ApubPrivateMessage::from_apub(self.object, context, self.actor.inner(), request_counter)
|
ApubPrivateMessage::from_apub(self.object, context, request_counter).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
let notif_type = match self.kind {
|
let notif_type = match self.kind {
|
||||||
CreateOrUpdateType::Create => UserOperationCrud::CreatePrivateMessage,
|
CreateOrUpdateType::Create => UserOperationCrud::CreatePrivateMessage,
|
||||||
|
|
|
@ -66,13 +66,21 @@ impl ApubObject for ApubCommunityModerators {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn verify(
|
||||||
|
group_moderators: &GroupModerators,
|
||||||
|
expected_domain: &Url,
|
||||||
|
_context: &CommunityContext,
|
||||||
|
_request_counter: &mut i32,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
verify_domains_match(&group_moderators.id, expected_domain)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
apub: Self::ApubType,
|
apub: Self::ApubType,
|
||||||
data: &Self::DataType,
|
data: &Self::DataType,
|
||||||
expected_domain: &Url,
|
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<Self, LemmyError> {
|
) -> Result<Self, LemmyError> {
|
||||||
verify_domains_match(expected_domain, &apub.id)?;
|
|
||||||
let community_id = data.0.id;
|
let community_id = data.0.id;
|
||||||
let current_moderators = blocking(data.1.pool(), move |conn| {
|
let current_moderators = blocking(data.1.pool(), move |conn| {
|
||||||
CommunityModeratorView::for_community(conn, community_id)
|
CommunityModeratorView::for_community(conn, community_id)
|
||||||
|
@ -165,7 +173,10 @@ mod tests {
|
||||||
0: community,
|
0: community,
|
||||||
1: context,
|
1: context,
|
||||||
};
|
};
|
||||||
ApubCommunityModerators::from_apub(json, &community_context, &url, &mut request_counter)
|
ApubCommunityModerators::verify(&json, &url, &community_context, &mut request_counter)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
ApubCommunityModerators::from_apub(json, &community_context, &mut request_counter)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(request_counter, 0);
|
assert_eq!(request_counter, 0);
|
||||||
|
|
|
@ -85,13 +85,21 @@ impl ApubObject for ApubCommunityOutbox {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn verify(
|
||||||
|
group_outbox: &GroupOutbox,
|
||||||
|
expected_domain: &Url,
|
||||||
|
_context: &CommunityContext,
|
||||||
|
_request_counter: &mut i32,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
verify_domains_match(expected_domain, &group_outbox.id)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
apub: Self::ApubType,
|
apub: Self::ApubType,
|
||||||
data: &Self::DataType,
|
data: &Self::DataType,
|
||||||
expected_domain: &Url,
|
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<Self, LemmyError> {
|
) -> Result<Self, LemmyError> {
|
||||||
verify_domains_match(expected_domain, &apub.id)?;
|
|
||||||
let mut outbox_activities = apub.ordered_items;
|
let mut outbox_activities = apub.ordered_items;
|
||||||
if outbox_activities.len() > 20 {
|
if outbox_activities.len() > 20 {
|
||||||
outbox_activities = outbox_activities[0..20].to_vec();
|
outbox_activities = outbox_activities[0..20].to_vec();
|
||||||
|
|
|
@ -61,19 +61,30 @@ impl ApubObject for PostOrComment {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn verify(
|
||||||
|
apub: &Self::ApubType,
|
||||||
|
expected_domain: &Url,
|
||||||
|
data: &Self::DataType,
|
||||||
|
request_counter: &mut i32,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
match apub {
|
||||||
|
PageOrNote::Page(a) => ApubPost::verify(a, expected_domain, data, request_counter).await,
|
||||||
|
PageOrNote::Note(a) => ApubComment::verify(a, expected_domain, data, request_counter).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
apub: PageOrNote,
|
apub: PageOrNote,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
expected_domain: &Url,
|
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<Self, LemmyError> {
|
) -> Result<Self, LemmyError> {
|
||||||
Ok(match apub {
|
Ok(match apub {
|
||||||
PageOrNote::Page(p) => PostOrComment::Post(
|
PageOrNote::Page(p) => {
|
||||||
ApubPost::from_apub(p, context, expected_domain, request_counter).await?,
|
PostOrComment::Post(ApubPost::from_apub(p, context, request_counter).await?)
|
||||||
),
|
}
|
||||||
PageOrNote::Note(n) => PostOrComment::Comment(
|
PageOrNote::Note(n) => {
|
||||||
ApubComment::from_apub(n, context, expected_domain, request_counter).await?,
|
PostOrComment::Comment(ApubComment::from_apub(n, context, request_counter).await?)
|
||||||
),
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,19 +163,40 @@ impl ApubObject for SearchableObjects {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn verify(
|
||||||
|
apub: &Self::ApubType,
|
||||||
|
expected_domain: &Url,
|
||||||
|
data: &Self::DataType,
|
||||||
|
request_counter: &mut i32,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
match apub {
|
||||||
|
SearchableApubTypes::Group(a) => {
|
||||||
|
ApubCommunity::verify(a, expected_domain, data, request_counter).await
|
||||||
|
}
|
||||||
|
SearchableApubTypes::Person(a) => {
|
||||||
|
ApubPerson::verify(a, expected_domain, data, request_counter).await
|
||||||
|
}
|
||||||
|
SearchableApubTypes::Page(a) => {
|
||||||
|
ApubPost::verify(a, expected_domain, data, request_counter).await
|
||||||
|
}
|
||||||
|
SearchableApubTypes::Note(a) => {
|
||||||
|
ApubComment::verify(a, expected_domain, data, request_counter).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
apub: Self::ApubType,
|
apub: Self::ApubType,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
ed: &Url,
|
|
||||||
rc: &mut i32,
|
rc: &mut i32,
|
||||||
) -> Result<Self, LemmyError> {
|
) -> Result<Self, LemmyError> {
|
||||||
use SearchableApubTypes as SAT;
|
use SearchableApubTypes as SAT;
|
||||||
use SearchableObjects as SO;
|
use SearchableObjects as SO;
|
||||||
Ok(match apub {
|
Ok(match apub {
|
||||||
SAT::Group(g) => SO::Community(ApubCommunity::from_apub(g, context, ed, rc).await?),
|
SAT::Group(g) => SO::Community(ApubCommunity::from_apub(g, context, rc).await?),
|
||||||
SAT::Person(p) => SO::Person(ApubPerson::from_apub(p, context, ed, rc).await?),
|
SAT::Person(p) => SO::Person(ApubPerson::from_apub(p, context, rc).await?),
|
||||||
SAT::Page(p) => SO::Post(ApubPost::from_apub(p, context, ed, rc).await?),
|
SAT::Page(p) => SO::Post(ApubPost::from_apub(p, context, rc).await?),
|
||||||
SAT::Note(n) => SO::Comment(ApubComment::from_apub(n, context, ed, rc).await?),
|
SAT::Note(n) => SO::Comment(ApubComment::from_apub(n, context, rc).await?),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,19 +62,34 @@ impl ApubObject for UserOrCommunity {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn verify(
|
||||||
|
apub: &Self::ApubType,
|
||||||
|
expected_domain: &Url,
|
||||||
|
data: &Self::DataType,
|
||||||
|
request_counter: &mut i32,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
match apub {
|
||||||
|
PersonOrGroup::Person(a) => {
|
||||||
|
ApubPerson::verify(a, expected_domain, data, request_counter).await
|
||||||
|
}
|
||||||
|
PersonOrGroup::Group(a) => {
|
||||||
|
ApubCommunity::verify(a, expected_domain, data, request_counter).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
apub: Self::ApubType,
|
apub: Self::ApubType,
|
||||||
data: &Self::DataType,
|
data: &Self::DataType,
|
||||||
expected_domain: &Url,
|
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<Self, LemmyError> {
|
) -> Result<Self, LemmyError> {
|
||||||
Ok(match apub {
|
Ok(match apub {
|
||||||
PersonOrGroup::Person(p) => UserOrCommunity::User(
|
PersonOrGroup::Person(p) => {
|
||||||
ApubPerson::from_apub(p, data, expected_domain, request_counter).await?,
|
UserOrCommunity::User(ApubPerson::from_apub(p, data, request_counter).await?)
|
||||||
),
|
}
|
||||||
PersonOrGroup::Group(p) => UserOrCommunity::Community(
|
PersonOrGroup::Group(p) => {
|
||||||
ApubCommunity::from_apub(p, data, expected_domain, request_counter).await?,
|
UserOrCommunity::Community(ApubCommunity::from_apub(p, data, request_counter).await?)
|
||||||
),
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::verify_person_in_community,
|
activities::{verify_is_public, verify_person_in_community},
|
||||||
check_is_apub_id_valid,
|
check_is_apub_id_valid,
|
||||||
protocol::{
|
protocol::{
|
||||||
objects::{
|
objects::{
|
||||||
|
@ -129,21 +129,16 @@ impl ApubObject for ApubComment {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a `Note` to `Comment`.
|
async fn verify(
|
||||||
///
|
note: &Note,
|
||||||
/// If the parent community, post and comment(s) are not known locally, these are also fetched.
|
|
||||||
async fn from_apub(
|
|
||||||
note: Note,
|
|
||||||
context: &LemmyContext,
|
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<ApubComment, LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
verify_domains_match(note.id.inner(), expected_domain)?;
|
verify_domains_match(note.id.inner(), expected_domain)?;
|
||||||
let creator = note
|
verify_domains_match(note.attributed_to.inner(), note.id.inner())?;
|
||||||
.attributed_to
|
verify_is_public(¬e.to)?;
|
||||||
.dereference(context, request_counter)
|
let (post, _) = note.get_parents(context, request_counter).await?;
|
||||||
.await?;
|
|
||||||
let (post, parent_comment_id) = note.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 = blocking(context.pool(), move |conn| {
|
||||||
Community::read(conn, community_id)
|
Community::read(conn, community_id)
|
||||||
|
@ -160,6 +155,22 @@ impl ApubObject for ApubComment {
|
||||||
if post.locked {
|
if post.locked {
|
||||||
return Err(anyhow!("Post is locked").into());
|
return Err(anyhow!("Post is locked").into());
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts a `Note` to `Comment`.
|
||||||
|
///
|
||||||
|
/// If the parent community, post and comment(s) are not known locally, these are also fetched.
|
||||||
|
async fn from_apub(
|
||||||
|
note: Note,
|
||||||
|
context: &LemmyContext,
|
||||||
|
request_counter: &mut i32,
|
||||||
|
) -> Result<ApubComment, LemmyError> {
|
||||||
|
let creator = note
|
||||||
|
.attributed_to
|
||||||
|
.dereference(context, request_counter)
|
||||||
|
.await?;
|
||||||
|
let (post, parent_comment_id) = note.get_parents(context, request_counter).await?;
|
||||||
|
|
||||||
let content = if let SourceCompat::Lemmy(source) = ¬e.source {
|
let content = if let SourceCompat::Lemmy(source) = ¬e.source {
|
||||||
source.content.clone()
|
source.content.clone()
|
||||||
|
@ -205,7 +216,10 @@ pub(crate) mod tests {
|
||||||
let person = parse_lemmy_person(context).await;
|
let person = parse_lemmy_person(context).await;
|
||||||
let community = parse_lemmy_community(context).await;
|
let community = parse_lemmy_community(context).await;
|
||||||
let post_json = file_to_json_object("assets/lemmy/objects/page.json");
|
let post_json = file_to_json_object("assets/lemmy/objects/page.json");
|
||||||
let post = ApubPost::from_apub(post_json, context, url, &mut 0)
|
ApubPost::verify(&post_json, url, context, &mut 0)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let post = ApubPost::from_apub(post_json, context, &mut 0)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
(person, community, post)
|
(person, community, post)
|
||||||
|
@ -226,7 +240,10 @@ pub(crate) mod tests {
|
||||||
|
|
||||||
let json: Note = file_to_json_object("assets/lemmy/objects/note.json");
|
let json: Note = file_to_json_object("assets/lemmy/objects/note.json");
|
||||||
let mut request_counter = 0;
|
let mut request_counter = 0;
|
||||||
let comment = ApubComment::from_apub(json.clone(), &context, &url, &mut request_counter)
|
ApubComment::verify(&json, &url, &context, &mut request_counter)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let comment = ApubComment::from_apub(json.clone(), &context, &mut request_counter)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -254,12 +271,18 @@ pub(crate) mod tests {
|
||||||
Url::parse("https://queer.hacktivis.me/objects/8d4973f4-53de-49cd-8c27-df160e16a9c2")
|
Url::parse("https://queer.hacktivis.me/objects/8d4973f4-53de-49cd-8c27-df160e16a9c2")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let person_json = file_to_json_object("assets/pleroma/objects/person.json");
|
let person_json = file_to_json_object("assets/pleroma/objects/person.json");
|
||||||
ApubPerson::from_apub(person_json, &context, &pleroma_url, &mut 0)
|
ApubPerson::verify(&person_json, &pleroma_url, &context, &mut 0)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
ApubPerson::from_apub(person_json, &context, &mut 0)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let json = file_to_json_object("assets/pleroma/objects/note.json");
|
let json = file_to_json_object("assets/pleroma/objects/note.json");
|
||||||
let mut request_counter = 0;
|
let mut request_counter = 0;
|
||||||
let comment = ApubComment::from_apub(json, &context, &pleroma_url, &mut request_counter)
|
ApubComment::verify(&json, &pleroma_url, &context, &mut request_counter)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let comment = ApubComment::from_apub(json, &context, &mut request_counter)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -124,14 +124,22 @@ impl ApubObject for ApubCommunity {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn verify(
|
||||||
|
group: &Group,
|
||||||
|
expected_domain: &Url,
|
||||||
|
context: &LemmyContext,
|
||||||
|
_request_counter: &mut i32,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
group.verify(expected_domain, context).await
|
||||||
|
}
|
||||||
|
|
||||||
/// Converts a `Group` to `Community`, inserts it into the database and updates moderators.
|
/// Converts a `Group` to `Community`, inserts it into the database and updates moderators.
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
group: Group,
|
group: Group,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
expected_domain: &Url,
|
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<ApubCommunity, LemmyError> {
|
) -> Result<ApubCommunity, LemmyError> {
|
||||||
let form = Group::into_form(group.clone(), expected_domain, &context.settings()).await?;
|
let form = Group::into_form(group.clone())?;
|
||||||
|
|
||||||
// Fetching mods and outbox is not necessary for Lemmy to work, so ignore errors. Besides,
|
// Fetching mods and outbox is not necessary for Lemmy to work, so ignore errors. Besides,
|
||||||
// we need to ignore these errors so that tests can work entirely offline.
|
// we need to ignore these errors so that tests can work entirely offline.
|
||||||
|
@ -232,7 +240,10 @@ pub(crate) mod tests {
|
||||||
|
|
||||||
let url = Url::parse("https://enterprise.lemmy.ml/c/tenforward").unwrap();
|
let url = Url::parse("https://enterprise.lemmy.ml/c/tenforward").unwrap();
|
||||||
let mut request_counter = 0;
|
let mut request_counter = 0;
|
||||||
let community = ApubCommunity::from_apub(json, context, &url, &mut request_counter)
|
ApubCommunity::verify(&json, &url, context, &mut request_counter)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let community = ApubCommunity::from_apub(json, context, &mut request_counter)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// this makes two requests to the (intentionally) broken outbox/moderators collections
|
// this makes two requests to the (intentionally) broken outbox/moderators collections
|
||||||
|
|
|
@ -125,32 +125,31 @@ impl ApubObject for ApubPerson {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn verify(
|
||||||
|
person: &Person,
|
||||||
|
expected_domain: &Url,
|
||||||
|
context: &LemmyContext,
|
||||||
|
_request_counter: &mut i32,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
verify_domains_match(person.id.inner(), expected_domain)?;
|
||||||
|
check_is_apub_id_valid(person.id.inner(), false, &context.settings())?;
|
||||||
|
|
||||||
|
let slur_regex = &context.settings().slur_regex();
|
||||||
|
check_slurs(&person.preferred_username, slur_regex)?;
|
||||||
|
check_slurs_opt(&person.name, slur_regex)?;
|
||||||
|
let bio = get_summary_from_string_or_source(&person.summary, &person.source);
|
||||||
|
check_slurs_opt(&bio, slur_regex)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
person: Person,
|
person: Person,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
expected_domain: &Url,
|
|
||||||
_request_counter: &mut i32,
|
_request_counter: &mut i32,
|
||||||
) -> Result<ApubPerson, LemmyError> {
|
) -> Result<ApubPerson, LemmyError> {
|
||||||
verify_domains_match(person.id.inner(), expected_domain)?;
|
|
||||||
let name = person.preferred_username;
|
|
||||||
let display_name: Option<String> = person.name;
|
|
||||||
let bio = get_summary_from_string_or_source(&person.summary, &person.source);
|
|
||||||
let shared_inbox = person.endpoints.shared_inbox.map(|s| s.into());
|
|
||||||
let bot_account = match person.kind {
|
|
||||||
UserTypes::Person => false,
|
|
||||||
UserTypes::Service => true,
|
|
||||||
};
|
|
||||||
|
|
||||||
let slur_regex = &context.settings().slur_regex();
|
|
||||||
check_slurs(&name, slur_regex)?;
|
|
||||||
check_slurs_opt(&display_name, slur_regex)?;
|
|
||||||
check_slurs_opt(&bio, slur_regex)?;
|
|
||||||
|
|
||||||
check_is_apub_id_valid(person.id.inner(), false, &context.settings())?;
|
|
||||||
|
|
||||||
let person_form = PersonForm {
|
let person_form = PersonForm {
|
||||||
name,
|
name: person.preferred_username,
|
||||||
display_name: Some(display_name),
|
display_name: Some(person.name),
|
||||||
banned: None,
|
banned: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
avatar: Some(person.icon.map(|i| i.url.into())),
|
avatar: Some(person.icon.map(|i| i.url.into())),
|
||||||
|
@ -158,15 +157,18 @@ impl ApubObject for ApubPerson {
|
||||||
published: person.published.map(|u| u.naive_local()),
|
published: person.published.map(|u| u.naive_local()),
|
||||||
updated: person.updated.map(|u| u.naive_local()),
|
updated: person.updated.map(|u| u.naive_local()),
|
||||||
actor_id: Some(person.id.into()),
|
actor_id: Some(person.id.into()),
|
||||||
bio: Some(bio),
|
bio: Some(get_summary_from_string_or_source(
|
||||||
|
&person.summary,
|
||||||
|
&person.source,
|
||||||
|
)),
|
||||||
local: Some(false),
|
local: Some(false),
|
||||||
admin: Some(false),
|
admin: Some(false),
|
||||||
bot_account: Some(bot_account),
|
bot_account: Some(person.kind == UserTypes::Service),
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: Some(Some(person.public_key.public_key_pem)),
|
public_key: Some(Some(person.public_key.public_key_pem)),
|
||||||
last_refreshed_at: Some(naive_now()),
|
last_refreshed_at: Some(naive_now()),
|
||||||
inbox_url: Some(person.inbox.into()),
|
inbox_url: Some(person.inbox.into()),
|
||||||
shared_inbox_url: Some(shared_inbox),
|
shared_inbox_url: Some(person.endpoints.shared_inbox.map(|s| s.into())),
|
||||||
matrix_user_id: Some(person.matrix_user_id),
|
matrix_user_id: Some(person.matrix_user_id),
|
||||||
};
|
};
|
||||||
let person = blocking(context.pool(), move |conn| {
|
let person = blocking(context.pool(), move |conn| {
|
||||||
|
@ -210,7 +212,10 @@ pub(crate) mod tests {
|
||||||
let json = file_to_json_object("assets/lemmy/objects/person.json");
|
let json = file_to_json_object("assets/lemmy/objects/person.json");
|
||||||
let url = Url::parse("https://enterprise.lemmy.ml/u/picard").unwrap();
|
let url = Url::parse("https://enterprise.lemmy.ml/u/picard").unwrap();
|
||||||
let mut request_counter = 0;
|
let mut request_counter = 0;
|
||||||
let person = ApubPerson::from_apub(json, context, &url, &mut request_counter)
|
ApubPerson::verify(&json, &url, context, &mut request_counter)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let person = ApubPerson::from_apub(json, context, &mut request_counter)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(request_counter, 0);
|
assert_eq!(request_counter, 0);
|
||||||
|
@ -238,7 +243,10 @@ pub(crate) mod tests {
|
||||||
let json = file_to_json_object("assets/pleroma/objects/person.json");
|
let json = file_to_json_object("assets/pleroma/objects/person.json");
|
||||||
let url = Url::parse("https://queer.hacktivis.me/users/lanodan").unwrap();
|
let url = Url::parse("https://queer.hacktivis.me/users/lanodan").unwrap();
|
||||||
let mut request_counter = 0;
|
let mut request_counter = 0;
|
||||||
let person = ApubPerson::from_apub(json, &context, &url, &mut request_counter)
|
ApubPerson::verify(&json, &url, &context, &mut request_counter)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let person = ApubPerson::from_apub(json, &context, &mut request_counter)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::verify_person_in_community,
|
activities::{verify_is_public, verify_person_in_community},
|
||||||
check_is_apub_id_valid,
|
check_is_apub_id_valid,
|
||||||
protocol::{
|
protocol::{
|
||||||
objects::{page::Page, tombstone::Tombstone},
|
objects::{page::Page, tombstone::Tombstone},
|
||||||
|
@ -30,7 +30,7 @@ use lemmy_db_schema::{
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
request::fetch_site_data,
|
request::fetch_site_data,
|
||||||
utils::{convert_datetime, markdown_to_html, remove_slurs},
|
utils::{check_slurs, convert_datetime, markdown_to_html, remove_slurs},
|
||||||
LemmyError,
|
LemmyError,
|
||||||
};
|
};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
@ -133,24 +133,37 @@ impl ApubObject for ApubPost {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn from_apub(
|
async fn verify(
|
||||||
page: Page,
|
page: &Page,
|
||||||
context: &LemmyContext,
|
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<ApubPost, LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
// We can't verify the domain in case of mod action, because the mod may be on a different
|
// We can't verify the domain in case of mod action, because the mod may be on a different
|
||||||
// instance from the post author.
|
// instance from the post author.
|
||||||
if !page.is_mod_action(context).await? {
|
if !page.is_mod_action(context).await? {
|
||||||
verify_domains_match(page.id.inner(), expected_domain)?;
|
verify_domains_match(page.id.inner(), expected_domain)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let community = page.extract_community(context, request_counter).await?;
|
||||||
|
check_is_apub_id_valid(page.id.inner(), community.local, &context.settings())?;
|
||||||
|
verify_person_in_community(&page.attributed_to, &community, context, request_counter).await?;
|
||||||
|
check_slurs(&page.name, &context.settings().slur_regex())?;
|
||||||
|
verify_domains_match(page.attributed_to.inner(), page.id.inner())?;
|
||||||
|
verify_is_public(&page.to.clone())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn from_apub(
|
||||||
|
page: Page,
|
||||||
|
context: &LemmyContext,
|
||||||
|
request_counter: &mut i32,
|
||||||
|
) -> Result<ApubPost, LemmyError> {
|
||||||
let creator = page
|
let creator = page
|
||||||
.attributed_to
|
.attributed_to
|
||||||
.dereference(context, request_counter)
|
.dereference(context, request_counter)
|
||||||
.await?;
|
.await?;
|
||||||
let community = page.extract_community(context, request_counter).await?;
|
let community = page.extract_community(context, request_counter).await?;
|
||||||
check_is_apub_id_valid(page.id.inner(), community.local, &context.settings())?;
|
|
||||||
verify_person_in_community(&page.attributed_to, &community, context, request_counter).await?;
|
|
||||||
|
|
||||||
let thumbnail_url: Option<Url> = page.image.map(|i| i.url);
|
let thumbnail_url: Option<Url> = page.image.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 {
|
||||||
|
@ -212,7 +225,10 @@ mod tests {
|
||||||
let json = file_to_json_object("assets/lemmy/objects/page.json");
|
let json = file_to_json_object("assets/lemmy/objects/page.json");
|
||||||
let url = Url::parse("https://enterprise.lemmy.ml/post/55143").unwrap();
|
let url = Url::parse("https://enterprise.lemmy.ml/post/55143").unwrap();
|
||||||
let mut request_counter = 0;
|
let mut request_counter = 0;
|
||||||
let post = ApubPost::from_apub(json, &context, &url, &mut request_counter)
|
ApubPost::verify(&json, &url, &context, &mut request_counter)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let post = ApubPost::from_apub(json, &context, &mut request_counter)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::protocol::{
|
||||||
objects::chat_message::{ChatMessage, ChatMessageType},
|
objects::chat_message::{ChatMessage, ChatMessageType},
|
||||||
Source,
|
Source,
|
||||||
};
|
};
|
||||||
|
use anyhow::anyhow;
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use html2md::parse_html;
|
use html2md::parse_html;
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
|
@ -100,14 +101,29 @@ impl ApubObject for ApubPrivateMessage {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn verify(
|
||||||
|
note: &ChatMessage,
|
||||||
|
expected_domain: &Url,
|
||||||
|
context: &LemmyContext,
|
||||||
|
request_counter: &mut i32,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
verify_domains_match(note.id.inner(), expected_domain)?;
|
||||||
|
verify_domains_match(note.attributed_to.inner(), note.id.inner())?;
|
||||||
|
let person = note
|
||||||
|
.attributed_to
|
||||||
|
.dereference(context, request_counter)
|
||||||
|
.await?;
|
||||||
|
if person.banned {
|
||||||
|
return Err(anyhow!("Person is banned from site").into());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
note: ChatMessage,
|
note: ChatMessage,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
expected_domain: &Url,
|
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<ApubPrivateMessage, LemmyError> {
|
) -> Result<ApubPrivateMessage, LemmyError> {
|
||||||
verify_domains_match(note.id.inner(), expected_domain)?;
|
|
||||||
let ap_id = Some(note.id.into());
|
|
||||||
let creator = note
|
let creator = note
|
||||||
.attributed_to
|
.attributed_to
|
||||||
.dereference(context, request_counter)
|
.dereference(context, request_counter)
|
||||||
|
@ -127,7 +143,7 @@ impl ApubObject for ApubPrivateMessage {
|
||||||
updated: note.updated.map(|u| u.naive_local()),
|
updated: note.updated.map(|u| u.naive_local()),
|
||||||
deleted: None,
|
deleted: None,
|
||||||
read: None,
|
read: None,
|
||||||
ap_id,
|
ap_id: Some(note.id.into()),
|
||||||
local: Some(false),
|
local: Some(false),
|
||||||
};
|
};
|
||||||
let pm = blocking(context.pool(), move |conn| {
|
let pm = blocking(context.pool(), move |conn| {
|
||||||
|
@ -150,12 +166,18 @@ mod tests {
|
||||||
|
|
||||||
async fn prepare_comment_test(url: &Url, context: &LemmyContext) -> (ApubPerson, ApubPerson) {
|
async fn prepare_comment_test(url: &Url, context: &LemmyContext) -> (ApubPerson, ApubPerson) {
|
||||||
let lemmy_person = file_to_json_object("assets/lemmy/objects/person.json");
|
let lemmy_person = file_to_json_object("assets/lemmy/objects/person.json");
|
||||||
let person1 = ApubPerson::from_apub(lemmy_person, context, url, &mut 0)
|
ApubPerson::verify(&lemmy_person, url, context, &mut 0)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let person1 = ApubPerson::from_apub(lemmy_person, context, &mut 0)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let pleroma_person = file_to_json_object("assets/pleroma/objects/person.json");
|
let pleroma_person = file_to_json_object("assets/pleroma/objects/person.json");
|
||||||
let pleroma_url = Url::parse("https://queer.hacktivis.me/users/lanodan").unwrap();
|
let pleroma_url = Url::parse("https://queer.hacktivis.me/users/lanodan").unwrap();
|
||||||
let person2 = ApubPerson::from_apub(pleroma_person, context, &pleroma_url, &mut 0)
|
ApubPerson::verify(&pleroma_person, &pleroma_url, context, &mut 0)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let person2 = ApubPerson::from_apub(pleroma_person, context, &mut 0)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
(person1, person2)
|
(person1, person2)
|
||||||
|
@ -174,7 +196,10 @@ mod tests {
|
||||||
let data = prepare_comment_test(&url, &context).await;
|
let data = prepare_comment_test(&url, &context).await;
|
||||||
let json: ChatMessage = file_to_json_object("assets/lemmy/objects/chat_message.json");
|
let json: ChatMessage = file_to_json_object("assets/lemmy/objects/chat_message.json");
|
||||||
let mut request_counter = 0;
|
let mut request_counter = 0;
|
||||||
let pm = ApubPrivateMessage::from_apub(json.clone(), &context, &url, &mut request_counter)
|
ApubPrivateMessage::verify(&json, &url, &context, &mut request_counter)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let pm = ApubPrivateMessage::from_apub(json.clone(), &context, &mut request_counter)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -199,7 +224,10 @@ mod tests {
|
||||||
let pleroma_url = Url::parse("https://queer.hacktivis.me/objects/2").unwrap();
|
let pleroma_url = Url::parse("https://queer.hacktivis.me/objects/2").unwrap();
|
||||||
let json = file_to_json_object("assets/pleroma/objects/chat_message.json");
|
let json = file_to_json_object("assets/pleroma/objects/chat_message.json");
|
||||||
let mut request_counter = 0;
|
let mut request_counter = 0;
|
||||||
let pm = ApubPrivateMessage::from_apub(json, &context, &pleroma_url, &mut request_counter)
|
ApubPrivateMessage::verify(&json, &pleroma_url, &context, &mut request_counter)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let pm = ApubPrivateMessage::from_apub(json, &context, &mut request_counter)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,7 @@ use activitystreams::{
|
||||||
chrono::{DateTime, FixedOffset},
|
chrono::{DateTime, FixedOffset},
|
||||||
unparsed::Unparsed,
|
unparsed::Unparsed,
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml};
|
||||||
use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml, verify::verify_domains_match};
|
|
||||||
use lemmy_utils::LemmyError;
|
|
||||||
use lemmy_websocket::LemmyContext;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::skip_serializing_none;
|
use serde_with::skip_serializing_none;
|
||||||
|
|
||||||
|
@ -35,21 +32,3 @@ pub struct ChatMessage {
|
||||||
pub enum ChatMessageType {
|
pub enum ChatMessageType {
|
||||||
ChatMessage,
|
ChatMessage,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChatMessage {
|
|
||||||
pub(crate) async fn verify(
|
|
||||||
&self,
|
|
||||||
context: &LemmyContext,
|
|
||||||
request_counter: &mut i32,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
verify_domains_match(self.attributed_to.inner(), self.id.inner())?;
|
|
||||||
let person = self
|
|
||||||
.attributed_to
|
|
||||||
.dereference(context, request_counter)
|
|
||||||
.await?;
|
|
||||||
if person.banned {
|
|
||||||
return Err(anyhow!("Person is banned from site").into());
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,10 +12,10 @@ use chrono::{DateTime, FixedOffset};
|
||||||
use lemmy_apub_lib::{object_id::ObjectId, signatures::PublicKey, verify::verify_domains_match};
|
use lemmy_apub_lib::{object_id::ObjectId, signatures::PublicKey, verify::verify_domains_match};
|
||||||
use lemmy_db_schema::{naive_now, source::community::CommunityForm};
|
use lemmy_db_schema::{naive_now, source::community::CommunityForm};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
settings::structs::Settings,
|
|
||||||
utils::{check_slurs, check_slurs_opt},
|
utils::{check_slurs, check_slurs_opt},
|
||||||
LemmyError,
|
LemmyError,
|
||||||
};
|
};
|
||||||
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::skip_serializing_none;
|
use serde_with::skip_serializing_none;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -52,27 +52,27 @@ pub struct Group {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Group {
|
impl Group {
|
||||||
pub(crate) async fn into_form(
|
pub(crate) async fn verify(
|
||||||
self,
|
&self,
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
settings: &Settings,
|
context: &LemmyContext,
|
||||||
) -> Result<CommunityForm, LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
check_is_apub_id_valid(self.id.inner(), true, settings)?;
|
check_is_apub_id_valid(self.id.inner(), true, &context.settings())?;
|
||||||
verify_domains_match(expected_domain, self.id.inner())?;
|
verify_domains_match(expected_domain, self.id.inner())?;
|
||||||
let name = self.preferred_username;
|
|
||||||
let title = self.name;
|
let slur_regex = &context.settings().slur_regex();
|
||||||
|
check_slurs(&self.preferred_username, slur_regex)?;
|
||||||
|
check_slurs(&self.name, slur_regex)?;
|
||||||
let description = get_summary_from_string_or_source(&self.summary, &self.source);
|
let description = get_summary_from_string_or_source(&self.summary, &self.source);
|
||||||
let shared_inbox = self.endpoints.shared_inbox.map(|s| s.into());
|
|
||||||
|
|
||||||
let slur_regex = &settings.slur_regex();
|
|
||||||
check_slurs(&name, slur_regex)?;
|
|
||||||
check_slurs(&title, slur_regex)?;
|
|
||||||
check_slurs_opt(&description, slur_regex)?;
|
check_slurs_opt(&description, slur_regex)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn into_form(self) -> Result<CommunityForm, LemmyError> {
|
||||||
Ok(CommunityForm {
|
Ok(CommunityForm {
|
||||||
name,
|
name: self.preferred_username,
|
||||||
title,
|
title: self.name,
|
||||||
description,
|
description: get_summary_from_string_or_source(&self.summary, &self.source),
|
||||||
removed: None,
|
removed: None,
|
||||||
published: self.published.map(|u| u.naive_local()),
|
published: self.published.map(|u| u.naive_local()),
|
||||||
updated: self.updated.map(|u| u.naive_local()),
|
updated: self.updated.map(|u| u.naive_local()),
|
||||||
|
@ -87,7 +87,7 @@ impl Group {
|
||||||
banner: Some(self.image.map(|i| i.url.into())),
|
banner: Some(self.image.map(|i| i.url.into())),
|
||||||
followers_url: Some(self.followers.into()),
|
followers_url: Some(self.followers.into()),
|
||||||
inbox_url: Some(self.inbox.into()),
|
inbox_url: Some(self.inbox.into()),
|
||||||
shared_inbox_url: Some(shared_inbox),
|
shared_inbox_url: Some(self.endpoints.shared_inbox.map(|s| s.into())),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,13 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::{verify_is_public, verify_person_in_community},
|
|
||||||
fetcher::post_or_comment::PostOrComment,
|
fetcher::post_or_comment::PostOrComment,
|
||||||
objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost},
|
objects::{comment::ApubComment, person::ApubPerson, post::ApubPost},
|
||||||
protocol::Source,
|
protocol::Source,
|
||||||
};
|
};
|
||||||
use activitystreams::{object::kind::NoteType, unparsed::Unparsed};
|
use activitystreams::{object::kind::NoteType, unparsed::Unparsed};
|
||||||
use anyhow::anyhow;
|
|
||||||
use chrono::{DateTime, FixedOffset};
|
use chrono::{DateTime, FixedOffset};
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml, verify::verify_domains_match};
|
use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{newtypes::CommentId, source::post::Post, traits::Crud};
|
||||||
newtypes::CommentId,
|
|
||||||
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};
|
||||||
|
@ -76,26 +70,4 @@ impl Note {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn verify(
|
|
||||||
&self,
|
|
||||||
context: &LemmyContext,
|
|
||||||
request_counter: &mut i32,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
let (post, _parent_comment_id) = self.get_parents(context, request_counter).await?;
|
|
||||||
let community_id = post.community_id;
|
|
||||||
let community: ApubCommunity = blocking(context.pool(), move |conn| {
|
|
||||||
Community::read(conn, community_id)
|
|
||||||
})
|
|
||||||
.await??
|
|
||||||
.into();
|
|
||||||
|
|
||||||
if post.locked {
|
|
||||||
return Err(anyhow!("Post is locked").into());
|
|
||||||
}
|
|
||||||
verify_domains_match(self.attributed_to.inner(), self.id.inner())?;
|
|
||||||
verify_person_in_community(&self.attributed_to, &community, context, request_counter).await?;
|
|
||||||
verify_is_public(&self.to)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::{verify_is_public, verify_person_in_community},
|
|
||||||
objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost},
|
objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost},
|
||||||
protocol::{ImageObject, Source},
|
protocol::{ImageObject, Source},
|
||||||
};
|
};
|
||||||
use activitystreams::{object::kind::PageType, unparsed::Unparsed};
|
use activitystreams::{object::kind::PageType, unparsed::Unparsed};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use chrono::{DateTime, FixedOffset};
|
use chrono::{DateTime, FixedOffset};
|
||||||
use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml, verify::verify_domains_match};
|
use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml};
|
||||||
use lemmy_utils::{utils::check_slurs, LemmyError};
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::skip_serializing_none;
|
use serde_with::skip_serializing_none;
|
||||||
|
@ -54,20 +53,6 @@ impl Page {
|
||||||
Ok(is_mod_action)
|
Ok(is_mod_action)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn verify(
|
|
||||||
&self,
|
|
||||||
context: &LemmyContext,
|
|
||||||
request_counter: &mut i32,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
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.inner())?;
|
|
||||||
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(
|
pub(crate) async fn extract_community(
|
||||||
&self,
|
&self,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
|
|
|
@ -140,7 +140,8 @@ where
|
||||||
|
|
||||||
let res2: Kind::ApubType = res.json().await?;
|
let res2: Kind::ApubType = res.json().await?;
|
||||||
|
|
||||||
Ok(Kind::from_apub(res2, data, self.inner(), request_counter).await?)
|
Kind::verify(&res2, self.inner(), data, request_counter).await?;
|
||||||
|
Ok(Kind::from_apub(res2, data, request_counter).await?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,13 @@ pub trait ApubObject {
|
||||||
async fn into_apub(self, data: &Self::DataType) -> Result<Self::ApubType, LemmyError>;
|
async fn into_apub(self, data: &Self::DataType) -> Result<Self::ApubType, LemmyError>;
|
||||||
fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError>;
|
fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError>;
|
||||||
|
|
||||||
|
async fn verify(
|
||||||
|
apub: &Self::ApubType,
|
||||||
|
expected_domain: &Url,
|
||||||
|
data: &Self::DataType,
|
||||||
|
request_counter: &mut i32,
|
||||||
|
) -> Result<(), LemmyError>;
|
||||||
|
|
||||||
/// Converts an object from ActivityPub type to Lemmy internal type.
|
/// Converts an object from ActivityPub type to Lemmy internal type.
|
||||||
///
|
///
|
||||||
/// * `apub` The object to read from
|
/// * `apub` The object to read from
|
||||||
|
@ -53,7 +60,6 @@ pub trait ApubObject {
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
apub: Self::ApubType,
|
apub: Self::ApubType,
|
||||||
data: &Self::DataType,
|
data: &Self::DataType,
|
||||||
expected_domain: &Url,
|
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<Self, LemmyError>
|
) -> Result<Self, LemmyError>
|
||||||
where
|
where
|
||||||
|
|
Loading…
Reference in a new issue