51 lines
2.6 KiB
Python
51 lines
2.6 KiB
Python
"""Workspaces und Mitgliedschaften (→ Konzept 6)."""
|
|
|
|
from datetime import datetime
|
|
from typing import Any
|
|
|
|
from sqlalchemy import JSON, ForeignKey, String, Text
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from app.core.database import Base, now
|
|
|
|
# admin: verwaltet den Workspace und entscheidet Anträge; approver (Freigeber): entscheidet Anträge
|
|
ROLES = ("admin", "approver", "member")
|
|
APPROVER_ROLES = ("admin", "approver")
|
|
ROLE_LABELS = {"admin": "Admin", "approver": "Freigeber", "member": "Mitglied"}
|
|
# Freigabemodus (→ Konzept 10.3): risikobasiert oder jede Schreibaktion nach außen
|
|
APPROVAL_MODES = ("risk", "all_writes")
|
|
|
|
|
|
class Workspace(Base):
|
|
__tablename__ = "workspaces"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
# Jeder Workspace gehört genau einem Team (→ Konzept 5.4)
|
|
team_id: Mapped[int] = mapped_column(ForeignKey("teams.id"), index=True)
|
|
name: Mapped[str] = mapped_column(String(200))
|
|
description: Mapped[str] = mapped_column(Text, default="")
|
|
approval_mode: Mapped[str] = mapped_column(String(20), default="risk")
|
|
# Spätere Anbindungen (→ Konzept 7.6, 7.9); hier nur Referenzen
|
|
munin_key_ref: Mapped[str | None] = mapped_column(String(200))
|
|
hugin_project: Mapped[str | None] = mapped_column(String(64))
|
|
# Leer = Standardmodell der Plattform (→ Konzept 8.1)
|
|
model_id: Mapped[int | None] = mapped_column(ForeignKey("models.id", ondelete="SET NULL"))
|
|
settings: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict)
|
|
created_by: Mapped[int] = mapped_column(ForeignKey("users.id"))
|
|
created: Mapped[datetime] = mapped_column(default=now)
|
|
# Webhook für Benachrichtigungen (Teams/Slack), verschlüsselt; Hint = Host zur Anzeige
|
|
webhook: Mapped[str | None] = mapped_column(Text)
|
|
webhook_hint: Mapped[str] = mapped_column(String(40), default="", server_default="")
|
|
# Papierkorb: gesetzt = gelöscht, aber noch wiederherstellbar bis zur endgültigen Löschung
|
|
# Speicherkontingent für Uploads in MB; leer = AIW_WORKSPACE_STORAGE_MB
|
|
storage_limit_mb: Mapped[int | None]
|
|
deleted: Mapped[datetime | None] = mapped_column(index=True)
|
|
deleted_by: Mapped[int | None] = mapped_column(ForeignKey("users.id"))
|
|
|
|
|
|
class WorkspaceMembership(Base):
|
|
__tablename__ = "workspace_memberships"
|
|
|
|
workspace_id: Mapped[int] = mapped_column(ForeignKey("workspaces.id", ondelete="CASCADE"), primary_key=True)
|
|
user_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"), primary_key=True, index=True)
|
|
role: Mapped[str] = mapped_column(String(20), default="member")
|