Initial working state: CL3.5 complete (Plesk sync + suspend/unsuspend)

This commit is contained in:
2026-03-05 06:47:43 +00:00
commit a36d55eae5
53 changed files with 9925 additions and 0 deletions

18
lib/api/rate-limit.ts Normal file
View File

@@ -0,0 +1,18 @@
const buckets = new Map<string, number[]>();
export function assertRateLimit(
key: string,
maxRequests: number,
windowMs: number,
) {
const now = Date.now();
const start = now - windowMs;
const hits = (buckets.get(key) ?? []).filter((ts) => ts >= start);
if (hits.length >= maxRequests) {
throw new Error("Rate limit exceeded. Please try again in a minute.");
}
hits.push(now);
buckets.set(key, hits);
}

19
lib/api/security.ts Normal file
View File

@@ -0,0 +1,19 @@
import { env } from "@/lib/env";
export function assertSameOrigin(request: Request) {
const origin = request.headers.get("origin");
const host =
request.headers.get("x-forwarded-host") ?? request.headers.get("host");
if (!origin || !host) {
throw new Error("Invalid request origin");
}
const originUrl = new URL(origin);
const appUrl = new URL(env.appUrl);
const allowedHosts = new Set([appUrl.host, host]);
if (!allowedHosts.has(originUrl.host)) {
throw new Error("Cross-site POST blocked");
}
}