feat(permission): 新增对象权限API接口及实现
- 定义ObjectPermissionApi接口提供对象作用域权限查询功能 - 实现ObjectPermissionApiImpl提供角色权限查询和转换逻辑 - 添加ObjectMenuRespDTO、ObjectRoleRespDTO和ObjectRolePermissionRespDTO数据传输对象 - 实现按角色ID、角色编码查询对象作用域角色及权限的功能 - 提供获取对象作用域角色菜单与权限聚合结果的方法 - 添加完整单元测试覆盖对象权限API的主要业务场景
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
package com.njcn.rdms.module.system.api.permission;
|
||||
|
||||
import com.njcn.rdms.framework.common.enums.CommonStatusEnum;
|
||||
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
||||
import com.njcn.rdms.module.system.api.permission.dto.ObjectMenuRespDTO;
|
||||
import com.njcn.rdms.module.system.api.permission.dto.ObjectRolePermissionRespDTO;
|
||||
import com.njcn.rdms.module.system.api.permission.dto.ObjectRoleRespDTO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.permission.MenuDO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.permission.RoleDO;
|
||||
import com.njcn.rdms.module.system.service.permission.PermissionService;
|
||||
import com.njcn.rdms.module.system.service.permission.RoleService;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.njcn.rdms.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@RestController
|
||||
@Validated
|
||||
@Primary
|
||||
@Hidden
|
||||
public class ObjectPermissionApiImpl implements ObjectPermissionApi {
|
||||
|
||||
@Resource
|
||||
private RoleService roleService;
|
||||
@Resource
|
||||
private PermissionService permissionService;
|
||||
|
||||
@Override
|
||||
public CommonResult<ObjectRoleRespDTO> getObjectRoleById(Long roleId, String scopeType, String objectType) {
|
||||
return success(convertRole(roleService.getRole(roleId, scopeType, objectType)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<ObjectRoleRespDTO> getObjectRoleByCode(String roleCode, String scopeType, String objectType) {
|
||||
return success(convertRole(roleService.getRoleByCode(roleCode, scopeType, objectType)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<List<ObjectRoleRespDTO>> getObjectRoleList(Collection<Long> roleIds, String scopeType, String objectType) {
|
||||
List<RoleDO> roles = roleService.getRoleList(roleIds, scopeType, objectType);
|
||||
return success(roles.stream().map(this::convertRole).toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Set<String>> getObjectRolePermissions(Long roleId, String scopeType, String objectType) {
|
||||
RoleDO role = getEnabledScopedRole(roleId, scopeType, objectType);
|
||||
if (role == null) {
|
||||
return success(Collections.emptySet());
|
||||
}
|
||||
return success(new LinkedHashSet<>(permissionService.getScopedPermissionsByRoleId(roleId, scopeType, objectType)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<ObjectRolePermissionRespDTO> getObjectRolePermissionDetail(Long roleId, String scopeType, String objectType) {
|
||||
RoleDO role = getEnabledScopedRole(roleId, scopeType, objectType);
|
||||
if (role == null) {
|
||||
return success(emptyPermissionDetail());
|
||||
}
|
||||
|
||||
ObjectRolePermissionRespDTO detail = new ObjectRolePermissionRespDTO();
|
||||
detail.setCurrentRole(convertRole(role));
|
||||
detail.setMenus(permissionService.getScopedMenusByRoleId(roleId, scopeType, objectType)
|
||||
.stream()
|
||||
.map(this::convertMenu)
|
||||
.toList());
|
||||
detail.setPermissions(new LinkedHashSet<>(
|
||||
permissionService.getScopedPermissionsByRoleId(roleId, scopeType, objectType)));
|
||||
return success(detail);
|
||||
}
|
||||
|
||||
private ObjectRolePermissionRespDTO emptyPermissionDetail() {
|
||||
ObjectRolePermissionRespDTO detail = new ObjectRolePermissionRespDTO();
|
||||
detail.setCurrentRole(null);
|
||||
detail.setMenus(Collections.emptyList());
|
||||
detail.setPermissions(Collections.emptySet());
|
||||
return detail;
|
||||
}
|
||||
|
||||
private RoleDO getEnabledScopedRole(Long roleId, String scopeType, String objectType) {
|
||||
RoleDO role = roleService.getRole(roleId, scopeType, objectType);
|
||||
if (role == null || !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())) {
|
||||
return null;
|
||||
}
|
||||
return role;
|
||||
}
|
||||
|
||||
private ObjectRoleRespDTO convertRole(RoleDO role) {
|
||||
if (role == null) {
|
||||
return null;
|
||||
}
|
||||
ObjectRoleRespDTO dto = new ObjectRoleRespDTO();
|
||||
dto.setId(role.getId());
|
||||
dto.setCode(role.getCode());
|
||||
dto.setName(role.getName());
|
||||
dto.setScopeType(role.getScopeType());
|
||||
dto.setObjectType(role.getObjectType());
|
||||
return dto;
|
||||
}
|
||||
|
||||
private ObjectMenuRespDTO convertMenu(MenuDO menu) {
|
||||
ObjectMenuRespDTO dto = new ObjectMenuRespDTO();
|
||||
dto.setId(menu.getId());
|
||||
dto.setName(menu.getName());
|
||||
dto.setPermission(menu.getPermission());
|
||||
dto.setType(menu.getType());
|
||||
dto.setSort(menu.getSort());
|
||||
dto.setPath(menu.getPath());
|
||||
dto.setIcon(menu.getIcon());
|
||||
dto.setVisible(menu.getVisible());
|
||||
return dto;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,465 @@
|
||||
package com.njcn.rdms.module.system.api.permission;
|
||||
|
||||
import com.njcn.rdms.framework.common.enums.CommonStatusEnum;
|
||||
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
||||
import com.njcn.rdms.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import com.njcn.rdms.module.system.api.permission.dto.ObjectMenuRespDTO;
|
||||
import com.njcn.rdms.module.system.api.permission.dto.ObjectRolePermissionRespDTO;
|
||||
import com.njcn.rdms.module.system.api.permission.dto.ObjectRoleRespDTO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.permission.MenuDO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.permission.RoleDO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.permission.RoleMenuDO;
|
||||
import com.njcn.rdms.module.system.dal.mysql.permission.MenuMapper;
|
||||
import com.njcn.rdms.module.system.dal.mysql.permission.RoleMapper;
|
||||
import com.njcn.rdms.module.system.dal.mysql.permission.RoleMenuMapper;
|
||||
import com.njcn.rdms.module.system.dal.mysql.permission.UserRoleMapper;
|
||||
import com.njcn.rdms.module.system.service.permission.MenuServiceImpl;
|
||||
import com.njcn.rdms.module.system.service.permission.PermissionService;
|
||||
import com.njcn.rdms.module.system.service.permission.PermissionServiceImpl;
|
||||
import com.njcn.rdms.module.system.service.permission.RoleService;
|
||||
import com.njcn.rdms.module.system.service.permission.RoleServiceImpl;
|
||||
import com.njcn.rdms.module.system.service.user.AdminUserService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class ObjectPermissionApiImplTest extends BaseMockitoUnitTest {
|
||||
|
||||
private static final String OBJECT_SCOPE = "object";
|
||||
private static final String PRODUCT_OBJECT = "product";
|
||||
private static final String GLOBAL_SCOPE = "global";
|
||||
private static final String GLOBAL_OBJECT = "";
|
||||
|
||||
@Mock
|
||||
private RoleService roleService;
|
||||
@Mock
|
||||
private PermissionService permissionService;
|
||||
@Mock
|
||||
private RoleMapper roleMapper;
|
||||
@Mock
|
||||
private RoleMenuMapper roleMenuMapper;
|
||||
@Mock
|
||||
private MenuMapper menuMapper;
|
||||
@Mock
|
||||
private UserRoleMapper userRoleMapper;
|
||||
@Mock
|
||||
private AdminUserService userService;
|
||||
|
||||
@InjectMocks
|
||||
private ObjectPermissionApiImpl objectPermissionApi;
|
||||
|
||||
@Test
|
||||
void getObjectRoleById_whenRoleExistsAndEnabled_thenReturnRoleSummary() {
|
||||
RoleDO role = buildRole(101L, "qa_owner", "QA Owner", OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
role.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
when(roleService.getRole(101L, OBJECT_SCOPE, PRODUCT_OBJECT)).thenReturn(role);
|
||||
|
||||
CommonResult<ObjectRoleRespDTO> result =
|
||||
objectPermissionApi.getObjectRoleById(101L, OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
|
||||
ObjectRoleRespDTO data = result.getCheckedData();
|
||||
assertNotNull(data);
|
||||
assertEquals(101L, data.getId());
|
||||
assertEquals("qa_owner", data.getCode());
|
||||
assertEquals("QA Owner", data.getName());
|
||||
assertEquals(OBJECT_SCOPE, data.getScopeType());
|
||||
assertEquals(PRODUCT_OBJECT, data.getObjectType());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getObjectRoleById_whenRoleMissing_thenReturnNull() {
|
||||
when(roleService.getRole(404L, OBJECT_SCOPE, PRODUCT_OBJECT)).thenReturn(null);
|
||||
|
||||
CommonResult<ObjectRoleRespDTO> result =
|
||||
objectPermissionApi.getObjectRoleById(404L, OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
|
||||
assertNull(result.getCheckedData());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getObjectRoleByCode_whenRoleExists_thenReturnProductManagerRole() {
|
||||
RoleDO role = buildRole(102L, "product_manager", "Product Manager", OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
when(roleService.getRoleByCode("product_manager", OBJECT_SCOPE, PRODUCT_OBJECT)).thenReturn(role);
|
||||
|
||||
CommonResult<ObjectRoleRespDTO> result =
|
||||
objectPermissionApi.getObjectRoleByCode("product_manager", OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
|
||||
ObjectRoleRespDTO data = result.getCheckedData();
|
||||
assertNotNull(data);
|
||||
assertEquals(102L, data.getId());
|
||||
assertEquals("product_manager", data.getCode());
|
||||
assertEquals("Product Manager", data.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getObjectRoleList_shouldFilterScopedRolesThroughRoleServiceImpl() {
|
||||
RoleServiceImpl realRoleService = createRoleServiceImpl();
|
||||
ObjectPermissionApiImpl realApi = createObjectPermissionApi(realRoleService, permissionService);
|
||||
Map<Long, RoleDO> roleStore = new LinkedHashMap<>();
|
||||
roleStore.put(201L, buildRole(201L, "product_manager", "Product Manager", OBJECT_SCOPE, PRODUCT_OBJECT));
|
||||
roleStore.put(202L, buildRole(202L, "global_admin", "Global Admin", GLOBAL_SCOPE, GLOBAL_OBJECT));
|
||||
roleStore.put(203L, buildRole(203L, "project_manager", "Project Manager", OBJECT_SCOPE, "project"));
|
||||
roleStore.put(204L, buildRole(204L, "product_tester", "Product Tester", OBJECT_SCOPE, PRODUCT_OBJECT));
|
||||
when(roleMapper.selectByIds(any())).thenAnswer(invocation -> selectValues(roleStore, invocation.getArgument(0)));
|
||||
|
||||
CommonResult<List<ObjectRoleRespDTO>> result =
|
||||
realApi.getObjectRoleList(List.of(201L, 202L, 203L, 204L), OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
|
||||
List<ObjectRoleRespDTO> data = result.getCheckedData();
|
||||
assertEquals(List.of(201L, 204L), data.stream().map(ObjectRoleRespDTO::getId).toList());
|
||||
assertEquals(List.of("product_manager", "product_tester"),
|
||||
data.stream().map(ObjectRoleRespDTO::getCode).toList());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getObjectRolePermissions_whenRoleMissing_thenReturnEmptySet() {
|
||||
when(roleService.getRole(303L, OBJECT_SCOPE, PRODUCT_OBJECT)).thenReturn(null);
|
||||
|
||||
CommonResult<Set<String>> result =
|
||||
objectPermissionApi.getObjectRolePermissions(303L, OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
|
||||
assertTrue(result.getCheckedData().isEmpty());
|
||||
verifyNoInteractions(permissionService);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getObjectRolePermissions_whenRoleDisabled_thenReturnEmptySet() {
|
||||
RoleDO role = buildRole(304L, "product_manager", "Product Manager", OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
role.setStatus(CommonStatusEnum.DISABLE.getStatus());
|
||||
when(roleService.getRole(304L, OBJECT_SCOPE, PRODUCT_OBJECT)).thenReturn(role);
|
||||
|
||||
CommonResult<Set<String>> result =
|
||||
objectPermissionApi.getObjectRolePermissions(304L, OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
|
||||
assertTrue(result.getCheckedData().isEmpty());
|
||||
verifyNoInteractions(permissionService);
|
||||
}
|
||||
|
||||
@Test
|
||||
void permissionServiceImpl_getScopedPermissionsByRoleId_shouldExtractButtonPermissionFromEffectiveMenus() {
|
||||
MenuServiceImpl realMenuService = createMenuServiceImpl();
|
||||
PermissionServiceImpl realPermissionService = createPermissionServiceImpl(roleService, realMenuService);
|
||||
RoleDO role = buildRole(301L, "product_manager", "Product Manager", OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
MenuDO menu = buildMenu(3011L, "Product Setting", null, 2, 10, "/product/setting",
|
||||
MenuDO.ID_ROOT, CommonStatusEnum.ENABLE.getStatus());
|
||||
MenuDO button = buildMenu(3012L, "Save", "project:product:update", 3, 20, null,
|
||||
3011L, CommonStatusEnum.ENABLE.getStatus());
|
||||
Map<Long, MenuDO> menuStore = menuStore(menu, button);
|
||||
when(roleService.getRole(301L, OBJECT_SCOPE, PRODUCT_OBJECT)).thenReturn(role);
|
||||
when(roleService.getRoleList(Collections.singleton(301L), OBJECT_SCOPE, PRODUCT_OBJECT))
|
||||
.thenReturn(List.of(role));
|
||||
when(roleMenuMapper.selectListByRoleId(Collections.singleton(301L)))
|
||||
.thenReturn(List.of(buildRoleMenu(301L, 3011L), buildRoleMenu(301L, 3012L)));
|
||||
when(menuMapper.selectByIds(any())).thenAnswer(invocation -> selectValues(menuStore, invocation.getArgument(0)));
|
||||
|
||||
Set<String> permissions = realPermissionService.getScopedPermissionsByRoleId(301L, OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
|
||||
assertEquals(Set.of("project:product:update"), permissions);
|
||||
}
|
||||
|
||||
@Test
|
||||
void permissionServiceImpl_getScopedMenusAndPermissionsByRoleId_shouldReturnEmptyResultsWhenRoleIsDisabled() {
|
||||
MenuServiceImpl realMenuService = createMenuServiceImpl();
|
||||
PermissionServiceImpl realPermissionService = createPermissionServiceImpl(roleService, realMenuService);
|
||||
RoleDO disabledRole = buildRole(305L, "product_manager", "Product Manager", OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
disabledRole.setStatus(CommonStatusEnum.DISABLE.getStatus());
|
||||
when(roleService.getRole(305L, OBJECT_SCOPE, PRODUCT_OBJECT)).thenReturn(disabledRole);
|
||||
|
||||
List<MenuDO> menus = realPermissionService.getScopedMenusByRoleId(305L, OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
Set<String> permissions = realPermissionService.getScopedPermissionsByRoleId(305L, OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
|
||||
assertTrue(menus.isEmpty());
|
||||
assertTrue(permissions.isEmpty());
|
||||
verifyNoInteractions(roleMenuMapper, menuMapper);
|
||||
}
|
||||
|
||||
@Test
|
||||
void permissionServiceImpl_getScopedMenusAndPermissionsByRoleId_shouldIgnoreMenusOutsideRequestedScopeAndObject() {
|
||||
MenuServiceImpl realMenuService = createMenuServiceImpl();
|
||||
PermissionServiceImpl realPermissionService = createPermissionServiceImpl(roleService, realMenuService);
|
||||
RoleDO role = buildRole(3051L, "product_manager", "Product Manager", OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
MenuDO directory = buildMenu(30511L, "Product", null, 1, 1, "/product",
|
||||
MenuDO.ID_ROOT, CommonStatusEnum.ENABLE.getStatus());
|
||||
MenuDO scopedButton = buildMenu(30512L, "Save", "project:product:update", 3, 10, null,
|
||||
30511L, CommonStatusEnum.ENABLE.getStatus());
|
||||
MenuDO globalButton = buildMenu(30513L, "Global Export", "system:global:export", 3, 20, null,
|
||||
MenuDO.ID_ROOT, CommonStatusEnum.ENABLE.getStatus(), GLOBAL_SCOPE, GLOBAL_OBJECT);
|
||||
MenuDO otherObjectButton = buildMenu(30514L, "Project Publish", "project:project:publish", 3, 30, null,
|
||||
MenuDO.ID_ROOT, CommonStatusEnum.ENABLE.getStatus(), OBJECT_SCOPE, "project");
|
||||
Map<Long, MenuDO> menuStore = menuStore(directory, scopedButton, globalButton, otherObjectButton);
|
||||
when(roleService.getRole(3051L, OBJECT_SCOPE, PRODUCT_OBJECT)).thenReturn(role);
|
||||
when(roleService.getRoleList(Collections.singleton(3051L), OBJECT_SCOPE, PRODUCT_OBJECT))
|
||||
.thenReturn(List.of(role));
|
||||
when(roleMenuMapper.selectListByRoleId(Collections.singleton(3051L)))
|
||||
.thenReturn(List.of(buildRoleMenu(3051L, 30511L), buildRoleMenu(3051L, 30512L),
|
||||
buildRoleMenu(3051L, 30513L),
|
||||
buildRoleMenu(3051L, 30514L)));
|
||||
when(menuMapper.selectByIds(any())).thenAnswer(invocation -> selectValues(menuStore, invocation.getArgument(0)));
|
||||
|
||||
List<MenuDO> menus = realPermissionService.getScopedMenusByRoleId(3051L, OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
Set<String> permissions = realPermissionService.getScopedPermissionsByRoleId(3051L, OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
|
||||
assertEquals(Set.of(30511L, 30512L),
|
||||
menus.stream().map(MenuDO::getId).collect(LinkedHashSet::new, Set::add, Set::addAll));
|
||||
assertEquals(Set.of("project:product:update"), permissions);
|
||||
}
|
||||
|
||||
@Test
|
||||
void permissionServiceImpl_getRoleMenuListByRoleIdScopedCollection_shouldExcludeDisabledRoles() {
|
||||
MenuServiceImpl realMenuService = createMenuServiceImpl();
|
||||
PermissionServiceImpl realPermissionService = createPermissionServiceImpl(roleService, realMenuService);
|
||||
RoleDO enabledRole = buildRole(306L, "product_manager", "Product Manager", OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
RoleDO disabledRole = buildRole(307L, "product_viewer", "Product Viewer", OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
disabledRole.setStatus(CommonStatusEnum.DISABLE.getStatus());
|
||||
MenuDO enabledMenu = buildMenu(3061L, "Enabled Menu", null, 2, 10, "/product/enabled",
|
||||
MenuDO.ID_ROOT, CommonStatusEnum.ENABLE.getStatus());
|
||||
MenuDO disabledRoleMenu = buildMenu(3071L, "Disabled Role Menu", null, 2, 20, "/product/disabled-role",
|
||||
MenuDO.ID_ROOT, CommonStatusEnum.ENABLE.getStatus());
|
||||
Map<Long, MenuDO> menuStore = menuStore(enabledMenu, disabledRoleMenu);
|
||||
when(roleService.getRoleList(List.of(306L, 307L), OBJECT_SCOPE, PRODUCT_OBJECT))
|
||||
.thenReturn(List.of(enabledRole, disabledRole));
|
||||
when(roleMenuMapper.selectListByRoleId(org.mockito.ArgumentMatchers.<Collection<Long>>any())).thenAnswer(invocation -> {
|
||||
Collection<Long> roleIds = invocation.getArgument(0);
|
||||
List<RoleMenuDO> results = new ArrayList<>();
|
||||
if (roleIds.contains(306L)) {
|
||||
results.add(buildRoleMenu(306L, 3061L));
|
||||
}
|
||||
if (roleIds.contains(307L)) {
|
||||
results.add(buildRoleMenu(307L, 3071L));
|
||||
}
|
||||
return results;
|
||||
});
|
||||
when(menuMapper.selectByIds(any())).thenAnswer(invocation -> selectValues(menuStore, invocation.getArgument(0)));
|
||||
|
||||
Set<Long> menuIds = realPermissionService.getRoleMenuListByRoleId(List.of(306L, 307L), OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
|
||||
assertEquals(Set.of(3061L), menuIds);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getObjectRolePermissionDetail_whenRoleMissing_thenReturnEmptyDetail() {
|
||||
when(roleService.getRole(401L, OBJECT_SCOPE, PRODUCT_OBJECT)).thenReturn(null);
|
||||
|
||||
CommonResult<ObjectRolePermissionRespDTO> result =
|
||||
objectPermissionApi.getObjectRolePermissionDetail(401L, OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
|
||||
ObjectRolePermissionRespDTO detail = result.getCheckedData();
|
||||
assertNotNull(detail);
|
||||
assertNull(detail.getCurrentRole());
|
||||
assertTrue(detail.getMenus().isEmpty());
|
||||
assertTrue(detail.getPermissions().isEmpty());
|
||||
verifyNoInteractions(permissionService);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getObjectRolePermissionDetail_whenRoleDisabled_thenReturnEmptyDetail() {
|
||||
RoleDO role = buildRole(405L, "product_manager", "Product Manager", OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
role.setStatus(CommonStatusEnum.DISABLE.getStatus());
|
||||
when(roleService.getRole(405L, OBJECT_SCOPE, PRODUCT_OBJECT)).thenReturn(role);
|
||||
|
||||
CommonResult<ObjectRolePermissionRespDTO> result =
|
||||
objectPermissionApi.getObjectRolePermissionDetail(405L, OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
|
||||
ObjectRolePermissionRespDTO detail = result.getCheckedData();
|
||||
assertNotNull(detail);
|
||||
assertNull(detail.getCurrentRole());
|
||||
assertTrue(detail.getMenus().isEmpty());
|
||||
assertTrue(detail.getPermissions().isEmpty());
|
||||
verifyNoInteractions(permissionService);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getObjectRolePermissionDetail_shouldAggregateRoleMenusAndPermissions() {
|
||||
RoleDO role = buildRole(402L, "product_manager", "Product Manager", OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
MenuDO directory = buildMenu(11L, "Product", null, 1, 1, "/product",
|
||||
MenuDO.ID_ROOT, CommonStatusEnum.ENABLE.getStatus());
|
||||
MenuDO menu = buildMenu(12L, "Product Setting", null, 2, 10, "/product/setting",
|
||||
11L, CommonStatusEnum.ENABLE.getStatus());
|
||||
MenuDO button = buildMenu(13L, "Save", "project:product:update", 3, 20, null,
|
||||
12L, CommonStatusEnum.ENABLE.getStatus());
|
||||
Set<String> permissions = new LinkedHashSet<>(Set.of("project:product:update"));
|
||||
when(roleService.getRole(402L, OBJECT_SCOPE, PRODUCT_OBJECT)).thenReturn(role);
|
||||
when(permissionService.getScopedMenusByRoleId(402L, OBJECT_SCOPE, PRODUCT_OBJECT))
|
||||
.thenReturn(List.of(directory, menu, button));
|
||||
when(permissionService.getScopedPermissionsByRoleId(402L, OBJECT_SCOPE, PRODUCT_OBJECT))
|
||||
.thenReturn(permissions);
|
||||
|
||||
CommonResult<ObjectRolePermissionRespDTO> result =
|
||||
objectPermissionApi.getObjectRolePermissionDetail(402L, OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
|
||||
ObjectRolePermissionRespDTO detail = result.getCheckedData();
|
||||
assertNotNull(detail.getCurrentRole());
|
||||
assertEquals(3, detail.getMenus().size());
|
||||
assertEquals(List.of(11L, 12L, 13L), detail.getMenus().stream().map(ObjectMenuRespDTO::getId).toList());
|
||||
assertEquals(permissions, detail.getPermissions());
|
||||
}
|
||||
|
||||
@Test
|
||||
void permissionServiceImpl_getScopedMenusByRoleId_shouldExcludeDisabledMenus() {
|
||||
MenuServiceImpl realMenuService = createMenuServiceImpl();
|
||||
PermissionServiceImpl realPermissionService = createPermissionServiceImpl(roleService, realMenuService);
|
||||
RoleDO role = buildRole(403L, "product_manager", "Product Manager", OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
MenuDO enabledMenu = buildMenu(21L, "Enabled Menu", null, 2, 10, "/product/setting",
|
||||
MenuDO.ID_ROOT, CommonStatusEnum.ENABLE.getStatus());
|
||||
MenuDO disabledMenu = buildMenu(22L, "Disabled Menu", null, 2, 20, "/product/disabled",
|
||||
MenuDO.ID_ROOT, CommonStatusEnum.DISABLE.getStatus());
|
||||
Map<Long, MenuDO> menuStore = menuStore(enabledMenu, disabledMenu);
|
||||
when(roleService.getRole(403L, OBJECT_SCOPE, PRODUCT_OBJECT)).thenReturn(role);
|
||||
when(roleService.getRoleList(Collections.singleton(403L), OBJECT_SCOPE, PRODUCT_OBJECT))
|
||||
.thenReturn(List.of(role));
|
||||
when(roleMenuMapper.selectListByRoleId(Collections.singleton(403L)))
|
||||
.thenReturn(List.of(buildRoleMenu(403L, 21L), buildRoleMenu(403L, 22L)));
|
||||
when(menuMapper.selectByIds(any())).thenAnswer(invocation -> selectValues(menuStore, invocation.getArgument(0)));
|
||||
|
||||
List<MenuDO> menus = realPermissionService.getScopedMenusByRoleId(403L, OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
|
||||
List<Long> menuIds = menus.stream().map(MenuDO::getId).toList();
|
||||
assertEquals(List.of(21L), menuIds);
|
||||
assertFalse(menuIds.contains(22L));
|
||||
}
|
||||
|
||||
void permissionServiceImpl_getScopedMenusByRoleId_shouldKeepAncestorMenusAfterExpandedRoleMenuAssignments() {
|
||||
MenuServiceImpl realMenuService = createMenuServiceImpl();
|
||||
PermissionServiceImpl realPermissionService = createPermissionServiceImpl(roleService, realMenuService);
|
||||
RoleDO role = buildRole(404L, "product_manager", "Product Manager", OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
MenuDO directory = buildMenu(31L, "Product", null, 1, 1, "/product",
|
||||
MenuDO.ID_ROOT, CommonStatusEnum.ENABLE.getStatus());
|
||||
MenuDO childMenu = buildMenu(32L, "Product Setting", null, 2, 10, "/product/setting",
|
||||
31L, CommonStatusEnum.ENABLE.getStatus());
|
||||
MenuDO button = buildMenu(33L, "Save", "project:product:update", 3, 20, null,
|
||||
32L, CommonStatusEnum.ENABLE.getStatus());
|
||||
Map<Long, MenuDO> menuStore = menuStore(directory, childMenu, button);
|
||||
List<RoleMenuDO> persistedRoleMenus = new ArrayList<>();
|
||||
when(roleService.getRole(404L)).thenReturn(role);
|
||||
when(roleService.getRole(404L, OBJECT_SCOPE, PRODUCT_OBJECT)).thenReturn(role);
|
||||
when(roleService.getRoleList(Collections.singleton(404L), OBJECT_SCOPE, PRODUCT_OBJECT))
|
||||
.thenReturn(List.of(role));
|
||||
when(roleMenuMapper.selectListByRoleId(404L)).thenReturn(Collections.emptyList());
|
||||
doAnswer(invocation -> {
|
||||
persistedRoleMenus.clear();
|
||||
persistedRoleMenus.addAll(invocation.getArgument(0));
|
||||
return null;
|
||||
}).when(roleMenuMapper).insertBatch(any());
|
||||
when(roleMenuMapper.selectListByRoleId(Collections.singleton(404L)))
|
||||
.thenAnswer(invocation -> new ArrayList<>(persistedRoleMenus));
|
||||
when(menuMapper.selectByIds(any())).thenAnswer(invocation -> selectValues(menuStore, invocation.getArgument(0)));
|
||||
|
||||
realPermissionService.assignRoleMenu(404L, Set.of(32L, 33L));
|
||||
List<MenuDO> menus = realPermissionService.getScopedMenusByRoleId(404L, OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
|
||||
assertEquals(Set.of(31L, 32L, 33L), menus.stream().map(MenuDO::getId).collect(LinkedHashSet::new, Set::add, Set::addAll));
|
||||
assertEquals(Set.of("Product", "Product Setting", "Save"),
|
||||
menus.stream().map(MenuDO::getName).collect(LinkedHashSet::new, Set::add, Set::addAll));
|
||||
}
|
||||
|
||||
private RoleServiceImpl createRoleServiceImpl() {
|
||||
RoleServiceImpl roleServiceImpl = new RoleServiceImpl();
|
||||
ReflectionTestUtils.setField(roleServiceImpl, "permissionService", permissionService);
|
||||
ReflectionTestUtils.setField(roleServiceImpl, "roleMapper", roleMapper);
|
||||
ReflectionTestUtils.setField(roleServiceImpl, "userRoleMapper", userRoleMapper);
|
||||
return roleServiceImpl;
|
||||
}
|
||||
|
||||
private MenuServiceImpl createMenuServiceImpl() {
|
||||
MenuServiceImpl menuServiceImpl = new MenuServiceImpl();
|
||||
ReflectionTestUtils.setField(menuServiceImpl, "menuMapper", menuMapper);
|
||||
ReflectionTestUtils.setField(menuServiceImpl, "permissionService", permissionService);
|
||||
return menuServiceImpl;
|
||||
}
|
||||
|
||||
private PermissionServiceImpl createPermissionServiceImpl(RoleService roleServiceDependency,
|
||||
MenuServiceImpl menuServiceDependency) {
|
||||
PermissionServiceImpl permissionServiceImpl = new PermissionServiceImpl();
|
||||
ReflectionTestUtils.setField(permissionServiceImpl, "roleMenuMapper", roleMenuMapper);
|
||||
ReflectionTestUtils.setField(permissionServiceImpl, "userRoleMapper", userRoleMapper);
|
||||
ReflectionTestUtils.setField(permissionServiceImpl, "roleService", roleServiceDependency);
|
||||
ReflectionTestUtils.setField(permissionServiceImpl, "menuService", menuServiceDependency);
|
||||
ReflectionTestUtils.setField(permissionServiceImpl, "userService", userService);
|
||||
return permissionServiceImpl;
|
||||
}
|
||||
|
||||
private ObjectPermissionApiImpl createObjectPermissionApi(RoleService roleServiceDependency,
|
||||
PermissionService permissionServiceDependency) {
|
||||
ObjectPermissionApiImpl api = new ObjectPermissionApiImpl();
|
||||
ReflectionTestUtils.setField(api, "roleService", roleServiceDependency);
|
||||
ReflectionTestUtils.setField(api, "permissionService", permissionServiceDependency);
|
||||
return api;
|
||||
}
|
||||
|
||||
private static RoleDO buildRole(Long id, String code, String name, String scopeType, String objectType) {
|
||||
RoleDO role = new RoleDO();
|
||||
role.setId(id);
|
||||
role.setCode(code);
|
||||
role.setName(name);
|
||||
role.setScopeType(scopeType);
|
||||
role.setObjectType(objectType);
|
||||
role.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
return role;
|
||||
}
|
||||
|
||||
private static MenuDO buildMenu(Long id, String name, String permission, Integer type, Integer sort, String path,
|
||||
Long parentId, Integer status) {
|
||||
return buildMenu(id, name, permission, type, sort, path, parentId, status, OBJECT_SCOPE, PRODUCT_OBJECT);
|
||||
}
|
||||
|
||||
private static MenuDO buildMenu(Long id, String name, String permission, Integer type, Integer sort, String path,
|
||||
Long parentId, Integer status, String scopeType, String objectType) {
|
||||
MenuDO menu = new MenuDO();
|
||||
menu.setId(id);
|
||||
menu.setName(name);
|
||||
menu.setPermission(permission);
|
||||
menu.setType(type);
|
||||
menu.setSort(sort);
|
||||
menu.setPath(path);
|
||||
menu.setParentId(parentId);
|
||||
menu.setStatus(status);
|
||||
menu.setVisible(Boolean.TRUE);
|
||||
menu.setScopeType(scopeType);
|
||||
menu.setObjectType(objectType);
|
||||
return menu;
|
||||
}
|
||||
|
||||
private static RoleMenuDO buildRoleMenu(Long roleId, Long menuId) {
|
||||
RoleMenuDO roleMenu = new RoleMenuDO();
|
||||
roleMenu.setRoleId(roleId);
|
||||
roleMenu.setMenuId(menuId);
|
||||
return roleMenu;
|
||||
}
|
||||
|
||||
private static <T> List<T> selectValues(Map<Long, T> store, Collection<Long> ids) {
|
||||
return ids.stream()
|
||||
.map(store::get)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
|
||||
}
|
||||
|
||||
private static Map<Long, MenuDO> menuStore(MenuDO... menus) {
|
||||
Map<Long, MenuDO> results = new LinkedHashMap<>();
|
||||
for (MenuDO menu : menus) {
|
||||
results.put(menu.getId(), menu);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user