Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
zuoqinbo 2023-11-23 19:00:10 +08:00
commit 04c50e6fbd
28 changed files with 434 additions and 97 deletions

View File

@ -81,7 +81,7 @@ public interface TyrSaasAuthApi {
* @return
*/
@PostMapping("/api/v2/auth/listIdentityFromPermission")
ApiResult<ListIdentityFromPermissionResp> listIdentityFromPermission(@RequestBody ListIdentityFromPermissionReq req);
ApiResult<ListIdentityFromPermissionResp> listIdentityFromPermission(@RequestBody @Valid ListIdentityFromPermissionReq req);
@PostMapping("/api/v2/auth/batchListIdentityFromPermission")
ApiResult<List<ListIdentityFromPermissionResp>> batchListIdentityFromPermission(@RequestBody List<ListIdentityFromPermissionReq> req);

View File

@ -10,6 +10,7 @@ import cn.axzo.tyr.client.model.res.IsSuperAdminRes;
import cn.axzo.tyr.client.model.res.QueryBatchByIdentityIdTypeRes;
import cn.axzo.tyr.client.model.res.QueryRoleByNameResp;
import cn.axzo.tyr.client.model.res.RoleWithUserRes;
import cn.axzo.tyr.client.model.vo.SaasRoleAndGroupVO;
import cn.axzo.tyr.client.model.vo.SaasRoleVO;
import cn.axzo.tyr.client.model.vo.SaveOrUpdateRoleVO;
import org.springframework.cloud.openfeign.FeignClient;
@ -90,4 +91,14 @@ public interface TyrSaasRoleApi {
@PostMapping("/api/saasRole/queryWithUser")
ApiPageResult<RoleWithUserRes> queryRoleWithUser(@RequestBody RoleWithUserQueryReq req);
/**
*
* 通过工作台类型获取对应的标准角
*
* */
@GetMapping("/api/saasRole/queryByWorkspaceType")
ApiResult<List<SaasRoleAndGroupVO>> queryInitRoleByWorkspaceId(@RequestParam ("workspaceType")String workspaceType);
}

View File

@ -1,5 +1,7 @@
package cn.axzo.tyr.client.feign;
import cn.axzo.basics.common.page.PageRequest;
import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserDTO;
import cn.axzo.tyr.client.model.roleuser.dto.SuperAminInfoResp;
@ -68,4 +70,8 @@ public interface TyrSaasRoleUserApi {
@PostMapping("/api/saas-role-user/batch-super-admin-list")
ApiResult<List<SuperAminInfoResp>> batchSuperAdminList(@RequestBody @Valid List<SuperAdminParam> param);
/** 分页查询角色用户数据 多条件 最大分页100**/
@PostMapping("/api/saas-role-user/page")
ApiPageResult<SaasRoleUserDTO> pageQuery(@RequestBody @Valid RoleUserParam param);
}

View File

@ -22,7 +22,7 @@ public class BasicDictNodeResp {
private String workspaceType;
/**
* 类型"ouType", "terminal"
* 类型"ouType", "terminal" identity
*/
private String type;

View File

@ -28,7 +28,8 @@ public enum DictTypeFiledEnum {
/**
* 工作台
*/
WORKSPACE("workspace","工作台")
WORKSPACE("workspace","工作台"),
IDENTITY("identity","身份"),
;
@EnumValue

View File

@ -48,4 +48,7 @@ public class PermissionPointTreeQueryReq {
/** featureType 层级过滤-过滤掉featureType大于该值的数据 **/
private Integer maxFeatureType;
/** 节点匹配后是否继续匹配子节点 **/
private boolean fiterChildren = false;
}

View File

@ -5,7 +5,7 @@ import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* OU和wokspace对
* OU和workspace对
*
* @version V1.0
* @author: ZhanSiHu

View File

@ -1,11 +1,13 @@
package cn.axzo.tyr.client.model.roleuser.req;
import cn.axzo.basics.common.page.PageRequest;
import cn.axzo.tyr.client.model.enums.IdentityType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Set;
/**
@ -16,7 +18,7 @@ import java.util.Set;
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RoleUserParam {
public class RoleUserParam extends PageRequest {
/**
* 工作台id
*/
@ -52,4 +54,10 @@ public class RoleUserParam {
* identityIds
*/
private Set<Long> identityIds;
/** ouId列表**/
private List<Long> ouIds;
/** 工作台ID列表 **/
private List<Long> workspaceIds;
}

View File

@ -0,0 +1,31 @@
package cn.axzo.tyr.client.model.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author tanjie@axzo.cn
* @date 2023/11/16 16:25
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class SaasRoleAndGroupVO {
/**
* 单位类型CODE
*/
private String ouTypeCode;
/**
* 单位类型名称
*/
private String ouTypeName;
/**
* 对应角色不包括权限
*/
private List<SaasRoleVO> simpleSaasRole;
}

View File

@ -1,12 +1,12 @@
package cn.axzo.tyr.client.model.vo;
import cn.axzo.trade.datasecurity.core.annotation.control.DisableCrypt;
import cn.axzo.tyr.client.model.permission.PermissionPointTreeNode;
import cn.hutool.core.collection.CollectionUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.Collection;
@ -21,6 +21,7 @@ import java.util.stream.Collectors;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Slf4j
public class SaasRoleVO {
private Long id;
@ -64,7 +65,7 @@ public class SaasRoleVO {
*
* @return
*/
public List<PermissionPointTreeNode> getFeature() {
public List<PermissionPointTreeNode> currentFeature() {
return this.permissionGroup.stream().map(SaasPermissionGroupVO::getFeature).flatMap(List::stream).distinct().collect(Collectors.toList());
}
@ -125,7 +126,7 @@ public class SaasRoleVO {
}
}
return new ArrayList<>((Collection) permissionPoint);
return new ArrayList<>(permissionPoint);
}
private boolean match(boolean isMatch, Set<PermissionPointTreeNode> source, Collection<PermissionPointTreeNode> target, Long scopeId, Long workspaceId) {
@ -136,6 +137,7 @@ public class SaasRoleVO {
source.addAll(target);
return true;
}
log.warn("------trace-L-I-F-P----> not match permission scope:{}", scopeId);
return false;
}
}

View File

@ -1,5 +1,6 @@
package cn.axzo.tyr.server.config;
import cn.hutool.core.thread.NamedThreadFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -24,11 +25,9 @@ public class ExecutorConfig {
@Bean
public ExecutorService authExecutor() {
new ThreadPoolExecutor.CallerRunsPolicy();
int coreSize = Runtime.getRuntime()
.availableProcessors() < 4 ? Runtime.getRuntime().availableProcessors() * 4
: Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor executor = new ThreadPoolExecutor(coreSize, coreSize * 4, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(1), r -> new Thread(r, "TYR-AUTH-EXECUTOR"), new ThreadPoolExecutor.CallerRunsPolicy() {
int coreSize = 5;
ThreadPoolExecutor executor = new ThreadPoolExecutor(coreSize, 30, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(50), new NamedThreadFactory("TYR-AUTH-EXECUTOR-", false), new ThreadPoolExecutor.CallerRunsPolicy() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
log.warn("auth executor rejected , use caller runs");

View File

@ -12,6 +12,7 @@ import cn.axzo.tyr.client.model.res.IsSuperAdminRes;
import cn.axzo.tyr.client.model.res.QueryBatchByIdentityIdTypeRes;
import cn.axzo.tyr.client.model.res.QueryRoleByNameResp;
import cn.axzo.tyr.client.model.res.RoleWithUserRes;
import cn.axzo.tyr.client.model.vo.SaasRoleAndGroupVO;
import cn.axzo.tyr.client.model.vo.SaasRoleVO;
import cn.axzo.tyr.client.model.vo.SaveOrUpdateRoleVO;
import cn.axzo.tyr.server.service.RoleService;
@ -92,4 +93,9 @@ public class SaasRoleController implements TyrSaasRoleApi {
return ApiPageResult.ok(roleService.queryRoleWithUser(req));
}
@Override
public ApiResult<List<SaasRoleAndGroupVO>> queryInitRoleByWorkspaceId(String workspaceType) {
return ApiResult.ok(roleService.queryInitRoleByWorkspaceId(workspaceType));
}
}

View File

@ -1,5 +1,6 @@
package cn.axzo.tyr.server.controller.roleuser;
import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.feign.TyrSaasRoleUserApi;
import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserDTO;
@ -75,4 +76,9 @@ public class RoleUserController implements TyrSaasRoleUserApi {
}
return ApiResult.ok(saasRoleUserService.batchSuperAdminList(param));
}
@Override
public ApiPageResult<SaasRoleUserDTO> pageQuery(RoleUserParam param) {
return ApiPageResult.ok(saasRoleUserRelationService.pageQuery(param));
}
}

View File

@ -0,0 +1,142 @@
package cn.axzo.tyr.server.job;
import cn.axzo.basics.common.constant.enums.OrganizationalUnitTypeEnum;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.tyr.server.repository.dao.*;
import cn.axzo.tyr.server.repository.entity.SaasRole;
import cn.axzo.tyr.server.repository.entity.SaasRoleGroup;
import cn.axzo.tyr.server.repository.entity.SaasRoleGroupRelation;
import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* CMS角色清洗job-将回溯不了的角色洗成其他
* @description
* @date 2021/9/13 11:31
*/
@Component
@AllArgsConstructor
@Slf4j
@RefreshScope
@RequiredArgsConstructor
public class CMSOtherRoleJobHandler extends IJobHandler {
@Autowired
SaasRoleGroupDao roleGroupDao;
@Autowired
SaasRoleDao roleDao;
@Autowired
SaasPermissionGroupDao saasPermissionGroupDao;
@Autowired
SaasFeatureDao featureDao;
@Autowired
SaasRoleGroupRelationDao roleGroupRelationDao;
@Autowired
SaasRoleUserRelationDao roleUserRelationDao;
@Autowired
SaasPgroupRoleRelationDao pgroupRoleRelationDao;
@Autowired
SaasPgroupPermissionRelationDao pgroupPermissionRelationDao;
@Autowired
SaasPreRoleDao saasPreRoleDao;
@Autowired
SaasPreTemplateDao saasPreTemplateDao;
@Autowired
SaasPreGroupRoleRelationDao saasPreGroupRoleRelationDao;
/**
* CMS角色清洗job-将回溯不了的角色洗成其他
*
* @param s
* @return
* @throws Exception
*/
@Transactional // 在一个事务里面做一起提交
@Override
@XxlJob("CMSOtherRoleJobHandler")
public ReturnT<String> execute(String s) throws Exception {
log.info("CMSOtherRoleJobHandler start");
// 查询无法回溯的角色
List<SaasRole> oldRole = roleDao.lambdaQuery()
.ne(SaasRole::getWorkspaceId, -1l)
.eq(SaasRole::getRoleType, "init")
.in(SaasRole::getFitOuTypeBit, Arrays.asList(1, 2, 4, 8, 16))
.eq(SaasRole::getFromPreRoleId, 0l)
.eq(BaseEntity::getIsDelete, 0)
.list();
if (CollectionUtils.isEmpty(oldRole)) {
log.info("未找到回溯不了的角色");
}
// 根据单位类型分组
Map<Long, List<SaasRole>> ouTypeMap = oldRole.stream().collect(Collectors.groupingBy(e -> e.getFitOuTypeBit()));
Set<Long> ouType = ouTypeMap.keySet();
ouType.forEach(e -> {
// 获取"其他"角色id
Long newRoleId = getNewRoleId(e);
// 更用户角色关联关系
roleUserRelationDao.lambdaUpdate()
.in(SaasRoleUserRelation::getRoleId,ouTypeMap.get(e).stream().map(BaseEntity::getId).collect(Collectors.toList()))
.set(SaasRoleUserRelation::getRoleId,newRoleId)
.update();
});
log.info("CMSOtherRoleJobHandler end");
return ReturnT.SUCCESS;
}
/**
* 查询新角色"其他" id
* @return
*/
private Long getNewRoleId(Long ouType) {
// 根据单位类型查询权限分组
SaasRoleGroup roleGroup = roleGroupDao.lambdaQuery().eq(SaasRoleGroup::getOuTypeCode, String.valueOf(tranceOuTypeBit(ouType))).one();
// 查询权限分组下的角色
List<SaasRoleGroupRelation> roleGroupRelation = roleGroupRelationDao.lambdaQuery()
.eq(SaasRoleGroupRelation::getSaasRoleGroupId, roleGroup.getId())
.eq(BaseEntity::getIsDelete, 0)
.list();
// 查询权限分组下的"其他"角色
SaasRole otherRole = roleDao.lambdaQuery()
.in(BaseEntity::getId, roleGroupRelation.stream().map(SaasRoleGroupRelation::getRoleId).collect(Collectors.toList()))
.eq(SaasRole::getName, "其他")
.eq(BaseEntity::getIsDelete, 0)
.one();
return otherRole.getId();
}
private Integer tranceOuTypeBit(Long ouTypeBit) {
Integer ouType;
if (ouTypeBit == 1) {
ouType = OrganizationalUnitTypeEnum.PRIMARY_CONTRACTING_UNIT.getValue();
} else if (ouTypeBit == 2) {
ouType = OrganizationalUnitTypeEnum.CONSTRUCTION_UNIT.getValue();
} else if (ouTypeBit == 4) {
ouType = OrganizationalUnitTypeEnum.SUPERVISION_UNIT.getValue();
} else if (ouTypeBit == 8) {
ouType = OrganizationalUnitTypeEnum.LABOR_SUBCONTRACTING.getValue();
} else if (ouTypeBit == 16) {
ouType = OrganizationalUnitTypeEnum.PROFESSIONAL_SUBCONTRACTING.getValue();
} else {
throw new IllegalStateException("ouTypeBit 错误: " + ouTypeBit);
}
return ouType;
}
}

View File

@ -25,5 +25,11 @@ public class SaasRoleGroupRelationDao extends ServiceImpl<SaasRoleGroupRelationM
.set(BaseEntity::getIsDelete, TableIsDeleteEnum.DELETE.value)
.update();
}
public List<SaasRoleGroupRelation> getByGroupIds(List<Long> groupIds) {
return lambdaQuery().in(SaasRoleGroupRelation::getSaasRoleGroupId, groupIds)
.eq(BaseEntity::getIsDelete, 0)
.list();
}
}

View File

@ -22,4 +22,6 @@ public class ProductFeatureQuery {
private String terminal;
private Integer workspaceJoinType;
private Set<Long> featureIds;
}

View File

@ -64,6 +64,13 @@ public class SaasRole extends BaseEntity<SaasRole> {
@Deprecated
private Long fromPreRoleId;
/**
* 适用单位类型 1:总包 2:建设单位 4:监理单位 8:劳务分包 16:专业分包 0都可以用 只会挂在最末级
* (1052上线后可删除)
*/
@Deprecated
private Long fitOuTypeBit;
/**
* 获取主键值
*

View File

@ -7,6 +7,7 @@ import cn.axzo.tyr.client.model.res.IsSuperAdminRes;
import cn.axzo.tyr.client.model.res.QueryBatchByIdentityIdTypeRes;
import cn.axzo.tyr.client.model.res.QueryRoleByNameResp;
import cn.axzo.tyr.client.model.res.RoleWithUserRes;
import cn.axzo.tyr.client.model.vo.SaasRoleAndGroupVO;
import cn.axzo.tyr.client.model.vo.SaasRoleVO;
import cn.axzo.tyr.client.model.vo.SaveOrUpdateRoleVO;
import cn.axzo.tyr.server.repository.entity.SaasRole;
@ -74,4 +75,7 @@ public interface RoleService {
List<SaasRoleVO> queryRoleByRoleTypes(QueryByIdentityIdTypeReq req, List<String> roleTypes);
List<SaasRole> listForOUWorkspace(Long ouId, Long workspaceId, Integer workspaceJoinType);
List<SaasRoleAndGroupVO> queryInitRoleByWorkspaceId(String workspaceType);
}

View File

@ -1,5 +1,6 @@
package cn.axzo.tyr.server.service;
import cn.axzo.framework.domain.page.PageResp;
import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserDTO;
import cn.axzo.tyr.client.model.roleuser.req.RoleUserParam;
@ -11,4 +12,6 @@ import java.util.List;
*/
public interface SaasRoleUserRelationService {
List<SaasRoleUserDTO> list(RoleUserParam param);
PageResp<SaasRoleUserDTO> pageQuery(RoleUserParam param);
}

View File

@ -63,7 +63,7 @@ public interface SaasRoleUserService {
*/
List<SuperAminInfoResp> batchSuperAdminList(List<SuperAdminParam> param);
List<SaasRoleUserRelation> listByRoleIds(List<Long> roleIds, Long workspaceId);
List<SaasRoleUserRelation> listByRoleIds(List<Long> roleIds, Long ouId, Long workspaceId);
/**
* 删除单位参与的工作台的所有的人员与角色 目前主要是用于移除参与单位的地方

View File

@ -243,23 +243,24 @@ public class PermissionPointServiceImpl implements PermissionPointService {
//条件匹配 - ID
boolean matchId = CollectionUtil.isEmpty(request.getIds()) || request.getIds().contains(node.getPermissionPointId());
if (matchKeyword && matchDelegateType && matchId) {
//如果匹配直接返回否则过滤子节点
boolean matched = matchKeyword && matchDelegateType && matchId;
if (matched && !request.isFiterChildren()) {
//如果匹配且不需要过滤子节点直接返回否则过滤子节点
return true;
}
if (CollectionUtil.isEmpty(node.getChildren())) {
return false;
return matched;
}
//过滤子节点 - 递归 - 必要时改为循环
List<PermissionPointTreeNode> filterChildren = node.getChildren().stream()
.filter(x -> recursionFilter(request, x))
.collect(Collectors.toList());
if (CollectionUtil.isEmpty(filterChildren)) {
return false;
}
//重置子节点
node.setChildren(filterChildren);
if (CollectionUtil.isEmpty(filterChildren)) {
return matched;
}
return true;
}
@ -567,7 +568,7 @@ public class PermissionPointServiceImpl implements PermissionPointService {
List<SaasFeature> currentFeatrureList = saasFeatureDao.list(new LambdaQueryWrapper<SaasFeature>()
.eq(SaasFeature::getFeatureCode, featureCode)
.eq(StrUtil.isNotBlank(terminal), SaasFeature::getTerminal, terminal));
//button过滤减少查询
//button过滤-如果全是按钮则不查子级
Set<String> pathsWithoutButton = currentFeatrureList.stream()
.filter(f -> !BUTTON.sameCode(f.getFeatureType()))
.map(SaasFeature::getPath)

View File

@ -156,7 +156,8 @@ public class ProductFeatureRelationServiceImpl implements ProductFeatureRelation
.in(CollectionUtil.isNotEmpty(condition.getProductIds()),
SaasProductModuleFeatureRelation::getProductModuleId, condition.getProductIds())
.eq(Objects.nonNull(condition.getWorkspaceJoinType()),
SaasProductModuleFeatureRelation::getDictCode, condition.getWorkspaceJoinType());
SaasProductModuleFeatureRelation::getDictCode, condition.getWorkspaceJoinType())
.in(CollectionUtil.isNotEmpty(condition.getFeatureIds()), SaasProductModuleFeatureRelation::getFeatureId, condition.getFeatureIds());
return this.saasProductModuleFeatureRelationDao.list(wrapper);
}

View File

@ -14,6 +14,7 @@ import cn.axzo.tyr.client.model.res.QueryBatchByIdentityIdTypeRes;
import cn.axzo.tyr.client.model.res.QueryRoleByNameResp;
import cn.axzo.tyr.client.model.res.RoleWithUserRes;
import cn.axzo.tyr.client.model.vo.SaasPermissionGroupVO;
import cn.axzo.tyr.client.model.vo.SaasRoleAndGroupVO;
import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO;
import cn.axzo.tyr.client.model.vo.SaasRoleVO;
import cn.axzo.tyr.client.model.vo.SaveOrUpdateRoleVO;
@ -22,6 +23,8 @@ import cn.axzo.tyr.server.repository.entity.*;
import cn.axzo.tyr.server.service.*;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
@ -540,4 +543,45 @@ public class RoleServiceImpl implements RoleService {
return resp;
}).collect(Collectors.toList());
}
@Override
public List<SaasRoleAndGroupVO> queryInitRoleByWorkspaceId(String workspaceType) {
if (StrUtil.isEmpty(workspaceType)) {
return new ArrayList<>();
}
List<SaasRoleGroup> query = saasRoleGroupDao.query(QuerySaasRoleGroupReq.builder()
.workspaceTypeCode(ListUtil.of(workspaceType))
.build());
if (CollectionUtils.isEmpty(query)) {
return Collections.emptyList();
}
List<SaasRoleGroupRelation> roleGroupRelation = roleGroupRelationDao.getByGroupIds(query.stream().map(BaseEntity::getId).collect(Collectors.toList()));
if (CollectionUtils.isEmpty(roleGroupRelation)) {
return Collections.emptyList();
}
Map<Long, List<SaasRoleGroupRelation>> groupIdMap = roleGroupRelation.stream().collect(Collectors.groupingBy(SaasRoleGroupRelation::getSaasRoleGroupId));
ArrayList<SaasRoleAndGroupVO> result = new ArrayList<>();
query.forEach(e->{
List<SaasRoleGroupRelation> saasRoleGroupRelations = groupIdMap.get(e.getId());
if (CollectionUtils.isEmpty(saasRoleGroupRelations)) {
return;
}
List<SaasRole> roles = saasRoleDao.listByIds(saasRoleGroupRelations.stream().map(SaasRoleGroupRelation::getRoleId).collect(Collectors.toList()));
result.add(SaasRoleAndGroupVO.builder()
.ouTypeName(e.getName())
.ouTypeCode(e.getOuTypeCode())
.simpleSaasRole(roles.stream().map(role -> SaasRoleVO.builder()
.roleType(role.getRoleType())
.id(role.getId())
.name(role.getName())
.build()).collect(Collectors.toList()))
.build());
});
return result;
}
}

View File

@ -77,7 +77,7 @@ public class RoleUserService implements SaasRoleUserService {
.build();
// 删除现有非管理员的角色
if (CollectionUtils.isNotEmpty(existsRoleUser)) {
if (CollectionUtils.isNotEmpty(notAdminRole)) {
roleUserRelationDao.deleteByUser(workspaceModel, notAdminRole);
}
// 清空所有角色
@ -227,11 +227,12 @@ public class RoleUserService implements SaasRoleUserService {
}
@Override
public List<SaasRoleUserRelation> listByRoleIds(List<Long> roleIds, Long workspaceId) {
public List<SaasRoleUserRelation> listByRoleIds(List<Long> roleIds, Long ouId, Long workspaceId) {
if (CollectionUtil.isEmpty(roleIds)) {
return new ArrayList<>();
}
return roleUserRelationDao.list(new LambdaQueryWrapper<SaasRoleUserRelation>()
.eq(SaasRoleUserRelation::getOuId, ouId)
.eq(SaasRoleUserRelation::getWorkspaceId, workspaceId)
.in(SaasRoleUserRelation::getRoleId, roleIds));
}

View File

@ -1,6 +1,8 @@
package cn.axzo.tyr.server.service.impl;
import cn.axzo.basics.common.BeanMapper;
import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum;
import cn.axzo.framework.domain.page.PageResp;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserDTO;
import cn.axzo.tyr.client.model.roleuser.req.RoleUserParam;
@ -11,6 +13,9 @@ import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation;
import cn.axzo.tyr.server.service.SaasRoleUserRelationService;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@ -39,16 +44,8 @@ public class SaasRoleUserRelationServiceImpl implements SaasRoleUserRelationServ
@Override
public List<SaasRoleUserDTO> list(RoleUserParam param) {
// TODO jhy 角色查询 需要验证标准角色和自定义角色的查询逻辑
List<SaasRoleUserRelation> saasRoleUserRelations = saasRoleUserRelationDao.lambdaQuery()
.eq(Objects.nonNull(param.getIdentityId()), SaasRoleUserRelation::getIdentityId, param.getIdentityId())
.eq(Objects.nonNull(param.getIdentityType()), SaasRoleUserRelation::getIdentityType, param.getIdentityType())
.eq(Objects.nonNull(param.getWorkspaceId()), SaasRoleUserRelation::getWorkspaceId, param.getWorkspaceId())
.eq(Objects.nonNull(param.getOuId()), SaasRoleUserRelation::getOuId, param.getOuId())
.in(CollectionUtil.isNotEmpty(param.getRoleIds()), SaasRoleUserRelation::getRoleId, param.getRoleIds())
.in(CollectionUtil.isNotEmpty(param.getIdentityIds()), SaasRoleUserRelation::getIdentityId, param.getIdentityIds())
.eq(BaseEntity::getIsDelete, TableIsDeleteEnum.NORMAL.value)
.last("LIMIT 1000")
.list();
LambdaQueryChainWrapper<SaasRoleUserRelation> wrapper = buildWrapper(param);
List<SaasRoleUserRelation> saasRoleUserRelations = wrapper.last("LIMIT 1000").list();
if (CollectionUtil.isEmpty(saasRoleUserRelations)) {
return Collections.emptyList();
}
@ -66,4 +63,36 @@ public class SaasRoleUserRelationServiceImpl implements SaasRoleUserRelationServ
return userRole;
}).collect(Collectors.toList());
}
private LambdaQueryChainWrapper<SaasRoleUserRelation> buildWrapper(RoleUserParam param) {
return saasRoleUserRelationDao.lambdaQuery()
.eq(Objects.nonNull(param.getIdentityId()), SaasRoleUserRelation::getIdentityId, param.getIdentityId())
.eq(Objects.nonNull(param.getIdentityType()), SaasRoleUserRelation::getIdentityType, param.getIdentityType())
.eq(Objects.nonNull(param.getWorkspaceId()), SaasRoleUserRelation::getWorkspaceId, param.getWorkspaceId())
.eq(Objects.nonNull(param.getOuId()), SaasRoleUserRelation::getOuId, param.getOuId())
.in(CollectionUtil.isNotEmpty(param.getOuIds()), SaasRoleUserRelation::getOuId, param.getOuIds())
.in(CollectionUtil.isNotEmpty(param.getWorkspaceIds()), SaasRoleUserRelation::getWorkspaceId, param.getWorkspaceId())
.in(CollectionUtil.isNotEmpty(param.getRoleIds()), SaasRoleUserRelation::getRoleId, param.getRoleIds())
.in(CollectionUtil.isNotEmpty(param.getIdentityIds()), SaasRoleUserRelation::getIdentityId, param.getIdentityIds())
.eq(BaseEntity::getIsDelete, TableIsDeleteEnum.NORMAL.value);
}
@Override
public PageResp<SaasRoleUserDTO> pageQuery(RoleUserParam param) {
//限制分页100
if (param.getPageSize() != null && param.getPageSize().compareTo(200L) > 0) {
param.setPageSize(100L);
}
//查询条件构造 - ID升序
LambdaQueryChainWrapper<SaasRoleUserRelation> wrapper = buildWrapper(param)
.orderByAsc(SaasRoleUserRelation::getId);
IPage<SaasRoleUserRelation> page = wrapper.page(param.toPage());
if (CollectionUtil.isEmpty(page.getRecords())) {
return PageResp.zero(param.getPage(), param.getPageSize());
}
List<SaasRoleUserDTO> list = page.getRecords().stream()
.map(r -> BeanMapper.copyBean(r, SaasRoleUserDTO.class))
.collect(Collectors.toList());
return PageResp.list(param.getPage(), param.getPageSize(), page.getTotal(), list);
}
}

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.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;
@ -15,25 +16,12 @@ import cn.axzo.tyr.client.model.permission.PermissionPointListQueryRequest;
import cn.axzo.tyr.client.model.permission.PermissionPointTreeNode;
import cn.axzo.tyr.client.model.permission.PermissionPointTreeQueryReq;
import cn.axzo.tyr.client.model.product.ProductFeatureRelationVO;
import cn.axzo.tyr.client.model.req.CheckIdentityPermissionReq;
import cn.axzo.tyr.client.model.req.IdentityAuthReq;
import cn.axzo.tyr.client.model.req.ListIdentityFromPermissionReq;
import cn.axzo.tyr.client.model.req.ListPermissionFromFeatureReq;
import cn.axzo.tyr.client.model.req.ListPermissionFromIdentityReq;
import cn.axzo.tyr.client.model.req.OUWorkspacePair;
import cn.axzo.tyr.client.model.req.QuerySaasRoleReq;
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.vo.SaasRoleVO;
import cn.axzo.tyr.server.repository.entity.ProductFeatureInfo;
import cn.axzo.tyr.server.repository.entity.ProductFeatureQuery;
import cn.axzo.tyr.server.repository.entity.RolePermission;
import cn.axzo.tyr.server.repository.entity.SaasFeature;
import cn.axzo.tyr.server.repository.entity.SaasProductModuleFeatureRelation;
import cn.axzo.tyr.server.repository.entity.SaasRole;
import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation;
import cn.axzo.tyr.server.repository.entity.SaasRoleWithUser;
import cn.axzo.tyr.server.repository.entity.*;
import cn.axzo.tyr.server.repository.mapper.TyrSaasAuthMapper;
import cn.axzo.tyr.server.service.PermissionPointService;
import cn.axzo.tyr.server.service.ProductFeatureRelationService;
@ -56,16 +44,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@ -532,78 +511,104 @@ 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());
//权限匹配 - 工作台是否有指定权限
List<SaasFeature> matchedFeature = matchWorkspaceFeature(req.getWorkspaceId(), req.getWorkspaceJoinType(), features);
if (CollectionUtil.isEmpty(matchedFeature)) {
log.warn("no matched feature in workspace");
watch.stop();
if (CollectionUtil.isEmpty(features)) {
log.warn("------trace-L-I-F-P----> no features 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 = matchedFeature.stream()
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("free feature found");
log.warn("------trace-L-I-F-P----> free feature found :{}", freeFeature.get().getId());
result.setFreePermission(true);
return result;
}
//从相关角色查询用户-超管和普通角色
List<ListIdentityFromPermissionResp.UserVO> users = getUsersFromRole(req, matchedFeature);
watch.start("getUsersFromRole");
List<ListIdentityFromPermissionResp.UserVO> users = getUsersFromRole(req, matchedFeatureIds);
watch.stop();
watch.prettyPrint(TimeUnit.MILLISECONDS);
result.setUsers(users);
return result;
}
private List<SaasFeature> matchWorkspaceFeature(Long workspaceId, Integer workspaceJoinType, List<SaasFeature> features) {
private Set<Long> matchWorkspaceFeature(Long workspaceId, Integer workspaceJoinType, Set<Long> featureIds) {
//查询工作台下产品
List<ServicePkgProduct> productList = checkAndGetData(servicePkgClient.listProductInWorkSpace(workspaceId));
if (CollectionUtil.isEmpty(productList)) {
log.warn("no product found for workspace:{}", workspaceId);
return new ArrayList<>();
log.warn("------trace-L-I-F-P----> no product found for workspace");
return Collections.emptySet();
}
//产品包含的权限-过滤参建类型
Set<Long> workspaceFeatures = productFeatureRelationService.queryOnCondition(ProductFeatureQuery.builder()
//产品包含的权限-过滤参建类型 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());
//权限匹配
return features.stream()
.filter(x -> workspaceFeatures.contains(x.getId()))
.collect(Collectors.toList());
}
private List<ListIdentityFromPermissionResp.UserVO> getUsersFromRole(ListIdentityFromPermissionReq req, List<SaasFeature> features) {
private List<ListIdentityFromPermissionResp.UserVO> getUsersFromRole(ListIdentityFromPermissionReq req, Set<Long> featureIds) {
Long ouId = req.getOuId();
Long workspaceId = req.getWorkspaceId();
//查询OU-工作台下的角色
StopWatch watch = StopWatch.create("getUsersFromRole");
//查询OU-工作台下的角色-含superAdmin
watch.start("listForOUWorkspace");
List<SaasRole> roleList = roleService.listForOUWorkspace(ouId, workspaceId, req.getWorkspaceJoinType());
log.info("====查询OU-工作台下的角色:{}===",roleList);
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();
}
//查询角色及权限
List<SaasRoleVO> rolePermissions = roleService.getByIds(roleList.stream().map(SaasRole::getId).collect(Collectors.toList()),
watch.start("roleService.getByIds");
List<SaasRoleVO> rolePermissions = roleService.getByIds(roleIds,
null, Lists.newArrayList(workspaceId), Lists.newArrayList(ouId), true);
log.info("====查询角色及权限:{}===",rolePermissions);
watch.stop();
//计算角色实际的权限 - 匹配请求的权限 --> 实际拥有权限的角色
Set<Long> featureIds = features.stream().map(SaasFeature::getId).collect(Collectors.toSet());
List<SaasRoleVO> matchedRoleList = rolePermissions.stream()
.filter(rp -> rp.getMatchFeature(workspaceId, ouId).stream()
.anyMatch(f -> featureIds.contains(f.getPermissionPointId())))
.collect(Collectors.toList());
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();
log.info("====计算角色实际的权限 - 匹配请求的权限 --> 实际拥有权限的角色:{}===",featureIds);
//查询角色下用户
watch.start("roleUserService.listByRoleIds");
List<Long> matchedRoleIds = matchedRoleList.stream().map(SaasRoleVO::getId).collect(Collectors.toList());
log.info("====查询角色下用户:{}===",matchedRoleIds);
//追加工作台超管
Set<Long> superAdmins = roleList
.stream()
@ -611,9 +616,14 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
.map(SaasRole::getId)
.collect(Collectors.toSet());
matchedRoleIds.addAll(superAdmins);
log.info("====追加工作台超管:{}===",superAdmins);
List<SaasRoleUserRelation> relationList = roleUserService.listByRoleIds(matchedRoleIds, workspaceId);
log.info("====追加工作台超管:{}===",relationList);
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<>();
@ -626,23 +636,34 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService {
users.add(user);
}
}
watch.prettyPrint(TimeUnit.MILLISECONDS);
return users;
}
@Override
public List<ListIdentityFromPermissionResp> batchListIdentityFromPermission(List<ListIdentityFromPermissionReq> reqList) {
//异步处理
StopWatch watch = StopWatch.create("batchListIdentityFromPermission");
watch.start("addFuture");
List<CompletableFuture<ListIdentityFromPermissionResp>> futureList = new ArrayList<>();
for (ListIdentityFromPermissionReq req : reqList) {
CompletableFuture<ListIdentityFromPermissionResp> future = CompletableFuture.supplyAsync(
() -> this.listIdentityFromPermission(req), executor);
long start = System.currentTimeMillis();
CompletableFuture<ListIdentityFromPermissionResp> future = CompletableFuture.supplyAsync(TraceSupplier.create(() -> {
ListIdentityFromPermissionResp resp = this.listIdentityFromPermission(req);
log.info("------trace-B-L-I-F-P----> code:{},task cost:{}", req.getFeatureCode(), System.currentTimeMillis() - start);
return resp;
}), executor);
futureList.add(future);
}
watch.stop();
List<ListIdentityFromPermissionResp> result = new ArrayList<>();
watch.start("collectResult");
for (CompletableFuture<ListIdentityFromPermissionResp> future : futureList) {
result.add(future.join());
}
watch.stop();
watch.prettyPrint(TimeUnit.MILLISECONDS);
return result;
}

View File

@ -47,7 +47,7 @@ spring:
cloud:
nacos:
config:
server-addr: ${NACOS_HOST:dev-nacos.axzo.cn}:${NACOS_PORT:80}
server-addr: ${NACOS_HOST:https://dev-nacos.axzo.cn}:${NACOS_PORT:443}
file-extension: yaml
namespace: ${NACOS_NAMESPACE_ID:f82179f1-81a9-41a1-a489-4f9ab5660a6e}
logging:
@ -62,7 +62,7 @@ spring:
cloud:
nacos:
config:
server-addr: ${NACOS_HOST:dev-nacos.axzo.cn}:${NACOS_PORT:80}
server-addr: ${NACOS_HOST:https://dev-nacos.axzo.cn}:${NACOS_PORT:443}
file-extension: yaml
namespace: ${NACOS_NAMESPACE_ID:35eada10-9574-4db8-9fea-bc6a4960b6c7}
---

View File

@ -1,8 +1,11 @@
package cn.axzo.tyr.server.permission;
import cn.axzo.tyr.client.model.permission.PermissionPointVO;
import cn.hutool.core.date.StopWatch;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
/**
* @version V1.0
* @author: ZhanSiHu