Commit d10b4595a23ec2652275820e6b373ee95facb1ea

Authored by YunaiV
1 parent e4be51b1

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

yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuController.java
1 1 package cn.iocoder.yudao.module.system.controller.admin.permission;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 6 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.*;
6 7 import cn.iocoder.yudao.module.system.convert.permission.MenuConvert;
7 8 import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
8 9 import cn.iocoder.yudao.module.system.service.permission.MenuService;
  10 +import cn.iocoder.yudao.module.system.service.tenant.TenantService;
9 11 import io.swagger.annotations.Api;
10 12 import io.swagger.annotations.ApiImplicitParam;
11 13 import io.swagger.annotations.ApiOperation;
... ... @@ -28,6 +30,8 @@ public class MenuController {
28 30  
29 31 @Resource
30 32 private MenuService menuService;
  33 + @Resource
  34 + private TenantService tenantService;
31 35  
32 36 @PostMapping("/create")
33 37 @ApiOperation("创建菜单")
... ... @@ -64,7 +68,8 @@ public class MenuController {
64 68 }
65 69  
66 70 @GetMapping("/list-all-simple")
67   - @ApiOperation(value = "获取菜单精简信息列表", notes = "只包含被开启的菜单,用于【角色分配菜单】功能的选项")
  71 + @ApiOperation(value = "获取菜单精简信息列表", notes = "只包含被开启的菜单,用于【角色分配菜单】功能的选项。" +
  72 + "在多租户的场景下,会只返回租户所在套餐有的菜单")
68 73 public CommonResult<List<MenuSimpleRespVO>> getSimpleMenus() {
69 74 // 获得菜单列表,只要开启状态的
70 75 MenuListReqVO reqVO = new MenuListReqVO();
... ... @@ -72,6 +77,9 @@ public class MenuController {
72 77 List<MenuDO> list = menuService.getMenus(reqVO);
73 78 // 排序后,返回给前端
74 79 list.sort(Comparator.comparing(MenuDO::getSort));
  80 +
  81 + // 开启多租户的情况下,需要过滤掉未开通的菜单
  82 + tenantService.handleTenantMenu(menuIds -> list.removeIf(menu -> !CollUtil.contains(menuIds, menu.getId())));
75 83 return success(MenuConvert.INSTANCE.convertList02(list));
76 84 }
77 85  
... ...
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/PermissionController.java
1 1 package cn.iocoder.yudao.module.system.controller.admin.permission;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 5 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleDataScopeReqVO;
5 6 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleMenuReqVO;
6 7 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignUserRoleReqVO;
7 8 import cn.iocoder.yudao.module.system.service.permission.PermissionService;
  9 +import cn.iocoder.yudao.module.system.service.tenant.TenantService;
8 10 import io.swagger.annotations.Api;
9 11 import io.swagger.annotations.ApiImplicitParam;
10 12 import io.swagger.annotations.ApiOperation;
  13 +import org.springframework.security.access.prepost.PreAuthorize;
11 14 import org.springframework.validation.annotation.Validated;
12 15 import org.springframework.web.bind.annotation.*;
13 16  
... ... @@ -29,28 +32,33 @@ public class PermissionController {
29 32  
30 33 @Resource
31 34 private PermissionService permissionService;
  35 + @Resource
  36 + private TenantService tenantService;
32 37  
33   - // TODO @芋艿:处理下全新啊标识
34 38  
35 39 @ApiOperation("获得角色拥有的菜单编号")
36 40 @ApiImplicitParam(name = "roleId", value = "角色编号", required = true, dataTypeClass = Long.class)
37 41 @GetMapping("/list-role-resources")
38   -// @RequiresPermissions("system:permission:assign-role-menu")
  42 + @PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')")
39 43 public CommonResult<Set<Long>> listRoleMenus(Long roleId) {
40 44 return success(permissionService.getRoleMenuIds(roleId));
41 45 }
42 46  
43 47 @PostMapping("/assign-role-menu")
44 48 @ApiOperation("赋予角色菜单")
45   -// @RequiresPermissions("system:permission:assign-role-resource")
  49 + @PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')")
46 50 public CommonResult<Boolean> assignRoleMenu(@Validated @RequestBody PermissionAssignRoleMenuReqVO reqVO) {
  51 + // 开启多租户的情况下,需要过滤掉未开通的菜单
  52 + tenantService.handleTenantMenu(menuIds -> reqVO.getMenuIds().removeIf(menuId -> !CollUtil.contains(menuIds, menuId)));
  53 +
  54 + // 执行菜单的分配
47 55 permissionService.assignRoleMenu(reqVO.getRoleId(), reqVO.getMenuIds());
48 56 return success(true);
49 57 }
50 58  
51 59 @PostMapping("/assign-role-data-scope")
52 60 @ApiOperation("赋予角色数据权限")
53   -// @RequiresPermissions("system:permission:assign-role-data-scope")
  61 + @PreAuthorize("@ss.hasPermission('system:permission:assign-role-data-scope')")
54 62 public CommonResult<Boolean> assignRoleDataScope(@Valid @RequestBody PermissionAssignRoleDataScopeReqVO reqVO) {
55 63 permissionService.assignRoleDataScope(reqVO.getRoleId(), reqVO.getDataScope(), reqVO.getDataScopeDeptIds());
56 64 return success(true);
... ... @@ -59,14 +67,14 @@ public class PermissionController {
59 67 @ApiOperation("获得管理员拥有的角色编号列表")
60 68 @ApiImplicitParam(name = "userId", value = "用户编号", required = true, dataTypeClass = Long.class)
61 69 @GetMapping("/list-user-roles")
62   -// @RequiresPermissions("system:permission:assign-user-role")
  70 + @PreAuthorize("@ss.hasPermission('system:permission:assign-user-role')")
63 71 public CommonResult<Set<Long>> listAdminRoles(@RequestParam("userId") Long userId) {
64 72 return success(permissionService.getUserRoleIdListByUserId(userId));
65 73 }
66 74  
67 75 @ApiOperation("赋予用户角色")
68 76 @PostMapping("/assign-user-role")
69   -// @RequiresPermissions("system:permission:assign-user-role")
  77 + @PreAuthorize("@ss.hasPermission('system:permission:assign-user-role')")
70 78 public CommonResult<Boolean> assignUserRole(@Validated @RequestBody PermissionAssignUserRoleReqVO reqVO) {
71 79 permissionService.assignUserRole(reqVO.getUserId(), reqVO.getRoleIds());
72 80 return success(true);
... ...
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java
1 1 package cn.iocoder.yudao.module.system.service.tenant;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
4 5 import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
5 6 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO;
6 7 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO;
7 8 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
8 9 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO;
9 10 import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
  11 +import cn.iocoder.yudao.module.system.service.tenant.handler.TenantMenuHandler;
10 12  
11 13 import javax.validation.Valid;
12 14 import java.util.Collection;
... ... @@ -111,4 +113,12 @@ public interface TenantService extends TenantFrameworkService {
111 113 */
112 114 List<TenantDO> getTenantListByPackageId(Long packageId);
113 115  
  116 + /**
  117 + * 进行租户的菜单处理逻辑
  118 + * 其中,租户编号从 {@link TenantContextHolder} 上下文中获取
  119 + *
  120 + * @param handler 处理器
  121 + */
  122 + void handleTenantMenu(TenantMenuHandler handler);
  123 +
114 124 }
... ...
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java
... ... @@ -7,6 +7,8 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
7 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 8 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
9 9 import cn.iocoder.yudao.framework.common.util.date.DateUtils;
  10 +import cn.iocoder.yudao.framework.tenant.config.TenantProperties;
  11 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
10 12 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
11 13 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO;
12 14 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;
23 25 import cn.iocoder.yudao.module.system.mq.producer.tenant.TenantProducer;
24 26 import cn.iocoder.yudao.module.system.service.permission.PermissionService;
25 27 import cn.iocoder.yudao.module.system.service.permission.RoleService;
  28 +import cn.iocoder.yudao.module.system.service.tenant.handler.TenantMenuHandler;
26 29 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
27 30 import lombok.extern.slf4j.Slf4j;
28 31 import org.springframework.scheduling.annotation.Scheduled;
... ... @@ -68,6 +71,9 @@ public class TenantServiceImpl implements TenantService {
68 71 private volatile Date maxUpdateTime;
69 72  
70 73 @Resource
  74 + private TenantProperties tenantProperties;
  75 +
  76 + @Resource
71 77 private TenantMapper tenantMapper;
72 78  
73 79 @Resource
... ... @@ -292,4 +298,17 @@ public class TenantServiceImpl implements TenantService {
292 298 return tenantMapper.selectListByPackageId(packageId);
293 299 }
294 300  
  301 + @Override
  302 + public void handleTenantMenu(TenantMenuHandler handler) {
  303 + // 如果禁用,则不执行逻辑
  304 + if (Boolean.FALSE.equals(tenantProperties.getEnable())) {
  305 + return;
  306 + }
  307 + // 获得租户,然后获得菜单
  308 + TenantDO tenant = getTenant(TenantContextHolder.getRequiredTenantId());
  309 + TenantPackageDO tenantPackage = tenantPackageService.getTenantPackage(tenant.getPackageId());
  310 + // 执行处理器
  311 + handler.handle(tenantPackage.getMenuIds());
  312 + }
  313 +
295 314 }
... ...
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/handler/TenantMenuHandler.java 0 → 100644
  1 +package cn.iocoder.yudao.module.system.service.tenant.handler;
  2 +
  3 +import java.util.Set;
  4 +
  5 +/**
  6 + * 租户菜单处理
  7 + * 目的:尽量减少租户逻辑耦合到系统中
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +public interface TenantMenuHandler {
  12 +
  13 + /**
  14 + * 基于传入的租户菜单【全】列表,进行相关逻辑的执行
  15 + * 例如说,返回可分配菜单的时候,可以移除多余的
  16 + *
  17 + * @param menuIds 菜单列表
  18 + */
  19 + void handle(Set<Long> menuIds);
  20 +
  21 +}
... ...