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

4.2 KiB
Raw Blame History

任务013严重问题修复

目标

修复全面代码审查发现的5个严重问题。

修复清单

1. 设备指令接口权限校验( 高优先级)

位置: src/tcp/commands.rs

问题: HTTP API接口缺少权限校验任何登录用户都能控制设备。

修复方案:

// 修改 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

问题: 组织树接口无权限校验,且未做数据隔离,用户能看到所有组织的数据。

修复方案:

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" 硬编码在代码中。

修复方案:

// 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.rssrc/tcp/handler.rs

问题: auth_str安全码明文打印到日志存在泄露风险。

修复方案:

// 修改日志输出只打印前2位+***
tracing::info!(
    "生成安全码 id={} auth_str={}***",
    id,
    &auth_str[..2]
);

// 或完全不打印auth_str
tracing::info!("生成安全码 id={}", id);

5. 前端刷新后用户信息丢失(🔴 中优先级)

位置: src/stores/auth.tssrc/App.tsx

问题: 页面刷新后虽然token在localStorage但用户信息permissions等未恢复导致权限按钮消失。

修复方案:

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