use crate::protocol::{ImageObject, Source};
+use anyhow::anyhow;
use html2md::parse_html;
use lemmy_apub_lib::verify::verify_domains_match;
-use lemmy_utils::LemmyError;
+use lemmy_utils::{settings::structs::Settings, LemmyError};
use url::Url;
pub mod comment;
}
}
-pub fn verify_image_domain_matches(a: &Url, b: &Option<ImageObject>) -> Result<(), LemmyError> {
+pub(crate) fn verify_image_domain_matches(
+ a: &Url,
+ b: &Option<ImageObject>,
+) -> Result<(), LemmyError> {
if let Some(b) = b {
verify_domains_match(a, &b.url)
} else {
}
}
+/// When for example a Post is made in a remote community, the community will send it back,
+/// wrapped in Announce. If we simply receive this like any other federated object, overwrite the
+/// existing, local Post. In particular, it will set the field local = false, so that the object
+/// can't be fetched from the Activitypub HTTP endpoint anymore (which only serves local objects).
+pub(crate) fn verify_is_remote_object(id: &Url) -> Result<(), LemmyError> {
+ let local_domain = Settings::get().get_hostname_without_port()?;
+ if id.domain() == Some(&local_domain) {
+ Err(anyhow!("cant accept local object from remote instance").into())
+ } else {
+ Ok(())
+ }
+}
+
#[cfg(test)]
pub(crate) mod tests {
use actix::Actor;
use crate::{
activities::{verify_is_public, verify_person_in_community},
check_is_apub_id_valid,
- objects::read_from_string_or_source_opt,
+ objects::{read_from_string_or_source_opt, verify_is_remote_object},
protocol::{
objects::{
page::{Attachment, Page, PageType},
// instance from the post author.
if !page.is_mod_action(context).await? {
verify_domains_match(page.id.inner(), expected_domain)?;
+ verify_is_remote_object(page.id.inner())?;
};
let community = page.extract_community(context, request_counter).await?;
.await?;
let community = page.extract_community(context, request_counter).await?;
- let url = if let Some(attachment) = page.attachment.first() {
- Some(attachment.href.clone())
- } else {
- page.url
- };
- let thumbnail_url: Option<Url> = page.image.map(|i| i.url);
- let (metadata_res, pictrs_thumbnail) = if let Some(url) = &url {
- fetch_site_data(context.client(), &context.settings(), Some(url)).await
- } else {
- (None, thumbnail_url)
- };
- let (embed_title, embed_description, embed_html) = metadata_res
- .map(|u| (u.title, u.description, u.html))
- .unwrap_or((None, None, None));
- let body_slurs_removed = read_from_string_or_source_opt(&page.content, &page.source)
- .map(|s| remove_slurs(&s, &context.settings().slur_regex()));
+ let form = if !page.is_mod_action(context).await? {
+ let url = if let Some(attachment) = page.attachment.first() {
+ Some(attachment.href.clone())
+ } else {
+ page.url
+ };
+ let thumbnail_url: Option<Url> = page.image.map(|i| i.url);
+ let (metadata_res, pictrs_thumbnail) = if let Some(url) = &url {
+ fetch_site_data(context.client(), &context.settings(), Some(url)).await
+ } else {
+ (None, thumbnail_url)
+ };
+ let (embed_title, embed_description, embed_html) = metadata_res
+ .map(|u| (u.title, u.description, u.html))
+ .unwrap_or((None, None, None));
+ let body_slurs_removed = read_from_string_or_source_opt(&page.content, &page.source)
+ .map(|s| remove_slurs(&s, &context.settings().slur_regex()));
- let form = PostForm {
- name: page.name.clone(),
- url: url.map(Into::into),
- body: body_slurs_removed,
- creator_id: creator.id,
- community_id: community.id,
- removed: None,
- locked: page.comments_enabled.map(|e| !e),
- published: page.published.map(|u| u.naive_local()),
- updated: page.updated.map(|u| u.naive_local()),
- deleted: None,
- nsfw: page.sensitive,
- stickied: page.stickied,
- embed_title,
- embed_description,
- embed_html,
- thumbnail_url: pictrs_thumbnail.map(|u| u.into()),
- ap_id: Some(page.id.clone().into()),
- local: Some(false),
+ PostForm {
+ name: page.name.clone(),
+ url: url.map(Into::into),
+ body: body_slurs_removed,
+ creator_id: creator.id,
+ community_id: community.id,
+ removed: None,
+ locked: page.comments_enabled.map(|e| !e),
+ published: page.published.map(|u| u.naive_local()),
+ updated: page.updated.map(|u| u.naive_local()),
+ deleted: None,
+ nsfw: page.sensitive,
+ stickied: page.stickied,
+ embed_title,
+ embed_description,
+ embed_html,
+ thumbnail_url: pictrs_thumbnail.map(|u| u.into()),
+ ap_id: Some(page.id.clone().into()),
+ local: Some(false),
+ }
+ } else {
+ // if is mod action, only update locked/stickied fields, nothing else
+ PostForm {
+ name: page.name.clone(),
+ creator_id: creator.id,
+ community_id: community.id,
+ locked: page.comments_enabled.map(|e| !e),
+ stickied: page.stickied,
+ updated: page.updated.map(|u| u.naive_local()),
+ ap_id: Some(page.id.clone().into()),
+ ..Default::default()
+ }
};
// read existing, local post if any (for generating mod log)