mirror of
https://github.com/bretzel-app/crumbs.git
synced 2026-10-12 20:06:57 +02:00
- Strip server paths from public attachment responses (new PublicAttachment type) - Use $page.url.origin instead of window.location.origin (SSR-safe) - Fix toggle switch left-4.5 → left-[1.125rem] (valid Tailwind) - Add aria-label to SharingIndicator button for screen readers - Add opportunistic pruning to IP rate limiter to prevent unbounded growth - Reduce shared attachment cache to 1 hour (respect share revocation) - Update OpenAPI schema with PublicAttachment type - Add unit test asserting server paths are not leaked Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
31 lines
760 B
TypeScript
31 lines
760 B
TypeScript
const store = new Map<string, { count: number; windowStart: number }>();
|
|
const WINDOW_MS = 60_000; // 1 minute
|
|
const MAX_REQUESTS = 60;
|
|
const MAX_ENTRIES = 10_000;
|
|
let cleanupCounter = 0;
|
|
|
|
export function checkIpRateLimit(ip: string): boolean {
|
|
const now = Date.now();
|
|
const entry = store.get(ip);
|
|
if (!entry || now - entry.windowStart > WINDOW_MS) {
|
|
store.set(ip, { count: 1, windowStart: now });
|
|
pruneIfNeeded(now);
|
|
return true;
|
|
}
|
|
entry.count++;
|
|
return entry.count <= MAX_REQUESTS;
|
|
}
|
|
|
|
function pruneIfNeeded(now: number) {
|
|
cleanupCounter++;
|
|
if (cleanupCounter < 100 || store.size < MAX_ENTRIES) {
|
|
return;
|
|
}
|
|
cleanupCounter = 0;
|
|
for (const [key, entry] of store) {
|
|
if (now - entry.windowStart > WINDOW_MS) {
|
|
store.delete(key);
|
|
}
|
|
}
|
|
}
|