refactor: mark dead exports with TODO, deduplicate field sanitization, fix import placement
Local Build and Deploy / deploy (push) Successful in 1m36s

This commit is contained in:
openhands committed 2026-07-20 14:47:05 +02:00
1 parent 2beba07ba5
commit d5e3bc7875
13 files changed
+49 -64

No files matched your search

+15 -58
View File
@@ -5,6 +5,7 @@ import { redirect } from "next/navigation";
import { requirePermission } from "@/lib/admin/guard"; import { requirePermission } from "@/lib/admin/guard";
import { PERMS } from "@/lib/permissions"; import { PERMS } from "@/lib/permissions";
import { formPositiveBigInt } from "@/lib/form-data"; import { formPositiveBigInt } from "@/lib/form-data";
import { canonicalize, sanitizeField } from "@/lib/foundation/security";
import { prisma } from "@/lib/prisma"; import { prisma } from "@/lib/prisma";
import { logStaffActivity } from "@/lib/services/staff-activity"; import { logStaffActivity } from "@/lib/services/staff-activity";
@@ -18,37 +19,15 @@ function parsePosition(value: FormDataEntryValue | null): number {
export async function createHelpQuestion(formData: FormData): Promise<void> { export async function createHelpQuestion(formData: FormData): Promise<void> {
const staff = await requirePermission(PERMS.PAGES_EDIT); const staff = await requirePermission(PERMS.PAGES_EDIT);
const name = String(formData.get("name") ?? "") const name = sanitizeField(formData.get("name"));
.normalize("NFC") const content = canonicalize(String(formData.get("content") ?? ""));
.trim()
.slice(0, 255);
const content = String(formData.get("content") ?? "")
.normalize("NFC")
.trim();
if (!name || !content) return; if (!name || !content) return;
const imageUrl = String(formData.get("imageUrl") ?? "") const imageUrl = sanitizeField(formData.get("imageUrl"));
.normalize("NFC") const buttonText = sanitizeField(formData.get("buttonText"));
.trim() const buttonUrl = sanitizeField(formData.get("buttonUrl"));
.slice(0, 255); const buttonColor = sanitizeField(formData.get("buttonColor"), 16) || "#eeb425";
const buttonText = String(formData.get("buttonText") ?? "") const buttonBorderColor = sanitizeField(formData.get("buttonBorderColor"), 16) || "#facc15";
.normalize("NFC")
.trim()
.slice(0, 255);
const buttonUrl = String(formData.get("buttonUrl") ?? "")
.normalize("NFC")
.trim()
.slice(0, 255);
const buttonColor =
String(formData.get("buttonColor") ?? "")
.normalize("NFC")
.trim()
.slice(0, 16) || "#eeb425";
const buttonBorderColor =
String(formData.get("buttonBorderColor") ?? "")
.normalize("NFC")
.trim()
.slice(0, 16) || "#facc15";
try { try {
const entry = await prisma.websiteHelpCenterCategories.create({ const entry = await prisma.websiteHelpCenterCategories.create({
@@ -87,37 +66,15 @@ export async function updateHelpQuestion(formData: FormData): Promise<void> {
const id = formPositiveBigInt(formData, "id"); const id = formPositiveBigInt(formData, "id");
if (!id) return; if (!id) return;
const name = String(formData.get("name") ?? "") const name = sanitizeField(formData.get("name"));
.normalize("NFC") const content = canonicalize(String(formData.get("content") ?? ""));
.trim()
.slice(0, 255);
const content = String(formData.get("content") ?? "")
.normalize("NFC")
.trim();
if (!name || !content) return; if (!name || !content) return;
const imageUrl = String(formData.get("imageUrl") ?? "") const imageUrl = sanitizeField(formData.get("imageUrl"));
.normalize("NFC") const buttonText = sanitizeField(formData.get("buttonText"));
.trim() const buttonUrl = sanitizeField(formData.get("buttonUrl"));
.slice(0, 255); const buttonColor = sanitizeField(formData.get("buttonColor"), 16) || "#eeb425";
const buttonText = String(formData.get("buttonText") ?? "") const buttonBorderColor = sanitizeField(formData.get("buttonBorderColor"), 16) || "#facc15";
.normalize("NFC")
.trim()
.slice(0, 255);
const buttonUrl = String(formData.get("buttonUrl") ?? "")
.normalize("NFC")
.trim()
.slice(0, 255);
const buttonColor =
String(formData.get("buttonColor") ?? "")
.normalize("NFC")
.trim()
.slice(0, 16) || "#eeb425";
const buttonBorderColor =
String(formData.get("buttonBorderColor") ?? "")
.normalize("NFC")
.trim()
.slice(0, 16) || "#facc15";
try { try {
await prisma.websiteHelpCenterCategories.update({ await prisma.websiteHelpCenterCategories.update({
+1 -2
View File
@@ -2,6 +2,7 @@
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { useCallback, useEffect, useRef, useState } from "react"; import { useCallback, useEffect, useRef, useState } from "react";
import { useEventSource } from "@/lib/use-event-source";
/** /**
* Fixed bottom-right radio player widget — the Next.js port of AtomCMS's * Fixed bottom-right radio player widget — the Next.js port of AtomCMS's
@@ -135,8 +136,6 @@ function parseListeners(data: unknown): number | null {
return null; return null;
} }
import { useEventSource } from "@/lib/use-event-source";
export default function RadioPlayer() { export default function RadioPlayer() {
const audioRef = useRef<HTMLAudioElement | null>(null); const audioRef = useRef<HTMLAudioElement | null>(null);
+1
View File
@@ -1,3 +1,4 @@
// TODO: Check of dit bestand weg kan — uitsluitend gebruikt door eigen test
export interface AdminMutationNotice { export interface AdminMutationNotice {
tone: "ok" | "danger"; tone: "ok" | "danger";
label: "Saved" | "Error"; label: "Saved" | "Error";
+1
View File
@@ -1,3 +1,4 @@
// TODO: Check of dit bestand weg kan — uitsluitend gebruikt door eigen test
import type { AuthorizationActor } from "@/lib/admin/authorization-policy"; import type { AuthorizationActor } from "@/lib/admin/authorization-policy";
export interface RankAuthorityDb { export interface RankAuthorityDb {
+1
View File
@@ -1,3 +1,4 @@
// TODO: Check of dit bestand weg kan — uitsluitend gebruikt door eigen test
import { isStaff } from "@/lib/admin/is-staff"; import { isStaff } from "@/lib/admin/is-staff";
export interface StaffUserRecord { export interface StaffUserRecord {
+1 -1
View File
@@ -30,7 +30,7 @@ export function apiValidationError(zodError: z.ZodError) {
); );
} }
/** Centralized error handler for API routes */ // TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export function handleApiError(error: unknown): Response { export function handleApiError(error: unknown): Response {
if (error instanceof ApiError) { if (error instanceof ApiError) {
return apiError(error.message, error.status); return apiError(error.message, error.status);
+1
View File
@@ -16,6 +16,7 @@ export function cached<T>(
}); });
} }
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export function bustCache(key: string): void { export function bustCache(key: string): void {
store.delete(key); store.delete(key);
} }
+1
View File
@@ -49,6 +49,7 @@ export class RateLimitError extends DomainError {
} }
} }
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export class ConflictError extends DomainError { export class ConflictError extends DomainError {
constructor(message: string) { constructor(message: string) {
super(message, 409); super(message, 409);
+3
View File
@@ -30,6 +30,7 @@ export function runWithStore<T>(store: RequestStore, fn: () => T): T {
return als.run(store, fn); return als.run(store, fn);
} }
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export function getRequestStore(): RequestStore | null { export function getRequestStore(): RequestStore | null {
return als.getStore() ?? null; return als.getStore() ?? null;
} }
@@ -38,6 +39,7 @@ export function getRequestId(): RequestId {
return als.getStore()?.requestId ?? generateRequestId(); return als.getStore()?.requestId ?? generateRequestId();
} }
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export function getClientIp(): IpAddress { export function getClientIp(): IpAddress {
return als.getStore()?.ip ?? ("0.0.0.0" as IpAddress); return als.getStore()?.ip ?? ("0.0.0.0" as IpAddress);
} }
@@ -47,6 +49,7 @@ export function setContextUserId(userId: UserId): void {
if (store) store.userId = userId; if (store) store.userId = userId;
} }
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export function elapsed(): number { export function elapsed(): number {
const store = als.getStore(); const store = als.getStore();
return store ? Date.now() - store.startedAt : 0; return store ? Date.now() - store.startedAt : 0;
+11
View File
@@ -182,6 +182,15 @@ export function canonicalize(input: string): string {
return input.normalize("NFC").trim(); return input.normalize("NFC").trim();
} }
/** Normalize, trim and truncate a form field value to maxLen (default 255). */
export function sanitizeField(
value: FormDataEntryValue | null,
maxLen = 255,
): string {
const s = canonicalize(String(value ?? ""));
return s.slice(0, maxLen);
}
const INVALID_FILENAME_CHARS = /[<>:"/\\|?*]/; const INVALID_FILENAME_CHARS = /[<>:"/\\|?*]/;
function removeControlChars(s: string): string { function removeControlChars(s: string): string {
@@ -193,6 +202,7 @@ function removeControlChars(s: string): string {
return result; return result;
} }
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export function sanitizeFilename(name: string): string { export function sanitizeFilename(name: string): string {
return removeControlChars( return removeControlChars(
name name
@@ -212,6 +222,7 @@ export function canonicalizeFormValue(
return maxLen ? s.slice(0, maxLen) : s; return maxLen ? s.slice(0, maxLen) : s;
} }
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export function canonicalizeFormData( export function canonicalizeFormData(
formData: FormData, formData: FormData,
fields: Record<string, number | undefined>, fields: Record<string, number | undefined>,
+1
View File
@@ -1,3 +1,4 @@
// TODO: Check of dit bestand weg kan — uitsluitend gebruikt door eigen test
import { access, readdir, readFile } from "node:fs/promises"; import { access, readdir, readFile } from "node:fs/promises";
import { dirname, extname, join, relative, resolve, sep } from "node:path"; import { dirname, extname, join, relative, resolve, sep } from "node:path";
+11
View File
@@ -1,35 +1,42 @@
import type { Variants } from "framer-motion"; import type { Variants } from "framer-motion";
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export const fadeIn: Variants = { export const fadeIn: Variants = {
hidden: { opacity: 0 }, hidden: { opacity: 0 },
visible: { opacity: 1, transition: { duration: 0.4 } }, visible: { opacity: 1, transition: { duration: 0.4 } },
}; };
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export const fadeInUp: Variants = { export const fadeInUp: Variants = {
hidden: { opacity: 0, y: 20 }, hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0, transition: { duration: 0.4 } }, visible: { opacity: 1, y: 0, transition: { duration: 0.4 } },
}; };
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export const fadeInDown: Variants = { export const fadeInDown: Variants = {
hidden: { opacity: 0, y: -12 }, hidden: { opacity: 0, y: -12 },
visible: { opacity: 1, y: 0, transition: { duration: 0.3 } }, visible: { opacity: 1, y: 0, transition: { duration: 0.3 } },
}; };
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export const fadeInLeft: Variants = { export const fadeInLeft: Variants = {
hidden: { opacity: 0, x: -20 }, hidden: { opacity: 0, x: -20 },
visible: { opacity: 1, x: 0, transition: { duration: 0.35 } }, visible: { opacity: 1, x: 0, transition: { duration: 0.35 } },
}; };
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export const fadeInRight: Variants = { export const fadeInRight: Variants = {
hidden: { opacity: 0, x: 20 }, hidden: { opacity: 0, x: 20 },
visible: { opacity: 1, x: 0, transition: { duration: 0.35 } }, visible: { opacity: 1, x: 0, transition: { duration: 0.35 } },
}; };
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export const scaleIn: Variants = { export const scaleIn: Variants = {
hidden: { opacity: 0, scale: 0.95 }, hidden: { opacity: 0, scale: 0.95 },
visible: { opacity: 1, scale: 1, transition: { duration: 0.25 } }, visible: { opacity: 1, scale: 1, transition: { duration: 0.25 } },
}; };
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export const slideUp: Variants = { export const slideUp: Variants = {
hidden: { opacity: 0, y: 30 }, hidden: { opacity: 0, y: 30 },
visible: { visible: {
@@ -39,6 +46,7 @@ export const slideUp: Variants = {
}, },
}; };
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export const staggerContainer: Variants = { export const staggerContainer: Variants = {
hidden: {}, hidden: {},
visible: { visible: {
@@ -49,6 +57,7 @@ export const staggerContainer: Variants = {
}, },
}; };
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export const staggerItem: Variants = { export const staggerItem: Variants = {
hidden: { opacity: 0, y: 16 }, hidden: { opacity: 0, y: 16 },
visible: { opacity: 1, y: 0, transition: { duration: 0.35 } }, visible: { opacity: 1, y: 0, transition: { duration: 0.35 } },
@@ -103,12 +112,14 @@ export const modalContentVariants: Variants = {
exit: { opacity: 0, scale: 0.95, y: 10, transition: { duration: 0.15 } }, exit: { opacity: 0, scale: 0.95, y: 10, transition: { duration: 0.15 } },
}; };
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export const hoverScale = { export const hoverScale = {
whileHover: { scale: 1.03 }, whileHover: { scale: 1.03 },
whileTap: { scale: 0.97 }, whileTap: { scale: 0.97 },
transition: { type: "spring" as const, stiffness: 400, damping: 17 }, transition: { type: "spring" as const, stiffness: 400, damping: 17 },
}; };
// TODO: Check of dit weg kan — niet geïmporteerd in de codebase
export const hoverLift = { export const hoverLift = {
whileHover: { y: -3, transition: { duration: 0.2 } }, whileHover: { y: -3, transition: { duration: 0.2 } },
whileTap: { y: 0 }, whileTap: { y: 0 },
+1 -3
View File
@@ -33,9 +33,7 @@ export async function redisCache<T>(
return fresh; return fresh;
} }
/** // TODO: Check of dit weg kan — niet geïmporteerd in de codebase
* Invalidate a cached key. No-op if Redis is unavailable.
*/
export async function invalidateCache(key: string): Promise<void> { export async function invalidateCache(key: string): Promise<void> {
if (!redis) return; if (!redis) return;
try { try {