Erste Produktivversion

This commit is contained in:
2026-08-08 20:31:58 +02:00
parent d8ded2816d
commit 7b21e2d1b4
110 changed files with 18170 additions and 644 deletions

View File

@@ -0,0 +1,83 @@
from datetime import datetime
from typing import Literal
from pydantic import BaseModel, EmailStr, Field
class AdminUserOut(BaseModel):
id: str
email: EmailStr
display_name: str | None
is_admin: bool
is_active: bool
verified: bool
# Nie angemeldet, oder seit wann nicht mehr
last_seen_at: datetime | None
deactivated_at: datetime | None
created_at: datetime
# Wie viele Listen gehoeren dem Konto, in wie vielen ist es Mitglied
owned_lists: int
memberships: int
# Laeuft gerade eine Adressaenderung?
pending_email: str | None = None
class AdminStatsOut(BaseModel):
total: int
active: int
inactive: int
unverified: int
admins: int
# Konten, die beim naechsten Durchlauf deaktiviert bzw. geloescht
# wuerden - damit die Automatik nicht ueberrascht.
due_deactivation: int
due_deletion: int
class UserCreateIn(BaseModel):
email: EmailStr
display_name: str | None = Field(default=None, max_length=80)
is_admin: bool = False
class EmailChangeIn(BaseModel):
new_email: EmailStr
class DeleteUserIn(BaseModel):
"""Wie mit den Listen des Kontos verfahren werden soll.
"refuse" bricht ab, wenn dem Konto Listen gehoeren - die
Voreinstellung, damit nichts unbeabsichtigt verschwindet.
"handover" uebertraegt geteilte Listen an das diensthaelteste andere
Mitglied und loescht nur die, die niemand sonst nutzt.
"""
lists: Literal["refuse", "handover"] = "refuse"
# Sicherheitsabfrage: die Adresse muss zum Konto passen
confirm_email: EmailStr
class AdminSettingsOut(BaseModel):
allow_self_registration: bool
locked_by_env: bool
# 0 = abgeschaltet
auto_deactivate_months: int
auto_delete_months: int
class AdminSettingsIn(BaseModel):
allow_self_registration: bool | None = None
auto_deactivate_months: int | None = Field(default=None, ge=0, le=600)
auto_delete_months: int | None = Field(default=None, ge=0, le=600)
class WelcomeCompleteIn(BaseModel):
token: str = Field(max_length=128)
password: str = Field(min_length=12, max_length=256)
display_name: str | None = Field(default=None, max_length=80)
class WelcomePreviewOut(BaseModel):
email: EmailStr
display_name: str | None