refactor: remove obsolete member management API module
Some checks failed
Workflow / ʦ TypeScript (pull_request) Failing after 5m57s
Workflow / ⚫️ Test (pull_request) Has been skipped

This commit is contained in:
T. Zehetbauer
2026-04-03 14:08:31 +02:00
parent 124c6a632a
commit 5c5aaabae5
132 changed files with 10107 additions and 3442 deletions

View File

@@ -0,0 +1,102 @@
import 'server-only';
/**
* Simple in-memory rate limiter for API routes.
* Tracks request counts per key within sliding time windows.
*
* For production at scale, consider Upstash Redis or Vercel Edge Config.
* This is sufficient for moderate traffic and single-instance deployments.
*/
interface RateLimitEntry {
count: number;
resetAt: number;
}
const store = new Map<string, RateLimitEntry>();
// Cleanup stale entries every 2 minutes
const CLEANUP_INTERVAL = 2 * 60 * 1000;
// Hard cap to prevent memory exhaustion under attack
const MAX_STORE_SIZE = 10_000;
let lastCleanup = Date.now();
function cleanup() {
const now = Date.now();
if (now - lastCleanup < CLEANUP_INTERVAL) return;
lastCleanup = now;
for (const [key, entry] of store) {
if (entry.resetAt <= now) {
store.delete(key);
}
}
// If still over limit after expiry cleanup, evict oldest entries
if (store.size > MAX_STORE_SIZE) {
const sorted = [...store.entries()].sort(
(a, b) => a[1].resetAt - b[1].resetAt,
);
const toDelete = sorted.slice(0, store.size - MAX_STORE_SIZE);
for (const [key] of toDelete) {
store.delete(key);
}
}
}
/**
* Check rate limit for a given key.
*
* @param key - Unique identifier (e.g., IP address, account ID)
* @param maxRequests - Maximum requests allowed within the window
* @param windowMs - Time window in milliseconds
* @returns Object with `allowed` boolean and `remaining` count
*/
export function checkRateLimit(
key: string,
maxRequests: number,
windowMs: number,
): { allowed: boolean; remaining: number; resetAt: number } {
cleanup();
const now = Date.now();
const entry = store.get(key);
if (!entry || entry.resetAt <= now) {
// New window
store.set(key, { count: 1, resetAt: now + windowMs });
return {
allowed: true,
remaining: maxRequests - 1,
resetAt: now + windowMs,
};
}
if (entry.count >= maxRequests) {
return { allowed: false, remaining: 0, resetAt: entry.resetAt };
}
entry.count++;
return {
allowed: true,
remaining: maxRequests - entry.count,
resetAt: entry.resetAt,
};
}
/**
* Extract client IP from request headers.
* Works with Vercel, Cloudflare, and standard proxies.
*/
export function getClientIp(request: Request): string {
return (
request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() ??
request.headers.get('x-real-ip') ??
request.headers.get('cf-connecting-ip') ??
'unknown'
);
}