fix(health): 客户试用前全局审计修复 — P0 权限旁路 + API 路径 + 事件注册
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

P0 阻塞修复:
- 修复 PrivateRoute 权限旁路: p.startsWith('auth.') 匹配不到任何权限码,
  改为基于实际权限码的路由级检查 (user.manage/role.manage/organization.manage)
- 修复 deviceReadings API 路径: /patients/{id}/device-readings/daily 改为
  /vital-signs/daily?patient_id=, 消除 404

P1 重要修复:
- 补全事件注册表: 新增 auth(11) + config(8) + workflow(4) + plugin(2) = 25 条
- article_article_tag 联表新增 tenant_id + deleted_at + 审计列 (迁移 107)
- vital_signs_hourly 新增 deleted_at 支持软删除过滤 (迁移 108)
- 6 个页面添加权限守卫 (AlertDashboard/AlertRuleList/DeviceManage/
  AiAnalysisList/AiUsageDashboard)
- DialysisModule 声明 auth 依赖
This commit is contained in:
iven
2026-05-04 11:02:25 +08:00
parent cde3a863a2
commit 30a578ee00
16 changed files with 260 additions and 17 deletions

View File

@@ -106,6 +106,8 @@ mod m20260502_000103_seed_follow_up_template_menu;
mod m20260504_000104_create_vital_signs_daily;
mod m20260504_000105_alter_patient_devices_add_status;
mod m20260504_000106_create_api_clients;
mod m20260504_000107_alter_article_article_tag_add_tenant_and_soft_delete;
mod m20260504_000108_alter_vital_signs_hourly_add_soft_delete;
pub struct Migrator;
@@ -219,6 +221,8 @@ impl MigratorTrait for Migrator {
Box::new(m20260504_000104_create_vital_signs_daily::Migration),
Box::new(m20260504_000105_alter_patient_devices_add_status::Migration),
Box::new(m20260504_000106_create_api_clients::Migration),
Box::new(m20260504_000107_alter_article_article_tag_add_tenant_and_soft_delete::Migration),
Box::new(m20260504_000108_alter_vital_signs_hourly_add_soft_delete::Migration),
]
}
}

View File

@@ -0,0 +1,113 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
// 添加 tenant_id 列(可为空,后续由应用层填充)
manager
.alter_table(
Table::alter()
.table(Alias::new("article_article_tag"))
.add_column(ColumnDef::new(Alias::new("tenant_id")).uuid().null())
.to_owned(),
)
.await?;
// 添加 deleted_at 列
manager
.alter_table(
Table::alter()
.table(Alias::new("article_article_tag"))
.add_column(
ColumnDef::new(Alias::new("deleted_at"))
.timestamp_with_time_zone()
.null(),
)
.to_owned(),
)
.await?;
// 添加 created_at / updated_at如果不存在
manager
.alter_table(
Table::alter()
.table(Alias::new("article_article_tag"))
.add_column(
ColumnDef::new(Alias::new("created_at"))
.timestamp_with_time_zone()
.not_null()
.default(Expr::val("NOW()")),
)
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(Alias::new("article_article_tag"))
.add_column(
ColumnDef::new(Alias::new("updated_at"))
.timestamp_with_time_zone()
.not_null()
.default(Expr::val("NOW()")),
)
.to_owned(),
)
.await?;
// 从关联的 article 表回填 tenant_id
manager
.get_connection()
.execute_unprepared(
"UPDATE article_article_tag aat SET tenant_id = (SELECT tenant_id FROM article WHERE article.id = aat.article_id) WHERE aat.tenant_id IS NULL",
)
.await?;
// 设置 tenant_id 为 NOT NULL回填完成后
manager
.alter_table(
Table::alter()
.table(Alias::new("article_article_tag"))
.modify_column(ColumnDef::new(Alias::new("tenant_id")).uuid().not_null())
.to_owned(),
)
.await?;
// 添加索引
manager
.create_index(
Index::create()
.name("idx_article_article_tag_tenant_id")
.table(Alias::new("article_article_tag"))
.col(Alias::new("tenant_id"))
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_index(
Index::drop()
.name("idx_article_article_tag_tenant_id")
.to_owned(),
)
.await?;
manager
.alter_table(
Table::alter()
.table(Alias::new("article_article_tag"))
.drop_column(Alias::new("updated_at"))
.drop_column(Alias::new("created_at"))
.drop_column(Alias::new("deleted_at"))
.drop_column(Alias::new("tenant_id"))
.to_owned(),
)
.await
}
}

View File

@@ -0,0 +1,33 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Alias::new("vital_signs_hourly"))
.add_column(
ColumnDef::new(Alias::new("deleted_at"))
.timestamp_with_time_zone()
.null(),
)
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Alias::new("vital_signs_hourly"))
.drop_column(Alias::new("deleted_at"))
.to_owned(),
)
.await
}
}