feat: 添加审批系统和遗留查询功能支持

- 添加审批系统,包括审批请求模型、服务和路由,支持创建、批准和拒绝操作
- 实现审批API密钥验证机制,区分普通API和审批API访问权限
- 添加Alembic数据库迁移支持,更新初始schema版本并添加降级保护
- 配置遗留MySQL查询白名单机制,支持命名查询和参数化查询
- 更新业务服务以集成审批流程,高风险操作需要审批票证
- 调整安全认证使用常量定义的HTTP头,增强安全性比较
- 优化.gitignore配置,添加日志目录排除和文档文件包含规则
- 更新Dockerfile添加alembic依赖包,修复OpenClaw适配器错误处理
```
This commit is contained in:
2026-07-06 09:39:25 +08:00
parent ae5990eaef
commit e3a4a6d426
28 changed files with 536 additions and 86 deletions

View File

@@ -7,7 +7,7 @@ Create Date: 2026-07-06
from alembic import op
from app.core.database import Base
from app.core.db_base import Base
from app.modules.approvals import models as approval_models
from app.modules.audit import models as audit_models
from app.modules.business import models as business_models
@@ -26,4 +26,4 @@ def upgrade() -> None:
def downgrade() -> None:
Base.metadata.drop_all(bind=op.get_bind())
raise RuntimeError("Initial schema downgrade is destructive; create an explicit rollback plan.")

View File

@@ -0,0 +1,57 @@
"""Add approval ticket consumption fields.
Revision ID: 202607060002
Revises: 202607060001
Create Date: 2026-07-06
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
revision = "202607060002"
down_revision = "202607060001"
branch_labels = None
depends_on = None
APPROVAL_REQUESTS_TABLE = "approval_requests"
USED_BY_COLUMN = "used_by"
USED_AT_COLUMN = "used_at"
def _column_names() -> set[str]:
inspector = inspect(op.get_bind())
return {
column["name"]
for column in inspector.get_columns(APPROVAL_REQUESTS_TABLE)
}
def upgrade() -> None:
columns = _column_names()
if USED_BY_COLUMN not in columns:
op.add_column(
APPROVAL_REQUESTS_TABLE,
sa.Column(USED_BY_COLUMN, sa.String(length=128), nullable=True),
)
op.create_index(
op.f("ix_approval_requests_used_by"),
APPROVAL_REQUESTS_TABLE,
[USED_BY_COLUMN],
unique=False,
)
if USED_AT_COLUMN not in columns:
op.add_column(
APPROVAL_REQUESTS_TABLE,
sa.Column(USED_AT_COLUMN, sa.DateTime(), nullable=True),
)
def downgrade() -> None:
columns = _column_names()
if USED_BY_COLUMN in columns:
op.drop_index(op.f("ix_approval_requests_used_by"), table_name=APPROVAL_REQUESTS_TABLE)
op.drop_column(APPROVAL_REQUESTS_TABLE, USED_BY_COLUMN)
if USED_AT_COLUMN in columns:
op.drop_column(APPROVAL_REQUESTS_TABLE, USED_AT_COLUMN)