proxy links received over federation

cleanup-request-rs
Felix Ableitner 2023-10-25 12:35:22 +02:00
parent 7306153161
commit aa49a1b173
13 changed files with 60 additions and 33 deletions

View File

@ -5,7 +5,7 @@ use lemmy_api_common::{
utils::{ utils::{
local_site_to_slur_regex, local_site_to_slur_regex,
process_markdown_opt, process_markdown_opt,
proxy_image_link_opt, proxy_image_link_opt_api,
send_verification_email, send_verification_email,
}, },
SuccessResponse, SuccessResponse,
@ -36,8 +36,8 @@ pub async fn save_user_settings(
let slur_regex = local_site_to_slur_regex(&site_view.local_site); let slur_regex = local_site_to_slur_regex(&site_view.local_site);
let bio = process_markdown_opt(&data.bio, &slur_regex, &context).await?; let bio = process_markdown_opt(&data.bio, &slur_regex, &context).await?;
let avatar = proxy_image_link_opt(&data.avatar, &context).await?; let avatar = proxy_image_link_opt_api(&data.avatar, &context).await?;
let banner = proxy_image_link_opt(&data.banner, &context).await?; let banner = proxy_image_link_opt_api(&data.banner, &context).await?;
let bio = diesel_option_overwrite(bio); let bio = diesel_option_overwrite(bio);
let display_name = diesel_option_overwrite(data.display_name.clone()); let display_name = diesel_option_overwrite(data.display_name.clone());
let matrix_user_id = diesel_option_overwrite(data.matrix_user_id.clone()); let matrix_user_id = diesel_option_overwrite(data.matrix_user_id.clone());

View File

@ -828,20 +828,29 @@ pub async fn proxy_image_link(link: Url, context: &LemmyContext) -> LemmyResult<
Ok(Url::parse(&proxied)?.into()) Ok(Url::parse(&proxied)?.into())
} }
pub async fn proxy_image_link_opt( pub async fn proxy_image_link_opt_api(
link: &Option<String>, link: &Option<String>,
context: &LemmyContext, context: &LemmyContext,
) -> LemmyResult<Option<Option<DbUrl>>> { ) -> LemmyResult<Option<Option<DbUrl>>> {
let link = diesel_option_overwrite_to_url(link)?; let link = diesel_option_overwrite_to_url(link)?;
if let Some(Some(l)) = link { if let Some(l) = link {
proxy_image_link(l.into(), context) proxy_image_link_opt_apub(l.map(Into::into), context)
.await .await
.map(Some) .map(Some)
.map(Some)
} else { } else {
Ok(link) Ok(link)
} }
} }
pub async fn proxy_image_link_opt_apub(
link: Option<Url>,
context: &LemmyContext,
) -> LemmyResult<Option<DbUrl>> {
if let Some(l) = link {
proxy_image_link(l.clone(), context).await.map(Some)
} else {
Ok(None)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View File

@ -12,7 +12,7 @@ use lemmy_api_common::{
is_admin, is_admin,
local_site_to_slur_regex, local_site_to_slur_regex,
process_markdown_opt, process_markdown_opt,
proxy_image_link_opt, proxy_image_link_opt_api,
EndpointType, EndpointType,
}, },
}; };
@ -56,8 +56,12 @@ pub async fn create_community(
check_slurs(&data.name, &slur_regex)?; check_slurs(&data.name, &slur_regex)?;
check_slurs(&data.title, &slur_regex)?; check_slurs(&data.title, &slur_regex)?;
let description = process_markdown_opt(&data.description, &slur_regex, &context).await?; let description = process_markdown_opt(&data.description, &slur_regex, &context).await?;
let icon = proxy_image_link_opt(&data.icon, &context).await?.unwrap(); let icon = proxy_image_link_opt_api(&data.icon, &context)
let banner = proxy_image_link_opt(&data.banner, &context).await?.unwrap(); .await?
.unwrap();
let banner = proxy_image_link_opt_api(&data.banner, &context)
.await?
.unwrap();
is_valid_actor_name(&data.name, local_site.actor_name_max_length as usize)?; is_valid_actor_name(&data.name, local_site.actor_name_max_length as usize)?;
is_valid_body_field(&data.description, false)?; is_valid_body_field(&data.description, false)?;

View File

@ -9,7 +9,7 @@ use lemmy_api_common::{
check_community_mod_action, check_community_mod_action,
local_site_to_slur_regex, local_site_to_slur_regex,
process_markdown_opt, process_markdown_opt,
proxy_image_link_opt, proxy_image_link_opt_api,
}, },
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
@ -41,8 +41,8 @@ pub async fn update_community(
is_valid_body_field(&data.description, false)?; is_valid_body_field(&data.description, false)?;
let description = diesel_option_overwrite(description); let description = diesel_option_overwrite(description);
let icon = proxy_image_link_opt(&data.icon, &context).await?; let icon = proxy_image_link_opt_api(&data.icon, &context).await?;
let banner = proxy_image_link_opt(&data.banner, &context).await?; let banner = proxy_image_link_opt_api(&data.banner, &context).await?;
// Verify its a mod (only mods can edit it) // Verify its a mod (only mods can edit it)
check_community_mod_action( check_community_mod_action(

View File

@ -10,7 +10,7 @@ use lemmy_api_common::{
local_site_rate_limit_to_rate_limit_config, local_site_rate_limit_to_rate_limit_config,
local_site_to_slur_regex, local_site_to_slur_regex,
process_markdown_opt, process_markdown_opt,
proxy_image_link_opt, proxy_image_link_opt_api,
}, },
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
@ -59,8 +59,8 @@ pub async fn create_site(
let slur_regex = local_site_to_slur_regex(&local_site); let slur_regex = local_site_to_slur_regex(&local_site);
let sidebar = process_markdown_opt(&data.sidebar, &slur_regex, &context).await?; let sidebar = process_markdown_opt(&data.sidebar, &slur_regex, &context).await?;
let icon = proxy_image_link_opt(&data.icon, &context).await?; let icon = proxy_image_link_opt_api(&data.icon, &context).await?;
let banner = proxy_image_link_opt(&data.banner, &context).await?; let banner = proxy_image_link_opt_api(&data.banner, &context).await?;
let site_form = SiteUpdateForm { let site_form = SiteUpdateForm {
name: Some(data.name.clone()), name: Some(data.name.clone()),

View File

@ -8,7 +8,7 @@ use lemmy_api_common::{
local_site_rate_limit_to_rate_limit_config, local_site_rate_limit_to_rate_limit_config,
local_site_to_slur_regex, local_site_to_slur_regex,
process_markdown_opt, process_markdown_opt,
proxy_image_link_opt, proxy_image_link_opt_api,
}, },
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
@ -62,8 +62,8 @@ pub async fn update_site(
let slur_regex = local_site_to_slur_regex(&local_site); let slur_regex = local_site_to_slur_regex(&local_site);
let sidebar = process_markdown_opt(&data.sidebar, &slur_regex, &context).await?; let sidebar = process_markdown_opt(&data.sidebar, &slur_regex, &context).await?;
let icon = proxy_image_link_opt(&data.icon, &context).await?; let icon = proxy_image_link_opt_api(&data.icon, &context).await?;
let banner = proxy_image_link_opt(&data.banner, &context).await?; let banner = proxy_image_link_opt_api(&data.banner, &context).await?;
let site_form = SiteUpdateForm { let site_form = SiteUpdateForm {
name: data.name.clone(), name: data.name.clone(),

View File

@ -161,7 +161,7 @@ impl Object for ApubComment {
let local_site = LocalSite::read(&mut context.pool()).await.ok(); let local_site = LocalSite::read(&mut context.pool()).await.ok();
let slur_regex = &local_site_opt_to_slur_regex(&local_site); let slur_regex = &local_site_opt_to_slur_regex(&local_site);
let content = process_markdown(&content, slur_regex, &context).await?; let content = process_markdown(&content, slur_regex, context).await?;
let language_id = let language_id =
LanguageTag::to_language_id_single(note.language, &mut context.pool()).await?; LanguageTag::to_language_id_single(note.language, &mut context.pool()).await?;

View File

@ -23,6 +23,7 @@ use lemmy_api_common::{
generate_outbox_url, generate_outbox_url,
local_site_opt_to_slur_regex, local_site_opt_to_slur_regex,
process_markdown_opt, process_markdown_opt,
proxy_image_link_opt_apub,
}, },
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
@ -142,7 +143,9 @@ impl Object for ApubCommunity {
let local_site = LocalSite::read(&mut context.pool()).await.ok(); let local_site = LocalSite::read(&mut context.pool()).await.ok();
let slur_regex = &local_site_opt_to_slur_regex(&local_site); let slur_regex = &local_site_opt_to_slur_regex(&local_site);
let description = read_from_string_or_source_opt(&group.summary, &None, &group.source); let description = read_from_string_or_source_opt(&group.summary, &None, &group.source);
let description = process_markdown_opt(&description, slur_regex, &context).await?; let description = process_markdown_opt(&description, slur_regex, context).await?;
let icon = proxy_image_link_opt_apub(group.icon.map(|i| i.url), context).await?;
let banner = proxy_image_link_opt_apub(group.image.map(|i| i.url), context).await?;
let form = CommunityInsertForm { let form = CommunityInsertForm {
name: group.preferred_username.clone(), name: group.preferred_username.clone(),
@ -159,8 +162,8 @@ impl Object for ApubCommunity {
hidden: None, hidden: None,
public_key: group.public_key.public_key_pem, public_key: group.public_key.public_key_pem,
last_refreshed_at: Some(naive_now()), last_refreshed_at: Some(naive_now()),
icon: group.icon.map(|i| i.url.into()), icon,
banner: group.image.map(|i| i.url.into()), banner,
followers_url: Some(group.followers.clone().into()), followers_url: Some(group.followers.clone().into()),
inbox_url: Some(group.inbox.into()), inbox_url: Some(group.inbox.into()),
shared_inbox_url: group.endpoints.map(|e| e.shared_inbox.into()), shared_inbox_url: group.endpoints.map(|e| e.shared_inbox.into()),

View File

@ -19,7 +19,7 @@ use activitypub_federation::{
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
utils::{local_site_opt_to_slur_regex, process_markdown_opt}, utils::{local_site_opt_to_slur_regex, process_markdown_opt, proxy_image_link_opt_apub},
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
newtypes::InstanceId, newtypes::InstanceId,
@ -137,14 +137,16 @@ impl Object for ApubSite {
let local_site = LocalSite::read(&mut context.pool()).await.ok(); let local_site = LocalSite::read(&mut context.pool()).await.ok();
let slur_regex = &local_site_opt_to_slur_regex(&local_site); let slur_regex = &local_site_opt_to_slur_regex(&local_site);
let sidebar = read_from_string_or_source_opt(&apub.content, &None, &apub.source); let sidebar = read_from_string_or_source_opt(&apub.content, &None, &apub.source);
let sidebar = process_markdown_opt(&sidebar, slur_regex, &context).await?; let sidebar = process_markdown_opt(&sidebar, slur_regex, context).await?;
let icon = proxy_image_link_opt_apub(apub.icon.map(|i| i.url), context).await?;
let banner = proxy_image_link_opt_apub(apub.image.map(|i| i.url), context).await?;
let site_form = SiteInsertForm { let site_form = SiteInsertForm {
name: apub.name.clone(), name: apub.name.clone(),
sidebar, sidebar,
updated: apub.updated, updated: apub.updated,
icon: apub.icon.clone().map(|i| i.url.into()), icon,
banner: apub.image.clone().map(|i| i.url.into()), banner,
description: apub.summary, description: apub.summary,
actor_id: Some(apub.id.clone().into()), actor_id: Some(apub.id.clone().into()),
last_refreshed_at: Some(naive_now()), last_refreshed_at: Some(naive_now()),

View File

@ -20,7 +20,12 @@ use activitypub_federation::{
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
utils::{generate_outbox_url, local_site_opt_to_slur_regex, process_markdown_opt}, utils::{
generate_outbox_url,
local_site_opt_to_slur_regex,
process_markdown_opt,
proxy_image_link_opt_apub,
},
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
source::{ source::{
@ -148,7 +153,9 @@ impl Object for ApubPerson {
let local_site = LocalSite::read(&mut context.pool()).await.ok(); let local_site = LocalSite::read(&mut context.pool()).await.ok();
let slur_regex = &local_site_opt_to_slur_regex(&local_site); let slur_regex = &local_site_opt_to_slur_regex(&local_site);
let bio = read_from_string_or_source_opt(&person.summary, &None, &person.source); let bio = read_from_string_or_source_opt(&person.summary, &None, &person.source);
let bio = process_markdown_opt(&bio, slur_regex, &context).await?; let bio = process_markdown_opt(&bio, slur_regex, context).await?;
let avatar = proxy_image_link_opt_apub(person.icon.map(|i| i.url), context).await?;
let banner = proxy_image_link_opt_apub(person.image.map(|i| i.url), context).await?;
// Some Mastodon users have `name: ""` (empty string), need to convert that to `None` // Some Mastodon users have `name: ""` (empty string), need to convert that to `None`
// https://github.com/mastodon/mastodon/issues/25233 // https://github.com/mastodon/mastodon/issues/25233
@ -160,8 +167,8 @@ impl Object for ApubPerson {
banned: None, banned: None,
ban_expires: None, ban_expires: None,
deleted: Some(false), deleted: Some(false),
avatar: person.icon.map(|i| i.url.into()), avatar,
banner: person.image.map(|i| i.url.into()), banner,
published: person.published.map(Into::into), published: person.published.map(Into::into),
updated: person.updated.map(Into::into), updated: person.updated.map(Into::into),
actor_id: Some(person.id.into()), actor_id: Some(person.id.into()),

View File

@ -237,7 +237,7 @@ impl Object for ApubPost {
let slur_regex = &local_site_opt_to_slur_regex(&local_site); let slur_regex = &local_site_opt_to_slur_regex(&local_site);
let body = read_from_string_or_source_opt(&page.content, &page.media_type, &page.source); let body = read_from_string_or_source_opt(&page.content, &page.media_type, &page.source);
let body = process_markdown_opt(&body, slur_regex, &context).await?; let body = process_markdown_opt(&body, slur_regex, context).await?;
let language_id = let language_id =
LanguageTag::to_language_id_single(page.language, &mut context.pool()).await?; LanguageTag::to_language_id_single(page.language, &mut context.pool()).await?;

View File

@ -128,7 +128,7 @@ impl Object for ApubPrivateMessage {
let local_site = LocalSite::read(&mut context.pool()).await.ok(); let local_site = LocalSite::read(&mut context.pool()).await.ok();
let slur_regex = &local_site_opt_to_slur_regex(&local_site); let slur_regex = &local_site_opt_to_slur_regex(&local_site);
let content = read_from_string_or_source(&note.content, &None, &note.source); let content = read_from_string_or_source(&note.content, &None, &note.source);
let content = process_markdown(&content, slur_regex, &context).await?; let content = process_markdown(&content, slur_regex, context).await?;
let form = PrivateMessageInsertForm { let form = PrivateMessageInsertForm {
creator_id: creator.id, creator_id: creator.id,

View File

@ -42,6 +42,8 @@ pub fn markdown_rewrite_image_links(mut src: String) -> (String, Vec<Url>) {
// Walk the syntax tree to find positions of image links // Walk the syntax tree to find positions of image links
ast.walk(|node, _depth| { ast.walk(|node, _depth| {
if let Some(image) = node.cast::<Image>() { if let Some(image) = node.cast::<Image>() {
// srcmap is always present for image
// https://github.com/markdown-it-rust/markdown-it/issues/36#issuecomment-1777844387
let node_offsets = node.srcmap.expect("srcmap is none").get_byte_offsets(); let node_offsets = node.srcmap.expect("srcmap is none").get_byte_offsets();
let start_offset = node_offsets.1 - image.url.len() - 1; let start_offset = node_offsets.1 - image.url.len() - 1;
let end_offset = node_offsets.1 - 1; let end_offset = node_offsets.1 - 1;