fix(health): 穷尽审计修复 — 权限同步/编译错误/前端bug/审计日志
审计发现并修复的问题: HIGH: - H1: ConsultationDetail 使用 getSession(id) 替代错误的列表搜索 - H2: SessionResp 添加 version/updated_at 字段 - H3: 移除 FollowUpRecordList 调用不存在的导出端点 - H4: 新增 articles.ts 前端 API 模块 MEDIUM: - M1: article delete 添加乐观锁 (expected_version) - M2: 取消预约排班释放传播错误 (log::warn -> ?) - M3: FollowUpTaskList 日期格式 Dayjs -> string - M4: 补充 15 个缺失审计日志 LOW: - L1: 替换 follow_up_service 中的 .unwrap() - L2: PatientListItem 添加 version 字段 CRITICAL (新发现): - 权限未同步: 健康模块 14 个权限从未写入数据库,添加启动时自动同步 - migration 表名错误: patients -> patient - 编译错误: health_trend entity 未导入, ToPrimitive trait 未导入 - HealthError 缺少 From<AppError> 实现
This commit is contained in:
@@ -363,6 +363,9 @@ async fn main() -> anyhow::Result<()> {
|
||||
registry.startup_all(&module_ctx).await?;
|
||||
tracing::info!("All modules started");
|
||||
|
||||
// 同步所有模块声明的权限到数据库(upsert)
|
||||
sync_module_permissions(&db, ®istry, default_tenant_id).await?;
|
||||
|
||||
// 恢复运行中的插件(服务器重启后自动重新加载)
|
||||
match plugin_engine.recover_plugins(&db).await {
|
||||
Ok(recovered) => {
|
||||
@@ -554,3 +557,67 @@ async fn shutdown_signal() {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// 同步所有模块声明的权限到数据库。
|
||||
///
|
||||
/// 对每个模块的 `permissions()` 返回的权限执行 upsert:
|
||||
/// - 新权限:INSERT
|
||||
/// - 已有权限(同 tenant_id + code):跳过
|
||||
/// 同时将新权限分配给 admin 角色。
|
||||
async fn sync_module_permissions(
|
||||
db: &sea_orm::DatabaseConnection,
|
||||
registry: &erp_core::module::ModuleRegistry,
|
||||
tenant_id: uuid::Uuid,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let system_user_id = uuid::Uuid::nil();
|
||||
let mut total_new = 0u32;
|
||||
|
||||
for module in registry.modules() {
|
||||
let perms = module.permissions();
|
||||
if perms.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
for perm in perms {
|
||||
let result = db.execute(sea_orm::Statement::from_sql_and_values(
|
||||
sea_orm::DatabaseBackend::Postgres,
|
||||
r#"INSERT INTO permissions (id, tenant_id, code, name, resource, action, description, created_at, updated_at, created_by, updated_by, deleted_at, version)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW(), $8, $8, NULL, 1)
|
||||
ON CONFLICT (tenant_id, code) WHERE deleted_at IS NULL DO NOTHING"#,
|
||||
[
|
||||
uuid::Uuid::now_v7().into(),
|
||||
tenant_id.into(),
|
||||
perm.code.clone().into(),
|
||||
perm.name.clone().into(),
|
||||
perm.module.clone().into(),
|
||||
perm.code.split('.').last().unwrap_or("manage").into(),
|
||||
perm.description.clone().into(),
|
||||
system_user_id.into(),
|
||||
],
|
||||
)).await?;
|
||||
|
||||
let rows = result.rows_affected();
|
||||
if rows > 0 {
|
||||
total_new += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if total_new > 0 {
|
||||
// 将新权限分配给 admin 角色
|
||||
db.execute(sea_orm::Statement::from_sql_and_values(
|
||||
sea_orm::DatabaseBackend::Postgres,
|
||||
r#"INSERT INTO role_permissions (role_id, permission_id, tenant_id, data_scope, created_at, updated_at, created_by, updated_by, deleted_at, version)
|
||||
SELECT r.id, p.id, p.tenant_id, 'all', NOW(), NOW(), $1, $1, NULL, 1
|
||||
FROM permissions p
|
||||
JOIN roles r ON r.code = 'admin' AND r.tenant_id = p.tenant_id AND r.deleted_at IS NULL
|
||||
WHERE p.tenant_id = $2 AND p.code LIKE 'health.%'
|
||||
ON CONFLICT DO NOTHING"#,
|
||||
[system_user_id.into(), tenant_id.into()],
|
||||
)).await?;
|
||||
|
||||
tracing::info!(total_new, "Module permissions synced to database");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user