import re from pydantic import BaseModel, Field, validator from typing import Optional class User(BaseModel): id: Optional[int] = Field(description="Идентификатор (автоматический)", default=None) username: str = Field(max_length=150, description="Пользовательское имя", example="john_doe") #password: str = Field(max_length=255, description="Пароль", example="secret123") email: Optional[str] = Field(max_length=254, default="", description="Электронная почта", example="john@example.com") first_name: Optional[str] = Field(max_length=150, default="", description="Имя", example="John") last_name: Optional[str] = Field(max_length=150, default="", description="Фамилия", example="Doe") #is_staff: bool = Field(default=False, description="Статус администратора") #is_active: bool = Field(default=False, description="Активен") #is_superuser: bool = Field(default=False, description="Суперпользователь") #date_joined: str = Field(description="Дата создания", example="2024-01-01T12:00:00") #last_login: Optional[str] = Field(null=True, default=None, description="Последний вход") class Config: extra = "ignore" from_attributes = True class SIPAccount(BaseModel): """ SIP-аккаунт. """ unique_id: str = Field(description="Уникальный идентификатор", example="00000000-0000-0000-0000-000000000000") id: Optional[int] = Field(description="Идентификатор (автоматический)", default=None) created_at: Optional[str] = Field(description="Дата создания", example="2024-01-01T12:00:00") updated_at: Optional[str] = Field(description="Дата обновления", example="2024-01-01T12:00:00") owner: Optional[User] = Field(description="Владелец") name: str = Field(max_length=255, description="Название", example="SIP-аккаунт-1") is_registered: bool = Field(default=False, description="Зарегистрирован") username: str = Field(max_length=40, description="Имя SIP клиента", example="user123") password: Optional[str] = Field(max_length=80, null=True, blank=True, description="Пароль (открытый, временно)") server_url: str = Field( max_length=215, description="URL сервера", example="https://192.168.1.100:5060" ) port: Optional[int] = Field(null=True, blank=True, description="Порт", ge=0, le=65535) internal_number: Optional[str] = Field(max_length=255, null=True, blank=True, description="Внутренний номер") endpoint_name: Optional[str] = Field(max_length=255, null=True, blank=True, description="Имя конечной точки") @validator("server_url") def validate_server_url(cls, v): if not v: return v # Проверяем, содержит ли строка URL (в формате http:// или https://) if v.startswith("http://") or v.startswith("https://"): return v # Проверяем, является ли это IPv4 (простая проверкаDetails) parts = v.strip().split(':') if len(parts) == 1: ip_part = parts[0] if re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", ip_part): # Проверяем, что каждая часть от 0 до 255 ip_parts = [int(x) for x in ip_part.split('.')] if all(0 <= part <= 255 for part in ip_parts): return v raise ValueError("Invalid server URL format (must be http(s):// or IPv4 address)") @validator("username") def validate_username(cls, v): if len(v) > 40: raise ValueError("Username too long (max 40 characters)") return v @validator("name") def validate_name(cls, v): if len(v) > 255: raise ValueError("Name too long (max 255 characters)") return v @validator("internal_number") def validate_internal_number(cls, v): if v and len(v) > 255: raise ValueError("Internal number too long (max 255 characters)") return v @validator("endpoint_name") def validate_endpoint_name(cls, v): if v and len(v) > 255: raise ValueError("Endpoint name too long (max 255 characters)") return v @validator("port") def validate_port(cls, v): if v is not None and not (0 <= v <= 65535): raise ValueError("Port must be between 0 and 65535") return v class Config: extra = "ignore" from_attributes = True class AccessResponse(BaseModel): success: bool token: str class Registration(BaseModel): auth_key: str