366 lines
9.2 KiB
Python
366 lines
9.2 KiB
Python
from pydantic import BaseModel, Field
|
|
from typing import Optional, List, Any, Dict
|
|
from datetime import datetime
|
|
|
|
# --- Auth Schemas ---
|
|
class LoginRequest(BaseModel):
|
|
email: str
|
|
password: str
|
|
|
|
class TokenResponse(BaseModel):
|
|
access_token: str
|
|
token_type: str = "bearer"
|
|
user: Dict[str, Any]
|
|
|
|
class UserResponse(BaseModel):
|
|
id: int
|
|
email: str
|
|
full_name: Optional[str]
|
|
role: str
|
|
is_active: bool
|
|
auth_source: str
|
|
created_at: datetime
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
class UserCreate(BaseModel):
|
|
email: str
|
|
password: str
|
|
full_name: Optional[str] = None
|
|
role: str = "OPERATOR"
|
|
is_active: bool = True
|
|
auth_source: str = "local"
|
|
|
|
class UserUpdate(BaseModel):
|
|
email: Optional[str] = None
|
|
password: Optional[str] = None
|
|
full_name: Optional[str] = None
|
|
role: Optional[str] = None
|
|
is_active: Optional[bool] = None
|
|
|
|
# --- Client Schemas ---
|
|
class RegistrationCodeCreate(BaseModel):
|
|
client_name_hint: Optional[str] = None
|
|
expires_in_hours: int = 48
|
|
|
|
class RegistrationCodeResponse(BaseModel):
|
|
id: int
|
|
code: str
|
|
expires_at: datetime
|
|
client_name_hint: Optional[str]
|
|
client_id: Optional[int] = None
|
|
|
|
class ClientRegisterRequest(BaseModel):
|
|
registration_code: str
|
|
name: str
|
|
hostname: str
|
|
os_info: Optional[str] = None
|
|
agent_version: str = "1.0.0"
|
|
|
|
class ClientRegisterResponse(BaseModel):
|
|
client_code: str
|
|
device_id: str
|
|
device_token: str
|
|
name: str
|
|
server_time: datetime
|
|
|
|
class ClientHeartbeatRequest(BaseModel):
|
|
status: str = "ONLINE" # ONLINE, OFFLINE, SYNCING, ERROR
|
|
agent_version: Optional[str] = None
|
|
ip_address: Optional[str] = None
|
|
|
|
class ClientUpdateRequest(BaseModel):
|
|
alias: Optional[str] = None
|
|
storage_quota_bytes: Optional[int] = None
|
|
|
|
class ClientResponse(BaseModel):
|
|
id: int
|
|
client_code: str
|
|
name: str
|
|
alias: Optional[str]
|
|
hostname: Optional[str]
|
|
os_info: Optional[str]
|
|
ip_address: Optional[str]
|
|
agent_version: str
|
|
status: str
|
|
storage_used_bytes: int
|
|
storage_quota_bytes: int
|
|
last_seen_at: Optional[datetime]
|
|
last_backup_at: Optional[datetime]
|
|
is_active: bool
|
|
created_at: datetime
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
# --- Backup Job Schemas ---
|
|
class JobCreate(BaseModel):
|
|
client_id: int
|
|
name: str
|
|
source_path: str
|
|
file_patterns: str = "*.bak,*.mdf"
|
|
exclude_patterns: str = ""
|
|
skip_hidden: bool = False
|
|
skip_system: bool = False
|
|
skip_readonly: bool = False
|
|
sync_deletions: bool = False
|
|
local_destination_path: Optional[str] = None
|
|
schedule_cron: str = "0 2 * * *"
|
|
keep_daily: int = 7
|
|
keep_weekly: int = 4
|
|
keep_monthly: int = 12
|
|
min_stable_time_seconds: int = 60
|
|
|
|
class JobUpdate(BaseModel):
|
|
name: Optional[str] = None
|
|
source_path: Optional[str] = None
|
|
file_patterns: Optional[str] = None
|
|
exclude_patterns: Optional[str] = None
|
|
skip_hidden: Optional[bool] = None
|
|
skip_system: Optional[bool] = None
|
|
skip_readonly: Optional[bool] = None
|
|
sync_deletions: Optional[bool] = None
|
|
local_destination_path: Optional[str] = None
|
|
schedule_cron: Optional[str] = None
|
|
is_active: Optional[bool] = None
|
|
keep_daily: Optional[int] = None
|
|
keep_weekly: Optional[int] = None
|
|
keep_monthly: Optional[int] = None
|
|
min_stable_time_seconds: Optional[int] = None
|
|
|
|
class JobResponse(BaseModel):
|
|
id: int
|
|
job_code: str
|
|
client_id: int
|
|
name: str
|
|
source_path: str
|
|
file_patterns: str
|
|
exclude_patterns: str
|
|
skip_hidden: bool
|
|
skip_system: bool
|
|
skip_readonly: bool
|
|
sync_deletions: bool
|
|
local_destination_path: Optional[str]
|
|
schedule_cron: str
|
|
is_active: bool
|
|
keep_daily: int
|
|
keep_weekly: int
|
|
keep_monthly: int
|
|
min_stable_time_seconds: int
|
|
status: str
|
|
last_run_at: Optional[datetime]
|
|
next_run_at: Optional[datetime]
|
|
created_at: datetime
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
# --- Upload Session & Chunk Schemas ---
|
|
class UploadSessionInitRequest(BaseModel):
|
|
filename: str
|
|
client_relative_path: Optional[str] = None
|
|
file_size: int
|
|
sha256: str
|
|
chunk_size: int = 4 * 1024 * 1024
|
|
job_id: Optional[int] = None
|
|
|
|
class UploadSessionInitResponse(BaseModel):
|
|
session_code: str
|
|
filename: str
|
|
file_size: int
|
|
chunk_size: int
|
|
total_chunks: int
|
|
received_chunks: List[int]
|
|
status: str
|
|
|
|
class UploadSessionStatusResponse(BaseModel):
|
|
session_code: str
|
|
filename: str
|
|
file_size: int
|
|
chunk_size: int
|
|
total_chunks: int
|
|
received_chunks: List[int]
|
|
missing_chunks: List[int]
|
|
status: str
|
|
progress_percent: float
|
|
|
|
class ChunkUploadResponse(BaseModel):
|
|
chunk_index: int
|
|
is_received: bool
|
|
total_received: int
|
|
total_chunks: int
|
|
progress_percent: float
|
|
|
|
class UploadSessionCompleteResponse(BaseModel):
|
|
session_code: str
|
|
filename: str
|
|
relative_path: str
|
|
file_size: int
|
|
sha256: str
|
|
status: str
|
|
completed_at: datetime
|
|
|
|
# --- Backup File Schemas ---
|
|
class BackupFileResponse(BaseModel):
|
|
id: int
|
|
client_id: int
|
|
job_id: Optional[int]
|
|
session_id: Optional[int]
|
|
filename: str
|
|
relative_path: str
|
|
file_size: int
|
|
sha256: str
|
|
retention_tag: str
|
|
is_active: bool
|
|
created_at: datetime
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
# --- Event Log Schemas ---
|
|
class EventLogResponse(BaseModel):
|
|
id: int
|
|
timestamp: datetime
|
|
event_type: str
|
|
severity: str
|
|
client_id: Optional[int]
|
|
job_id: Optional[int]
|
|
user_email: Optional[str]
|
|
ip_address: Optional[str]
|
|
message: str
|
|
details_json: Optional[str]
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
# --- Dashboard & Storage Stats ---
|
|
class StorageStatsResponse(BaseModel):
|
|
total_bytes: int
|
|
used_bytes: int
|
|
free_bytes: int
|
|
usage_percent: float
|
|
storage_root: str
|
|
|
|
class DashboardStatsResponse(BaseModel):
|
|
total_clients: int
|
|
online_clients: int
|
|
offline_clients: int
|
|
total_jobs: int
|
|
backups_today_count: int
|
|
backups_today_success: int
|
|
backups_today_failed: int
|
|
active_uploads_count: int
|
|
storage: StorageStatsResponse
|
|
|
|
# --- System Settings Schemas ---
|
|
class SystemSettingsResponse(BaseModel):
|
|
storage_root: str
|
|
global_quota_gb: int
|
|
default_client_quota_gb: int
|
|
default_keep_daily: int
|
|
default_keep_weekly: int
|
|
default_keep_monthly: int
|
|
auth_mode: Optional[str] = "local"
|
|
radius_host: Optional[str] = ""
|
|
radius_port: Optional[int] = 1812
|
|
radius_secret: Optional[str] = ""
|
|
storage_network_enabled: Optional[bool] = False
|
|
storage_network_user: Optional[str] = ""
|
|
storage_network_pass: Optional[str] = ""
|
|
|
|
class SystemSettingsUpdate(BaseModel):
|
|
storage_root: Optional[str] = None
|
|
global_quota_gb: Optional[int] = None
|
|
default_client_quota_gb: Optional[int] = None
|
|
default_keep_daily: Optional[int] = None
|
|
default_keep_weekly: Optional[int] = None
|
|
default_keep_monthly: Optional[int] = None
|
|
auth_mode: Optional[str] = None
|
|
radius_host: Optional[str] = None
|
|
radius_port: Optional[int] = None
|
|
radius_secret: Optional[str] = None
|
|
storage_network_enabled: Optional[bool] = None
|
|
storage_network_user: Optional[str] = None
|
|
storage_network_pass: Optional[str] = None
|
|
|
|
class AgentJobRegister(BaseModel):
|
|
name: str
|
|
source_path: str
|
|
file_patterns: str = "*.bak,*.mdf"
|
|
exclude_patterns: str = ""
|
|
skip_hidden: bool = False
|
|
skip_system: bool = False
|
|
skip_readonly: bool = False
|
|
sync_deletions: bool = False
|
|
local_destination_path: Optional[str] = None
|
|
schedule_cron: str = "daily"
|
|
keep_daily: int = 7
|
|
keep_weekly: int = 4
|
|
keep_monthly: int = 12
|
|
min_stable_time_seconds: int = 60
|
|
|
|
class PurgeOrphansRequest(BaseModel):
|
|
active_relative_paths: List[str]
|
|
|
|
# --- Job Run Schemas ---
|
|
class JobRunStartRequest(BaseModel):
|
|
client_id: int
|
|
|
|
class JobRunCompleteRequest(BaseModel):
|
|
status: str # SUCCESS, FAILED
|
|
files_scanned: int
|
|
files_copied: int
|
|
files_skipped: int
|
|
errors_count: int
|
|
bytes_transferred: int
|
|
error_summary: Optional[str] = None
|
|
|
|
class JobRunResponse(BaseModel):
|
|
id: int
|
|
job_id: int
|
|
client_id: int
|
|
started_at: datetime
|
|
completed_at: Optional[datetime]
|
|
status: str
|
|
files_scanned: int
|
|
files_copied: int
|
|
files_skipped: int
|
|
errors_count: int
|
|
bytes_transferred: int
|
|
error_summary: Optional[str]
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
# --- Script Jobs Schemas ---
|
|
class ScriptJobRunResponse(BaseModel):
|
|
id: int
|
|
script_job_id: int
|
|
started_at: datetime
|
|
completed_at: Optional[datetime]
|
|
status: str
|
|
duration_seconds: float
|
|
log_output: Optional[str]
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
class ScriptJobResponse(BaseModel):
|
|
id: int
|
|
name: str
|
|
script_type: str
|
|
script_path: str
|
|
schedule_cron: str
|
|
is_active: bool
|
|
created_at: datetime
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
class ScriptJobCreate(BaseModel):
|
|
name: str
|
|
script_type: str
|
|
script_path: str
|
|
schedule_cron: str
|
|
is_active: bool = True
|
|
|
|
class ScriptJobUpdate(BaseModel):
|
|
name: Optional[str] = None
|
|
script_type: Optional[str] = None
|
|
script_path: Optional[str] = None
|
|
schedule_cron: Optional[str] = None
|
|
is_active: Optional[bool] = None
|