From 217edb09d29429e004295e736902b463bd1fa99d Mon Sep 17 00:00:00 2001 From: let5sne Date: Wed, 15 Jul 2026 01:12:36 +0800 Subject: [PATCH] fix(aihr): reject unknown interview sessions --- .../dromara/aihr/service/AihrInterviewService.java | 2 +- .../aihr/service/AihrInterviewServiceTest.java | 13 +++++++++++++ docs/BRD_IMPLEMENTATION_AUDIT.md | 1 + scripts/demo-check.sh | 1 + 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrInterviewService.java b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrInterviewService.java index 783f7576..365e535a 100644 --- a/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrInterviewService.java +++ b/backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrInterviewService.java @@ -629,7 +629,7 @@ public class AihrInterviewService { } private static void requireSessionTenant(InterviewSession session, String tenantId) { - if (session != null && !clean(tenantId).equals(clean(session.tenantId()))) { + if (session == null || !clean(tenantId).equals(clean(session.tenantId()))) { throw new IllegalArgumentException("面试会话不存在或无权访问"); } } diff --git a/backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrInterviewServiceTest.java b/backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrInterviewServiceTest.java index 58d1c01e..5f990741 100644 --- a/backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrInterviewServiceTest.java +++ b/backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrInterviewServiceTest.java @@ -334,6 +334,19 @@ class AihrInterviewServiceTest { service.answer(new AnswerRequest(ownerSession.sessionId(), "q1", "本人回答", null), "candidate-a"); } + @Test + @Tag("dev") + void interviewAnswerRejectsUnknownSessionForSystemFlow() { + JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class); + AihrInterviewService service = new AihrInterviewService(new ObjectMapper(), null, jdbcTemplate); + + IllegalArgumentException error = assertThrows(IllegalArgumentException.class, () -> service.answer( + new AnswerRequest("iv-not-started", "q1", "不存在会话的回答", null) + )); + + assertEquals("面试会话不存在或无权访问", error.getMessage()); + } + @Test @Tag("dev") void interviewMemorySessionsCarryTenantBoundary() throws Exception { diff --git a/docs/BRD_IMPLEMENTATION_AUDIT.md b/docs/BRD_IMPLEMENTATION_AUDIT.md index 8b446729..214c4896 100644 --- a/docs/BRD_IMPLEMENTATION_AUDIT.md +++ b/docs/BRD_IMPLEMENTATION_AUDIT.md @@ -406,3 +406,4 @@ - 2026-07-14 BRD 4.3.4 场景 schema 发布补齐:只读核验发现生产缺少 `aihr_practice_scenario`、`aihr_practice_rubric`、`aihr_practice_rubric_dimension` 三张表;现新增只建结构的 `aihr_20260714_practice_catalog_schema_mysql8.sql`,并让补充场景迁移显式依赖该基础迁移。未写入生产数据,正式发布仍需按顺序执行基础 schema、场景 seed 与 SOP seed 迁移。 - 2026-07-14 BRD 4.7 住宅 SOP 内容补齐:原知识库只有 3 份已解析住宅 SOP;现新增增值服务需求识别、日常服务回访两份 SOP 及各 3 个检索片段,reset SQL 与版本化迁移同步,临时库连续执行两次保持幂等。严格门禁已从 `sop_docs=3/5` 推进到 `5/5`;案例库、正式组织身份和正式试点证据仍未完成。 - 2026-07-15 BRD G3 候选人面试操作角色边界修复:`/api/recruit/interview/start`、`answer`、`finish` 此前只要求登录,普通后台系统用户可绕过 HR/管理员权限创建或完成面试;现统一限制为 APP 候选人本人或 `superadmin/hr_operator`,候选人会话仍按本人手机号绑定。新增源码契约测试和 `demo-check` marker;尚未发布生产。 +- 2026-07-15 BRD G3 面试未知会话状态边界修复:系统用户调用 `answer` 携带不存在或已失效的 `sessionId` 此前会返回“已暂存”而不暴露会话无效;现统一要求会话存在且属于当前租户,`finish` 保留 HR 管理端既有的兼容性创建逻辑。新增服务回归测试和 `demo-check` marker;尚未发布生产。 diff --git a/scripts/demo-check.sh b/scripts/demo-check.sh index 0d2f1a79..d5c23862 100755 --- a/scripts/demo-check.sh +++ b/scripts/demo-check.sh @@ -509,6 +509,7 @@ contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/control contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrInterviewController.java "无权查看面试记录" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrInterviewController.java "/records/{sessionId}/review" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrInterviewService.java "reviewed_score" +contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrInterviewService.java "session == null || !clean(tenantId).equals(clean(session.tenantId()))" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrInterviewController.java "interviewService.answer(request, currentAppUsername())" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrInterviewController.java "interviewService.finish(request, currentAppUsername())" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrInterviewService.java "面试会话不存在或无权访问"