2026-07-08 23:25:58 +08:00
|
|
|
|
"""DB 域模型:密钥注入 / 密钥状态 / DB 初始化。"""
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
|
|
from typing import Optional
|
|
|
|
|
|
|
|
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
# DB 解密接口(POST /api/db/decrypt, GET /api/db/key/status)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class DbDecryptRequest(BaseModel):
|
|
|
|
|
|
"""手动 key 注入请求。
|
|
|
|
|
|
|
|
|
|
|
|
外部系统(如 ForcePilot)或管理员通过 POST /api/db/decrypt 传入 64 位
|
|
|
|
|
|
十六进制密钥,bridge 验证并缓存,后续所有 DB 查询接口立即恢复可用。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
key: str = Field(description="64 位十六进制 SQLCipher 密钥")
|
|
|
|
|
|
salt: Optional[str] = Field(
|
|
|
|
|
|
default=None,
|
|
|
|
|
|
description="可选:该 key 对应的 DB salt(32 位十六进制)。未指定时 bridge 自动读取当前 DB 的 salt",
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DbDecryptResponse(BaseModel):
|
|
|
|
|
|
"""key 注入结果。
|
|
|
|
|
|
|
|
|
|
|
|
- verified=true 时 key 已缓存,后续 DB 查询接口立即可用
|
|
|
|
|
|
- verified=false 时 key 不匹配,未缓存
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
success: bool = Field(description="请求是否处理成功(不代表 key 正确)")
|
|
|
|
|
|
verified: bool = Field(default=False, description="key 是否通过验证并缓存")
|
|
|
|
|
|
key_mode: Optional[str] = Field(
|
|
|
|
|
|
default=None,
|
2026-07-16 01:19:47 +08:00
|
|
|
|
description="key 形态:enc_key(已派生密钥)/ key_material(原始密钥材料);验证失败时为 None",
|
2026-07-08 23:25:58 +08:00
|
|
|
|
)
|
|
|
|
|
|
error: Optional[str] = Field(default=None, description="验证失败或特殊状态:key_mismatch / file_too_small / db_not_encrypted")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DbKeyStatusResponse(BaseModel):
|
|
|
|
|
|
"""key 缓存状态查询响应。
|
|
|
|
|
|
|
|
|
|
|
|
供调用方判断是否需要注入 key 或等待自动提取。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
cached: bool = Field(default=False, description="是否有缓存的 key")
|
|
|
|
|
|
source: Optional[str] = Field(
|
|
|
|
|
|
default=None,
|
|
|
|
|
|
description="key 来源:env(环境变量)/ api(POST 注入)/ auto_extract(内存扫描)/ file(持久化文件)",
|
|
|
|
|
|
)
|
|
|
|
|
|
verified: bool = Field(default=False, description="缓存 key 是否已通过验证")
|
|
|
|
|
|
key_prefix: Optional[str] = Field(
|
|
|
|
|
|
default=None,
|
|
|
|
|
|
description="key 前 4 + ... + 后 4 字符,用于确认是哪个 key(不泄露完整 key)",
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DbInitRequest(BaseModel):
|
|
|
|
|
|
"""DB 初始化请求(显式触发密钥提取)。"""
|
|
|
|
|
|
|
|
|
|
|
|
pid: Optional[int] = Field(default=None, description="可选:指定微信进程 PID")
|
|
|
|
|
|
db_dir: Optional[str] = Field(default=None, description="可选:指定微信数据目录,默认自动检测")
|
|
|
|
|
|
force: bool = Field(default=False, description="是否强制重新提取,忽略已有 keys 文件")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DbInitResponse(BaseModel):
|
|
|
|
|
|
"""DB 初始化响应。"""
|
|
|
|
|
|
|
|
|
|
|
|
success: bool = Field(description="请求是否受理")
|
|
|
|
|
|
state: str = Field(description="状态:started / already_done / in_progress / failed")
|
|
|
|
|
|
message: str = Field(description="阶段描述")
|
|
|
|
|
|
key_count: Optional[int] = Field(default=None, description="已提取到的 salt→key 映射数量")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DbInitStatusResponse(BaseModel):
|
|
|
|
|
|
"""DB 初始化后台任务状态。"""
|
|
|
|
|
|
|
|
|
|
|
|
state: str = Field(description="状态:idle / running / success / failed")
|
|
|
|
|
|
progress_pct: Optional[float] = Field(default=None, description="进度百分比 0-100")
|
|
|
|
|
|
message: Optional[str] = Field(default=None, description="当前阶段描述")
|
|
|
|
|
|
key_count: Optional[int] = Field(default=None, description="成功提取的密钥数")
|
|
|
|
|
|
error: Optional[str] = Field(default=None, description="失败原因")
|