From 789deeabac4b7c3119904a006caa59a35c0c0df6 Mon Sep 17 00:00:00 2001 From: Lilly Schramm Date: Wed, 18 Jun 2025 20:08:06 +0200 Subject: [PATCH 1/3] fix(backend): Send Abuse Reports To Set Maintainer E-Mail --- .../core/AbuseReportNotificationService.ts | 29 +++++--- .../unit/AbuseReportNotificationService.ts | 73 +++++++++++++++++++ 2 files changed, 93 insertions(+), 9 deletions(-) diff --git a/packages/backend/src/core/AbuseReportNotificationService.ts b/packages/backend/src/core/AbuseReportNotificationService.ts index 9bca795479..a67e5e19a7 100644 --- a/packages/backend/src/core/AbuseReportNotificationService.ts +++ b/packages/backend/src/core/AbuseReportNotificationService.ts @@ -82,6 +82,25 @@ export class AbuseReportNotificationService implements OnApplicationShutdown { } } + /** + * Collects all email addresses that a abuse report should be sent to. + */ + @bindThis + public async getRecipientEMailAddresses(): Promise { + const recipientEMailAddresses = await this.fetchEMailRecipients().then(it => it + .filter(it => it.isActive && it.userProfile?.emailVerified) + .map(it => it.userProfile?.email) + .filter(x => x != null), + ); + + recipientEMailAddresses.push( + ...(this.meta.email ? [this.meta.email] : []), + ...(this.meta.maintainerEmail ? [this.meta.maintainerEmail] : []), + ); + + return recipientEMailAddresses; + } + /** * Mailを用いて{@link abuseReports}の内容を管理者各位に通知する. * メールアドレスの送信先は以下の通り. @@ -96,15 +115,7 @@ export class AbuseReportNotificationService implements OnApplicationShutdown { return; } - const recipientEMailAddresses = await this.fetchEMailRecipients().then(it => it - .filter(it => it.isActive && it.userProfile?.emailVerified) - .map(it => it.userProfile?.email) - .filter(x => x != null), - ); - - recipientEMailAddresses.push( - ...(this.meta.email ? [this.meta.email] : []), - ); + const recipientEMailAddresses = await this.getRecipientEMailAddresses(); if (recipientEMailAddresses.length <= 0) { return; diff --git a/packages/backend/test/unit/AbuseReportNotificationService.ts b/packages/backend/test/unit/AbuseReportNotificationService.ts index ee68b10f1b..19ba238a55 100644 --- a/packages/backend/test/unit/AbuseReportNotificationService.ts +++ b/packages/backend/test/unit/AbuseReportNotificationService.ts @@ -11,6 +11,7 @@ import { AbuseReportNotificationRecipientRepository, MiAbuseReportNotificationRecipient, MiAbuseUserReport, + MiMeta, MiSystemWebhook, MiUser, SystemWebhooksRepository, @@ -56,6 +57,16 @@ describe('AbuseReportNotificationService', () => { // -------------------------------------------------------------------------------------- + const metaInitial = {} as MiMeta; + const meta = { ...metaInitial }; + + function updateMeta(newMeta: Partial): void { + for (const key in meta) { + delete (meta as any)[key]; + } + Object.assign(meta, newMeta); + } + async function createUser(data: Partial = {}) { const user = await usersRepository .insert({ @@ -66,6 +77,8 @@ describe('AbuseReportNotificationService', () => { await userProfilesRepository.insert({ userId: user.id, + email: user.username + '@example.com', + emailVerified: true, }); return user; @@ -130,6 +143,9 @@ describe('AbuseReportNotificationService', () => { { provide: GlobalEventService, useFactory: () => ({ publishAdminStream: jest.fn() }), }, + { + provide: DI.meta, useFactory: () => meta, + }, ], }) .compile(); @@ -156,6 +172,8 @@ describe('AbuseReportNotificationService', () => { systemWebhook2 = await createWebhook(); roleService.getModeratorIds.mockResolvedValue([root.id, alice.id, bob.id]); + + updateMeta({} as MiMeta); }); afterEach(async () => { @@ -392,4 +410,59 @@ describe('AbuseReportNotificationService', () => { expect(webhookService.enqueueSystemWebhook.mock.calls[0][2]).toEqual({ excludes: [systemWebhook2.id] }); }); }); + + describe('collection of recipient-mails', () => { + async function create() { + const recipient = await createRecipient({ + method: 'email', + userId: alice.id, + }); + + return recipient; + } + + test('with nothing set', async () => { + const mails = await service.getRecipientEMailAddresses(); + expect(mails).toEqual([]); + }); + + test('with maintainer mail set', async () => { + updateMeta({ maintainerEmail: 'maintainer_mail' }); + const mails = await service.getRecipientEMailAddresses(); + expect(mails).toEqual(['maintainer_mail']); + }); + + test('with smtp mail set', async () => { + updateMeta({ email: 'smtp_mail' }); + const mails = await service.getRecipientEMailAddresses(); + expect(mails).toEqual(['smtp_mail']); + }); + + test('with maintainer mail and smtp mail set', async () => { + updateMeta({ email: 'smtp_mail', maintainerEmail: 'maintainer_mail' }); + const mails = await service.getRecipientEMailAddresses(); + expect(mails).toEqual(['smtp_mail', 'maintainer_mail']); + }); + + test('with recipients', async () => { + await create(); + + const mails = await service.getRecipientEMailAddresses(); + expect(mails).toEqual([ + 'alice@example.com', + ]); + }); + + test('with recipients and maintainer mail set and smtp mail set', async () => { + await create(); + updateMeta({ maintainerEmail: 'maintainer_mail', email: 'smtp_mail' }); + + const mails = await service.getRecipientEMailAddresses(); + expect(mails).toEqual([ + 'alice@example.com', + 'smtp_mail', + 'maintainer_mail', + ]); + }); + }); }); From 372e141bcf133708c23368043d3fdda26f8890da Mon Sep 17 00:00:00 2001 From: Lilly Schramm Date: Wed, 18 Jun 2025 20:25:32 +0200 Subject: [PATCH 2/3] refactor(backend): Resolve Nested Conditionals --- .../src/core/AbuseReportNotificationService.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/backend/src/core/AbuseReportNotificationService.ts b/packages/backend/src/core/AbuseReportNotificationService.ts index a67e5e19a7..307f22586e 100644 --- a/packages/backend/src/core/AbuseReportNotificationService.ts +++ b/packages/backend/src/core/AbuseReportNotificationService.ts @@ -93,10 +93,13 @@ export class AbuseReportNotificationService implements OnApplicationShutdown { .filter(x => x != null), ); - recipientEMailAddresses.push( - ...(this.meta.email ? [this.meta.email] : []), - ...(this.meta.maintainerEmail ? [this.meta.maintainerEmail] : []), - ); + if (this.meta.email) { + recipientEMailAddresses.push(this.meta.email); + } + + if (this.meta.maintainerEmail) { + recipientEMailAddresses.push(this.meta.maintainerEmail); + } return recipientEMailAddresses; } From ab5c247f09336b5d60abf1344df7983c818a5e6e Mon Sep 17 00:00:00 2001 From: Lilly Schramm Date: Wed, 18 Jun 2025 20:30:40 +0200 Subject: [PATCH 3/3] refactor(backend): Remove Useless Variable --- packages/backend/test/unit/AbuseReportNotificationService.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/backend/test/unit/AbuseReportNotificationService.ts b/packages/backend/test/unit/AbuseReportNotificationService.ts index 19ba238a55..a67cb3664a 100644 --- a/packages/backend/test/unit/AbuseReportNotificationService.ts +++ b/packages/backend/test/unit/AbuseReportNotificationService.ts @@ -57,8 +57,7 @@ describe('AbuseReportNotificationService', () => { // -------------------------------------------------------------------------------------- - const metaInitial = {} as MiMeta; - const meta = { ...metaInitial }; + const meta = {} as MiMeta; function updateMeta(newMeta: Partial): void { for (const key in meta) {