feat(后端): 添加授权体系、系统监控与试用期计提
按 2026-11-02 需求补齐计划交付后端能力: - 角色授权:权限目录化,接口统一准入校验,未登记默认拒绝; 管理员判断改为按数据库角色重新判定,防止权限码持有者绕过 - 系统监控:单进程采集资源、请求与异常指标,分钟级聚合, 阈值配置化;敏感配置增加 repr 保护,Redis 密码 URL 转义 - 试用期计提:按回款日判定并写入快照,年度结清与调整单联动; 人员模型补试用期、离职日期与工资版本历史字段 - 计提模板:公式骨架受控,页面维护名称与参数绑定 - T+ 采集:自动化配置表与进度查询 内置角色禁停用保护对齐模块注释;核算规则版本提为常量并 补充批量核算失败堆栈日志。 影响范围:后端全部模块、数据库迁移 V22-V28 验证:uv run ruff check 通过;922 个单元测试全部通过; 集成测试因本机 MySQL 数据卷被其他容器锁定暂未运行
This commit is contained in:
1 parent
02fb06e0af
commit
1461a8d113
149 files changed
+8736
-368
No files matched your search
@@ -0,0 +1,78 @@
|
||||
"""监控接口只暴露固定白名单,不传输内部异常或连接配置。"""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Annotated, Literal
|
||||
|
||||
from pydantic import BaseModel, BeforeValidator, ConfigDict, Field
|
||||
|
||||
from app.core.response import PageQuery
|
||||
|
||||
Status = Literal["normal", "warning", "error", "unknown"]
|
||||
Hours = Annotated[
|
||||
Literal[1, 24, 168],
|
||||
BeforeValidator(lambda value: int(value) if value in ("1", "24", "168") else value),
|
||||
]
|
||||
|
||||
|
||||
class MonitorWindow(BaseModel):
|
||||
hours: Hours = 1
|
||||
end: datetime | None = None
|
||||
route: str | None = Field(default=None, max_length=256)
|
||||
|
||||
|
||||
class EventQuery(PageQuery):
|
||||
hours: Hours = 24
|
||||
end: datetime | None = None
|
||||
route: str | None = Field(default=None, max_length=256)
|
||||
kind: Literal["HEALTH", "REQUEST_ERROR", "SLOW_REQUEST", "RUNTIME_ERROR"] | None = None
|
||||
request_id: str | None = Field(default=None, pattern=r"^[a-f0-9]{32}$")
|
||||
active_only: bool = False
|
||||
|
||||
|
||||
class EventOut(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
instance_id: str
|
||||
kind: str
|
||||
code: str
|
||||
component: str
|
||||
level: str
|
||||
message: str
|
||||
request_id: str | None = None
|
||||
method: str | None = None
|
||||
route: str | None = None
|
||||
status_code: int | None = None
|
||||
duration_ms: float | None = None
|
||||
batch_no: str | None = None
|
||||
first_seen: datetime
|
||||
last_seen: datetime
|
||||
occurrences: int
|
||||
resolved_at: datetime | None = None
|
||||
|
||||
|
||||
class DependencyOut(BaseModel):
|
||||
name: str
|
||||
status: Status
|
||||
message: str
|
||||
checked_at: datetime | None = None
|
||||
duration_ms: float | None = None
|
||||
|
||||
|
||||
class OverviewOut(BaseModel):
|
||||
status: Status
|
||||
environment: str
|
||||
version: str
|
||||
instance_id: str
|
||||
uptime_seconds: int
|
||||
collected_at: datetime | None
|
||||
last_persisted_at: datetime | None
|
||||
collection_status: Status
|
||||
collection_message: str
|
||||
resources: dict
|
||||
requests: dict
|
||||
dependencies: list[DependencyOut]
|
||||
alerts: list[EventOut]
|
||||
tasks: dict
|
||||
dropped_events: int
|
||||
retention_days: int = 7
|
||||
Reference in new issue
Block a user