feat(2227-permissionQuery): 查询用户角色和权限
This commit is contained in:
parent
599fd9ddaf
commit
695d48560e
@ -5,6 +5,7 @@ import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -45,4 +46,10 @@ public enum FeatureResourceType {
|
||||
public static boolean applyPage(Integer code) {
|
||||
return PAGE.apply(code) || APP_ENTRY.apply(code);
|
||||
}
|
||||
|
||||
public static List<Integer> navTypes() {
|
||||
return Arrays.asList(FeatureResourceType.MENU.getCode(),
|
||||
FeatureResourceType.PAGE.getCode(),
|
||||
FeatureResourceType.APP_ENTRY.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -44,4 +45,10 @@ public enum RoleTypeEnum {
|
||||
return isAdmin;
|
||||
}
|
||||
|
||||
public static boolean isAdmin(String roleType) {
|
||||
return Optional.ofNullable(getRoleType(roleType))
|
||||
.map(RoleTypeEnum::isAdminRole)
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -21,4 +21,8 @@ public class WorkspaceOUPair {
|
||||
private Long ouId;
|
||||
|
||||
private Long workspaceId;
|
||||
|
||||
private String buildKey() {
|
||||
return ouId + "-" + workspaceId;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,15 @@
|
||||
package cn.axzo.tyr.client.model.req;
|
||||
|
||||
import cn.axzo.tyr.client.model.base.WorkspaceOUPair;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* NavTreeReq
|
||||
*
|
||||
@ -18,9 +23,12 @@ import lombok.NoArgsConstructor;
|
||||
@AllArgsConstructor
|
||||
public class NavTreeReq {
|
||||
|
||||
@NotNull(message = "人员ID不能为空")
|
||||
private Long personId;
|
||||
|
||||
/** 登录端 **/
|
||||
@NotNull(message = "登录端不能为空")
|
||||
private String terminal;
|
||||
|
||||
private Long ouId;
|
||||
@NotEmpty(message = "单位标识对不能为空")
|
||||
private List<WorkspaceOUPair> workspaceOUPairs;
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ public class PermissionQueryReq {
|
||||
|
||||
private String terminal;
|
||||
|
||||
private Integer featureType;
|
||||
private List<Integer> featureTypes;
|
||||
|
||||
private List<String> featureCodes;
|
||||
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package cn.axzo.tyr.client.model.res;
|
||||
|
||||
import cn.axzo.basics.common.model.IBaseTree;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@ -18,7 +20,7 @@ import java.util.List;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class NavTreeResp {
|
||||
public class NavTreeResp implements IBaseTree<NavTreeResp, Long> {
|
||||
|
||||
//APP侧需要扩展返回必要的数据
|
||||
|
||||
@ -30,6 +32,31 @@ public class NavTreeResp {
|
||||
private String featureName;
|
||||
/** 资源类型 **/
|
||||
private Integer featureType;
|
||||
/** 上级ID **/
|
||||
private Long parentId;
|
||||
/** 子级 **/
|
||||
private List<NavTreeResp> children;
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public Long getNodeCode() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public Long getParentNodeCode() {
|
||||
return parentId;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public List<NavTreeResp> getNodeChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNodeChildren(List<NavTreeResp> nodeChildren) {
|
||||
this.children = nodeChildren;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,18 +2,16 @@ package cn.axzo.tyr.server.controller.permission;
|
||||
|
||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.tyr.client.feign.FeatureResourceApi;
|
||||
import cn.axzo.tyr.client.model.req.ResourceSyncReq;
|
||||
import cn.axzo.tyr.client.model.req.FeatureResourceTreeSaveReq;
|
||||
import cn.axzo.tyr.client.model.res.FeatureResourceDTO;
|
||||
import cn.axzo.tyr.client.model.req.ResourceSyncReq;
|
||||
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
|
||||
import cn.axzo.tyr.server.service.FeatureResourceSyncService;
|
||||
import cn.axzo.tyr.server.service.SaasFeatureResourceService;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -28,11 +26,13 @@ import java.util.List;
|
||||
@RequiredArgsConstructor
|
||||
public class FeatureResourceController implements FeatureResourceApi {
|
||||
|
||||
private final FeatureResourceSyncService featureResourceSyncService;
|
||||
|
||||
private final SaasFeatureResourceService featureResourceService;
|
||||
|
||||
@Override
|
||||
public ApiResult<List<FeatureResourceTreeNode>> getSyncTreeById(Long id) {
|
||||
return ApiResult.ok(featureResourceService.getSyncTreeById(id));
|
||||
return ApiResult.ok(featureResourceSyncService.getSyncTreeById(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -42,7 +42,7 @@ public class FeatureResourceController implements FeatureResourceApi {
|
||||
log.warn("no ids to sync from base env");
|
||||
return ApiResult.ok();
|
||||
}
|
||||
featureResourceService.syncFromBase(req);
|
||||
featureResourceSyncService.syncFromBase(req);
|
||||
return ApiResult.ok();
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
package cn.axzo.tyr.server.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 权限对象
|
||||
*
|
||||
* @version V1.0
|
||||
* @author: ZhanSiHu
|
||||
* @date: 2024/4/8 11:09
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PermissionDO {
|
||||
private Long ouId;
|
||||
private Long workspaceId;
|
||||
private List<Long> featureIds;
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package cn.axzo.tyr.server.model;
|
||||
|
||||
import cn.axzo.tyr.client.model.base.WorkspaceOUPair;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 权限查询上下文
|
||||
*
|
||||
* @version V1.0
|
||||
* @author: ZhanSiHu
|
||||
* @date: 2024/4/8 11:04
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PermissionQueryContext {
|
||||
|
||||
/** 用户标识 **/
|
||||
private UserIdentity userIdentity;
|
||||
/** 权限范围 **/
|
||||
private List<WorkspaceOUPair> workspaceOUPairs;
|
||||
/** 登录端 **/
|
||||
private String terminal;
|
||||
/** 资源类型 **/
|
||||
private List<Integer> featureTypes;
|
||||
|
||||
/** 预览角色ID **/
|
||||
private List<Long> previewRoleIds;
|
||||
|
||||
/** 资源ID **/
|
||||
private Set<Long> featureIds;
|
||||
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package cn.axzo.tyr.server.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 角色权限关联
|
||||
*
|
||||
* @version V1.0
|
||||
* @author: ZhanSiHu
|
||||
* @date: 2024/4/8 14:50
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RoleFeatureRelation {
|
||||
|
||||
private Long roleId;
|
||||
|
||||
private Long featureId;
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package cn.axzo.tyr.server.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色和权限
|
||||
*
|
||||
* @version V1.0
|
||||
* @author: ZhanSiHu
|
||||
* @date: 2024/4/8 14:16
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RoleWithFeature {
|
||||
|
||||
private Long roleId;
|
||||
|
||||
private String roleName;
|
||||
|
||||
private String roleType;
|
||||
|
||||
private Integer productUnitType;
|
||||
|
||||
private List<Long> featureIds;
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package cn.axzo.tyr.server.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 用户标识对象
|
||||
*
|
||||
* @version V1.0
|
||||
* @author: ZhanSiHu
|
||||
* @date: 2024/4/8 10:59
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class UserIdentity {
|
||||
|
||||
private Long personId;
|
||||
private Long identityId;
|
||||
private Integer identityType;
|
||||
}
|
||||
@ -5,6 +5,7 @@ import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
|
||||
import cn.axzo.tyr.client.common.enums.RoleTypeEnum;
|
||||
import cn.axzo.tyr.client.model.enums.IdentityType;
|
||||
import cn.axzo.tyr.client.model.req.RoleWithUserQueryReq;
|
||||
import cn.axzo.tyr.server.model.RoleFeatureRelation;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasRole;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasRoleWithUser;
|
||||
import cn.axzo.tyr.server.repository.mapper.SaasRoleMapper;
|
||||
@ -115,5 +116,9 @@ public class SaasRoleDao extends ServiceImpl<SaasRoleMapper, SaasRole> {
|
||||
.eq(SaasRole::getRoleType, RoleTypeEnum.INIT.getValue())
|
||||
.list();
|
||||
}
|
||||
|
||||
public List<RoleFeatureRelation> listFeatureByIds(Set<Long> roleIds, Set<Long> featureIds) {
|
||||
return this.baseMapper.listFeatureByIds(roleIds, featureIds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package cn.axzo.tyr.server.repository.mapper;
|
||||
|
||||
import cn.axzo.tyr.client.model.enums.IdentityType;
|
||||
import cn.axzo.tyr.server.model.RoleFeatureRelation;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasRole;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasRoleWithUser;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
@ -27,5 +28,6 @@ public interface SaasRoleMapper extends BaseMapper<SaasRole> {
|
||||
|
||||
List<SaasRole> listRoleByFeatures(@Param("featureIds") Set<Long> featureIds);
|
||||
|
||||
List<RoleFeatureRelation> listFeatureByIds(@Param("roleIds") Set<Long> roleIds, @Param("featureIds") Set<Long> featureIds);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
package cn.axzo.tyr.server.service;
|
||||
|
||||
import cn.axzo.tyr.client.model.req.ResourceSyncReq;
|
||||
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 功能资源同步服务
|
||||
*
|
||||
* @version V1.0
|
||||
* @author: ZhanSiHu
|
||||
* @date: 2024/4/8 10:09
|
||||
*/
|
||||
public interface FeatureResourceSyncService {
|
||||
|
||||
List<FeatureResourceTreeNode> getSyncTreeById(Long id);
|
||||
|
||||
void syncFromBase(ResourceSyncReq req);
|
||||
}
|
||||
@ -12,6 +12,7 @@ import cn.axzo.tyr.client.model.vo.SaasRoleCategoryVO;
|
||||
import cn.axzo.tyr.client.model.vo.SaasRoleGroupCodeVO;
|
||||
import cn.axzo.tyr.client.model.vo.SaasRoleVO;
|
||||
import cn.axzo.tyr.client.model.vo.SaveOrUpdateRoleVO;
|
||||
import cn.axzo.tyr.server.model.RoleWithFeature;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasRole;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasRoleWithUser;
|
||||
import cn.axzo.tyr.server.service.impl.TyrSaasAuthServiceImpl;
|
||||
@ -101,4 +102,6 @@ public interface RoleService {
|
||||
|
||||
/** 查询超管和管理员角色 **/
|
||||
List<SaasRole> listAdmins(Long workspaceId, Long ouId);
|
||||
|
||||
List<RoleWithFeature> listWithFeatures(Set<Long> roleIds, Set<Long> featureIds);
|
||||
}
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
package cn.axzo.tyr.server.service;
|
||||
|
||||
import cn.axzo.tyr.client.model.req.ResourceSyncReq;
|
||||
import cn.axzo.tyr.client.model.res.FeatureResourceDTO;
|
||||
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -15,7 +13,6 @@ import java.util.List;
|
||||
*/
|
||||
public interface SaasFeatureResourceService {
|
||||
|
||||
List<FeatureResourceTreeNode> getSyncTreeById(Long id);
|
||||
|
||||
void syncFromBase(ResourceSyncReq req);
|
||||
/** 根据ID查询导航菜单页面信息 - 限制查询字段 **/
|
||||
List<SaasFeatureResource> listNavByIds(List<Long> featureIds);
|
||||
}
|
||||
|
||||
@ -0,0 +1,151 @@
|
||||
package cn.axzo.tyr.server.service.impl;
|
||||
|
||||
import cn.axzo.basics.common.BeanMapper;
|
||||
import cn.axzo.basics.common.util.TreeUtil;
|
||||
import cn.axzo.tyr.client.common.enums.FeatureResourceType;
|
||||
import cn.axzo.tyr.client.model.req.ResourceSyncReq;
|
||||
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
|
||||
import cn.axzo.tyr.server.inner.feign.BaseFeatureResourceApi;
|
||||
import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
|
||||
import cn.axzo.tyr.server.service.FeatureResourceSyncService;
|
||||
import cn.axzo.tyr.server.util.RpcInternalUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 功能资源同步服务实现
|
||||
*
|
||||
* @version V1.0
|
||||
* @author: ZhanSiHu
|
||||
* @date: 2024/4/8 10:09
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncService {
|
||||
|
||||
private final SaasFeatureResourceDao featureResourceDao;
|
||||
|
||||
private final BaseFeatureResourceApi baseFeatureResourceApi;
|
||||
|
||||
@Override
|
||||
public List<FeatureResourceTreeNode> getSyncTreeById(Long id) {
|
||||
//选中同步的数据
|
||||
SaasFeatureResource resource = featureResourceDao.lambdaQuery()
|
||||
.eq(SaasFeatureResource::getId, id)
|
||||
.one();
|
||||
if (resource == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
//找到所有上级 - 包含自己?
|
||||
List<SaasFeatureResource> resourceList = featureResourceDao.lambdaQuery()
|
||||
.in(SaasFeatureResource::getId, resource.splitPath())
|
||||
.list();
|
||||
//resourceList.add(resource);
|
||||
//如果是页面或应用入口-同时返回所有页面组件
|
||||
if (FeatureResourceType.applyPage(resource.getFeatureType())) {
|
||||
List<SaasFeatureResource> componentList = featureResourceDao.lambdaQuery()
|
||||
.eq(SaasFeatureResource::getFeatureType, FeatureResourceType.COMPONENT.getCode())
|
||||
.apply("FIND_IN_SET(" + id + ", path)")
|
||||
.list();
|
||||
resourceList.addAll(componentList);
|
||||
}
|
||||
List<FeatureResourceTreeNode> dtoList = BeanMapper.copyList(resourceList, FeatureResourceTreeNode.class);
|
||||
return TreeUtil.buildTree(dtoList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncFromBase(ResourceSyncReq req) {
|
||||
final Map<Long, String> codeCache = new ConcurrentHashMap<>();
|
||||
for (Long id : req.getIds()) {
|
||||
//TODO:@Zhan 并发处理;同一个parent下同批查询
|
||||
//获取基准环境配置数据:同步某个ID的数据 需要同步处理它所有上级及下级组件
|
||||
List<FeatureResourceTreeNode> syncList = RpcInternalUtil.rpcProcessor(() -> baseFeatureResourceApi.getSyncTreeById(id),
|
||||
"get base sync tree by id", id).getData();
|
||||
doSyncFromBase(syncList, codeCache, req.getOperatorId());
|
||||
}
|
||||
}
|
||||
|
||||
private void doSyncFromBase(List<FeatureResourceTreeNode> syncList, Map<Long, String> codeCache, Long operatorId) {
|
||||
|
||||
for (FeatureResourceTreeNode treeNode : syncList) {
|
||||
if (codeCache.containsKey(treeNode.getId())) {
|
||||
//已处理过
|
||||
log.info("already sync resource:{}", treeNode.getId());
|
||||
//递归子节点
|
||||
if (CollectionUtil.isNotEmpty(treeNode.getChildren())) {
|
||||
doSyncFromBase(treeNode.getChildren(), codeCache, operatorId);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//缓存code
|
||||
codeCache.put(treeNode.getId(), treeNode.getFeatureCode());
|
||||
|
||||
SaasFeatureResource baseResource = BeanMapper.copyBean(treeNode, SaasFeatureResource.class);
|
||||
//修正数据
|
||||
String parentCode = codeCache.get(baseResource.getParentId());
|
||||
fixData(baseResource, parentCode);
|
||||
|
||||
SaasFeatureResource resource = featureResourceDao.getByCode(treeNode.getFeatureCode());
|
||||
if (resource == null) {
|
||||
//新增
|
||||
baseResource.setCreateBy(operatorId);
|
||||
baseResource.setUpdateBy(operatorId);
|
||||
newResource(baseResource);
|
||||
} else {
|
||||
//更新
|
||||
baseResource.setId(resource.getId());
|
||||
baseResource.setPath(baseResource.getPath() + "," + resource.getId());
|
||||
baseResource.setUpdateBy(operatorId);
|
||||
featureResourceDao.updateById(baseResource);
|
||||
|
||||
if (!StrUtil.equals(baseResource.getPath(), resource.getPath())) {
|
||||
//层级变化
|
||||
log.info("replace path from old:{} to new:{}", resource.getPath(), baseResource.getPath());
|
||||
featureResourceDao.replacePath(resource.getPath(), baseResource.getPath());
|
||||
}
|
||||
}
|
||||
//递归子节点
|
||||
if (CollectionUtil.isNotEmpty(treeNode.getChildren())) {
|
||||
doSyncFromBase(treeNode.getChildren(), codeCache, operatorId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** 修正当前环境的数据 parentId path **/
|
||||
private void fixData(SaasFeatureResource resource, String parentCode) {
|
||||
if (StrUtil.isBlank(parentCode)) {
|
||||
resource.setParentId(0L);
|
||||
resource.setPath("0");
|
||||
} else {
|
||||
//找当前环境的parent
|
||||
SaasFeatureResource parent = featureResourceDao.getByCode(parentCode);
|
||||
if (parent == null) {
|
||||
resource.setParentId(0L);
|
||||
resource.setPath("0");
|
||||
} else {
|
||||
resource.setParentId(parent.getId());
|
||||
resource.setPath(parent.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void newResource(SaasFeatureResource resource) {
|
||||
|
||||
featureResourceDao.save(resource);
|
||||
//path追加自身ID
|
||||
resource.setPath(resource.getPath() + "," + resource.getId());
|
||||
featureResourceDao.updateById(resource);
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,35 @@
|
||||
package cn.axzo.tyr.server.service.impl;
|
||||
|
||||
import cn.axzo.basics.common.BeanMapper;
|
||||
import cn.axzo.basics.common.util.TreeUtil;
|
||||
import cn.axzo.tyr.client.common.enums.FeatureResourceType;
|
||||
import cn.axzo.tyr.client.model.enums.IdentityType;
|
||||
import cn.axzo.tyr.server.model.PermissionDO;
|
||||
import cn.axzo.tyr.server.model.PermissionQueryContext;
|
||||
import cn.axzo.tyr.server.model.RoleWithFeature;
|
||||
import cn.axzo.tyr.server.model.UserIdentity;
|
||||
import cn.axzo.tyr.client.model.base.WorkspaceOUPair;
|
||||
import cn.axzo.tyr.client.model.req.IdentityAuthReq;
|
||||
import cn.axzo.tyr.client.model.req.NavTreeReq;
|
||||
import cn.axzo.tyr.client.model.req.PermissionQueryReq;
|
||||
import cn.axzo.tyr.client.model.res.NavTreeResp;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation;
|
||||
import cn.axzo.tyr.server.service.PermissionQueryService;
|
||||
import cn.axzo.tyr.server.service.RoleService;
|
||||
import cn.axzo.tyr.server.service.SaasFeatureResourceService;
|
||||
import cn.axzo.tyr.server.util.KeyUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 权限查询服务实现
|
||||
@ -22,11 +43,94 @@ import java.util.List;
|
||||
@RequiredArgsConstructor
|
||||
public class PermissionQueryServiceImpl implements PermissionQueryService {
|
||||
|
||||
|
||||
private final SaasFeatureResourceService featureResourceService;
|
||||
private final RoleUserService roleUserService;
|
||||
private final RoleService roleService;
|
||||
|
||||
@Override
|
||||
public List<NavTreeResp> getNavTree(NavTreeReq req) {
|
||||
//TODO:@Zhan
|
||||
//构造参数
|
||||
PermissionQueryContext context = BeanMapper.copyBean(req, PermissionQueryContext.class);
|
||||
//限制只查菜单页面
|
||||
context.setFeatureTypes(FeatureResourceType.navTypes());
|
||||
//查询权限
|
||||
List<PermissionDO> permissions = queryUserPermission(context);
|
||||
if (CollectionUtil.isEmpty(permissions)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<Long> featureIds = permissions.stream().map(PermissionDO::getFeatureIds).flatMap(List::stream).collect(Collectors.toList());
|
||||
//反查资源信息
|
||||
List<SaasFeatureResource> resourceList = featureResourceService.listNavByIds(featureIds);
|
||||
//组装导航树
|
||||
return TreeUtil.buildTree(BeanMapper.copyList(resourceList, NavTreeResp.class));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private List<PermissionDO> queryUserPermission(PermissionQueryContext context) {
|
||||
//查询用户具有的角色
|
||||
List<SaasRoleUserRelation> userRoleRelations = listRoleUserRelations(context);
|
||||
if (CollectionUtil.isEmpty(userRoleRelations)) {
|
||||
log.warn("no user role relation found");
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Set<Long> realWorkspaceId = userRoleRelations.stream().map(SaasRoleUserRelation::getWorkspaceId).collect(Collectors.toSet());
|
||||
//TODO: 查询产品分配的权限
|
||||
Set<Long> roleIds = userRoleRelations.stream().map(SaasRoleUserRelation::getRoleId).collect(Collectors.toSet());
|
||||
//查询角色权限
|
||||
List<RoleWithFeature> roles = roleService.listWithFeatures(roleIds, context.getFeatureIds());
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private List<SaasRoleUserRelation> listRoleUserRelations(PermissionQueryContext context) {
|
||||
if (CollectionUtil.isNotEmpty(context.getPreviewRoleIds())) {
|
||||
//指定了角色 则不需要去查用户角色关系
|
||||
log.info("mock specify roles relation");
|
||||
return mockRoleUserRelation(context);
|
||||
}
|
||||
//查询人员角色关系
|
||||
Set<Long> workspaceIds = new HashSet<>();
|
||||
Set<Long> ouIds = new HashSet<>();
|
||||
Set<String> owKeys = new HashSet<>();
|
||||
List<WorkspaceOUPair> workspaceOUPairs = context.getWorkspaceOUPairs();
|
||||
workspaceOUPairs.forEach(ow -> {
|
||||
workspaceIds.add(ow.getWorkspaceId());
|
||||
ouIds.add(ow.getOuId());
|
||||
owKeys.add(KeyUtil.buildKeyBySeparator(ow.getWorkspaceId(), ow.getOuId()));
|
||||
});
|
||||
UserIdentity userIdentity = context.getUserIdentity();
|
||||
List<SaasRoleUserRelation> relations = roleUserService.queryByWorkspaceIdOrOu(userIdentity.getPersonId(),
|
||||
userIdentity.getIdentityId(), IdentityType.getIdentityType(userIdentity.getIdentityType()), workspaceIds, ouIds);
|
||||
if (CollectionUtil.isEmpty(relations)) {
|
||||
log.warn("no user role relations found");
|
||||
return relations;
|
||||
}
|
||||
//工作台和单位需成对查询, 对结果二次过滤
|
||||
return relations.stream()
|
||||
.filter(roleUserService -> owKeys.contains(
|
||||
KeyUtil.buildKeyBySeparator(roleUserService.getWorkspaceId(), roleUserService.getOuId())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<SaasRoleUserRelation> mockRoleUserRelation(PermissionQueryContext context) {
|
||||
final List<SaasRoleUserRelation> relations = new ArrayList<>();
|
||||
List<WorkspaceOUPair> workspaceOUPairs = context.getWorkspaceOUPairs();
|
||||
// mock 看做已有指定的角色
|
||||
for (WorkspaceOUPair ow : workspaceOUPairs) {
|
||||
List<SaasRoleUserRelation> mockRelations = context.getPreviewRoleIds().stream().map(id -> {
|
||||
SaasRoleUserRelation relation = new SaasRoleUserRelation();
|
||||
relation.setRoleId(id);
|
||||
relation.setOuId(ow.getOuId());
|
||||
relation.setWorkspaceId(ow.getWorkspaceId());
|
||||
relation.setIdentityId(context.getUserIdentity().getIdentityId());
|
||||
relation.setIdentityType(context.getUserIdentity().getIdentityType());
|
||||
// 使用角色ID替代,不需要在查询一次
|
||||
relation.setId(id);
|
||||
return relation;
|
||||
}).collect(Collectors.toList());
|
||||
relations.addAll(mockRelations);
|
||||
}
|
||||
return relations;
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,8 @@ import cn.axzo.tyr.client.model.vo.SaasRoleGroupCodeVO;
|
||||
import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO;
|
||||
import cn.axzo.tyr.client.model.vo.SaasRoleVO;
|
||||
import cn.axzo.tyr.client.model.vo.SaveOrUpdateRoleVO;
|
||||
import cn.axzo.tyr.server.model.RoleFeatureRelation;
|
||||
import cn.axzo.tyr.server.model.RoleWithFeature;
|
||||
import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
|
||||
import cn.axzo.tyr.server.repository.dao.SaasPermissionGroupDao;
|
||||
import cn.axzo.tyr.server.repository.dao.SaasPgroupRoleRelationDao;
|
||||
@ -975,4 +977,30 @@ public class RoleServiceImpl implements RoleService {
|
||||
.or().eq(SaasRole::getRoleType, RoleTypeEnum.ADMIN.getValue());})
|
||||
.list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RoleWithFeature> listWithFeatures(Set<Long> roleIds, Set<Long> featureIds) {
|
||||
List<RoleWithFeature> result = new ArrayList<>();
|
||||
|
||||
List<SaasRole> roles = saasRoleDao.listByIds(roleIds);
|
||||
if (CollectionUtil.isEmpty(roles)) {
|
||||
log.warn("no roles found for ids:{}", roles);
|
||||
return result;
|
||||
}
|
||||
|
||||
List<RoleFeatureRelation> relations = saasRoleDao.listFeatureByIds(roleIds, featureIds);
|
||||
Map<Long, List<Long>> mapping = relations.stream()
|
||||
.collect(Collectors.groupingBy(RoleFeatureRelation::getRoleId,
|
||||
Collectors.mapping(RoleFeatureRelation::getFeatureId, Collectors.toList())));
|
||||
for (SaasRole role : roles) {
|
||||
result.add(RoleWithFeature.builder()
|
||||
.roleId(role.getId())
|
||||
.roleName(role.getName())
|
||||
.roleType(role.getRoleType())
|
||||
.productUnitType(role.getProductUnitType())
|
||||
.featureIds(mapping.getOrDefault(role.getId(), Collections.emptyList()))
|
||||
.build());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,29 +1,13 @@
|
||||
package cn.axzo.tyr.server.service.impl;
|
||||
|
||||
import cn.axzo.basics.common.BeanMapper;
|
||||
import cn.axzo.basics.common.util.TreeUtil;
|
||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.tyr.client.common.enums.FeatureResourceType;
|
||||
import cn.axzo.tyr.client.model.req.ResourceSyncReq;
|
||||
import cn.axzo.tyr.client.model.res.FeatureResourceDTO;
|
||||
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
|
||||
import cn.axzo.tyr.server.inner.feign.BaseFeatureResourceApi;
|
||||
import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
|
||||
import cn.axzo.tyr.server.service.SaasFeatureResourceService;
|
||||
import cn.axzo.tyr.server.util.RpcInternalUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 功能资源服务实现
|
||||
@ -39,117 +23,15 @@ public class SaasFeatureResourceServiceImpl implements SaasFeatureResourceServic
|
||||
|
||||
private final SaasFeatureResourceDao featureResourceDao;
|
||||
|
||||
private final BaseFeatureResourceApi baseFeatureResourceApi;
|
||||
|
||||
@Override
|
||||
public List<FeatureResourceTreeNode> getSyncTreeById(Long id) {
|
||||
//选中同步的数据
|
||||
SaasFeatureResource resource = featureResourceDao.lambdaQuery()
|
||||
.eq(SaasFeatureResource::getId, id)
|
||||
.one();
|
||||
if (resource == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
//找到所有上级 - 包含自己?
|
||||
List<SaasFeatureResource> resourceList = featureResourceDao.lambdaQuery()
|
||||
.in(SaasFeatureResource::getId, resource.splitPath())
|
||||
public List<SaasFeatureResource> listNavByIds(List<Long> featureIds) {
|
||||
//按需扩展要查询的字段
|
||||
return featureResourceDao.lambdaQuery()
|
||||
.select(SaasFeatureResource::getId,
|
||||
SaasFeatureResource::getFeatureCode,
|
||||
SaasFeatureResource::getFeatureName,
|
||||
SaasFeatureResource::getFeatureType)
|
||||
.in(SaasFeatureResource::getId, featureIds)
|
||||
.list();
|
||||
//resourceList.add(resource);
|
||||
//如果是页面或应用入口-同时返回所有页面组件
|
||||
if (FeatureResourceType.applyPage(resource.getFeatureType())) {
|
||||
List<SaasFeatureResource> componentList = featureResourceDao.lambdaQuery()
|
||||
.eq(SaasFeatureResource::getFeatureType, FeatureResourceType.COMPONENT.getCode())
|
||||
.apply("FIND_IN_SET(" + id + ", path)")
|
||||
.list();
|
||||
resourceList.addAll(componentList);
|
||||
}
|
||||
List<FeatureResourceTreeNode> dtoList = BeanMapper.copyList(resourceList, FeatureResourceTreeNode.class);
|
||||
return TreeUtil.buildTree(dtoList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncFromBase(ResourceSyncReq req) {
|
||||
final Map<Long, String> codeCache = new ConcurrentHashMap<>();
|
||||
for (Long id : req.getIds()) {
|
||||
//TODO:@Zhan 并发处理;同一个parent下同批查询
|
||||
//获取基准环境配置数据:同步某个ID的数据 需要同步处理它所有上级及下级组件
|
||||
List<FeatureResourceTreeNode> syncList = RpcInternalUtil.rpcProcessor(() -> baseFeatureResourceApi.getSyncTreeById(id),
|
||||
"get base sync tree by id", id).getData();
|
||||
doSyncFromBase(syncList, codeCache, req.getOperatorId());
|
||||
}
|
||||
}
|
||||
|
||||
private void doSyncFromBase(List<FeatureResourceTreeNode> syncList, Map<Long, String> codeCache, Long operatorId) {
|
||||
|
||||
for (FeatureResourceTreeNode treeNode : syncList) {
|
||||
if (codeCache.containsKey(treeNode.getId())) {
|
||||
//已处理过
|
||||
log.info("already sync resource:{}", treeNode.getId());
|
||||
//递归子节点
|
||||
if (CollectionUtil.isNotEmpty(treeNode.getChildren())) {
|
||||
doSyncFromBase(treeNode.getChildren(), codeCache, operatorId);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//缓存code
|
||||
codeCache.put(treeNode.getId(), treeNode.getFeatureCode());
|
||||
|
||||
SaasFeatureResource baseResource = BeanMapper.copyBean(treeNode, SaasFeatureResource.class);
|
||||
//修正数据
|
||||
String parentCode = codeCache.get(baseResource.getParentId());
|
||||
fixData(baseResource, parentCode);
|
||||
|
||||
SaasFeatureResource resource = featureResourceDao.getByCode(treeNode.getFeatureCode());
|
||||
if (resource == null) {
|
||||
//新增
|
||||
baseResource.setCreateBy(operatorId);
|
||||
baseResource.setUpdateBy(operatorId);
|
||||
newResource(baseResource);
|
||||
} else {
|
||||
//更新
|
||||
baseResource.setId(resource.getId());
|
||||
baseResource.setPath(baseResource.getPath() + "," + resource.getId());
|
||||
baseResource.setUpdateBy(operatorId);
|
||||
featureResourceDao.updateById(baseResource);
|
||||
|
||||
if (!StrUtil.equals(baseResource.getPath(), resource.getPath())) {
|
||||
//层级变化
|
||||
log.info("replace path from old:{} to new:{}", resource.getPath(), baseResource.getPath());
|
||||
featureResourceDao.replacePath(resource.getPath(), baseResource.getPath());
|
||||
}
|
||||
}
|
||||
//递归子节点
|
||||
if (CollectionUtil.isNotEmpty(treeNode.getChildren())) {
|
||||
doSyncFromBase(treeNode.getChildren(), codeCache, operatorId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** 修正当前环境的数据 parentId path **/
|
||||
private void fixData(SaasFeatureResource resource, String parentCode) {
|
||||
if (StrUtil.isBlank(parentCode)) {
|
||||
resource.setParentId(0L);
|
||||
resource.setPath("0");
|
||||
} else {
|
||||
//找当前环境的parent
|
||||
SaasFeatureResource parent = featureResourceDao.getByCode(parentCode);
|
||||
if (parent == null) {
|
||||
resource.setParentId(0L);
|
||||
resource.setPath("0");
|
||||
} else {
|
||||
resource.setParentId(parent.getId());
|
||||
resource.setPath(parent.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void newResource(SaasFeatureResource resource) {
|
||||
|
||||
featureResourceDao.save(resource);
|
||||
//path追加自身ID
|
||||
resource.setPath(resource.getPath() + "," + resource.getId());
|
||||
featureResourceDao.updateById(resource);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,4 +126,22 @@
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<select id="listFeatureByIds" resultType="cn.axzo.tyr.server.model.RoleFeatureRelation">
|
||||
SELECT rg.role_id AS roleId, pg.feature_id AS featureId
|
||||
FROM saas_pgroup_role_relation rg, saas_pgroup_permission_relation pg
|
||||
WHERE rg.group_id = pg.group_id AND rg.is_delete = 0 AND pg.is_delete = 0
|
||||
<if test="roleIds != null and roleIds.size > 0">
|
||||
AND rg.role_id IN
|
||||
<foreach collection="roleIds" index="index" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="featureIds != null and featureIds.size > 0">
|
||||
AND pg.feature_id IN
|
||||
<foreach collection="featureIds" index="index" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</if>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue
Block a user