Files
florian.wilde 6f78762e27 Letzte Supabase-Erwähnungen aus aktiver Doku/Kommentaren entfernt
README.md, db/migrations/0001_init.sql, lib/auth/webauthn-config.ts,
lib/branding.ts nannten Supabase noch in Kommentaren, die erklären,
was diese Stellen ersetzen. Umformuliert, ohne den alten Anbieter beim
Namen zu nennen. CHANGELOG.md bleibt unverändert – die Erwähnungen dort
sind historischer Bestand (u. a. der v1.5.0-Eintrag über die
Supabase-Ablösung selbst) und sollen als Zeitdokument stehen bleiben.
2026-07-18 12:21:21 +02:00

49 lines
1.7 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import "server-only";
import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
import path from "node:path";
// Logo/Favicon liegen als Dateien in einem lokalen Verzeichnis
// (Docker-Volume in Produktion, s. docker-compose.yml).
export function brandingDir(): string {
// turbopackIgnore: process.cwd() ist hier dynamisch, aber der Pfad
// bleibt statisch unter "data/branding" – ohne den Kommentar versucht
// Turbopack sonst, das gesamte Projektverzeichnis nach möglichen
// dynamischen require()-Zielen zu durchsuchen (harmlos, aber unnötig).
return (
process.env.BRANDING_DIR ??
path.join(/*turbopackIgnore: true*/ process.cwd(), "data", "branding")
);
}
// Nur einfache, von uns selbst vergebene Dateinamen zulassen
// (`${kind}-${Date.now()}.${ext}`) – verhindert Path-Traversal über
// Dateinamen aus der DB-Spalte logo_path/favicon_path.
const SAFE_FILENAME = /^[a-zA-Z0-9_.-]+$/;
export function isSafeFilename(filename: string): boolean {
return SAFE_FILENAME.test(filename) && !filename.includes("..");
}
export async function saveBrandingFile(filename: string, data: Buffer): Promise<void> {
const dir = brandingDir();
await mkdir(dir, { recursive: true });
await writeFile(path.join(dir, filename), data);
}
export async function readBrandingFile(filename: string): Promise<Buffer | null> {
if (!isSafeFilename(filename)) return null;
try {
return await readFile(path.join(brandingDir(), filename));
} catch {
return null;
}
}
export async function removeBrandingFile(filename: string): Promise<void> {
try {
await unlink(path.join(brandingDir(), filename));
} catch (err) {
if ((err as NodeJS.ErrnoException).code !== "ENOENT") throw err;
}
}