# Copyright (c) 2025 Patrick Motsch # All rights reserved. """Security models: Token and AuthEvent.""" from typing import Optional from pydantic import BaseModel, Field, ConfigDict from modules.shared.attributeUtils import registerModelLabels from modules.shared.timeUtils import getUtcTimestamp from .datamodelUam import AuthAuthority from enum import Enum import uuid class TokenStatus(str, Enum): ACTIVE = "active" REVOKED = "revoked" class Token(BaseModel): id: Optional[str] = None userId: str authority: AuthAuthority connectionId: Optional[str] = Field( None, description="ID of the connection this token belongs to" ) tokenAccess: str tokenType: str = "bearer" expiresAt: float = Field( description="When the token expires (UTC timestamp in seconds)" ) tokenRefresh: Optional[str] = None createdAt: Optional[float] = Field( None, description="When the token was created (UTC timestamp in seconds)" ) status: TokenStatus = Field( default=TokenStatus.ACTIVE, description="Token status: active/revoked" ) revokedAt: Optional[float] = Field( None, description="When the token was revoked (UTC timestamp in seconds)" ) revokedBy: Optional[str] = Field( None, description="User ID who revoked the token (admin/self)" ) reason: Optional[str] = Field(None, description="Optional revocation reason") sessionId: Optional[str] = Field( None, description="Logical session grouping for logout revocation" ) mandateId: Optional[str] = Field( None, description="Mandate ID for tenant scoping of the token" ) model_config = ConfigDict(use_enum_values=True) registerModelLabels( "Token", {"en": "Token", "fr": "Jeton"}, { "id": {"en": "ID", "fr": "ID"}, "userId": {"en": "User ID", "fr": "ID utilisateur"}, "authority": {"en": "Authority", "fr": "Autorité"}, "connectionId": {"en": "Connection ID", "fr": "ID de connexion"}, "tokenAccess": {"en": "Access Token", "fr": "Jeton d'accès"}, "tokenType": {"en": "Token Type", "fr": "Type de jeton"}, "expiresAt": {"en": "Expires At", "fr": "Expire le"}, "tokenRefresh": {"en": "Refresh Token", "fr": "Jeton de rafraîchissement"}, "createdAt": {"en": "Created At", "fr": "Créé le"}, "status": {"en": "Status", "fr": "Statut"}, "revokedAt": {"en": "Revoked At", "fr": "Révoqué le"}, "revokedBy": {"en": "Revoked By", "fr": "Révoqué par"}, "reason": {"en": "Reason", "fr": "Raison"}, "sessionId": {"en": "Session ID", "fr": "ID de session"}, "mandateId": {"en": "Mandate ID", "fr": "ID de mandat"}, }, ) class AuthEvent(BaseModel): id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique ID of the auth event", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False}) userId: str = Field(description="ID of the user this event belongs to", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": True}) eventType: str = Field(description="Type of authentication event (e.g., 'login', 'logout', 'token_refresh')", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": True}) timestamp: float = Field(default_factory=getUtcTimestamp, description="Unix timestamp when the event occurred", json_schema_extra={"frontend_type": "datetime", "frontend_readonly": True, "frontend_required": True}) ipAddress: Optional[str] = Field(default=None, description="IP address from which the event originated", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False}) userAgent: Optional[str] = Field(default=None, description="User agent string from the request", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False}) success: bool = Field(default=True, description="Whether the authentication event was successful", json_schema_extra={"frontend_type": "boolean", "frontend_readonly": True, "frontend_required": True}) details: Optional[str] = Field(default=None, description="Additional details about the event", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False}) registerModelLabels( "AuthEvent", {"en": "Authentication Event", "fr": "Événement d'authentification"}, { "id": {"en": "ID", "fr": "ID"}, "userId": {"en": "User ID", "fr": "ID utilisateur"}, "eventType": {"en": "Event Type", "fr": "Type d'événement"}, "timestamp": {"en": "Timestamp", "fr": "Horodatage"}, "ipAddress": {"en": "IP Address", "fr": "Adresse IP"}, "userAgent": {"en": "User Agent", "fr": "Agent utilisateur"}, "success": {"en": "Success", "fr": "Succès"}, "details": {"en": "Details", "fr": "Détails"}, }, )