from typing import Optional, List from pydantic import BaseModel, ConfigDict from datetime import datetime class UserCreate(BaseModel): username: str password: str class UserOut(BaseModel): id: int username: str role: str created_at: Optional[datetime] model_config = ConfigDict(from_attributes=True) class UserUpdate(BaseModel): role: Optional[str] = None password: Optional[str] = None class UserListOut(BaseModel): id: int username: str role: str created_at: Optional[datetime] model_config = ConfigDict(from_attributes=True) class Token(BaseModel): access_token: str refresh_token: str token_type: str = "bearer" class TokenRefresh(BaseModel): refresh_token: str class LoginPayload(BaseModel): username: str password: str class SessionInfo(BaseModel): username: Optional[str] = None tty: Optional[str] = None login_time: Optional[str] = None origin: Optional[str] = None class HeartbeatPayload(BaseModel): hostname: str username: str os_info: Optional[str] = None local_ip: Optional[str] = None public_ip: Optional[str] = None uptime_sec: int cpu_percent: float ram_percent: float ram_total_gb: Optional[float] = None ram_used_gb: Optional[float] = None ram_available_gb: Optional[float] = None swap_total_gb: Optional[float] = None swap_used_gb: Optional[float] = None swap_free_gb: Optional[float] = None swap_percent: Optional[float] = None disk_info: Optional[List[dict]] = None cpu_temp: Optional[float] = None load_avg: Optional[str] = None processes: Optional[List[dict]] = None sessions: Optional[List[SessionInfo]] = None class HeartbeatOut(BaseModel): id: int timestamp: datetime username: Optional[str] local_ip: Optional[str] cpu_percent: Optional[float] ram_percent: Optional[float] ram_total_gb: Optional[float] ram_used_gb: Optional[float] ram_available_gb: Optional[float] swap_total_gb: Optional[float] swap_used_gb: Optional[float] swap_free_gb: Optional[float] swap_percent: Optional[float] cpu_temp: Optional[float] sessions: Optional[List[SessionInfo]] = None model_config = ConfigDict(from_attributes=True) class ComputerOut(BaseModel): id: int hostname: str os_info: Optional[str] first_seen: Optional[datetime] last_seen: Optional[datetime] status: str current_user: Optional[str] current_ip: Optional[str] current_cpu_percent: Optional[float] current_ram_percent: Optional[float] current_ram_total_gb: Optional[float] current_ram_used_gb: Optional[float] current_ram_available_gb: Optional[float] current_swap_total_gb: Optional[float] current_swap_used_gb: Optional[float] current_swap_free_gb: Optional[float] current_swap_percent: Optional[float] model_config = ConfigDict(from_attributes=True) class ComputerDetailOut(ComputerOut): heartbeats: List[HeartbeatOut] = [] class NotificationOut(BaseModel): id: int computer_id: Optional[int] type: str title: str message: str is_read: bool sent_at: Optional[datetime] read_at: Optional[datetime] model_config = ConfigDict(from_attributes=True) class AuditLogOut(BaseModel): id: int user_id: Optional[int] username: Optional[str] action: str details: Optional[str] timestamp: Optional[datetime] model_config = ConfigDict(from_attributes=True) class SettingOut(BaseModel): key: str value: Optional[str] class SettingsUpdate(BaseModel): AGENT_TOKEN: Optional[str] = None OFFLINE_THRESHOLD_MINUTES: Optional[int] = None NOTIFICATION_WEBHOOK_URL: Optional[str] = None NOTIFICATION_TELEGRAM_BOT_TOKEN: Optional[str] = None NOTIFICATION_TELEGRAM_CHAT_ID: Optional[str] = None TIMEZONE: Optional[str] = None