Files
Nexus/server/api/schemas.py
T
Your Name c9a99f4fb3 fix: 全项目文档对齐 + 代码清理
代码修复:
- web/agent/agent.py: datetime.utcnow() → datetime.now(timezone.utc)
- requirements.txt: 移除 paramiko==3.5.0 (已无活跃引用)
- 删除 server/infrastructure/ssh/pool.py (DEPRECATED, 无引用)

连接池三层对齐 (config.py/.env.example/session.py):
- DB_POOL_SIZE 100→160, DB_MAX_OVERFLOW 100→120
- 基于 MySQL max_connections=400, install.php 公式

文档修复 (21项):
- P0: 硬编码域名/IP替换为配置变量占位符
- P1: 10个过时设计文档加归档标注 (引用旧文件结构)
- P2: step-3-webssh报告 paramiko引用修正
- 6份审查报告连接池参数勘误 100/100→160/120
- ECC安全报告 EC5 datetime.utcnow 标记已修复
- docs/README.md 文档索引重写
- docs/memory/mem_nexus_overview.md 移除硬编码凭证
- docs/project/tech-stack-inventory.md paramiko标记已移除

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 08:19:56 +08:00

222 lines
6.6 KiB
Python

"""Nexus — Pydantic Request/Response Models
Shared schemas for API validation, replacing raw `dict` parameters.
"""
from typing import Optional, List
from pydantic import BaseModel, Field
# ── Setting ──
class SettingUpdatePayload(BaseModel):
value: str = Field(..., min_length=0)
# ── Agent ──
class AgentHeartbeat(BaseModel):
server_id: int
is_online: bool = True
system_info: Optional[dict] = None
agent_version: Optional[str] = None
class AgentExec(BaseModel):
command: str = Field(..., min_length=1)
timeout: int = Field(30, ge=1, le=300)
sudo: bool = False
# ── Server ──
class ServerCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=100)
domain: str = Field(..., min_length=1, max_length=255)
port: int = Field(22, ge=1, le=65535)
username: str = Field("root", max_length=100)
auth_method: str = Field("key", pattern="^(key|password)$")
password: Optional[str] = None
ssh_key_path: Optional[str] = None
ssh_key_private: Optional[str] = None
ssh_key_public: Optional[str] = None
agent_port: int = Field(8601, ge=1, le=65535)
agent_api_key: Optional[str] = None
description: Optional[str] = None
target_path: Optional[str] = None
category: Optional[str] = None
platform_id: Optional[int] = None
node_id: Optional[int] = None
protocols: Optional[list] = None
extra_attrs: Optional[dict] = None
class ServerUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1, max_length=100)
domain: Optional[str] = Field(None, min_length=1, max_length=255)
port: Optional[int] = Field(None, ge=1, le=65535)
username: Optional[str] = None
auth_method: Optional[str] = Field(None, pattern="^(key|password)$")
password: Optional[str] = None
ssh_key_path: Optional[str] = None
ssh_key_private: Optional[str] = None
ssh_key_public: Optional[str] = None
agent_port: Optional[int] = Field(None, ge=1, le=65535)
agent_api_key: Optional[str] = None
description: Optional[str] = None
target_path: Optional[str] = None
category: Optional[str] = None
platform_id: Optional[int] = None
node_id: Optional[int] = None
protocols: Optional[list] = None
extra_attrs: Optional[dict] = None
connectivity: Optional[str] = None
class ServerPush(BaseModel):
server_ids: List[int] = Field(..., min_length=1)
source_path: str = Field(..., min_length=1)
sync_mode: str = Field("incremental", pattern="^(incremental|full|overwrite|checksum)$")
batch_size: int = Field(50, ge=1, le=200)
concurrency: int = Field(10, ge=1, le=50)
class ServerCheck(BaseModel):
server_ids: List[int] = Field(..., min_length=1)
# ── Sync ──
class SyncFiles(BaseModel):
server_ids: List[int] = Field(..., min_length=1)
source_path: str = Field(..., min_length=1)
target_path: Optional[str] = None
sync_mode: str = Field("incremental", pattern="^(incremental|full|overwrite|checksum)$")
batch_size: int = Field(50, ge=1, le=200)
concurrency: int = Field(10, ge=1, le=50)
class SyncCommands(BaseModel):
server_ids: List[int] = Field(..., min_length=1)
commands: List[str] = Field(..., min_length=1)
timeout: int = Field(60, ge=1, le=600)
concurrency: int = Field(10, ge=1, le=50)
class SyncConfig(BaseModel):
server_ids: List[int] = Field(..., min_length=1)
config: dict = Field(..., min_length=1)
concurrency: int = Field(10, ge=1, le=50)
class SyncSftp(BaseModel):
server_id: int
operation: str = Field("put", pattern="^(put|get)$")
local_path: str = Field(..., min_length=1)
remote_path: str = Field(..., min_length=1)
class SyncBrowse(BaseModel):
server_id: int
path: str = Field("/", min_length=1)
# ── Script ──
class ScriptCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=100)
category: str = Field("ops", pattern="^(ops|deploy|check|cleanup)$")
content: str = Field(..., min_length=1)
description: Optional[str] = None
created_by: Optional[str] = None
class ScriptUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1, max_length=100)
category: Optional[str] = Field(None, pattern="^(ops|deploy|check|cleanup)$")
content: Optional[str] = None
description: Optional[str] = None
class ScriptExecute(BaseModel):
script_id: Optional[int] = None
command: str = Field(..., min_length=1)
server_ids: List[int] = Field(..., min_length=1)
timeout: int = Field(60, ge=1, le=600)
# ── DB Credential ──
class DbCredentialCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=100)
db_type: str = Field("mysql", pattern="^(mysql|postgresql|mariadb|mongodb|redis)$")
host: str = Field(..., min_length=1)
port: int = Field(3306, ge=1, le=65535)
username: str = Field(..., min_length=1)
password: str = Field(..., min_length=1)
database: Optional[str] = None
# ── Schedule ──
class ScheduleCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=100)
source_path: str = Field(..., min_length=1)
server_ids: str = Field(..., min_length=3) # JSON array string
cron_expr: str = Field(..., min_length=9, max_length=100)
enabled: bool = True
class ScheduleUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1, max_length=100)
source_path: Optional[str] = None
server_ids: Optional[str] = None
cron_expr: Optional[str] = None
enabled: Optional[bool] = None
# ── Preset ──
class PresetCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=100)
encrypted_pw: str = Field(..., min_length=1)
# ── Platform / Node ──
class PlatformCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=100)
category: str = Field(..., min_length=1, max_length=50)
type: str = Field(..., min_length=1, max_length=50)
default_protocols: Optional[list] = None
charset: str = "utf-8"
class PlatformUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1, max_length=100)
category: Optional[str] = None
type: Optional[str] = None
default_protocols: Optional[list] = None
charset: Optional[str] = None
class NodeCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=100)
parent_id: Optional[int] = None
sort_order: int = 0
class NodeUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1, max_length=100)
parent_id: Optional[int] = None
sort_order: Optional[int] = None
# ── Pagination ──
class PaginatedResponse(BaseModel):
items: list
total: int
page: int
per_page: int
pages: int