Files
MABEA/backend/app/models/permission.py
T
patrickandClaude Sonnet 5 c56fc285de
CI / backend-tests (push) Failing after 1m55s
CI / frontend-build (push) Successful in 19s
feat(rollen): granulares Rechte-System (Roadmap Phase 6, letztes Modul)
Additiv neben dem bestehenden 4-Rollen-System (mitarbeiter/material-
verantwortlicher/leitungsverantwortlicher/administration bleiben unverändert,
kein Breaking Change): Admin kann jetzt eigene Rollen (z.B. "Materialwart",
"Helfer" aus der Ursprungs-Anforderung) mit frei wählbaren Einzelrechten aus
einem Berechtigungs-Katalog anlegen und Benutzern zuweisen - auch Benutzern
ganz ohne feste RolleTyp-Zuordnung.

Neue Tabellen: berechtigung (Katalog), rolle (custom, admin-anlegbar),
rolle_berechtigung (M:N), benutzer_rolle_zuordnung (M:N, eigene Tabelle statt
Wiederverwendung des ENUM-basierten benutzer_rolle).

require_roles_or_permission() kombiniert beide Systeme: bestehende feste
Rollen ODER eine passende granulare Berechtigung. Auf die vom Nutzer genannten
Beispiel-Endpunkte angewendet: Material anlegen/bearbeiten, Lagerbewegung
durchführen, Mangel melden/lesen/bearbeiten, Prüfung durchführen - weitere
Endpunkte folgen bei Bedarf nach demselben Muster (require_permission()/
require_roles_or_permission() stehen jetzt als Bausteine bereit).

Neue Endpunkte: GET /berechtigungen, CRUD /rollen, PUT/DELETE
/rollen/{id}/berechtigungen/{id}, PUT/DELETE /benutzer/{id}/rollen/{id}.

Frontend: neuer Admin-Tab "Rollen & Rechte" (Rolle anlegen, Rechte togglen,
Benutzer zuweisen/entfernen).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KC8HYvv6UkCVYheYiTw9DD
2026-09-05 14:07:03 +02:00

49 lines
1.9 KiB
Python

from sqlalchemy import ForeignKey, String
from sqlalchemy.orm import Mapped, mapped_column
from app.db.base import Base
class Berechtigung(Base):
"""Roadmap Phase 6: Katalog einzelner Rechte (z.B. "material.erstellen").
Fest im Code definiert (welche Endpunkte welches Recht prüfen), aber wer
welche Berechtigung über welche Rolle bekommt, ist frei konfigurierbar."""
__tablename__ = "berechtigung"
id: Mapped[int] = mapped_column(primary_key=True)
schluessel: Mapped[str] = mapped_column(String, unique=True, nullable=False)
beschreibung: Mapped[str] = mapped_column(String, nullable=False)
class Rolle(Base):
"""Vom Admin frei anlegbare Rolle (z.B. "Materialwart", "Helfer") - additiv
neben dem bestehenden festen 4-Rollen-System (RolleTyp), nicht dessen
Ersatz. Ein Benutzer kann beides gleichzeitig haben."""
__tablename__ = "rolle"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String, unique=True, nullable=False)
beschreibung: Mapped[str | None] = mapped_column(String)
class RolleBerechtigung(Base):
__tablename__ = "rolle_berechtigung"
rolle_id: Mapped[int] = mapped_column(ForeignKey("rolle.id", ondelete="CASCADE"), primary_key=True)
berechtigung_id: Mapped[int] = mapped_column(
ForeignKey("berechtigung.id", ondelete="CASCADE"), primary_key=True
)
class BenutzerRolleZuordnung(Base):
"""M:N Benutzer<->Rolle (neues System) - eigene Tabelle statt
Wiederverwendung von benutzer_rolle, dessen rolle-Spalte ein fester ENUM
ist und keine FK auf frei anlegbare rolle-Zeilen erlaubt."""
__tablename__ = "benutzer_rolle_zuordnung"
benutzer_id: Mapped[int] = mapped_column(ForeignKey("benutzer.id", ondelete="CASCADE"), primary_key=True)
rolle_id: Mapped[int] = mapped_column(ForeignKey("rolle.id", ondelete="CASCADE"), primary_key=True)