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.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
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();
|
||||
}
|
||||
Reference in New Issue
Block a user