refactor(permission): 授权查询缓存

This commit is contained in:
zhansihu 2023-12-26 17:10:12 +08:00
parent 0ac6eecde7
commit d061dbad4d
6 changed files with 104 additions and 27 deletions

View File

@ -59,6 +59,10 @@ public class IdentityAuthReq {
/** 指定角色ID - 预览用,不需要用户已配置角色 **/
private Set<Long> specifyRoleIds;
/** 是否使用缓存 **/
@Builder.Default
private boolean useCache = false;
@Data
@Builder

View File

@ -59,7 +59,7 @@ public class IdentityAuthRes {
// private FeatureType featureType;
// private String terminal;
private String terminal;
}

View File

@ -47,7 +47,7 @@ public class TyrSaasAuthController implements TyrSaasAuthApi {
@Override
public ApiResult<IdentityAuthRes> findIdentityAuth(@Valid IdentityAuthReq identityAuthReq) {
return ApiResult.ok(tyrSaasAuthService.findIdentityAuth(identityAuthReq));
return ApiResult.ok(tyrSaasAuthService.findIdentityAuthMix(identityAuthReq));
}
@Override

View File

@ -27,16 +27,16 @@ public interface TyrSaasAuthService {
//------------------上面权限接口为2023/10月未上线前提供的接口在此日期之后的接口统一使用下面的接口---------------------------
/**
* 查询指定人的权限
* @param identityAuthReq
* @return
*/
IdentityAuthRes findIdentityAuth(IdentityAuthReq identityAuthReq);
boolean hasPermissionForIdentityV2(CheckIdentityPermissionReq req);
ListIdentityFromPermissionResp listIdentityFromPermission(ListIdentityFromPermissionReq req);
List<ListIdentityFromPermissionResp> batchListIdentityFromPermission(List<ListIdentityFromPermissionReq> req);
/**
* 查询指定人的权限
* @param identityAuthReq
* @return
*/
IdentityAuthRes findIdentityAuthMix(IdentityAuthReq identityAuthReq);
}

View File

@ -8,6 +8,7 @@ import cn.axzo.tyr.client.model.res.IdentityAuthRes;
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.StrUtil;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -44,13 +45,15 @@ public class SaasFeatureServiceImpl implements SaasFeatureService {
workspaceOuPair.setWorkspaceJoinType(req.getWorkspaceJoinType());
authReq.setWorkspaceOusPairs(Lists.newArrayList(workspaceOuPair));
IdentityAuthRes identityAuthRes = tyrSaasAuthService.findIdentityAuth(authReq);
IdentityAuthRes identityAuthRes = tyrSaasAuthService.findIdentityAuthMix(authReq);
List<IdentityAuthRes.WorkspacePermission> workspacePermissionList = identityAuthRes.getPermissions();
if (CollUtil.isNotEmpty(workspacePermissionList)) {
IdentityAuthRes.WorkspacePermission workspacePermission = workspacePermissionList.get(0);
featurePermissionRes.setSuperAdmin(workspacePermission.isSuperAdmin());
featurePermissionRes.setPermissionCodes(workspacePermission.getPermissionPoint()
.stream().map(IdentityAuthRes.PermissionPoint::getFeatureCode).collect(Collectors.toSet()));
.stream()
.map(IdentityAuthRes.PermissionPoint::getFeatureCode)
.collect(Collectors.toSet()));
}
return featurePermissionRes;
}

View File

@ -4,6 +4,7 @@ import cn.axzo.basics.common.BeanMapper;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.framework.domain.ServiceException;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.pokonyan.config.redis.RedisUtil;
import cn.axzo.pokonyan.util.TraceSupplier;
import cn.axzo.thrones.client.saas.ServicePkgClient;
import cn.axzo.thrones.client.saas.entity.serivicepgkproduct.ServicePkgProduct;
@ -36,6 +37,8 @@ import cn.hutool.core.date.StopWatch;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.collect.Lists;
import lombok.Data;
import lombok.RequiredArgsConstructor;
@ -292,8 +295,7 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
}
@Override
public IdentityAuthRes findIdentityAuth(IdentityAuthReq identityAuthReq) {
private IdentityAuthRes findIdentityAuth(IdentityAuthReq identityAuthReq) {
log.info("find identityAuth :{}", JSONUtil.toJsonStr(identityAuthReq));
StopWatch stopWatch = new StopWatch("find identity Auth");
AssertUtil.notNull(identityAuthReq.getIdentityId(), "查询指定人的权限失败,未获取到人员信息");
@ -433,14 +435,13 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
//通过子级查询父级并打平树型结构
List<PermissionPointTreeNode> allPermissionPoint = permissionPointService.listTreeNodesFlatChild(PermissionPointTreeQueryReq.builder()
.ids(buttonPermissionPointId)
.terminalList(identityAuthReq.getTerminal())
.build());
workspacePermission.getPermissionPoint().addAll(allPermissionPoint.stream()
.map(permissionPointTreeNode -> IdentityAuthRes.PermissionPoint.builder()
.featureCode(permissionPointTreeNode.getCode())
.featureId(permissionPointTreeNode.getPermissionPointId())
// .terminal(permissionPointTreeNode.getTerminal())
.terminal(permissionPointTreeNode.getTerminal())
// .featureType(FeatureType.apply(permissionPointTreeNode.getFeatureType()))
.build())
.collect(Collectors.toList()));
@ -470,24 +471,13 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
//通过子级查询父级并平铺菜单
List<PermissionPointTreeNode> allPermissionPoint = permissionPointService.listTreeNodesFlatChild(PermissionPointTreeQueryReq.builder()
.ids(new HashSet<>(resultHashAuthPointId))
.terminalList(identityAuthReq.getTerminal())
.build());
workspacePermission.getPermissionPoint().addAll(allPermissionPoint.stream()
.filter(permissionPointTreeNode -> {
if (CollectionUtil.isEmpty(identityAuthReq.getFeatureId()) && CollectionUtil.isEmpty(identityAuthReq.getFeatureCode())) {
return Boolean.TRUE;
}
return (identityAuthReq.getFeatureId().contains(permissionPointTreeNode.getPermissionPointId())) ||
identityAuthReq.getFeatureCode().contains(permissionPointTreeNode.getCode());
}
)
.map(permissionPointTreeNode -> IdentityAuthRes.PermissionPoint.builder()
.featureCode(permissionPointTreeNode.getCode())
.featureId(permissionPointTreeNode.getPermissionPointId())
// .terminal(permissionPointTreeNode.getTerminal())
.terminal(permissionPointTreeNode.getTerminal())
// .featureType(FeatureType.apply(permissionPointTreeNode.getFeatureType()))
.build())
.collect(Collectors.toList()));
@ -521,7 +511,7 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
}
List<IdentityAuthReq.WorkspaceOuPair> pairs = BeanMapper.copyList(req.getWorkspaceAndOU(), IdentityAuthReq.WorkspaceOuPair.class);
request.setWorkspaceOusPairs(pairs);
IdentityAuthRes authRes = this.findIdentityAuth(request);
IdentityAuthRes authRes = this.findIdentityAuthMix(request);
HashSet<String> codeSet = new HashSet<>(req.getCodes());
//比较code
return authRes.getPermissions().stream()
@ -693,6 +683,86 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
return result;
}
@Override
public IdentityAuthRes findIdentityAuthMix(IdentityAuthReq req) {
List<IdentityAuthRes.WorkspacePermission> permissions = null;
if (req.isUseCache() || CollectionUtil.isNotEmpty(req.getSpecifyRoleIds())) {
//不走缓存 或者 角色预览
permissions = findIdentityPermission(req);
} else {
permissions = findIdentityPermissionFromCache(req);
}
IdentityAuthRes result = new IdentityAuthRes();
result.setIdentity(req.getIdentityId());
result.setIdentityType(req.getIdentityType());
//过滤参数统一处理
boolean needFilter = CollectionUtil.isNotEmpty(req.getTerminal())
|| CollectionUtil.isNotEmpty(req.getFeatureCode())
|| CollectionUtil.isNotEmpty(req.getFeatureId());
if (!needFilter) {
return result;
}
Set<String> terminals = req.getTerminal() == null ? null : new HashSet<>(req.getTerminal());
permissions.forEach(permission -> {
List<IdentityAuthRes.PermissionPoint> filterPermission = permission.getPermissionPoint().stream()
.filter(p -> CollectionUtil.isEmpty(terminals) || terminals.contains(p.getTerminal()))
.filter(p -> CollectionUtil.isEmpty(req.getFeatureId()) || req.getFeatureId().contains(p.getFeatureId()))
.filter(p -> CollectionUtil.isEmpty(req.getFeatureCode()) || req.getFeatureCode().contains(p.getFeatureCode()))
.collect(Collectors.toList());
permission.setPermissionPoint(filterPermission);
});
result.setPermissions(permissions);
return result;
}
private List<IdentityAuthRes.WorkspacePermission> findIdentityPermission(IdentityAuthReq req) {
return findIdentityAuth(req).getPermissions();
}
private List<IdentityAuthRes.WorkspacePermission> findIdentityPermissionFromCache(IdentityAuthReq req) {
//服务包产品变化 - 角色配置的权限变化 - 用户角色变化
List<IdentityAuthRes.WorkspacePermission> permissions = new ArrayList<>();
//从缓存取权限并记录缓存中没有的OW
List<IdentityAuthReq.WorkspaceOuPair> needQueryPairs = new ArrayList<>();
req.getWorkspaceOusPairs().forEach(ow -> {
String key = KeyUtil.buildKeyBySeparator("auth", req.getIdentityId(), req.getIdentityType(), ow.getOuId(), ow.getWorkspaceId());
IdentityAuthRes.WorkspacePermission permission = getIdentityAuthFromCache(key);
if (permission == null) {
needQueryPairs.add(ow);
} else {
//加入返回
permissions.add(permission);
}
});
if (CollectionUtil.isNotEmpty(needQueryPairs)) {
//有需要从数据库查询的数据 - 走原查询逻辑 并缓存结果
req.setWorkspaceOusPairs(needQueryPairs);
List<IdentityAuthRes.WorkspacePermission> authPermission = findIdentityPermission(req);
permissions.addAll(authPermission);
authPermission.forEach(p -> {
String key = KeyUtil.buildKeyBySeparator("auth", req.getIdentityId(), req.getIdentityType(), p.getOuId(), p.getWorkspaceId());
cacheIdentityAuth(key, p);
});
}
return permissions;
}
private void cacheIdentityAuth(String key, IdentityAuthRes.WorkspacePermission permission) {
RedisUtil.StringOps.setEx(key, JSONObject.toJSONString(permission, SerializerFeature.DisableCircularReferenceDetect),
60L, TimeUnit.MINUTES);
}
private IdentityAuthRes.WorkspacePermission getIdentityAuthFromCache(String key) {
String permission = RedisUtil.StringOps.get(key);
return permission == null ? null : JSONObject.parseObject(StrUtil.unWrap(permission, '"', '"'),
IdentityAuthRes.WorkspacePermission.class);
}
@Data
public static class UserRoleInfoMap {