6.2 KiB
6.2 KiB
任务015:Nemotron审查问题修复
目标
修复Nemotron审查发现的7个严重问题。
修复清单
1. 权限码种子数据缺失( 高优先级)
位置: src/db/migrate.rs
问题: org:*、project:*、device:edit 等权限码未在seed_permissions中初始化。
修复方案:
// 在 seed_permissions 函数中添加缺失的权限码
let permissions = vec![
// ... 已有的权限码
// 组织管理
("org:view", "查看组织"),
("org:create", "创建组织"),
("org:edit", "编辑组织"),
("org:delete", "删除组织"),
// 项目管理
("project:view", "查看项目"),
("project:create", "创建项目"),
("project:edit", "编辑项目"),
("project:delete", "删除项目"),
// 设备管理(补充)
("device:edit", "编辑设备"),
];
// 插入数据库(使用 INSERT IGNORE 避免重复)
for (code, name) in permissions {
sqlx::query(
"INSERT IGNORE INTO permissions (code, name) VALUES (?, ?)"
)
.bind(code)
.bind(name)
.execute(pool)
.await?;
}
角色权限分配:
// 总管理员 — 全部权限
// 企业管理员 — 添加 org:*, project:*, device:edit 权限
// 普通用户 — 只保留 view 权限
2. H5接口数据隔离(🔴 高优先级)
位置: src/routes/h5.rs
问题: get_dashboard返回全局统计数据,get_cabinet_detail/get_compartment_detail无权限校验。
修复方案:
/// GET /api/h5/dashboard — H5首页数据(带组织隔离)
pub async fn get_dashboard(
user: CurrentUser,
State(state): State<AppState>,
) -> Result<Json<Value>, AppError> {
auth::check_permission(&user, "device:view")?;
let db = &state.mysql;
// 根据角色过滤数据
let org_filter = if user.role_level >= 2 {
None // 总管理员看全部
} else {
user.organization_id // 企业管理员只看本组织
};
// 查询柜子统计(带组织过滤)
let cabinet_stats = if let Some(org_id) = org_filter {
sqlx::query_as::<_, (i64, i64, i64, i64)>(
r#"SELECT
COUNT(*) as total,
SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) as online,
SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END) as charging,
SUM(CASE WHEN status = 3 THEN 1 ELSE 0 END) as fault
FROM cabinets c
INNER JOIN projects p ON c.project_id = p.id
WHERE p.organization_id = ?"#
)
.bind(org_id)
.fetch_one(db)
.await?
} else {
// 总管理员查询全部
// ...
};
Ok(Json(json!({
"total": cabinet_stats.0,
"online": cabinet_stats.1,
"charging": cabinet_stats.2,
"fault": cabinet_stats.3
})))
}
/// GET /api/h5/cabinets/:id — H5设备详情(带权限校验)
pub async fn get_cabinet_detail(
user: CurrentUser,
State(state): State<AppState>,
Path(id): Path<i64>,
) -> Result<Json<Value>, AppError> {
auth::check_permission(&user, "device:view")?;
let db = &state.mysql;
// 验证用户是否有权访问该设备
if user.role_level < 2 {
if let Some(org_id) = user.organization_id {
let access: Option<(i64,)> = sqlx::query_as(
r#"SELECT c.id FROM cabinets c
INNER JOIN projects p ON c.project_id = p.id
WHERE c.id = ? AND p.organization_id = ?"#
)
.bind(id)
.bind(org_id)
.fetch_optional(db)
.await?;
if access.is_none() {
return Err(AppError::Forbidden("无权访问该设备".into()));
}
} else {
return Err(AppError::Forbidden("无组织关联".into()));
}
}
// ... 原有查询逻辑
}
3. 前后端H5告警字段匹配(🔴 中优先级)
位置: src/routes/h5.rs 和 src/h5/pages/home.tsx
问题: 后端返回{compartment_id, cabinet_id},前端期望{project, cabinet}。
修复方案(后端):
// 修改告警查询,返回前端期望的字段
let alerts = sqlx::query_as::<_, (String, String, String)>(
r#"SELECT
p.name as project,
cab.name as cabinet,
dl.content as message
FROM device_logs dl
INNER JOIN cabinets cab ON dl.cabinet_id = cab.id
INNER JOIN projects p ON cab.project_id = p.id
WHERE dl.log_type = 3 -- 告警
ORDER BY dl.created_at DESC
LIMIT 10"#
)
.fetch_all(db)
.await?;
Ok(Json(json!({
"alerts": alerts.iter().map(|(project, cabinet, message)| {
json!({
"project": project,
"cabinet": cabinet,
"message": message
})
}).collect::<Vec<_>>()
})))
4. 其他严重问题修复
4.1 SQL参数化(charge_records.rs)
// 确保所有SQL查询使用参数化绑定
// 检查并修复任何 format! 拼接SQL的地方
4.2 数据库索引(migrate.rs)
// 添加关键索引
sqlx::query("CREATE INDEX idx_cabinets_project ON cabinets(project_id)")
.execute(pool).await?;
sqlx::query("CREATE INDEX idx_charge_records_cabinet ON charge_records(cabinet_id)")
.execute(pool).await?;
sqlx::query("CREATE INDEX idx_device_logs_cabinet ON device_logs(cabinet_id)")
.execute(pool).await?;
4.3 消除重复代码
// 提取公共的组织过滤逻辑到 middleware/auth.rs
pub fn org_condition(user: &CurrentUser) -> String {
if user.role_level >= 2 {
String::new()
} else if let Some(org_id) = user.organization_id {
format!("AND organization_id = {}", org_id)
} else {
"AND 1=0".to_string()
}
}
质量约束
- 完成代码后执行
cargo check+cargo clippy+tsc --noEmit,零报错零警告 - 分层拆分,单函数≤80行,命名语义化,完整注释
- 所有外部IO/网络请求异常捕获,禁止裸panic
- 分支逻辑全覆盖,不遗漏兜底分支
- 常量抽离,不使用废弃API
- Rust内存安全,React函数组件+Hooks
- H5接口必须添加权限校验和组织数据隔离