From b2d95dcff7acd0ac9b95b38454a83bb1aceb76dc Mon Sep 17 00:00:00 2001 From: let5sne Date: Tue, 14 Jul 2026 10:10:08 +0800 Subject: [PATCH] fix(aihr): fail safe on mobile identity lookup --- .../aihr/controller/AihrMobileController.java | 18 +++++++++++++----- .../service/AihrPracticeSeedServiceTest.java | 2 ++ docs/BRD_IMPLEMENTATION_AUDIT.md | 1 + scripts/demo-check.sh | 1 + 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrMobileController.java b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrMobileController.java index 7f3d3742..5f313e5c 100644 --- a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrMobileController.java +++ b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrMobileController.java @@ -5,6 +5,7 @@ import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.stp.StpUtil; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.dromara.aihr.domain.AihrPracticeDto.AnnotationResponse; import org.dromara.aihr.domain.AihrPracticeDto.CompetencyResponse; import org.dromara.aihr.domain.AihrPracticeDto.DailyDrillAnswerRequest; @@ -20,6 +21,7 @@ import org.dromara.aihr.domain.AihrPracticeDto.ReviewAdviceRequest; import org.dromara.aihr.domain.AihrPracticeDto.ReviewDetailResponse; import org.dromara.aihr.domain.AihrPracticeDto.SatisfactionRequest; import org.dromara.aihr.domain.AihrPracticeDto.SatisfactionResponse; +import org.dromara.aihr.domain.AihrOrgSyncDto.OrgPersonRow; import org.dromara.aihr.domain.vo.AihrMobileDto.HomeResponse; import org.dromara.aihr.domain.vo.AihrMobileDto.IdentityResponse; import org.dromara.aihr.service.AihrOrgSyncService; @@ -48,6 +50,7 @@ import java.util.Map; * Mobile H5 home APIs. */ @RequiredArgsConstructor +@Slf4j @RestController @RequestMapping("/api/aihr/mobile") @SaCheckLogin @@ -73,11 +76,16 @@ public class AihrMobileController { if (phone.isBlank()) { return R.ok(new IdentityResponse("user", "员工端", "", "一线")); } - var snapshot = orgSyncService.snapshot(phone, null, null, "active", 1, 500, 500); - var row = snapshot.rows().stream() - .filter(person -> "主管".equals(person.positionLevel()) || "项目经理".equals(person.positionLevel())) - .findFirst() - .or(() -> snapshot.rows().stream().findFirst()); + var row = java.util.Optional.empty(); + try { + var snapshot = orgSyncService.snapshot(phone, null, null, "active", 1, 500, 500); + row = snapshot.rows().stream() + .filter(person -> "主管".equals(person.positionLevel()) || "项目经理".equals(person.positionLevel())) + .findFirst() + .or(() -> snapshot.rows().stream().findFirst()); + } catch (RuntimeException ex) { + log.warn("mobile identity lookup failed, fallback to employee role(处理错误已隐藏)"); + } if (row.isEmpty()) { return R.ok(new IdentityResponse("user", "员工端", "", "一线")); } diff --git a/backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrPracticeSeedServiceTest.java b/backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrPracticeSeedServiceTest.java index fe178ef9..b7652b16 100644 --- a/backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrPracticeSeedServiceTest.java +++ b/backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrPracticeSeedServiceTest.java @@ -395,6 +395,8 @@ public class AihrPracticeSeedServiceTest { assertTrue(controllerSource.contains("mobileSeedService.practiceAlerts(supervisorScopeExtPartyId())")); assertTrue(controllerSource.contains("mobileSeedService.createPracticeAssignment(request, supervisorScopeExtPartyId())")); assertTrue(controllerSource.contains("orgSyncService.snapshot(phone, null, null, \"active\", 1, 500, 500)")); + assertTrue(controllerSource.contains("mobile identity lookup failed, fallback to employee role")); + assertTrue(controllerSource.contains("catch (RuntimeException ex)")); assertTrue(controllerSource.contains("private String supervisorScopeExtPartyId()")); assertTrue(controllerSource.contains("mobileSeedService.requireSupervisorIdentity(currentAppUsername())")); assertTrue(controllerSource.contains("@SaCheckLogin\npublic class AihrMobileController")); diff --git a/docs/BRD_IMPLEMENTATION_AUDIT.md b/docs/BRD_IMPLEMENTATION_AUDIT.md index f5cc42f1..892189bb 100644 --- a/docs/BRD_IMPLEMENTATION_AUDIT.md +++ b/docs/BRD_IMPLEMENTATION_AUDIT.md @@ -166,3 +166,4 @@ - 2026-07-14 BRD G3 面试会话归属复核:发现候选人端 `answer/finish` 原先只按客户端提交的 `sessionId` 查内存会话,未知会话还会自动创建并落库;现由控制器把当前 APP 手机号传入服务,APP 请求必须匹配启动会话的候选人 ID,外部会话和未知会话统一拒绝;后台系统调用保留原有兼容行为。新增越权/未知会话回归测试与 `demo-check` marker,未修改生产环境。 - 2026-07-14 BRD G3 对练会话归属复核:发现三角色对练的 `start` 虽已绑定 APP 手机号,但 `turn/finish` 原先可用任意会话 ID继续提交,未知会话还会回退场景并落成训练记录;现由控制器把当前 APP 手机号传入服务,移动端回合与完成操作必须匹配启动会话的 `ext_party_id`,外部/未知会话统一拒绝;后台管理端调用保留原有演示兼容行为。新增越权/未知会话回归测试与 `demo-check` marker,未修改生产环境。 - 2026-07-14 BRD G3 主管身份多记录复核:同一手机号可能对应多条在职组织记录,主管身份检查和团队范围解析现从全部匹配记录中选择“主管/项目经理”,不再因第一条记录是一线岗位而误拒主管或选错项目范围;新增多岗位手机号回归测试,未修改生产环境。 +- 2026-07-14 BRD G3 移动端角色降级复核:`/api/aihr/mobile/me` 组织快照查询异常时原先会直接返回 500,与“组织身份不可用时安全降级员工端”的口径不一致;现捕获组织查询运行时异常并返回员工端默认身份,同时仅记录固定错误提示,不泄露外部/数据库错误详情;新增源码契约 marker,未修改生产环境。 diff --git a/scripts/demo-check.sh b/scripts/demo-check.sh index cfe869fd..7399a224 100755 --- a/scripts/demo-check.sh +++ b/scripts/demo-check.sh @@ -535,6 +535,7 @@ contains backend/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthContro contains backend/ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java "aihr.sms.login-template-id" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrMobileController.java "/api/aihr/mobile" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrMobileController.java "@SaCheckLogin" +contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrMobileController.java "mobile identity lookup failed, fallback to employee role" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrMobileSeedService.java "candidateHome" echo "OK: demo routes and real-flow markers"