Benutzerverwaltung, Firmenstamm und Rollenlegende
Die Verwaltung war bisher eine reine Anzeige. Sie gliedert sich jetzt in vier Reiter und ist handlungsfähig. Benutzer - Zugänge anlegen, bearbeiten, sperren und entsperren - Startkennwort wird erzeugt und genau einmal angezeigt, auf Wunsch zusätzlich per E-Mail versandt; es liegt nirgends im Klartext - Kennwort zurücksetzen beendet zugleich alle laufenden Sitzungen - Wer sich mit einem Startkennwort anmeldet, wird unmittelbar zur Vergabe eines eigenen Kennworts geführt; bis dahin weist ein Streifen im Kopfbereich darauf hin - Zugänge werden gesperrt, nicht gelöscht: Bautagebucheinträge, Prüfvermerke und Bescheinigungen müssen dauerhaft einer Person zuordenbar bleiben Aussperrschutz - der eigene Zugang lässt sich weder sperren noch die eigene Administration entziehen - es muss stets mindestens ein aktiver Administrationszugang bestehen - Firmen mit bestehenden Verträgen lassen sich nicht stilllegen Firmen - Stammdaten mit Art, Anschrift, Kreditorennummer und USt-IdNr., stilllegbar Rollen und Rechte - Legende aller Rollen, getrennt nach Auftraggeber- und Auftragnehmerseite - vollständige Rechtematrix, unmittelbar aus PERMISSIONS erzeugt und damit nicht von der Wirklichkeit im Code trennbar - Übersicht der Projektschalter und der fest verdrahteten Sperren Protokoll - Filter nach Aktion und Person, Blätterung, haftungsrelevante Vorgänge hervorgehoben Nebenbei behoben - next.config: "output: standalone" entfernt, weil es sich mit "next start" nicht verträgt; nicht mehr unterstützten eslint-Schlüssel entfernt - Unterlagen des Auftraggebers (*.xlsx) gehören nicht ins Repository Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
807b7ce541
commit
8af6b384ea
+3
-1
@@ -14,6 +14,7 @@ export type SessionUser = {
|
||||
email: string;
|
||||
name: string;
|
||||
isAdmin: boolean;
|
||||
mustChangePw: boolean;
|
||||
companyId: string | null;
|
||||
companyName: string | null;
|
||||
companyType: string | null;
|
||||
@@ -62,7 +63,7 @@ export async function login(email: string, password: string) {
|
||||
path: "/",
|
||||
expires: expiresAt,
|
||||
});
|
||||
return { ok: true as const };
|
||||
return { ok: true as const, kennwortWechseln: user.mustChangePw };
|
||||
}
|
||||
|
||||
export async function logout() {
|
||||
@@ -88,6 +89,7 @@ export async function getSessionUser(): Promise<SessionUser | null> {
|
||||
email: session.user.email,
|
||||
name: session.user.name,
|
||||
isAdmin: session.user.isAdmin,
|
||||
mustChangePw: session.user.mustChangePw,
|
||||
companyId: session.user.companyId,
|
||||
companyName: session.user.company?.name ?? null,
|
||||
companyType: session.user.company?.type ?? null,
|
||||
|
||||
@@ -87,6 +87,90 @@ export function assertCan(roles: Role[], permission: Permission) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Klartext für die Rechtelegende. Bewusst als `satisfies Record<Permission, …>`:
|
||||
* Wer oben ein Recht ergänzt, bekommt hier einen Übersetzungsfehler und kann es
|
||||
* nicht vergessen.
|
||||
*/
|
||||
export const PERMISSION_INFO = {
|
||||
"projekt.anlegen": { gruppe: "Projekt", label: "Projekt anlegen" },
|
||||
"projekt.bearbeiten": { gruppe: "Projekt", label: "Projektdaten und Einstellungen ändern" },
|
||||
"projekt.mitglieder": { gruppe: "Projekt", label: "Beteiligte und Rollen vergeben" },
|
||||
|
||||
"dokument.lesen": { gruppe: "Dokumente", label: "Dokumente lesen" },
|
||||
"dokument.hochladen": { gruppe: "Dokumente", label: "Dokumente einstellen", optional: "anDarfDokumente" },
|
||||
"dokument.freigeben": { gruppe: "Dokumente", label: "Dokumente prüfen und freigeben" },
|
||||
"dokument.loeschen": { gruppe: "Dokumente", label: "Dokumente löschen" },
|
||||
"dokument.intern": { gruppe: "Dokumente", label: "Interne und vertrauliche Unterlagen sehen" },
|
||||
|
||||
"ablage.lesen": { gruppe: "Ablagestruktur", label: "Dokumentationsstand einsehen", optional: "anSichtDokumentation" },
|
||||
"ablage.steuern": { gruppe: "Ablagestruktur", label: "Status und Zuständigkeit setzen" },
|
||||
|
||||
"bautagebuch.lesen": { gruppe: "Bautagebuch", label: "Bautagebuch lesen", optional: "anSichtBautagebuch" },
|
||||
"bautagebuch.schreiben": { gruppe: "Bautagebuch", label: "Bautagebuch führen" },
|
||||
"bautagebuch.gegenzeichnen": { gruppe: "Bautagebuch", label: "Bautagebuch gegenzeichnen" },
|
||||
|
||||
"vorgang.anlegen": { gruppe: "Meldungen", label: "Meldung anlegen" },
|
||||
"vorgang.bearbeiten": { gruppe: "Meldungen", label: "Meldung bearbeiten" },
|
||||
"vorgang.schliessen": { gruppe: "Meldungen", label: "Meldung schließen" },
|
||||
|
||||
"vertrag.lesen": { gruppe: "Verträge", label: "Verträge einsehen", optional: "anSichtVertrag" },
|
||||
"vertrag.bearbeiten": { gruppe: "Verträge", label: "Verträge und LV pflegen" },
|
||||
"nachtrag.pruefen": { gruppe: "Verträge", label: "Nachtrag prüfen und bewerten" },
|
||||
|
||||
"stunden.einreichen": { gruppe: "Stunden und Aufmaß", label: "Stundenlohnzettel einreichen" },
|
||||
"stunden.pruefen": { gruppe: "Stunden und Aufmaß", label: "Stunden zeilenweise anerkennen" },
|
||||
"aufmass.einreichen": { gruppe: "Stunden und Aufmaß", label: "Aufmaß einreichen" },
|
||||
"aufmass.pruefen": { gruppe: "Stunden und Aufmaß", label: "Aufmaß anerkennen" },
|
||||
|
||||
"rechnung.erfassen": { gruppe: "Rechnungsprüfung", label: "Rechnung erfassen" },
|
||||
"rechnung.lesen": { gruppe: "Rechnungsprüfung", label: "Rechnungen einsehen", optional: "anSichtRechnungen" },
|
||||
"rechnung.sachlich": { gruppe: "Rechnungsprüfung", label: "sachlich richtig bescheinigen" },
|
||||
"rechnung.rechnerisch": { gruppe: "Rechnungsprüfung", label: "rechnerisch richtig bescheinigen" },
|
||||
"rechnung.freigeben": { gruppe: "Rechnungsprüfung", label: "Zahlung freigeben" },
|
||||
|
||||
"chat.schreiben": { gruppe: "Kommunikation", label: "Nachrichten schreiben" },
|
||||
"chat.kanal.anlegen": { gruppe: "Kommunikation", label: "Kanäle anlegen" },
|
||||
|
||||
"admin.benutzer": { gruppe: "Administration", label: "Benutzerverwaltung" },
|
||||
"admin.firmen": { gruppe: "Administration", label: "Firmenstamm pflegen" },
|
||||
"admin.audit": { gruppe: "Administration", label: "Protokoll einsehen" },
|
||||
} as const satisfies Record<Permission, { gruppe: string; label: string; optional?: keyof ProjektOptionen }>;
|
||||
|
||||
export const PERMISSION_GRUPPEN = [
|
||||
"Projekt", "Dokumente", "Ablagestruktur", "Bautagebuch", "Meldungen",
|
||||
"Verträge", "Stunden und Aufmaß", "Rechnungsprüfung", "Kommunikation", "Administration",
|
||||
] as const;
|
||||
|
||||
export const ROLE_KURZ: Record<Role, string> = {
|
||||
ADMIN: "ADM",
|
||||
PROJEKTLEITER: "PL",
|
||||
BAUHERRENVERTRETER: "BHV",
|
||||
BAUUEBERWACHER: "BÜB",
|
||||
FACHBAUUEBERWACHER: "FBÜ",
|
||||
KAUFMANN: "KFM",
|
||||
PLANER: "PLA",
|
||||
AUFTRAGNEHMER: "AN",
|
||||
PRUEFER: "PRF",
|
||||
BETREIBER: "BTR",
|
||||
LESER: "LES",
|
||||
};
|
||||
|
||||
/** Auf welcher Seite des Bauvertrags eine Rolle steht. */
|
||||
export const ROLE_SEITE: Record<Role, "AG" | "AN" | "NEUTRAL"> = {
|
||||
ADMIN: "NEUTRAL",
|
||||
PROJEKTLEITER: "AG",
|
||||
BAUHERRENVERTRETER: "AG",
|
||||
BAUUEBERWACHER: "AG",
|
||||
FACHBAUUEBERWACHER: "AG",
|
||||
KAUFMANN: "AG",
|
||||
PLANER: "NEUTRAL",
|
||||
AUFTRAGNEHMER: "AN",
|
||||
PRUEFER: "NEUTRAL",
|
||||
BETREIBER: "NEUTRAL",
|
||||
LESER: "NEUTRAL",
|
||||
};
|
||||
|
||||
export const ROLE_LABEL: Record<Role, string> = {
|
||||
ADMIN: "Administration",
|
||||
PROJEKTLEITER: "Projektleitung (PL)",
|
||||
|
||||
Reference in New Issue
Block a user