|
@@ -5,7 +5,6 @@ import cn.hutool.core.collection.CollectionUtil;
|
|
|
import cn.hutool.core.util.ArrayUtil;
|
|
|
import cn.hutool.extra.spring.SpringUtil;
|
|
|
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
|
|
|
-import com.citu.framework.common.enums.CommonStatusEnum;
|
|
|
import com.citu.framework.common.util.collection.CollectionUtils;
|
|
|
import com.citu.framework.datapermission.core.annotation.DataPermission;
|
|
|
import com.citu.module.menduner.system.dal.dataobject.enterprise.EnterpriseUserBindDO;
|
|
@@ -13,7 +12,6 @@ import com.citu.module.menduner.system.dal.dataobject.permission.MdeMenuDO;
|
|
|
import com.citu.module.menduner.system.dal.dataobject.permission.MdeRoleDO;
|
|
|
import com.citu.module.menduner.system.dal.dataobject.permission.MdeRoleMenuDO;
|
|
|
import com.citu.module.menduner.system.dal.dataobject.permission.MdeUserRoleDO;
|
|
|
-import com.citu.module.menduner.system.dal.dataobject.user.MdeUserDO;
|
|
|
import com.citu.module.menduner.system.dal.mysql.permission.MdeRoleMenuMapper;
|
|
|
import com.citu.module.menduner.system.dal.mysql.permission.MdeUserRoleMapper;
|
|
|
import com.citu.module.menduner.system.dal.redis.RedisKeyConstants;
|
|
@@ -74,387 +72,312 @@ public class MdePermissionServiceImpl implements MdePermissionService {
|
|
|
@Resource
|
|
|
@Lazy
|
|
|
private EnterpriseService enterpriseService;
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// public boolean hasAnyPermissions(Long userId, String... permissions) {
|
|
|
-// // 如果为空,说明已经有权限
|
|
|
-// if (ArrayUtil.isEmpty(permissions)) {
|
|
|
-// return true;
|
|
|
-// }
|
|
|
-//
|
|
|
-// // 获得当前登录的角色。如果为空,说明没有权限
|
|
|
-// List<MdeRoleDO> roles = getEnableUserRoleListByUserIdFromCache(userId);
|
|
|
-// if (CollUtil.isEmpty(roles)) {
|
|
|
-// return false;
|
|
|
-// }
|
|
|
-//
|
|
|
-// // 情况一:遍历判断每个权限,如果有一满足,说明有权限
|
|
|
-// for (String permission : permissions) {
|
|
|
-// if (hasAnyPermission(roles, permission)) {
|
|
|
-// return true;
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-// // 情况二:如果是超管,也说明有权限
|
|
|
-// return roleService.hasAnySuperAdmin(convertSet(roles, MdeRoleDO::getId));
|
|
|
-// }
|
|
|
-//
|
|
|
-// /**
|
|
|
-// * 判断指定角色,是否拥有该 permission 权限
|
|
|
-// *
|
|
|
-// * @param roles 指定角色数组
|
|
|
-// * @param permission 权限标识
|
|
|
-// * @return 是否拥有
|
|
|
-// */
|
|
|
-// private boolean hasAnyPermission(List<MdeRoleDO> roles, String permission) {
|
|
|
-// List<Long> menuIds = menuService.getMenuIdListByPermissionFromCache(permission);
|
|
|
-// // 采用严格模式,如果权限找不到对应的 Menu 的话,也认为没有权限
|
|
|
-// if (CollUtil.isEmpty(menuIds)) {
|
|
|
-// return false;
|
|
|
-// }
|
|
|
-//
|
|
|
-// // 判断是否有权限
|
|
|
-// Set<Long> roleIds = convertSet(roles, MdeRoleDO::getId);
|
|
|
-// for (Long menuId : menuIds) {
|
|
|
-// // 获得拥有该菜单的角色编号集合
|
|
|
-// Set<Long> menuRoleIds = getSelf().getMenuRoleIdListByMenuIdFromCache(menuId);
|
|
|
-// // 如果有交集,说明有权限
|
|
|
-// if (CollUtil.containsAny(menuRoleIds, roleIds)) {
|
|
|
-// return true;
|
|
|
-// }
|
|
|
-// }
|
|
|
-// return false;
|
|
|
-// }
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// public boolean hasAnyRoles(Long userId, String... roles) {
|
|
|
-// // 如果为空,说明已经有权限
|
|
|
-// if (ArrayUtil.isEmpty(roles)) {
|
|
|
-// return true;
|
|
|
-// }
|
|
|
-//
|
|
|
-// // 获得当前登录的角色。如果为空,说明没有权限
|
|
|
-// List<MdeRoleDO> roleList = getEnableUserRoleListByUserIdFromCache(userId);
|
|
|
-// if (CollUtil.isEmpty(roleList)) {
|
|
|
-// return false;
|
|
|
-// }
|
|
|
-//
|
|
|
-// // 判断是否有角色
|
|
|
-// Set<String> userRoles = convertSet(roleList, MdeRoleDO::getCode);
|
|
|
-// return CollUtil.containsAny(userRoles, Sets.newHashSet(roles));
|
|
|
-// }
|
|
|
-//
|
|
|
-// // ========== 角色-菜单的相关方法 ==========
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换
|
|
|
-// @Caching(evict = {
|
|
|
-// @CacheEvict(value = RedisKeyConstants.MDE_MENU_ROLE_ID_LIST,
|
|
|
-// allEntries = true),
|
|
|
-// @CacheEvict(value = RedisKeyConstants.MDE_PERMISSION_MENU_ID_LIST,
|
|
|
-// allEntries = true) // allEntries 清空所有缓存,主要一次更新涉及到的 menuIds 较多,反倒批量会更快
|
|
|
-// })
|
|
|
-// public void assignRoleMenu(Long roleId, Set<Long> menuIds) {
|
|
|
-// // 获得角色拥有菜单编号
|
|
|
-// Set<Long> dbMenuIds = convertSet(roleMenuMapper.selectListByRoleId(roleId), MdeRoleMenuDO::getMenuId);
|
|
|
-// // 计算新增和删除的菜单编号
|
|
|
-// Set<Long> menuIdList = CollUtil.emptyIfNull(menuIds);
|
|
|
-// Collection<Long> createMenuIds = CollUtil.subtract(menuIdList, dbMenuIds);
|
|
|
-// Collection<Long> deleteMenuIds = CollUtil.subtract(dbMenuIds, menuIdList);
|
|
|
-// // 执行新增和删除。对于已经授权的菜单,不用做任何处理
|
|
|
-// if (CollUtil.isNotEmpty(createMenuIds)) {
|
|
|
-// roleMenuMapper.insertBatch(CollectionUtils.convertList(createMenuIds, menuId -> {
|
|
|
-// MdeRoleMenuDO entity = new MdeRoleMenuDO();
|
|
|
-// entity.setRoleId(roleId);
|
|
|
-// entity.setMenuId(menuId);
|
|
|
-// return entity;
|
|
|
-// }));
|
|
|
-// }
|
|
|
-// if (CollUtil.isNotEmpty(deleteMenuIds)) {
|
|
|
-// roleMenuMapper.deleteListByRoleIdAndMenuIds(roleId, deleteMenuIds);
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// @Transactional(rollbackFor = Exception.class)
|
|
|
-// @Caching(evict = {
|
|
|
-// @CacheEvict(value = RedisKeyConstants.MDE_MENU_ROLE_ID_LIST,
|
|
|
-// allEntries = true), // allEntries 清空所有缓存,此处无法方便获得 roleId 对应的 menu 缓存们
|
|
|
-// @CacheEvict(value = RedisKeyConstants.MDE_USER_ROLE_IDS,
|
|
|
-// allEntries = true) // allEntries 清空所有缓存,此处无法方便获得 roleId 对应的 user 缓存们
|
|
|
-// })
|
|
|
-// public void processRoleDeleted(Long roleId) {
|
|
|
-// // 标记删除 UserRole
|
|
|
-// userRoleMapper.deleteListByRoleId(roleId);
|
|
|
-// // 标记删除 RoleMenu
|
|
|
-// roleMenuMapper.deleteListByRoleId(roleId);
|
|
|
-// }
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// @CacheEvict(value = RedisKeyConstants.MDE_MENU_ROLE_ID_LIST, key = "#menuId")
|
|
|
-// public void processMenuDeleted(Long menuId) {
|
|
|
-// roleMenuMapper.deleteListByMenuId(menuId);
|
|
|
-// }
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// public Set<Long> getRoleMenuListByRoleId(Collection<Long> roleIds) {
|
|
|
-// if (CollUtil.isEmpty(roleIds)) {
|
|
|
-// return Collections.emptySet();
|
|
|
-// }
|
|
|
-//
|
|
|
-// // 如果是管理员的情况下,获取全部菜单编号
|
|
|
-// if (roleService.hasAnySuperAdmin(roleIds)) {
|
|
|
-// return convertSet(menuService.getMenuList(), MdeMenuDO::getId);
|
|
|
-// }
|
|
|
-// // 如果是非管理员的情况下,获得拥有的菜单编号
|
|
|
-// return convertSet(roleMenuMapper.selectListByRoleId(roleIds), MdeRoleMenuDO::getMenuId);
|
|
|
-// }
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// @Cacheable(value = RedisKeyConstants.MDE_MENU_ROLE_ID_LIST, key = "#menuId")
|
|
|
-// public Set<Long> getMenuRoleIdListByMenuIdFromCache(Long menuId) {
|
|
|
-// return convertSet(roleMenuMapper.selectListByMenuId(menuId), MdeRoleMenuDO::getRoleId);
|
|
|
-// }
|
|
|
-//
|
|
|
-// // ========== 用户-角色的相关方法 ==========
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换
|
|
|
-// @CacheEvict(value = RedisKeyConstants.MDE_USER_ROLE_IDS, key = "#userId")
|
|
|
-// public void assignUserRole(Long enterpriseId,Long userId, Set<Long> roleIds) {
|
|
|
-// // 获得角色拥有角色编号
|
|
|
-// Set<Long> dbRoleIds = convertSet(userRoleMapper.selectListByEnterpriseIdAndUserId(enterpriseId,userId),
|
|
|
-// MdeUserRoleDO::getRoleId);
|
|
|
-// // 计算新增和删除的角色编号
|
|
|
-// Set<Long> roleIdList = CollUtil.emptyIfNull(roleIds);
|
|
|
-// Collection<Long> createRoleIds = CollUtil.subtract(roleIdList, dbRoleIds);
|
|
|
-// Collection<Long> deleteMenuIds = CollUtil.subtract(dbRoleIds, roleIdList);
|
|
|
-// // 执行新增和删除。对于已经授权的角色,不用做任何处理
|
|
|
-// if (!CollectionUtil.isEmpty(createRoleIds)) {
|
|
|
-// userRoleMapper.insertBatch(CollectionUtils.convertList(createRoleIds, roleId -> {
|
|
|
-// MdeUserRoleDO entity = new MdeUserRoleDO();
|
|
|
-// entity.setUserId(userId);
|
|
|
-// entity.setRoleId(roleId);
|
|
|
-// return entity;
|
|
|
-// }));
|
|
|
-// }
|
|
|
-// if (!CollectionUtil.isEmpty(deleteMenuIds)) {
|
|
|
-// userRoleMapper.deleteListByEnterpriseIdAndUserIdAndRoleIdIds(enterpriseId,userId, deleteMenuIds);
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// public void assignUserRoleByDefault(Long userId, MdeDefaultRoleEnum roleEnum) {
|
|
|
-// // 获得默认角色信息
|
|
|
-// MdeRoleDO role = roleService.getRoleByDefault(roleEnum);
|
|
|
-// MdeUserRoleDO entity = new MdeUserRoleDO();
|
|
|
-// entity.setUserId(userId);
|
|
|
-// entity.setRoleId(role.getId());
|
|
|
-// userRoleMapper.insert(entity);
|
|
|
-// }
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// @CacheEvict(value = RedisKeyConstants.MDE_USER_ROLE_IDS, key = "#enterpriseId + ':' + #userId")
|
|
|
-// public void processUserDeleted(Long enterpriseId,Long userId) {
|
|
|
-// userRoleMapper.deleteListByEnterpriseIdAndUserId(enterpriseId,userId);
|
|
|
-// }
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// public Set<Long> getUserRoleIdListByUserId(Long enterpriseId,Long userId) {
|
|
|
-// return convertSet(userRoleMapper.selectListByEnterpriseIdAndUserId(enterpriseId,userId), MdeUserRoleDO::getRoleId);
|
|
|
-// }
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// @Cacheable(value = RedisKeyConstants.MDE_USER_ROLE_IDS, key = "#userId")
|
|
|
-// public Set<Long> getUserRoleIdListByUserIdFromCache(Long userId) {
|
|
|
-// return getUserRoleIdListByUserId(userId);
|
|
|
-// }
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// public Set<Long> getUserRoleIdListByRoleId(Collection<Long> roleIds) {
|
|
|
-// return convertSet(userRoleMapper.selectListByRoleIds(roleIds), MdeUserRoleDO::getUserId);
|
|
|
-// }
|
|
|
-//
|
|
|
-// /**
|
|
|
-// * 获得用户拥有的角色,并且这些角色是开启状态的
|
|
|
-// *
|
|
|
-// * @param userId 用户编号
|
|
|
-// * @return 用户拥有的角色
|
|
|
-// */
|
|
|
-// @VisibleForTesting
|
|
|
-// List<MdeRoleDO> getEnableUserRoleListByUserIdFromCache(Long userId) {
|
|
|
-// // 获得用户拥有的角色编号
|
|
|
-// Set<Long> roleIds = getSelf().getUserRoleIdListByUserIdFromCache(userId);
|
|
|
-// // 获得角色数组,并移除被禁用的
|
|
|
-// List<MdeRoleDO> roles = roleService.getRoleListFromCache(roleIds);
|
|
|
-// roles.removeIf(role -> !MendunerStatusEnum.ENABLE.getStatus().equals(role.getStatus()));
|
|
|
-// return roles;
|
|
|
-// }
|
|
|
-//
|
|
|
-// // ========== 用户-部门的相关方法 ==========
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// public void assignRoleDataScope(Long roleId, Integer dataScope, Set<Long> dataScopeDataIds) {
|
|
|
-// roleService.updateRoleDataScope(roleId, dataScope, dataScopeDataIds);
|
|
|
-// }
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// @DataPermission(enable = false) // 关闭数据权限,不然就会出现递归获取数据权限的问题
|
|
|
-// public DataPermissionRespDTO getDataPermission(Long userId, Long enterpriseId) {
|
|
|
-// DataPermissionRespDTO result = new DataPermissionRespDTO();
|
|
|
-// // 获得用户的角色
|
|
|
-// List<MdeRoleDO> roles = getEnableUserRoleListByUserIdFromCache(userId);
|
|
|
-// // 如果角色为空,则只能查看自己
|
|
|
-// if (CollUtil.isEmpty(roles)) {
|
|
|
-// result.setSelf(true);
|
|
|
-// return result;
|
|
|
-// }
|
|
|
-//
|
|
|
-// // 获得用户的部门编号的缓存,通过 Guava 的 Suppliers 惰性求值,即有且仅有第一次发起 DB 的查询
|
|
|
-// EnterpriseUserBindDO enterpriseUserBind = enterpriseUserBindService
|
|
|
-// .selectByEnterpriseIdAndUserId(enterpriseId, userId);
|
|
|
-// if (enterpriseUserBind == null) {
|
|
|
-// // 找不到企业用户 or 禁用了
|
|
|
-// return result;
|
|
|
-// }
|
|
|
-// // 遍历每个角色,计算
|
|
|
-// for (MdeRoleDO role : roles) {
|
|
|
-// // 为空时,跳过
|
|
|
-// if (role.getDataScope() == null) {
|
|
|
-// continue;
|
|
|
-// }
|
|
|
-// // 情况一,ALL 所有的数据权限
|
|
|
-// if (Objects.equals(role.getDataScope(), DataScopeEnum.ALL.getScope())) {
|
|
|
-// result.setAll(true);
|
|
|
-// continue;
|
|
|
-// }
|
|
|
-// // 情况二,DEPT_CUSTOM 自定义
|
|
|
-// if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_CUSTOM.getScope())) {
|
|
|
-// CollUtil.addAll(result.getDataIds(), role.getDataScopeEnterpriseIds());
|
|
|
-// // 自定义可见部门时,保证可以看到自己所在的部门。否则,一些场景下可能会有问题。
|
|
|
-// // 例如说,登录时,基于 t_user 的 username 查询会可能被 dept_id 过滤掉
|
|
|
-// CollUtil.addAll(result.getDataIds(), enterpriseUserBind.getEnterpriseId());
|
|
|
-// continue;
|
|
|
-// }
|
|
|
-// // 情况三,DEPT_ONLY 自己所在的数据权限
|
|
|
-// if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_ONLY.getScope())) {
|
|
|
-// CollectionUtils.addIfNotNull(result.getDataIds(), enterpriseUserBind.getEnterpriseId());
|
|
|
-// continue;
|
|
|
-// }
|
|
|
-// // 情况四,DEPT_DEPT_AND_CHILD 自己所在及以下的数据权限
|
|
|
-// if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_AND_CHILD.getScope())) {
|
|
|
-// CollUtil.addAll(result.getDataIds(), enterpriseService
|
|
|
-// .getChildEnterpriseIdListFromCache(enterpriseUserBind.getEnterpriseId()));
|
|
|
-// // 添加本身部门编号
|
|
|
-// CollUtil.addAll(result.getDataIds(), enterpriseUserBind
|
|
|
-// .getEnterpriseId());
|
|
|
-// continue;
|
|
|
-// }
|
|
|
-// // 情况五,SELF
|
|
|
-// if (Objects.equals(role.getDataScope(), DataScopeEnum.SELF.getScope())) {
|
|
|
-// // if (!EnterpriseUserTypeEnum.ADMIN.getType()
|
|
|
-// // .equals(enterpriseUserBind.getUserType())) {
|
|
|
-// // // 不是管理员,加入自己的权限
|
|
|
-// // result.setSelf(true);
|
|
|
-// // }
|
|
|
-// // 20240718 更改 所有用户都只能看到自己的数据
|
|
|
-// result.setSelf(true);
|
|
|
-// continue;
|
|
|
-// }
|
|
|
-// // 未知情况,error log 即可
|
|
|
-// log.error("[getDeptDataPermission][LoginUser({}) role({}) 无法处理]", userId, toJsonString(result));
|
|
|
-// }
|
|
|
-// return result;
|
|
|
-// }
|
|
|
-//
|
|
|
-//
|
|
|
-// /**
|
|
|
-// * 获得自身的代理对象,解决 AOP 生效问题
|
|
|
-// *
|
|
|
-// * @return 自己
|
|
|
-// */
|
|
|
-// private MdePermissionServiceImpl getSelf() {
|
|
|
-// return SpringUtil.getBean(getClass());
|
|
|
-// }
|
|
|
-
|
|
|
|
|
|
@Override
|
|
|
- public boolean hasAnyPermissions(Long userId, String... permissions) {
|
|
|
+ public boolean hasAnyPermissions(Long enterpriseId, Long userId, String... permissions) {
|
|
|
+ // 如果为空,说明已经有权限
|
|
|
+ if (ArrayUtil.isEmpty(permissions)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获得当前登录的角色。如果为空,说明没有权限
|
|
|
+ List<MdeRoleDO> roles = getEnableUserRoleListByUserIdFromCache(enterpriseId,userId);
|
|
|
+ if (CollUtil.isEmpty(roles)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 情况一:遍历判断每个权限,如果有一满足,说明有权限
|
|
|
+ for (String permission : permissions) {
|
|
|
+ if (hasAnyPermission(roles, permission)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 情况二:如果是超管,也说明有权限
|
|
|
+ return roleService.hasAnySuperAdmin(convertSet(roles, MdeRoleDO::getId));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断指定角色,是否拥有该 permission 权限
|
|
|
+ *
|
|
|
+ * @param roles 指定角色数组
|
|
|
+ * @param permission 权限标识
|
|
|
+ * @return 是否拥有
|
|
|
+ */
|
|
|
+ private boolean hasAnyPermission(List<MdeRoleDO> roles, String permission) {
|
|
|
+ List<Long> menuIds = menuService.getMenuIdListByPermissionFromCache(permission);
|
|
|
+ // 采用严格模式,如果权限找不到对应的 Menu 的话,也认为没有权限
|
|
|
+ if (CollUtil.isEmpty(menuIds)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断是否有权限
|
|
|
+ Set<Long> roleIds = convertSet(roles, MdeRoleDO::getId);
|
|
|
+ for (Long menuId : menuIds) {
|
|
|
+ // 获得拥有该菜单的角色编号集合
|
|
|
+ Set<Long> menuRoleIds = getSelf().getMenuRoleIdListByMenuIdFromCache(menuId);
|
|
|
+ // 如果有交集,说明有权限
|
|
|
+ if (CollUtil.containsAny(menuRoleIds, roleIds)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public boolean hasAnyRoles(Long userId, String... roles) {
|
|
|
- return false;
|
|
|
+ public boolean hasAnyRoles(Long enterpriseId, Long userId, String... roles) {
|
|
|
+ // 如果为空,说明已经有权限
|
|
|
+ if (ArrayUtil.isEmpty(roles)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获得当前登录的角色。如果为空,说明没有权限
|
|
|
+ List<MdeRoleDO> roleList = getEnableUserRoleListByUserIdFromCache(enterpriseId, userId);
|
|
|
+ if (CollUtil.isEmpty(roleList)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断是否有角色
|
|
|
+ Set<String> userRoles = convertSet(roleList, MdeRoleDO::getCode);
|
|
|
+ return CollUtil.containsAny(userRoles, Sets.newHashSet(roles));
|
|
|
}
|
|
|
|
|
|
+ // ========== 角色-菜单的相关方法 ==========
|
|
|
+
|
|
|
@Override
|
|
|
+ @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换
|
|
|
+ @Caching(evict = {
|
|
|
+ @CacheEvict(value = RedisKeyConstants.MDE_MENU_ROLE_ID_LIST,
|
|
|
+ allEntries = true),
|
|
|
+ @CacheEvict(value = RedisKeyConstants.MDE_PERMISSION_MENU_ID_LIST,
|
|
|
+ allEntries = true) // allEntries 清空所有缓存,主要一次更新涉及到的 menuIds 较多,反倒批量会更快
|
|
|
+ })
|
|
|
public void assignRoleMenu(Long roleId, Set<Long> menuIds) {
|
|
|
-
|
|
|
+ // 获得角色拥有菜单编号
|
|
|
+ Set<Long> dbMenuIds = convertSet(roleMenuMapper.selectListByRoleId(roleId), MdeRoleMenuDO::getMenuId);
|
|
|
+ // 计算新增和删除的菜单编号
|
|
|
+ Set<Long> menuIdList = CollUtil.emptyIfNull(menuIds);
|
|
|
+ Collection<Long> createMenuIds = CollUtil.subtract(menuIdList, dbMenuIds);
|
|
|
+ Collection<Long> deleteMenuIds = CollUtil.subtract(dbMenuIds, menuIdList);
|
|
|
+ // 执行新增和删除。对于已经授权的菜单,不用做任何处理
|
|
|
+ if (CollUtil.isNotEmpty(createMenuIds)) {
|
|
|
+ roleMenuMapper.insertBatch(CollectionUtils.convertList(createMenuIds, menuId -> {
|
|
|
+ MdeRoleMenuDO entity = new MdeRoleMenuDO();
|
|
|
+ entity.setRoleId(roleId);
|
|
|
+ entity.setMenuId(menuId);
|
|
|
+ return entity;
|
|
|
+ }));
|
|
|
+ }
|
|
|
+ if (CollUtil.isNotEmpty(deleteMenuIds)) {
|
|
|
+ roleMenuMapper.deleteListByRoleIdAndMenuIds(roleId, deleteMenuIds);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ @Caching(evict = {
|
|
|
+ @CacheEvict(value = RedisKeyConstants.MDE_MENU_ROLE_ID_LIST,
|
|
|
+ allEntries = true), // allEntries 清空所有缓存,此处无法方便获得 roleId 对应的 menu 缓存们
|
|
|
+ @CacheEvict(value = RedisKeyConstants.MDE_USER_ROLE_IDS,
|
|
|
+ allEntries = true) // allEntries 清空所有缓存,此处无法方便获得 roleId 对应的 user 缓存们
|
|
|
+ })
|
|
|
public void processRoleDeleted(Long roleId) {
|
|
|
-
|
|
|
+ // 标记删除 UserRole
|
|
|
+ userRoleMapper.deleteListByRoleId(roleId);
|
|
|
+ // 标记删除 RoleMenu
|
|
|
+ roleMenuMapper.deleteListByRoleId(roleId);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
+ @CacheEvict(value = RedisKeyConstants.MDE_MENU_ROLE_ID_LIST, key = "#menuId")
|
|
|
public void processMenuDeleted(Long menuId) {
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Set<Long> getRoleMenuListByRoleId(Long roleId) {
|
|
|
- return MdePermissionService.super.getRoleMenuListByRoleId(roleId);
|
|
|
+ roleMenuMapper.deleteListByMenuId(menuId);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public Set<Long> getRoleMenuListByRoleId(Collection<Long> roleIds) {
|
|
|
- return Set.of();
|
|
|
+ if (CollUtil.isEmpty(roleIds)) {
|
|
|
+ return Collections.emptySet();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果是管理员的情况下,获取全部菜单编号
|
|
|
+ if (roleService.hasAnySuperAdmin(roleIds)) {
|
|
|
+ return convertSet(menuService.getMenuList(), MdeMenuDO::getId);
|
|
|
+ }
|
|
|
+ // 如果是非管理员的情况下,获得拥有的菜单编号
|
|
|
+ return convertSet(roleMenuMapper.selectListByRoleId(roleIds), MdeRoleMenuDO::getMenuId);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
+ @Cacheable(value = RedisKeyConstants.MDE_MENU_ROLE_ID_LIST, key = "#menuId")
|
|
|
public Set<Long> getMenuRoleIdListByMenuIdFromCache(Long menuId) {
|
|
|
- return Set.of();
|
|
|
+ return convertSet(roleMenuMapper.selectListByMenuId(menuId), MdeRoleMenuDO::getRoleId);
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public void assignUserRole(Long userId, Set<Long> roleIds) {
|
|
|
+ // ========== 用户-角色的相关方法 ==========
|
|
|
|
|
|
+ @Override
|
|
|
+ @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换
|
|
|
+ @CacheEvict(value = RedisKeyConstants.MDE_USER_ROLE_IDS, key = "#userId")
|
|
|
+ public void assignEnterpriseUserRole(Long enterpriseId, Long userId, Set<Long> roleIds) {
|
|
|
+ // 获得角色拥有角色编号
|
|
|
+ Set<Long> dbRoleIds = convertSet(userRoleMapper.selectListByEnterpriseIdAndUserId(enterpriseId, userId),
|
|
|
+ MdeUserRoleDO::getRoleId);
|
|
|
+ // 计算新增和删除的角色编号
|
|
|
+ Set<Long> roleIdList = CollUtil.emptyIfNull(roleIds);
|
|
|
+ Collection<Long> createRoleIds = CollUtil.subtract(roleIdList, dbRoleIds);
|
|
|
+ Collection<Long> deleteMenuIds = CollUtil.subtract(dbRoleIds, roleIdList);
|
|
|
+ // 执行新增和删除。对于已经授权的角色,不用做任何处理
|
|
|
+ if (!CollectionUtil.isEmpty(createRoleIds)) {
|
|
|
+ userRoleMapper.insertBatch(CollectionUtils.convertList(createRoleIds, roleId -> {
|
|
|
+ MdeUserRoleDO entity = new MdeUserRoleDO();
|
|
|
+ entity.setUserId(userId);
|
|
|
+ entity.setRoleId(roleId);
|
|
|
+ return entity;
|
|
|
+ }));
|
|
|
+ }
|
|
|
+ if (!CollectionUtil.isEmpty(deleteMenuIds)) {
|
|
|
+ userRoleMapper.deleteListByEnterpriseIdAndUserIdAndRoleIdIds(enterpriseId, userId, deleteMenuIds);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public void assignUserRoleByDefault(Long userId, MdeDefaultRoleEnum roleEnum) {
|
|
|
-
|
|
|
+ public void assignEnterpriseUserRoleByDefault(Long enterpriseId, Long userId, MdeDefaultRoleEnum roleEnum) {
|
|
|
+ // 获得默认角色信息
|
|
|
+ MdeRoleDO role = roleService.getRoleByDefault(roleEnum);
|
|
|
+ MdeUserRoleDO entity = new MdeUserRoleDO();
|
|
|
+ entity.setEnterpriseId(enterpriseId);
|
|
|
+ entity.setUserId(userId);
|
|
|
+ entity.setRoleId(role.getId());
|
|
|
+ userRoleMapper.insert(entity);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public void processUserDeleted(Long userId) {
|
|
|
-
|
|
|
+ @CacheEvict(value = RedisKeyConstants.MDE_USER_ROLE_IDS, key = "#userId")
|
|
|
+ public void processEnterpriseUserDeleted(Long userId) {
|
|
|
+ userRoleMapper.deleteListByEnterpriseIdAndUserId(userId);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public Set<Long> getUserRoleIdListByRoleId(Collection<Long> roleIds) {
|
|
|
- return Set.of();
|
|
|
+ public Set<Long> getEnterpriseUserRoleIdListByUserId(Long enterpriseId, Long userId) {
|
|
|
+ return convertSet(userRoleMapper.selectListByEnterpriseIdAndUserId(enterpriseId, userId), MdeUserRoleDO::getRoleId);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public Set<Long> getUserRoleIdListByUserId(Long userId) {
|
|
|
- return Set.of();
|
|
|
+ @Cacheable(value = RedisKeyConstants.MDE_USER_ROLE_IDS, key = "#enterpriseId + ':' + #userId")
|
|
|
+ public Set<Long> getEnterpriseUserRoleIdListByUserIdFromCache(Long enterpriseId, Long userId) {
|
|
|
+ return getEnterpriseUserRoleIdListByUserId(enterpriseId, userId);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public Set<Long> getUserRoleIdListByUserIdFromCache(Long userId) {
|
|
|
- return Set.of();
|
|
|
+ public Set<Long> getUserRoleIdListByRoleId(Collection<Long> roleIds) {
|
|
|
+ return convertSet(userRoleMapper.selectListByRoleIds(roleIds), MdeUserRoleDO::getUserId);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获得用户拥有的角色,并且这些角色是开启状态的
|
|
|
+ *
|
|
|
+ * @param userId 用户编号
|
|
|
+ * @return 用户拥有的角色
|
|
|
+ */
|
|
|
+ @VisibleForTesting
|
|
|
+ List<MdeRoleDO> getEnableUserRoleListByUserIdFromCache(Long enterpriseId, Long userId) {
|
|
|
+ // 获得用户拥有的角色编号
|
|
|
+ Set<Long> roleIds = getSelf().getEnterpriseUserRoleIdListByUserIdFromCache(enterpriseId, userId);
|
|
|
+ // 获得角色数组,并移除被禁用的
|
|
|
+ List<MdeRoleDO> roles = roleService.getRoleListFromCache(roleIds);
|
|
|
+ roles.removeIf(role -> !MendunerStatusEnum.ENABLE.getStatus().equals(role.getStatus()));
|
|
|
+ return roles;
|
|
|
}
|
|
|
|
|
|
+ // ========== 用户-部门的相关方法 ==========
|
|
|
+
|
|
|
@Override
|
|
|
public void assignRoleDataScope(Long roleId, Integer dataScope, Set<Long> dataScopeDataIds) {
|
|
|
-
|
|
|
+ roleService.updateRoleDataScope(roleId, dataScope, dataScopeDataIds);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public DataPermissionRespDTO getDataPermission(Long userId, Long enterpriseId) {
|
|
|
- return null;
|
|
|
+ @DataPermission(enable = false) // 关闭数据权限,不然就会出现递归获取数据权限的问题
|
|
|
+ public DataPermissionRespDTO getDataPermission(Long enterpriseId, Long userId) {
|
|
|
+ DataPermissionRespDTO result = new DataPermissionRespDTO();
|
|
|
+ // 获得用户的部门编号的缓存,通过 Guava 的 Suppliers 惰性求值,即有且仅有第一次发起 DB 的查询
|
|
|
+ EnterpriseUserBindDO enterpriseUserBind = enterpriseUserBindService
|
|
|
+ .selectByEnterpriseIdAndUserId(enterpriseId, userId);
|
|
|
+ if (enterpriseUserBind == null) {
|
|
|
+ // 找不到企业用户 or 禁用了
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ // 获得用户的角色
|
|
|
+ List<MdeRoleDO> roles = getEnableUserRoleListByUserIdFromCache(enterpriseId, userId);
|
|
|
+ // 如果角色为空,则只能查看自己
|
|
|
+ if (CollUtil.isEmpty(roles)) {
|
|
|
+ result.setSelf(true);
|
|
|
+ if(enterpriseUserBindService.checkIsAdmin(enterpriseUserBind)) {
|
|
|
+ // 管理员
|
|
|
+ result.setDataIds(Collections.singleton(enterpriseId));
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 遍历每个角色,计算
|
|
|
+ for (MdeRoleDO role : roles) {
|
|
|
+ // 为空时,跳过
|
|
|
+ if (role.getDataScope() == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 情况一,ALL 所有的数据权限
|
|
|
+ if (Objects.equals(role.getDataScope(), DataScopeEnum.ALL.getScope())) {
|
|
|
+ result.setAll(true);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 情况二,DEPT_CUSTOM 自定义
|
|
|
+ if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_CUSTOM.getScope())) {
|
|
|
+ CollUtil.addAll(result.getDataIds(), role.getDataScopeEnterpriseIds());
|
|
|
+ // 自定义可见部门时,保证可以看到自己所在的部门。否则,一些场景下可能会有问题。
|
|
|
+ // 例如说,登录时,基于 t_user 的 username 查询会可能被 dept_id 过滤掉
|
|
|
+ CollUtil.addAll(result.getDataIds(), enterpriseUserBind.getEnterpriseId());
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 情况三,DEPT_ONLY 自己所在的数据权限
|
|
|
+ if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_ONLY.getScope())) {
|
|
|
+ CollectionUtils.addIfNotNull(result.getDataIds(), enterpriseUserBind.getEnterpriseId());
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 情况四,DEPT_DEPT_AND_CHILD 自己所在及以下的数据权限
|
|
|
+ if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_AND_CHILD.getScope())) {
|
|
|
+ CollUtil.addAll(result.getDataIds(), enterpriseService
|
|
|
+ .getChildEnterpriseIdListFromCache(enterpriseUserBind.getEnterpriseId()));
|
|
|
+ // 添加本身部门编号
|
|
|
+ CollUtil.addAll(result.getDataIds(), enterpriseUserBind
|
|
|
+ .getEnterpriseId());
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 情况五,SELF
|
|
|
+ if (Objects.equals(role.getDataScope(), DataScopeEnum.SELF.getScope())) {
|
|
|
+ // if (!EnterpriseUserTypeEnum.ADMIN.getType()
|
|
|
+ // .equals(enterpriseUserBind.getUserType())) {
|
|
|
+ // // 不是管理员,加入自己的权限
|
|
|
+ // result.setSelf(true);
|
|
|
+ // }
|
|
|
+ // 20240718 更改 所有用户都只能看到自己的数据
|
|
|
+ result.setSelf(true);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 未知情况,error log 即可
|
|
|
+ log.error("[getDeptDataPermission][LoginUser({}) role({}) 无法处理]", userId, toJsonString(result));
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获得自身的代理对象,解决 AOP 生效问题
|
|
|
+ *
|
|
|
+ * @return 自己
|
|
|
+ */
|
|
|
+ private MdePermissionServiceImpl getSelf() {
|
|
|
+ return SpringUtil.getBean(getClass());
|
|
|
}
|
|
|
+
|
|
|
}
|