fix: P0/P1 安全与质量缺陷修复 — 10 项 QA 审查问题解决
Some checks failed
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled

P0 安全修复:
- tenant_rls: SQL 拼接改为参数化查询防止注入
- follow_up_service: UUID SQL 拼接改为参数化原生查询
- RLS 策略: 新迁移移除空字符串绕过条件
- SSE 消息推送: token 键名 'token' → 'access_token' 修复
- rate_limit: 登录端点 Redis 不可达时 fail-close

P1 质量修复:
- 小程序缓存清理: preservedKeys 补全认证键名
- 小程序 token 刷新: 失败时清除所有认证数据
- 小程序 401: redirectTo → reLaunch 兼容 tabBar
- 集成测试: 信号量限制并行数据库创建(4个)
- change_password: 乐观锁 version 硬编码 → 动态递增

测试: 516 全部通过 (含 153 集成测试)
This commit is contained in:
iven
2026-04-28 00:57:41 +08:00
parent 3d34e021a9
commit 9dd6095e77
11 changed files with 391 additions and 21 deletions

View File

@@ -13,7 +13,7 @@ export default function Settings() {
content: '确定要清除本地缓存数据吗?不会影响账号信息。',
}).then((res) => {
if (res.confirm) {
const preservedKeys = ['user', 'current_patient', 'current_patient_id', 'tenant_id', 'wechat_openid'];
const preservedKeys = ['access_token', 'refresh_token', 'user_data', 'user_roles', 'tenant_id', 'wechat_openid', 'current_patient', 'current_patient_id'];
const preservedData: Record<string, unknown> = {};
for (const key of preservedKeys) {
const val = Taro.getStorageSync(key);

View File

@@ -49,6 +49,10 @@ async function doRefresh(): Promise<boolean> {
}
secureRemove('access_token');
secureRemove('refresh_token');
secureRemove('user_data');
secureRemove('user_roles');
secureRemove('tenant_id');
secureRemove('wechat_openid');
return false;
}
@@ -69,7 +73,7 @@ export async function request<T>(method: string, path: string, data?: unknown):
const pages = Taro.getCurrentPages();
const currentPath = pages[pages.length - 1]?.path || '';
if (!currentPath.includes('pages/login')) {
Taro.redirectTo({ url: '/pages/login/index' });
Taro.reLaunch({ url: '/pages/login/index' });
}
throw new Error('登录已过期');
}