fix(miniprogram): 小程序审计修复 — 安全加固+功能链路+输入验证
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

安全修复:
- H1: Token 刷新竞态条件 → Singleton Promise 模式防止并发刷新
- H4: 移除 store 中的 token 明文状态,统一走 secure storage
- H5: 登录/绑定手机号添加 loading 防重复点击保护
- H6: Analytics 改用 request.ts 统一请求层,不再绕过认证
- M1: logout 清理所有残留数据(openid/tenant_id/analytics_queue)
- M2/M7: 敏感数据(user/openid/tenant_id)统一走加密存储
- M3: 移除开发日志中的请求体打印
- M4: secure-storage 解密失败返回 null 而非空串

功能修复:
- F1: 今日体征概览 API 支持 patient_id 查询参数(后端+前端)
- F2: 积分商城对无患者档案用户展示引导 UI
- M6: daily-monitoring 添加 Zod 数值范围验证

清理:
- L4: 移除 devLogin 开发辅助函数
This commit is contained in:
iven
2026-04-27 00:41:30 +08:00
parent 2defbd7ab3
commit 3424a33b6b
12 changed files with 198 additions and 63 deletions

View File

@@ -388,6 +388,7 @@ where
pub async fn get_mini_today<S>(
State(state): State<HealthState>,
Extension(ctx): Extension<TenantContext>,
Query(params): Query<MiniTodayParams>,
) -> Result<Json<ApiResponse<MiniTodayResp>>, AppError>
where
HealthState: FromRef<S>,
@@ -395,12 +396,19 @@ where
{
require_permission(&ctx, "health.health-data.list")?;
let result = trend_service::get_mini_today(
&state, ctx.tenant_id, ctx.user_id,
&state, ctx.tenant_id, ctx.user_id, params.patient_id,
)
.await?;
Ok(Json(ApiResponse::ok(result)))
}
/// 小程序今日体征请求参数
#[derive(Debug, serde::Deserialize, utoipa::IntoParams)]
pub struct MiniTodayParams {
/// 可选:直接指定患者 ID小程序传入当前选中患者
pub patient_id: Option<Uuid>,
}
// ---------------------------------------------------------------------------
// 带版本号的更新请求包装
// ---------------------------------------------------------------------------

View File

@@ -414,8 +414,14 @@ pub async fn get_mini_today(
state: &HealthState,
tenant_id: Uuid,
user_id: Uuid,
explicit_patient_id: Option<Uuid>,
) -> HealthResult<MiniTodayResp> {
let patient_id = find_patient_by_user_id(state, tenant_id, user_id).await?;
// 优先使用显式传入的 patient_id小程序端传入当前选中患者
let patient_id = if let Some(pid) = explicit_patient_id {
Some(pid)
} else {
find_patient_by_user_id(state, tenant_id, user_id).await?
};
let Some(patient_id) = patient_id else {
return Ok(MiniTodayResp {