diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/ProductApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/ProductApi.java index 2a0faf78..c042e336 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/ProductApi.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/ProductApi.java @@ -111,6 +111,6 @@ public interface ProductApi { * @param workspaceIds * @return */ - @PostMapping("/temp") - ApiResult>> queryProductFeatureRelationByWorkspace(Set workspaceIds); + @PostMapping("api/auth/product/feature/query") + ApiResult>> queryProductFeatureRelationByWorkspace(@RequestBody Set workspaceIds); } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/TyrSaasAuthApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/TyrSaasAuthApi.java index 56247eaf..f006bc9d 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/TyrSaasAuthApi.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/TyrSaasAuthApi.java @@ -77,7 +77,7 @@ public interface TyrSaasAuthApi { * @param req * @return */ - @PostMapping("/api/v2/auth/listPermissionFromFeature") + @PostMapping("/api/v2/auth/listIdentityFromPermission") ApiResult> listIdentityFromPermissionV2(@RequestBody ListPermissionFromFeatureReq req); diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/TyrSaasFeatureApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/TyrSaasFeatureApi.java new file mode 100644 index 00000000..e0c32ff6 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/TyrSaasFeatureApi.java @@ -0,0 +1,20 @@ +package cn.axzo.tyr.client.feign; + +import cn.axzo.framework.domain.web.result.ApiResult; +import cn.axzo.tyr.client.model.req.FeaturePermissionReq; +import cn.axzo.tyr.client.model.res.FeaturePermissionRes; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +/** + * @author honghao.zhang + * @since 2023/10/18 18:29 + */ +@FeignClient(name = "tyr", url = "${axzo.service.tyr:http://tyr:8080}") +public interface TyrSaasFeatureApi { + + @PostMapping("/api/saasFeature/permission/codes") + ApiResult listPermissionCodes(@RequestBody @Validated FeaturePermissionReq req); +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/FeaturePermissionReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/FeaturePermissionReq.java new file mode 100644 index 00000000..fd143810 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/FeaturePermissionReq.java @@ -0,0 +1,47 @@ +package cn.axzo.tyr.client.model.req; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.FieldDefaults; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; + +/** + * @author honghao.zhang + * @since 2023/10/18 17:17 + */ +@Getter +@Setter +@ToString(callSuper = true) +@FieldDefaults(level = AccessLevel.PRIVATE) +public class FeaturePermissionReq { + + /** + * 工作台id + */ + @NotNull + @Min(value = 1) + Long workspaceId; + /** + * 单位id + */ + @NotNull + @Min(value = 1) + Long ouId; + + /** + * 指定端的权限 + */ + String terminal; + + @NotNull + @Min(value = 1) + Long identityId; + @NotNull + @Min(value = 0) + Integer identityType; + +} \ No newline at end of file diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/FeatureTreeReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/FeatureTreeReq.java new file mode 100644 index 00000000..f26a00e0 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/FeatureTreeReq.java @@ -0,0 +1,41 @@ +package cn.axzo.tyr.client.model.req; + +import lombok.Data; + +/** + * @author honghao.zhang + * @since 2023/10/18 17:50 + */ +@Data +public class FeatureTreeReq { + + /** + * 身份Id + */ + private Long identityId; + + private Integer identityType; + + /** + * 工作台Id + */ + private Long workspaceId; + + /** + * 单位Id + */ + private Long ouId; + + /** + * 指定端的权限 + */ + private String terminal; + + /** + * FeatureType: 类型 0.模块 1.菜单 2页面 3功能 + * 此字段=0,只返回模块,=1,返回到菜单级,=2,返回到页面级,=3,到功能级。 + * 此字段默认到功能级, (会做为递归的深度限制) + * ------ + */ + private Integer limitFeatureTypeLevel = 3; +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/FeaturePermissionRes.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/FeaturePermissionRes.java new file mode 100644 index 00000000..21467b5c --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/FeaturePermissionRes.java @@ -0,0 +1,23 @@ +package cn.axzo.tyr.client.model.res; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.FieldDefaults; + +import java.util.Set; + +/** + * @author honghao.zhang + * @since 2023/10/18 17:30 + */ +@Getter +@Setter +@ToString(callSuper = true) +@FieldDefaults(level = AccessLevel.PRIVATE) +public class FeaturePermissionRes { + + boolean superAdmin = false; + Set permissionCodes; +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/FeatureTreeResp.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/FeatureTreeResp.java new file mode 100644 index 00000000..3815d10b --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/FeatureTreeResp.java @@ -0,0 +1,159 @@ +package cn.axzo.tyr.client.model.res; + +import cn.axzo.basics.common.model.IBaseTree; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +import java.util.Date; +import java.util.List; + +/** + * @author honghao.zhang + * @since 2023/10/18 18:10 + */ +@Data +public class FeatureTreeResp implements IBaseTree { + + /** + * 元素 Id + */ + private Long id; + + /** + * 父级 Id + */ + private Long parentId; + + /** + * 0.模块 1.菜单 2页面 3功能 99:端-不可编辑 + */ + private Integer menuType; + + /** + * 元素名称 + */ + private String name; + /** + * code + */ + private String code; + + /** + * 图标名 + */ + private String icon; + /** + * 路由地址 + */ + private String linkUrl; + /** + * 1:安心筑企业 2:小程序 4:原生 如果菜单同时又对应app上展示 则填写对应linkUrl 和linkExt + */ + private Integer linkType; + /** + * 扩展字段 原生使用 + */ + private String linkExt; + + /** + * 排序号 + */ + private Integer sort; + + + /** + * 小程序id 关联micro_app_item id + */ + private String microAppItemId; + + /** + * 菜单适用于平台 NT_CMS_WEB_ENT_ZB:企业工作台 NT_CMS_WEB_PROJ:项目工作台 + * NT_CMP_APP_ENT_ZB:从业人员企业端 NT_CMP_APP_PROJ:从业人员项目端 + * NT_CM_APP_CM_LEADER:班组长侧 NT_CM_APP_WORKER:工人侧 + * NT_OMS_WEB OMS,运营管理后台 NT_SM:数据大屏 + * NT_SCREEN 数据大屏 + * */ + private String terminal; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createAt; + + /** + * 更新时间 + */ + private Date updateAt; + + /** + * 1:总包 2:建设单位 4:监理单位 8:劳务分包 16:专业分包 + */ + private List fitOuTypes; + + /** + * 1:部门 2:班组 4:小组 + */ + private List fitOuNodeTypes; + + /** + * 适配老接口 应用所属 system:系统应用 personal:个人应用 business:业务应用 只会挂在第一级别 + */ + private String legacyLayout; + + + /** + * 网关专属字段,所属应用 + */ + private String appName; + /** + * 网关专属字段,是否授权 0:无需要授权 1:需要授权 + */ + private Integer needAuth; + + /** + * 网关专属字段,是否认证 0:无需要认证 1:需要认证 + */ + private Integer needCert; + + /** + * 网关专属字段 ,功能URL,对应后端接口url + */ + private String featureUrl; + + /** + * 子集 + */ + private List children; + + private String businessNo; + + private String parentBusinessNo; + + @Override + @JsonIgnore + public String getNodeCode() { + return businessNo; + } + + @Override + @JsonIgnore + public String getParentNodeCode() { + return parentBusinessNo; + } + + @Override + @JsonIgnore + public List getNodeChildren() { + return children; + } + + @Override + public void setNodeChildren(List nodeChildren) { + this.children = nodeChildren; + } +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/auth/TyrSaasAuthController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/auth/TyrSaasAuthController.java index 4c5c1dcf..2ff3bd76 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/auth/TyrSaasAuthController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/auth/TyrSaasAuthController.java @@ -49,14 +49,12 @@ public class TyrSaasAuthController implements TyrSaasAuthApi { @Override public ApiResult hasPermissionForIdentityV2(CheckIdentityPermissionReq req) { - //TODO:@Zhan - return null; + return ApiResult.ok(tyrSaasAuthService.hasPermissionForIdentityV2(req)); } @Override public ApiResult> listIdentityFromPermissionV2(ListPermissionFromFeatureReq req) { - //TODO:@Zhan - return null; + return ApiResult.ok(tyrSaasAuthService.listIdentityFromPermissionV2(req)); } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/TyrSaasFeatureController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/TyrSaasFeatureController.java new file mode 100644 index 00000000..c39d2ef0 --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/TyrSaasFeatureController.java @@ -0,0 +1,27 @@ +package cn.axzo.tyr.server.controller.permission; + +import cn.axzo.framework.domain.web.result.ApiResult; +import cn.axzo.tyr.client.feign.TyrSaasFeatureApi; +import cn.axzo.tyr.client.model.req.FeaturePermissionReq; +import cn.axzo.tyr.client.model.res.FeaturePermissionRes; +import cn.axzo.tyr.server.service.SaasFeatureService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author honghao.zhang + * @since 2023/10/18 18:30 + */ +@Slf4j +@RestController +@RequiredArgsConstructor +public class TyrSaasFeatureController implements TyrSaasFeatureApi { + + private final SaasFeatureService saasFeatureService; + + @Override + public ApiResult listPermissionCodes(FeaturePermissionReq req) { + return ApiResult.ok(saasFeatureService.listPermissionCodes(req)); + } +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasFeatureDao.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasFeatureDao.java index bfe031a1..d0d6b79d 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasFeatureDao.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasFeatureDao.java @@ -1,5 +1,6 @@ package cn.axzo.tyr.server.repository.dao; +import cn.axzo.tyr.client.model.req.FeatureTreeReq; import cn.axzo.tyr.server.repository.entity.SaasFeature; import com.baomidou.mybatisplus.extension.service.IService; @@ -24,4 +25,11 @@ public interface SaasFeatureDao extends IService { List listLikePath(String path); List listByParentIdAndTerminal(Long parentId, String terminal); + + List listFeatureByTerminal(String terminal); + + List listCodeByProductIds(FeatureTreeReq req, List productIds); + + List listByProductIdsAndTerminal(List productIds, String terminal); + } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/impl/SaasFeatureDaoImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/impl/SaasFeatureDaoImpl.java index 48791cd3..0bf47fdc 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/impl/SaasFeatureDaoImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/impl/SaasFeatureDaoImpl.java @@ -1,11 +1,13 @@ package cn.axzo.tyr.server.repository.dao.impl; +import cn.axzo.tyr.client.model.req.FeatureTreeReq; import cn.axzo.tyr.server.repository.entity.SaasFeature; import cn.axzo.tyr.server.repository.mapper.SaasFeatureMapper; import cn.axzo.tyr.server.repository.dao.SaasFeatureDao; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import java.util.List; @@ -47,4 +49,19 @@ public class SaasFeatureDaoImpl extends ServiceImpl listFeatureByTerminal(String terminal) { + return lambdaQuery().eq(StringUtils.isNotEmpty(terminal), SaasFeature::getTerminal, terminal).list(); + } + + @Override + public List listCodeByProductIds(FeatureTreeReq req, List productIds) { + return this.baseMapper.listCodeByProductIds(req, productIds); + } + + @Override + public List listByProductIdsAndTerminal(List productIds, String terminal) { + return this.baseMapper.listCodeByProductIdsAndTerminal(productIds, terminal); + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasFeatureMapper.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasFeatureMapper.java index c5f38ccb..75c8a225 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasFeatureMapper.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasFeatureMapper.java @@ -1,9 +1,13 @@ package cn.axzo.tyr.server.repository.mapper; +import cn.axzo.tyr.client.model.req.FeatureTreeReq; import cn.axzo.tyr.server.repository.entity.SaasFeature; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Update; +import java.util.List; + /** *

* Mapper 接口 @@ -18,4 +22,8 @@ public interface SaasFeatureMapper extends BaseMapper { "SET path = REPLACE(path,#{pathPrefix}, #{newPathPrefix}) , update_by = #{updater} " + "WHERE path LIKE CONCAT(#{pathPrefix},'%') ") void updateChildrenPath(Long updater, String pathPrefix, String newPathPrefix); + + List listCodeByProductIds(@Param("req") FeatureTreeReq req, @Param("productIds") List productIds); + + List listCodeByProductIdsAndTerminal(@Param("productIds") List productIds, @Param("terminal") String terminal); } \ No newline at end of file diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/RoleService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/RoleService.java index 6349ecb2..e883805c 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/RoleService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/RoleService.java @@ -60,6 +60,15 @@ public interface RoleService { * @return */ List findRoleByName(QueryRoleByNameReq req); + /** 分页查询角色含用户 **/ PageResp queryRoleWithUser(RoleWithUserQueryReq req); + + /** + * 通过角色类型获取角色 + * @param req + * @param roleTypes + * @return + */ + List queryRoleByRoleTypes(QueryByIdentityIdTypeReq req, List roleTypes); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasFeatureService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasFeatureService.java new file mode 100644 index 00000000..960381ef --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasFeatureService.java @@ -0,0 +1,13 @@ +package cn.axzo.tyr.server.service; + +import cn.axzo.tyr.client.model.req.FeaturePermissionReq; +import cn.axzo.tyr.client.model.res.FeaturePermissionRes; + +/** + * @author honghao.zhang + * @since 2023/10/18 18:25 + */ +public interface SaasFeatureService { + + FeaturePermissionRes listPermissionCodes(FeaturePermissionReq req); +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/TyrSaasAuthService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/TyrSaasAuthService.java index 8ca641b7..4da38b6d 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/TyrSaasAuthService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/TyrSaasAuthService.java @@ -31,4 +31,7 @@ public interface TyrSaasAuthService { */ IdentityAuthRes findIdentityAuth(IdentityAuthReq identityAuthReq); + boolean hasPermissionForIdentityV2(CheckIdentityPermissionReq req); + + List listIdentityFromPermissionV2(ListPermissionFromFeatureReq req); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleServiceImpl.java index 3d5d0ca3..e8d87f49 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleServiceImpl.java @@ -493,6 +493,20 @@ public class RoleServiceImpl implements RoleService { return PageResp.list(req.getPage(), req.getPageSize(), rolePage.getTotal(), resultData); } + @Override + public List queryRoleByRoleTypes(QueryByIdentityIdTypeReq req, List roleTypes) { + List roleIds = roleUserRelationDao.query(req.getIdentityId(), req.getIdentityType(), + req.getWorkspaceId(), req.getOuId()).stream().map(SaasRoleUserRelation::getRoleId).collect(Collectors.toList()); + List list = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(roleIds)) { + list = saasRoleDao.lambdaQuery() + .in(BaseEntity::getId, roleIds) + .in(SaasRole::getRoleType, roleTypes) + .list(); + } + return BeanUtil.copyToList(list, SaasRoleVO.class); + } + @Override public List findRoleByName(QueryRoleByNameReq req) { List roleList = saasRoleDao.findRoleByName(req.getOuId(), req.getWorkspaceId(), req.getRoleNames()); diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureServiceImpl.java new file mode 100644 index 00000000..d4f88f1f --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureServiceImpl.java @@ -0,0 +1,202 @@ +package cn.axzo.tyr.server.service.impl; + +import cn.axzo.framework.domain.ServiceException; +import cn.axzo.thrones.client.saas.ServicePkgClient; +import cn.axzo.thrones.client.saas.entity.serivicepgkproduct.ServicePkgProduct; +import cn.axzo.tyr.client.common.enums.RoleTypeEnum; +import cn.axzo.tyr.client.model.req.FeaturePermissionReq; +import cn.axzo.tyr.client.model.req.FeatureTreeReq; +import cn.axzo.tyr.client.model.req.QueryByIdentityIdTypeReq; +import cn.axzo.tyr.client.model.res.FeaturePermissionRes; +import cn.axzo.tyr.client.model.res.FeatureTreeResp; +import cn.axzo.tyr.client.model.vo.SaasRoleVO; +import cn.axzo.tyr.server.repository.dao.SaasFeatureDao; +import cn.axzo.tyr.server.repository.entity.SaasFeature; +import cn.axzo.tyr.server.service.RoleService; +import cn.axzo.tyr.server.service.SaasFeatureService; +import cn.axzo.tyr.server.util.IdPathUtil; +import cn.azxo.framework.common.logger.MethodAroundLog; +import cn.azxo.framework.common.model.CommonResponse; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; +import com.google.common.collect.Lists; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static cn.axzo.tyr.server.util.RpcInternalUtil.checkAndGetData; + +/** + * @author honghao.zhang + * @since 2023/10/18 18:26 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class SaasFeatureServiceImpl implements SaasFeatureService { + + private final RoleService roleService; + private final ServicePkgClient servicePkgClient; + private final SaasFeatureDao saasFeatureDao; + + @Override + public FeaturePermissionRes listPermissionCodes(FeaturePermissionReq req) { + FeaturePermissionRes featurePermissionRes = new FeaturePermissionRes(); + QueryByIdentityIdTypeReq idTypeReq = QueryByIdentityIdTypeReq.builder() + .identityId(req.getIdentityId()).identityType(req.getIdentityType()) + .ouId(req.getOuId()).workspaceId(req.getWorkspaceId()) + .build(); + List saasRoleVOS = roleService.queryRoleByRoleTypes(idTypeReq, Lists.newArrayList(RoleTypeEnum.SUPER_ADMIN.getValue(), + RoleTypeEnum.ADMIN.getValue())); + featurePermissionRes.setSuperAdmin(saasRoleVOS.stream().anyMatch(e -> RoleTypeEnum.SUPER_ADMIN.getValue().equals(e.getRoleType()))); + FeatureTreeReq featureTreeReq = new FeatureTreeReq(); + featureTreeReq.setIdentityId(req.getIdentityId()); + featureTreeReq.setIdentityType(req.getIdentityType()); + featureTreeReq.setWorkspaceId(req.getWorkspaceId()); + featureTreeReq.setOuId(req.getOuId()); + featureTreeReq.setTerminal(req.getTerminal()); + + List saasFeatureTreeResp = filterFeatureTree(featureTreeReq, !saasRoleVOS.isEmpty()); + Map> treeMap = groupByMenuType( + saasFeatureTreeResp, 20); + featurePermissionRes.setPermissionCodes(treeMap.getOrDefault(3, Collections.emptyList()).stream().map(FeatureTreeResp::getCode) + .collect(Collectors.toSet())); + return featurePermissionRes; + } + + @MethodAroundLog(value = "获取权限集树") + private List filterFeatureTree(FeatureTreeReq req, boolean isAdmin) { + // 1. 根据这个用户的角色,找到对应的code,Admin/Common各自的拿法。 + List minFeatureCode = listFeatureCode(req, isAdmin); + + log.info("产品对应的最小权限集:{}", minFeatureCode); + // 因为只能查出来最小功能FeatureCode,所以在递归查询出其上级. + List allFeature = saasFeatureDao.listFeatureByTerminal(req.getTerminal()); + List featureTree = constructFeatureByMinFeatureCode(minFeatureCode, allFeature + ); + + // 2. 组织成一棵树 + return formatToTreeAndSort(featureTree, req.getLimitFeatureTypeLevel()); + } + + private List formatToTreeAndSort(List featureTree, Integer level) { + List roots = new ArrayList<>(); + Map map = new LinkedHashMap<>(); + + for (SaasFeature feature : featureTree) { + if (feature.getFeatureType() > level) + continue; + FeatureTreeResp resp = featureBOToResp(feature); + map.put(feature.getId(), resp); + if (feature.getFeatureType() == 0 || feature.getParentId() == 0) { + roots.add(resp); + } + } + + for (FeatureTreeResp feature : map.values()) { + FeatureTreeResp parent = map.get(feature.getParentId()); + if (null == parent) { + continue; + } + if (parent.getChildren() == null) + parent.setChildren(new ArrayList<>()); + parent.getChildren().add(feature); + } + return roots; + } + + private FeatureTreeResp featureBOToResp(SaasFeature feature) { + FeatureTreeResp resp = new FeatureTreeResp(); + BeanUtil.copyProperties(feature, resp); + resp.setName(feature.getFeatureName()); + resp.setCode(feature.getFeatureCode()); + resp.setMenuType(feature.getFeatureType()); + return resp; + } + + private List constructFeatureByMinFeatureCode(List minFeatureCode, List allFeature) { + List result = new ArrayList<>(); + Map featureMap = allFeature.stream() + .collect(Collectors.toMap(SaasFeature::getId, Function.identity())); + if (!CollectionUtils.isEmpty(minFeatureCode)) { + List minFeature = allFeature.stream() + .filter(e -> org.apache.commons.lang3.StringUtils.isNotBlank(e.getFeatureCode()) + && minFeatureCode.contains(e.getFeatureCode())).collect(Collectors.toList()); + result.addAll(minFeature); + Set collect = minFeature.stream().map(SaasFeature::getPath) + .collect(Collectors.toSet()); + Set longs = IdPathUtil.featurePathsToIds(collect); + for (Long aLong : longs) { + SaasFeature saasFeatureBO = featureMap.get(aLong); + if (saasFeatureBO != null) { + result.add(saasFeatureBO); + } + } + } + return getFeatureBOS(result); + } + + private ArrayList getFeatureBOS(List result) { + return result.stream() + .collect(Collectors.collectingAndThen( + Collectors.toCollection( + () -> new TreeSet<>(Comparator.comparing(SaasFeature::getId))), + ArrayList::new)); + } + + private List listFeatureCode(FeatureTreeReq req, boolean isAdmin) { + List productIds = getProductIdsOfWorkspace(req.getWorkspaceId()); + if (isAdmin) { + return listCodeByProductIdsAndTerminal(productIds, req.getTerminal()); + } + return listCodeByProductIds(req, productIds); + } + + private List listCodeByProductIds(FeatureTreeReq req, List productIds) { + return saasFeatureDao.listCodeByProductIds(req, productIds); + } + + private List listCodeByProductIdsAndTerminal(List productIds, String terminal) { + return saasFeatureDao.listByProductIdsAndTerminal(productIds, terminal); + } + + private Map> groupByMenuType(List saasFeatureTree, Integer maxDepth) { + HashMap> result = new HashMap<>(); + if (CollectionUtil.isEmpty(saasFeatureTree) || maxDepth <= 0) { + return result; + } + for (FeatureTreeResp featureTreeResp : saasFeatureTree) { + + List defaultLists = result.getOrDefault(featureTreeResp.getMenuType(), new ArrayList<>()); + if (defaultLists.isEmpty()) { + result.put(featureTreeResp.getMenuType(), defaultLists); + } + defaultLists.add(featureTreeResp); + Map> children = groupByMenuType(featureTreeResp.getChildren(), --maxDepth); + for (Integer childrenKey : children.keySet()) { + List childList = result.getOrDefault(childrenKey, new ArrayList<>()); + if (childList.isEmpty()) { + result.put(childrenKey, childList); + } + childList.addAll(children.get(childrenKey)); + + } + } + return result; + } + + public List getProductIdsOfWorkspace(Long workspaceId) { + CommonResponse> servicePkgResponse = servicePkgClient.listProductInWorkSpace(workspaceId); + List products = checkAndGetData(servicePkgResponse); + if (CollectionUtil.isEmpty(products)) { + log.warn("thrones:获取产品列表失败:workspaceId{}", workspaceId); + throw new ServiceException("当前工作台未找到任何的产品"); + } + return products.stream().map(ServicePkgProduct::getProductId).collect(Collectors.toList()); + } +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/TyrSaasAuthServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/TyrSaasAuthServiceImpl.java index 307e7045..28d1c47c 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/TyrSaasAuthServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/TyrSaasAuthServiceImpl.java @@ -52,6 +52,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -499,6 +500,35 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService { return result; } + @Override + public boolean hasPermissionForIdentityV2(CheckIdentityPermissionReq req) { + if (CollectionUtil.isEmpty(req.getCodes())) { + return true; + } + IdentityAuthReq request = new IdentityAuthReq(); + request.setIdentityId(req.getIdentityId()); + request.setIdentityType(req.getIdentityType()); + if (StrUtil.isNotBlank(req.getTerminal())) { + request.setTerminal(Collections.singletonList(req.getTerminal())); + } + IdentityAuthRes authRes = this.findIdentityAuth(request); + HashSet codeSet = new HashSet<>(req.getCodes()); + //比较code + return authRes.getPermissions().stream() + .anyMatch(e -> e.getPermissionPoint() + .stream() + .anyMatch(p -> codeSet.contains(p.getFeatureCode()))); + } + + @Override + public List listIdentityFromPermissionV2(ListPermissionFromFeatureReq req) { + //TODO:@Zhan + //超管 - 保持原逻辑 + //非超管 权限code+terminal -> feature -> 权限集 -> 例外权限集作用范围过滤 --> 权限集角色-角色组匹配OU类型资质(OU参建单位) + //免授权型 - 没有意义 + return null; + } + @Data public static class UserRoleInfoMap { diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/util/IdPathUtil.java b/tyr-server/src/main/java/cn/axzo/tyr/server/util/IdPathUtil.java new file mode 100644 index 00000000..249b733d --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/util/IdPathUtil.java @@ -0,0 +1,33 @@ +package cn.axzo.tyr.server.util; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class IdPathUtil { + + private static final String PATH_SPLIT = "/"; + + public static Set featurePathsToIds(Set paths) { + if (CollectionUtils.isEmpty(paths)) { + return Collections.emptySet(); + } + return paths.stream().map(e -> { + String[] split = e.split(PATH_SPLIT); + return Arrays.stream(split).filter(StringUtils::hasText).map(Long::parseLong) + .collect(Collectors.toSet()); + }).reduce(new HashSet<>(), (a, b) -> { + a.addAll(b); + return a; + }); + } + +} diff --git a/tyr-server/src/main/resources/mapper/SaasFeatureMapper.xml b/tyr-server/src/main/resources/mapper/SaasFeatureMapper.xml new file mode 100644 index 00000000..0b97e0cc --- /dev/null +++ b/tyr-server/src/main/resources/mapper/SaasFeatureMapper.xml @@ -0,0 +1,56 @@ + + + + + + + + + \ No newline at end of file