add config option

This commit is contained in:
Felix Ableitner 2023-10-26 10:52:24 +02:00
parent f057abff71
commit 986913d250
8 changed files with 49 additions and 61 deletions

View file

@ -44,7 +44,13 @@
# Set a custom pictrs API key. ( Required for deleting images ) # Set a custom pictrs API key. ( Required for deleting images )
api_key: "string" api_key: "string"
# Cache remote images # Cache remote images
cache_remote_images: true cache_remote_thumbnails: true
# If enabled, all images from remote domains are rewritten to pass through `/api/v3/image_proxy`.
# This improves privacy as users don't expose their IP to untrusted servers, and decreases load
# on other servers. However it causes more load for the local server.
#
# Requires pict-rs 0.5
image_proxy: false
} }
# Email sending configuration. All options except login/password are mandatory # Email sending configuration. All options except login/password are mandatory
email: { email: {

View file

@ -124,7 +124,7 @@ pub(crate) async fn fetch_pictrs(
let pictrs_config = settings.pictrs_config()?; let pictrs_config = settings.pictrs_config()?;
is_image_content_type(client, image_url).await?; is_image_content_type(client, image_url).await?;
if pictrs_config.cache_remote_images { if pictrs_config.cache_remote_thumbnails {
// fetch remote non-pictrs images for persistent thumbnail link // fetch remote non-pictrs images for persistent thumbnail link
let fetch_url = format!( let fetch_url = format!(
"{}image/download?url={}", "{}image/download?url={}",

View file

@ -12,7 +12,6 @@ use lemmy_api_common::{
honeypot_check, honeypot_check,
local_site_to_slur_regex, local_site_to_slur_regex,
mark_post_as_read, mark_post_as_read,
process_markdown_opt,
EndpointType, EndpointType,
}, },
}; };
@ -32,13 +31,14 @@ use lemmy_utils::{
error::{LemmyError, LemmyErrorExt, LemmyErrorType}, error::{LemmyError, LemmyErrorExt, LemmyErrorType},
spawn_try_task, spawn_try_task,
utils::{ utils::{
slurs::check_slurs, slurs::{check_slurs},
validation::{check_url_scheme, clean_url_params, is_valid_body_field, is_valid_post_title}, validation::{check_url_scheme, clean_url_params, is_valid_body_field, is_valid_post_title},
}, },
}; };
use tracing::Instrument; use tracing::Instrument;
use url::Url; use url::Url;
use webmention::{Webmention, WebmentionError}; use webmention::{Webmention, WebmentionError};
use lemmy_api_common::utils::process_markdown_opt;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
pub async fn create_post( pub async fn create_post(
@ -53,6 +53,9 @@ pub async fn create_post(
let body = process_markdown_opt(&data.body, &slur_regex, &context).await?; let body = process_markdown_opt(&data.body, &slur_regex, &context).await?;
honeypot_check(&data.honeypot)?; honeypot_check(&data.honeypot)?;
let data_url = data.url.as_ref();
let url = data_url.map(clean_url_params).map(Into::into); // TODO no good way to handle a "clear"
is_valid_post_title(&data.name)?; is_valid_post_title(&data.name)?;
is_valid_body_field(&body, true)?; is_valid_body_field(&body, true)?;
check_url_scheme(&data.url)?; check_url_scheme(&data.url)?;
@ -80,29 +83,12 @@ pub async fn create_post(
} }
// Fetch post links and pictrs cached image // Fetch post links and pictrs cached image
let (metadata_res, thumbnail_url) = fetch_site_data( let (metadata_res, thumbnail_url) =
context.client(), fetch_site_data(context.client(), context.settings(), data_url, true).await;
context.settings(),
data.url.as_ref(),
true,
)
.await;
let (embed_title, embed_description, embed_video_url) = metadata_res let (embed_title, embed_description, embed_video_url) = metadata_res
.map(|u| (u.title, u.description, u.embed_video_url)) .map(|u| (u.title, u.description, u.embed_video_url))
.unwrap_or_default(); .unwrap_or_default();
// TODO No good way to handle a clear.
// Issue link: https://github.com/LemmyNet/lemmy/issues/2287
let url = data.url.as_ref().map(clean_url_params).map(Into::into);
// TODO: not sure how to get this working
/*
let url_is_image = todo!();
if url_is_image {
proxy_image_link_opt(url, &context).await?;
}
*/
// Only need to check if language is allowed in case user set it explicitly. When using default // Only need to check if language is allowed in case user set it explicitly. When using default
// language, it already only returns allowed languages. // language, it already only returns allowed languages.
CommunityLanguage::is_allowed_community_language( CommunityLanguage::is_allowed_community_language(

View file

@ -6,7 +6,7 @@ use lemmy_api_common::{
post::{EditPost, PostResponse}, post::{EditPost, PostResponse},
request::fetch_site_data, request::fetch_site_data,
send_activity::{ActivityChannel, SendActivityData}, send_activity::{ActivityChannel, SendActivityData},
utils::{check_community_user_action, local_site_to_slur_regex, process_markdown_opt}, utils::{check_community_user_action, local_site_to_slur_regex},
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
source::{ source::{
@ -26,6 +26,7 @@ use lemmy_utils::{
}, },
}; };
use std::ops::Deref; use std::ops::Deref;
use lemmy_api_common::utils::process_markdown_opt;
#[tracing::instrument(skip(context))] #[tracing::instrument(skip(context))]
pub async fn update_post( pub async fn update_post(
@ -35,6 +36,12 @@ pub async fn update_post(
) -> Result<Json<PostResponse>, LemmyError> { ) -> Result<Json<PostResponse>, LemmyError> {
let local_site = LocalSite::read(&mut context.pool()).await?; let local_site = LocalSite::read(&mut context.pool()).await?;
let data_url = data.url.as_ref();
// TODO No good way to handle a clear.
// Issue link: https://github.com/LemmyNet/lemmy/issues/2287
let url = Some(data_url.map(clean_url_params).map(Into::into));
let slur_regex = local_site_to_slur_regex(&local_site); let slur_regex = local_site_to_slur_regex(&local_site);
check_slurs_opt(&data.name, &slur_regex)?; check_slurs_opt(&data.name, &slur_regex)?;
let body = process_markdown_opt(&data.body, &slur_regex, &context).await?; let body = process_markdown_opt(&data.body, &slur_regex, &context).await?;
@ -69,19 +76,6 @@ pub async fn update_post(
.map(|u| (Some(u.title), Some(u.description), Some(u.embed_video_url))) .map(|u| (Some(u.title), Some(u.description), Some(u.embed_video_url)))
.unwrap_or_default(); .unwrap_or_default();
// TODO No good way to handle a clear.
// Issue link: https://github.com/LemmyNet/lemmy/issues/2287
let url = Some(data.url.as_ref().map(clean_url_params).map(Into::into));
// TODO: not sure how to get this working
/*
let url_is_image = todo!();
if url_is_image {
data_url = proxy_image_link_opt(url, &context).await?;
}
*/
let language_id = data.language_id; let language_id = data.language_id;
CommunityLanguage::is_allowed_community_language( CommunityLanguage::is_allowed_community_language(
&mut context.pool(), &mut context.pool(),

View file

@ -25,12 +25,7 @@ use html2text::{from_read_with_decorator, render::text_renderer::TrivialDecorato
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
request::fetch_site_data, request::fetch_site_data,
utils::{ utils::{is_mod_or_admin, local_site_opt_to_sensitive, local_site_opt_to_slur_regex},
is_mod_or_admin,
local_site_opt_to_sensitive,
local_site_opt_to_slur_regex,
process_markdown_opt,
},
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
self, self,
@ -45,11 +40,16 @@ use lemmy_db_schema::{
}; };
use lemmy_utils::{ use lemmy_utils::{
error::LemmyError, error::LemmyError,
utils::{markdown::markdown_to_html, slurs::check_slurs_opt, validation::check_url_scheme}, utils::{
markdown::markdown_to_html,
slurs::{check_slurs_opt},
validation::check_url_scheme,
},
}; };
use std::ops::Deref; use std::ops::Deref;
use stringreader::StringReader; use stringreader::StringReader;
use url::Url; use url::Url;
use lemmy_api_common::utils::process_markdown_opt;
const MAX_TITLE_LENGTH: usize = 200; const MAX_TITLE_LENGTH: usize = 200;

View file

@ -1,29 +1,17 @@
use actix_web::{ use actix_web::{web, web::Query, HttpResponse};
web,
web::{Query, ServiceConfig},
HttpResponse,
};
use lemmy_api_common::context::LemmyContext; use lemmy_api_common::context::LemmyContext;
use lemmy_db_schema::source::images::RemoteImage; use lemmy_db_schema::source::images::RemoteImage;
use lemmy_utils::{error::LemmyResult, rate_limit::RateLimitCell}; use lemmy_utils::error::LemmyResult;
use serde::Deserialize; use serde::Deserialize;
use url::Url; use url::Url;
use urlencoding::decode; use urlencoding::decode;
pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) {
cfg.service(
web::resource("/api/v3/image_proxy")
.wrap(rate_limit.message())
.route(web::post().to(image_proxy)),
);
}
#[derive(Deserialize)] #[derive(Deserialize)]
struct ImageProxyParams { pub struct ImageProxyParams {
url: String, url: String,
} }
async fn image_proxy( pub async fn image_proxy(
Query(params): Query<ImageProxyParams>, Query(params): Query<ImageProxyParams>,
context: web::Data<LemmyContext>, context: web::Data<LemmyContext>,
) -> LemmyResult<HttpResponse> { ) -> LemmyResult<HttpResponse> {

View file

@ -65,7 +65,15 @@ pub struct PictrsConfig {
/// Cache remote images /// Cache remote images
#[default(true)] #[default(true)]
pub cache_remote_images: bool, pub cache_remote_thumbnails: bool,
/// If enabled, all images from remote domains are rewritten to pass through `/api/v3/image_proxy`.
/// This improves privacy as users don't expose their IP to untrusted servers, and decreases load
/// on other servers. However it causes more load for the local server.
///
/// Requires pict-rs 0.5
#[default(false)]
pub image_proxy: bool,
} }
#[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)] #[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)]

View file

@ -124,11 +124,17 @@ use lemmy_apub::api::{
search::search, search::search,
user_settings_backup::{export_settings, import_settings}, user_settings_backup::{export_settings, import_settings},
}; };
use lemmy_routes::image_proxy::image_proxy;
use lemmy_utils::rate_limit::RateLimitCell; use lemmy_utils::rate_limit::RateLimitCell;
pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) { pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
cfg.service( cfg.service(
web::scope("/api/v3") web::scope("/api/v3")
.service(
web::scope("")
.wrap(rate_limit.message())
.route("image_proxy", web::post().to(image_proxy)),
)
// Site // Site
.service( .service(
web::scope("/site") web::scope("/site")