- admin_email bzw. reseller email optional; ohne E-Mail wird interne Login- Kennung (<name>@<slug>.local) + einmaliges Temp-Passwort erzeugt, Account sofort aktiv, kein Mailversand - TenantOut/ResellerOut: initial_password (einmalig) ergänzt - LoginRequest.email: str statt EmailStr (Kennung muss kein zustellbares Postfach sein; .local-Domains sind sonst nicht einloggbar) - Frontend: E-Mail-Felder optional, CredDialog zeigt Login + Temp-Passwort einmalig - Test: Anlage ohne E-Mail + Login mit generierten Zugangsdaten; 173/173 grün Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
77 lines
2.5 KiB
Python
77 lines
2.5 KiB
Python
"""Schemas für Reseller-Selbstverwaltung und SUPER_ADMIN-Mandantenübersicht.
|
||
|
||
Wichtig (DSGVO): Reseller sehen ausschließlich Firmen-Stammdaten und Kennzahlen
|
||
(z.B. Nutzeranzahl) – KEINE personenbezogenen Zeit-/Abwesenheitsdaten.
|
||
"""
|
||
import uuid
|
||
from datetime import datetime
|
||
|
||
from pydantic import BaseModel, EmailStr, Field
|
||
|
||
|
||
class TenantOut(BaseModel):
|
||
"""Eine Firma als Mandant – für Reseller- und SUPER_ADMIN-Übersicht."""
|
||
model_config = {"from_attributes": True}
|
||
|
||
id: uuid.UUID
|
||
name: str
|
||
slug: str
|
||
plan: str
|
||
is_active: bool
|
||
country: str
|
||
reseller_id: uuid.UUID | None = None
|
||
reseller_name: str | None = None
|
||
user_count: int = 0
|
||
active_user_count: int = 0
|
||
admin_email: str | None = None
|
||
created_at: datetime | None = None
|
||
# Nur bei Anlage ohne E-Mail befüllt: einmalig anzuzeigende Zugangsdaten
|
||
# (Login-Kennung = admin_email, Passwort hier). Sonst None.
|
||
initial_password: str | None = None
|
||
|
||
|
||
class TenantCreate(BaseModel):
|
||
"""Neue Firma anlegen (durch Reseller oder SUPER_ADMIN).
|
||
|
||
Es wird automatisch ein erster COMPANY_ADMIN angelegt. Mit admin_email wird
|
||
eine Einladung verschickt; ohne admin_email wird eine interne Login-Kennung
|
||
plus Temporär-Passwort erzeugt und einmalig zurückgegeben (kein Mailversand).
|
||
"""
|
||
name: str = Field(min_length=2, max_length=255)
|
||
country: str = Field(default="DE", max_length=10)
|
||
plan: str = Field(default="trial", max_length=50)
|
||
admin_email: EmailStr | None = None
|
||
admin_first_name: str = Field(min_length=1, max_length=100)
|
||
admin_last_name: str = Field(min_length=1, max_length=100)
|
||
|
||
|
||
class TenantUpdate(BaseModel):
|
||
name: str | None = Field(None, min_length=2, max_length=255)
|
||
plan: str | None = Field(None, max_length=50)
|
||
is_active: bool | None = None
|
||
|
||
|
||
class TenantAssignReseller(BaseModel):
|
||
"""SUPER_ADMIN: Firma einem Reseller zuordnen (oder lösen mit null)."""
|
||
reseller_id: uuid.UUID | None = None
|
||
|
||
|
||
class ResellerOut(BaseModel):
|
||
model_config = {"from_attributes": True}
|
||
|
||
id: uuid.UUID
|
||
email: str
|
||
first_name: str
|
||
last_name: str
|
||
is_active: bool
|
||
created_at: datetime | None = None
|
||
company_count: int = 0
|
||
# Nur bei Anlage ohne E-Mail befüllt: einmalig anzuzeigendes Temporär-Passwort.
|
||
initial_password: str | None = None
|
||
|
||
|
||
class ResellerCreate(BaseModel):
|
||
email: EmailStr | None = None
|
||
first_name: str = Field(min_length=1, max_length=100)
|
||
last_name: str = Field(min_length=1, max_length=100)
|