From becf54c4c4e3fc000f7430120a34dbbe956a9931 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Thu, 21 Dec 2023 12:04:43 +0100 Subject: [PATCH] add image proxy test, fix test --- api_tests/src/image.spec.ts | 61 ++++++++++++++++++++++++--- api_tests/src/shared.ts | 2 +- crates/api_common/src/utils.rs | 4 +- crates/api_crud/src/post/create.rs | 4 +- crates/api_crud/src/post/update.rs | 38 +++++++++++++---- crates/apub/src/objects/post.rs | 1 + docker/federation/lemmy_epsilon.hjson | 4 ++ docker/federation/lemmy_gamma.hjson | 4 ++ 8 files changed, 100 insertions(+), 18 deletions(-) diff --git a/api_tests/src/image.spec.ts b/api_tests/src/image.spec.ts index 569507d07..7587d1374 100644 --- a/api_tests/src/image.spec.ts +++ b/api_tests/src/image.spec.ts @@ -7,16 +7,23 @@ import { PurgePost, } from "lemmy-js-client"; import { + alpha, alphaImage, alphaUrl, beta, betaUrl, + createCommunity, createPost, + delta, + epsilon, + gamma, getSite, registerUser, resolveBetaCommunity, + resolvePost, setupLogins, unfollowRemotes, + waitForPost, } from "./shared"; const downloadFileSync = require("download-file-sync"); @@ -29,9 +36,8 @@ afterAll(() => { test("Upload image and delete it", async () => { // Upload test image. We use a simple string buffer as pictrs doesnt require an actual image // in testing mode. - const upload_image = Buffer.from("test"); const upload_form: UploadImage = { - image: upload_image, + image: Buffer.from("test"), }; const upload = await alphaImage.uploadImage(upload_form); expect(upload.files![0].file).toBeDefined(); @@ -60,9 +66,8 @@ test("Purge user, uploaded image removed", async () => { let user = await registerUser(alphaImage, alphaUrl); // upload test image - const upload_image = Buffer.from("test"); const upload_form: UploadImage = { - image: upload_image, + image: Buffer.from("test"), }; const upload = await user.uploadImage(upload_form); expect(upload.files![0].file).toBeDefined(); @@ -91,9 +96,8 @@ test("Purge post, linked image removed", async () => { let user = await registerUser(beta, betaUrl); // upload test image - const upload_image = Buffer.from("test"); const upload_form: UploadImage = { - image: upload_image, + image: Buffer.from("test"), }; const upload = await user.uploadImage(upload_form); expect(upload.files![0].file).toBeDefined(); @@ -124,3 +128,48 @@ test("Purge post, linked image removed", async () => { const content2 = downloadFileSync(upload.url); expect(content2).toBe(""); }); + +test("Images in remote post are proxied", async () => { + let user = await registerUser(beta, betaUrl); + let community = await createCommunity(gamma); + + const upload_form: UploadImage = { + image: Buffer.from("test"), + }; + const upload = await user.uploadImage(upload_form); + console.log(upload); + let post = await createPost( + gamma, + community.community_view.community.id, + upload.url, + "![](http://example.com/image2.png)", + ); + expect(post.post_view.post).toBeDefined(); + // remote image gets proxied after upload + console.log(post.post_view.post); + expect( + post.post_view.post.url?.startsWith( + "http://lemmy-gamma:8561/api/v3/image_proxy?url", + ), + ).toBeTruthy(); + expect( + post.post_view.post.body?.startsWith( + "![](http://lemmy-gamma:8561/api/v3/image_proxy?url", + ), + ).toBeTruthy(); + + let epsilonPost = await resolvePost(epsilon, post.post_view.post); + expect(epsilonPost.post).toBeDefined(); + console.log(epsilonPost.post); + // remote image gets proxied after federation + expect( + epsilonPost.post!.post.url?.startsWith( + "http://lemmy-epsilon:8581/api/v3/image_proxy?url", + ), + ).toBeTruthy(); + expect( + epsilonPost.post!.post.body?.startsWith( + "![](http://lemmy-epsilon:8581/api/v3/image_proxy?url", + ), + ).toBeTruthy(); +}); diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index fe51fb046..f9580ce96 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -204,9 +204,9 @@ export async function createPost( community_id: number, // use example.com for consistent title and embed description url: string = "https://example.com/", + body = randomString(10), ): Promise { let name = randomString(5); - let body = randomString(10); let form: CreatePost = { name, url, diff --git a/crates/api_common/src/utils.rs b/crates/api_common/src/utils.rs index e37070268..87faf5698 100644 --- a/crates/api_common/src/utils.rs +++ b/crates/api_common/src/utils.rs @@ -864,7 +864,9 @@ pub async fn process_markdown_opt( pub async fn proxy_image_link(link: Url, context: &LemmyContext) -> LemmyResult { // Dont rewrite links pointing to local domain. - if link.domain() == Some(&context.settings().hostname) { + if link.domain() == Some(&context.settings().hostname) + || !context.settings().pictrs_config()?.image_proxy + { return Ok(link.into()); } diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 344d54641..775e5b7e9 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -13,6 +13,7 @@ use lemmy_api_common::{ local_site_to_slur_regex, mark_post_as_read, process_markdown_opt, + proxy_image_link_opt_apub, EndpointType, }, }; @@ -84,6 +85,7 @@ pub async fn create_post( // Fetch post links and pictrs cached image let metadata = fetch_link_metadata_opt(url.as_ref(), true, &context).await?; + let url = proxy_image_link_opt_apub(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. @@ -109,7 +111,7 @@ pub async fn create_post( let post_form = PostInsertForm::builder() .name(data.name.trim().to_string()) - .url(url.map(Into::into)) + .url(url) .body(body) .community_id(data.community_id) .creator_id(local_user_view.person.id) diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs index b0f41951d..c2877ec9d 100644 --- a/crates/api_crud/src/post/update.rs +++ b/crates/api_crud/src/post/update.rs @@ -4,9 +4,14 @@ use lemmy_api_common::{ build_response::build_post_response, context::LemmyContext, post::{EditPost, PostResponse}, - request::fetch_link_metadata_opt, + request::fetch_link_metadata, 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, + process_markdown_opt, + proxy_image_link_opt_apub, + }, }; use lemmy_db_schema::{ source::{ @@ -65,8 +70,23 @@ pub async fn update_post( Err(LemmyErrorType::NoPostEditAllowed)? } - // Fetch post links and Pictrs cached image - let metadata = fetch_link_metadata_opt(url.as_ref(), true, &context).await?; + // Fetch post links and Pictrs cached image if url was updated + let (embed_title, embed_description, embed_video_url, thumbnail_url) = match &url { + Some(url) => { + let metadata = fetch_link_metadata(url, true, &context).await?; + ( + Some(metadata.title), + Some(metadata.description), + Some(metadata.embed_video_url), + Some(metadata.thumbnail), + ) + } + _ => Default::default(), + }; + let url = match url { + Some(url) => Some(proxy_image_link_opt_apub(Some(url), &context).await?), + _ => Default::default(), + }; let language_id = data.language_id; CommunityLanguage::is_allowed_community_language( @@ -78,14 +98,14 @@ pub async fn update_post( let post_form = PostUpdateForm { name: data.name.clone(), - url: Some(url.map(Into::into)), + url, body: diesel_option_overwrite(body), nsfw: data.nsfw, - embed_title: Some(metadata.title), - embed_description: Some(metadata.description), - embed_video_url: Some(metadata.embed_video_url), + embed_title, + embed_description, + embed_video_url, language_id: data.language_id, - thumbnail_url: Some(metadata.thumbnail), + thumbnail_url, updated: Some(Some(naive_now())), ..Default::default() }; diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index d05ef4e1d..dd4df7488 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -228,6 +228,7 @@ impl Object for ApubPost { if let Some(thumbnail_url_) = metadata.thumbnail { thumbnail_url = Some(thumbnail_url_.into()); } + let url = proxy_image_link_opt_apub(url, context).await?; let thumbnail_url = proxy_image_link_opt_apub(thumbnail_url, context).await?; let slur_regex = &local_site_opt_to_slur_regex(&local_site); diff --git a/docker/federation/lemmy_epsilon.hjson b/docker/federation/lemmy_epsilon.hjson index 17fe2f635..51a79ddb9 100644 --- a/docker/federation/lemmy_epsilon.hjson +++ b/docker/federation/lemmy_epsilon.hjson @@ -10,4 +10,8 @@ database: { host: postgres_epsilon } + pictrs: { + api_key: "my-pictrs-key" + image_proxy: true + } } diff --git a/docker/federation/lemmy_gamma.hjson b/docker/federation/lemmy_gamma.hjson index 2041c9840..de1e6961c 100644 --- a/docker/federation/lemmy_gamma.hjson +++ b/docker/federation/lemmy_gamma.hjson @@ -10,4 +10,8 @@ database: { host: postgres_gamma } + pictrs: { + api_key: "my-pictrs-key" + image_proxy: true + } }