Spreadsheet-UX op een echte relationele engine
Deze repository wordt als momentopname gepubliceerd: een clone bevat de volledige inhoud, maar geen commitgeschiedenis.
/**
* Login and signup throttling, keyed by email and by client address.
*
* In-memory on purpose: it protects a single process against online guessing
* and resets on restart. Anything stronger belongs at the reverse proxy.
*/
export class LoginThrottle {
private readonly hits = new Map<string, { count: number; first: number; until: number }>();
constructor(
private readonly limit = 8,
private readonly windowMs = 5 * 60_000,
private readonly lockoutMs = 15 * 60_000,
) {}
/** Milliseconds the caller must wait, or 0 when the attempt may proceed. */
check(key: string): number {
const entry = this.hits.get(key);
if (!entry) return 0;
const now = Date.now();
if (entry.until > now) return entry.until - now;
if (now - entry.first > this.windowMs) {
this.hits.delete(key);
return 0;
}
return 0;
}
fail(key: string): void {
const now = Date.now();
const entry = this.hits.get(key);
if (!entry || now - entry.first > this.windowMs) {
this.hits.set(key, { count: 1, first: now, until: 0 });
return;
}
entry.count++;
if (entry.count >= this.limit) {
entry.until = now + this.lockoutMs;
entry.count = 0;
entry.first = now;
}
}
succeed(key: string): void {
this.hits.delete(key);
}
clear(): void {
this.hits.clear();
}
}