From ccb1883e3e934bad354a9a099837d6b882cce740 Mon Sep 17 00:00:00 2001 From: caipira113 Date: Mon, 19 Aug 2024 19:03:26 +0900 Subject: [PATCH] feat(backend): Override the file URL rendering in AP --- .config/docker_example.yml | 3 +++ .config/example.yml | 3 +++ .devcontainer/devcontainer.yml | 3 +++ chart/files/default.yml | 3 +++ packages/backend/src/config.ts | 4 ++++ .../src/core/activitypub/ApRendererService.ts | 4 ++-- .../src/core/activitypub/models/ApPersonService.ts | 4 ++-- .../src/core/entities/DriveFileEntityService.ts | 12 +++++++++++- 8 files changed, 31 insertions(+), 5 deletions(-) diff --git a/.config/docker_example.yml b/.config/docker_example.yml index d347882d1..92c9f90c1 100644 --- a/.config/docker_example.yml +++ b/.config/docker_example.yml @@ -178,6 +178,9 @@ id: 'aidx' # IP address family used for outgoing request (ipv4, ipv6 or dual) #outgoingAddressFamily: ipv4 +# Override the file URL rendering in ActivityPub (Object Storage file only) +#apFileBaseUrl: https://example.com/ + # Proxy for HTTP/HTTPS #proxy: http://127.0.0.1:3128 diff --git a/.config/example.yml b/.config/example.yml index b11cbd137..2a76432e7 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -251,6 +251,9 @@ id: 'aidx' # IP address family used for outgoing request (ipv4, ipv6 or dual) #outgoingAddressFamily: ipv4 +# Override the file URL rendering in ActivityPub (Object Storage file only) +#apFileBaseUrl: https://example.com/ + # Proxy for HTTP/HTTPS #proxy: http://127.0.0.1:3128 diff --git a/.devcontainer/devcontainer.yml b/.devcontainer/devcontainer.yml index beefcfd0a..9d3023581 100644 --- a/.devcontainer/devcontainer.yml +++ b/.devcontainer/devcontainer.yml @@ -171,6 +171,9 @@ id: 'aidx' # IP address family used for outgoing request (ipv4, ipv6 or dual) #outgoingAddressFamily: ipv4 +# Override the file URL rendering in ActivityPub (Object Storage file only) +#apFileBaseUrl: https://example.com/ + # Proxy for HTTP/HTTPS #proxy: http://127.0.0.1:3128 diff --git a/chart/files/default.yml b/chart/files/default.yml index f98b8ebfe..698c3d734 100644 --- a/chart/files/default.yml +++ b/chart/files/default.yml @@ -192,6 +192,9 @@ id: "aidx" # IP address family used for outgoing request (ipv4, ipv6 or dual) #outgoingAddressFamily: ipv4 +# Override the file URL rendering in ActivityPub (Object Storage file only) +#apFileBaseUrl: https://example.com/ + # Proxy for HTTP/HTTPS #proxy: http://127.0.0.1:3128 diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index 3e5a1e81c..5428b59f9 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -62,6 +62,8 @@ type Source = { publishTarballInsteadOfProvideRepositoryUrl?: boolean; + apFileBaseUrl?: string; + proxy?: string; proxySmtp?: string; proxyBypassHosts?: string[]; @@ -129,6 +131,7 @@ export type Config = { index: string; scope?: 'local' | 'global' | string[]; } | undefined; + apFileBaseUrl: string | undefined; proxy: string | undefined; proxySmtp: string | undefined; proxyBypassHosts: string[] | undefined; @@ -246,6 +249,7 @@ export function loadConfig(): Config { sentryForBackend: config.sentryForBackend, sentryForFrontend: config.sentryForFrontend, id: config.id, + apFileBaseUrl: config.apFileBaseUrl, proxy: config.proxy, proxySmtp: config.proxySmtp, proxyBypassHosts: config.proxyBypassHosts, diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts index 98e944f34..d134e46b5 100644 --- a/packages/backend/src/core/activitypub/ApRendererService.ts +++ b/packages/backend/src/core/activitypub/ApRendererService.ts @@ -164,7 +164,7 @@ export class ApRendererService { return { type: 'Document', mediaType: file.webpublicType ?? file.type, - url: this.driveFileEntityService.getPublicUrl(file), + url: this.driveFileEntityService.getPublicUrl(file, undefined, true), name: file.comment, sensitive: file.isSensitive, }; @@ -244,7 +244,7 @@ export class ApRendererService { public renderImage(file: MiDriveFile): IApImage { return { type: 'Image', - url: this.driveFileEntityService.getPublicUrl(file), + url: this.driveFileEntityService.getPublicUrl(file, undefined, true), sensitive: file.isSensitive, name: file.comment, }; diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index f3ddf3952..53092ba57 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -256,12 +256,12 @@ export class ApPersonService implements OnModuleInit { return { ...( avatar ? { avatarId: avatar.id, - avatarUrl: avatar.url ? this.driveFileEntityService.getPublicUrl(avatar, 'avatar') : null, + avatarUrl: avatar.url ? this.driveFileEntityService.getPublicUrl(avatar, 'avatar', true) : null, avatarBlurhash: avatar.blurhash, } : {}), ...( banner ? { bannerId: banner.id, - bannerUrl: banner.url ? this.driveFileEntityService.getPublicUrl(banner) : null, + bannerUrl: banner.url ? this.driveFileEntityService.getPublicUrl(banner, undefined, true) : null, bannerBlurhash: banner.blurhash, } : {}), }; diff --git a/packages/backend/src/core/entities/DriveFileEntityService.ts b/packages/backend/src/core/entities/DriveFileEntityService.ts index c485555f9..9d4c5e1f6 100644 --- a/packages/backend/src/core/entities/DriveFileEntityService.ts +++ b/packages/backend/src/core/entities/DriveFileEntityService.ts @@ -108,7 +108,7 @@ export class DriveFileEntityService { } @bindThis - public getPublicUrl(file: MiDriveFile, mode?: 'avatar'): string { // static = thumbnail + public getPublicUrl(file: MiDriveFile, mode?: 'avatar', ap?: boolean): string { // static = thumbnail // リモートかつメディアプロキシ if (file.uri != null && file.userHost != null && this.config.externalMediaProxyEnabled) { return this.getProxiedUrl(file.uri, mode); @@ -130,6 +130,16 @@ export class DriveFileEntityService { if (mode === 'avatar') { return this.getProxiedUrl(url, 'avatar'); } + + if (ap && this.config.apFileBaseUrl) { + const baseUrl = this.config.apFileBaseUrl; + const isValidBaseUrl = /^https?:\/\/[\w.-]+\.[a-zA-Z]{2,}(\/.*)?$/i.test(baseUrl); + if (isValidBaseUrl) { + const trimmedBaseUrl = baseUrl.replace(/\/$/, ''); + return url.replace(/^https?:\/\/[\w.-]+\.[a-zA-Z]{2,}/, trimmedBaseUrl); + } + } + return url; }