feat: redesign CMS and unify German admin UI
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Minimal in-memory fixed-window rate limiter for a single Node process
|
||||
* (this app always runs as one process — see server.ts). Good enough to
|
||||
* (this app always runs as one process - see server.ts). Good enough to
|
||||
* blunt abuse of the email-verification resend endpoint without adding an
|
||||
* external store; resets on deploy/restart, which is an acceptable
|
||||
* trade-off for this use case.
|
||||
@@ -34,12 +34,12 @@ export function checkRateLimit(key: string, opts: { max: number; windowMs: numbe
|
||||
|
||||
export function getClientIp(request: { headers: Headers }): string {
|
||||
// Deployment is always behind exactly one trusted reverse proxy (see
|
||||
// DEPLOYMENT.md — Nginx Proxy Manager; the app port isn't published
|
||||
// DEPLOYMENT.md - Nginx Proxy Manager; the app port isn't published
|
||||
// directly to the host). nginx's default `$proxy_add_x_forwarded_for`
|
||||
// *appends* the real client IP to any X-Forwarded-For it already
|
||||
// received rather than replacing it, so a directly-connecting client
|
||||
// could prepend arbitrary spoofed entries of their own. Only the
|
||||
// right-most (last) entry — the one the trusted proxy itself appended —
|
||||
// right-most (last) entry - the one the trusted proxy itself appended -
|
||||
// is trustworthy; taking the first entry would let a client bypass this
|
||||
// rate limit entirely by sending a fake X-Forwarded-For header.
|
||||
const forwarded = request.headers.get("x-forwarded-for");
|
||||
|
||||
@@ -3,13 +3,13 @@ import { createHash, randomBytes } from "node:crypto";
|
||||
/** How long a freshly issued email-verification link stays valid. */
|
||||
export const EMAIL_VERIFICATION_TTL_MS = 24 * 60 * 60 * 1000;
|
||||
|
||||
/** 256 bits of randomness, hex-encoded — not guessable, never derived from user data. */
|
||||
/** 256 bits of randomness, hex-encoded - not guessable, never derived from user data. */
|
||||
export function generateVerificationToken(): string {
|
||||
return randomBytes(32).toString("hex");
|
||||
}
|
||||
|
||||
/**
|
||||
* Only this hash is ever persisted (see collections/Customers.ts) — the
|
||||
* Only this hash is ever persisted (see collections/Customers.ts) - the
|
||||
* plaintext token exists only in the URL sent by email and briefly in
|
||||
* memory while that email is being sent.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user