feat(2046-permission): 重构权限查人逻辑

This commit is contained in:
zhansihu 2024-02-01 14:47:57 +08:00
parent 86dcb10442
commit 2e1e09760b
9 changed files with 99 additions and 155 deletions

View File

@ -27,15 +27,15 @@ public class FeaturePermissionReq {
Long workspaceId;
/**
* 工作台类型
* 工作台类型 - 废弃
*/
@NotNull
@Deprecated
private Integer workspaceType;
/**
* 使用{@link WorkspaceJoinType}
* 使用{@link WorkspaceJoinType} - 废弃
*/
@NotNull
@Deprecated
private Integer workspaceJoinType;
/**
@ -50,11 +50,12 @@ public class FeaturePermissionReq {
*/
String terminal;
@NotNull
@Min(value = 1)
Long identityId;
@NotNull
@Min(value = 0)
Integer identityType;
/** 人员ID - 优先于identity **/
Long personId;
}

View File

@ -31,8 +31,8 @@ public class ListIdentityFromPermissionReq {
@NotNull(message = "工作台不能为空")
private Long workspaceId;
/** 参建单位类型 **/
@NotNull(message = "参建单位类型不能为空")
/** 参建单位类型 - 废弃 直接依赖角色上类型 **/
@Deprecated
private Integer workspaceJoinType;
/**

View File

@ -57,4 +57,7 @@ public class SaasRoleWithUser {
* relation 工作台Id
*/
private Long relationWorkspaceId;
private Integer productUnitType;
}

View File

@ -26,5 +26,8 @@ public interface SaasRoleMapper extends BaseMapper<SaasRole> {
List<SaasRole> listForOUWorkspace(Long ouId, Long workspaceId, Integer workspaceJoinType);
List<SaasRole> listRoleByFeatures(@Param("featureIds") Set<Long> featureIds);
List<SaasRoleWithUser> listAdminsByWorkspace(List<Long> workspaceIds);
}

View File

@ -98,4 +98,7 @@ public interface RoleService {
List<SaasRoleGroupCodeVO> queryByCodes(List<String> codes);
void changeGroupLeaderRole(List<ChangeGroupLeaderRoleReq> reqs);
/** 查询超管和管理员角色 **/
List<SaasRole> listAdmins(Long workspaceId, Long ouId);
}

View File

@ -934,4 +934,13 @@ public class RoleServiceImpl implements RoleService {
saasRoleUserRelationDao.saveOrUpdateBatch(addList);
saasRoleUserRelationDao.deleteById(deductList);
}
@Override
public List<SaasRole> listAdmins(Long workspaceId, Long ouId) {
return saasRoleDao.lambdaQuery()
.eq(Objects.nonNull(workspaceId), SaasRole::getWorkspaceId, workspaceId)
.eq(Objects.nonNull(ouId), SaasRole::getOwnerOuId, ouId)
.list();
}
}

View File

@ -12,6 +12,7 @@ import cn.axzo.tyr.server.service.SaasFeatureService;
import cn.axzo.tyr.server.service.TyrSaasAuthService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -41,16 +42,14 @@ public class SaasFeatureServiceImpl implements SaasFeatureService {
public FeaturePermissionRes listPermissionCodes(FeaturePermissionReq req) {
FeaturePermissionRes featurePermissionRes = new FeaturePermissionRes();
IdentityAuthReq authReq = new IdentityAuthReq();
if (StringUtils.hasText(req.getTerminal())) {
authReq.setTerminal(Lists.newArrayList());
if (StrUtil.isNotBlank(req.getTerminal())) {
authReq.setTerminal(Collections.singletonList(req.getTerminal()));
}
authReq.setIdentityId(req.getIdentityId());
authReq.setIdentityType(IdentityType.getIdentityType(req.getIdentityType()));
IdentityAuthReq.WorkspaceOuPair workspaceOuPair = new IdentityAuthReq.WorkspaceOuPair();
workspaceOuPair.setWorkspaceId(req.getWorkspaceId());
workspaceOuPair.setOuId(req.getOuId());
workspaceOuPair.setWorkspaceType(req.getWorkspaceType());
workspaceOuPair.setWorkspaceJoinType(req.getWorkspaceJoinType());
authReq.setWorkspaceOusPairs(Lists.newArrayList(workspaceOuPair));
IdentityAuthRes identityAuthRes = tyrSaasAuthService.findIdentityAuthMix(authReq);

View File

@ -596,133 +596,53 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
result.setOuId(req.getOuId());
result.setWorkspaceId(req.getWorkspaceId());
StopWatch watch = StopWatch.create("listIdentityFromPermission");
//code查询权限点信息
watch.start("listNodeWithChildrenByCode");
List<SaasFeature> features = permissionPointService.listNodeWithChildrenByCode(req.getFeatureCode(), req.getTerminal());
watch.stop();
if (CollectionUtil.isEmpty(features)) {
log.warn("------trace-L-I-F-P----> no features found for:{}", req.getFeatureCode());
log.warn("no features data found for:{}", req.getFeatureCode());
return result;
}
Set<Long> featureIds = features.stream().map(SaasFeature::getId).collect(Collectors.toSet());
log.info("------trace-L-I-F-P----> features need to check:{}", featureIds);
//权限匹配 - 工作台是否有指定权限
watch.start("matchWorkspaceFeature");
Set<Long> matchedFeatureIds = matchWorkspaceFeature(req.getWorkspaceId(), req.getWorkspaceJoinType(), featureIds);
watch.stop();
if (CollectionUtil.isEmpty(matchedFeatureIds)) {
log.warn("------trace-L-I-F-P----> no matched feature in workspace");
return result;
}
log.info("------trace-L-I-F-P----> matched feature in workspace:{}", matchedFeatureIds);
//是否免授权权限点
Optional<SaasFeature> freeFeature = features.stream()
.filter(f -> matchedFeatureIds.contains(f.getId()))
.filter(f -> DelegatedType.NO_NEED.sameCode(f.getDelegatedType()))
.findAny();
if (freeFeature.isPresent()) {
log.warn("------trace-L-I-F-P----> free feature found :{}", freeFeature.get().getId());
result.setFreePermission(true);
log.warn("free feature found :{}", freeFeature.get().getId());
throw new ServiceException("不能查询免授权权限点人员");
}
Set<Long> featureIds = features.stream().map(SaasFeature::getId).collect(Collectors.toSet());
//权限匹配 - 有该权限的工作台产品 productUnitType -> featureIds
Map<Integer, Set<Long>> workspaceFeatureMap = matchWorkspaceFeature(req.getWorkspaceId(), featureIds);
if (CollectionUtil.isEmpty(workspaceFeatureMap)) {
log.warn("no matched product feature in workspace");
return result;
}
//从相关角色查询用户-超管和普通角色
watch.start("getUsersFromRole");
List<ListIdentityFromPermissionResp.UserVO> users = getUsersFromRole(req, matchedFeatureIds);
watch.stop();
watch.prettyPrint(TimeUnit.MILLISECONDS);
result.setUsers(users);
return result;
List<ListIdentityFromPermissionResp> matchedUsers = getWorkspaceUser(req.getWorkspaceId(), req.getOuId(), workspaceFeatureMap);
if (CollectionUtil.isEmpty(matchedUsers)) {
return result;
}
return matchedUsers.get(0);
}
private Set<Long> matchWorkspaceFeature(Long workspaceId, Integer workspaceJoinType, Set<Long> featureIds) {
private Map<Integer, Set<Long>> matchWorkspaceFeature(Long workspaceId, Set<Long> featureIds) {
//查询工作台下产品
List<ServicePkgProduct> productList = checkAndGetData(servicePkgClient.listProductInWorkSpace(workspaceId));
if (CollectionUtil.isEmpty(productList)) {
log.warn("------trace-L-I-F-P----> no product found for workspace");
return Collections.emptySet();
return Collections.emptyMap();
}
//产品包含的权限-过滤参建类型 feature
return productFeatureRelationService.queryOnCondition(ProductFeatureQuery.builder()
.productIds(productList.stream()
.map(ServicePkgProduct::getProductId)
.collect(Collectors.toSet()))
.workspaceJoinType(workspaceJoinType)
.featureIds(featureIds)
.build())
.stream()
.map(SaasProductModuleFeatureRelation::getFeatureId)
.collect(Collectors.toSet());
}
private List<ListIdentityFromPermissionResp.UserVO> getUsersFromRole(ListIdentityFromPermissionReq req, Set<Long> featureIds) {
Long ouId = req.getOuId();
Long workspaceId = req.getWorkspaceId();
StopWatch watch = StopWatch.create("getUsersFromRole");
//查询OU-工作台下的角色-含superAdmin
watch.start("listForOUWorkspace");
List<SaasRole> roleList = roleService.listForOUWorkspace(ouId, workspaceId, req.getWorkspaceJoinType());
watch.stop();
List<Long> roleIds = roleList.stream().map(SaasRole::getId).collect(Collectors.toList());
log.info("------trace-L-I-F-P----> roles from ou-workspace:{}", roleIds);
if (CollectionUtil.isEmpty(roleList)) {
log.info("------trace-L-I-F-P----> no role found for ou-workspace and type");
return Collections.emptyList();
}
//查询角色及权限
watch.start("roleService.getByIds");
List<SaasRoleVO> rolePermissions = roleService.getByIds(roleIds,
null, Lists.newArrayList(workspaceId), Lists.newArrayList(ouId), true,null);
watch.stop();
//计算角色实际的权限 - 匹配请求的权限 --> 实际拥有权限的角色
watch.start("filterMatchFeature");
List<SaasRoleVO> matchedRoleList = new ArrayList<>();
for (SaasRoleVO rolePermission : rolePermissions) {
List<PermissionPointTreeNode> filterFeature = rolePermission.getMatchFeature(workspaceId, ouId);
if (filterFeature.stream().anyMatch(f -> featureIds.contains(f.getPermissionPointId()))) {
log.info("------trace-L-I-F-P----> matched role:{}", rolePermission.getId());
matchedRoleList.add(rolePermission);
} else {
log.info("------trace-L-I-F-P----> not matched role:{}", rolePermission.getId());
}
}
watch.stop();
//查询角色下用户
watch.start("roleUserService.listByRoleIds");
List<Long> matchedRoleIds = matchedRoleList.stream().map(SaasRoleVO::getId).collect(Collectors.toList());
//追加工作台超管
Set<Long> superAdmins = roleList
.stream()
.filter(r -> r.getRoleType().equals(RoleTypeEnum.SUPER_ADMIN.getValue()))
.map(SaasRole::getId)
.collect(Collectors.toSet());
matchedRoleIds.addAll(superAdmins);
log.info("------trace-L-I-F-P----> append super admins:{}, final roles:{}", superAdmins, matchedRoleIds);
if (CollectionUtil.isEmpty(matchedRoleIds)) {
log.info("------trace-L-I-F-P----> no matched role found for feature");
return Collections.emptyList();
}
List<SaasRoleUserRelation> relationList = roleUserService.listByRoleIds(matchedRoleIds, ouId, workspaceId);
watch.stop();
//构建用户-去重(identityId-identityType)
List<ListIdentityFromPermissionResp.UserVO> users = new ArrayList<>();
Set<String> filterSet = new HashSet<>();
for (SaasRoleUserRelation relation : relationList) {
String key = relation.getIdentityId() + "-" + relation.getIdentityType();
if (!filterSet.contains(key)) {
filterSet.add(key);
ListIdentityFromPermissionResp.UserVO user = new ListIdentityFromPermissionResp.UserVO(relation.getIdentityId(),
relation.getIdentityType(), relation.getNaturalPersonId(), superAdmins.contains(relation.getIdentityId()));
users.add(user);
}
}
watch.prettyPrint(TimeUnit.MILLISECONDS);
return users;
.collect(Collectors.groupingBy(r -> Integer.valueOf(r.getDictCode()),
Collectors.mapping(SaasProductModuleFeatureRelation::getFeatureId, Collectors.toSet())));
}
@Override
@ -957,18 +877,19 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
//code查询权限点信息
List<SaasFeature> features = permissionPointService.listNodeWithChildrenByCodes(req.getFeatureCodes(), null);
if (CollectionUtil.isEmpty(features)) {
log.warn("no features found for:{}", req.getFeatureCodes());
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> matchedFeatureIds = matchWorkspaceFeature(req.getWorkspaceId(), null, featureIds);
if (CollectionUtil.isEmpty(matchedFeatureIds)) {
log.warn("------trace-L-I-F-P----> no matched feature in workspace");
//权限匹配 - 工作台是否有指定权限 productUnitType -> featureIds
Map<Integer, Set<Long>> workspaceFeatureMap = matchWorkspaceFeature(req.getWorkspaceId(), featureIds);
if (CollectionUtil.isEmpty(workspaceFeatureMap)) {
log.warn("no matched feature in workspace product");
return Collections.emptyList();
}
//是否免授权权限点
Set<Long> matchedFeatureIds = workspaceFeatureMap.values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
Optional<SaasFeature> freeFeature = features.stream()
.filter(f -> matchedFeatureIds.contains(f.getId()))
.filter(f -> DelegatedType.NO_NEED.sameCode(f.getDelegatedType()))
@ -978,50 +899,53 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
}
//从相关角色查询用户-超管和普通角色
Map<Long, ListIdentityFromPermissionResp> respMap = getWorkspaceUser(req, matchedFeatureIds);
return new ArrayList<>(respMap.values());
return getWorkspaceUser(req.getWorkspaceId(), null, workspaceFeatureMap);
}
private Map<Long, ListIdentityFromPermissionResp> getWorkspaceUser(WorkspacePermissionIdentityReq req, Set<Long> matchedFeatureIds) {
Map<Long, ListIdentityFromPermissionResp> result = new HashMap<>();
Map<Long, Set<String>> distinctMap = new HashMap<>();
//超管
List<SaasRoleWithUser> superAdmins = roleService.listSuperAdminByWorkspace(Collections.singletonList(req.getWorkspaceId()));
for (SaasRoleWithUser superAdmin : superAdmins) {
Set<String> distinctSet = distinctMap.getOrDefault(superAdmin.getOuId(), new HashSet<>());
boolean suc = distinctSet.add(superAdmin.getIdentityId() + "-" + superAdmin.getIdentityType());
distinctMap.put(superAdmin.getOuId(), distinctSet);
if (!suc) {
continue;
}
ListIdentityFromPermissionResp resp = result.getOrDefault(superAdmin.getOuId(), new ListIdentityFromPermissionResp());
ListIdentityFromPermissionResp.UserVO user = ListIdentityFromPermissionResp.UserVO.builder()
.isSuperAdmin(true)
.identityId(superAdmin.getIdentityId())
.identityType(superAdmin.getIdentityType())
.personalId(superAdmin.getNaturalPersonId())
.build();
resp.setOuId(superAdmin.getOuId());
resp.getUsers().add(user);
result.put(superAdmin.getOuId(), resp);
private List<ListIdentityFromPermissionResp> getWorkspaceUser(Long workspaceId, Long ouId, Map<Integer, Set<Long>> workspaceFeatureMap) {
Set<Integer> productTypes = workspaceFeatureMap.keySet();
Set<Long> matchedFeatureIds = workspaceFeatureMap.values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
List<SaasRole> matchedRoles = new ArrayList<>();
//超管和管理员
List<SaasRole> adminRoles = roleService.listAdmins(workspaceId, ouId);
if (CollectionUtil.isEmpty(adminRoles)) {
log.warn("no admin roles found for workspaceId:{}, ouId:{}", workspaceId, ouId);
} else {
matchedRoles.addAll(adminRoles);
}
//权限点查角色 -- 不考虑 角色权限集例外
List<SaasRole> roles = roleService.queryRoleByFeatures(matchedFeatureIds);
if (CollectionUtil.isEmpty(roles)) {
//普通角色 权限点查角色 -- 不考虑 角色权限集例外
List<SaasRole> normalRoles = roleService.queryRoleByFeatures(matchedFeatureIds);
if (CollectionUtil.isEmpty(normalRoles)) {
log.warn("no role found for featureIds:{}", matchedFeatureIds);
return result;
} else {
matchedRoles.addAll(normalRoles);
}
//角色查人
List<Long> roleIds = roles.stream()
//匹配角色和产品标签
List<Long> roleIds = matchedRoles.stream()
.filter(r -> productTypes.contains(r.getProductUnitType()))
.map(SaasRole::getId)
.collect(Collectors.toList());
List<SaasRoleUserRelation> relations = roleUserService.listByRoleIds(roleIds, null, req.getWorkspaceId());
if (CollectionUtil.isEmpty(relations)) {
log.warn("no user role relation found. roleIds:{}, workspaceId:{}", roleIds, req.getWorkspaceId());
return result;
if (CollectionUtil.isEmpty(roleIds)) {
log.warn("no role matched product unit types");
return Collections.emptyList();
}
//角色查人
List<SaasRoleUserRelation> relations = roleUserService.listByRoleIds(roleIds, ouId, workspaceId);
if (CollectionUtil.isEmpty(relations)) {
log.warn("no user role relation found. roleIds:{}, ouId:{} workspaceId:{}", roleIds, ouId, workspaceId);
return Collections.emptyList();
}
Map<Long, Set<String>> distinctMap = new HashMap<>();
//ouId -> resp : ou维度去重
Map<Long, ListIdentityFromPermissionResp> resultMap = new HashMap<>();
//组装去重
for (SaasRoleUserRelation relation : relations) {
Set<String> distinctSet = distinctMap.getOrDefault(relation.getOuId(), new HashSet<>());
boolean suc = distinctSet.add(relation.getIdentityId() + "-" + relation.getIdentityType());
@ -1030,17 +954,18 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
continue;
}
ListIdentityFromPermissionResp resp = result.getOrDefault(relation.getOuId(), new ListIdentityFromPermissionResp());
ListIdentityFromPermissionResp resp = resultMap.getOrDefault(relation.getOuId(), new ListIdentityFromPermissionResp());
ListIdentityFromPermissionResp.UserVO user = ListIdentityFromPermissionResp.UserVO.builder()
.identityId(relation.getIdentityId())
.identityType(relation.getIdentityType())
.personalId(relation.getNaturalPersonId())
.build();
resp.setWorkspaceId(workspaceId);
resp.setOuId(relation.getOuId());
resp.getUsers().add(user);
result.put(relation.getOuId(), resp);
resultMap.put(relation.getOuId(), resp);
}
return result;
return new ArrayList<>(resultMap.values());
}
}

View File

@ -34,6 +34,7 @@
r.`name` AS roleName,
r.role_type AS roleType,
r.workspace_id AS workspaceId,
r.product_unit_type AS productUnitType,
ru.identity_id AS identityId,
ru.identity_type AS identityType,
ru.natural_person_id AS naturalPersonId,