Build and Push Docker Image / build-and-push (push) Successful in 5m37s
Routes move to server/routes/ (auth, account, projects, reader, sharing, admin); index.js keeps setup only. A smoke test walks 90 API calls against the real server and compares every status with the pre-split behaviour. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
24 lines
1022 B
JavaScript
24 lines
1022 B
JavaScript
// In-memory limiter for sign-in style endpoints: 10 FAILED attempts per 15 min, tracked per IP and per
|
|
// account (key). Successful sign-ins don't count, so a shared IP doesn't lock everyone out.
|
|
const _failures = new Map();
|
|
const FAIL_WINDOW = 15 * 60 * 1000;
|
|
const FAIL_MAX = 10;
|
|
setInterval(() => {
|
|
const now = Date.now();
|
|
for (const [k, e] of _failures) if (now > e.resetAt) _failures.delete(k);
|
|
}, 60 * 60 * 1000).unref();
|
|
export function isLimited(...keys) {
|
|
const now = Date.now();
|
|
return keys.some((k) => { const e = _failures.get(k); return e && now <= e.resetAt && e.count >= FAIL_MAX; });
|
|
}
|
|
export function recordFailure(...keys) {
|
|
const now = Date.now();
|
|
for (const k of keys) {
|
|
const e = _failures.get(k);
|
|
if (!e || now > e.resetAt) _failures.set(k, { count: 1, resetAt: now + FAIL_WINDOW });
|
|
else e.count += 1;
|
|
}
|
|
}
|
|
export function clearFailures(...keys) { keys.forEach((k) => _failures.delete(k)); }
|
|
export const TOO_MANY = { error: 'Too many attempts. Please wait 15 minutes.' };
|