quality-inspection-platform/app/schemas.py
qihongkun d810abdcee 初始化仓库:AI 接口自动化测试平台
纳入 FastAPI 后端、Vue 管理端、MCP 桥接与文档;通过 .gitignore 排除本地数据库与构建产物。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-22 15:44:50 +08:00

409 lines
8.2 KiB
Python

from typing import Any, Literal
from pydantic import BaseModel, Field
class ApiBase(BaseModel):
name: str
folder_path: str = ""
method: str = "GET"
url: str
headers: dict[str, Any] = Field(default_factory=dict)
body: dict[str, Any] = Field(default_factory=dict)
query: dict[str, Any] = Field(default_factory=dict)
path_params: dict[str, Any] = Field(default_factory=dict)
timeout_seconds: float = 10.0
class ApiCreate(ApiBase):
pass
class ApiUpdate(ApiBase):
pass
class ApiOut(ApiBase):
id: int
creator_id: int = 0
creator_name: str = ""
class Config:
from_attributes = True
class WorkflowPayload(BaseModel):
nodes: list[dict[str, Any]] = Field(default_factory=list)
edges: list[dict[str, Any]] = Field(default_factory=list)
variables: dict[str, Any] = Field(default_factory=dict)
class WorkflowBase(BaseModel):
name: str
folder_path: str = ""
definition: WorkflowPayload = Field(default_factory=WorkflowPayload)
default_headers: dict[str, Any] = Field(default_factory=dict)
class WorkflowCreate(WorkflowBase):
pass
class WorkflowUpdate(WorkflowBase):
pass
class WorkflowOut(WorkflowBase):
id: int
creator_id: int = 0
creator_name: str = ""
last_run: dict[str, Any] | None = None
class Config:
from_attributes = True
class ReplayRunRequest(BaseModel):
base_url: str = ""
fail_fast: bool = True
class MockDataBase(BaseModel):
name: str
data: dict[str, Any] = Field(default_factory=dict)
class MockDataCreate(MockDataBase):
pass
class MockDataOut(MockDataBase):
id: int
creator_id: int = 0
creator_name: str = ""
class Config:
from_attributes = True
class McpToolBase(BaseModel):
name: str
enabled: bool = True
config: dict[str, Any] = Field(default_factory=dict)
class McpToolCreate(McpToolBase):
pass
class McpToolOut(McpToolBase):
id: int
creator_id: int = 0
creator_name: str = ""
class Config:
from_attributes = True
class SshCommandPreset(BaseModel):
name: str
command: str
description: str = ""
class SshProfileBase(BaseModel):
name: str
host: str
port: int = 22
username: str
auth_type: Literal["key", "password"] = "key"
key_path: str = ""
presets: list[SshCommandPreset] = Field(default_factory=list)
class SshProfileCreate(SshProfileBase):
pass
class SshProfileUpdate(SshProfileBase):
pass
class SshProfileOut(SshProfileBase):
id: int
creator_id: int = 0
creator_name: str = ""
class Config:
from_attributes = True
class SshExecuteRequest(BaseModel):
command: str = ""
preset_name: str = ""
password: str = ""
timeout_seconds: float = 20.0
class SshExecuteResponse(BaseModel):
ok: bool
command: str
stdout: str = ""
stderr: str = ""
exit_status: int = 0
class SshShortcutBase(BaseModel):
name: str
command: str
description: str = ""
class SshShortcutCreate(SshShortcutBase):
pass
class SshShortcutUpdate(SshShortcutBase):
pass
class SshShortcutOut(SshShortcutBase):
id: int
creator_id: int = 0
creator_name: str = ""
class Config:
from_attributes = True
class SshScriptBase(BaseModel):
profile_id: int
name: str
description: str = ""
source_type: Literal["inline", "file"] = "inline"
content: str = ""
class SshScriptCreate(SshScriptBase):
pass
class SshScriptUpdate(BaseModel):
name: str
description: str = ""
content: str = ""
class SshScriptOut(SshScriptBase):
id: int
storage_path: str = ""
creator_id: int = 0
creator_name: str = ""
class Config:
from_attributes = True
class SshTreeScriptNode(BaseModel):
id: int
name: str
description: str = ""
source_type: Literal["inline", "file"] = "inline"
storage_path: str = ""
class SshTreeProfileNode(BaseModel):
id: int
name: str
host: str
port: int = 22
username: str
auth_type: Literal["key", "password"] = "key"
key_path: str = ""
scripts: list[SshTreeScriptNode] = Field(default_factory=list)
class LoginRequest(BaseModel):
username: str
password: str
class CurrentUserOut(BaseModel):
id: int
username: str
display_name: str
role: Literal["superadmin", "user"]
class LoginResponse(BaseModel):
token: str
user: CurrentUserOut
class UserCreate(BaseModel):
username: str
password: str
display_name: str = ""
role: Literal["superadmin", "user"] = "user"
class UserUpdate(BaseModel):
display_name: str = ""
role: Literal["superadmin", "user"] = "user"
is_active: bool = True
password: str = ""
class UserOut(BaseModel):
id: int
username: str
display_name: str
role: Literal["superadmin", "user"]
is_active: bool
class UserApiKeyCreate(BaseModel):
expires_at: str | None = None
class UserApiKeyOut(BaseModel):
id: int
key_prefix: str
key_hint: str
masked_key: str = ""
expires_at: str | None = None
is_active: bool = True
created_at: str = ""
class Config:
from_attributes = True
class UserApiKeyCreateResponse(UserApiKeyOut):
api_key: str
class RunWorkflowRequest(BaseModel):
workflow_id: int
base_url: str = ""
fail_fast: bool = True
class NodeExecutionResult(BaseModel):
node_id: str
node_type: str
status: Literal["success", "failed", "skipped"]
output: dict[str, Any] = Field(default_factory=dict)
error: str | None = None
class RunWorkflowResponse(BaseModel):
status: Literal["success", "failed"]
variables: dict[str, Any]
results: list[NodeExecutionResult]
run_id: int | None = None
workflow_id: int | None = None
batch_id: int | None = None
class WorkflowBatchCreate(BaseModel):
name: str = ""
base_url: str = ""
fail_fast: bool = True
workflow_ids: list[int] = Field(default_factory=list)
class WorkflowBatchUpdate(BaseModel):
name: str | None = None
base_url: str | None = None
fail_fast: bool | None = None
workflow_ids: list[int] | None = None
class RunWorkflowBatchRequest(BaseModel):
"""快捷:创建批次并立即执行(兼容旧调用)。"""
workflow_ids: list[int] = Field(default_factory=list)
name: str = ""
base_url: str = ""
fail_fast: bool = True
class WorkflowBatchRunItem(BaseModel):
workflow_id: int
workflow_name: str = ""
run_id: int | None = None
status: str = "pending"
error: str | None = None
class RunWorkflowBatchResponse(BaseModel):
batch_id: int
status: Literal["draft", "running", "success", "failed", "partial"]
items: list[WorkflowBatchRunItem]
class WorkflowBatchOut(BaseModel):
id: int
name: str = ""
status: Literal["draft", "running", "success", "failed", "partial"]
triggered_by: str = ""
creator_id: int = 0
creator_name: str = ""
base_url: str = ""
fail_fast: bool = True
workflow_ids: list[int] = Field(default_factory=list)
summary: dict[str, Any] = Field(default_factory=dict)
created_at: str | None = None
finished_at: str | None = None
runs: list[dict[str, Any]] = Field(default_factory=list)
class LokiLogLinkOut(BaseModel):
enabled: bool = False
explore_url: str = ""
logql: str = ""
time_from: str = ""
time_to: str = ""
method: str = ""
url: str = ""
hint: str = ""
class RunNodeRequest(BaseModel):
workflow_id: int
node_id: str
base_url: str = ""
class RunNodeResponse(BaseModel):
status: Literal["success", "failed"]
variables: dict[str, Any]
result: NodeExecutionResult
class FolderMoveRequest(BaseModel):
target: Literal["apis", "workflows"]
from_path: str
to_path: str
class McpInvokeRequest(BaseModel):
tool: str
arguments: dict[str, Any] = Field(default_factory=dict)
api_key: str | None = Field(
default=None,
description="Optional sto- API key when Authorization header is unavailable",
)
class McpInvokeBatchRequest(BaseModel):
calls: list[McpInvokeRequest] = Field(default_factory=list)
stop_on_error: bool = True
class McpInvokeResponse(BaseModel):
ok: bool
tool: str
data: dict[str, Any] = Field(default_factory=dict)
error: str | None = None