Files
ProxLedger/src/server/actions/hosts.ts
T
florian.wildeandClaude Opus 5 7775b6211f feat(security): Haertung nach OWASP Top 10 (#024)
Drei echte Luecken gefunden und geschlossen:

1. Die 27 Server Actions verliessen sich allein auf proxy.ts. Jede prueft die
   Sitzung jetzt selbst und schlaegt gegen die Datenbank nach, ob das Konto
   noch gilt - damit lassen sich Sitzungen ueberhaupt erst widerrufen.
2. Der Anmelde-Endpunkt prueft die Herkunft des Formulars; vorher war
   Login-CSRF moeglich.
3. Content-Security-Policy mit Nonce je Anfrage und strict-dynamic.

Dazu: npm audit ist ohne Befund (mysql2 und deepmerge-ts per overrides
angehoben statt Prisma zurueckzustufen), eine Benutzerverwaltung fuer die
Kommandozeile und docs/sicherheit.md mit allem, was bewusst offen bleibt -
keine Rollen, keine Zwei-Faktor-Anmeldung.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 23:45:35 +02:00

48 lines
1.8 KiB
TypeScript

"use server";
import { revalidatePath } from "next/cache";
import { prisma } from "@/lib/db";
import { protokolliere } from "@/server/audit";
import { sitzungErforderlich } from "@/server/auth/sitzungspflicht";
import { hostsZuweisenService, ZuweisungsFehler } from "@/server/services/zuweisung";
import type { AktionsErgebnis } from "./kunden";
/** Weist mehrere Hosts in einem Schritt einem Kunden zu. */
export async function hostsZuweisen(_vorher: AktionsErgebnis, formular: FormData): Promise<AktionsErgebnis> {
await sitzungErforderlich();
const hostIds = formular.getAll("hostId").map(String).filter(Boolean);
const kundeId = formular.get("kundeId")?.toString() || null;
const standortId = formular.get("standortId")?.toString() || null;
try {
const { anzahl, kundenName } = await hostsZuweisenService(hostIds, kundeId, standortId);
revalidatePath("/hosts/nicht-zugeordnet");
revalidatePath("/hosts");
revalidatePath("/kunden");
revalidatePath(`/kunden/${kundeId}`);
revalidatePath("/");
return { erfolg: `${anzahl} Host${anzahl === 1 ? "" : "s"} ${kundenName} zugewiesen.` };
} catch (fehler) {
if (fehler instanceof ZuweisungsFehler) return { fehler: fehler.message };
throw fehler;
}
}
/** Hebt die Zuordnung eines einzelnen Hosts auf. */
export async function hostZuordnungAufheben(formular: FormData) {
await sitzungErforderlich();
const hostId = formular.get("hostId")?.toString();
if (!hostId) return;
await prisma.host.update({ where: { id: hostId }, data: { kundeId: null, standortId: null } });
await protokolliere("host.zuordnung_aufgehoben", "Host", hostId, {});
revalidatePath("/hosts");
revalidatePath("/hosts/nicht-zugeordnet");
revalidatePath(`/hosts/${hostId}`);
revalidatePath("/kunden");
revalidatePath("/");
}