Files
qrcode-generator/src/lib/settings.ts
T
Florian Wilde 46e7eb0b59 Sprechende Kurz-Links: selbst vergeben, aendern, frueher gueltig halten
Schliesst Issue #1. Der Wunsch betraf den Kurz-Link, nicht das Ziel: Er soll
sich von Anfang an bestimmen und spaeter aendern lassen.

Beim Anlegen gibt es dafuer ein Feld, im Bearbeiten-Dialog laesst er sich
aendern. Erlaubt sind Kleinbuchstaben, Ziffern, Bindestriche und „/" als
Trenner — damit sind Adressen wie kunde-a/sommer moeglich. Umlaute bleiben
draussen, weil sie in Adressen unleserlich kodiert werden; Gross- und
Kleinschreibung ist beim Aufrufen egal.

Beim Aendern bleibt die vorherige Adresse gueltig. Das ist der Kern: Auf
gedruckten Codes steht die alte, und genau deren Bestand ist der Sinn eines
dynamischen Codes. Frueher vergebene Adressen stehen im Dialog und lassen
sich einzeln freigeben — fuer den Tippfehler, mit dem noch nichts gedruckt
ist. Solange eine Adresse gehalten wird, kann sie kein anderer Code
uebernehmen; sonst liessen sich fremde gedruckte Codes umlenken.

Vergeben und Aendern ist standardmaessig Administratoren vorbehalten. Ein
Kurz-Link ist eine oeffentliche Adresse, und wer ihn aendert, kann Aushaenge
entwerten. Unter Verwaltung -> Einstellungen laesst sich das fuer Bearbeiter
freigeben; ohne das Recht erscheint das Feld gar nicht, Codes anlegen und
deren Ziel aendern geht weiterhin. Eigene Aktion in der Policy statt Teil von
codes:update, weil sie mehr wiegt.

Technisch: /r und /s sind Sammelrouten, weil ein Kurz-Link „/" enthalten
darf. Die Eindeutigkeit gilt zusaetzlich auf der kleingeschriebenen Form; die
Migration bricht ab, falls der Bestand das nicht zulaesst, statt still Daten
zu verlieren. Der bestehende exakte Index bleibt — er traegt den haeufigen
Fall, den gescannten Code.
2026-08-17 10:41:57 +02:00

46 lines
1.3 KiB
TypeScript

import "server-only";
import { prisma } from "@/lib/db";
export type InstanceSettings = {
/** Dürfen Bearbeiter den Kurz-Link selbst vergeben und ändern? */
editorsMaySetSlug: boolean;
};
export const DEFAULT_SETTINGS: InstanceSettings = {
editorsMaySetSlug: false,
};
/**
* Bewusst ohne Zwischenspeicher — dieselbe Erfahrung wie beim
* Erscheinungsbild: API-Route und Seite laufen in getrennten Modulinstanzen,
* ein Puffer wäre nach dem Speichern veraltet. Es ist eine Abfrage auf den
* Primärschlüssel einer Tabelle mit einer einzigen Zeile.
*/
export async function getSettings(): Promise<InstanceSettings> {
try {
const zeile = await prisma.instanceSetting.findUnique({
where: { id: "instance" },
});
return zeile
? { editorsMaySetSlug: zeile.editorsMaySetSlug }
: DEFAULT_SETTINGS;
} catch (error) {
// Ein Datenbankproblem darf nicht dazu führen, dass keine Seite erscheint.
// Im Zweifel gilt die zurückhaltendere Einstellung.
console.error("Einstellungen konnten nicht geladen werden:", error);
return DEFAULT_SETTINGS;
}
}
export async function saveSettings(
update: Partial<InstanceSettings>,
): Promise<InstanceSettings> {
await prisma.instanceSetting.upsert({
where: { id: "instance" },
update,
create: { id: "instance", ...update },
});
return getSettings();
}