fix(aihr): resolve supervisor identity across roles

This commit is contained in:
2026-07-14 10:08:16 +08:00
parent 4f96df27d2
commit 20330df042
4 changed files with 29 additions and 8 deletions
@@ -2116,7 +2116,7 @@ public class AihrPracticeSeedService {
AND employment_status = 'active'
LIMIT 1
""", (rs, rowNum) -> rs.getString("position_level"), args.toArray());
if (positionLevels.isEmpty() || !canSeeProject(positionLevels.get(0))) {
if (positionLevels.stream().noneMatch(AihrPracticeSeedService::canSeeProject)) {
throw new ServiceException("无主管权限,无法访问主管功能");
}
return identity;
@@ -2149,8 +2149,11 @@ public class AihrPracticeSeedService {
if (owners.isEmpty()) {
return TeamScope.scoped(List.of());
}
OrgScopeRow row = owners.get(0);
if (!canSeeProject(row.positionLevel())) {
OrgScopeRow row = owners.stream()
.filter(scope -> canSeeProject(scope.positionLevel()))
.findFirst()
.orElse(null);
if (row == null) {
return TeamScope.scoped(List.of(owner));
}
List<String> ids = jdbcTemplate.query("""
@@ -241,6 +241,15 @@ public class AihrPracticeSeedServiceTest {
assertEquals(List.of("000000", "13900001111", "13900001111"), jdbcTemplate.authorizationArgs);
}
@Test
public void supervisorIdentityAcceptsSupervisorWhenPhoneAlsoMatchesFrontlineRow() {
SupervisorAuthorizationJdbcTemplate jdbcTemplate = new SupervisorAuthorizationJdbcTemplate(
"13900001111", List.of("一线", "主管"));
AihrPracticeSeedService service = new AihrPracticeSeedService(new ObjectMapper(), jdbcTemplate, null, null);
assertEquals("13900001111", service.requireSupervisorIdentity("13900001111"));
}
@Test
public void supervisorIdentityRejectsFrontlineUnknownAndBlankIdentity() {
SupervisorAuthorizationJdbcTemplate jdbcTemplate = new SupervisorAuthorizationJdbcTemplate(Map.of(
@@ -872,13 +881,18 @@ public class AihrPracticeSeedServiceTest {
}
private static final class SupervisorAuthorizationJdbcTemplate extends JdbcTemplate {
private final Map<String, String> positionLevels;
private final Map<String, List<String>> positionLevels;
private String authorizationSql = "";
private List<Object> authorizationArgs = List.of();
private int authorizationQueryCount;
private SupervisorAuthorizationJdbcTemplate(Map<String, String> positionLevels) {
this.positionLevels = positionLevels;
this.positionLevels = positionLevels.entrySet().stream()
.collect(java.util.stream.Collectors.toMap(Map.Entry::getKey, entry -> List.of(entry.getValue())));
}
private SupervisorAuthorizationJdbcTemplate(String identity, List<String> positionLevels) {
this.positionLevels = Map.of(identity, List.copyOf(positionLevels));
}
@Override
@@ -896,12 +910,14 @@ public class AihrPracticeSeedServiceTest {
authorizationSql = sql;
authorizationArgs = List.of(args);
authorizationQueryCount += 1;
String positionLevel = positionLevels.get(String.valueOf(args[1]));
if (positionLevel == null) {
List<String> positionRows = positionLevels.get(String.valueOf(args[1]));
if (positionRows == null) {
return List.of();
}
try {
return mapRows(rowMapper, List.of(Map.of("position_level", positionLevel)));
return mapRows(rowMapper, positionRows.stream()
.map(positionLevel -> Map.of("position_level", positionLevel))
.toList());
} catch (SQLException e) {
throw new IllegalStateException(e);
}
+1
View File
@@ -165,3 +165,4 @@
- 2026-07-14 线上资源只读核对:生产根站、`/h5/` 和 `/prod-api/auth/tenant/list` 均返回 `200`;生产管理端仍加载 `index-CJZ3Ax3Z.js`,本地当前管理端构建为 `index-D4ywKu9Y.js`。本次只读检查,未执行生产写入、静态资源同步或后端重启,因此不能把本地人工复核修复宣称为线上已生效。
- 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 主管身份多记录复核:同一手机号可能对应多条在职组织记录,主管身份检查和团队范围解析现从全部匹配记录中选择“主管/项目经理”,不再因第一条记录是一线岗位而误拒主管或选错项目范围;新增多岗位手机号回归测试,未修改生产环境。
+1
View File
@@ -400,6 +400,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/AihrPracticeController.java "practiceSeedService.turn(request, currentAppUsername())"
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrPracticeController.java "practiceSeedService.finish(request, currentAppUsername())"
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrPracticeSeedService.java "训练会话不存在或无权访问"
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrPracticeSeedService.java "noneMatch(AihrPracticeSeedService::canSeeProject)"
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrPracticeController.java "@SaCheckLogin"
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrPracticeController.java "sessions/{sessionId}/annotations"
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrPromptTemplateController.java "/api/aihr/prompt-templates"