Browse Source

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

YunaiV 3 years ago
parent
commit
d10b4595a2

+ 9 - 1
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuController.java

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

+ 14 - 6
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/PermissionController.java

@@ -1,13 +1,16 @@
 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.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.PermissionAssignUserRoleReqVO;
 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.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
@@ -29,28 +32,33 @@ public class PermissionController {
 
     @Resource
     private PermissionService permissionService;
+    @Resource
+    private TenantService tenantService;
 
-    // TODO @芋艿:处理下全新啊标识
 
     @ApiOperation("获得角色拥有的菜单编号")
     @ApiImplicitParam(name = "roleId", value = "角色编号", required = true, dataTypeClass = Long.class)
     @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) {
         return success(permissionService.getRoleMenuIds(roleId));
     }
 
     @PostMapping("/assign-role-menu")
     @ApiOperation("赋予角色菜单")
-//    @RequiresPermissions("system:permission:assign-role-resource")
+    @PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')")
     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());
         return success(true);
     }
 
     @PostMapping("/assign-role-data-scope")
     @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) {
         permissionService.assignRoleDataScope(reqVO.getRoleId(), reqVO.getDataScope(), reqVO.getDataScopeDeptIds());
         return success(true);
@@ -59,14 +67,14 @@ public class PermissionController {
     @ApiOperation("获得管理员拥有的角色编号列表")
     @ApiImplicitParam(name = "userId", value = "用户编号", required = true, dataTypeClass = Long.class)
     @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) {
         return success(permissionService.getUserRoleIdListByUserId(userId));
     }
 
     @ApiOperation("赋予用户角色")
     @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) {
         permissionService.assignUserRole(reqVO.getUserId(), reqVO.getRoleIds());
         return success(true);

+ 10 - 0
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java

@@ -1,12 +1,14 @@
 package cn.iocoder.yudao.module.system.service.tenant;
 
 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.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.TenantPageReqVO;
 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.service.tenant.handler.TenantMenuHandler;
 
 import javax.validation.Valid;
 import java.util.Collection;
@@ -111,4 +113,12 @@ public interface TenantService extends TenantFrameworkService {
      */
     List<TenantDO> getTenantListByPackageId(Long packageId);
 
+    /**
+     * 进行租户的菜单处理逻辑
+     * 其中,租户编号从 {@link TenantContextHolder} 上下文中获取
+     *
+     * @param handler 处理器
+     */
+    void handleTenantMenu(TenantMenuHandler handler);
+
 }

+ 19 - 0
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;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 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.module.system.controller.admin.permission.vo.role.RoleCreateReqVO;
 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.service.permission.PermissionService;
 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 lombok.extern.slf4j.Slf4j;
 import org.springframework.scheduling.annotation.Scheduled;
@@ -67,6 +70,9 @@ public class TenantServiceImpl implements TenantService {
      */
     private volatile Date maxUpdateTime;
 
+    @Resource
+    private TenantProperties tenantProperties;
+
     @Resource
     private TenantMapper tenantMapper;
 
@@ -292,4 +298,17 @@ public class TenantServiceImpl implements TenantService {
         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());
+    }
+
 }

+ 21 - 0
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/handler/TenantMenuHandler.java

@@ -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);
+
+}