com.diboot.iam.service.impl.IamResourceServiceImpl Maven / Gradle / Ivy
/*
* Copyright (c) 2015-2020, www.dibo.ltd ([email protected]).
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.diboot.iam.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.diboot.core.binding.RelationsBinder;
import com.diboot.core.exception.BusinessException;
import com.diboot.core.service.impl.BaseServiceImpl;
import com.diboot.core.util.BeanUtils;
import com.diboot.core.util.V;
import com.diboot.core.vo.LabelValue;
import com.diboot.core.vo.Status;
import com.diboot.iam.config.Cons;
import com.diboot.iam.dto.IamResourceDTO;
import com.diboot.iam.entity.IamResource;
import com.diboot.iam.mapper.IamResourceMapper;
import com.diboot.iam.service.IamResourceService;
import com.diboot.iam.vo.IamResourceListVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
/**
* 前端资源权限相关Service实现
*
* @author yangzhao
* @version 2.0.0
* @date 2020-02-27
* Copyright © diboot.com
*/
@Service
@Slf4j
public class IamResourceServiceImpl extends BaseServiceImpl implements IamResourceService {
@Override
@Transactional(rollbackFor = Exception.class)
public void deepCreateResourceAndChildren(IamResourceListVO iamResource) {
if (iamResource == null) {
return;
}
if (!super.createEntity(iamResource)) {
log.warn("新建资源权限失败,displayType = {}", iamResource.getDisplayType());
throw new BusinessException(Status.FAIL_OPERATION, "exception.business.resourceService.createFailed");
}
List children = iamResource.getChildren();
if (V.notEmpty(children)) {
for (IamResourceListVO vo : children) {
vo.setParentId(iamResource.getId());
if(V.isEmpty(vo.getId())) {
vo.setTenantId(iamResource.getTenantId());
}
this.deepCreateResourceAndChildren(vo);
}
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void createMenuResources(IamResourceDTO iamResourceDTO) {
// 创建menu
boolean success = this.createEntity(iamResourceDTO);
if (!success) {
throw new BusinessException(Status.FAIL_OPERATION, "exception.business.resourceService.createFailed");
}
// 批量创建按钮/权限列表
List permissionList = iamResourceDTO.getPermissionList();
if (V.isEmpty(permissionList)) {
return;
}
// 设置每一条按钮/权限的parentId与接口列表
permissionList.forEach(p -> {
p.setParentId(iamResourceDTO.getId());
p.setTenantId(iamResourceDTO.getTenantId());
p.setDisplayType(Cons.RESOURCE_PERMISSION_DISPLAY_TYPE.PERMISSION.name());
});
this.createEntities(permissionList);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateMenuResources(IamResourceDTO iamResourceDTO) {
// 检查是否设置了自身id为parentId,如果设置parentId与自身id相同,将会导致非常严重的潜在隐患
if (V.equals(iamResourceDTO.getId(), iamResourceDTO.getParentId())) {
throw new BusinessException(Status.FAIL_OPERATION, "exception.business.resourceService.setParentIdEqId");
}
// 更新 menu
this.updateEntity(iamResourceDTO);
List permissionList = iamResourceDTO.getPermissionList();
permissionList.forEach(p -> {
p.setParentId(iamResourceDTO.getId());
if(V.isEmpty(p.getId())) {
p.setTenantId(iamResourceDTO.getTenantId());
}
p.setDisplayType(Cons.RESOURCE_PERMISSION_DISPLAY_TYPE.PERMISSION.name());
});
// 需要更新的列表
List updatePermissionList = permissionList.stream()
.filter(p -> V.notEmpty(p.getId()))
.collect(Collectors.toList());
// 需要新建的列表
List createPermissionList = permissionList.stream()
.filter(p -> V.isEmpty(p.getId()))
.collect(Collectors.toList());
// 批量删除不存在的按钮/权限列表
LambdaQueryWrapper deleteWrapper = Wrappers.lambdaQuery()
.eq(IamResource::getParentId, iamResourceDTO.getId())
.eq(IamResource::getDisplayType, Cons.RESOURCE_PERMISSION_DISPLAY_TYPE.PERMISSION);
if (V.notEmpty(updatePermissionList)) {
deleteWrapper.notIn(IamResource::getId, updatePermissionList.stream().map(IamResource::getId).collect(Collectors.toList()));
}
this.deleteEntities(deleteWrapper);
// 批量新建按钮/权限列表
if (V.notEmpty(createPermissionList)) {
this.createEntities(createPermissionList);
}
// 批量更新按钮/权限列表
if (V.notEmpty(updatePermissionList)) {
this.updateEntities(updatePermissionList);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteMenuResources(String id) {
if (V.isEmpty(id)) {
throw new BusinessException(Status.FAIL_OPERATION, "exception.business.resourceService.paramsError");
}
// 删除该菜单
this.deleteEntity(id);
// 删除该菜单下的子菜单列表和相关按钮/权限列表
LambdaQueryWrapper subWrapper = Wrappers.lambdaQuery()
.eq(IamResource::getParentId, id);
List subList = this.getEntityList(subWrapper);
if (subList.size() > 0) {
this.deleteEntities(subWrapper);
}
// 递归删除下级子菜单的子菜单以及按钮/权限列表
List subMenuIdList = subList.stream()
.filter(item -> Cons.RESOURCE_PERMISSION_DISPLAY_TYPE.MENU.name().equals(item.getDisplayType()))
.map(IamResource::getId)
.collect(Collectors.toList());
if (V.notEmpty(subMenuIdList)) {
subMenuIdList.forEach(menuId -> {
log.info("开始递归删除子资源:{}", menuId);
this.deleteMenuResources(menuId);
});
}
}
@Override
public List getAllResources(String application) {
// 查询数据库中的所有权限
List entList = this.getEntityList(null);
return entList;
}
@Override
public List getMenuResources(String application) {
LambdaQueryWrapper wrapper = Wrappers.lambdaQuery()
.eq(V.notEmpty(application), IamResource::getAppModule, application)
.ne(IamResource::getDisplayType, Cons.RESOURCE_PERMISSION_DISPLAY_TYPE.PERMISSION.name());
List menuPermissionList = getEntityList(wrapper);
if (V.isEmpty(menuPermissionList)) {
return Collections.emptyList();
}
// 构建树结构
List iamResourceTreeVOList = RelationsBinder.convertAndBind(menuPermissionList, IamResourceListVO.class);
return BeanUtils.buildTree(iamResourceTreeVOList, Cons.TREE_ROOT_ID);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteMenuResources(List idList) {
if (V.isEmpty(idList)) {
throw new BusinessException(Status.FAIL_OPERATION, "exception.business.resourceService.nullIdList");
}
// 删除所有idList权限
this.deleteEntities(
Wrappers.lambdaQuery().in(IamResource::getId, idList)
);
// 删除idList下的子菜单列表和相关按钮/权限列表
LambdaQueryWrapper subWrapper = Wrappers.lambdaQuery()
.in(IamResource::getParentId, idList);
List subList = this.getEntityList(subWrapper);
if (subList.size() > 0) {
this.deleteEntities(subWrapper);
}
// 筛选出是菜单的选项,递归删除
List subMenuIdList = subList.stream()
.filter(item -> Cons.RESOURCE_PERMISSION_DISPLAY_TYPE.MENU.name().equals(item.getDisplayType()))
.map(IamResource::getId)
.collect(Collectors.toList());
if (V.notEmpty(subMenuIdList)) {
deleteMenuResources(subMenuIdList);
}
}
@Override
public List getMenuCatalogues() {
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper()
.select(IamResource::getDisplayName, IamResource::getId, IamResource::getRoutePath, IamResource::getParentId)
.in(IamResource::getDisplayType, Cons.RESOURCE_PERMISSION_DISPLAY_TYPE.CATALOGUE.name())
.orderByAsc(IamResource::getSortId);
return this.getLabelValueList(queryWrapper);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void createOrUpdateMenuResources(IamResourceDTO resourceDTO) {
// 如果dto的id存在,则更新
if(V.isEmpty(resourceDTO.getId())) {
this.createMenuResources(resourceDTO);
return;
}
// 更新 menu
this.updateEntity(resourceDTO);
List permissionList = resourceDTO.getPermissionList();
if(V.isEmpty(permissionList)) {
return;
}
List resourceCodes = new ArrayList<>();
permissionList.forEach(p -> {
p.setParentId(resourceDTO.getId());
p.setDisplayType(Cons.RESOURCE_PERMISSION_DISPLAY_TYPE.PERMISSION.name());
resourceCodes.add(p.getResourceCode());
});
// 查询本次涉及的资源
LambdaQueryWrapper oldPermissionsQuery = new QueryWrapper().lambda()
.eq(IamResource::getParentId, resourceDTO.getId()).eq(IamResource::getDisplayType, Cons.RESOURCE_PERMISSION_DISPLAY_TYPE.PERMISSION.name())
.in(IamResource::getResourceCode, resourceCodes);
List oldPermissionList = this.getEntityList(oldPermissionsQuery);
Map oldPermissionMap = oldPermissionList.stream().collect(Collectors.toMap(IamResource::getResourceCode, p->p));
// 需要更新的列表
List updatePermissionList = new ArrayList<>();
List createPermissionList = new ArrayList<>();
for(IamResource current : permissionList) {
IamResource originRes = oldPermissionMap.get(current.getResourceCode());
if(originRes != null) {
originRes.setMeta(current.getMeta()).setPermissionCode(current.getPermissionCode()).setDisplayName(current.getDisplayName());
updatePermissionList.add(originRes);
}
else {
current.setTenantId(resourceDTO.getTenantId());
createPermissionList.add(current);
}
}
// 批量新建按钮/权限列表
if (V.notEmpty(createPermissionList)) {
this.createEntities(createPermissionList);
}
// 批量更新按钮/权限列表
if (V.notEmpty(updatePermissionList)) {
this.updateEntities(updatePermissionList);
}
}
}