fix(release): close fixed-code mobile auth gaps
This commit is contained in:
+23
-19
@@ -92,10 +92,11 @@ public class AihrMobileController {
|
||||
}
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
String identity = currentAppUsername();
|
||||
if (loginUser == null
|
||||
|| !UserType.APP_USER.getUserType().equals(loginUser.getUserType())
|
||||
|| identity.isBlank()) {
|
||||
return R.ok(mobileSeedService.publicHome(role));
|
||||
if (loginUser == null || identity.isBlank()) {
|
||||
throw new ServiceException("移动端登录身份缺失,请重新登录");
|
||||
}
|
||||
if (!UserType.APP_USER.getUserType().equals(loginUser.getUserType())) {
|
||||
throw new ServiceException("后台管理账号不能使用移动端员工首页");
|
||||
}
|
||||
String resolvedIdentity = identity;
|
||||
if (supervisorRoleRequested(role)) {
|
||||
@@ -114,36 +115,39 @@ public class AihrMobileController {
|
||||
public R<IdentityResponse> me() {
|
||||
String phone = currentAppUsername();
|
||||
if (phone.isBlank()) {
|
||||
return R.ok(new IdentityResponse("user", "员工端", "", "一线", List.of()));
|
||||
throw new ServiceException("移动端登录身份缺失,请重新登录");
|
||||
}
|
||||
// APP username is a phone number. Validate it before it reaches the
|
||||
// organization lookup so a phone-shaped external ID cannot borrow
|
||||
// another employee's role or project scope.
|
||||
mobileSeedService.requireMobileIdentity(phone);
|
||||
List<OrgPersonRow> people = List.of();
|
||||
var row = java.util.Optional.<OrgPersonRow>empty();
|
||||
List<OrgPersonRow> people;
|
||||
try {
|
||||
var snapshotPeople = orgSyncService.activeByMobilePhone(phone);
|
||||
people = snapshotPeople;
|
||||
row = snapshotPeople.stream()
|
||||
.filter(person -> "主管".equals(person.positionLevel()) || "项目经理".equals(person.positionLevel()))
|
||||
.findFirst()
|
||||
.or(() -> snapshotPeople.stream().findFirst());
|
||||
people = orgSyncService.activeByMobilePhone(phone);
|
||||
} catch (RuntimeException ex) {
|
||||
log.warn("mobile identity lookup failed, fallback to employee role(处理错误已隐藏)");
|
||||
log.warn("mobile identity lookup failed closed: {}", ex.getClass().getSimpleName());
|
||||
throw new ServiceException("组织身份加载失败,请稍后重试");
|
||||
}
|
||||
if (row.isEmpty()) {
|
||||
return R.ok(new IdentityResponse("user", "员工端", "", "一线", List.of()));
|
||||
return R.ok(identityResponse(people));
|
||||
}
|
||||
|
||||
static IdentityResponse identityResponse(List<OrgPersonRow> people) {
|
||||
if (people == null || people.isEmpty()) {
|
||||
throw new ServiceException("未找到有效的在职组织身份,请联系管理员");
|
||||
}
|
||||
var person = row.get();
|
||||
var person = people.stream()
|
||||
.filter(item -> "主管".equals(item.positionLevel()) || "项目经理".equals(item.positionLevel()))
|
||||
.findFirst()
|
||||
.or(() -> people.stream().findFirst())
|
||||
.orElseThrow(() -> new ServiceException("未找到有效的在职组织身份,请联系管理员"));
|
||||
boolean supervisor = "主管".equals(person.positionLevel()) || "项目经理".equals(person.positionLevel());
|
||||
return R.ok(new IdentityResponse(
|
||||
return new IdentityResponse(
|
||||
supervisor ? "supervisor" : "user",
|
||||
supervisor ? "主管端" : "员工端",
|
||||
person.positionName(),
|
||||
person.positionLevel(),
|
||||
projectOptions(people)
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
static List<ProjectResponse> projectOptions(List<OrgPersonRow> people) {
|
||||
|
||||
+26
-1
@@ -1,12 +1,14 @@
|
||||
package org.dromara.aihr.controller;
|
||||
|
||||
import org.dromara.aihr.domain.AihrOrgSyncDto.OrgPersonRow;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@Tag("dev")
|
||||
class AihrMobileControllerTest {
|
||||
@@ -27,8 +29,31 @@ class AihrMobileControllerTest {
|
||||
assertEquals("星河湾一期", projects.get(1).projectName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void identityResponsePrefersSupervisorAndKeepsProjectOptions() {
|
||||
var rows = List.of(
|
||||
row(1L, "P2", "星河湾二期", "一线"),
|
||||
row(2L, "P1", "星河湾一期", "主管")
|
||||
);
|
||||
|
||||
var response = AihrMobileController.identityResponse(rows);
|
||||
|
||||
assertEquals("supervisor", response.role());
|
||||
assertEquals("主管端", response.roleLabel());
|
||||
assertEquals(List.of("P1", "P2"), response.projects().stream().map(item -> item.projectCode()).toList());
|
||||
}
|
||||
|
||||
@Test
|
||||
void identityResponseFailsClosedWithoutActiveOrganizationRows() {
|
||||
assertThrows(ServiceException.class, () -> AihrMobileController.identityResponse(List.of()));
|
||||
}
|
||||
|
||||
private static OrgPersonRow row(Long id, String projectCode, String projectName) {
|
||||
return row(id, projectCode, projectName, "一线");
|
||||
}
|
||||
|
||||
private static OrgPersonRow row(Long id, String projectCode, String projectName, String positionLevel) {
|
||||
return new OrgPersonRow(id, projectCode, projectName, "客服部", "employee-1", "王敏",
|
||||
"生活顾问", "一线", "active", "2026-07-21");
|
||||
"生活顾问", positionLevel, "active", "2026-07-21");
|
||||
}
|
||||
}
|
||||
|
||||
+9
-1
@@ -1602,8 +1602,11 @@ public class AihrPracticeSeedServiceTest {
|
||||
assertTrue(controllerSource.contains("mobileSeedService.practiceAlerts(supervisorScopeExtPartyId())"));
|
||||
assertTrue(controllerSource.contains("mobileSeedService.createPracticeAssignment(request, supervisorScopeExtPartyId())"));
|
||||
assertTrue(controllerSource.contains("orgSyncService.activeByMobilePhone(phone)"));
|
||||
assertTrue(controllerSource.contains("mobile identity lookup failed, fallback to employee role"));
|
||||
assertTrue(controllerSource.contains("mobile identity lookup failed closed"));
|
||||
assertTrue(controllerSource.contains("catch (RuntimeException ex)"));
|
||||
assertTrue(controllerSource.contains("throw new ServiceException(\"组织身份加载失败,请稍后重试\")"));
|
||||
assertTrue(controllerSource.contains("throw new ServiceException(\"未找到有效的在职组织身份,请联系管理员\")"));
|
||||
assertFalse(controllerSource.contains("fallback to employee role"));
|
||||
assertTrue(controllerSource.contains("private String supervisorScopeExtPartyId()"));
|
||||
assertTrue(controllerSource.contains("if (isSystemOperator())"));
|
||||
assertTrue(controllerSource.contains("后台管理账号不能使用主管带教接口"));
|
||||
@@ -1623,6 +1626,11 @@ public class AihrPracticeSeedServiceTest {
|
||||
assertTrue(controllerSource.contains("if (!LoginHelper.isLogin())"));
|
||||
assertTrue(controllerSource.contains("return R.ok(mobileSeedService.publicHome(role))"));
|
||||
assertTrue(controllerSource.contains("!UserType.APP_USER.getUserType().equals(loginUser.getUserType())"));
|
||||
assertTrue(controllerSource.contains("throw new ServiceException(\"后台管理账号不能使用移动端员工首页\")"));
|
||||
assertEquals(
|
||||
controllerSource.indexOf("return R.ok(mobileSeedService.publicHome(role))"),
|
||||
controllerSource.lastIndexOf("return R.ok(mobileSeedService.publicHome(role))")
|
||||
);
|
||||
assertTrue(controllerSource.contains("return R.ok(mobileSeedService.home(role, resolvedIdentity))"));
|
||||
assertTrue(controllerSource.contains("mobileSeedService.requireMobileSupervisorIdentity(identity)"));
|
||||
assertTrue(controllerSource.contains("mobileSeedService.requireMobileIdentity(identity)"));
|
||||
|
||||
Reference in New Issue
Block a user