""" Device model for passwordless authentication Represents a registered mobile device (app) """ from datetime import datetime from typing import Optional from enum import Enum from pydantic import BaseModel, Field import uuid class DevicePlatform(str, Enum): """Supported device platforms""" IOS = "ios" ANDROID = "android" WEB = "web" OTHER = "other" class DeviceStatus(str, Enum): """Device status""" ACTIVE = "active" REVOKED = "revoked" SUSPENDED = "suspended" class Device(BaseModel): """Device database model""" id: str = Field(default_factory=lambda: str(uuid.uuid4())) user_id: str = Field(..., description="Associated user ID") device_name: str = Field(..., description="Human-readable device name") platform: DevicePlatform = Field(..., description="Device platform") # Device fingerprinting public_key: str = Field(..., description="Device public key for challenge signing") device_fingerprint: str = Field(..., description="Unique device fingerprint hash") # Metadata push_token: Optional[str] = Field(None, description="Push notification token") last_ip: Optional[str] = Field(None, description="Last known IP address") last_user_agent: Optional[str] = Field(None, description="Last user agent") # Status status: DeviceStatus = Field(default=DeviceStatus.ACTIVE) # Timestamps created_at: datetime = Field(default_factory=datetime.utcnow) updated_at: datetime = Field(default_factory=datetime.utcnow) last_used_at: Optional[datetime] = Field(None) class Config: json_schema_extra = { "example": { "id": "dev_123456789", "user_id": "user_abc123", "device_name": "iPhone 15 Pro", "platform": "ios", "public_key": "-----BEGIN PUBLIC KEY-----\n...", "device_fingerprint": "sha256:abc123...", "status": "active", "created_at": "2024-01-15T10:30:00Z" } } class DeviceCreate(BaseModel): """Request model for device registration""" user_id: str = Field(..., description="User ID to associate with device") device_name: str = Field(..., min_length=1, max_length=100) platform: DevicePlatform public_key: str = Field(..., min_length=100, description="Device public key") device_fingerprint: str = Field(..., min_length=32, description="Device fingerprint") push_token: Optional[str] = Field(None, max_length=500) class DeviceUpdate(BaseModel): """Request model for device update""" device_name: Optional[str] = Field(None, min_length=1, max_length=100) push_token: Optional[str] = Field(None, max_length=500) status: Optional[DeviceStatus] = None class DeviceResponse(BaseModel): """Response model for device operations""" id: str user_id: str device_name: str platform: DevicePlatform status: DeviceStatus created_at: datetime last_used_at: Optional[datetime] = None class Config: from_attributes = True class DeviceListResponse(BaseModel): """Response model for listing devices""" devices: list[DeviceResponse] total: int