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/feign/TyrSaasRoleUserApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/TyrSaasRoleUserApi.java index 548fd6ec..5a290da0 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/TyrSaasRoleUserApi.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/TyrSaasRoleUserApi.java @@ -1,17 +1,19 @@ package cn.axzo.tyr.client.feign; +import java.util.List; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.tyr.client.model.roleuser.dto.CreateAdminRoleDTO; import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserRelationDTO; import cn.axzo.tyr.client.model.roleuser.dto.SuperAdminInfoDTO; import cn.axzo.tyr.client.model.roleuser.req.*; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; - -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; -import java.util.List; /** * 角色 @@ -63,12 +65,12 @@ public interface TyrSaasRoleUserApi { ApiResult createSuperAdminRole(@RequestBody @Valid @NotEmpty CreateSuperAdminRoleParam param); /** - * 移除超管角色 + * 移除用户权限,包含超管,一般用于移除超管权限 * @param params * @return */ - @PostMapping("/api/saas-role-user/delete-admin-role") - ApiResult deleteAdminRole(@RequestBody @Valid @NotEmpty List params); + @PostMapping("/api/saas-role-user/delete-user-role-include-admin") + ApiResult deleteUserRoleIncludeAdmin(@RequestBody @Valid @NotEmpty List params); /** * 批量查询超管, 只能批量获取单个工作台台下的超管,业务系统需要根据返回的identityId和identityType查询identityProfile查询用户明细信息 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-api/src/main/java/cn/axzo/tyr/client/model/roleuser/req/DeleteAdminRoleParam.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/req/DeleteUserRoleIncludeAdminParam.java similarity index 75% rename from tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/req/DeleteAdminRoleParam.java rename to tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/req/DeleteUserRoleIncludeAdminParam.java index a29c29dd..d65ac28d 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/req/DeleteAdminRoleParam.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/req/DeleteUserRoleIncludeAdminParam.java @@ -3,24 +3,30 @@ package cn.axzo.tyr.client.model.roleuser.req; import cn.axzo.tyr.client.model.enums.IdentityType; import lombok.Data; +import javax.validation.constraints.NotNull; + @Data -public class DeleteAdminRoleParam { +public class DeleteUserRoleIncludeAdminParam { /** * 工作台id,与context校验 */ + @NotNull private Long workspaceId; /** * 单位id : 非必填 */ + @NotNull private Long ouId; /** * 被赋予角色的人的身份id */ + @NotNull private Long identityId; /** * 身份类型,必填 */ + @NotNull private IdentityType identityType; } 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/controller/roleuser/RoleUserController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/roleuser/RoleUserController.java index cb781a2a..cdb1be21 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/roleuser/RoleUserController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/roleuser/RoleUserController.java @@ -67,8 +67,8 @@ public class RoleUserController implements TyrSaasRoleUserApi { } @Override - public ApiResult deleteAdminRole(List params) { - // todo cn.axzo.basics.auth.api.SaasRoleApi#ungrantAdminRole + public ApiResult deleteUserRoleIncludeAdmin(List params) { + saasRoleUserService.deleteUserRoleIncludeAdmin(params); return ApiResult.ok(true); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CMSRoleJobHandler.java b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CMSRoleJobHandler.java new file mode 100644 index 00000000..ade73159 --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CMSRoleJobHandler.java @@ -0,0 +1,225 @@ +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.client.common.enums.RoleTypeEnum; +import cn.axzo.tyr.server.repository.dao.*; +import cn.axzo.tyr.server.repository.entity.*; +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.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.stream.Collectors; + +/** + * CMS角色清洗job + * saas_pre_template + * 生产 项目 5 企业 23 + * pre 5 35 + * test 5 239 + * dev 5 40 + * @author cn + * @version 1.0 + * @description + * @date 2021/9/13 11:31 + */ +@Component +@AllArgsConstructor +@Slf4j +public class CMSRoleJobHandler extends IJobHandler { + + @Value("${saasPreTempalteIdOfProject") + Long saasPreTempalteIdOfProject; + + @Value("${saasPreTempalteIdOfOu") + Long saasPreTempalteIdOfOu; + + @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角色相关数据(注:先通过SQL检查和清除脏数据,要不然无法保证各个实体的关联关系) + * + * @param s + * @return + * @throws Exception + */ + @Transactional // 在一个事务里面做,一起提交 + @Override + @XxlJob("CMSRoleJobHandler") + public ReturnT execute(String s) throws Exception { + log.info("CMSRoleJobHandler start"); + buildProjectRole(saasPreTempalteIdOfProject,"2"); + buildOuRole(saasPreTempalteIdOfOu,"1"); + log.info("CMSRoleJobHandler end"); + return ReturnT.SUCCESS; + } + + private void buildProjectRole(Long templateId,String workspaceTypCode) { + // 根据模板id查询角色列表 + List role = saasPreRoleDao.lambdaQuery() + .in(SaasPreRole::getTemplateId, templateId) + .in(SaasPreRole::getFitOuTypeBit, Arrays.asList(1,2,4,8,16)) + .eq(BaseEntity::getIsDelete,0) + .list(); + // 根据单位类型遍历预制角色 + Map> preRoleMap = role.stream().collect(Collectors.groupingBy(SaasPreRole::getFitOuTypeBit)); + preRoleMap.forEach(new BiConsumer>() { + @Override + public void accept(Long ouTypeBit, List saasPreRoles) { + // 转换ouTypeBit -> ouType + Integer ouType = tranceOuTypeBit(ouTypeBit); + // 保存权限 + saveRole(saasPreRoles, workspaceTypCode, String.valueOf(ouType),OrganizationalUnitTypeEnum.getByType(ouType).getDesc()); + } + }); + } + + private void buildOuRole(Long templateId,String workspaceTypCode) { + // 根据模板id查询角色列表 + List role = saasPreRoleDao.lambdaQuery() + .in(SaasPreRole::getTemplateId, templateId) + .eq(SaasPreRole::getFitOuTypeBit, Arrays.asList(64)) + .eq(BaseEntity::getIsDelete,0) + .list(); + saveRole(role,workspaceTypCode,"1,2,3,4,5","企业通用"); + } + + /** + * 保存权限通用方法 + * @param saasPreRoles + * @param workspaceTypCode + * @param ouType + */ + private void saveRole(List saasPreRoles,String workspaceTypCode,String ouType,String groupName) { + // 创建角色分组 + SaasRoleGroup roleGroup = new SaasRoleGroup(); + roleGroup.setWorkspaceTypeCode(workspaceTypCode); + roleGroup.setOuTypeCode(ouType); + roleGroup.setName(groupName); + roleGroup.setWorkspaceId(-1l); + roleGroup.setOuId(-1l); + roleGroup.setSort(1); + roleGroupDao.save(roleGroup); + + saasPreRoles.forEach(preRole -> { + // 根据角色id查询角色权限集关联关系 + List pgroupRoleRelation = saasPreGroupRoleRelationDao.lambdaQuery() + .eq(SaasPreGroupRoleRelation::getPreRoleId, preRole.getId()) + .eq(BaseEntity::getIsDelete, 0) + .list(); + if (CollectionUtils.isEmpty(pgroupRoleRelation)) { + return; + } + List permissionGroup = saasPermissionGroupDao.lambdaQuery() + .in(BaseEntity::getId, pgroupRoleRelation.stream().map(SaasPreGroupRoleRelation::getGroupId).collect(Collectors.toList())) + .eq(BaseEntity::getIsDelete, 0) + .list(); + List pgroupPermissionRelation = pgroupPermissionRelationDao.lambdaQuery() + .in(SaasPgroupPermissionRelation::getGroupId, permissionGroup.stream().map(BaseEntity::getId).collect(Collectors.toList())) + .eq(BaseEntity::getIsDelete, 0) + .list(); + List feature = featureDao.lambdaQuery() + .in(BaseEntity::getId, pgroupPermissionRelation.stream().map(SaasPgroupPermissionRelation::getFeatureId).collect(Collectors.toList())) + .eq(BaseEntity::getIsDelete, 0) + .list(); + + // 创建新的权限集 + SaasPermissionGroup saasPermissionGroup = new SaasPermissionGroup(); + saasPermissionGroup.setName("通用权限"); + saasPermissionGroup.setDescription(""); + saasPermissionGroup.setCreateBy(-1L); + saasPermissionGroup.setUpdateBy(-1L); + saasPermissionGroup.setType("feature"); + saasPermissionGroup.setIsCommon(1); + saasPermissionGroupDao.save(saasPermissionGroup); + // 创建新的权限集权限关联关系 + feature.forEach(e -> { + SaasPgroupPermissionRelation saasPgroupPermissionRelation = new SaasPgroupPermissionRelation(); + saasPgroupPermissionRelation.setGroupId(saasPermissionGroup.getId()); + saasPgroupPermissionRelation.setFeatureId(e.getId()); + saasPgroupPermissionRelation.setCreateBy(-1L); + saasPgroupPermissionRelation.setUpdateBy(-1L); + pgroupPermissionRelationDao.save(saasPgroupPermissionRelation); + }); + + // 创建角色:根据预设角色创建新的角色 + SaasRole newRole = new SaasRole(); + newRole.setRoleType(RoleTypeEnum.INIT.getValue()); + newRole.setName(preRole.getName()); + newRole.setCreateBy(-1l); + newRole.setUpdateBy(-1l); + newRole.setOwnerOuId(-1l); + newRole.setWorkspaceId(-1l); + roleDao.save(newRole); + + // 创建新的角色权限集关联关系 + SaasPgroupRoleRelation saasPgroupRoleRelation = new SaasPgroupRoleRelation(); + saasPgroupRoleRelation.setRoleId(newRole.getId()); + saasPgroupRoleRelation.setGroupId(saasPermissionGroup.getId()); + saasPgroupRoleRelation.setCreateBy(-1L); + saasPgroupRoleRelation.setUpdateBy(-1L); + pgroupRoleRelationDao.save(saasPgroupRoleRelation); + + // 创建角色分组关联关系 + SaasRoleGroupRelation saasRoleGroupRelation = new SaasRoleGroupRelation(); + saasRoleGroupRelation.setRoleId(newRole.getId()); + saasRoleGroupRelation.setSaasRoleGroupId(roleGroup.getId()); + roleGroupRelationDao.save(saasRoleGroupRelation); + + // 更新用户关联关系表(根据老的fromRoleId更新至新roldId) + // 根据fromeRoleId查询老的roleId + // TODO zhaobudao fromRoleId的是自定义角色,不用管直接丢弃 + + + }); + } + + 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; + } + +} 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/SaasPreGroupRoleRelationDao.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPreGroupRoleRelationDao.java new file mode 100644 index 00000000..c3c480f1 --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPreGroupRoleRelationDao.java @@ -0,0 +1,14 @@ +package cn.axzo.tyr.server.repository.dao; + +import cn.axzo.tyr.server.repository.entity.SaasPreGroupRoleRelation; +import cn.axzo.tyr.server.repository.entity.SaasPreRole; +import cn.axzo.tyr.server.repository.mapper.SaasPreGroupRoleRelationMapper; +import cn.axzo.tyr.server.repository.mapper.SaasPreRoleMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Repository; + +@Repository +public class SaasPreGroupRoleRelationDao extends ServiceImpl { + +} + diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPreRoleDao.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPreRoleDao.java new file mode 100644 index 00000000..13c6667f --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPreRoleDao.java @@ -0,0 +1,12 @@ +package cn.axzo.tyr.server.repository.dao; + +import cn.axzo.tyr.server.repository.entity.SaasPreRole; +import cn.axzo.tyr.server.repository.mapper.SaasPreRoleMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Repository; + +@Repository +public class SaasPreRoleDao extends ServiceImpl { + +} + diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPreTemplateDao.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPreTemplateDao.java new file mode 100644 index 00000000..5ed3193a --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPreTemplateDao.java @@ -0,0 +1,12 @@ +package cn.axzo.tyr.server.repository.dao; + +import cn.axzo.tyr.server.repository.entity.SaasPreTemplate; +import cn.axzo.tyr.server.repository.mapper.SaasPreTemplateMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Repository; + +@Repository +public class SaasPreTemplateDao extends ServiceImpl { + +} + 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/entity/SaasPreGroupRoleRelation.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPreGroupRoleRelation.java new file mode 100644 index 00000000..e7710568 --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPreGroupRoleRelation.java @@ -0,0 +1,58 @@ +package cn.axzo.tyr.server.repository.entity; + +import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.io.Serializable; + +/** + * saas-模板角色资源关联表(SaasPreFatureRoleRelation)表实体类 + * + * @author makejava + * @since 2022-05-28 17:42:41 + */ +@Getter +@Setter +@ToString +@EqualsAndHashCode(callSuper = true) +@TableName("saas_pre_group_role_relation") +public class SaasPreGroupRoleRelation extends BaseEntity { + /** + * id + */ + + /** + * 角色Id + */ + private Long preRoleId; + /** + * 权限Id + */ + private Long groupId; + + /** + * 创建人id + */ + private Long createBy; + + /** + * 修改人id + */ + private Long updateBy; + + + /** + * 获取主键值 + * + * @return 主键值 + */ + @Override + protected Serializable pkVal() { + return this.id; + } +} + diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPreRole.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPreRole.java new file mode 100644 index 00000000..610f81a2 --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPreRole.java @@ -0,0 +1,65 @@ +package cn.axzo.tyr.server.repository.entity; + +import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.io.Serializable; +import java.util.List; + +/** + * saas-模板角色(SaasPreRole)表实体类 + * + * @author makejava + * @since 2022-05-28 17:42:41 + */ +@Getter +@Setter +@ToString +@EqualsAndHashCode(callSuper = true) +@TableName("saas_pre_role") +public class SaasPreRole extends BaseEntity { + + /** + * 角色名称 + */ + private String name; + /** + * 角色描述 + */ + private String description; + /** + * 角色类型:common 普通角色 super_admin超级管理员(禁止删除) admin子管理员(禁止删除) init初始化内置角色 + */ + private String roleType; + + /** + * 创建者 + */ + private Long createBy; + /** + * 更新者 + */ + private Long updateBy; + /** + * 模板Id + */ + private Long templateId; + /** + * 适用单位类型 1:总包 2:建设单位 4:监理单位 8:劳务分包 16:专业分包 0都可以用 只会挂在最末级 + */ + private Long fitOuTypeBit; + + /** + * 获取主键值 + * + * @return 主键值 + */ + @Override + protected Serializable pkVal() { + return this.id; + } +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPreTemplate.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPreTemplate.java new file mode 100644 index 00000000..f55a7d28 --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPreTemplate.java @@ -0,0 +1,58 @@ +package cn.axzo.tyr.server.repository.entity; + +import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.io.Serializable; + +/** + * saas-模板(SaasPreTemplate)表实体类 + * + * @author makejava + * @since 2022-05-28 17:42:40 + */ +@Getter +@Setter +@ToString +@EqualsAndHashCode(callSuper = true) +@TableName("saas_pre_template") +public class SaasPreTemplate extends BaseEntity { + + /** + * 角色名称 + */ + private String name; + /** + * 0:企业工作台 1:项目工作台 + */ + private Integer type; + /** + * 角色描述 + */ + private String description; + + /** + * 创建者 + */ + private Long createBy; + /** + * 更新者 + */ + private Long updateBy; + + + /** + * 获取主键值 + * + * @return 主键值 + */ + @Override + protected Serializable pkVal() { + return this.id; + } +} + 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/repository/mapper/SaasPreGroupRoleRelationMapper.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasPreGroupRoleRelationMapper.java new file mode 100644 index 00000000..9214065f --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasPreGroupRoleRelationMapper.java @@ -0,0 +1,11 @@ +package cn.axzo.tyr.server.repository.mapper; + +import cn.axzo.tyr.server.repository.entity.SaasPreGroupRoleRelation; +import cn.axzo.tyr.server.repository.entity.SaasPreRole; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + + +public interface SaasPreGroupRoleRelationMapper extends BaseMapper { + +} + diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasPreRoleMapper.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasPreRoleMapper.java new file mode 100644 index 00000000..26063bd3 --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasPreRoleMapper.java @@ -0,0 +1,10 @@ +package cn.axzo.tyr.server.repository.mapper; + +import cn.axzo.tyr.server.repository.entity.SaasPreRole; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + + +public interface SaasPreRoleMapper extends BaseMapper { + +} + diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasPreTemplateMapper.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasPreTemplateMapper.java new file mode 100644 index 00000000..b4f5f13d --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasPreTemplateMapper.java @@ -0,0 +1,10 @@ +package cn.axzo.tyr.server.repository.mapper; + +import cn.axzo.tyr.server.repository.entity.SaasPreTemplate; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + + +public interface SaasPreTemplateMapper extends BaseMapper { + +} + 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/SaasRoleUserService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasRoleUserService.java index 12bc37f0..e518c9b6 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasRoleUserService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasRoleUserService.java @@ -1,13 +1,13 @@ package cn.axzo.tyr.server.service; +import java.util.List; +import java.util.Set; + import cn.axzo.tyr.client.model.enums.IdentityType; import cn.axzo.tyr.client.model.roleuser.dto.SuperAdminInfoDTO; import cn.axzo.tyr.client.model.roleuser.req.*; import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation; -import java.util.List; -import java.util.Set; - /** * @author tanjie@axzo.cn * @date 2023/9/13 15:36 @@ -72,9 +72,9 @@ public interface SaasRoleUserService { List superAdminList(SuperAdminParam param); /** - * 移除管理员 + * 移除用户角色包含超管 * @param params * @return */ - boolean deleteAdminRole(List params); + boolean deleteUserRoleIncludeAdmin(List params); } \ No newline at end of file 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/RoleUserService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleUserService.java index a3bdeff9..8039ecd7 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleUserService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleUserService.java @@ -211,8 +211,25 @@ public class RoleUserService implements SaasRoleUserService { @Override @Transactional(rollbackFor = Exception.class) - public boolean deleteAdminRole(List params) { - - return false; + public boolean deleteUserRoleIncludeAdmin(List params) { + if (CollectionUtils.isEmpty(params)) { + return false; + } + params.forEach(param -> { + List roles = saasRoleDao.lambdaQuery() + .eq(SaasRole::getWorkspaceId, param.getWorkspaceId()).eq(SaasRole::getOwnerOuId, param.getOuId()).eq(SaasRole::getIsDelete, TableIsDeleteEnum.NORMAL.value).list(); + if (CollectionUtils.isEmpty(roles)) { + return; + } + List roleIds = roles.stream().map(SaasRole::getId).sorted().collect(Collectors.toList()); + List relations = roleUserRelationDao.lambdaQuery().in(SaasRoleUserRelation::getRoleId, roleIds) + .eq(SaasRoleUserRelation::getIdentityId, param.getIdentityId()).eq(SaasRoleUserRelation::getIdentityType, param.getIdentityType().getCode()) + .eq(SaasRoleUserRelation::getIsDelete, TableIsDeleteEnum.NORMAL.value).list(); + if (CollectionUtils.isNotEmpty(relations)) { + relations.forEach(r -> r.setIsDelete(r.getId())); + roleUserRelationDao.updateBatchById(relations); + } + }); + return true; } } 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/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