mirror of
https://github.com/LemmyNet/lemmy.git
synced 2025-01-03 16:51:35 +00:00
Add option to disable image upload (fixes #1118)
This commit is contained in:
parent
8ae4b405d0
commit
b0d4bdb8ff
9 changed files with 29 additions and 14 deletions
|
@ -320,7 +320,7 @@ pub async fn purge_image_from_pictrs(image_url: &Url, context: &LemmyContext) ->
|
||||||
.next_back()
|
.next_back()
|
||||||
.ok_or(LemmyErrorType::ImageUrlMissingLastPathSegment)?;
|
.ok_or(LemmyErrorType::ImageUrlMissingLastPathSegment)?;
|
||||||
|
|
||||||
let pictrs_config = context.settings().pictrs_config()?;
|
let pictrs_config = context.settings().pictrs()?;
|
||||||
let purge_url = format!("{}internal/purge?alias={}", pictrs_config.url, alias);
|
let purge_url = format!("{}internal/purge?alias={}", pictrs_config.url, alias);
|
||||||
|
|
||||||
let pictrs_api_key = pictrs_config
|
let pictrs_api_key = pictrs_config
|
||||||
|
@ -348,7 +348,7 @@ pub async fn delete_image_from_pictrs(
|
||||||
delete_token: &str,
|
delete_token: &str,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> LemmyResult<()> {
|
) -> LemmyResult<()> {
|
||||||
let pictrs_config = context.settings().pictrs_config()?;
|
let pictrs_config = context.settings().pictrs()?;
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}image/delete/{}/{}",
|
"{}image/delete/{}/{}",
|
||||||
pictrs_config.url, &delete_token, &alias
|
pictrs_config.url, &delete_token, &alias
|
||||||
|
@ -366,7 +366,7 @@ pub async fn delete_image_from_pictrs(
|
||||||
/// Retrieves the image with local pict-rs and generates a thumbnail. Returns the thumbnail url.
|
/// Retrieves the image with local pict-rs and generates a thumbnail. Returns the thumbnail url.
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
async fn generate_pictrs_thumbnail(image_url: &Url, context: &LemmyContext) -> LemmyResult<Url> {
|
async fn generate_pictrs_thumbnail(image_url: &Url, context: &LemmyContext) -> LemmyResult<Url> {
|
||||||
let pictrs_config = context.settings().pictrs_config()?;
|
let pictrs_config = context.settings().pictrs()?;
|
||||||
|
|
||||||
match pictrs_config.image_mode() {
|
match pictrs_config.image_mode() {
|
||||||
PictrsImageMode::None => return Ok(image_url.clone()),
|
PictrsImageMode::None => return Ok(image_url.clone()),
|
||||||
|
@ -382,7 +382,7 @@ async fn generate_pictrs_thumbnail(image_url: &Url, context: &LemmyContext) -> L
|
||||||
"{}image/download?url={}&resize={}",
|
"{}image/download?url={}&resize={}",
|
||||||
pictrs_config.url,
|
pictrs_config.url,
|
||||||
encode(image_url.as_str()),
|
encode(image_url.as_str()),
|
||||||
context.settings().pictrs_config()?.max_thumbnail_size
|
context.settings().pictrs()?.max_thumbnail_size
|
||||||
);
|
);
|
||||||
|
|
||||||
let res = context
|
let res = context
|
||||||
|
@ -425,7 +425,7 @@ pub async fn fetch_pictrs_proxied_image_details(
|
||||||
image_url: &Url,
|
image_url: &Url,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> LemmyResult<PictrsFileDetails> {
|
) -> LemmyResult<PictrsFileDetails> {
|
||||||
let pictrs_url = context.settings().pictrs_config()?.url;
|
let pictrs_url = context.settings().pictrs()?.url;
|
||||||
let encoded_image_url = encode(image_url.as_str());
|
let encoded_image_url = encode(image_url.as_str());
|
||||||
|
|
||||||
// Pictrs needs you to fetch the proxied image before you can fetch the details
|
// Pictrs needs you to fetch the proxied image before you can fetch the details
|
||||||
|
|
|
@ -455,6 +455,9 @@ pub struct GetSiteResponse {
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
pub admin_oauth_providers: Option<Vec<OAuthProvider>>,
|
pub admin_oauth_providers: Option<Vec<OAuthProvider>>,
|
||||||
pub blocked_urls: Vec<LocalSiteUrlBlocklist>,
|
pub blocked_urls: Vec<LocalSiteUrlBlocklist>,
|
||||||
|
// If true then uploads for post images or markdown images are disabled. Only avatars, icons and
|
||||||
|
// banners can be set.
|
||||||
|
pub image_upload_disabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
|
|
|
@ -1060,7 +1060,7 @@ pub async fn process_markdown(
|
||||||
|
|
||||||
markdown_check_for_blocked_urls(&text, url_blocklist)?;
|
markdown_check_for_blocked_urls(&text, url_blocklist)?;
|
||||||
|
|
||||||
if context.settings().pictrs_config()?.image_mode() == PictrsImageMode::ProxyAllImages {
|
if context.settings().pictrs()?.image_mode() == PictrsImageMode::ProxyAllImages {
|
||||||
let (text, links) = markdown_rewrite_image_links(text);
|
let (text, links) = markdown_rewrite_image_links(text);
|
||||||
RemoteImage::create(&mut context.pool(), links.clone()).await?;
|
RemoteImage::create(&mut context.pool(), links.clone()).await?;
|
||||||
|
|
||||||
|
@ -1130,7 +1130,7 @@ async fn proxy_image_link_internal(
|
||||||
pub async fn proxy_image_link(link: Url, context: &LemmyContext) -> LemmyResult<DbUrl> {
|
pub async fn proxy_image_link(link: Url, context: &LemmyContext) -> LemmyResult<DbUrl> {
|
||||||
proxy_image_link_internal(
|
proxy_image_link_internal(
|
||||||
link,
|
link,
|
||||||
context.settings().pictrs_config()?.image_mode(),
|
context.settings().pictrs()?.image_mode(),
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -69,5 +69,6 @@ async fn read_site(context: &LemmyContext) -> LemmyResult<GetSiteResponse> {
|
||||||
tagline,
|
tagline,
|
||||||
oauth_providers: Some(oauth_providers),
|
oauth_providers: Some(oauth_providers),
|
||||||
admin_oauth_providers: Some(admin_oauth_providers),
|
admin_oauth_providers: Some(admin_oauth_providers),
|
||||||
|
image_upload_disabled: context.settings().pictrs()?.disable_image_upload,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ use actix_web::{body::BoxBody, web::*, HttpRequest, HttpResponse, Responder};
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
image::{DeleteImageParams, ImageGetParams, ImageProxyParams, UploadImageResponse},
|
image::{DeleteImageParams, ImageGetParams, ImageProxyParams, UploadImageResponse},
|
||||||
|
LemmyErrorType,
|
||||||
SuccessResponse,
|
SuccessResponse,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
|
@ -22,6 +23,10 @@ pub async fn upload_image(
|
||||||
local_user_view: LocalUserView,
|
local_user_view: LocalUserView,
|
||||||
context: Data<LemmyContext>,
|
context: Data<LemmyContext>,
|
||||||
) -> LemmyResult<Json<UploadImageResponse>> {
|
) -> LemmyResult<Json<UploadImageResponse>> {
|
||||||
|
if context.settings().pictrs()?.disable_image_upload {
|
||||||
|
return Err(LemmyErrorType::ImageUploadDisabled.into());
|
||||||
|
}
|
||||||
|
|
||||||
let image = do_upload_image(req, body, UploadType::Other, &local_user_view, &context).await?;
|
let image = do_upload_image(req, body, UploadType::Other, &local_user_view, &context).await?;
|
||||||
|
|
||||||
let image_url = image.image_url(&context.settings().get_protocol_and_hostname())?;
|
let image_url = image.image_url(&context.settings().get_protocol_and_hostname())?;
|
||||||
|
@ -47,7 +52,7 @@ pub async fn get_image(
|
||||||
let name = &filename.into_inner();
|
let name = &filename.into_inner();
|
||||||
|
|
||||||
// If there are no query params, the URL is original
|
// If there are no query params, the URL is original
|
||||||
let pictrs_url = context.settings().pictrs_config()?.url;
|
let pictrs_url = context.settings().pictrs()?.url;
|
||||||
let processed_url = if params.file_type.is_none() && params.max_size.is_none() {
|
let processed_url = if params.file_type.is_none() && params.max_size.is_none() {
|
||||||
format!("{}image/original/{}", pictrs_url, name)
|
format!("{}image/original/{}", pictrs_url, name)
|
||||||
} else {
|
} else {
|
||||||
|
@ -69,7 +74,7 @@ pub async fn delete_image(
|
||||||
// require login
|
// require login
|
||||||
_local_user_view: LocalUserView,
|
_local_user_view: LocalUserView,
|
||||||
) -> LemmyResult<Json<SuccessResponse>> {
|
) -> LemmyResult<Json<SuccessResponse>> {
|
||||||
let pictrs_config = context.settings().pictrs_config()?;
|
let pictrs_config = context.settings().pictrs()?;
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}image/delete/{}/{}",
|
"{}image/delete/{}/{}",
|
||||||
pictrs_config.url, &data.token, &data.filename
|
pictrs_config.url, &data.token, &data.filename
|
||||||
|
@ -83,7 +88,7 @@ pub async fn delete_image(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn pictrs_health(context: Data<LemmyContext>) -> LemmyResult<Json<SuccessResponse>> {
|
pub async fn pictrs_health(context: Data<LemmyContext>) -> LemmyResult<Json<SuccessResponse>> {
|
||||||
let pictrs_config = context.settings().pictrs_config()?;
|
let pictrs_config = context.settings().pictrs()?;
|
||||||
let url = format!("{}healthz", pictrs_config.url);
|
let url = format!("{}healthz", pictrs_config.url);
|
||||||
|
|
||||||
PICTRS_CLIENT.get(url).send().await?.error_for_status()?;
|
PICTRS_CLIENT.get(url).send().await?.error_for_status()?;
|
||||||
|
@ -102,7 +107,7 @@ pub async fn image_proxy(
|
||||||
// for arbitrary purposes.
|
// for arbitrary purposes.
|
||||||
RemoteImage::validate(&mut context.pool(), url.clone().into()).await?;
|
RemoteImage::validate(&mut context.pool(), url.clone().into()).await?;
|
||||||
|
|
||||||
let pictrs_config = context.settings().pictrs_config()?;
|
let pictrs_config = context.settings().pictrs()?;
|
||||||
let processed_url = if params.file_type.is_none() && params.max_size.is_none() {
|
let processed_url = if params.file_type.is_none() && params.max_size.is_none() {
|
||||||
format!("{}image/original?proxy={}", pictrs_config.url, params.url)
|
format!("{}image/original?proxy={}", pictrs_config.url, params.url)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -125,7 +125,7 @@ pub(super) async fn do_upload_image(
|
||||||
local_user_view: &LocalUserView,
|
local_user_view: &LocalUserView,
|
||||||
context: &Data<LemmyContext>,
|
context: &Data<LemmyContext>,
|
||||||
) -> LemmyResult<PictrsFile> {
|
) -> LemmyResult<PictrsFile> {
|
||||||
let pictrs_config = context.settings().pictrs_config()?;
|
let pictrs_config = context.settings().pictrs()?;
|
||||||
let image_url = format!("{}image", pictrs_config.url);
|
let image_url = format!("{}image", pictrs_config.url);
|
||||||
|
|
||||||
let mut client_req = adapt_request(&req, image_url);
|
let mut client_req = adapt_request(&req, image_url);
|
||||||
|
@ -134,7 +134,7 @@ pub(super) async fn do_upload_image(
|
||||||
UploadType::Avatar => {
|
UploadType::Avatar => {
|
||||||
let max_size = context
|
let max_size = context
|
||||||
.settings()
|
.settings()
|
||||||
.pictrs_config()?
|
.pictrs()?
|
||||||
.max_avatar_size
|
.max_avatar_size
|
||||||
.to_string();
|
.to_string();
|
||||||
client_req.query(&[
|
client_req.query(&[
|
||||||
|
|
|
@ -31,6 +31,7 @@ pub enum LemmyErrorType {
|
||||||
NoContentTypeHeader,
|
NoContentTypeHeader,
|
||||||
NotAnImageType,
|
NotAnImageType,
|
||||||
InvalidImageUpload,
|
InvalidImageUpload,
|
||||||
|
ImageUploadDisabled,
|
||||||
NotAModOrAdmin,
|
NotAModOrAdmin,
|
||||||
NotTopMod,
|
NotTopMod,
|
||||||
NotLoggedIn,
|
NotLoggedIn,
|
||||||
|
|
|
@ -97,7 +97,7 @@ impl Settings {
|
||||||
WEBFINGER_REGEX.clone()
|
WEBFINGER_REGEX.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pictrs_config(&self) -> LemmyResult<PictrsConfig> {
|
pub fn pictrs(&self) -> LemmyResult<PictrsConfig> {
|
||||||
self
|
self
|
||||||
.pictrs
|
.pictrs
|
||||||
.clone()
|
.clone()
|
||||||
|
|
|
@ -116,6 +116,11 @@ pub struct PictrsConfig {
|
||||||
/// if image is larger.
|
/// if image is larger.
|
||||||
#[default(512)]
|
#[default(512)]
|
||||||
pub max_banner_size: u32,
|
pub max_banner_size: u32,
|
||||||
|
|
||||||
|
/// Prevent users from uploading images for posts or embedding in markdown. Avatars, icons and
|
||||||
|
/// banners can still be uploaded.
|
||||||
|
#[default(false)]
|
||||||
|
pub disable_image_upload: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document, PartialEq)]
|
#[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document, PartialEq)]
|
||||||
|
|
Loading…
Reference in a new issue