mirror of https://github.com/LemmyNet/lemmy.git
proxy links received over federation
parent
7306153161
commit
aa49a1b173
|
@ -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());
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)?;
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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()),
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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?;
|
||||||
|
|
||||||
|
|
|
@ -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()),
|
||||||
|
|
|
@ -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()),
|
||||||
|
|
|
@ -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()),
|
||||||
|
|
|
@ -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?;
|
||||||
|
|
||||||
|
|
|
@ -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(¬e.content, &None, ¬e.source);
|
let content = read_from_string_or_source(¬e.content, &None, ¬e.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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue