调整 SecurityPermissionFrameworkService 的实现,完善 PermissionServiceTest 的单元测试

This commit is contained in:
YunaiV
2022-05-13 00:24:10 +08:00
parent 49b4eedfc0
commit 5794780c4e
18 changed files with 246 additions and 88 deletions

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.system.api.permission;
import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import org.springframework.stereotype.Service;
@ -23,4 +24,19 @@ public class PermissionApiImpl implements PermissionApi {
return permissionService.getUserRoleIdListByRoleIds(roleIds);
}
@Override
public boolean hasAnyPermissions(Long userId, String... permissions) {
return permissionService.hasAnyPermissions(userId, permissions);
}
@Override
public boolean hasAnyRoles(Long userId, String... roles) {
return permissionService.hasAnyRoles(userId, roles);
}
@Override
public DeptDataPermissionRespDTO getDeptDataPermission(Long userId) {
return permissionService.getDeptDataPermission(userId);
}
}

View File

@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.system.framework.datapermission.config;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.framework.datapermission.core.dept.rule.DeptDataPermissionRuleCustomizer;
import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRuleCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

View File

@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.system.service.permission;
import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService;
import cn.iocoder.yudao.framework.security.core.service.SecurityPermissionFrameworkService;
import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
import org.springframework.lang.Nullable;
@ -16,7 +15,7 @@ import java.util.Set;
*
* @author 芋道源码
*/
public interface PermissionService extends SecurityPermissionFrameworkService, DeptDataPermissionFrameworkService {
public interface PermissionService {
/**
* 初始化权限的本地缓存
@ -115,4 +114,29 @@ public interface PermissionService extends SecurityPermissionFrameworkService, D
*/
void processUserDeleted(Long userId);
/**
* 判断是否有权限,任一一个即可
*
* @param userId 用户编号
* @param permissions 权限
* @return 是否
*/
boolean hasAnyPermissions(Long userId, String... permissions);
/**
* 判断是否有角色,任一一个即可
*
* @param roles 角色数组
* @return 是否
*/
boolean hasAnyRoles(Long userId, String... roles);
/**
* 获得登陆用户的部门数据权限
*
* @param userId 用户编号
* @return 部门数据权限
*/
DeptDataPermissionRespDTO getDeptDataPermission(Long userId);
}

View File

@ -8,7 +8,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
@ -45,7 +45,6 @@ import java.util.function.Supplier;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMaxValue;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static java.util.Collections.singleton;
/**
@ -53,7 +52,7 @@ import static java.util.Collections.singleton;
*
* @author 芋道源码
*/
@Service("ss") // 使用 Spring Security 的缩写,方便食用
@Service
@Slf4j
public class PermissionServiceImpl implements PermissionService {
@ -71,7 +70,7 @@ public class PermissionServiceImpl implements PermissionService {
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
*/
@Getter
@Setter // 单元测试
@Setter // 单元测试需要
private volatile Multimap<Long, Long> roleMenuCache;
/**
* 菜单编号与角色编号的缓存映射
@ -81,6 +80,7 @@ public class PermissionServiceImpl implements PermissionService {
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
*/
@Getter
@Setter // 单元测试需要
private volatile Multimap<Long, Long> menuRoleCache;
/**
* 缓存 RoleMenu 的最大更新时间,用于后续的增量轮询,判断是否有更新
@ -399,19 +399,14 @@ public class PermissionServiceImpl implements PermissionService {
}
@Override
public boolean hasPermission(String permission) {
return hasAnyPermissions(permission);
}
@Override
public boolean hasAnyPermissions(String... permissions) {
public boolean hasAnyPermissions(Long userId, String... permissions) {
// 如果为空,说明已经有权限
if (ArrayUtil.isEmpty(permissions)) {
return true;
}
// 获得当前登录的角色。如果为空,说明没有权限
Set<Long> roleIds = getUserRoleIdsFromCache(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus()));
Set<Long> roleIds = getUserRoleIdsFromCache(userId, singleton(CommonStatusEnum.ENABLE.getStatus()));
if (CollUtil.isEmpty(roleIds)) {
return false;
}
@ -434,19 +429,14 @@ public class PermissionServiceImpl implements PermissionService {
}
@Override
public boolean hasRole(String role) {
return hasAnyRoles(role);
}
@Override
public boolean hasAnyRoles(String... roles) {
public boolean hasAnyRoles(Long userId, String... roles) {
// 如果为空,说明已经有权限
if (ArrayUtil.isEmpty(roles)) {
return true;
}
// 获得当前登录的角色。如果为空,说明没有权限
Set<Long> roleIds = getUserRoleIdsFromCache(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus()));
Set<Long> roleIds = getUserRoleIdsFromCache(userId, singleton(CommonStatusEnum.ENABLE.getStatus()));
if (CollUtil.isEmpty(roleIds)) {
return false;
}

View File

@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
import cn.iocoder.yudao.module.system.service.common.CaptchaService;
import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
import cn.iocoder.yudao.module.system.service.member.MemberService;
import cn.iocoder.yudao.module.system.service.social.SocialUserService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import org.junit.jupiter.api.BeforeEach;
@ -49,6 +50,8 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
private SmsCodeApi smsCodeApi;
@MockBean
private OAuth2TokenService oauth2TokenService;
@MockBean
private MemberService memberService;
@MockBean
private Validator validator;

View File

@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
@ -359,22 +359,84 @@ public class PermissionServiceTest extends BaseDbUnitTest {
verify(permissionProducer).sendUserRoleRefreshMessage();
}
// @Test
// public void testHasAnyRoles_superAdmin() {
// // 准备参数
// String[] roles = new String[]{"yunai", "tudou"};
// // mock 方法
// List<RoleDO> roleList = singletonList(randomPojo(RoleDO.class, o -> o.setId(100L)));
// when(roleService.getRolesFromCache(eq(roleIds))).thenReturn(roleList);
// when(roleService.hasAnySuperAdmin(same(roleList))).thenReturn(true);
// List<MenuDO> menuList = randomPojoList(MenuDO.class);
// when(menuService.getMenuListFromCache(eq(menuTypes), eq(menusStatuses))).thenReturn(menuList);
//
// // 调用
// List<MenuDO> result = permissionService.getRoleMenuListFromCache(roleIds, menuTypes, menusStatuses);
// // 断言
// assertSame(menuList, result);
// }
@Test
public void testHasAnyPermissions_superAdmin() {
// 准备参数
Long userId = 1L;
String[] roles = new String[]{"system:user:query", "system:user:create"};
// mock 用户与角色的缓存
permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(100L)).build());
RoleDO role = randomPojo(RoleDO.class, o -> o.setId(100L)
.setStatus(CommonStatusEnum.ENABLE.getStatus()));
when(roleService.getRoleFromCache(eq(100L))).thenReturn(role);
// mock 其它方法
when(roleService.hasAnySuperAdmin(eq(asSet(100L)))).thenReturn(true);
// 调用
boolean has = permissionService.hasAnyPermissions(userId, roles);
// 断言
assertTrue(has);
}
@Test
public void testHasAnyPermissions_normal() {
// 准备参数
Long userId = 1L;
String[] roles = new String[]{"system:user:query", "system:user:create"};
// mock 用户与角色的缓存
permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(100L)).build());
RoleDO role = randomPojo(RoleDO.class, o -> o.setId(100L)
.setStatus(CommonStatusEnum.ENABLE.getStatus()));
when(roleService.getRoleFromCache(eq(100L))).thenReturn(role);
// mock 其它方法
MenuDO menu = randomPojo(MenuDO.class, o -> o.setId(1000L));
when(menuService.getMenuListByPermissionFromCache(eq("system:user:create"))).thenReturn(singletonList(menu));
permissionService.setMenuRoleCache(ImmutableMultimap.<Long, Long>builder().put(1000L, 100L).build());
// 调用
boolean has = permissionService.hasAnyPermissions(userId, roles);
// 断言
assertTrue(has);
}
@Test
public void testHasAnyRoles_superAdmin() {
// 准备参数
Long userId = 1L;
String[] roles = new String[]{"yunai", "tudou"};
// mock 用户与角色的缓存
permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(100L)).build());
RoleDO role = randomPojo(RoleDO.class, o -> o.setId(100L)
.setStatus(CommonStatusEnum.ENABLE.getStatus()));
when(roleService.getRoleFromCache(eq(100L))).thenReturn(role);
// mock 其它方法
when(roleService.hasAnySuperAdmin(eq(asSet(100L)))).thenReturn(true);
// 调用
boolean has = permissionService.hasAnyRoles(userId, roles);
// 断言
assertTrue(has);
}
@Test
public void testHasAnyRoles_normal() {
// 准备参数
Long userId = 1L;
String[] roles = new String[]{"yunai", "tudou"};
// mock 用户与角色的缓存
permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(100L)).build());
RoleDO role = randomPojo(RoleDO.class, o -> o.setId(100L).setCode("yunai")
.setStatus(CommonStatusEnum.ENABLE.getStatus()));
when(roleService.getRoleFromCache(eq(100L))).thenReturn(role);
// mock 其它方法
when(roleService.getRolesFromCache(eq(asSet(100L)))).thenReturn(singletonList(role));
// 调用
boolean has = permissionService.hasAnyRoles(userId, roles);
// 断言
assertTrue(has);
}
@Test
public void testGetDeptDataPermission_All() {