test(federation-identity): #15 rate limit 5/15min

This commit is contained in:
Jannis Braun
2026-05-04 00:26:35 +02:00
parent 8e3fa1d5aa
commit d917ff5354
@@ -846,3 +846,62 @@ describe('Federation identity deletion — all-remotes fan-out', () => {
home.close();
});
});
let rateLimitHarness: TwoInstanceHarness;
describe('Federation identity deletion — rate limit', () => {
beforeAll(async () => {
const { bootTwoInstancesWithRateLimits } = await import('./helpers/twoInstanceHarness.js');
rateLimitHarness = await bootTwoInstancesWithRateLimits();
// No peer setup needed — leave-mode tests skip S2S calls anyway, and
// the test only exercises the home endpoint's rate-limit hook.
}, 60_000);
afterAll(async () => {
if (rateLimitHarness) await rateLimitHarness.cleanup();
});
it('#15 rate limit: 6th call within 15min returns 429', async () => {
const { registerLocal } = await import('./helpers/testUsers.js');
const home = await registerLocal(rateLimitHarness.home, 't15');
const now = Date.now();
const fakeOrigins = Array.from({ length: 5 }, (_, i) => `http://ratelimit-${i}.test:99`);
// Seed 5 ephemeral registry entries on home (no peer rows needed — leave skips S2S)
const regRes = await fetch(`${rateLimitHarness.home.origin}/api/users/@me/federation-registry`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${home.token}` },
body: JSON.stringify({
updatedAt: now,
registry: fakeOrigins.map(o => ({
origin: o,
label: o,
username: 'x',
remoteUserId: '',
status: 'connected',
addedAt: now,
})),
}),
});
expect(regRes.ok).toBe(true);
// 5 successful leave calls (each targets a different fake origin)
for (const origin of fakeOrigins) {
const res = await fetch(`${rateLimitHarness.home.origin}/api/users/@me/federation-identity/delete`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${home.token}` },
body: JSON.stringify({ origins: [origin], mode: 'leave' }),
});
expect(res.status).toBe(200);
}
// 6th attempt should be rate-limited
const res6 = await fetch(`${rateLimitHarness.home.origin}/api/users/@me/federation-identity/delete`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${home.token}` },
body: JSON.stringify({ origins: ['http://does-not-matter.test'], mode: 'leave' }),
});
expect(res6.status).toBe(429);
expect(res6.headers.get('retry-after')).toBeTruthy();
});
});