fix(case): restrict mobile case writes

This commit is contained in:
2026-07-14 05:16:42 +08:00
parent 7175399f50
commit cd4e930832
6 changed files with 65 additions and 2 deletions
@@ -38,16 +38,25 @@ public class AihrCaseController {
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<UploadResponse> upload(@RequestPart("file") MultipartFile file, @RequestParam(value = "projectExtOrgId", required = false) String projectExtOrgId) {
if (!canManageCases()) {
return R.fail("仅项目负责人或主管可提交案例素材");
}
return R.ok(caseService.upload(file, projectExtOrgId, currentProjectScopes()));
}
@PostMapping("/organize")
public R<OrganizeResponse> organize(@RequestBody OrganizeRequest request) {
if (!canManageCases()) {
return R.fail("仅项目负责人或主管可整理案例素材");
}
return R.ok(caseService.organize(request, currentProjectScopes()));
}
@PostMapping("/curate")
public R<CurateResponse> curate(@RequestBody CurateRequest request) {
if (!canManageCases()) {
return R.fail("仅项目负责人或主管可入库案例");
}
return R.ok(caseService.curate(request, currentProjectScopes()));
}
@@ -72,4 +81,14 @@ public class AihrCaseController {
}
return caseService.projectScopesForAppUser(loginUser.getUsername());
}
private boolean canManageCases() {
LoginUser loginUser = LoginHelper.getLoginUser();
if (loginUser != null && UserType.SYS_USER.getUserType().equals(loginUser.getUserType())) {
return true;
}
return loginUser != null
&& UserType.APP_USER.getUserType().equals(loginUser.getUserType())
&& caseService.isCaseContributor(loginUser.getUsername());
}
}
@@ -181,6 +181,31 @@ public class AihrCaseService {
}
}
public boolean isCaseContributor(String identity) {
String username = clean(identity);
if (username.isBlank()) {
return false;
}
try {
Integer count = jdbcTemplate.queryForObject("""
SELECT COUNT(*)
FROM aihr_org_snapshot
WHERE tenant_id = '000000'
AND employment_status = 'active'
AND (person_phone = ? OR ext_party_id = ?)
AND (position_level IN ('主管', '项目经理')
OR position_name LIKE '%主管%'
OR position_name LIKE '%经理%'
OR position_name LIKE '%负责人%'
OR position_name LIKE '%组长%')
""", Integer.class, username, username);
return count != null && count > 0;
} catch (DataAccessException e) {
log.warn("resolve case contributor failed: {}", e.getMessage());
return false;
}
}
private void saveCase(CaseState state, String status, String title, String summary) {
ensureCaseTable();
jdbcTemplate.update("""
@@ -305,6 +330,13 @@ public class AihrCaseService {
|| (!projectScopes.isEmpty() && projectScopes.contains(clean(projectExtOrgId)));
}
static boolean isCaseContributorPosition(String positionName, String positionLevel) {
String name = clean(positionName);
String level = clean(positionLevel);
return "主管".equals(level) || "项目经理".equals(level)
|| name.contains("主管") || name.contains("经理") || name.contains("负责人") || name.contains("组长");
}
private String resolveUploadProject(String requestedProject, List<String> projectScopes) {
if (projectScopes == null) {
return firstNonBlank(requestedProject, "");
@@ -82,6 +82,16 @@ class AihrCaseServiceTest {
assertTrue(AihrCaseService.caseProjectAllowed("P1", null));
}
@Test
@Tag("dev")
void caseContributorPositionRecognizesProjectManagersAndLeads() {
assertTrue(AihrCaseService.isCaseContributorPosition("项目经理", "一线"));
assertTrue(AihrCaseService.isCaseContributorPosition("招商主管", "一线"));
assertTrue(AihrCaseService.isCaseContributorPosition("项目负责人", "一线"));
assertTrue(AihrCaseService.isCaseContributorPosition("普通员工", "主管"));
assertFalse(AihrCaseService.isCaseContributorPosition("普通员工", "一线"));
}
private static class CaseJdbcTemplate extends JdbcTemplate {
private Object[] updateArgs = new Object[0];