mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-04 08:15:41 +00:00
fix: let the webmail build again with the device registry's rate limit out of its route
This commit is contained in:
@@ -18,7 +18,7 @@ vi.mock('@/lib/admin/session', async (original) => ({
|
||||
getClientIP: () => client.ip,
|
||||
}));
|
||||
|
||||
import { POST as checkIn, REGISTER_PER_HOUR } from '../route';
|
||||
import { POST as checkIn } from '../route';
|
||||
import { POST as wiped } from '../wiped/route';
|
||||
import { GET as adminList, POST as adminAct } from '../../admin/devices/route';
|
||||
import * as registry from '@/lib/devices/registry';
|
||||
@@ -120,12 +120,12 @@ describe('POST /api/devices', () => {
|
||||
it('holds new rows to a much lower limit per address than check-ins, and a 429 changes nothing', async () => {
|
||||
creds.value = { accountName: 'alice@example.org', serverUrl: 'https://mail.example.org' };
|
||||
const statuses: number[] = [];
|
||||
for (let i = 0; i <= REGISTER_PER_HOUR; i += 1) {
|
||||
for (let i = 0; i <= registry.REGISTER_PER_HOUR; i += 1) {
|
||||
statuses.push((await checkIn(request('/api/devices', { platform: 'x', appVersion: '1' }))).status);
|
||||
}
|
||||
expect(statuses.slice(0, REGISTER_PER_HOUR).every((status) => status === 200)).toBe(true);
|
||||
expect(statuses.slice(0, registry.REGISTER_PER_HOUR).every((status) => status === 200)).toBe(true);
|
||||
expect(statuses.at(-1)).toBe(429);
|
||||
expect((await registry.listDevices()).total).toBe(REGISTER_PER_HOUR);
|
||||
expect((await registry.listDevices()).total).toBe(registry.REGISTER_PER_HOUR);
|
||||
|
||||
// A device that's already registered still hears about its wipe.
|
||||
const [{ id }] = (await registry.listDevices()).devices;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { getClientIP } from '@/lib/admin/session';
|
||||
import { checkInDevice, DEVICE_ID_RE, DEVICE_SECRET_RE, registerDevice, TooManyDevicesError } from '@/lib/devices/registry';
|
||||
import { checkInDevice, DEVICE_ID_RE, DEVICE_SECRET_RE, REGISTER_PER_HOUR, registerDevice, TooManyDevicesError } from '@/lib/devices/registry';
|
||||
import { logger } from '@/lib/logger';
|
||||
import { rejectCrossOriginRequest } from '@/lib/security/same-origin';
|
||||
import { getStore } from '@/lib/shared-store';
|
||||
@@ -11,12 +11,6 @@ const NO_STORE = { 'Cache-Control': 'no-store' };
|
||||
const MAX_BODY_BYTES = 2048;
|
||||
// Per address: a whole office can sit behind one, checking in as it starts up.
|
||||
const PER_MINUTE = 300;
|
||||
/**
|
||||
* A new row is written to the state dir and stays half a year, for anyone with a
|
||||
* session. Enough for an office turning this on in one morning: a device turned
|
||||
* away tries again in a quarter of an hour.
|
||||
*/
|
||||
export const REGISTER_PER_HOUR = 60;
|
||||
|
||||
function cleanText(value: unknown): string {
|
||||
if (typeof value !== 'string') return '';
|
||||
|
||||
@@ -19,6 +19,12 @@ import { settingsId } from '@/lib/settings-sync';
|
||||
import { getStore, type CollectionOptions } from '@/lib/shared-store';
|
||||
import type { DeviceView, WipeReason } from './types';
|
||||
|
||||
/**
|
||||
* A new row is written to the state dir and stays half a year, for anyone with a
|
||||
* session. Enough for an office turning this on in one morning: a device turned
|
||||
* away tries again in a quarter of an hour.
|
||||
*/
|
||||
export const REGISTER_PER_HOUR = 60;
|
||||
export const DEVICE_ID_RE = /^[0-9a-f]{64}\/[0-9a-f]{32}$/;
|
||||
export const DEVICE_SECRET_RE = /^[0-9a-f]{64}$/;
|
||||
const USER_KEY_RE = /^[0-9a-f]{64}$/;
|
||||
|
||||
Reference in New Issue
Block a user