merge: fix(backend): Send Abuse Reports To Set Maintainer E-Mail (!1127)

View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1127

Closes #1069

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Hazelnoot <acomputerdog@gmail.com>
This commit is contained in:
dakkar 2025-06-19 15:54:55 +00:00
commit 169c06d4ca
2 changed files with 95 additions and 9 deletions

View file

@ -82,6 +82,28 @@ export class AbuseReportNotificationService implements OnApplicationShutdown {
} }
} }
/**
* Collects all email addresses that a abuse report should be sent to.
*/
@bindThis
public async getRecipientEMailAddresses(): Promise<string[]> {
const recipientEMailAddresses = await this.fetchEMailRecipients().then(it => it
.filter(it => it.isActive && it.userProfile?.emailVerified)
.map(it => it.userProfile?.email)
.filter(x => x != null),
);
if (this.meta.email) {
recipientEMailAddresses.push(this.meta.email);
}
if (this.meta.maintainerEmail) {
recipientEMailAddresses.push(this.meta.maintainerEmail);
}
return recipientEMailAddresses;
}
/** /**
* Mailを用いて{@link abuseReports}. * Mailを用いて{@link abuseReports}.
* . * .
@ -96,15 +118,7 @@ export class AbuseReportNotificationService implements OnApplicationShutdown {
return; return;
} }
const recipientEMailAddresses = await this.fetchEMailRecipients().then(it => it const recipientEMailAddresses = await this.getRecipientEMailAddresses();
.filter(it => it.isActive && it.userProfile?.emailVerified)
.map(it => it.userProfile?.email)
.filter(x => x != null),
);
recipientEMailAddresses.push(
...(this.meta.email ? [this.meta.email] : []),
);
if (recipientEMailAddresses.length <= 0) { if (recipientEMailAddresses.length <= 0) {
return; return;

View file

@ -11,6 +11,7 @@ import {
AbuseReportNotificationRecipientRepository, AbuseReportNotificationRecipientRepository,
MiAbuseReportNotificationRecipient, MiAbuseReportNotificationRecipient,
MiAbuseUserReport, MiAbuseUserReport,
MiMeta,
MiSystemWebhook, MiSystemWebhook,
MiUser, MiUser,
SystemWebhooksRepository, SystemWebhooksRepository,
@ -56,6 +57,15 @@ describe('AbuseReportNotificationService', () => {
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
const meta = {} as MiMeta;
function updateMeta(newMeta: Partial<MiMeta>): void {
for (const key in meta) {
delete (meta as any)[key];
}
Object.assign(meta, newMeta);
}
async function createUser(data: Partial<MiUser> = {}) { async function createUser(data: Partial<MiUser> = {}) {
const user = await usersRepository const user = await usersRepository
.insert({ .insert({
@ -66,6 +76,8 @@ describe('AbuseReportNotificationService', () => {
await userProfilesRepository.insert({ await userProfilesRepository.insert({
userId: user.id, userId: user.id,
email: user.username + '@example.com',
emailVerified: true,
}); });
return user; return user;
@ -130,6 +142,9 @@ describe('AbuseReportNotificationService', () => {
{ {
provide: GlobalEventService, useFactory: () => ({ publishAdminStream: jest.fn() }), provide: GlobalEventService, useFactory: () => ({ publishAdminStream: jest.fn() }),
}, },
{
provide: DI.meta, useFactory: () => meta,
},
], ],
}) })
.compile(); .compile();
@ -156,6 +171,8 @@ describe('AbuseReportNotificationService', () => {
systemWebhook2 = await createWebhook(); systemWebhook2 = await createWebhook();
roleService.getModeratorIds.mockResolvedValue([root.id, alice.id, bob.id]); roleService.getModeratorIds.mockResolvedValue([root.id, alice.id, bob.id]);
updateMeta({} as MiMeta);
}); });
afterEach(async () => { afterEach(async () => {
@ -392,4 +409,59 @@ describe('AbuseReportNotificationService', () => {
expect(webhookService.enqueueSystemWebhook.mock.calls[0][2]).toEqual({ excludes: [systemWebhook2.id] }); 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',
]);
});
});
}); });