diff --git a/locales/index.d.ts b/locales/index.d.ts index 0b4fb366c4..8296a0fbdf 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -1097,6 +1097,9 @@ export interface Locale { "doYouAgree": string; "beSureToReadThisAsItIsImportant": string; "iHaveReadXCarefullyAndAgree": string; + "doNotSendNotificationEmailsForAbuseReport": string; + "emailToReceiveAbuseReport": string; + "emailToReceiveAbuseReportCaption": string; "_initialAccountSetting": { "accountCreated": string; "letsStartAccountSetup": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 27af578a29..8904620cc3 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1094,6 +1094,9 @@ expired: "期限切れ" doYouAgree: "同意しますか?" beSureToReadThisAsItIsImportant: "重要ですので必ずお読みください。" iHaveReadXCarefullyAndAgree: "「{x}」の内容をよく読み、同意します。" +doNotSendNotificationEmailsForAbuseReport: "通報の通知メールを発送しないようにする" +emailToReceiveAbuseReport: "通報通知を受け取るためのメールアドレス" +emailToReceiveAbuseReportCaption: "通報通知を受け取るためのメールアドレスを指定します。ここの入力欄を空にするとメールサーバーのメールアドレスが使用されます。" _initialAccountSetting: accountCreated: "アカウントの作成が完了しました!" diff --git a/packages/backend/migration/1691120548582-notification-emails-for-abuse-report.js b/packages/backend/migration/1691120548582-notification-emails-for-abuse-report.js new file mode 100644 index 0000000000..09bdca7025 --- /dev/null +++ b/packages/backend/migration/1691120548582-notification-emails-for-abuse-report.js @@ -0,0 +1,13 @@ +export class NotificationEmailsForAbuseReport1691120548582 { + name = 'NotificationEmailsForAbuseReport1691120548582' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "emailToReceiveAbuseReport" character varying(1024)`); + await queryRunner.query(`ALTER TABLE "meta" ADD "doNotSendNotificationEmailsForAbuseReport" boolean NOT NULL DEFAULT false`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "doNotSendNotificationEmailsForAbuseReport"`); + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "emailToReceiveAbuseReport"`); + } +} diff --git a/packages/backend/src/models/entities/Meta.ts b/packages/backend/src/models/entities/Meta.ts index bf05e2dd91..eb782d7ce1 100644 --- a/packages/backend/src/models/entities/Meta.ts +++ b/packages/backend/src/models/entities/Meta.ts @@ -41,6 +41,11 @@ export class Meta { }) public maintainerEmail: string | null; + @Column('varchar', { + length: 1024, nullable: true, + }) + public emailToReceiveAbuseReport: string | null; + @Column('boolean', { default: false, }) @@ -432,6 +437,11 @@ export class Meta { }) public enableIdenticonGeneration: boolean; + @Column('boolean', { + default: false, + }) + public doNotSendNotificationEmailsForAbuseReport: boolean; + @Column('jsonb', { default: { }, }) diff --git a/packages/backend/src/queue/processors/ReportAbuseProcessorService.ts b/packages/backend/src/queue/processors/ReportAbuseProcessorService.ts index d1ff3a5a49..ae63d2786f 100644 --- a/packages/backend/src/queue/processors/ReportAbuseProcessorService.ts +++ b/packages/backend/src/queue/processors/ReportAbuseProcessorService.ts @@ -104,8 +104,8 @@ export class ReportAbuseProcessorService { } const meta = await this.metaService.fetch(); - if (meta.email) { - this.emailService.sendEmail(meta.email, 'New abuse report', + if ((meta.emailToReceiveAbuseReport || meta.email) && !meta.doNotSendNotificationEmailsForAbuseReport) { + this.emailService.sendEmail(meta.emailToReceiveAbuseReport ?? meta.email!, 'New abuse report', sanitizeHtml(job.data.comment), sanitizeHtml(job.data.comment)); } diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 93423a743d..c610ace4d0 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -278,6 +278,14 @@ export const meta = { type: 'boolean', optional: false, nullable: false, }, + doNotSendNotificationEmailsForAbuseReport: { + type: 'boolean', + optional: false, nullable: false, + }, + emailToReceiveAbuseReport: { + type: 'string', + optional: false, nullable: true, + }, policies: { type: 'object', optional: false, nullable: false, @@ -383,6 +391,8 @@ export default class extends Endpoint { enableChartsForFederatedInstances: instance.enableChartsForFederatedInstances, enableServerMachineStats: instance.enableServerMachineStats, enableIdenticonGeneration: instance.enableIdenticonGeneration, + doNotSendNotificationEmailsForAbuseReport: instance.doNotSendNotificationEmailsForAbuseReport, + emailToReceiveAbuseReport: instance.emailToReceiveAbuseReport, policies: { ...DEFAULT_POLICIES, ...instance.policies }, }; }); 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 e5b97890b3..b31a3662c7 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -104,6 +104,8 @@ export const paramDef = { enableChartsForFederatedInstances: { type: 'boolean' }, enableServerMachineStats: { type: 'boolean' }, enableIdenticonGeneration: { type: 'boolean' }, + doNotSendNotificationEmailsForAbuseReport: { type: 'boolean' }, + emailToReceiveAbuseReport: { type: 'string', nullable: true }, serverRules: { type: 'array', items: { type: 'string' } }, preservedUsernames: { type: 'array', items: { type: 'string' } }, }, @@ -419,6 +421,14 @@ export default class extends Endpoint { set.enableIdenticonGeneration = ps.enableIdenticonGeneration; } + if (ps.doNotSendNotificationEmailsForAbuseReport !== undefined) { + set.doNotSendNotificationEmailsForAbuseReport = ps.doNotSendNotificationEmailsForAbuseReport; + } + + if (ps.emailToReceiveAbuseReport !== undefined) { + set.emailToReceiveAbuseReport = ps.emailToReceiveAbuseReport; + } + if (ps.serverRules !== undefined) { set.serverRules = ps.serverRules; } diff --git a/packages/frontend/src/pages/admin/other-settings.vue b/packages/frontend/src/pages/admin/other-settings.vue index 7a4d3831a0..7c7724e4cb 100644 --- a/packages/frontend/src/pages/admin/other-settings.vue +++ b/packages/frontend/src/pages/admin/other-settings.vue @@ -36,6 +36,12 @@ SPDX-License-Identifier: AGPL-3.0-only + +
+ + + +
@@ -56,6 +62,7 @@ let enableServerMachineStats: boolean = $ref(false); let enableIdenticonGeneration: boolean = $ref(false); let enableChartsForRemoteUser: boolean = $ref(false); let enableChartsForFederatedInstances: boolean = $ref(false); +let doNotSendNotificationEmailsForAbuseReport: boolean = $ref(false); async function init() { const meta = await os.api('admin/meta'); @@ -63,6 +70,7 @@ async function init() { enableIdenticonGeneration = meta.enableIdenticonGeneration; enableChartsForRemoteUser = meta.enableChartsForRemoteUser; enableChartsForFederatedInstances = meta.enableChartsForFederatedInstances; + doNotSendNotificationEmailsForAbuseReport = meta.doNotSendNotificationEmailsForAbuseReport; } function save() { @@ -71,6 +79,7 @@ function save() { enableIdenticonGeneration, enableChartsForRemoteUser, enableChartsForFederatedInstances, + doNotSendNotificationEmailsForAbuseReport, }).then(() => { fetchInstance(); }); diff --git a/packages/frontend/src/pages/admin/settings.vue b/packages/frontend/src/pages/admin/settings.vue index 81ef32ac06..c8e27b3509 100644 --- a/packages/frontend/src/pages/admin/settings.vue +++ b/packages/frontend/src/pages/admin/settings.vue @@ -29,6 +29,12 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + + + @@ -121,6 +127,7 @@ let name: string | null = $ref(null); let description: string | null = $ref(null); let maintainerName: string | null = $ref(null); let maintainerEmail: string | null = $ref(null); +let emailToReceiveAbuseReport: string | null = $ref(null); let pinnedUsers: string = $ref(''); let cacheRemoteFiles: boolean = $ref(false); let cacheRemoteSensitiveFiles: boolean = $ref(false); @@ -136,6 +143,7 @@ async function init(): Promise { description = meta.description; maintainerName = meta.maintainerName; maintainerEmail = meta.maintainerEmail; + emailToReceiveAbuseReport = meta.emailToReceiveAbuseReport; pinnedUsers = meta.pinnedUsers.join('\n'); cacheRemoteFiles = meta.cacheRemoteFiles; cacheRemoteSensitiveFiles = meta.cacheRemoteSensitiveFiles; @@ -152,6 +160,8 @@ function save(): void { description, maintainerName, maintainerEmail, + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + emailToReceiveAbuseReport: emailToReceiveAbuseReport || null, pinnedUsers: pinnedUsers.split('\n'), cacheRemoteFiles, cacheRemoteSensitiveFiles,