feat(permission): 增加person查询权限;重构权限点查询

This commit is contained in:
zhansihu 2024-01-03 15:43:50 +08:00
parent 5f9bf8f710
commit 5884bd1edc
13 changed files with 277 additions and 31 deletions

View File

@ -28,11 +28,14 @@ import java.util.Set;
@NoArgsConstructor
public class IdentityAuthReq {
@NotNull
/** 身份ID - 不能和人员ID同时为空**/
private Long identityId;
@NotNull
/** 身份类型 **/
private IdentityType identityType;
/** 人员ID 优先于身份- 不能和身份同时为空 **/
private Long personId;
/**
*<pre>
* 防止数据量过多工作台与单位必传

View File

@ -0,0 +1,38 @@
package cn.axzo.tyr.client.model.req;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
import java.util.Set;
/**
* 根据ID查询权限点
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/1/3 13:57
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class QueryPermissionByIdsReq {
@NotEmpty(message = "权限点ID不能为空")
private Set<Long> ids;
/** 是否包含父节点 - 默认false **/
@Builder.Default
private boolean includeParent = false;
/** 是否包含子节点 - 默认false **/
@Builder.Default
private boolean includeChildren = false;
/** 是否构建树型结构 - 默认false **/
@Builder.Default
private boolean buildTree = false;
}

View File

@ -24,6 +24,7 @@ import java.util.List;
public class IdentityAuthRes {
private Long identity;
private IdentityType identityType;
private Long personId;
@Builder.Default
private List<WorkspacePermission> permissions=new ArrayList<>();

View File

@ -0,0 +1,67 @@
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;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 权限点 - 字段简化
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/1/3 11:52
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SimplePermissionPointResp implements IBaseTree<SimplePermissionPointResp, Long> {
/** 权限点ID **/
private Long id;
/** 权限点名称 **/
private String name;
/** 权限点编码 **/
private String code;
/** 权限点所属端 **/
private String terminal;
/** 上级权限点ID **/
private Long parentId;
/** 子节点 **/
private List<SimplePermissionPointResp> children;
@JsonIgnore
@Override
public Long getNodeCode() {
return id;
}
@JsonIgnore
@Override
public Long getParentNodeCode() {
return parentId;
}
@JsonIgnore
@Override
public List<SimplePermissionPointResp> getNodeChildren() {
return children;
}
@JsonIgnore
@Override
public void setNodeChildren(List<SimplePermissionPointResp> nodeChildren) {
this.children = nodeChildren;
}
}

View File

@ -1,5 +1,6 @@
package cn.axzo.tyr.server.controller.auth;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.feign.TyrSaasAuthApi;
import cn.axzo.tyr.client.model.req.CheckIdentityPermissionReq;
@ -47,6 +48,11 @@ public class TyrSaasAuthController implements TyrSaasAuthApi {
@Override
public ApiResult<IdentityAuthRes> findIdentityAuth(@Valid IdentityAuthReq identityAuthReq) {
//单独做下参数校验
if (identityAuthReq.getPersonId() == null
&& (identityAuthReq.getIdentityId() == null || identityAuthReq.getIdentityType() == null)) {
AssertUtil.fail("自然人ID和身份ID/Type不能同时为空");
}
return ApiResult.ok(tyrSaasAuthService.findIdentityAuthMix(identityAuthReq));
}

View File

@ -0,0 +1,36 @@
package cn.axzo.tyr.server.model;
import cn.axzo.tyr.server.util.KeyUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 权限缓存key
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/1/2 18:36
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AuthPermissionCacheKey {
private Long personId;
private Long identityId;
private Integer identityType;
private Long workspaceId;
private Long ouId;
public String buildKey() {
return personId == null ? KeyUtil.buildKeyBySeparator("auth-i", identityId, identityType, ouId, workspaceId)
: KeyUtil.buildKeyBySeparator("auth-p", personId, ouId, workspaceId);
}
}

View File

@ -12,6 +12,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@Repository
@ -63,9 +64,11 @@ public class SaasRoleUserRelationDao extends ServiceImpl<SaasRoleUserRelationMap
* @param ouIds
* @return
*/
public List<SaasRoleUserRelation> queryByWorkspaceIdOrOu(Long identityId, IdentityType identityType, Set<Long> workspaceIds, Set<Long> ouIds) {
return lambdaQuery().eq(SaasRoleUserRelation::getIdentityId, identityId)
.eq(SaasRoleUserRelation::getIdentityType, identityType)
public List<SaasRoleUserRelation> queryByWorkspaceIdOrOu(Long personId, Long identityId, IdentityType identityType, Set<Long> workspaceIds, Set<Long> ouIds) {
return lambdaQuery()
.eq(Objects.nonNull(personId), SaasRoleUserRelation::getNaturalPersonId, personId)
.eq(Objects.nonNull(identityId), SaasRoleUserRelation::getIdentityId, identityId)
.eq(Objects.nonNull(identityType), SaasRoleUserRelation::getIdentityType, identityType)
.in(CollectionUtil.isNotEmpty(workspaceIds), SaasRoleUserRelation::getWorkspaceId, workspaceIds)
.in(CollectionUtil.isNotEmpty(ouIds), SaasRoleUserRelation::getOuId, ouIds)
.list();

View File

@ -1,6 +1,7 @@
package cn.axzo.tyr.server.repository.entity;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
@ -8,6 +9,11 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* <p>
@ -166,4 +172,13 @@ public class SaasFeature extends BaseEntity<SaasFeature> implements Serializable
private Integer delegatedType;
public Set<Long> splitPath() {
if (StrUtil.isBlank(this.path)) {
return Collections.emptySet();
}
return StrUtil.split(this.path, "/").stream()
.filter(id -> StrUtil.equals(id, "0"))
.map(Long::valueOf)
.collect(Collectors.toSet());
}
}

View File

@ -6,6 +6,8 @@ import cn.axzo.tyr.client.model.permission.PermissionPointMoveRequest;
import cn.axzo.tyr.client.model.permission.PermissionPointTreeNode;
import cn.axzo.tyr.client.model.permission.PermissionPointTreeQueryReq;
import cn.axzo.tyr.client.model.permission.PermissionPointVO;
import cn.axzo.tyr.client.model.req.QueryPermissionByIdsReq;
import cn.axzo.tyr.client.model.res.SimplePermissionPointResp;
import cn.axzo.tyr.server.repository.entity.SaasFeature;
import java.util.List;
@ -68,4 +70,7 @@ public interface PermissionPointService {
* @return
*/
List<PermissionPointDTO> getChildByParentId(Long parentId);
/** 根据ID查询权限点 **/
List<SimplePermissionPointResp> listPermissionByIds(QueryPermissionByIdsReq req);
}

View File

@ -42,7 +42,7 @@ public interface SaasRoleUserService {
* @param ouIds
* @return
*/
List<SaasRoleUserRelation> queryByWorkspaceIdOrOu(Long identityId, IdentityType identityType, Set<Long> workspaceIds, Set<Long> ouIds);
List<SaasRoleUserRelation> queryByWorkspaceIdOrOu(Long personId, Long identityId, IdentityType identityType, Set<Long> workspaceIds, Set<Long> ouIds);
/**
* workpaceId + ownerOuId + roleId + 手机号 + 姓名 赋予角色支持角色赋予的同时 角色创建

View File

@ -9,6 +9,9 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import cn.axzo.tyr.client.model.enums.FeatureDataType;
import cn.axzo.tyr.client.model.req.QueryPermissionByIdsReq;
import cn.axzo.tyr.client.model.res.SimplePermissionPointResp;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.lang.Opt;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -600,4 +603,55 @@ public class PermissionPointServiceImpl implements PermissionPointService {
List<SaasFeature> feature = saasFeatureDao.getChildByParentId(parentId);
return BeanMapper.copyList(feature, PermissionPointDTO.class);
}
@Override
public List<SimplePermissionPointResp> listPermissionByIds(QueryPermissionByIdsReq req) {
//查所有节点 - 按需过滤
List<SimplePermissionPointResp> result = new ArrayList<>();
List<SaasFeature> allPermissions = saasFeatureDao.list(new LambdaQueryWrapper<SaasFeature>()
.select(SaasFeature::getId,
SaasFeature::getFeatureCode,
SaasFeature::getFeatureName,
SaasFeature::getParentId,
SaasFeature::getTerminal));
Set<Long> parentIds = new HashSet<>();
for (SaasFeature permission : allPermissions) {
if (req.getIds().contains(permission.getId())) {
//匹配查询的节点ID
result.add(toSimplePermission(permission));
if (req.isIncludeParent()) {
//通过path汇总parent
parentIds.addAll(permission.splitPath());
}
} else if (req.isIncludeChildren()) {
//path匹配查询节点ID - 子节点
boolean isChildren = permission.splitPath().stream().anyMatch(id -> req.getIds().contains(id));
if (isChildren) {
result.add(toSimplePermission(permission));
}
}
}
if (!parentIds.isEmpty()) {
//加入所有父级节点
result.addAll(allPermissions.stream()
.filter(p -> parentIds.contains(p.getId()))
.map(this::toSimplePermission)
.collect(Collectors.toList()));
}
return result;
}
private SimplePermissionPointResp toSimplePermission(SaasFeature permission) {
return SimplePermissionPointResp.builder()
.id(permission.getId())
.code(permission.getFeatureCode())
.name(permission.getFeatureName())
.parentId(permission.getParentId())
.terminal(permission.getTerminal())
.build();
}
}

View File

@ -149,8 +149,8 @@ public class RoleUserService implements SaasRoleUserService {
}
@Override
public List<SaasRoleUserRelation> queryByWorkspaceIdOrOu(Long identityId, IdentityType identityType, Set<Long> workspaceIds, Set<Long> ouIds) {
return roleUserRelationDao.queryByWorkspaceIdOrOu(identityId, identityType, workspaceIds, ouIds);
public List<SaasRoleUserRelation> queryByWorkspaceIdOrOu(Long personId, Long identityId, IdentityType identityType, Set<Long> workspaceIds, Set<Long> ouIds) {
return roleUserRelationDao.queryByWorkspaceIdOrOu(personId, identityId, identityType, workspaceIds, ouIds);
}
@Override

View File

@ -21,7 +21,9 @@ import cn.axzo.tyr.client.model.req.*;
import cn.axzo.tyr.client.model.res.IdentityAuthRes;
import cn.axzo.tyr.client.model.res.ListIdentityFromPermissionResp;
import cn.axzo.tyr.client.model.res.QueryIdentityByPermissionResp;
import cn.axzo.tyr.client.model.res.SimplePermissionPointResp;
import cn.axzo.tyr.client.model.vo.SaasRoleVO;
import cn.axzo.tyr.server.model.AuthPermissionCacheKey;
import cn.axzo.tyr.server.repository.entity.*;
import cn.axzo.tyr.server.repository.mapper.TyrSaasAuthMapper;
import cn.axzo.tyr.server.service.PermissionPointService;
@ -347,7 +349,7 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
});
} else {
stopWatch.start("query role user relation");
List<SaasRoleUserRelation> relations = roleUserService.queryByWorkspaceIdOrOu(identityAuthReq.getIdentityId(), identityAuthReq.getIdentityType(), queryWorkspace, queryOuId);
List<SaasRoleUserRelation> relations = roleUserService.queryByWorkspaceIdOrOu(identityAuthReq.getPersonId(), identityAuthReq.getIdentityId(), identityAuthReq.getIdentityType(), queryWorkspace, queryOuId);
stopWatch.stop();
if (CollectionUtil.isEmpty(relations)) {
return result;
@ -440,15 +442,17 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
return;
}
//通过子级查询父级并打平树型结构
List<PermissionPointTreeNode> allPermissionPoint = permissionPointService.listTreeNodesFlatChild(PermissionPointTreeQueryReq.builder()
//查询权限点及父级权限点
List<SimplePermissionPointResp> allPermissionPoint = permissionPointService.listPermissionByIds(
QueryPermissionByIdsReq.builder()
.ids(buttonPermissionPointId)
.includeParent(true)
.build());
workspacePermission.getPermissionPoint().addAll(allPermissionPoint.stream()
.map(permissionPointTreeNode -> IdentityAuthRes.PermissionPoint.builder()
.featureCode(permissionPointTreeNode.getCode())
.featureId(permissionPointTreeNode.getPermissionPointId())
.featureId(permissionPointTreeNode.getId())
.terminal(permissionPointTreeNode.getTerminal())
// .featureType(FeatureType.apply(permissionPointTreeNode.getFeatureType()))
.build())
@ -476,15 +480,17 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
permissions.add(workspacePermission);
return;
}
//通过子级查询父级并平铺菜单
List<PermissionPointTreeNode> allPermissionPoint = permissionPointService.listTreeNodesFlatChild(PermissionPointTreeQueryReq.builder()
//查询权限点及父级权限点
List<SimplePermissionPointResp> allPermissionPoint = permissionPointService.listPermissionByIds(
QueryPermissionByIdsReq.builder()
.ids(new HashSet<>(resultHashAuthPointId))
.includeParent(true)
.build());
workspacePermission.getPermissionPoint().addAll(allPermissionPoint.stream()
.map(permissionPointTreeNode -> IdentityAuthRes.PermissionPoint.builder()
.featureCode(permissionPointTreeNode.getCode())
.featureId(permissionPointTreeNode.getPermissionPointId())
.featureId(permissionPointTreeNode.getId())
.terminal(permissionPointTreeNode.getTerminal())
// .featureType(FeatureType.apply(permissionPointTreeNode.getFeatureType()))
.build())
@ -744,8 +750,14 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
} else {
//从缓存取权限并记录缓存中没有的OW
req.getWorkspaceOusPairs().forEach(ow -> {
String key = KeyUtil.buildKeyBySeparator("auth", req.getIdentityId(), req.getIdentityType().getCode(), ow.getOuId(), ow.getWorkspaceId());
IdentityAuthRes.WorkspacePermission permission = getIdentityAuthFromCache(key);
IdentityAuthRes.WorkspacePermission permission = getIdentityAuthFromCache(AuthPermissionCacheKey.builder()
.personId(req.getPersonId())
.identityId(req.getIdentityId())
.identityType(req.getIdentityType().getCode())
.ouId(ow.getOuId())
.workspaceId(ow.getWorkspaceId())
.build()
.buildKey());
if (permission == null) {
needQueryPairs.add(ow);
} else {
@ -760,20 +772,25 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
req.setWorkspaceOusPairs(needQueryPairs);
List<IdentityAuthRes.WorkspacePermission> authPermission = findIdentityPermission(req);
permissions.addAll(authPermission);
if (CollectionUtil.isEmpty(authPermission)) {
//没有权限构建空权限对象进行缓存
authPermission = needQueryPairs.stream()
.map(p -> IdentityAuthRes.WorkspacePermission.builder()
//缓存结果 - 无权限的缓存空权限对象
Map<String, IdentityAuthRes.WorkspacePermission> permissionMap = authPermission.stream()
.collect(Collectors.toMap(p -> p.getOuId() + "-" + p.getWorkspaceId(), Function.identity()));
needQueryPairs.forEach(p -> {
IdentityAuthRes.WorkspacePermission permission = permissionMap.getOrDefault(p.getOuId() + "-" + p.getWorkspaceId(),
IdentityAuthRes.WorkspacePermission.builder()//空权限对象
.ouId(p.getOuId())
.workspaceId(p.getWorkspaceId())
.isSuperAdmin(false)
.permissionPoint(Collections.emptyList())
.build())
.collect(Collectors.toList());
}
authPermission.forEach(p -> {
String key = KeyUtil.buildKeyBySeparator("auth", req.getIdentityId(), req.getIdentityType().getCode(), p.getOuId(), p.getWorkspaceId());
cacheIdentityAuth(key, p);
.build());
cacheIdentityAuth(AuthPermissionCacheKey.builder()
.personId(req.getPersonId())
.identityId(req.getIdentityId())
.identityType(req.getIdentityType().getCode())
.ouId(p.getOuId())
.workspaceId(p.getWorkspaceId())
.build()
.buildKey(), permission);
});
}
@ -781,6 +798,7 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
}
private boolean needRefreshAuth(Long identityId, IdentityType identityType) {
//TODO:@Zhan 触发刷新逻辑检测
return false;
}