diff options
| author | PrivateGER <privateger@privateger.me> | 2024-10-06 23:13:10 +0200 |
|---|---|---|
| committer | PrivateGER <privateger@privateger.me> | 2024-10-06 23:13:10 +0200 |
| commit | fadae347ffd52a3610ef2e6ce160ade32d3dac31 (patch) | |
| tree | 2731c25215245ba6c9cf4b8738f6868cf33afb78 /packages/backend/src | |
| parent | Move text into translation files (diff) | |
| parent | merge: Add option to reject reports from an instance (Resolves #579, #715, #7... (diff) | |
| download | sharkey-fadae347ffd52a3610ef2e6ce160ade32d3dac31.tar.gz sharkey-fadae347ffd52a3610ef2e6ce160ade32d3dac31.tar.bz2 sharkey-fadae347ffd52a3610ef2e6ce160ade32d3dac31.zip | |
Merge branch 'develop' of https://activitypub.software/TransFem-org/Sharkey into feat/instance-admin-ui
Diffstat (limited to 'packages/backend/src')
13 files changed, 95 insertions, 6 deletions
diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts index 6a28cbad15..bce67a458f 100644 --- a/packages/backend/src/core/activitypub/ApInboxService.ts +++ b/packages/backend/src/core/activitypub/ApInboxService.ts @@ -5,6 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { In } from 'typeorm'; +import * as Bull from 'bullmq'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import { UserFollowingService } from '@/core/UserFollowingService.js'; @@ -29,6 +30,7 @@ import { bindThis } from '@/decorators.js'; import type { MiRemoteUser } from '@/models/User.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { AbuseReportService } from '@/core/AbuseReportService.js'; +import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import { getApHrefNullable, getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js'; import { ApNoteService } from './models/ApNoteService.js'; import { ApLoggerService } from './ApLoggerService.js'; @@ -83,6 +85,7 @@ export class ApInboxService { private apQuestionService: ApQuestionService, private queueService: QueueService, private globalEventService: GlobalEventService, + private federatedInstanceService: FederatedInstanceService, ) { this.logger = this.apLoggerService.logger; } @@ -530,6 +533,12 @@ export class ApInboxService { @bindThis private async flag(actor: MiRemoteUser, activity: IFlag): Promise<string> { + // Make sure the source instance is allowed to send reports. + const instance = await this.federatedInstanceService.fetch(actor.host); + if (instance.rejectReports) { + throw new Bull.UnrecoverableError(`Rejecting report from instance: ${actor.host}`); + } + // objectは `(User|Note) | (User|Note)[]` だけど、全パターンDBスキーマと対応させられないので // 対象ユーザーは一番最初のユーザー として あとはコメントとして格納する const uris = getApIds(activity.object); diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts index 55d1054de9..499a163d6c 100644 --- a/packages/backend/src/core/activitypub/ApRendererService.ts +++ b/packages/backend/src/core/activitypub/ApRendererService.ts @@ -526,6 +526,7 @@ export class ApRendererService { publicKey: this.renderKey(user, keypair, '#main-key'), isCat: user.isCat, noindex: user.noindex, + indexable: !user.noindex, speakAsCat: user.speakAsCat, attachment: attachment.length ? attachment : undefined, }; diff --git a/packages/backend/src/core/activitypub/misc/contexts.ts b/packages/backend/src/core/activitypub/misc/contexts.ts index 815b20b910..86a665732a 100644 --- a/packages/backend/src/core/activitypub/misc/contexts.ts +++ b/packages/backend/src/core/activitypub/misc/contexts.ts @@ -545,6 +545,7 @@ const extension_context_definition = { Emoji: 'toot:Emoji', featured: 'toot:featured', discoverable: 'toot:discoverable', + indexable: 'toot:indexable', // schema schema: 'http://schema.org#', PropertyValue: 'schema:PropertyValue', diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts index 7b7a7921fb..382cda301f 100644 --- a/packages/backend/src/core/activitypub/models/ApNoteService.ts +++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts @@ -587,7 +587,7 @@ export class ApNoteService { // ここでuriの代わりに添付されてきたNote Objectが指定されていると、サーバーフェッチを経ずにノートが生成されるが // 添付されてきたNote Objectは偽装されている可能性があるため、常にuriを指定してサーバーフェッチを行う。 const createFrom = options.sentFrom?.origin === new URL(uri).origin ? value : uri; - return await this.createNote(createFrom, options.resolver, true); + return await this.createNote(createFrom, options.resolver, false); } finally { unlock(); } diff --git a/packages/backend/src/core/entities/MetaEntityService.ts b/packages/backend/src/core/entities/MetaEntityService.ts index afeefc9033..fa4ddc0bd6 100644 --- a/packages/backend/src/core/entities/MetaEntityService.ts +++ b/packages/backend/src/core/entities/MetaEntityService.ts @@ -120,6 +120,7 @@ export class MetaEntityService { imageUrl: ad.imageUrl, dayOfWeek: ad.dayOfWeek, })), + trustedLinkUrlPatterns: instance.trustedLinkUrlPatterns, notesPerOneAd: instance.notesPerOneAd, enableEmail: instance.enableEmail, enableServiceWorker: instance.enableServiceWorker, diff --git a/packages/backend/src/models/Instance.ts b/packages/backend/src/models/Instance.ts index dd625f95d3..ba93190c57 100644 --- a/packages/backend/src/models/Instance.ts +++ b/packages/backend/src/models/Instance.ts @@ -158,7 +158,12 @@ export class MiInstance { default: false, }) public isNSFW: boolean; - + + @Column('boolean', { + default: false, + }) + public rejectReports: boolean; + @Column('varchar', { length: 16384, default: '', }) diff --git a/packages/backend/src/models/Meta.ts b/packages/backend/src/models/Meta.ts index 29e1dd032a..0e244931d9 100644 --- a/packages/backend/src/models/Meta.ts +++ b/packages/backend/src/models/Meta.ts @@ -674,4 +674,12 @@ export class MiMeta { nullable: true, }) public urlPreviewUserAgent: string | null; + + @Column('varchar', { + length: 3072, + array: true, + default: '{}', + comment: 'An array of URL strings or regex that can be used to omit warnings about redirects to external sites. Separate them with spaces to specify AND, and enclose them with slashes to specify regular expressions. Each item is regarded as an OR.', + }) + public trustedLinkUrlPatterns: string[]; } diff --git a/packages/backend/src/models/json-schema/meta.ts b/packages/backend/src/models/json-schema/meta.ts index 74b6cfe883..8915436b9e 100644 --- a/packages/backend/src/models/json-schema/meta.ts +++ b/packages/backend/src/models/json-schema/meta.ts @@ -273,6 +273,14 @@ export const packedMetaLiteSchema = { optional: false, nullable: false, default: 'local', }, + trustedLinkUrlPatterns: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'string', + optional: false, nullable: false, + }, + }, }, } as const; diff --git a/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts b/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts index 8b142910a6..daf19c4435 100644 --- a/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts +++ b/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts @@ -25,6 +25,7 @@ export const paramDef = { host: { type: 'string' }, isSuspended: { type: 'boolean' }, isNSFW: { type: 'boolean' }, + rejectReports: { type: 'boolean' }, moderationNote: { type: 'string' }, }, required: ['host'], @@ -57,6 +58,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- await this.federatedInstanceService.update(instance.id, { suspensionState, isNSFW: ps.isNSFW, + rejectReports: ps.rejectReports, moderationNote: ps.moderationNote, }); @@ -74,6 +76,22 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- } } + if (ps.isNSFW != null && instance.isNSFW !== ps.isNSFW) { + const message = ps.rejectReports ? 'setRemoteInstanceNSFW' : 'unsetRemoteInstanceNSFW'; + this.moderationLogService.log(me, message, { + id: instance.id, + host: instance.host, + }); + } + + if (ps.rejectReports != null && instance.rejectReports !== ps.rejectReports) { + const message = ps.rejectReports ? 'rejectRemoteInstanceReports' : 'acceptRemoteInstanceReports'; + this.moderationLogService.log(me, message, { + id: instance.id, + host: instance.host, + }); + } + if (ps.moderationNote != null && instance.moderationNote !== ps.moderationNote) { this.moderationLogService.log(me, 'updateRemoteInstanceNote', { id: instance.id, diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 5a69fbf679..29c165f87a 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -128,7 +128,7 @@ export const meta = { }, silencedHosts: { type: 'array', - optional: true, + optional: false, nullable: false, items: { type: 'string', @@ -526,6 +526,14 @@ export const meta = { type: 'string', optional: false, nullable: true, }, + trustedLinkUrlPatterns: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'string', + optional: false, nullable: false, + }, + }, }, }, } as const; @@ -669,6 +677,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- urlPreviewRequireContentLength: instance.urlPreviewRequireContentLength, urlPreviewUserAgent: instance.urlPreviewUserAgent, urlPreviewSummaryProxyUrl: instance.urlPreviewSummaryProxyUrl, + trustedLinkUrlPatterns: instance.trustedLinkUrlPatterns, }; }); } 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 c56dd053d3..cbde554428 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -176,6 +176,11 @@ export const paramDef = { urlPreviewRequireContentLength: { type: 'boolean' }, urlPreviewUserAgent: { type: 'string', nullable: true }, urlPreviewSummaryProxyUrl: { type: 'string', nullable: true }, + trustedLinkUrlPatterns: { + type: 'array', nullable: true, items: { + type: 'string', + }, + }, }, required: [], } as const; @@ -665,6 +670,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- set.urlPreviewSummaryProxyUrl = value === '' ? null : value; } + if (Array.isArray(ps.trustedLinkUrlPatterns)) { + set.trustedLinkUrlPatterns = ps.trustedLinkUrlPatterns.filter(Boolean); + } + const before = await this.metaService.fetch(true); await this.metaService.update(set); diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index 0af90a844b..e20707977f 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -193,9 +193,9 @@ export class ClientServerService { icon: meta.iconUrl, appleTouchIcon: meta.app512IconUrl, themeColor: meta.themeColor, - serverErrorImageUrl: meta.serverErrorImageUrl ?? 'https://launcher.moe/error.png', - infoImageUrl: meta.infoImageUrl ?? 'https://launcher.moe/nothinghere.png', - notFoundImageUrl: meta.notFoundImageUrl ?? 'https://launcher.moe/missingpage.webp', + serverErrorImageUrl: meta.serverErrorImageUrl ?? '/status/error.png', + infoImageUrl: meta.infoImageUrl ?? '/status/nothinghere.png', + notFoundImageUrl: meta.notFoundImageUrl ?? '/status/missingpage.webp', instanceUrl: this.config.url, randomMOTD: this.config.customMOTD ? this.config.customMOTD[Math.floor(Math.random() * this.config.customMOTD.length)] : undefined, metaJson: htmlSafeJsonStringify(await this.metaEntityService.packDetailed(meta)), diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index d83d414096..d64d72c07f 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -77,8 +77,12 @@ export const moderationLogTypes = [ 'deleteGlobalAnnouncement', 'deleteUserAnnouncement', 'resetPassword', + 'setRemoteInstanceNSFW', + 'unsetRemoteInstanceNSFW', 'suspendRemoteInstance', 'unsuspendRemoteInstance', + 'rejectRemoteInstanceReports', + 'acceptRemoteInstanceReports', 'updateRemoteInstanceNote', 'markSensitiveDriveFile', 'unmarkSensitiveDriveFile', @@ -227,6 +231,14 @@ export type ModerationLogPayloads = { userUsername: string; userHost: string | null; }; + setRemoteInstanceNSFW: { + id: string; + host: string; + }; + unsetRemoteInstanceNSFW: { + id: string; + host: string; + }; suspendRemoteInstance: { id: string; host: string; @@ -235,6 +247,14 @@ export type ModerationLogPayloads = { id: string; host: string; }; + rejectRemoteInstanceReports: { + id: string; + host: string; + }; + acceptRemoteInstanceReports: { + id: string; + host: string; + }; updateRemoteInstanceNote: { id: string; host: string; |