From 986913d250e2211cfa8e9b9acdb6128ade6320d8 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Thu, 26 Oct 2023 10:52:24 +0200 Subject: [PATCH] add config option --- config/defaults.hjson | 8 +++++++- crates/api_common/src/request.rs | 2 +- crates/api_crud/src/post/create.rs | 28 +++++++--------------------- crates/api_crud/src/post/update.rs | 22 ++++++++-------------- crates/apub/src/objects/post.rs | 14 +++++++------- crates/routes/src/image_proxy.rs | 20 ++++---------------- crates/utils/src/settings/structs.rs | 10 +++++++++- src/api_routes_http.rs | 6 ++++++ 8 files changed, 49 insertions(+), 61 deletions(-) diff --git a/config/defaults.hjson b/config/defaults.hjson index 4b616f677..6475dc825 100644 --- a/config/defaults.hjson +++ b/config/defaults.hjson @@ -44,7 +44,13 @@ # Set a custom pictrs API key. ( Required for deleting images ) api_key: "string" # 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: { diff --git a/crates/api_common/src/request.rs b/crates/api_common/src/request.rs index 0064c8045..6ed1173ce 100644 --- a/crates/api_common/src/request.rs +++ b/crates/api_common/src/request.rs @@ -124,7 +124,7 @@ pub(crate) async fn fetch_pictrs( let pictrs_config = settings.pictrs_config()?; 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 let fetch_url = format!( "{}image/download?url={}", diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 6ee2bab44..b45f3c8dc 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -12,7 +12,6 @@ use lemmy_api_common::{ honeypot_check, local_site_to_slur_regex, mark_post_as_read, - process_markdown_opt, EndpointType, }, }; @@ -32,13 +31,14 @@ use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType}, spawn_try_task, utils::{ - slurs::check_slurs, + slurs::{check_slurs}, validation::{check_url_scheme, clean_url_params, is_valid_body_field, is_valid_post_title}, }, }; use tracing::Instrument; use url::Url; use webmention::{Webmention, WebmentionError}; +use lemmy_api_common::utils::process_markdown_opt; #[tracing::instrument(skip(context))] 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?; 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_body_field(&body, true)?; check_url_scheme(&data.url)?; @@ -80,29 +83,12 @@ pub async fn create_post( } // Fetch post links and pictrs cached image - let (metadata_res, thumbnail_url) = fetch_site_data( - context.client(), - context.settings(), - data.url.as_ref(), - true, - ) - .await; + let (metadata_res, thumbnail_url) = + fetch_site_data(context.client(), context.settings(), data_url, true).await; let (embed_title, embed_description, embed_video_url) = metadata_res .map(|u| (u.title, u.description, u.embed_video_url)) .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 // language, it already only returns allowed languages. CommunityLanguage::is_allowed_community_language( diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs index e8e127b1d..ac275fe00 100644 --- a/crates/api_crud/src/post/update.rs +++ b/crates/api_crud/src/post/update.rs @@ -6,7 +6,7 @@ use lemmy_api_common::{ post::{EditPost, PostResponse}, request::fetch_site_data, 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::{ source::{ @@ -26,6 +26,7 @@ use lemmy_utils::{ }, }; use std::ops::Deref; +use lemmy_api_common::utils::process_markdown_opt; #[tracing::instrument(skip(context))] pub async fn update_post( @@ -35,6 +36,12 @@ pub async fn update_post( ) -> Result, LemmyError> { 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); check_slurs_opt(&data.name, &slur_regex)?; 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))) .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; CommunityLanguage::is_allowed_community_language( &mut context.pool(), diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index f7c799e97..c59ab74f8 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -25,12 +25,7 @@ use html2text::{from_read_with_decorator, render::text_renderer::TrivialDecorato use lemmy_api_common::{ context::LemmyContext, request::fetch_site_data, - utils::{ - is_mod_or_admin, - local_site_opt_to_sensitive, - local_site_opt_to_slur_regex, - process_markdown_opt, - }, + utils::{is_mod_or_admin, local_site_opt_to_sensitive, local_site_opt_to_slur_regex}, }; use lemmy_db_schema::{ self, @@ -45,11 +40,16 @@ use lemmy_db_schema::{ }; use lemmy_utils::{ 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 stringreader::StringReader; use url::Url; +use lemmy_api_common::utils::process_markdown_opt; const MAX_TITLE_LENGTH: usize = 200; diff --git a/crates/routes/src/image_proxy.rs b/crates/routes/src/image_proxy.rs index 9d95404fb..185ae830e 100644 --- a/crates/routes/src/image_proxy.rs +++ b/crates/routes/src/image_proxy.rs @@ -1,29 +1,17 @@ -use actix_web::{ - web, - web::{Query, ServiceConfig}, - HttpResponse, -}; +use actix_web::{web, web::Query, HttpResponse}; use lemmy_api_common::context::LemmyContext; use lemmy_db_schema::source::images::RemoteImage; -use lemmy_utils::{error::LemmyResult, rate_limit::RateLimitCell}; +use lemmy_utils::error::LemmyResult; use serde::Deserialize; use url::Url; 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)] -struct ImageProxyParams { +pub struct ImageProxyParams { url: String, } -async fn image_proxy( +pub async fn image_proxy( Query(params): Query, context: web::Data, ) -> LemmyResult { diff --git a/crates/utils/src/settings/structs.rs b/crates/utils/src/settings/structs.rs index aa3f852ce..57b4893e8 100644 --- a/crates/utils/src/settings/structs.rs +++ b/crates/utils/src/settings/structs.rs @@ -65,7 +65,15 @@ pub struct PictrsConfig { /// Cache remote images #[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)] diff --git a/src/api_routes_http.rs b/src/api_routes_http.rs index fb784b3b3..5e66723a8 100644 --- a/src/api_routes_http.rs +++ b/src/api_routes_http.rs @@ -124,11 +124,17 @@ use lemmy_apub::api::{ search::search, user_settings_backup::{export_settings, import_settings}, }; +use lemmy_routes::image_proxy::image_proxy; use lemmy_utils::rate_limit::RateLimitCell; pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) { cfg.service( web::scope("/api/v3") + .service( + web::scope("") + .wrap(rate_limit.message()) + .route("image_proxy", web::post().to(image_proxy)), + ) // Site .service( web::scope("/site")