charging-cabinet/tasks/013-critical-fixes.md
2026-07-02 05:38:01 +08:00

154 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 任务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. 修复后重新运行审查清单中的安全项目,确保全部通过