fix: E2E 测试发现的后端 BUG 修复 — 限流拆分 + 积分查询 + 错误码修正

- 拆分 refresh token 限流为独立中间件(30次/分 vs 登录5次/分)
- 修复积分 recent-activity 500:JOIN 通过 points_account 中间表
- 修复患者/医生不存在返回 400 → 正确的 404 NotFound
This commit is contained in:
iven
2026-05-15 22:58:02 +08:00
parent 50e3b16381
commit bf8bcdbd5d
5 changed files with 46 additions and 7 deletions

View File

@@ -40,10 +40,7 @@ struct RateLimitResponse {
const ACCOUNT_LOCKOUT_MAX_FAILURES: i64 = 5;
const ACCOUNT_LOCKOUT_TTL_SECS: i64 = 900; // 15 分钟
/// 基于 Redis 的 IP 限流中间件。
///
/// 使用 INCR + EXPIRE 实现固定窗口计数器。
/// 超限返回 HTTP 429 Too Many Requests。
/// 基于 Redis 的 IP 限流中间件登录等敏感操作5 次/分钟)
pub async fn rate_limit_by_ip(
State(state): State<AppState>,
req: Request<Body>,
@@ -66,6 +63,29 @@ pub async fn rate_limit_by_ip(
.await
}
/// 基于 Redis 的 IP 限流中间件Token 刷新30 次/分钟)。
pub async fn rate_limit_refresh_by_ip(
State(state): State<AppState>,
req: Request<Body>,
next: Next,
) -> Response {
let identifier = extract_client_ip(req.headers());
let fail_close = state.config.rate_limit.fail_close;
apply_rate_limit(
RateLimitParams {
redis_client: &state.redis,
fail_close,
max_requests: 30,
window_secs: 60,
prefix: "refresh",
},
&identifier,
req,
next,
)
.await
}
/// 基于 Redis 的用户限流中间件。
///
/// 从 TenantContext 中读取 user_id 作为标识符。