feat: Iteration 1 — 审计日志IP记录、文件上传、医护端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

Iteration 1 六项任务全部完成:

1. 审计日志IP记录 — task_local RequestInfo 自动注入 IP/user_agent
2. 文件上传服务 — multipart 上传 + ServeDir 静态文件服务
3. 医护端后端API — 医生工作台仪表盘 + 患者标签CRUD + 会话已读
4. 小程序角色切换 — 登录后根据角色跳转医护台/患者首页
5. 小程序安全加固 — secure-storage 开发模式警告
6. 讨论记录归档 — docs/discussions/
This commit is contained in:
iven
2026-04-26 13:13:25 +08:00
parent 1326b3e504
commit a0b72b0f73
21 changed files with 679 additions and 12 deletions

View File

@@ -3,6 +3,8 @@ use axum::http::Request;
use axum::middleware::Next;
use axum::response::Response;
use erp_core::error::AppError;
use erp_core::request_info::REQUEST_INFO;
use erp_core::request_info::RequestInfo;
use erp_core::types::TenantContext;
use crate::service::token_service::TokenService;
@@ -13,6 +15,9 @@ use crate::service::token_service::TokenService;
/// using `TokenService::decode_token`, and injects a `TenantContext` into the
/// request extensions so downstream handlers can access tenant/user identity.
///
/// 同时提取请求的 IP 地址和 User-Agent通过 task_local 传递给审计服务,
/// 使所有审计日志自动记录来源信息。
///
/// The `jwt_secret` parameter is passed explicitly by the server crate at
/// middleware construction time, avoiding any circular dependency between
/// erp-auth and erp-server.
@@ -58,6 +63,9 @@ pub async fn jwt_auth_middleware_fn(
None => vec![],
};
// 提取请求来源信息IP + User-Agent用于审计日志
let request_info = RequestInfo::from_headers(req.headers());
let ctx = TenantContext {
tenant_id: claims.tid,
user_id: claims.sub,
@@ -72,7 +80,8 @@ pub async fn jwt_auth_middleware_fn(
let mut req = Request::from_parts(parts, body);
req.extensions_mut().insert(ctx);
Ok(next.run(req).await)
// 在 task_local scope 中运行后续处理,审计服务可自动读取请求信息
Ok(REQUEST_INFO.scope(request_info, next.run(req)).await)
}
/// 查询用户所属的所有部门 ID通过 user_departments 关联表)