charging-cabinet/tasks/013-critical-fixes.md

154 lines
4.2 KiB
Markdown
Raw Normal View History

# 任务013严重问题修复
## 目标
修复全面代码审查发现的5个严重问题。
## 修复清单
### 1. 设备指令接口权限校验( 高优先级)
**位置:** `src/tcp/commands.rs`
**问题:** HTTP API接口缺少权限校验任何登录用户都能控制设备。
**修复方案:**
```rust
// 修改 send_command handler
pub async fn send_command(
user: CurrentUser, // 新增
State(state): State<AppState>,
Path(dev_id): Path<String>,
Json(body): Json<CommandRequest>,
) -> Result<Json<Value>, AppError> {
auth::check_permission(&user, "device:operate")?; // 新增
// ... 原有逻辑
}
// 修改 get_online_devices handler
pub async fn get_online_devices(
user: CurrentUser, // 新增
State(state): State<AppState>,
) -> Result<Json<Value>, AppError> {
auth::check_permission(&user, "device:view")?; // 新增
// ... 原有逻辑
}
```
### 2. 组织树接口权限校验和数据隔离(🔴 高优先级)
**位置:** `src/routes/cabinet_tree.rs`
**问题:** 组织树接口无权限校验,且未做数据隔离,用户能看到所有组织的数据。
**修复方案:**
```rust
pub async fn get_organization_tree(
user: CurrentUser, // 新增
State(state): State<AppState>,
) -> Result<Json<Value>, AppError> {
auth::check_permission(&user, "device:view")?; // 新增
let db = &state.mysql;
// 根据角色过滤数据
let orgs = if user.role_level >= 2 {
// 总管理员看所有组织
sqlx::query_as::<_, OrganizationRow>("SELECT id, name FROM organizations ORDER BY id")
.fetch_all(db)
.await?
} else if let Some(org_id) = user.organization_id {
// 企业管理员只看本组织
sqlx::query_as::<_, OrganizationRow>(
"SELECT id, name FROM organizations WHERE id = ? ORDER BY id"
)
.bind(org_id)
.fetch_all(db)
.await?
} else {
vec![] // 无组织用户看不到数据
};
// ... 构建树状结构
}
```
### 3. 默认密码硬编码(🔴 中优先级)
**位置:** `src/routes/users.rs`
**问题:** 默认密码 "123456" 硬编码在代码中。
**修复方案:**
```rust
// config.rs 添加默认密码配置
pub const DEFAULT_PASSWORD: &str = "123456"; // 或从环境变量读取
// users.rs 使用配置
use crate::config::DEFAULT_PASSWORD;
// 创建用户时
let password = body.password.unwrap_or_else(|| DEFAULT_PASSWORD.to_string());
let hashed = auth::hash_password(&password)?;
```
### 4. auth_str安全码明文打印到日志🔴 中优先级)
**位置:** `src/routes/organizations.rs``src/tcp/handler.rs`
**问题:** auth_str安全码明文打印到日志存在泄露风险。
**修复方案:**
```rust
// 修改日志输出只打印前2位+***
tracing::info!(
"生成安全码 id={} auth_str={}***",
id,
&auth_str[..2]
);
// 或完全不打印auth_str
tracing::info!("生成安全码 id={}", id);
```
### 5. 前端刷新后用户信息丢失(🔴 中优先级)
**位置:** `src/stores/auth.ts``src/App.tsx`
**问题:** 页面刷新后虽然token在localStorage但用户信息permissions等未恢复导致权限按钮消失。
**修复方案:**
```tsx
// stores/auth.ts 添加 restore 方法
const restoreAuth = async () => {
const token = localStorage.getItem('token');
if (!token) return false;
try {
const user = await api.get('/auth/me');
setToken(token);
setUser(user);
setPermissions(user.permissions);
return true;
} catch {
localStorage.removeItem('token');
return false;
}
};
// App.tsx 或 AdminLayout.tsx 中调用
useEffect(() => {
restoreAuth();
}, []);
```
## 质量约束
1. 完成代码后执行 `cargo check` + `cargo clippy` + `tsc --noEmit`,零报错零警告
2. 分层拆分单函数≤80行命名语义化完整注释
3. 所有外部IO/网络请求异常捕获禁止裸panic
4. 分支逻辑全覆盖,不遗漏兜底分支
5. 常量抽离不使用废弃API
6. Rust内存安全React函数组件+Hooks
7. 修复后重新运行审查清单中的安全项目,确保全部通过