Files
timemaster/backend/app/schemas/kiosk_auth.py
T
patrickandClaude Sonnet 5 2ce363c422 feat(kiosk): Stempel-Endpunkte für Kiosk-Sessions (fehlten bisher komplett)
Login (PIN/NFC/QR/Liste) lieferte einen session_token, aber es gab keinen
Endpunkt der ihn tatsächlich zum Stempeln nutzt (X-Kiosk-Session-Token war
nur als Konzept in kiosk_session_service dokumentiert, nirgends verdrahtet).

Neu: POST /kiosk/stamp/{in,out,break-start,break-end,status}. Gerät wird
weiterhin per Ed25519 verifiziert (verify_kiosk_request), zusätzlich validiert
_user_from_session() dass der session_token zu genau diesem Gerät gehört und
der User noch aktiv/in der richtigen Firma ist. Reuse von time_service
(stamp_in/out/break_start/break_end/get_today), source=KIOSK.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gis16MnuwkYcivLrSxK1pD
2026-08-27 13:32:46 +02:00

64 lines
1.9 KiB
Python

"""Schemas für Kiosk-User-Authentifizierung."""
import uuid
from pydantic import BaseModel, Field
class KioskPinLoginRequest(BaseModel):
"""Login via Personalnummer + PIN."""
personnel_number: str = Field(..., min_length=1)
pin: str = Field(..., min_length=4, max_length=16)
class KioskNfcLoginRequest(BaseModel):
"""Login via NFC-UID + Pflicht-PIN (Zweitfaktor, da UID allein klonbar ist)."""
nfc_uid: str = Field(..., min_length=1, max_length=64)
pin: str = Field(..., min_length=4, max_length=16)
class KioskQrLoginRequest(BaseModel):
"""Login via QR-Code (enthält verschlüsselten Token)."""
qr_token: str = Field(..., min_length=1)
class KioskSessionResponse(BaseModel):
"""Antwort nach erfolgreichem Kiosk-Login."""
session_token: str
user_id: uuid.UUID
user_name: str # "Max M." (Vorname + Nachname abgekürzt für Datenschutz)
expires_in_seconds: int # 900 (15 min)
auth_method: str # "pin" | "nfc" | "qr" | "list"
class KioskUserListEntry(BaseModel):
"""Minimale User-Info für Auswahl in der Mitarbeiterliste."""
id: uuid.UUID
display_name: str # "Max M." oder Kürzel
class KioskUserListResponse(BaseModel):
users: list[KioskUserListEntry]
class KioskStampRequest(BaseModel):
"""Body für Stempel-Aktionen. session_token identifiziert den eingeloggten
Mitarbeiter (aus /auth/pin|nfc|qr|list), das Gerät ist bereits über die
Ed25519-Signatur (verify_kiosk_request) authentifiziert."""
session_token: str = Field(..., min_length=1)
note: str | None = None
class KioskStampResponse(BaseModel):
entry_id: uuid.UUID
status: str # "stamped_in" | "stamped_out" | "break_started" | "break_ended"
warnings: list[str] = []
class KioskStampStatusRequest(BaseModel):
session_token: str = Field(..., min_length=1)
class KioskStampStatusResponse(BaseModel):
stamped_in: bool
on_break: bool
start_time: str | None = None