Harden CMS security and theme contrast

This commit is contained in:
Simo committed 2026-07-11 20:27:20 +02:00
1 parent 2465ff2170
commit 4a1e1115b3
57 files changed
+1023 -231

No files matched your search

+23 -5
View File
@@ -25,12 +25,30 @@ export function apiError(message: string, status = 400): NextResponse {
return apiJson({ error: message }, { status });
}
/** Safe response for temporary infrastructure failures. */
export function apiUnavailable(message = "Service temporarily unavailable"): NextResponse {
return apiError(message, 503);
}
/** Parse an unsigned, non-zero database identifier without Number precision loss. */
export function positiveBigInt(raw: string | null): bigint | null {
if (!raw || !/^\d+$/.test(raw)) return null;
const value = BigInt(raw);
return value > 0n ? value : null;
}
/** Clamp a ?page / ?perPage pair from search params. */
export function pagination(searchParams: URLSearchParams, defaultPer = 20, maxPer = 100) {
const page = Math.max(1, Number(searchParams.get("page") ?? "1") || 1);
const perPage = Math.min(
maxPer,
Math.max(1, Number(searchParams.get("perPage") ?? defaultPer) || defaultPer),
);
const requestedPage = positiveInteger(searchParams.get("page"), 1);
const requestedPerPage = positiveInteger(searchParams.get("perPage"), defaultPer);
const perPage = Math.min(maxPer, requestedPerPage);
const maxSafePage = Math.floor(Number.MAX_SAFE_INTEGER / perPage) + 1;
const page = Math.min(requestedPage, maxSafePage);
return { page, perPage, skip: (page - 1) * perPage, take: perPage };
}
function positiveInteger(raw: string | null, fallback: number): number {
if (!raw || !/^\d+$/.test(raw)) return fallback;
const value = Number(raw);
return Number.isSafeInteger(value) && value > 0 ? value : fallback;
}