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 package cn.iocoder.yudao.module.system.controller.admin.permission; 1 package cn.iocoder.yudao.module.system.controller.admin.permission;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.*; 6 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.*;
6 import cn.iocoder.yudao.module.system.convert.permission.MenuConvert; 7 import cn.iocoder.yudao.module.system.convert.permission.MenuConvert;
7 import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; 8 import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
8 import cn.iocoder.yudao.module.system.service.permission.MenuService; 9 import cn.iocoder.yudao.module.system.service.permission.MenuService;
  10 +import cn.iocoder.yudao.module.system.service.tenant.TenantService;
9 import io.swagger.annotations.Api; 11 import io.swagger.annotations.Api;
10 import io.swagger.annotations.ApiImplicitParam; 12 import io.swagger.annotations.ApiImplicitParam;
11 import io.swagger.annotations.ApiOperation; 13 import io.swagger.annotations.ApiOperation;
@@ -28,6 +30,8 @@ public class MenuController { @@ -28,6 +30,8 @@ public class MenuController {
28 30
29 @Resource 31 @Resource
30 private MenuService menuService; 32 private MenuService menuService;
  33 + @Resource
  34 + private TenantService tenantService;
31 35
32 @PostMapping("/create") 36 @PostMapping("/create")
33 @ApiOperation("创建菜单") 37 @ApiOperation("创建菜单")
@@ -64,7 +68,8 @@ public class MenuController { @@ -64,7 +68,8 @@ public class MenuController {
64 } 68 }
65 69
66 @GetMapping("/list-all-simple") 70 @GetMapping("/list-all-simple")
67 - @ApiOperation(value = "获取菜单精简信息列表", notes = "只包含被开启的菜单,用于【角色分配菜单】功能的选项") 71 + @ApiOperation(value = "获取菜单精简信息列表", notes = "只包含被开启的菜单,用于【角色分配菜单】功能的选项。" +
  72 + "在多租户的场景下,会只返回租户所在套餐有的菜单")
68 public CommonResult<List<MenuSimpleRespVO>> getSimpleMenus() { 73 public CommonResult<List<MenuSimpleRespVO>> getSimpleMenus() {
69 // 获得菜单列表,只要开启状态的 74 // 获得菜单列表,只要开启状态的
70 MenuListReqVO reqVO = new MenuListReqVO(); 75 MenuListReqVO reqVO = new MenuListReqVO();
@@ -72,6 +77,9 @@ public class MenuController { @@ -72,6 +77,9 @@ public class MenuController {
72 List<MenuDO> list = menuService.getMenus(reqVO); 77 List<MenuDO> list = menuService.getMenus(reqVO);
73 // 排序后,返回给前端 78 // 排序后,返回给前端
74 list.sort(Comparator.comparing(MenuDO::getSort)); 79 list.sort(Comparator.comparing(MenuDO::getSort));
  80 +
  81 + // 开启多租户的情况下,需要过滤掉未开通的菜单
  82 + tenantService.handleTenantMenu(menuIds -> list.removeIf(menu -> !CollUtil.contains(menuIds, menu.getId())));
75 return success(MenuConvert.INSTANCE.convertList02(list)); 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 package cn.iocoder.yudao.module.system.controller.admin.permission; 1 package cn.iocoder.yudao.module.system.controller.admin.permission;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleDataScopeReqVO; 5 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleDataScopeReqVO;
5 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleMenuReqVO; 6 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleMenuReqVO;
6 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignUserRoleReqVO; 7 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignUserRoleReqVO;
7 import cn.iocoder.yudao.module.system.service.permission.PermissionService; 8 import cn.iocoder.yudao.module.system.service.permission.PermissionService;
  9 +import cn.iocoder.yudao.module.system.service.tenant.TenantService;
8 import io.swagger.annotations.Api; 10 import io.swagger.annotations.Api;
9 import io.swagger.annotations.ApiImplicitParam; 11 import io.swagger.annotations.ApiImplicitParam;
10 import io.swagger.annotations.ApiOperation; 12 import io.swagger.annotations.ApiOperation;
  13 +import org.springframework.security.access.prepost.PreAuthorize;
11 import org.springframework.validation.annotation.Validated; 14 import org.springframework.validation.annotation.Validated;
12 import org.springframework.web.bind.annotation.*; 15 import org.springframework.web.bind.annotation.*;
13 16
@@ -29,28 +32,33 @@ public class PermissionController { @@ -29,28 +32,33 @@ public class PermissionController {
29 32
30 @Resource 33 @Resource
31 private PermissionService permissionService; 34 private PermissionService permissionService;
  35 + @Resource
  36 + private TenantService tenantService;
32 37
33 - // TODO @芋艿:处理下全新啊标识  
34 38
35 @ApiOperation("获得角色拥有的菜单编号") 39 @ApiOperation("获得角色拥有的菜单编号")
36 @ApiImplicitParam(name = "roleId", value = "角色编号", required = true, dataTypeClass = Long.class) 40 @ApiImplicitParam(name = "roleId", value = "角色编号", required = true, dataTypeClass = Long.class)
37 @GetMapping("/list-role-resources") 41 @GetMapping("/list-role-resources")
38 -// @RequiresPermissions("system:permission:assign-role-menu") 42 + @PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')")
39 public CommonResult<Set<Long>> listRoleMenus(Long roleId) { 43 public CommonResult<Set<Long>> listRoleMenus(Long roleId) {
40 return success(permissionService.getRoleMenuIds(roleId)); 44 return success(permissionService.getRoleMenuIds(roleId));
41 } 45 }
42 46
43 @PostMapping("/assign-role-menu") 47 @PostMapping("/assign-role-menu")
44 @ApiOperation("赋予角色菜单") 48 @ApiOperation("赋予角色菜单")
45 -// @RequiresPermissions("system:permission:assign-role-resource") 49 + @PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')")
46 public CommonResult<Boolean> assignRoleMenu(@Validated @RequestBody PermissionAssignRoleMenuReqVO reqVO) { 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 permissionService.assignRoleMenu(reqVO.getRoleId(), reqVO.getMenuIds()); 55 permissionService.assignRoleMenu(reqVO.getRoleId(), reqVO.getMenuIds());
48 return success(true); 56 return success(true);
49 } 57 }
50 58
51 @PostMapping("/assign-role-data-scope") 59 @PostMapping("/assign-role-data-scope")
52 @ApiOperation("赋予角色数据权限") 60 @ApiOperation("赋予角色数据权限")
53 -// @RequiresPermissions("system:permission:assign-role-data-scope") 61 + @PreAuthorize("@ss.hasPermission('system:permission:assign-role-data-scope')")
54 public CommonResult<Boolean> assignRoleDataScope(@Valid @RequestBody PermissionAssignRoleDataScopeReqVO reqVO) { 62 public CommonResult<Boolean> assignRoleDataScope(@Valid @RequestBody PermissionAssignRoleDataScopeReqVO reqVO) {
55 permissionService.assignRoleDataScope(reqVO.getRoleId(), reqVO.getDataScope(), reqVO.getDataScopeDeptIds()); 63 permissionService.assignRoleDataScope(reqVO.getRoleId(), reqVO.getDataScope(), reqVO.getDataScopeDeptIds());
56 return success(true); 64 return success(true);
@@ -59,14 +67,14 @@ public class PermissionController { @@ -59,14 +67,14 @@ public class PermissionController {
59 @ApiOperation("获得管理员拥有的角色编号列表") 67 @ApiOperation("获得管理员拥有的角色编号列表")
60 @ApiImplicitParam(name = "userId", value = "用户编号", required = true, dataTypeClass = Long.class) 68 @ApiImplicitParam(name = "userId", value = "用户编号", required = true, dataTypeClass = Long.class)
61 @GetMapping("/list-user-roles") 69 @GetMapping("/list-user-roles")
62 -// @RequiresPermissions("system:permission:assign-user-role") 70 + @PreAuthorize("@ss.hasPermission('system:permission:assign-user-role')")
63 public CommonResult<Set<Long>> listAdminRoles(@RequestParam("userId") Long userId) { 71 public CommonResult<Set<Long>> listAdminRoles(@RequestParam("userId") Long userId) {
64 return success(permissionService.getUserRoleIdListByUserId(userId)); 72 return success(permissionService.getUserRoleIdListByUserId(userId));
65 } 73 }
66 74
67 @ApiOperation("赋予用户角色") 75 @ApiOperation("赋予用户角色")
68 @PostMapping("/assign-user-role") 76 @PostMapping("/assign-user-role")
69 -// @RequiresPermissions("system:permission:assign-user-role") 77 + @PreAuthorize("@ss.hasPermission('system:permission:assign-user-role')")
70 public CommonResult<Boolean> assignUserRole(@Validated @RequestBody PermissionAssignUserRoleReqVO reqVO) { 78 public CommonResult<Boolean> assignUserRole(@Validated @RequestBody PermissionAssignUserRoleReqVO reqVO) {
71 permissionService.assignUserRole(reqVO.getUserId(), reqVO.getRoleIds()); 79 permissionService.assignUserRole(reqVO.getUserId(), reqVO.getRoleIds());
72 return success(true); 80 return success(true);
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java
1 package cn.iocoder.yudao.module.system.service.tenant; 1 package cn.iocoder.yudao.module.system.service.tenant;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
4 import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; 5 import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
5 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO; 6 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO;
6 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO; 7 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO;
7 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; 8 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
8 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO; 9 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO;
9 import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; 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 import javax.validation.Valid; 13 import javax.validation.Valid;
12 import java.util.Collection; 14 import java.util.Collection;
@@ -111,4 +113,12 @@ public interface TenantService extends TenantFrameworkService { @@ -111,4 +113,12 @@ public interface TenantService extends TenantFrameworkService {
111 */ 113 */
112 List<TenantDO> getTenantListByPackageId(Long packageId); 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,6 +7,8 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
7 import cn.iocoder.yudao.framework.common.pojo.PageResult; 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 8 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
9 import cn.iocoder.yudao.framework.common.util.date.DateUtils; 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 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; 12 import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
11 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO; 13 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO;
12 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO; 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,6 +25,7 @@ import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum;
23 import cn.iocoder.yudao.module.system.mq.producer.tenant.TenantProducer; 25 import cn.iocoder.yudao.module.system.mq.producer.tenant.TenantProducer;
24 import cn.iocoder.yudao.module.system.service.permission.PermissionService; 26 import cn.iocoder.yudao.module.system.service.permission.PermissionService;
25 import cn.iocoder.yudao.module.system.service.permission.RoleService; 27 import cn.iocoder.yudao.module.system.service.permission.RoleService;
  28 +import cn.iocoder.yudao.module.system.service.tenant.handler.TenantMenuHandler;
26 import cn.iocoder.yudao.module.system.service.user.AdminUserService; 29 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
27 import lombok.extern.slf4j.Slf4j; 30 import lombok.extern.slf4j.Slf4j;
28 import org.springframework.scheduling.annotation.Scheduled; 31 import org.springframework.scheduling.annotation.Scheduled;
@@ -68,6 +71,9 @@ public class TenantServiceImpl implements TenantService { @@ -68,6 +71,9 @@ public class TenantServiceImpl implements TenantService {
68 private volatile Date maxUpdateTime; 71 private volatile Date maxUpdateTime;
69 72
70 @Resource 73 @Resource
  74 + private TenantProperties tenantProperties;
  75 +
  76 + @Resource
71 private TenantMapper tenantMapper; 77 private TenantMapper tenantMapper;
72 78
73 @Resource 79 @Resource
@@ -292,4 +298,17 @@ public class TenantServiceImpl implements TenantService { @@ -292,4 +298,17 @@ public class TenantServiceImpl implements TenantService {
292 return tenantMapper.selectListByPackageId(packageId); 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 +}