mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 13:05:32 +09:00
chore: tidy request handling across services (#3168)
This commit is contained in:
1 parent
c6941d5905
commit
da9e9ff0be
11 files changed
+428
-44
No files matched your search
@@ -95,6 +95,8 @@ const DSA_CODE_CHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
const DSA_CODE_SEGMENT_LENGTH = 4;
|
||||
const DSA_CODE_SEPARATOR = '-';
|
||||
const DSA_TICKET_BYTES = 32;
|
||||
const DSA_EMAIL_SEND_RECIPIENT_MAX = 3;
|
||||
const DSA_EMAIL_SEND_RECIPIENT_WINDOW = ms('1 hour');
|
||||
|
||||
async function emitReportFiled(row: IARSubmissionRow, target: ReportTarget): Promise<void> {
|
||||
const key = row.reported_user_id ?? row.reporter_id;
|
||||
@@ -373,6 +375,20 @@ export class ReportService {
|
||||
|
||||
async sendDsaReportVerificationCode(email: string, locale: string | null = null): Promise<void> {
|
||||
const normalizedEmail = this.normalizeEmail(email);
|
||||
const recipientLimit = await this.rateLimitService.checkLimit({
|
||||
identifier: `dsa:report:email:send:recipient:${normalizedEmail}`,
|
||||
maxAttempts: DSA_EMAIL_SEND_RECIPIENT_MAX,
|
||||
windowMs: DSA_EMAIL_SEND_RECIPIENT_WINDOW,
|
||||
});
|
||||
if (!recipientLimit.allowed) {
|
||||
throw new RateLimitError({
|
||||
retryAfter: recipientLimit.retryAfter,
|
||||
retryAfterDecimal: recipientLimit.retryAfterDecimal,
|
||||
limit: recipientLimit.limit,
|
||||
resetTime: recipientLimit.resetTime,
|
||||
resetAfterDecimal: recipientLimit.resetAfterDecimal,
|
||||
});
|
||||
}
|
||||
const hasValidDns = await this.emailDnsValidationService.hasValidDnsRecords(normalizedEmail);
|
||||
if (!hasValidDns) {
|
||||
throw InputValidationError.fromCode('email', ValidationErrorCodes.EMAIL_DOMAIN_CANNOT_RECEIVE_MAIL);
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {clearTestEmails, createUniqueEmail, listTestEmails} from '@app/api/auth/tests/AuthTestUtils';
|
||||
import {type ApiTestHarness, createApiTestHarness} from '@app/api/test/ApiTestHarness';
|
||||
import {HTTP_STATUS} from '@app/api/test/TestConstants';
|
||||
import {createBuilderWithoutAuth} from '@app/api/test/TestRequestBuilder';
|
||||
import {afterEach, beforeEach, describe, expect, test} from 'vitest';
|
||||
|
||||
async function countVerificationEmailsTo(harness: ApiTestHarness, email: string): Promise<number> {
|
||||
const emails = await listTestEmails(harness);
|
||||
return emails.filter((sent) => sent.type === 'dsa_report_verification' && sent.to === email.toLowerCase()).length;
|
||||
}
|
||||
|
||||
describe('DSA report verification email recipient limit', () => {
|
||||
let harness: ApiTestHarness;
|
||||
beforeEach(async () => {
|
||||
harness = await createApiTestHarness();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await harness?.shutdown();
|
||||
});
|
||||
|
||||
test('limits verification emails per address regardless of letter case', async () => {
|
||||
await clearTestEmails(harness);
|
||||
const email = createUniqueEmail('dsa-recipient');
|
||||
for (let attempt = 0; attempt < 3; attempt++) {
|
||||
await createBuilderWithoutAuth(harness)
|
||||
.post('/reports/dsa/email/send')
|
||||
.body({email})
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.execute();
|
||||
}
|
||||
await createBuilderWithoutAuth(harness)
|
||||
.post('/reports/dsa/email/send')
|
||||
.body({email: email.toUpperCase()})
|
||||
.expect(429)
|
||||
.execute();
|
||||
expect(await countVerificationEmailsTo(harness, email)).toBe(3);
|
||||
});
|
||||
|
||||
test('keeps sending to other addresses after one address reaches its limit', async () => {
|
||||
await clearTestEmails(harness);
|
||||
const limited = createUniqueEmail('dsa-recipient');
|
||||
for (let attempt = 0; attempt < 3; attempt++) {
|
||||
await createBuilderWithoutAuth(harness).post('/reports/dsa/email/send').body({email: limited}).execute();
|
||||
}
|
||||
const other = createUniqueEmail('dsa-recipient');
|
||||
await createBuilderWithoutAuth(harness)
|
||||
.post('/reports/dsa/email/send')
|
||||
.body({email: other})
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.execute();
|
||||
expect(await countVerificationEmailsTo(harness, other)).toBe(1);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user