summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsyuilo <4439005+syuilo@users.noreply.github.com>2025-05-12 16:55:01 +0900
committerGitHub <noreply@github.com>2025-05-12 16:55:01 +0900
commit26506677c2debbe7d58b26f1e5c98b834bc72e0f (patch)
treef6b8da6b0e7ddf837b41895ef4de1e3f36275d0b
parent🎨 (diff)
downloadmisskey-26506677c2debbe7d58b26f1e5c98b834bc72e0f.tar.gz
misskey-26506677c2debbe7d58b26f1e5c98b834bc72e0f.tar.bz2
misskey-26506677c2debbe7d58b26f1e5c98b834bc72e0f.zip
enhance: いくつかの設定ファイルの項目をコントロールパネルで設定するように (#16026)
* wip * Update CHANGELOG.md * feat: migrate to existing config value (#16030) * wip * Update CHANGELOG.md --------- Co-authored-by: anatawa12 <anatawa12@icloud.com>
-rw-r--r--.config/cypress-devcontainer.yml11
-rw-r--r--.config/docker_example.yml11
-rw-r--r--.config/example.yml12
-rw-r--r--.devcontainer/devcontainer.yml6
-rw-r--r--CHANGELOG.md7
-rw-r--r--chart/files/default.yml3
-rw-r--r--locales/index.d.ts30
-rw-r--r--locales/ja-JP.yml9
-rw-r--r--packages/backend/migration/1746949539915-migrateSomeConfigFileSettingsToMeta.js24
-rw-r--r--packages/backend/migration/js/migration-config.js23
-rw-r--r--packages/backend/src/config.ts12
-rw-r--r--packages/backend/src/core/activitypub/ApResolverService.ts2
-rw-r--r--packages/backend/src/core/entities/DriveFileEntityService.ts9
-rw-r--r--packages/backend/src/models/Meta.ts15
-rw-r--r--packages/backend/src/server/ServerService.ts6
-rw-r--r--packages/backend/src/server/api/endpoints/admin/meta.ts15
-rw-r--r--packages/backend/src/server/api/endpoints/admin/update-meta.ts15
-rw-r--r--packages/backend/test-federation/.config/example.default.yml2
-rw-r--r--packages/frontend/src/pages/admin/settings.vue73
-rw-r--r--packages/misskey-js/src/autogen/types.ts6
20 files changed, 193 insertions, 98 deletions
diff --git a/.config/cypress-devcontainer.yml b/.config/cypress-devcontainer.yml
index a028e2685e..8b11c8413c 100644
--- a/.config/cypress-devcontainer.yml
+++ b/.config/cypress-devcontainer.yml
@@ -215,20 +215,9 @@ proxyBypassHosts:
# Media Proxy
#mediaProxy: https://example.com/proxy
-# Proxy remote files (default: true)
-proxyRemoteFiles: true
-
-# Sign to ActivityPub GET request (default: true)
-signToActivityPubGet: true
-
allowedPrivateNetworks: [
'127.0.0.1/32'
]
-# Disable automatic redirect for ActivityPub object lookup. (default: false)
-# This is a strong defense against potential impersonation attacks if the viewer instance has inadequate validation.
-# However it will make it impossible for other instances to lookup third-party user and notes through your URL.
-#disallowExternalApRedirect: true
-
# Upload or download file size limits (bytes)
#maxFileSize: 262144000
diff --git a/.config/docker_example.yml b/.config/docker_example.yml
index 4be1352bd7..dc354324dc 100644
--- a/.config/docker_example.yml
+++ b/.config/docker_example.yml
@@ -227,12 +227,6 @@ proxyBypassHosts:
# Media Proxy
#mediaProxy: https://example.com/proxy
-# Proxy remote files (default: true)
-proxyRemoteFiles: true
-
-# Sign to ActivityPub GET request (default: true)
-signToActivityPubGet: true
-
# For security reasons, uploading attachments from the intranet is prohibited,
# but exceptions can be made from the following settings. Default value is "undefined".
# Read changelog to learn more (Improvements of 12.90.0 (2021/09/04)).
@@ -240,11 +234,6 @@ signToActivityPubGet: true
# '127.0.0.1/32'
#]
-# Disable automatic redirect for ActivityPub object lookup. (default: false)
-# This is a strong defense against potential impersonation attacks if the viewer instance has inadequate validation.
-# However it will make it impossible for other instances to lookup third-party user and notes through your URL.
-#disallowExternalApRedirect: true
-
# Upload or download file size limits (bytes)
#maxFileSize: 262144000
diff --git a/.config/example.yml b/.config/example.yml
index d4584215c9..c127eaae22 100644
--- a/.config/example.yml
+++ b/.config/example.yml
@@ -319,19 +319,12 @@ proxyBypassHosts:
# * Perform image compression (on a different server resource than the main process)
#mediaProxy: https://example.com/proxy
-# Proxy remote files (default: true)
-# Proxy remote files by this instance or mediaProxy to prevent remote files from running in remote domains.
-proxyRemoteFiles: true
-
# Movie Thumbnail Generation URL
# There is no reference implementation.
# For example, Misskey will point to the following URL:
# https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4
#videoThumbnailGenerator: https://example.com
-# Sign to ActivityPub GET request (default: true)
-signToActivityPubGet: true
-
# For security reasons, uploading attachments from the intranet is prohibited,
# but exceptions can be made from the following settings. Default value is "undefined".
# Read changelog to learn more (Improvements of 12.90.0 (2021/09/04)).
@@ -339,11 +332,6 @@ signToActivityPubGet: true
# '127.0.0.1/32'
#]
-# Disable automatic redirect for ActivityPub object lookup. (default: false)
-# This is a strong defense against potential impersonation attacks if the viewer instance has inadequate validation.
-# However it will make it impossible for other instances to lookup third-party user and notes through your URL.
-#disallowExternalApRedirect: true
-
# Upload or download file size limits (bytes)
#maxFileSize: 262144000
diff --git a/.devcontainer/devcontainer.yml b/.devcontainer/devcontainer.yml
index 6d904e87b9..fb0d25c214 100644
--- a/.devcontainer/devcontainer.yml
+++ b/.devcontainer/devcontainer.yml
@@ -202,12 +202,6 @@ proxyBypassHosts:
# Media Proxy
#mediaProxy: https://example.com/proxy
-# Proxy remote files (default: true)
-proxyRemoteFiles: true
-
-# Sign to ActivityPub GET request (default: true)
-signToActivityPubGet: true
-
allowedPrivateNetworks: [
'127.0.0.1/32'
]
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2d4fa47589..3a72ed9bdb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
## 2025.5.1
+### Note
+- 設定ファイルの以下の項目がコントロールパネルから設定するようになりました
+ - signToActivityPubGet
+ - proxyRemoteFiles
+ - disallowExternalApRedirect
+ - 許可しないかどうかではなく、許可するかどうかの設定(allowExternalApRedirect)になりました
+
### General
- Feat: 非ログインでサーバーを閲覧された際に、サーバー内のコンテンツを非公開にすることができるようになりました
- モデレーションが行き届きにくい不適切なリモートコンテンツなどが、自サーバー経由で図らずもインターネットに公開されてしまうことによるトラブル防止などに役立ちます
diff --git a/chart/files/default.yml b/chart/files/default.yml
index 06f762aafa..8fa0b39eff 100644
--- a/chart/files/default.yml
+++ b/chart/files/default.yml
@@ -221,9 +221,6 @@ id: "aidx"
# Media Proxy
#mediaProxy: https://example.com/proxy
-# Sign to ActivityPub GET request (default: true)
-signToActivityPubGet: true
-
#allowedPrivateNetworks: [
# '127.0.0.1/32'
#]
diff --git a/locales/index.d.ts b/locales/index.d.ts
index ed9d127a2e..d4ff9a8b03 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -707,7 +707,7 @@ export interface Locale extends ILocale {
*/
"cacheRemoteFiles": string;
/**
- * この設定を有効にすると、リモートファイルをこのサーバーのストレージにキャッシュするようになります。画像の表示が高速になりますが、サーバーのストレージを多く消費します。リモートユーザーがどれほどキャッシュを保持するかは、ロールによるドライブ容量制限によって決定されます。この制限を超えた場合、古いファイルからキャッシュが削除されリンクになります。この設定が無効の場合、リモートのファイルを最初からリンクとして保持しますが、画像のサムネイル生成やユーザーのプライバシー保護のために、default.ymlでproxyRemoteFilesをtrueにすることをお勧めします。
+ * この設定を有効にすると、リモートファイルをこのサーバーのストレージにキャッシュするようになります。画像の表示が高速になりますが、サーバーのストレージを多く消費します。リモートユーザーがどれほどキャッシュを保持するかは、ロールによるドライブ容量制限によって決定されます。この制限を超えた場合、古いファイルからキャッシュが削除されリンクになります。この設定が無効の場合、リモートのファイルを最初からリンクとして保持します。
*/
"cacheRemoteFilesDescription": string;
/**
@@ -3187,6 +3187,10 @@ export interface Locale extends ILocale {
*/
"needReloadToApply": string;
/**
+ * 反映にはサーバーの再起動が必要です。
+ */
+ "needToRestartServerToApply": string;
+ /**
* タイトルバーを表示する
*/
"showTitlebar": string;
@@ -6453,6 +6457,30 @@ export interface Locale extends ILocale {
*/
"singleUserMode_description": string;
/**
+ * GETリクエストに署名する
+ */
+ "signToActivityPubGet": string;
+ /**
+ * 通常は有効にしてください。連合の通信に関する問題がある場合に、無効にすると改善することがありますが、逆にサーバーによっては通信が不可になることがあります。
+ */
+ "signToActivityPubGet_description": string;
+ /**
+ * リモートファイルをプロキシする
+ */
+ "proxyRemoteFiles": string;
+ /**
+ * 有効にすると、リモートのファイルをプロキシして提供します。画像のサムネイル生成やユーザーのプライバシー保護に役立ちます。
+ */
+ "proxyRemoteFiles_description": string;
+ /**
+ * ActivityPub経由の照会にリダイレクトを許可する
+ */
+ "allowExternalApRedirect": string;
+ /**
+ * 有効にすると、他のサーバーがこのサーバーを通して第三者のコンテンツを照会することが可能になりますが、コンテンツのなりすましが発生する可能性があります。
+ */
+ "allowExternalApRedirect_description": string;
+ /**
* 非利用者に対するユーザー作成コンテンツの公開範囲
*/
"userGeneratedContentsVisibilityForVisitor": string;
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index e318234087..8f1a245f02 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -172,7 +172,7 @@ emojiUrl: "絵文字画像URL"
addEmoji: "絵文字を追加"
settingGuide: "おすすめ設定"
cacheRemoteFiles: "リモートのファイルをキャッシュする"
-cacheRemoteFilesDescription: "この設定を有効にすると、リモートファイルをこのサーバーのストレージにキャッシュするようになります。画像の表示が高速になりますが、サーバーのストレージを多く消費します。リモートユーザーがどれほどキャッシュを保持するかは、ロールによるドライブ容量制限によって決定されます。この制限を超えた場合、古いファイルからキャッシュが削除されリンクになります。この設定が無効の場合、リモートのファイルを最初からリンクとして保持しますが、画像のサムネイル生成やユーザーのプライバシー保護のために、default.ymlでproxyRemoteFilesをtrueにすることをお勧めします。"
+cacheRemoteFilesDescription: "この設定を有効にすると、リモートファイルをこのサーバーのストレージにキャッシュするようになります。画像の表示が高速になりますが、サーバーのストレージを多く消費します。リモートユーザーがどれほどキャッシュを保持するかは、ロールによるドライブ容量制限によって決定されます。この制限を超えた場合、古いファイルからキャッシュが削除されリンクになります。この設定が無効の場合、リモートのファイルを最初からリンクとして保持します。"
youCanCleanRemoteFilesCache: "ファイル管理の🗑️ボタンで全てのキャッシュを削除できます。"
cacheRemoteSensitiveFiles: "リモートのセンシティブなファイルをキャッシュする"
cacheRemoteSensitiveFilesDescription: "この設定を無効にすると、リモートのセンシティブなファイルはキャッシュせず直リンクするようになります。"
@@ -792,6 +792,7 @@ wide: "広い"
narrow: "狭い"
reloadToApplySetting: "設定はページリロード後に反映されます。"
needReloadToApply: "反映には再起動が必要です。"
+needToRestartServerToApply: "反映にはサーバーの再起動が必要です。"
showTitlebar: "タイトルバーを表示する"
clearCache: "キャッシュをクリア"
onlineUsersCount: "{n}人がオンライン"
@@ -1639,6 +1640,12 @@ _serverSettings:
deliverSuspendedSoftwareDescription: "脆弱性などの理由で、サーバーのソフトウェアの名前及びバージョンの範囲を指定して配信を停止できます。このバージョン情報はサーバーが提供したものであり、信頼性は保証されません。バージョン指定には semver の範囲指定が使用できますが、>= 2024.3.1 と指定すると 2024.3.1-custom.0 のようなカスタムバージョンが含まれないため、>= 2024.3.1-0 のように prerelease の指定を行うことを推奨します。"
singleUserMode: "お一人様モード"
singleUserMode_description: "このサーバーを利用するのが自分だけの場合、このモードを有効にすることで動作が最適化されます。"
+ signToActivityPubGet: "GETリクエストに署名する"
+ signToActivityPubGet_description: "通常は有効にしてください。連合の通信に関する問題がある場合に、無効にすると改善することがありますが、逆にサーバーによっては通信が不可になることがあります。"
+ proxyRemoteFiles: "リモートファイルをプロキシする"
+ proxyRemoteFiles_description: "有効にすると、リモートのファイルをプロキシして提供します。画像のサムネイル生成やユーザーのプライバシー保護に役立ちます。"
+ allowExternalApRedirect: "ActivityPub経由の照会にリダイレクトを許可する"
+ allowExternalApRedirect_description: "有効にすると、他のサーバーがこのサーバーを通して第三者のコンテンツを照会することが可能になりますが、コンテンツのなりすましが発生する可能性があります。"
userGeneratedContentsVisibilityForVisitor: "非利用者に対するユーザー作成コンテンツの公開範囲"
userGeneratedContentsVisibilityForVisitor_description: "モデレーションが行き届きにくい不適切なリモートコンテンツなどが、自サーバー経由で図らずもインターネットに公開されてしまうことによるトラブル防止などに役立ちます。"
userGeneratedContentsVisibilityForVisitor_description2: "サーバーで受信したリモートのコンテンツを含め、サーバー内の全てのコンテンツを無条件でインターネットに公開することはリスクが伴います。特に、分散型の特性を知らない閲覧者にとっては、リモートのコンテンツであってもサーバー内で作成されたコンテンツであると誤って認識してしまう可能性があるため、注意が必要です。"
diff --git a/packages/backend/migration/1746949539915-migrateSomeConfigFileSettingsToMeta.js b/packages/backend/migration/1746949539915-migrateSomeConfigFileSettingsToMeta.js
new file mode 100644
index 0000000000..3243f43b91
--- /dev/null
+++ b/packages/backend/migration/1746949539915-migrateSomeConfigFileSettingsToMeta.js
@@ -0,0 +1,24 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import {loadConfig} from "./js/migration-config.js";
+
+export class MigrateSomeConfigFileSettingsToMeta1746949539915 {
+ name = 'MigrateSomeConfigFileSettingsToMeta1746949539915'
+
+ async up(queryRunner) {
+ const config = loadConfig();
+ // $1 cannot be used in ALTER TABLE queries
+ await queryRunner.query(`ALTER TABLE "meta" ADD "proxyRemoteFiles" boolean NOT NULL DEFAULT ${config.proxyRemoteFiles}`);
+ await queryRunner.query(`ALTER TABLE "meta" ADD "signToActivityPubGet" boolean NOT NULL DEFAULT ${config.signToActivityPubGet}`);
+ await queryRunner.query(`ALTER TABLE "meta" ADD "allowExternalApRedirect" boolean NOT NULL DEFAULT ${!config.disallowExternalApRedirect}`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "allowExternalApRedirect"`);
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "signToActivityPubGet"`);
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "proxyRemoteFiles"`);
+ }
+}
diff --git a/packages/backend/migration/js/migration-config.js b/packages/backend/migration/js/migration-config.js
index 8cfbb21470..853735661b 100644
--- a/packages/backend/migration/js/migration-config.js
+++ b/packages/backend/migration/js/migration-config.js
@@ -3,6 +3,29 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
+import { path as configYamlPath } from '../../built/config.js';
+import * as yaml from 'js-yaml';
+import fs from "node:fs";
+
export function isConcurrentIndexMigrationEnabled() {
return process.env.MISSKEY_MIGRATION_CREATE_INDEX_CONCURRENTLY === '1';
}
+
+let loadedConfigCache = undefined;
+
+function loadConfigInternal() {
+ const config = yaml.load(fs.readFileSync(configYamlPath, 'utf-8'));
+
+ return {
+ disallowExternalApRedirect: Boolean(config.disallowExternalApRedirect ?? false),
+ proxyRemoteFiles: Boolean(config.proxyRemoteFiles ?? false),
+ signToActivityPubGet: Boolean(config.signToActivityPubGet ?? true),
+ }
+}
+
+export function loadConfig() {
+ if (loadedConfigCache === undefined) {
+ loadedConfigCache = loadConfigInternal();
+ }
+ return loadedConfigCache;
+}
diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts
index 646fa07911..9031096745 100644
--- a/packages/backend/src/config.ts
+++ b/packages/backend/src/config.ts
@@ -79,7 +79,6 @@ type Source = {
proxyBypassHosts?: string[];
allowedPrivateNetworks?: string[];
- disallowExternalApRedirect?: boolean;
maxFileSize?: number;
@@ -100,11 +99,8 @@ type Source = {
inboxJobMaxAttempts?: number;
mediaProxy?: string;
- proxyRemoteFiles?: boolean;
videoThumbnailGenerator?: string;
- signToActivityPubGet?: boolean;
-
perChannelMaxNoteCacheCount?: number;
perUserNotificationsMaxCount?: number;
deactivateAntennaThreshold?: number;
@@ -156,7 +152,6 @@ export type Config = {
proxySmtp: string | undefined;
proxyBypassHosts: string[] | undefined;
allowedPrivateNetworks: string[] | undefined;
- disallowExternalApRedirect: boolean;
maxFileSize: number;
clusterLimit: number | undefined;
id: string;
@@ -170,8 +165,6 @@ export type Config = {
relationshipJobPerSec: number | undefined;
deliverJobMaxAttempts: number | undefined;
inboxJobMaxAttempts: number | undefined;
- proxyRemoteFiles: boolean | undefined;
- signToActivityPubGet: boolean | undefined;
logging?: {
sql?: {
disableQueryTruncation?: boolean,
@@ -229,7 +222,7 @@ const dir = `${_dirname}/../../../.config`;
/**
* Path of configuration file
*/
-const path = process.env.MISSKEY_CONFIG_YML
+export const path = process.env.MISSKEY_CONFIG_YML
? resolve(dir, process.env.MISSKEY_CONFIG_YML)
: process.env.NODE_ENV === 'test'
? resolve(dir, 'test.yml')
@@ -300,7 +293,6 @@ export function loadConfig(): Config {
proxySmtp: config.proxySmtp,
proxyBypassHosts: config.proxyBypassHosts,
allowedPrivateNetworks: config.allowedPrivateNetworks,
- disallowExternalApRedirect: config.disallowExternalApRedirect ?? false,
maxFileSize: config.maxFileSize ?? 262144000,
clusterLimit: config.clusterLimit,
outgoingAddress: config.outgoingAddress,
@@ -313,8 +305,6 @@ export function loadConfig(): Config {
relationshipJobPerSec: config.relationshipJobPerSec,
deliverJobMaxAttempts: config.deliverJobMaxAttempts,
inboxJobMaxAttempts: config.inboxJobMaxAttempts,
- proxyRemoteFiles: config.proxyRemoteFiles,
- signToActivityPubGet: config.signToActivityPubGet ?? true,
mediaProxy: externalMediaProxy ?? internalMediaProxy,
externalMediaProxyEnabled: externalMediaProxy !== null && externalMediaProxy !== internalMediaProxy,
videoThumbnailGenerator: config.videoThumbnailGenerator ?
diff --git a/packages/backend/src/core/activitypub/ApResolverService.ts b/packages/backend/src/core/activitypub/ApResolverService.ts
index 2534899ad1..646150455b 100644
--- a/packages/backend/src/core/activitypub/ApResolverService.ts
+++ b/packages/backend/src/core/activitypub/ApResolverService.ts
@@ -104,7 +104,7 @@ export class Resolver {
throw new IdentifiableError('09d79f9e-64f1-4316-9cfa-e75c4d091574', 'Instance is blocked');
}
- if (this.config.signToActivityPubGet && !this.user) {
+ if (this.meta.signToActivityPubGet && !this.user) {
this.user = await this.systemAccountService.fetch('actor');
}
diff --git a/packages/backend/src/core/entities/DriveFileEntityService.ts b/packages/backend/src/core/entities/DriveFileEntityService.ts
index c485555f90..a6f7f369a6 100644
--- a/packages/backend/src/core/entities/DriveFileEntityService.ts
+++ b/packages/backend/src/core/entities/DriveFileEntityService.ts
@@ -6,7 +6,7 @@
import { forwardRef, Inject, Injectable } from '@nestjs/common';
import { In } from 'typeorm';
import { DI } from '@/di-symbols.js';
-import type { DriveFilesRepository } from '@/models/_.js';
+import type { DriveFilesRepository, MiMeta } from '@/models/_.js';
import type { Config } from '@/config.js';
import type { Packed } from '@/misc/json-schema.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
@@ -34,6 +34,9 @@ export class DriveFileEntityService {
@Inject(DI.config)
private config: Config,
+ @Inject(DI.meta)
+ private meta: MiMeta,
+
@Inject(DI.driveFilesRepository)
private driveFilesRepository: DriveFilesRepository,
@@ -95,7 +98,7 @@ export class DriveFileEntityService {
return this.getProxiedUrl(file.uri, 'static');
}
- if (file.uri != null && file.isLink && this.config.proxyRemoteFiles) {
+ if (file.uri != null && file.isLink && this.meta.proxyRemoteFiles) {
// リモートかつ期限切れはローカルプロキシを試みる
// 従来は/files/${thumbnailAccessKey}にアクセスしていたが、
// /filesはメディアプロキシにリダイレクトするようにしたため直接メディアプロキシを指定する
@@ -115,7 +118,7 @@ export class DriveFileEntityService {
}
// リモートかつ期限切れはローカルプロキシを試みる
- if (file.uri != null && file.isLink && this.config.proxyRemoteFiles) {
+ if (file.uri != null && file.isLink && this.meta.proxyRemoteFiles) {
const key = file.webpublicAccessKey;
if (key && !key.match('/')) { // 古いものはここにオブジェクトストレージキーが入ってるので除外
diff --git a/packages/backend/src/models/Meta.ts b/packages/backend/src/models/Meta.ts
index e3625b247c..545173ff3c 100644
--- a/packages/backend/src/models/Meta.ts
+++ b/packages/backend/src/models/Meta.ts
@@ -680,6 +680,21 @@ export class MiMeta {
default: false,
})
public singleUserMode: boolean;
+
+ @Column('boolean', {
+ default: true,
+ })
+ public proxyRemoteFiles: boolean;
+
+ @Column('boolean', {
+ default: true,
+ })
+ public signToActivityPubGet: boolean;
+
+ @Column('boolean', {
+ default: true,
+ })
+ public allowExternalApRedirect: boolean;
}
export type SoftwareSuspension = {
diff --git a/packages/backend/src/server/ServerService.ts b/packages/backend/src/server/ServerService.ts
index c859f1d82c..23c085ee27 100644
--- a/packages/backend/src/server/ServerService.ts
+++ b/packages/backend/src/server/ServerService.ts
@@ -108,7 +108,7 @@ export class ServerService implements OnApplicationShutdown {
// this will break lookup that involve copying a URL from a third-party server, like trying to lookup http://charlie.example.com/@alice@alice.com
//
// this is not required by standard but protect us from peers that did not validate final URL.
- if (this.config.disallowExternalApRedirect) {
+ if (!this.meta.allowExternalApRedirect) {
const maybeApLookupRegex = /application\/activity\+json|application\/ld\+json.+activitystreams/i;
fastify.addHook('onSend', (request, reply, _, done) => {
const location = reply.getHeader('location');
@@ -133,8 +133,8 @@ export class ServerService implements OnApplicationShutdown {
reply.header('content-type', 'text/plain; charset=utf-8');
reply.header('link', `<${encodeURI(location)}>; rel="canonical"`);
done(null, [
- "Refusing to relay remote ActivityPub object lookup.",
- "",
+ 'Refusing to relay remote ActivityPub object lookup.',
+ '',
`Please remove 'application/activity+json' and 'application/ld+json' from the Accept header or fetch using the authoritative URL at ${location}.`,
].join('\n'));
});
diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts
index cd36985485..0cd46b614f 100644
--- a/packages/backend/src/server/api/endpoints/admin/meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/meta.ts
@@ -555,6 +555,18 @@ export const meta = {
enum: ['all', 'local', 'none'],
optional: false, nullable: false,
},
+ proxyRemoteFiles: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
+ signToActivityPubGet: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
+ allowExternalApRedirect: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
},
},
} as const;
@@ -702,6 +714,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
deliverSuspendedSoftware: instance.deliverSuspendedSoftware,
singleUserMode: instance.singleUserMode,
ugcVisibilityForVisitor: instance.ugcVisibilityForVisitor,
+ proxyRemoteFiles: instance.proxyRemoteFiles,
+ signToActivityPubGet: instance.signToActivityPubGet,
+ allowExternalApRedirect: instance.allowExternalApRedirect,
};
});
}
diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
index a96fbd759c..0e3569d667 100644
--- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
@@ -201,6 +201,9 @@ export const paramDef = {
type: 'string',
enum: ['all', 'local', 'none'],
},
+ proxyRemoteFiles: { type: 'boolean' },
+ signToActivityPubGet: { type: 'boolean' },
+ allowExternalApRedirect: { type: 'boolean' },
},
required: [],
} as const;
@@ -703,6 +706,18 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
set.ugcVisibilityForVisitor = ps.ugcVisibilityForVisitor;
}
+ if (ps.proxyRemoteFiles !== undefined) {
+ set.proxyRemoteFiles = ps.proxyRemoteFiles;
+ }
+
+ if (ps.signToActivityPubGet !== undefined) {
+ set.signToActivityPubGet = ps.signToActivityPubGet;
+ }
+
+ if (ps.allowExternalApRedirect !== undefined) {
+ set.allowExternalApRedirect = ps.allowExternalApRedirect;
+ }
+
const before = await this.metaService.fetch(true);
await this.metaService.update(set);
diff --git a/packages/backend/test-federation/.config/example.default.yml b/packages/backend/test-federation/.config/example.default.yml
index 28d51ac86e..fd20613885 100644
--- a/packages/backend/test-federation/.config/example.default.yml
+++ b/packages/backend/test-federation/.config/example.default.yml
@@ -17,8 +17,6 @@ proxyBypassHosts:
- www.recaptcha.net
- hcaptcha.com
- challenges.cloudflare.com
-proxyRemoteFiles: true
-signToActivityPubGet: true
allowedPrivateNetworks:
- 127.0.0.1/32
- 172.20.0.0/16
diff --git a/packages/frontend/src/pages/admin/settings.vue b/packages/frontend/src/pages/admin/settings.vue
index 82083b4e08..8e0c373a7b 100644
--- a/packages/frontend/src/pages/admin/settings.vue
+++ b/packages/frontend/src/pages/admin/settings.vue
@@ -87,28 +87,6 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkFolder>
<MkFolder>
- <template #icon><i class="ti ti-cloud"></i></template>
- <template #label>{{ i18n.ts.files }}</template>
- <template v-if="filesForm.modified.value" #footer>
- <MkFormFooter :form="filesForm"/>
- </template>
-
- <div class="_gaps">
- <MkSwitch v-model="filesForm.state.cacheRemoteFiles">
- <template #label>{{ i18n.ts.cacheRemoteFiles }}<span v-if="filesForm.modifiedStates.cacheRemoteFiles" class="_modified">{{ i18n.ts.modified }}</span></template>
- <template #caption>{{ i18n.ts.cacheRemoteFilesDescription }}{{ i18n.ts.youCanCleanRemoteFilesCache }}</template>
- </MkSwitch>
-
- <template v-if="filesForm.state.cacheRemoteFiles">
- <MkSwitch v-model="filesForm.state.cacheRemoteSensitiveFiles">
- <template #label>{{ i18n.ts.cacheRemoteSensitiveFiles }}<span v-if="filesForm.modifiedStates.cacheRemoteSensitiveFiles" class="_modified">{{ i18n.ts.modified }}</span></template>
- <template #caption>{{ i18n.ts.cacheRemoteSensitiveFilesDescription }}</template>
- </MkSwitch>
- </template>
- </div>
- </MkFolder>
-
- <MkFolder>
<template #icon><i class="ti ti-world-cog"></i></template>
<template #label>ServiceWorker</template>
<template v-if="serviceWorkerForm.modified.value" #footer>
@@ -255,6 +233,36 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
</MkFolder>
+
+ <MkSwitch v-model="federationForm.state.signToActivityPubGet">
+ <template #label>{{ i18n.ts._serverSettings.signToActivityPubGet }}<span v-if="federationForm.modifiedStates.signToActivityPubGet" class="_modified">{{ i18n.ts.modified }}</span></template>
+ <template #caption>{{ i18n.ts._serverSettings.signToActivityPubGet_description }}</template>
+ </MkSwitch>
+
+ <MkSwitch v-model="federationForm.state.proxyRemoteFiles">
+ <template #label>{{ i18n.ts._serverSettings.proxyRemoteFiles }}<span v-if="federationForm.modifiedStates.proxyRemoteFiles" class="_modified">{{ i18n.ts.modified }}</span></template>
+ <template #caption>{{ i18n.ts._serverSettings.proxyRemoteFiles_description }}</template>
+ </MkSwitch>
+
+ <MkSwitch v-model="federationForm.state.allowExternalApRedirect">
+ <template #label>{{ i18n.ts._serverSettings.allowExternalApRedirect }}<span v-if="federationForm.modifiedStates.allowExternalApRedirect" class="_modified">{{ i18n.ts.modified }}</span></template>
+ <template #caption>
+ <div>{{ i18n.ts._serverSettings.allowExternalApRedirect_description }}</div>
+ <div>{{ i18n.ts.needToRestartServerToApply }}</div>
+ </template>
+ </MkSwitch>
+
+ <MkSwitch v-model="federationForm.state.cacheRemoteFiles">
+ <template #label>{{ i18n.ts.cacheRemoteFiles }}<span v-if="federationForm.modifiedStates.cacheRemoteFiles" class="_modified">{{ i18n.ts.modified }}</span></template>
+ <template #caption>{{ i18n.ts.cacheRemoteFilesDescription }}{{ i18n.ts.youCanCleanRemoteFilesCache }}</template>
+ </MkSwitch>
+
+ <template v-if="federationForm.state.cacheRemoteFiles">
+ <MkSwitch v-model="federationForm.state.cacheRemoteSensitiveFiles">
+ <template #label>{{ i18n.ts.cacheRemoteSensitiveFiles }}<span v-if="federationForm.modifiedStates.cacheRemoteSensitiveFiles" class="_modified">{{ i18n.ts.modified }}</span></template>
+ <template #caption>{{ i18n.ts.cacheRemoteSensitiveFilesDescription }}</template>
+ </MkSwitch>
+ </template>
</div>
</MkFolder>
@@ -338,17 +346,6 @@ const pinnedUsersForm = useForm({
fetchInstance(true);
});
-const filesForm = useForm({
- cacheRemoteFiles: meta.cacheRemoteFiles,
- cacheRemoteSensitiveFiles: meta.cacheRemoteSensitiveFiles,
-}, async (state) => {
- await os.apiWithDialog('admin/update-meta', {
- cacheRemoteFiles: state.cacheRemoteFiles,
- cacheRemoteSensitiveFiles: state.cacheRemoteSensitiveFiles,
- });
- fetchInstance(true);
-});
-
const serviceWorkerForm = useForm({
enableServiceWorker: meta.enableServiceWorker,
swPublicKey: meta.swPublickey ?? '',
@@ -394,11 +391,21 @@ const federationForm = useForm({
federation: meta.federation,
federationHosts: meta.federationHosts.join('\n'),
deliverSuspendedSoftware: meta.deliverSuspendedSoftware,
+ signToActivityPubGet: meta.signToActivityPubGet,
+ proxyRemoteFiles: meta.proxyRemoteFiles,
+ allowExternalApRedirect: meta.allowExternalApRedirect,
+ cacheRemoteFiles: meta.cacheRemoteFiles,
+ cacheRemoteSensitiveFiles: meta.cacheRemoteSensitiveFiles,
}, async (state) => {
await os.apiWithDialog('admin/update-meta', {
federation: state.federation,
federationHosts: state.federationHosts.split('\n'),
deliverSuspendedSoftware: state.deliverSuspendedSoftware,
+ signToActivityPubGet: state.signToActivityPubGet,
+ proxyRemoteFiles: state.proxyRemoteFiles,
+ allowExternalApRedirect: state.allowExternalApRedirect,
+ cacheRemoteFiles: state.cacheRemoteFiles,
+ cacheRemoteSensitiveFiles: state.cacheRemoteSensitiveFiles,
});
fetchInstance(true);
});
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 1e38446882..1abc721997 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -8785,6 +8785,9 @@ export type operations = {
singleUserMode: boolean;
/** @enum {string} */
ugcVisibilityForVisitor: 'all' | 'local' | 'none';
+ proxyRemoteFiles: boolean;
+ signToActivityPubGet: boolean;
+ allowExternalApRedirect: boolean;
};
};
};
@@ -11458,6 +11461,9 @@ export type operations = {
singleUserMode?: boolean;
/** @enum {string} */
ugcVisibilityForVisitor?: 'all' | 'local' | 'none';
+ proxyRemoteFiles?: boolean;
+ signToActivityPubGet?: boolean;
+ allowExternalApRedirect?: boolean;
};
};
};