""" SQLAlchemy-Datenmodelle für lokale RBAC- und Projektzuweisung. Alle Nutzeridentitäten stammen aus Zitadel (``zitadel_user_id`` = OIDC ``sub``-Claim). Die lokalen Tabellen regeln nur die Autorisierung – nie die Authentifizierung. :author: :date: 2026-06-17 :version: 0.1 """ from datetime import datetime from .database import db class User(db.Model): __tablename__ = "users" zitadel_user_id = db.Column(db.String(128), primary_key=True) email = db.Column(db.String(256), nullable=False) global_role = db.Column(db.String(64), nullable=False) class Client(db.Model): __tablename__ = "clients" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(256), nullable=False) projects = db.relationship("Project", back_populates="client") class Project(db.Model): __tablename__ = "projects" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(256), nullable=False) client_id = db.Column(db.Integer, db.ForeignKey("clients.id"), nullable=False) client = db.relationship("Client", back_populates="projects") notes = db.relationship("Note", back_populates="project", order_by="Note.created_at.desc()") class ProjectMitarbeiterMapping(db.Model): __tablename__ = "project_mitarbeiter" user_id = db.Column(db.String(128), db.ForeignKey("users.zitadel_user_id"), primary_key=True) project_id = db.Column(db.Integer, db.ForeignKey("projects.id"), primary_key=True) class ProjectKundenMapping(db.Model): __tablename__ = "project_kunden" user_id = db.Column(db.String(128), db.ForeignKey("users.zitadel_user_id"), primary_key=True) project_id = db.Column(db.Integer, db.ForeignKey("projects.id"), primary_key=True) class Note(db.Model): __tablename__ = "notes" id = db.Column(db.Integer, primary_key=True) text = db.Column(db.Text, nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) user_id = db.Column(db.String(128), db.ForeignKey("users.zitadel_user_id"), nullable=False) project_id = db.Column(db.Integer, db.ForeignKey("projects.id"), nullable=False) project = db.relationship("Project", back_populates="notes")