租户修改角色的权限时,增加租户套餐的过滤,避免越权!

This commit is contained in:
YunaiV 2022-02-23 13:19:08 +08:00
parent e4be51b14a
commit d10b4595a2
5 changed files with 73 additions and 7 deletions

View File

@ -1,11 +1,13 @@
package cn.iocoder.yudao.module.system.controller.admin.permission; package cn.iocoder.yudao.module.system.controller.admin.permission;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.*; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.*;
import cn.iocoder.yudao.module.system.convert.permission.MenuConvert; import cn.iocoder.yudao.module.system.convert.permission.MenuConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
import cn.iocoder.yudao.module.system.service.permission.MenuService; import cn.iocoder.yudao.module.system.service.permission.MenuService;
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
@ -28,6 +30,8 @@ public class MenuController {
@Resource @Resource
private MenuService menuService; private MenuService menuService;
@Resource
private TenantService tenantService;
@PostMapping("/create") @PostMapping("/create")
@ApiOperation("创建菜单") @ApiOperation("创建菜单")
@ -64,7 +68,8 @@ public class MenuController {
} }
@GetMapping("/list-all-simple") @GetMapping("/list-all-simple")
@ApiOperation(value = "获取菜单精简信息列表", notes = "只包含被开启的菜单,用于【角色分配菜单】功能的选项") @ApiOperation(value = "获取菜单精简信息列表", notes = "只包含被开启的菜单,用于【角色分配菜单】功能的选项。" +
"在多租户的场景下,会只返回租户所在套餐有的菜单")
public CommonResult<List<MenuSimpleRespVO>> getSimpleMenus() { public CommonResult<List<MenuSimpleRespVO>> getSimpleMenus() {
// 获得菜单列表只要开启状态的 // 获得菜单列表只要开启状态的
MenuListReqVO reqVO = new MenuListReqVO(); MenuListReqVO reqVO = new MenuListReqVO();
@ -72,6 +77,9 @@ public class MenuController {
List<MenuDO> list = menuService.getMenus(reqVO); List<MenuDO> list = menuService.getMenus(reqVO);
// 排序后返回给前端 // 排序后返回给前端
list.sort(Comparator.comparing(MenuDO::getSort)); list.sort(Comparator.comparing(MenuDO::getSort));
// 开启多租户的情况下需要过滤掉未开通的菜单
tenantService.handleTenantMenu(menuIds -> list.removeIf(menu -> !CollUtil.contains(menuIds, menu.getId())));
return success(MenuConvert.INSTANCE.convertList02(list)); return success(MenuConvert.INSTANCE.convertList02(list));
} }

View File

@ -1,13 +1,16 @@
package cn.iocoder.yudao.module.system.controller.admin.permission; package cn.iocoder.yudao.module.system.controller.admin.permission;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleDataScopeReqVO; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleDataScopeReqVO;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleMenuReqVO; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleMenuReqVO;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignUserRoleReqVO; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignUserRoleReqVO;
import cn.iocoder.yudao.module.system.service.permission.PermissionService; import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -29,28 +32,33 @@ public class PermissionController {
@Resource @Resource
private PermissionService permissionService; private PermissionService permissionService;
@Resource
private TenantService tenantService;
// TODO @芋艿处理下全新啊标识
@ApiOperation("获得角色拥有的菜单编号") @ApiOperation("获得角色拥有的菜单编号")
@ApiImplicitParam(name = "roleId", value = "角色编号", required = true, dataTypeClass = Long.class) @ApiImplicitParam(name = "roleId", value = "角色编号", required = true, dataTypeClass = Long.class)
@GetMapping("/list-role-resources") @GetMapping("/list-role-resources")
// @RequiresPermissions("system:permission:assign-role-menu") @PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')")
public CommonResult<Set<Long>> listRoleMenus(Long roleId) { public CommonResult<Set<Long>> listRoleMenus(Long roleId) {
return success(permissionService.getRoleMenuIds(roleId)); return success(permissionService.getRoleMenuIds(roleId));
} }
@PostMapping("/assign-role-menu") @PostMapping("/assign-role-menu")
@ApiOperation("赋予角色菜单") @ApiOperation("赋予角色菜单")
// @RequiresPermissions("system:permission:assign-role-resource") @PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')")
public CommonResult<Boolean> assignRoleMenu(@Validated @RequestBody PermissionAssignRoleMenuReqVO reqVO) { public CommonResult<Boolean> assignRoleMenu(@Validated @RequestBody PermissionAssignRoleMenuReqVO reqVO) {
// 开启多租户的情况下需要过滤掉未开通的菜单
tenantService.handleTenantMenu(menuIds -> reqVO.getMenuIds().removeIf(menuId -> !CollUtil.contains(menuIds, menuId)));
// 执行菜单的分配
permissionService.assignRoleMenu(reqVO.getRoleId(), reqVO.getMenuIds()); permissionService.assignRoleMenu(reqVO.getRoleId(), reqVO.getMenuIds());
return success(true); return success(true);
} }
@PostMapping("/assign-role-data-scope") @PostMapping("/assign-role-data-scope")
@ApiOperation("赋予角色数据权限") @ApiOperation("赋予角色数据权限")
// @RequiresPermissions("system:permission:assign-role-data-scope") @PreAuthorize("@ss.hasPermission('system:permission:assign-role-data-scope')")
public CommonResult<Boolean> assignRoleDataScope(@Valid @RequestBody PermissionAssignRoleDataScopeReqVO reqVO) { public CommonResult<Boolean> assignRoleDataScope(@Valid @RequestBody PermissionAssignRoleDataScopeReqVO reqVO) {
permissionService.assignRoleDataScope(reqVO.getRoleId(), reqVO.getDataScope(), reqVO.getDataScopeDeptIds()); permissionService.assignRoleDataScope(reqVO.getRoleId(), reqVO.getDataScope(), reqVO.getDataScopeDeptIds());
return success(true); return success(true);
@ -59,14 +67,14 @@ public class PermissionController {
@ApiOperation("获得管理员拥有的角色编号列表") @ApiOperation("获得管理员拥有的角色编号列表")
@ApiImplicitParam(name = "userId", value = "用户编号", required = true, dataTypeClass = Long.class) @ApiImplicitParam(name = "userId", value = "用户编号", required = true, dataTypeClass = Long.class)
@GetMapping("/list-user-roles") @GetMapping("/list-user-roles")
// @RequiresPermissions("system:permission:assign-user-role") @PreAuthorize("@ss.hasPermission('system:permission:assign-user-role')")
public CommonResult<Set<Long>> listAdminRoles(@RequestParam("userId") Long userId) { public CommonResult<Set<Long>> listAdminRoles(@RequestParam("userId") Long userId) {
return success(permissionService.getUserRoleIdListByUserId(userId)); return success(permissionService.getUserRoleIdListByUserId(userId));
} }
@ApiOperation("赋予用户角色") @ApiOperation("赋予用户角色")
@PostMapping("/assign-user-role") @PostMapping("/assign-user-role")
// @RequiresPermissions("system:permission:assign-user-role") @PreAuthorize("@ss.hasPermission('system:permission:assign-user-role')")
public CommonResult<Boolean> assignUserRole(@Validated @RequestBody PermissionAssignUserRoleReqVO reqVO) { public CommonResult<Boolean> assignUserRole(@Validated @RequestBody PermissionAssignUserRoleReqVO reqVO) {
permissionService.assignUserRole(reqVO.getUserId(), reqVO.getRoleIds()); permissionService.assignUserRole(reqVO.getUserId(), reqVO.getRoleIds());
return success(true); return success(true);

View File

@ -1,12 +1,14 @@
package cn.iocoder.yudao.module.system.service.tenant; package cn.iocoder.yudao.module.system.service.tenant;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.service.tenant.handler.TenantMenuHandler;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.Collection; import java.util.Collection;
@ -111,4 +113,12 @@ public interface TenantService extends TenantFrameworkService {
*/ */
List<TenantDO> getTenantListByPackageId(Long packageId); List<TenantDO> getTenantListByPackageId(Long packageId);
/**
* 进行租户的菜单处理逻辑
* 其中租户编号从 {@link TenantContextHolder} 上下文中获取
*
* @param handler 处理器
*/
void handleTenantMenu(TenantMenuHandler handler);
} }

View File

@ -7,6 +7,8 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.tenant.config.TenantProperties;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO;
@ -23,6 +25,7 @@ import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum;
import cn.iocoder.yudao.module.system.mq.producer.tenant.TenantProducer; import cn.iocoder.yudao.module.system.mq.producer.tenant.TenantProducer;
import cn.iocoder.yudao.module.system.service.permission.PermissionService; import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.permission.RoleService; import cn.iocoder.yudao.module.system.service.permission.RoleService;
import cn.iocoder.yudao.module.system.service.tenant.handler.TenantMenuHandler;
import cn.iocoder.yudao.module.system.service.user.AdminUserService; import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
@ -67,6 +70,9 @@ public class TenantServiceImpl implements TenantService {
*/ */
private volatile Date maxUpdateTime; private volatile Date maxUpdateTime;
@Resource
private TenantProperties tenantProperties;
@Resource @Resource
private TenantMapper tenantMapper; private TenantMapper tenantMapper;
@ -292,4 +298,17 @@ public class TenantServiceImpl implements TenantService {
return tenantMapper.selectListByPackageId(packageId); return tenantMapper.selectListByPackageId(packageId);
} }
@Override
public void handleTenantMenu(TenantMenuHandler handler) {
// 如果禁用则不执行逻辑
if (Boolean.FALSE.equals(tenantProperties.getEnable())) {
return;
}
// 获得租户然后获得菜单
TenantDO tenant = getTenant(TenantContextHolder.getRequiredTenantId());
TenantPackageDO tenantPackage = tenantPackageService.getTenantPackage(tenant.getPackageId());
// 执行处理器
handler.handle(tenantPackage.getMenuIds());
}
} }

View File

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.system.service.tenant.handler;
import java.util.Set;
/**
* 租户菜单处理
* 目的尽量减少租户逻辑耦合到系统中
*
* @author 芋道源码
*/
public interface TenantMenuHandler {
/**
* 基于传入的租户菜单列表进行相关逻辑的执行
* 例如说返回可分配菜单的时候可以移除多余的
*
* @param menuIds 菜单列表
*/
void handle(Set<Long> menuIds);
}