feat:(REQ-2720) 权限查询做降级处理

This commit is contained in:
lilong 2024-07-30 18:45:02 +08:00
parent 4ad6bd7306
commit 7aa3615cc3
3 changed files with 762 additions and 25 deletions

View File

@ -65,6 +65,23 @@ public class IdentityAuthReq {
@Builder.Default
private boolean useCache = true;
public IdentityAuthRes toEmpty() {
IdentityAuthRes result = new IdentityAuthRes();
result.setIdentity(this.getIdentityId());
result.setIdentityType(this.getIdentityType());
result.setPersonId(this.getPersonId());
List<IdentityAuthRes.WorkspacePermission> permissions = this.getWorkspaceOusPairs().stream()
.map(workspaceOuPair -> IdentityAuthRes.WorkspacePermission.builder()
.workspaceId(workspaceOuPair.getWorkspaceId())
.ouId(workspaceOuPair.getOuId())
.build())
.collect(Collectors.toList());
result.setPermissions(permissions);
return result;
}
public void distinctOUWorkspacePair() {
if (CollectionUtil.isEmpty(this.workspaceOusPairs)) {
return;

View File

@ -19,6 +19,7 @@ import cn.axzo.tyr.client.model.base.FeatureResourceExtraDO;
import cn.axzo.tyr.client.model.base.WorkspaceOUPair;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.product.ProductFeatureRelationVO;
import cn.axzo.tyr.client.model.req.FeatureIdPair;
import cn.axzo.tyr.client.model.req.IdentityAuthReq;
import cn.axzo.tyr.client.model.req.NavTreeReq;
import cn.axzo.tyr.client.model.req.PagePermissionReq;
@ -32,6 +33,7 @@ import cn.axzo.tyr.client.model.res.IdentityAuthRes;
import cn.axzo.tyr.client.model.res.NavTreeResp;
import cn.axzo.tyr.client.model.res.ProductFeatureResourceResp;
import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp;
import cn.axzo.tyr.client.model.res.SaasPermissionRelationRes;
import cn.axzo.tyr.client.model.res.TreePermissionResp;
import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserV2DTO;
import cn.axzo.tyr.client.model.roleuser.req.ListRoleUserRelationParam;
@ -45,6 +47,7 @@ import cn.axzo.tyr.server.model.WorkspaceFeatureRelation;
import cn.axzo.tyr.server.repository.dao.ProductModuleDao;
import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao;
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
import cn.axzo.tyr.server.repository.entity.SaasProductModuleFeatureRelation;
import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation;
import cn.axzo.tyr.server.service.PermissionQueryService;
import cn.axzo.tyr.server.service.ProductFeatureRelationService;
@ -89,7 +92,7 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import static cn.axzo.tyr.server.repository.entity.SaasFeatureResource.DISPLAY_STATUS;
import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.NEW_FEATURE;
/**
* 权限查询服务实现
*
@ -117,6 +120,7 @@ public class PermissionQueryServiceImpl implements PermissionQueryService {
private final RoleSaasFeatureResourceCacheService roleSaasFeatureResourceCacheService;
private final ProductSaasFeatureResourceCacheService productSaasFeatureResourceCacheService;
@Qualifier("authExecutor")
@Autowired
private Executor executor;
@ -320,11 +324,129 @@ public class PermissionQueryServiceImpl implements PermissionQueryService {
}
private List<Long> resolveFeatureIds(TreePermissionReq treePermissionReq) {
if (StringUtils.isBlank(treePermissionReq.getUniCode())) {
return Collections.emptyList();
}
PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder()
.uniCodes(Sets.newHashSet(treePermissionReq.getUniCode()))
.build();
return featureResourceService.list(pageSaasFeatureResourceReq).stream()
.map(SaasFeatureResourceResp::getId)
.collect(Collectors.toList());
}
private List<SaasRoleUserV2DTO> listUserPermission(TreePermissionReq treePermissionReq, List<Long> featureIds) {
List<ListRoleUserRelationParam.WorkspaceOuPair> workspaceOuPairs = treePermissionReq.getWorkspaceOUPairs().stream()
.map(e -> ListRoleUserRelationParam.WorkspaceOuPair.builder()
.workspaceId(e.getWorkspaceId())
.ouId(e.getOuId())
.build())
.collect(Collectors.toList());
ListRoleUserRelationParam listRoleUserRelationParam = ListRoleUserRelationParam.builder()
.personId(treePermissionReq.getPersonId())
.workspaceOuPairs(Lists.newArrayList(workspaceOuPairs))
.needRole(true)
.needPermissionRelation(true)
.featureResourceTypes(treePermissionReq.getFeatureResourceTypes())
.type(NEW_FEATURE)
.terminal(treePermissionReq.getTerminal())
.featureIds(featureIds)
.build();
return saasRoleUserRelationService.listV2(listRoleUserRelationParam).stream()
.filter(e -> e.getSaasRole() != null)
.collect(Collectors.toList());
}
private Set<Long> listUserPermissionFeatureIdsFromDB(TreePermissionReq treePermissionReq) {
List<Long> featureIds = resolveFeatureIds(treePermissionReq);
if (StringUtils.isNotBlank(treePermissionReq.getUniCode()) && CollectionUtils.isEmpty(featureIds)) {
return Collections.emptySet();
}
List<SaasRoleUserV2DTO> saasRoleUserV2DTOS = listUserPermission(treePermissionReq, featureIds);
// 用户可能没有角色
if (CollectionUtils.isEmpty(saasRoleUserV2DTOS)) {
return Collections.emptySet();
}
List<WorkspaceProductService.WorkspaceProduct> workspaceProducts = listWorkspaceProducts(treePermissionReq, featureIds);
//免授权
List<Long> authFreeFeatureIds = listNotAuthFeatures(treePermissionReq);
//取交集确定权限
return mixFeatureIds(saasRoleUserV2DTOS, workspaceProducts, authFreeFeatureIds);
}
private Set<Long> mixFeatureIds(List<SaasRoleUserV2DTO> saasRoleUsers,
List<WorkspaceProductService.WorkspaceProduct> workspaceProducts,
List<Long> authFreeFeatureIds) {
Map<Long, WorkspaceProductService.WorkspaceProduct> workspaceProductMap = workspaceProducts.stream()
.collect(Collectors.toMap(WorkspaceProductService.WorkspaceProduct::getWorkspaceId, Function.identity()));
return saasRoleUsers.stream()
.filter(roleUser -> {
WorkspaceProductService.WorkspaceProduct workspaceProduct = workspaceProductMap.get(roleUser.getSaasRoleUser().getWorkspaceId());
if (workspaceProduct == null || CollectionUtils.isEmpty(workspaceProduct.getSaasProductModuleFeatureRelations())) {
log.warn("no workspace product feature found for id:{}", roleUser.getSaasRoleUser().getWorkspaceId());
return false;
}
return true;
})
.map(roleUser -> {
WorkspaceProductService.WorkspaceProduct workspaceProduct = workspaceProductMap.get(roleUser.getSaasRoleUser().getWorkspaceId());
SaasRoleUserV2DTO.SaasRole saasRole = roleUser.getSaasRole();
if (RoleTypeEnum.isAdmin(saasRole.getRoleType())) {
return resolveAdminRole(workspaceProduct, saasRole);
}
return resolveNormalRole(workspaceProduct, saasRole, authFreeFeatureIds);
})
.flatMap(Collection::stream)
.collect(Collectors.toSet());
}
private List<WorkspaceProductService.WorkspaceProduct> listWorkspaceProducts(TreePermissionReq treePermissionReq,
List<Long> featureIds) {
//查询租户产品权限点
Set<Long> workspaceIds = treePermissionReq.getWorkspaceOUPairs().stream()
.map(WorkspaceOUPair::getWorkspaceId)
.collect(Collectors.toSet());
WorkspaceProductService.WorkspaceProductParam workspaceProductParam = WorkspaceProductService.WorkspaceProductParam.builder()
.terminal(treePermissionReq.getTerminal())
.workspaceIds(workspaceIds)
.featureResourceTypes(treePermissionReq.getFeatureResourceTypes())
.type(NEW_FEATURE)
.build();
if (CollectionUtils.isNotEmpty(featureIds)) {
workspaceProductParam.setFeatureIdPairs(Lists.newArrayList(FeatureIdPair.builder()
.featureIds(Sets.newHashSet(featureIds))
.type(NEW_FEATURE)
.build()));
}
return workspaceProductService.listWorkspaceProduct(workspaceProductParam);
}
@Override
public List<TreePermissionResp> treePermission(TreePermissionReq req) {
Set<Long> allFeatureIds = Sets.newHashSet();
Set<Long> featureIds = listUserPermissionFeatureIds(req);
Set<Long> featureIds;
try {
featureIds = listUserPermissionFeatureIds(req);
} catch (Exception ex) {
log.error("查询权限异常,执行降级处理");
featureIds = listUserPermissionFeatureIdsFromDB(req);
}
Set<Long> defaultFeatureIds = listNotAuthFeatureIds();
allFeatureIds.addAll(featureIds);
@ -829,4 +951,33 @@ public class PermissionQueryServiceImpl implements PermissionQueryService {
.filter(authFreeFeatureIds::contains)
.collect(Collectors.toSet());
}
private List<Long> resolveAdminRole(WorkspaceProductService.WorkspaceProduct workspaceProduct,
SaasRoleUserV2DTO.SaasRole saasRole) {
//超管和管理员 直接取和角色类型匹配的租户产品权限
return workspaceProduct.getSaasProductModuleFeatureRelations().stream()
.filter(f -> Objects.equals(f.getDictCode(), saasRole.getProductUnitType().toString())
|| !NumberUtil.isPositiveNumber(saasRole.getProductUnitType()))
.map(SaasProductModuleFeatureRelation::getFeatureId)
.collect(Collectors.toList());
}
private List<Long> resolveNormalRole(WorkspaceProductService.WorkspaceProduct workspaceProduct,
SaasRoleUserV2DTO.SaasRole saasRole,
List<Long> authFreeFeatureIds) {
//普通角色角色同类型的租户产品权限已分配 且角色上已分配 + 免授权
Set<Long> roleFeatureIds = Optional.ofNullable(saasRole.getPermissionRelations())
.map(e -> e.stream()
.map(SaasPermissionRelationRes::getFeatureId)
.collect(Collectors.toSet()))
.orElseGet(Collections::emptySet);
return workspaceProduct.getSaasProductModuleFeatureRelations().stream()
.filter(f -> Objects.equals(f.getDictCode(), saasRole.getProductUnitType().toString())
|| !NumberUtil.isPositiveNumber(saasRole.getProductUnitType()))
.map(SaasProductModuleFeatureRelation::getFeatureId)
.filter(id -> roleFeatureIds.contains(id) || authFreeFeatureIds.contains(id))
.collect(Collectors.toList());
}
}

View File

@ -7,10 +7,12 @@ import cn.axzo.pokonyan.util.TraceSupplier;
import cn.axzo.thrones.client.saas.ServicePkgClient;
import cn.axzo.thrones.client.saas.entity.serivicepgkproduct.ServicePkgProduct;
import cn.axzo.thrones.client.saas.entity.servicepkg.ServicePkgDetailRes;
import cn.axzo.tyr.client.common.enums.FeatureResourceAuthType;
import cn.axzo.tyr.client.common.enums.RoleTypeEnum;
import cn.axzo.tyr.client.common.enums.WorkspaceJoinType;
import cn.axzo.tyr.client.model.enums.DelegatedType;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.permission.PermissionPointListQueryRequest;
import cn.axzo.tyr.client.model.permission.PermissionPointTreeNode;
import cn.axzo.tyr.client.model.product.ProductFeatureRelationVO;
import cn.axzo.tyr.client.model.req.CheckIdentityPermissionReq;
@ -25,6 +27,7 @@ import cn.axzo.tyr.client.model.req.PageElementFeatureResourceRelationReq;
import cn.axzo.tyr.client.model.req.PagePgroupPermissionRelationReq;
import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq;
import cn.axzo.tyr.client.model.req.PermissionCheckReq;
import cn.axzo.tyr.client.model.req.QueryPermissionByIdsReq;
import cn.axzo.tyr.client.model.req.QuerySaasRoleReq;
import cn.axzo.tyr.client.model.req.WorkspacePermissionIdentityReq;
import cn.axzo.tyr.client.model.res.IdentityAuthRes;
@ -33,6 +36,7 @@ import cn.axzo.tyr.client.model.res.ListPermissionFromRoleGroupResp;
import cn.axzo.tyr.client.model.res.QueryIdentityByPermissionResp;
import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp;
import cn.axzo.tyr.client.model.res.SaasRoleRes;
import cn.axzo.tyr.client.model.res.SimplePermissionPointResp;
import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserV2DTO;
import cn.axzo.tyr.client.model.roleuser.req.ListRoleUserRelationParam;
import cn.axzo.tyr.client.model.vo.SaasPermissionGroupVO;
@ -76,6 +80,7 @@ import cn.azxo.framework.common.model.CommonResponse;
import cn.azxo.framework.common.utils.LogUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
@ -520,7 +525,15 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
@Override
public ListIdentityFromPermissionResp listIdentityFromPermission(ListIdentityFromPermissionReq req) {
try {
return listIdentityFromPermissionResp(req);
} catch (Exception ex) {
log.error("查询权限异常,执行降级处理");
return listIdentityFromPermissionFromDB(req);
}
}
private ListIdentityFromPermissionResp listIdentityFromPermissionResp(ListIdentityFromPermissionReq req) {
Set<String> newFeatureCodes = featureCodeUtil.resolveFeatureCode(Sets.newHashSet(req.getFeatureCode()));
ListPermissionUser listPermissionUser = ListPermissionUser.builder()
.featureCodes(newFeatureCodes)
@ -781,7 +794,12 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
}
private List<IdentityAuthRes.WorkspacePermission> findIdentityPermission(IdentityAuthReq req) {
return findIdentityAuthV2(req).getPermissions();
try {
return findIdentityAuthV2(req).getPermissions();
} catch (Exception ex) {
log.error("查询权限异常,执行降级处理");
return findIdentityAuth(req).getPermissions();
}
}
private List<IdentityAuthRes.WorkspacePermission> findIdentityPermissionFromCache(IdentityAuthReq req) {
@ -960,32 +978,37 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
@Override
public List<ListIdentityFromPermissionResp> listWorkspacePermissionIdentity(WorkspacePermissionIdentityReq req) {
Set<String> newFeatureCodes = featureCodeUtil.resolveFeatureCode(Sets.newHashSet(req.getFeatureCodes()));
try {
Set<String> newFeatureCodes = featureCodeUtil.resolveFeatureCode(Sets.newHashSet(req.getFeatureCodes()));
Set<String> featureCodes = Sets.newHashSet(req.getFeatureCodes());
featureCodes.addAll(newFeatureCodes);
Set<String> featureCodes = Sets.newHashSet(req.getFeatureCodes());
featureCodes.addAll(newFeatureCodes);
ListPermissionUser listPermissionUser = ListPermissionUser.builder()
.featureCodes(featureCodes)
.workspaceId(req.getWorkspaceId())
.build();
List<ListIdentityFromPermissionResp.UserVO> users = listPermissionUser(listPermissionUser);
if (CollectionUtil.isEmpty(users)) {
return Collections.emptyList();
}
//按ou分组返回
List<ListIdentityFromPermissionResp> result = new ArrayList<>();
Map<Long, List<ListIdentityFromPermissionResp.UserVO>> userMap = users.stream()
.collect(Collectors.groupingBy(ListIdentityFromPermissionResp.UserVO::getOuId));
for (Map.Entry<Long, List<ListIdentityFromPermissionResp.UserVO>> entry : userMap.entrySet()) {
result.add(ListIdentityFromPermissionResp.builder()
ListPermissionUser listPermissionUser = ListPermissionUser.builder()
.featureCodes(featureCodes)
.workspaceId(req.getWorkspaceId())
.ouId(entry.getKey())
.users(entry.getValue())
.build());
.build();
List<ListIdentityFromPermissionResp.UserVO> users = listPermissionUser(listPermissionUser);
if (CollectionUtil.isEmpty(users)) {
return Collections.emptyList();
}
//按ou分组返回
List<ListIdentityFromPermissionResp> result = new ArrayList<>();
Map<Long, List<ListIdentityFromPermissionResp.UserVO>> userMap = users.stream()
.collect(Collectors.groupingBy(ListIdentityFromPermissionResp.UserVO::getOuId));
for (Map.Entry<Long, List<ListIdentityFromPermissionResp.UserVO>> entry : userMap.entrySet()) {
result.add(ListIdentityFromPermissionResp.builder()
.workspaceId(req.getWorkspaceId())
.ouId(entry.getKey())
.users(entry.getValue())
.build());
}
return result;
} catch (Exception ex) {
log.error("查询权限异常,执行降级处理");
return listWorkspacePermissionIdentityFromDB(req);
}
return result;
}
private List<SaasRole> listFeatureRoles(Set<Long> featureIds, Integer type) {
@ -1685,4 +1708,550 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
.build();
return rolePermissionCacheService.list(listRolePermissionParam);
}
private IdentityAuthRes findIdentityAuth(IdentityAuthReq identityAuthReq) {
//用户角色关系
List<SaasRoleUserRelation> saasRoleUserRelations = listRoleUserRelations(identityAuthReq);
if (CollectionUtils.isEmpty(saasRoleUserRelations)) {
log.warn("no user role relations found");
return identityAuthReq.toEmpty();
}
Set<Long> realWorkspaceId = saasRoleUserRelations.stream().map(SaasRoleUserRelation::getWorkspaceId).collect(Collectors.toSet());
//工作台对应产品 key = workspaceId
CompletableFuture<List<WorkspaceProductService.WorkspaceProduct>> workspacePermissionPointFuture = CompletableFuture
.supplyAsync(TraceSupplier.create(() -> {
WorkspaceProductService.WorkspaceProductParam workspaceProductParam = WorkspaceProductService.WorkspaceProductParam.builder()
.workspaceIds(realWorkspaceId)
.build();
return workspaceProductService.listWorkspaceProduct(workspaceProductParam);
}), executor);
//查询工作台下授予的角色和权限
List<OUWRoleInfo> owRoles = listRolesWithPermission(saasRoleUserRelations, identityAuthReq);
Map<Long, WorkspaceProductService.WorkspaceProduct> workspaceProductPermissionMap = workspacePermissionPointFuture.join().stream()
.collect(Collectors.toMap(WorkspaceProductService.WorkspaceProduct::getWorkspaceId, Function.identity()));
List<CompletableFuture<IdentityAuthRes.WorkspacePermission>> futureList = new ArrayList<>();
for (OUWRoleInfo owRoleInfo : owRoles) {
// 工作台的产品权限点
WorkspaceProductService.WorkspaceProduct workspaceProduct = workspaceProductPermissionMap.get(owRoleInfo.getWorkspaceId());
//构建每个工作台的实际权限点
futureList.add(CompletableFuture.supplyAsync(TraceSupplier.create(() -> buildPermissions(owRoleInfo, workspaceProduct)), executor)
.exceptionally(t -> {
LogUtil.error("获取角色对应权限失败", t);
throw new ServiceException(t);
}));
}
//汇总结果
IdentityAuthRes result = new IdentityAuthRes();
result.setIdentity(identityAuthReq.getIdentityId());
result.setIdentityType(identityAuthReq.getIdentityType());
result.setPersonId(identityAuthReq.getPersonId());
for (CompletableFuture<IdentityAuthRes.WorkspacePermission> future : futureList) {
result.getPermissions().add(future.join());
}
return result;
}
private List<SaasRoleUserRelation> listRoleUserRelations(IdentityAuthReq identityAuthReq) {
if (CollectionUtil.isNotEmpty(identityAuthReq.getSpecifyRoleIds())) {
//指定了角色 则不需要去查用户角色关系
log.info("mock specify roles relation");
return mockRoleUserRelation(identityAuthReq);
}
//查询人员角色关系
Set<Long> workspaceIds = new HashSet<>();
Set<Long> ouIds = new HashSet<>();
Set<String> owKeys = new HashSet<>();
identityAuthReq.getWorkspaceOusPairs().forEach(ow -> {
workspaceIds.add(ow.getWorkspaceId());
ouIds.add(ow.getOuId());
owKeys.add(KeyUtil.buildKeyBySeparator(ow.getWorkspaceId(), ow.getOuId()));
});
List<SaasRoleUserRelation> relations = roleUserService.queryByWorkspaceIdOrOu(identityAuthReq.getPersonId(),
identityAuthReq.getIdentityId(), identityAuthReq.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(IdentityAuthReq identityAuthReq) {
final List<SaasRoleUserRelation> relations = new ArrayList<>();
// mock 看做已有指定的角色
for (IdentityAuthReq.WorkspaceOuPair ow : identityAuthReq.getWorkspaceOusPairs()) {
List<SaasRoleUserRelation> mockRelations = identityAuthReq.getSpecifyRoleIds().stream().map(id -> {
SaasRoleUserRelation relation = new SaasRoleUserRelation();
relation.setRoleId(id);
relation.setOuId(ow.getOuId());
relation.setWorkspaceId(ow.getWorkspaceId());
relation.setIdentityId(identityAuthReq.getIdentityId());
relation.setIdentityType(identityAuthReq.getIdentityType().getCode());
// 使用角色ID替代不需要在查询一次
relation.setId(id);
return relation;
}).collect(Collectors.toList());
relations.addAll(mockRelations);
}
return relations;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
static class FeatureWrapper {
private Long featureId;
/**
* 关联类型0saas_feature,1:saas_feature_resource
*/
private Integer type;
}
private List<OUWRoleInfo> listRolesWithPermission(List<SaasRoleUserRelation> roleUserRelations, IdentityAuthReq identityAuthReq) {
//拼装参数
Set<Long> roleIds = new HashSet<>();
//按ow分组角色ID: workspaceId-ouId --> roleIds
Map<String, Set<Long>> owRoleIdMap = new HashMap<>();
for (SaasRoleUserRelation relation : roleUserRelations) {
roleIds.add(relation.getRoleId());
String key = KeyUtil.buildKeyBySeparator(relation.getWorkspaceId(), relation.getOuId());
Set<Long> owRoleIds = owRoleIdMap.getOrDefault(key, new HashSet<>());
owRoleIds.add(relation.getRoleId());
owRoleIdMap.put(key, owRoleIds);
}
//获取角色和关联权限信息
RoleService.ListSaasRoleParam listSaasRoleParam = RoleService.ListSaasRoleParam.builder()
.roleIds(Lists.newArrayList(roleIds))
.needPermissionRelation(true)
.build();
Map<Long, SaasRoleRes> saasRoleRes = roleService.list(listSaasRoleParam).stream()
.collect(Collectors.toMap(SaasRoleRes::getId, Function.identity()));
//按ow组装拥有的角色
List<OUWRoleInfo> owRoleMap = new ArrayList<>();
for (IdentityAuthReq.WorkspaceOuPair ow : identityAuthReq.getWorkspaceOusPairs()) {
OUWRoleInfo owRoleInfo = OUWRoleInfo.builder()
.workspaceId(ow.getWorkspaceId())
.ouId(ow.getOuId())
.build();
String key = KeyUtil.buildKeyBySeparator(ow.getWorkspaceId(), ow.getOuId());
Set<Long> owRoleIds = owRoleIdMap.get(key);
if (CollectionUtil.isEmpty(owRoleIds)) {
log.info("no roles found for ow:{}", key);
owRoleInfo.setRoles(Collections.emptySet());
} else {
owRoleInfo.setRoles(owRoleIds.stream()
.map(saasRoleRes::get)
// 有saas_role_user_relation有记录但是对应的saas_role不存在的情况
.filter(Objects::nonNull)
.collect(Collectors.toSet()));
}
owRoleMap.add(owRoleInfo);
}
return owRoleMap;
}
private IdentityAuthRes.WorkspacePermission buildPermissions(OUWRoleInfo ouwRoleInfo, WorkspaceProductService.WorkspaceProduct workspaceProduct) {
IdentityAuthRes.WorkspacePermission resultPermission = IdentityAuthRes.WorkspacePermission.builder()
.workspaceId(ouwRoleInfo.getWorkspaceId())
.ouId(ouwRoleInfo.getOuId())
.build();
if (Objects.isNull(workspaceProduct) || CollectionUtil.isEmpty(workspaceProduct.getSaasProductModuleFeatureRelations())) {
log.warn("no product features found for workspace :{}", ouwRoleInfo.getWorkspaceId());
return resultPermission;
}
Set<SaasRoleRes> roles = ouwRoleInfo.getRoles();
if (CollectionUtil.isEmpty(roles)) {
log.warn("no roles for ou:{} workspace:{}", ouwRoleInfo.getOuId(), ouwRoleInfo.getWorkspaceId());
return resultPermission;
}
List<SaasProductModuleFeatureRelation> productFeatures = workspaceProduct.getSaasProductModuleFeatureRelations();
// 因为存在同时有saas_feature和saas_feature_resource的权限所以要返回type根据type解析code
//超管和管理员权限
Pair<Boolean, Set<FeatureWrapper>> adminPermissions = buildAdminPermission(ouwRoleInfo, productFeatures);
//标准角和自定义角色权限
Set<FeatureWrapper> normalPermissions = buildNormalPermission(ouwRoleInfo, productFeatures);
Set<FeatureWrapper> allPermissions = Sets.newHashSet();
allPermissions.addAll(adminPermissions.getValue());
allPermissions.addAll(normalPermissions);
//查询权限点及父级权限点
List<SimplePermissionPointResp> allOldPermissionPoint = listOldFeatures(allPermissions);
List<IdentityAuthRes.PermissionPoint> newPermissionPoints = listNewFeatures(allPermissions);
//组装返回值
//是否超管
resultPermission.setSuperAdmin(BooleanUtil.isTrue(adminPermissions.getKey()));
//权限数据
resultPermission.getPermissionPoint().addAll(allOldPermissionPoint.stream()
.map(permissionPointTreeNode -> IdentityAuthRes.PermissionPoint.builder()
.featureCode(permissionPointTreeNode.getCode())
.featureId(permissionPointTreeNode.getId())
.terminal(permissionPointTreeNode.getTerminal())
.build())
.collect(Collectors.toList()));
resultPermission.getPermissionPoint().addAll(newPermissionPoints);
return resultPermission;
}
private Pair<Boolean, Set<FeatureWrapper>> buildAdminPermission(OUWRoleInfo userRoleInfoMap, List<SaasProductModuleFeatureRelation> productFeatures) {
Boolean superAdmin = false;
//超管和管理员角色
List<SaasRoleRes> adminRoles = userRoleInfoMap.getRoles().stream()
.filter(r -> RoleTypeEnum.isAdmin(r.getRoleType()))
.collect(Collectors.toList());
if (CollectionUtil.isEmpty(adminRoles)) {
log.info("no admin roles");
return Pair.of(superAdmin, Collections.emptySet());
}
log.info("build admin permission for ou:{}, workspace:{}", userRoleInfoMap.getOuId(), userRoleInfoMap.getWorkspaceId());
//聚合超管和管理员的权限点 直接取角色标签和产品标签相匹配的权限点
Set<FeatureWrapper> permissions = Sets.newHashSet();
for (SaasRoleRes adminRole : adminRoles) {
//超管查询工作台对应产品获取权限点 权限点通过单位类型过滤)
if (RoleTypeEnum.SUPER_ADMIN.getValue().equals(adminRole.getRoleType())) {
superAdmin = true;
}
//角色标签类型匹配产品标签类型
Set<FeatureWrapper> permission = productFeatures.stream()
.filter(productFeatureRelationVO -> Objects.equals(productFeatureRelationVO.getDictCode(),
String.valueOf(adminRole.getProductUnitType())))
.map(e -> FeatureWrapper.builder()
.featureId(e.getFeatureId())
.type(e.getType())
.build())
.collect(Collectors.toSet());
if (CollectionUtil.isEmpty(permission)) {
log.warn("empty permission for admin role:{}", adminRole.getId());
continue;
}
log.info("add all permissions for role:{}", adminRole.getId());
permissions.addAll(permission);
}
return Pair.of(superAdmin, permissions);
}
private Set<FeatureWrapper> buildNormalPermission(OUWRoleInfo userRoleInfoMap, List<SaasProductModuleFeatureRelation> productFeatures) {
log.info("build permission for ou:{}, workspace:{}", userRoleInfoMap.getOuId(), userRoleInfoMap.getWorkspaceId());
Set<FeatureWrapper> allMatchedProductFeatures = new HashSet<>();
Set<FeatureWrapper> allAuthFeatures = new HashSet<>();
//聚合实际授权的权限角色权限和产品权限交集
for (SaasRoleRes role : userRoleInfoMap.getRoles()) {
//跳过超管和管理员
if (RoleTypeEnum.SUPER_ADMIN.getValue().equals(role.getRoleType())
|| RoleTypeEnum.ADMIN.getValue().equals(role.getRoleType())) {
continue;
}
log.info("build permission for role:{}", role.getId());
Set<FeatureWrapper> rolePermissions = Optional.ofNullable(role.getPermissionRelations())
.map(e -> e.stream()
.filter(Objects::nonNull)
.map(f -> FeatureWrapper.builder()
.featureId(f.getFeatureId())
.type(f.getType())
.build())
.collect(Collectors.toSet()))
.orElseGet(Sets::newHashSet);
//角色标签类型匹配产品标签类型
Set<FeatureWrapper> productPermissions = productFeatures.stream()
.filter(productFeatureRelationVO -> Objects.equals(productFeatureRelationVO.getDictCode(), String.valueOf(role.getProductUnitType())))
.map(e -> FeatureWrapper.builder()
.featureId(e.getFeatureId())
.type(e.getType())
.build())
.collect(Collectors.toSet());
allMatchedProductFeatures.addAll(productPermissions);
// 产品对应权限点 角色权限点 取交集
Collection<FeatureWrapper> resultHashAuthPointId = CollectionUtil.intersection(productPermissions, rolePermissions);
if (CollectionUtil.isNotEmpty(resultHashAuthPointId)) {
log.info("add auth permission for role:{}", role.getId());
allAuthFeatures.addAll(resultHashAuthPointId);
}
}
if (CollectionUtil.isEmpty(allMatchedProductFeatures)) {
log.info("no normal roles found");
return allAuthFeatures;
}
Set<FeatureWrapper> newFeatureNoAuth = listNoAuthFeatureResources(allMatchedProductFeatures);
Set<FeatureWrapper> oldFeatureNoAuth = listNoAuthFeatures(allMatchedProductFeatures);
allAuthFeatures.addAll(newFeatureNoAuth);
allAuthFeatures.addAll(oldFeatureNoAuth);
return allAuthFeatures;
}
private Set<FeatureWrapper> listNoAuthFeatures(Set<FeatureWrapper> featureWrappers) {
List<Long> featureIds = featureWrappers.stream()
.filter(e -> Objects.equals(e.getType(), OLD_FEATURE))
.map(FeatureWrapper::getFeatureId)
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(featureIds)) {
return Collections.emptySet();
}
return permissionPointService.queryList(PermissionPointListQueryRequest.builder()
.ids(featureIds)
.delegatedType(DelegatedType.NO_NEED.getCode())
.build())
.stream()
.map(e -> FeatureWrapper.builder()
.featureId(e.getPermissionPointId())
.type(OLD_FEATURE)
.build())
.collect(Collectors.toSet());
}
private Set<FeatureWrapper> listNoAuthFeatureResources(Set<FeatureWrapper> featureWrappers) {
List<Long> featureIds = featureWrappers.stream()
.filter(e -> Objects.equals(e.getType(), NEW_FEATURE))
.map(FeatureWrapper::getFeatureId)
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(featureIds)) {
return Collections.emptySet();
}
PageSaasFeatureResourceReq pageSaasFeatureResourceReq = PageSaasFeatureResourceReq.builder()
.ids(featureIds)
.authType(FeatureResourceAuthType.ALL_ROLE.getCode())
.build();
return saasFeatureResourceService.list(pageSaasFeatureResourceReq).stream()
.map(e -> FeatureWrapper.builder()
.featureId(e.getId())
.type(NEW_FEATURE)
.build())
.collect(Collectors.toSet());
}
private List<IdentityAuthRes.PermissionPoint> listNewFeatures(Set<FeatureWrapper> featureWrappers) {
List<Long> featureIds = featureWrappers.stream()
.filter(e -> Objects.equals(e.getType(), NEW_FEATURE))
.map(FeatureWrapper::getFeatureId)
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(featureIds)) {
return Collections.emptyList();
}
// 因为新版本配置权限点的时候会在选中某个权限节点时把所有父节点也冗余到权限里所以只需要查询权限点信息
return saasFeatureResourceService.list(PageSaasFeatureResourceReq.builder()
.ids(featureIds)
.needFeatureCodes(true)
.build())
.stream()
.filter(e -> !CollectionUtils.isEmpty(e.getFeatureCodes()))
.map(e ->
// 兼容历史情况根据featureCode组装数据
e.getFeatureCodes().stream()
.map(featureCode -> IdentityAuthRes.PermissionPoint.builder()
.featureCode(featureCode)
.featureId(e.getId())
.terminal(e.getTerminal())
.build())
.collect(Collectors.toList()))
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
private List<SimplePermissionPointResp> listOldFeatures(Set<FeatureWrapper> featureWrappers) {
Set<Long> featureIds = featureWrappers.stream()
.filter(e -> Objects.equals(e.getType(), OLD_FEATURE))
.map(FeatureWrapper::getFeatureId)
.collect(Collectors.toSet());
if (CollectionUtils.isEmpty(featureIds)) {
return Collections.emptyList();
}
return permissionPointService.listPermissionByIds(
QueryPermissionByIdsReq.builder()
.ids(featureIds)
.includeParent(true)
.build());
}
public ListIdentityFromPermissionResp listIdentityFromPermissionFromDB(ListIdentityFromPermissionReq req) {
ListIdentityFromPermissionResp result = new ListIdentityFromPermissionResp();
result.setOuId(req.getOuId());
result.setWorkspaceId(req.getWorkspaceId());
Set<String> newFeatureCodes = featureCodeUtil.resolveFeatureCode(Sets.newHashSet(req.getFeatureCode()));
//code查询权限点信息
List<SaasFeature> features = permissionPointService.listNodeWithChildrenByCodes(Lists.newArrayList(newFeatureCodes), req.getTerminal());
// 兼容新老版本需要通过featureCode查询新版本的features原逻辑是查询当前菜单资源的所有子数据
ListSaasFeatureResourceParam listSaasFeatureResourceParam = ListSaasFeatureResourceParam.builder()
.featureCodes(newFeatureCodes)
.terminal(req.getTerminal())
.build();
List<SaasFeatureResourceResp> saasFeatureResources = listSaasFeatureResource(listSaasFeatureResourceParam);
if (CollectionUtil.isEmpty(features) && CollectionUtils.isEmpty(saasFeatureResources)) {
log.warn("no features data found for:{}", req.getFeatureCode());
return result;
}
//是否免授权权限点
Optional<SaasFeature> freeFeature = features.stream()
.filter(f -> DelegatedType.NO_NEED.sameCode(f.getDelegatedType()))
.findAny();
Optional<SaasFeatureResourceResp> freeFeatureResource = saasFeatureResources.stream()
.filter(e -> SaasFeatureResource.AuthType.isAllRole(e.getAuthType()))
.findFirst();
if (freeFeature.isPresent() || freeFeatureResource.isPresent()) {
log.warn("free feature found : featureId:{}, featureResourceId:{}",
freeFeature.map(SaasFeature::getId).orElse(null),
freeFeatureResource.map(SaasFeatureResourceResp::getId).orElse(null));
throw new ServiceException("不能查询免授权权限点人员");
}
Set<Long> featureIds = features.stream().map(SaasFeature::getId).collect(Collectors.toSet());
Set<Long> newFeatureIds = saasFeatureResources.stream().map(SaasFeatureResourceResp::getId).collect(Collectors.toSet());
List<FeatureIdPair> featureIdPairs = Lists.newArrayList();
if (!CollectionUtils.isEmpty(featureIds)) {
featureIdPairs.add(FeatureIdPair.builder().featureIds(featureIds).type(OLD_FEATURE).build());
}
if (!CollectionUtils.isEmpty(newFeatureIds)) {
featureIdPairs.add(FeatureIdPair.builder().featureIds(newFeatureIds).type(NEW_FEATURE).build());
}
WorkspaceProductService.WorkspaceProductParam workspaceProductParam = WorkspaceProductService.WorkspaceProductParam.builder()
.workspaceIds(Sets.newHashSet(req.getWorkspaceId()))
.featureIdPairs(featureIdPairs)
.build();
List<SaasProductModuleFeatureRelation> workspaceProducts = workspaceProductService.listWorkspaceProduct(workspaceProductParam)
.stream()
.map(WorkspaceProductService.WorkspaceProduct::getSaasProductModuleFeatureRelations)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.collect(Collectors.toList());
if (CollectionUtil.isEmpty(workspaceProducts)) {
log.warn("no matched product feature in workspace");
return result;
}
List<ListIdentityFromPermissionResp.UserVO> matchedUsers = getWorkspaceUser(req.getWorkspaceId(), req.getOuId(), workspaceProducts);
if (CollectionUtil.isEmpty(matchedUsers)) {
return result;
}
result.setUsers(matchedUsers);
return result;
}
public List<ListIdentityFromPermissionResp> listWorkspacePermissionIdentityFromDB(WorkspacePermissionIdentityReq req) {
Set<String> newFeatureCodes = featureCodeUtil.resolveFeatureCode(Sets.newHashSet(req.getFeatureCodes()));
req.setFeatureCodes(Lists.newArrayList(newFeatureCodes));
//code查询权限点信息
List<SaasFeature> features = permissionPointService.listNodeWithChildrenByCodes(req.getFeatureCodes(), null);
// 兼容新老版本需要通过featureCode查询新版本的features原逻辑是查询当前菜单资源的所有子数据
ListSaasFeatureResourceParam listSaasFeatureResourceParam = ListSaasFeatureResourceParam.builder()
.featureCodes(Sets.newHashSet(req.getFeatureCodes()))
.build();
List<SaasFeatureResourceResp> saasFeatureResources = listSaasFeatureResource(listSaasFeatureResourceParam);
if (CollectionUtil.isEmpty(features) && CollectionUtils.isEmpty(saasFeatureResources)) {
log.warn("no features data found for:{}", req.getFeatureCodes());
return Collections.emptyList();
}
Set<Long> featureIds = features.stream().map(SaasFeature::getId).collect(Collectors.toSet());
Set<Long> newFeatureIds = saasFeatureResources.stream().map(SaasFeatureResourceResp::getId).collect(Collectors.toSet());
List<FeatureIdPair> featureIdPairs = Lists.newArrayList();
if (!CollectionUtils.isEmpty(featureIds)) {
featureIdPairs.add(FeatureIdPair.builder().featureIds(featureIds).type(OLD_FEATURE).build());
}
if (!CollectionUtils.isEmpty(newFeatureIds)) {
featureIdPairs.add(FeatureIdPair.builder().featureIds(newFeatureIds).type(NEW_FEATURE).build());
}
WorkspaceProductService.WorkspaceProductParam workspaceProductParam = WorkspaceProductService.WorkspaceProductParam.builder()
.workspaceIds(Sets.newHashSet(req.getWorkspaceId()))
.featureIdPairs(featureIdPairs)
.build();
List<SaasProductModuleFeatureRelation> workspaceProducts = workspaceProductService.listWorkspaceProduct(workspaceProductParam)
.stream()
.map(WorkspaceProductService.WorkspaceProduct::getSaasProductModuleFeatureRelations)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.collect(Collectors.toList());
if (CollectionUtil.isEmpty(workspaceProducts)) {
log.warn("no matched feature in workspace product");
return Collections.emptyList();
}
//是否免授权权限点
Set<Long> matchedOldFeatureIds = workspaceProducts.stream()
.filter(e -> Objects.equals(OLD_FEATURE, e.getType()))
.map(SaasProductModuleFeatureRelation::getFeatureId)
.collect(Collectors.toSet());
Optional<SaasFeature> freeFeature = features.stream()
.filter(f -> matchedOldFeatureIds.contains(f.getId()))
.filter(f -> DelegatedType.NO_NEED.sameCode(f.getDelegatedType()))
.findAny();
Set<Long> matchedNewFeatureIds = workspaceProducts.stream()
.filter(e -> Objects.equals(NEW_FEATURE, e.getType()))
.map(SaasProductModuleFeatureRelation::getFeatureId)
.collect(Collectors.toSet());
Optional<SaasFeatureResourceResp> freeFeatureResource = saasFeatureResources.stream()
.filter(f -> matchedNewFeatureIds.contains(f.getId()))
.filter(e -> SaasFeatureResource.AuthType.isAllRole(e.getAuthType()))
.findFirst();
if (freeFeature.isPresent() || freeFeatureResource.isPresent()) {
throw new ServiceException("免授权权限点调用查人接口");
}
//从相关角色查询用户-超管和普通角色
List<ListIdentityFromPermissionResp.UserVO> users = getWorkspaceUser(req.getWorkspaceId(), null, workspaceProducts);
if (CollectionUtil.isEmpty(users)) {
return Collections.emptyList();
}
//按ou分组返回
List<ListIdentityFromPermissionResp> result = new ArrayList<>();
Map<Long, List<ListIdentityFromPermissionResp.UserVO>> userMap = users.stream()
.collect(Collectors.groupingBy(ListIdentityFromPermissionResp.UserVO::getOuId));
for (Map.Entry<Long, List<ListIdentityFromPermissionResp.UserVO>> entry : userMap.entrySet()) {
result.add(ListIdentityFromPermissionResp.builder()
.workspaceId(req.getWorkspaceId())
.ouId(entry.getKey())
.users(entry.getValue())
.build());
}
return result;
}
}