Scrum4Me/lib/rate-limit.ts
janpeter visser d11b114fc1 feat: ST-601-ST-612 M6 polish, beveiliging en launch-ready
- ST-601/602: loading skeletons en error boundary
- ST-603: Sonner toasts op alle CRUD-operaties
- ST-604: DemoTooltip op uitgeschakelde knoppen
- ST-605: KeyboardSensor dnd-kit, Escape sluit modals
- ST-606: min-width banner < 1024px
- ST-607: WCAG AA aria-labels en skip link
- ST-608: rate limiting login (10/min) en registratie (5/uur)
- ST-609: security integratietests cross-user toegang (7 tests)
- ST-610: GitHub Actions CI/CD workflow
- ST-611: README met quickstart, deployment en API-docs
- ST-612: Lars-flow acceptatiechecklist
- fix: settings toont gebruikersnaam i.p.v. interne id
- fix: seed idempotent, testdata altijd gekoppeld aan demo-gebruiker

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 12:36:23 +02:00

36 lines
999 B
TypeScript

// Simple in-memory rate limiter.
// Note: resets on server restart and does not share state across multiple processes.
// Suitable for MVP; replace with Redis for production scale-out.
interface RateLimitConfig {
windowMs: number
max: number
}
const CONFIGS: Record<string, RateLimitConfig> = {
login: { windowMs: 60_000, max: 10 }, // 10 attempts per minute
register: { windowMs: 3_600_000, max: 5 }, // 5 attempts per hour
}
const DEFAULT_CONFIG: RateLimitConfig = { windowMs: 60_000, max: 10 }
const store = new Map<string, { count: number; resetAt: number }>()
export function checkRateLimit(key: string): boolean {
const prefix = key.split(':')[0]
const config = CONFIGS[prefix] ?? DEFAULT_CONFIG
const now = Date.now()
const entry = store.get(key)
if (!entry || now > entry.resetAt) {
store.set(key, { count: 1, resetAt: now + config.windowMs })
return true
}
if (entry.count >= config.max) {
return false
}
entry.count++
return true
}