mirror of
https://github.com/iflytek/skillhub.git
synced 2026-08-27 11:14:59 +00:00
fix(auth): guard SUPER_ADMIN role mutations
Signed-off-by: dongmucat <1127093059@qq.com>
This commit is contained in:
parent
06cc523a0c
commit
3a254d7524
5 changed files with 24 additions and 6 deletions
|
|
@ -319,7 +319,7 @@ Admin API 按最小权限拆分,不再统一要求 SUPER_ADMIN:
|
|||
|------|------|------|
|
||||
| GET | `/api/v1/admin/users` | 用户列表 |
|
||||
| GET | `/api/v1/admin/users/{id}` | 用户详情 |
|
||||
| PUT | `/api/v1/admin/users/{id}/roles` | 修改用户角色(USER_ADMIN 不可分配 SUPER_ADMIN) |
|
||||
| PUT | `/api/v1/admin/users/{id}/role` | 修改用户角色(USER_ADMIN 不可分配 SUPER_ADMIN,也不可修改已有 SUPER_ADMIN 的角色状态) |
|
||||
| POST | `/api/v1/admin/users/{id}/approve` | 审批待准入用户 |
|
||||
| POST | `/api/v1/admin/users/{id}/disable` | 封禁用户 |
|
||||
| POST | `/api/v1/admin/users/{id}/enable` | 解封用户 |
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ import java.util.stream.Collectors;
|
|||
public class AdminUserAppService {
|
||||
|
||||
private static final Set<UserStatus> MANAGEABLE_STATUSES = Set.of(UserStatus.ACTIVE, UserStatus.DISABLED);
|
||||
private static final String SUPER_ADMIN_ROLE = "SUPER_ADMIN";
|
||||
private static final String USER_ROLE = "USER";
|
||||
|
||||
private final AdminUserSearchRepository adminUserSearchRepository;
|
||||
private final UserAccountRepository userAccountRepository;
|
||||
|
|
@ -83,15 +85,17 @@ public class AdminUserAppService {
|
|||
UserAccount user = loadUser(userId);
|
||||
rejectSystemAccountMutation(user);
|
||||
String normalizedRoleCode = normalizeRoleCode(roleCode);
|
||||
boolean targetHasSuperAdminRole = userRoleBindingRepository.findByUserId(user.getId()).stream()
|
||||
.anyMatch(binding -> SUPER_ADMIN_ROLE.equals(binding.getRole().getCode()));
|
||||
|
||||
if ("SUPER_ADMIN".equals(normalizedRoleCode)
|
||||
&& (actorPlatformRoles == null || !actorPlatformRoles.contains("SUPER_ADMIN"))) {
|
||||
if ((SUPER_ADMIN_ROLE.equals(normalizedRoleCode) || targetHasSuperAdminRole)
|
||||
&& (actorPlatformRoles == null || !actorPlatformRoles.contains(SUPER_ADMIN_ROLE))) {
|
||||
throw new DomainForbiddenException("error.admin.user.role.superAdmin.assignDenied");
|
||||
}
|
||||
|
||||
userRoleBindingRepository.deleteByUserId(user.getId());
|
||||
|
||||
if (!"USER".equals(normalizedRoleCode)) {
|
||||
if (!USER_ROLE.equals(normalizedRoleCode)) {
|
||||
Role role = roleRepository.findByCode(normalizedRoleCode)
|
||||
.orElseThrow(() -> new DomainBadRequestException("error.admin.user.role.invalid", roleCode));
|
||||
userRoleBindingRepository.save(new UserRoleBinding(user.getId(), role));
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ error.deviceAuth.deviceCode.invalid=Device code expired or invalid
|
|||
error.deviceAuth.deviceCode.used=Device code has already been used
|
||||
error.admin.user.notFound=User not found: {0}
|
||||
error.admin.user.role.invalid=Invalid role: {0}
|
||||
error.admin.user.role.superAdmin.assignDenied=Only SUPER_ADMIN can assign SUPER_ADMIN role
|
||||
error.admin.user.role.superAdmin.assignDenied=Only SUPER_ADMIN can mutate SUPER_ADMIN role state
|
||||
error.admin.user.systemAccount.immutable=System accounts cannot be modified from user management
|
||||
error.admin.user.status.invalid=Invalid user status: {0}
|
||||
error.admin.user.status.unsupported=Only ACTIVE or DISABLED status can be managed here
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ error.deviceAuth.deviceCode.invalid=设备验证码无效或已过期
|
|||
error.deviceAuth.deviceCode.used=设备验证码已被使用
|
||||
error.admin.user.notFound=用户不存在:{0}
|
||||
error.admin.user.role.invalid=无效的角色:{0}
|
||||
error.admin.user.role.superAdmin.assignDenied=只有 SUPER_ADMIN 可以分配 SUPER_ADMIN 角色
|
||||
error.admin.user.role.superAdmin.assignDenied=只有 SUPER_ADMIN 可以修改 SUPER_ADMIN 角色状态
|
||||
error.admin.user.systemAccount.immutable=系统账号不能在用户管理中修改
|
||||
error.admin.user.status.invalid=无效的用户状态:{0}
|
||||
error.admin.user.status.unsupported=这里只允许管理 ACTIVE 或 DISABLED 状态的用户
|
||||
|
|
|
|||
|
|
@ -89,6 +89,20 @@ class AdminUserAppServiceTest {
|
|||
() -> service.updateUserRole("user-1", "SUPER_ADMIN", Set.of("USER_ADMIN")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateUserRole_nonSuperAdminCannotReplaceExistingSuperAdminRole() {
|
||||
when(userAccountRepository.findById("user-1"))
|
||||
.thenReturn(Optional.of(user("user-1", "alice", "alice@example.com", UserStatus.ACTIVE)));
|
||||
when(userRoleBindingRepository.findByUserId("user-1"))
|
||||
.thenReturn(List.of(new UserRoleBinding("user-1", role("SUPER_ADMIN"))));
|
||||
|
||||
assertThrows(DomainForbiddenException.class,
|
||||
() -> service.updateUserRole("user-1", "USER", Set.of("USER_ADMIN")));
|
||||
|
||||
verify(userRoleBindingRepository, never()).deleteByUserId(any());
|
||||
verify(userRoleBindingRepository, never()).save(any(UserRoleBinding.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateUserRole_rejectsSystemAccount() {
|
||||
when(userAccountRepository.findById("builtin-skill-publisher"))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue