From fa731ac717eb4a9cec8939c787eb32f3aa1c22cd Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Mon, 31 Mar 2025 13:10:05 +0900 Subject: [PATCH 1/9] feat(backend): suspend instance by software --- .../1743403874305-DeliverSuspendedSoftware.js | 16 +++++ packages/backend/package.json | 1 + packages/backend/src/core/UtilityService.ts | 20 +++++- .../core/entities/InstanceEntityService.ts | 5 +- packages/backend/src/models/Meta.ts | 10 +++ .../models/json-schema/federation-instance.ts | 2 +- .../processors/DeliverProcessorService.ts | 13 ++-- .../src/server/api/endpoints/admin/meta.ts | 19 ++++++ .../server/api/endpoints/admin/update-meta.ts | 15 +++++ packages/misskey-js/src/autogen/types.ts | 10 ++- pnpm-lock.yaml | 67 ++++++++++--------- 11 files changed, 137 insertions(+), 41 deletions(-) create mode 100644 packages/backend/migration/1743403874305-DeliverSuspendedSoftware.js diff --git a/packages/backend/migration/1743403874305-DeliverSuspendedSoftware.js b/packages/backend/migration/1743403874305-DeliverSuspendedSoftware.js new file mode 100644 index 0000000000..19983a72bd --- /dev/null +++ b/packages/backend/migration/1743403874305-DeliverSuspendedSoftware.js @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class DeliverSuspendedSoftware1743403874305 { + name = 'DeliverSuspendedSoftware1743403874305' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "deliverSuspendedSoftware" jsonb NOT NULL DEFAULT '[]'`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "deliverSuspendedSoftware"`); + } +} diff --git a/packages/backend/package.json b/packages/backend/package.json index bcaa6357ce..4f81addf81 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -166,6 +166,7 @@ "rxjs": "7.8.2", "sanitize-html": "2.15.0", "secure-json-parse": "3.0.2", + "semver": "7.7.1", "sharp": "0.33.5", "slacc": "0.0.10", "strict-event-emitter-types": "2.0.0", diff --git a/packages/backend/src/core/UtilityService.ts b/packages/backend/src/core/UtilityService.ts index 23fb928ac9..67ec6cc7b0 100644 --- a/packages/backend/src/core/UtilityService.ts +++ b/packages/backend/src/core/UtilityService.ts @@ -6,10 +6,12 @@ import { URL, domainToASCII } from 'node:url'; import { Inject, Injectable } from '@nestjs/common'; import RE2 from 're2'; +import semver from 'semver'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import { bindThis } from '@/decorators.js'; -import { MiMeta } from '@/models/Meta.js'; +import { MiMeta, SoftwareSuspension } from '@/models/Meta.js'; +import { MiInstance } from '@/models/Instance.js'; @Injectable() export class UtilityService { @@ -143,4 +145,20 @@ export class UtilityService { const host = this.extractDbHost(uri); return this.isFederationAllowedHost(host); } + + @bindThis + public isDeliverSuspendedSoftware(software: Pick): SoftwareSuspension | undefined { + if (software.softwareName == null) return undefined; + if (software.softwareVersion == null) { + // software version is null; suspend iff versionRange is * + return this.meta.deliverSuspendedSoftware.find(x => + x.software === software.softwareName + && x.versionRange.trim() === '*'); + } else { + const softwareVersion = software.softwareVersion; + return this.meta.deliverSuspendedSoftware.find(x => + x.software === software.softwareName + && semver.satisfies(softwareVersion, x.versionRange, { includePrerelease: true })); + } + } } diff --git a/packages/backend/src/core/entities/InstanceEntityService.ts b/packages/backend/src/core/entities/InstanceEntityService.ts index 284537b986..3688cfb363 100644 --- a/packages/backend/src/core/entities/InstanceEntityService.ts +++ b/packages/backend/src/core/entities/InstanceEntityService.ts @@ -31,6 +31,7 @@ export class InstanceEntityService { me?: { id: MiUser['id']; } | null | undefined, ): Promise> { const iAmModerator = me ? await this.roleService.isModerator(me as MiUser) : false; + const softwareSuspended = this.utilityService.isDeliverSuspendedSoftware(instance); return { id: instance.id, @@ -41,8 +42,8 @@ export class InstanceEntityService { followingCount: instance.followingCount, followersCount: instance.followersCount, isNotResponding: instance.isNotResponding, - isSuspended: instance.suspensionState !== 'none', - suspensionState: instance.suspensionState, + isSuspended: instance.suspensionState !== 'none' || Boolean(softwareSuspended), + suspensionState: instance.suspensionState === 'none' && softwareSuspended ? 'softwareSuspended' : instance.suspensionState, isBlocked: this.utilityService.isBlockedHost(this.meta.blockedHosts, instance.host), softwareName: instance.softwareName, softwareVersion: instance.softwareVersion, diff --git a/packages/backend/src/models/Meta.ts b/packages/backend/src/models/Meta.ts index 1fbf5371bc..46f3b2e3c0 100644 --- a/packages/backend/src/models/Meta.ts +++ b/packages/backend/src/models/Meta.ts @@ -664,4 +664,14 @@ export class MiMeta { nullable: true, }) public googleAnalyticsMeasurementId: string | null; + + @Column('jsonb', { + default: [], + }) + public deliverSuspendedSoftware: SoftwareSuspension[]; } + +export type SoftwareSuspension = { + software: string, + versionRange: string, +}; diff --git a/packages/backend/src/models/json-schema/federation-instance.ts b/packages/backend/src/models/json-schema/federation-instance.ts index 912a0399d8..85f84952f1 100644 --- a/packages/backend/src/models/json-schema/federation-instance.ts +++ b/packages/backend/src/models/json-schema/federation-instance.ts @@ -48,7 +48,7 @@ export const packedFederationInstanceSchema = { suspensionState: { type: 'string', nullable: false, optional: false, - enum: ['none', 'manuallySuspended', 'goneSuspended', 'autoSuspendedForNotResponding'], + enum: ['none', 'manuallySuspended', 'goneSuspended', 'autoSuspendedForNotResponding', 'softwareSuspended'], }, isBlocked: { type: 'boolean', diff --git a/packages/backend/src/queue/processors/DeliverProcessorService.ts b/packages/backend/src/queue/processors/DeliverProcessorService.ts index 5a16496011..391ccdac05 100644 --- a/packages/backend/src/queue/processors/DeliverProcessorService.ts +++ b/packages/backend/src/queue/processors/DeliverProcessorService.ts @@ -71,6 +71,15 @@ export class DeliverProcessorService { return 'skip (suspended)'; } + const i = await (this.meta.enableStatsForFederatedInstances + ? this.federatedInstanceService.fetchOrRegister(host) + : this.federatedInstanceService.fetch(host)); + + // suspend server by software + if (i != null && this.utilityService.isDeliverSuspendedSoftware(i)) { + return 'skip (software suspended)'; + } + try { await this.apRequestService.signedPost(job.data.user, job.data.to, job.data.content, job.data.digest); @@ -79,10 +88,6 @@ export class DeliverProcessorService { // Update instance stats process.nextTick(async () => { - const i = await (this.meta.enableStatsForFederatedInstances - ? this.federatedInstanceService.fetchOrRegister(host) - : this.federatedInstanceService.fetch(host)); - if (i == null) return; if (i.isNotResponding) { diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 53e2b2b237..4a106e7175 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -528,6 +528,24 @@ export const meta = { optional: false, nullable: false, }, }, + deliverSuspendedSoftware: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'object', + optional: false, nullable: false, + properties: { + software: { + type: 'string', + optional: false, nullable: false, + }, + versionRange: { + type: 'string', + optional: false, nullable: false, + }, + }, + }, + }, }, }, } as const; @@ -672,6 +690,7 @@ export default class extends Endpoint { // eslint- urlPreviewSummaryProxyUrl: instance.urlPreviewSummaryProxyUrl, federation: instance.federation, federationHosts: instance.federationHosts, + deliverSuspendedSoftware: instance.deliverSuspendedSoftware, }; }); } 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 bc05587668..31eeaa5e38 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -185,6 +185,17 @@ export const paramDef = { type: 'string', }, }, + deliverSuspendedSoftware: { + type: 'array', + items: { + type: 'object', + properties: { + software: { type: 'string' }, + versionRange: { type: 'string' }, + }, + required: ['software', 'versionRange'], + }, + }, }, required: [], } as const; @@ -671,6 +682,10 @@ export default class extends Endpoint { // eslint- set.federation = ps.federation; } + if (ps.deliverSuspendedSoftware !== undefined) { + set.deliverSuspendedSoftware = ps.deliverSuspendedSoftware; + } + if (Array.isArray(ps.federationHosts)) { set.federationHosts = ps.federationHosts.filter(Boolean).map(x => x.toLowerCase()); } diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 57c4824424..bd6ccb31ee 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -4933,7 +4933,7 @@ export type components = { isNotResponding: boolean; isSuspended: boolean; /** @enum {string} */ - suspensionState: 'none' | 'manuallySuspended' | 'goneSuspended' | 'autoSuspendedForNotResponding'; + suspensionState: 'none' | 'manuallySuspended' | 'goneSuspended' | 'autoSuspendedForNotResponding' | 'softwareSuspended'; isBlocked: boolean; /** @example misskey */ softwareName: string | null; @@ -8662,6 +8662,10 @@ export type operations = { /** @enum {string} */ federation: 'all' | 'specified' | 'none'; federationHosts: string[]; + deliverSuspendedSoftware: { + software: string; + versionRange: string; + }[]; }; }; }; @@ -11007,6 +11011,10 @@ export type operations = { /** @enum {string} */ federation?: 'all' | 'none' | 'specified'; federationHosts?: string[]; + deliverSuspendedSoftware?: { + software: string; + versionRange: string; + }[]; }; }; }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3034b9bb84..3a97601987 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -389,6 +389,9 @@ importers: secure-json-parse: specifier: 3.0.2 version: 3.0.2 + semver: + specifier: 7.7.1 + version: 7.7.1 sharp: specifier: 0.33.5 version: 0.33.5 @@ -9491,8 +9494,8 @@ packages: engines: {node: '>=10'} hasBin: true - semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} engines: {node: '>=10'} hasBin: true @@ -12570,7 +12573,7 @@ snapshots: nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 - semver: 7.6.3 + semver: 7.7.1 tar: 6.2.1 transitivePeerDependencies: - encoding @@ -12790,7 +12793,7 @@ snapshots: '@npmcli/fs@3.1.0': dependencies: - semver: 7.6.3 + semver: 7.7.1 '@nuxt/opencollective@0.4.1': dependencies: @@ -12912,7 +12915,7 @@ snapshots: '@opentelemetry/instrumentation': 0.57.1(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.28.0 forwarded-parse: 2.1.2 - semver: 7.6.3 + semver: 7.7.1 transitivePeerDependencies: - supports-color @@ -13045,7 +13048,7 @@ snapshots: '@types/shimmer': 1.2.0 import-in-the-middle: 1.11.2 require-in-the-middle: 7.3.0 - semver: 7.6.3 + semver: 7.7.1 shimmer: 1.2.1 transitivePeerDependencies: - supports-color @@ -13057,7 +13060,7 @@ snapshots: '@types/shimmer': 1.2.0 import-in-the-middle: 1.11.2 require-in-the-middle: 7.3.0 - semver: 7.6.3 + semver: 7.7.1 shimmer: 1.2.1 transitivePeerDependencies: - supports-color @@ -13069,7 +13072,7 @@ snapshots: '@types/shimmer': 1.2.0 import-in-the-middle: 1.11.2 require-in-the-middle: 7.3.0 - semver: 7.6.3 + semver: 7.7.1 shimmer: 1.2.1 transitivePeerDependencies: - supports-color @@ -14033,7 +14036,7 @@ snapshots: jsdoc-type-pratt-parser: 4.1.0 process: 0.11.10 recast: 0.23.6 - semver: 7.6.3 + semver: 7.7.1 util: 0.12.5 ws: 8.18.1(bufferutil@4.0.9)(utf-8-validate@6.0.5) optionalDependencies: @@ -14188,7 +14191,7 @@ snapshots: fast-glob: 3.3.3 minimatch: 9.0.4 piscina: 4.4.0 - semver: 7.6.3 + semver: 7.7.1 slash: 3.0.0 source-map: 0.7.4 optionalDependencies: @@ -14857,7 +14860,7 @@ snapshots: fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.4 - semver: 7.6.3 + semver: 7.7.1 ts-api-utils: 2.0.1(typescript@5.8.2) typescript: 5.8.2 transitivePeerDependencies: @@ -14871,7 +14874,7 @@ snapshots: fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.4 - semver: 7.6.3 + semver: 7.7.1 ts-api-utils: 2.0.1(typescript@5.8.2) typescript: 5.8.2 transitivePeerDependencies: @@ -15636,7 +15639,7 @@ snapshots: bin-version-check@5.1.0: dependencies: bin-version: 6.0.0 - semver: 7.6.3 + semver: 7.7.1 semver-truncate: 3.0.0 bin-version@6.0.0: @@ -15747,7 +15750,7 @@ snapshots: ioredis: 5.6.0 msgpackr: 1.11.2 node-abort-controller: 3.1.1 - semver: 7.6.3 + semver: 7.7.1 tslib: 2.8.1 uuid: 9.0.1 transitivePeerDependencies: @@ -16343,7 +16346,7 @@ snapshots: process: 0.11.10 proxy-from-env: 1.0.0 request-progress: 3.0.0 - semver: 7.6.3 + semver: 7.7.1 supports-color: 8.1.1 tmp: 0.2.3 tree-kill: 1.2.2 @@ -16389,7 +16392,7 @@ snapshots: process: 0.11.10 proxy-from-env: 1.0.0 request-progress: 3.0.0 - semver: 7.6.3 + semver: 7.7.1 supports-color: 8.1.1 tmp: 0.2.3 tree-kill: 1.2.2 @@ -16676,7 +16679,7 @@ snapshots: '@one-ini/wasm': 0.1.1 commander: 10.0.1 minimatch: 9.0.1 - semver: 7.6.3 + semver: 7.7.1 ee-first@1.1.1: {} @@ -17063,7 +17066,7 @@ snapshots: natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 6.1.2 - semver: 7.6.3 + semver: 7.7.1 vue-eslint-parser: 10.1.1(eslint@9.22.0) xml-name-validator: 4.0.0 @@ -17425,7 +17428,7 @@ snapshots: process-warning: 4.0.0 rfdc: 1.4.1 secure-json-parse: 3.0.2 - semver: 7.6.3 + semver: 7.7.1 toad-cache: 3.7.0 fastq@1.17.1: @@ -18325,7 +18328,7 @@ snapshots: '@babel/parser': 7.25.6 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 - semver: 7.6.3 + semver: 7.7.1 transitivePeerDependencies: - supports-color @@ -18712,7 +18715,7 @@ snapshots: jest-util: 29.7.0 natural-compare: 1.4.0 pretty-format: 29.7.0 - semver: 7.6.3 + semver: 7.7.1 transitivePeerDependencies: - supports-color @@ -19094,7 +19097,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.6.3 + semver: 7.7.1 make-fetch-happen@13.0.0: dependencies: @@ -19720,7 +19723,7 @@ snapshots: node-abi@3.62.0: dependencies: - semver: 7.6.3 + semver: 7.7.1 node-abort-controller@3.1.1: {} @@ -19765,7 +19768,7 @@ snapshots: make-fetch-happen: 13.0.0 nopt: 7.2.0 proc-log: 4.2.0 - semver: 7.6.3 + semver: 7.7.1 tar: 6.2.1 which: 4.0.0 transitivePeerDependencies: @@ -19784,7 +19787,7 @@ snapshots: ignore-by-default: 1.0.1 minimatch: 3.1.2 pstree.remy: 1.1.8 - semver: 7.6.3 + semver: 7.7.1 simple-update-notifier: 2.0.0 supports-color: 5.5.0 touch: 3.1.0 @@ -19820,7 +19823,7 @@ snapshots: dependencies: hosted-git-info: 4.1.0 is-core-module: 2.15.1 - semver: 7.6.3 + semver: 7.7.1 validate-npm-package-license: 3.0.4 normalize-path@3.0.0: {} @@ -21027,7 +21030,7 @@ snapshots: semver-truncate@3.0.0: dependencies: - semver: 7.6.3 + semver: 7.7.1 semver@5.7.1: {} @@ -21037,7 +21040,7 @@ snapshots: dependencies: lru-cache: 6.0.0 - semver@7.6.3: {} + semver@7.7.1: {} send@0.19.0: dependencies: @@ -21099,7 +21102,7 @@ snapshots: dependencies: color: 4.2.3 detect-libc: 2.0.3 - semver: 7.6.3 + semver: 7.7.1 optionalDependencies: '@img/sharp-darwin-arm64': 0.33.5 '@img/sharp-darwin-x64': 0.33.5 @@ -21178,7 +21181,7 @@ snapshots: simple-update-notifier@2.0.0: dependencies: - semver: 7.6.3 + semver: 7.7.1 sinon@18.0.1: dependencies: @@ -22205,7 +22208,7 @@ snapshots: vscode-languageclient@9.0.1: dependencies: minimatch: 5.1.2 - semver: 7.6.3 + semver: 7.7.1 vscode-languageserver-protocol: 3.17.5 vscode-languageserver-protocol@3.17.5: @@ -22260,7 +22263,7 @@ snapshots: espree: 10.3.0 esquery: 1.6.0 lodash: 4.17.21 - semver: 7.6.3 + semver: 7.7.1 transitivePeerDependencies: - supports-color From 573bb8327ec304dc8348a8dfa5540381fa3c36ae Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Mon, 31 Mar 2025 17:04:13 +0900 Subject: [PATCH 2/9] feat(frontend): suspend instance by software --- locales/index.d.ts | 16 ++++ locales/ja-JP.yml | 4 + .../frontend/src/pages/admin/settings.vue | 76 +++++++++++++++++++ packages/frontend/src/pages/instance-info.vue | 4 +- packages/frontend/src/use/use-form.ts | 3 +- 5 files changed, 100 insertions(+), 3 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index 3645639305..b9558b2cff 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -898,6 +898,10 @@ export interface Locale extends ILocale { * ソフトウェア */ "software": string; + /** + * ソフトウェア名 + */ + "softwareName": string; /** * バージョン */ @@ -5828,6 +5832,10 @@ export interface Locale extends ILocale { * サーバー応答なしのため停止中 */ "autoSuspendedForNotResponding": string; + /** + * 配信停止中のソフトウェアであるため停止中 + */ + "softwareSuspended": string; }; }; "_bubbleGame": { @@ -6313,6 +6321,14 @@ export interface Locale extends ILocale { * 一定期間モデレーターのアクティビティが検出されなかった場合、スパム防止のためこの設定は自動でオフになります。 */ "thisSettingWillAutomaticallyOffWhenModeratorsInactive": string; + /** + * 配信停止中のソフトウェア + */ + "deliverSuspendedSoftware": string; + /** + * 脆弱性などの理由で、サーバーのソフトウェアの名前及びバージョンの範囲を指定して配信を停止できます。このバージョン情報はサーバーが提供したものであり、信頼性は保証されません。バージョン指定には semver の範囲指定が使用できますが、>= 2024.3.1 と指定すると 2024.3.1-io.0 のようなカスタムバージョンが含まれないため、>= 2024.3.1-0 のように prerelease の指定を行うことを推奨します。 + */ + "deliverSuspendedSoftwareDescription": string; }; "_accountMigration": { /** diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 0e20001d6b..6ab287831d 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -220,6 +220,7 @@ silenceThisInstance: "サーバーをサイレンス" mediaSilenceThisInstance: "サーバーをメディアサイレンス" operations: "操作" software: "ソフトウェア" +softwareName: "ソフトウェア名" version: "バージョン" metadata: "メタデータ" withNFiles: "{n}つのファイル" @@ -1467,6 +1468,7 @@ _delivery: manuallySuspended: "手動停止中" goneSuspended: "サーバー削除のため停止中" autoSuspendedForNotResponding: "サーバー応答なしのため停止中" + softwareSuspended: "配信停止中のソフトウェアであるため停止中" _bubbleGame: howToPlay: "遊び方" @@ -1605,6 +1607,8 @@ _serverSettings: openRegistration: "アカウントの作成をオープンにする" openRegistrationWarning: "登録を開放することはリスクが伴います。サーバーを常に監視し、トラブルが発生した際にすぐに対応できる体制がある場合のみオンにすることを推奨します。" thisSettingWillAutomaticallyOffWhenModeratorsInactive: "一定期間モデレーターのアクティビティが検出されなかった場合、スパム防止のためこの設定は自動でオフになります。" + deliverSuspendedSoftware: "配信停止中のソフトウェア" + deliverSuspendedSoftwareDescription: "脆弱性などの理由で、サーバーのソフトウェアの名前及びバージョンの範囲を指定して配信を停止できます。このバージョン情報はサーバーが提供したものであり、信頼性は保証されません。バージョン指定には semver の範囲指定が使用できますが、>= 2024.3.1 と指定すると 2024.3.1-io.0 のようなカスタムバージョンが含まれないため、>= 2024.3.1-0 のように prerelease の指定を行うことを推奨します。" _accountMigration: moveFrom: "別のアカウントからこのアカウントに移行" diff --git a/packages/frontend/src/pages/admin/settings.vue b/packages/frontend/src/pages/admin/settings.vue index c019bda32c..fd8e76b2bd 100644 --- a/packages/frontend/src/pages/admin/settings.vue +++ b/packages/frontend/src/pages/admin/settings.vue @@ -232,6 +232,31 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + + + +
+ {{ i18n.ts._serverSettings.deliverSuspendedSoftwareDescription }} +
+ +
+ + + + + + +
+
+
+
@@ -372,10 +397,12 @@ const urlPreviewForm = useForm({ const federationForm = useForm({ federation: meta.federation, federationHosts: meta.federationHosts.join('\n'), + deliverSuspendedSoftware: meta.deliverSuspendedSoftware, }, async (state) => { await os.apiWithDialog('admin/update-meta', { federation: state.federation, federationHosts: state.federationHosts.split('\n'), + deliverSuspendedSoftware: state.deliverSuspendedSoftware, }); fetchInstance(true); }); @@ -402,4 +429,53 @@ definePage(() => ({ font-size: 0.85em; color: var(--MI_THEME-fgTransparentWeak); } + +.metadataRoot { + container-type: inline-size; +} + +.fieldDragItem { + display: flex; + padding: 10px; + align-items: flex-end; + border-radius: 6px; + + /* (drag button) 32px + (drag button margin) 8px + (input width) 200px * 2 + (input gap) 12px = 452px */ + @container (max-width: 452px) { + align-items: center; + } +} + +.dragItemHandle { + cursor: grab; + width: 32px; + height: 32px; + margin: 0 8px 0 0; + opacity: 0.5; + flex-shrink: 0; + + &:active { + cursor: grabbing; + } +} + +.dragItemRemove { + @extend .dragItemHandle; + + color: #ff2a2a; + opacity: 1; + cursor: pointer; + + &:hover, &:focus { + opacity: .7; + } + + &:active { + cursor: pointer; + } +} + +.dragItemForm { + flex-grow: 1; +} diff --git a/packages/frontend/src/pages/instance-info.vue b/packages/frontend/src/pages/instance-info.vue index 66ddf627e4..89d9a93fe7 100644 --- a/packages/frontend/src/pages/instance-info.vue +++ b/packages/frontend/src/pages/instance-info.vue @@ -43,7 +43,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts._delivery.stop }} - {{ i18n.ts._delivery.resume }} + {{ i18n.ts._delivery.resume }} {{ i18n.ts.blockThisInstance }} {{ i18n.ts.silenceThisInstance }} {{ i18n.ts.mediaSilenceThisInstance }} @@ -167,7 +167,7 @@ const tab = ref('overview'); const chartSrc = ref('instance-requests'); const meta = ref(null); const instance = ref(null); -const suspensionState = ref<'none' | 'manuallySuspended' | 'goneSuspended' | 'autoSuspendedForNotResponding'>('none'); +const suspensionState = ref<'none' | 'manuallySuspended' | 'goneSuspended' | 'autoSuspendedForNotResponding' | 'softwareSuspended'>('none'); const isBlocked = ref(false); const isSilenced = ref(false); const isMediaSilenced = ref(false); diff --git a/packages/frontend/src/use/use-form.ts b/packages/frontend/src/use/use-form.ts index 26cca839c3..1c93557413 100644 --- a/packages/frontend/src/use/use-form.ts +++ b/packages/frontend/src/use/use-form.ts @@ -5,6 +5,7 @@ import { computed, reactive, watch } from 'vue'; import type { Reactive } from 'vue'; +import { deepEqual } from '@/utility/deep-equal'; function copy(v: T): T { return JSON.parse(JSON.stringify(v)); @@ -27,7 +28,7 @@ export function useForm>(initialState: T, save: (n watch([currentState, previousState], () => { for (const key in modifiedStates) { - modifiedStates[key] = currentState[key] !== previousState[key]; + modifiedStates[key] = !deepEqual(currentState[key], previousState[key]); } }, { deep: true }); From 31a7f7df7dae753d33d93ebaa0a1c499854bd94e Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Mon, 31 Mar 2025 17:05:23 +0900 Subject: [PATCH 3/9] =?UTF-8?q?docs(chaangelog):=20=E9=80=A3=E5=90=88?= =?UTF-8?q?=E5=85=88=E3=81=AE=E3=82=BD=E3=83=95=E3=83=88=E3=82=A6=E3=82=A7?= =?UTF-8?q?=E3=82=A2=E5=8F=8A=E3=81=B3=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E5=90=8D=E3=81=AB=E3=82=88=E3=82=8A=E9=85=8D=E4=BF=A1?= =?UTF-8?q?=E5=81=9C=E6=AD=A2=E3=82=92=E8=A1=8C=E3=81=88=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=E3=81=AA=E3=82=8A=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ecec21953..0a564e0d34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - Enhance: セキュリティを強化するため、ジョブキューのダッシュボード(bull-board)統合が削除されました。 - Misskeyネイティブでダッシュボードを実装予定です - Enhance: ミュートしているユーザーをユーザー検索の結果から除外するように +- Enhance: 連合先のソフトウェア及びバージョン名により配信停止を行えるようになりました ### Client - Feat: 設定の管理が強化されました From 2cd4321f053c570438afb0f44ef49ac0cd5809d0 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Mon, 31 Mar 2025 22:12:39 +0900 Subject: [PATCH 4/9] =?UTF-8?q?chore:=20=E4=BE=8B=E3=81=A7=E4=BD=BF?= =?UTF-8?q?=E3=81=86=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7=E3=83=B3=E5=90=8D?= =?UTF-8?q?=E3=82=92=E5=A4=89=E3=81=88=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/index.d.ts | 2 +- locales/ja-JP.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index b9558b2cff..11632a966f 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -6326,7 +6326,7 @@ export interface Locale extends ILocale { */ "deliverSuspendedSoftware": string; /** - * 脆弱性などの理由で、サーバーのソフトウェアの名前及びバージョンの範囲を指定して配信を停止できます。このバージョン情報はサーバーが提供したものであり、信頼性は保証されません。バージョン指定には semver の範囲指定が使用できますが、>= 2024.3.1 と指定すると 2024.3.1-io.0 のようなカスタムバージョンが含まれないため、>= 2024.3.1-0 のように prerelease の指定を行うことを推奨します。 + * 脆弱性などの理由で、サーバーのソフトウェアの名前及びバージョンの範囲を指定して配信を停止できます。このバージョン情報はサーバーが提供したものであり、信頼性は保証されません。バージョン指定には semver の範囲指定が使用できますが、>= 2024.3.1 と指定すると 2024.3.1-custom.0 のようなカスタムバージョンが含まれないため、>= 2024.3.1-0 のように prerelease の指定を行うことを推奨します。 */ "deliverSuspendedSoftwareDescription": string; }; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 6ab287831d..822c38adea 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1608,7 +1608,7 @@ _serverSettings: openRegistrationWarning: "登録を開放することはリスクが伴います。サーバーを常に監視し、トラブルが発生した際にすぐに対応できる体制がある場合のみオンにすることを推奨します。" thisSettingWillAutomaticallyOffWhenModeratorsInactive: "一定期間モデレーターのアクティビティが検出されなかった場合、スパム防止のためこの設定は自動でオフになります。" deliverSuspendedSoftware: "配信停止中のソフトウェア" - deliverSuspendedSoftwareDescription: "脆弱性などの理由で、サーバーのソフトウェアの名前及びバージョンの範囲を指定して配信を停止できます。このバージョン情報はサーバーが提供したものであり、信頼性は保証されません。バージョン指定には semver の範囲指定が使用できますが、>= 2024.3.1 と指定すると 2024.3.1-io.0 のようなカスタムバージョンが含まれないため、>= 2024.3.1-0 のように prerelease の指定を行うことを推奨します。" + deliverSuspendedSoftwareDescription: "脆弱性などの理由で、サーバーのソフトウェアの名前及びバージョンの範囲を指定して配信を停止できます。このバージョン情報はサーバーが提供したものであり、信頼性は保証されません。バージョン指定には semver の範囲指定が使用できますが、>= 2024.3.1 と指定すると 2024.3.1-custom.0 のようなカスタムバージョンが含まれないため、>= 2024.3.1-0 のように prerelease の指定を行うことを推奨します。" _accountMigration: moveFrom: "別のアカウントからこのアカウントに移行" From add9d88e06ea4b6766bf2a55051e5fae29bfdf38 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Wed, 2 Apr 2025 10:28:40 +0900 Subject: [PATCH 5/9] fix: broken lockfile --- pnpm-lock.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 821c168e05..c7863c9a57 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14444,7 +14444,7 @@ snapshots: '@stylistic/eslint-plugin@2.13.0(eslint@9.22.0)(typescript@5.8.2)': dependencies: - '@typescript-eslint/utils': 8.27.0(eslint@9.22.0)(typescript@5.8.2) + '@typescript-eslint/utils': 8.29.0(eslint@9.22.0)(typescript@5.8.2) eslint: 9.22.0 eslint-visitor-keys: 4.2.0 espree: 10.3.0 @@ -15207,7 +15207,7 @@ snapshots: fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.4 - semver: 7.6.3 + semver: 7.7.1 ts-api-utils: 2.0.1(typescript@5.8.2) typescript: 5.8.2 transitivePeerDependencies: From e21b0a0747dc1c6e1ebb50ece50bac1d3266410d Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Mon, 7 Apr 2025 20:34:21 +0900 Subject: [PATCH 6/9] fix: broken lock file --- packages/frontend/tsconfig.json | 1 + pnpm-lock.yaml | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/frontend/tsconfig.json b/packages/frontend/tsconfig.json index ee200d6890..9c7c611e5b 100644 --- a/packages/frontend/tsconfig.json +++ b/packages/frontend/tsconfig.json @@ -46,6 +46,7 @@ }, "compileOnSave": false, "include": [ + "./lib/**/*.ts", "./src/**/*.ts", "./src/**/*.vue", "./test/**/*.ts", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cbf5cc74e5..ab10ddfabf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9748,11 +9748,6 @@ packages: engines: {node: '>=10'} hasBin: true - semver@7.7.1: - resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} - engines: {node: '>=10'} - hasBin: true - send@0.19.0: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} @@ -21481,9 +21476,6 @@ snapshots: semver@7.7.1: {} - semver@7.7.1: - optional: true - send@0.19.0: dependencies: debug: 2.6.9 From 2bf0d4f8c32f4f170790ae89d618c740a216f176 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Mon, 14 Apr 2025 01:53:37 +0900 Subject: [PATCH 7/9] fix broken lock file --- pnpm-lock.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4aaa29e9c5..5cd3487686 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -395,9 +395,6 @@ importers: semver: specifier: 7.7.1 version: 7.7.1 - sharp: - specifier: 0.34.1 - version: 0.34.1 slacc: specifier: 0.0.10 version: 0.0.10 From b1e66d88595e6fd510dd1b0e9f25be044dd464b2 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Mon, 14 Apr 2025 01:55:47 +0900 Subject: [PATCH 8/9] update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfd045d07c..a0ed05d3a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ### Server - Enhance: フォローしているユーザーならフォロワー限定投稿のノートでもアンテナで検知できるように (Cherry-picked from https://github.com/yojo-art/cherrypick/pull/568 and https://github.com/team-shahu/misskey/pull/38) +- Enhance: 連合先のソフトウェア及びバージョン名により配信停止を行えるように `#15727` - Fix: システムアカウントの名前がサーバー名と同期されない問題を修正 - Fix: 大文字を含むユーザの URL で紹介された場合に 404 エラーを返す問題 #15813 - Fix: リードレプリカ設定時にレコードの追加・更新・削除を伴うクエリを発行した際はmasterノードで実行されるように調整( #10897 ) @@ -37,7 +38,6 @@ - 外部サービスであるSentryへエラー情報が送信されます。ご利用の地域の法令に従い、適切なプライバシーポリシーを策定の上で運用してください。 - Enhance: ミュートしているユーザーをユーザー検索の結果から除外するように - Enhance: アンテナでセンシティブなチャンネルのノートを除外できるように `#14177` -- Enhance: 連合先のソフトウェア及びバージョン名により配信停止を行えるように `#15727` - Fix: 通知のページネーションで2つ以上読み込めなくなることがある問題を修正 ### Client From dc3db4cd36288f025ec73d51bedf9c1b2ad8cbd2 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Mon, 14 Apr 2025 03:47:42 +0900 Subject: [PATCH 9/9] fix dependencies --- packages/backend/package.json | 1 + pnpm-lock.yaml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/packages/backend/package.json b/packages/backend/package.json index 98179fc4b9..f21c1457e6 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -166,6 +166,7 @@ "rxjs": "7.8.2", "sanitize-html": "2.15.0", "secure-json-parse": "3.0.2", + "sharp": "0.34.1", "semver": "7.7.1", "slacc": "0.0.10", "strict-event-emitter-types": "2.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5cd3487686..4aaa29e9c5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -395,6 +395,9 @@ importers: semver: specifier: 7.7.1 version: 7.7.1 + sharp: + specifier: 0.34.1 + version: 0.34.1 slacc: specifier: 0.0.10 version: 0.0.10