diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/AttrPermissionEnum.java b/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/AttrPermissionEnum.java index 2df34aed..3144b4ba 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/AttrPermissionEnum.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/AttrPermissionEnum.java @@ -15,7 +15,7 @@ public enum AttrPermissionEnum { DEPARTMENT_SUBORDINATE(4, "本部门及以下数据"), - UNIT_ONLY(5, "仅本单位数据"), + UNIT_ONLY(5, "仅本单位数据(包含班组)"), UNIT_DIRECT_SUBORDINATE(6, "本单位及下级直属单位数据"), @@ -24,6 +24,8 @@ public enum AttrPermissionEnum { UNIT_ALL_SUBORDINATE(8, "本单位及以下协同(直属+合作)单位数据"), WORKSPACE(9, "本项目数据"), EQUAL_TO_ROW(10, "同行级数据权限"), + + UNIT_ONLY_EXCLUDE_TEAM(11, "仅本单位数据(不包含班组)"), ; private final Integer value; private final String desc; @@ -34,6 +36,6 @@ public enum AttrPermissionEnum { public static List listAttrPermissionForNotWorkspace() { return Lists.newArrayList(SELF_ONLY, SELF_SUBORDINATE, - DEPARTMENT_ONLY, DEPARTMENT_SUBORDINATE, UNIT_ONLY, EQUAL_TO_ROW); + DEPARTMENT_ONLY, DEPARTMENT_SUBORDINATE, UNIT_ONLY, UNIT_ONLY_EXCLUDE_TEAM, EQUAL_TO_ROW); } } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PermissionRelationOperateLogSceneEnum.java b/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PermissionRelationOperateLogSceneEnum.java index d66d6b02..420bb7ad 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PermissionRelationOperateLogSceneEnum.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/PermissionRelationOperateLogSceneEnum.java @@ -28,6 +28,11 @@ public enum PermissionRelationOperateLogSceneEnum { */ OMS_ROLE_BIND_FEATURE_RESOURCE("OMS_ROLE_BIND_FEATURE_RESOURCE", "oms后台更新角色绑定的资源"), + /** + * [老]oms后台更新角色绑定资源绑定的 + */ + OLD_OMS_ROLE_BIND_FEATURE("OLD_OMS_ROLE_BIND_FEATURE", "[老]oms后台更新角色绑定的资源"), + /** * oms后台更新资源绑定的页面元素 */ @@ -38,6 +43,36 @@ public enum PermissionRelationOperateLogSceneEnum { */ OMS_PRODUCT_BIND_FEATURE_RESOURCE("OMS_PRODUCT_BIND_FEATURE_RESOURCE", "oms后台更新产品榜的资源"), + /** + * [老]oms后台更新产品权限点 + */ + OLD_OMS_PRODUCT__UPDATE("OLD_OMS_PRODUCT__UPDATE", "[老]oms后台更新产品"), + + /** + * [老]oms后台更新产品权限点 + */ + OLD_OMS_PRODUCT_PERMISSION_POINT__SAVE_BATCH("OLD_OMS_PRODUCT_PERMISSION_POINT__SAVE_BATCH", "[老]oms后台更新产品权限点"), + + /** + * [老]角色分组新增/更新 + */ + OLD_OMS_ROLE_GROUP__SAVE_OR_UPDATE("OLD_OMS_ROLE_GROUP__SAVE_OR_UPDATE", "[老]角色分组新增/更新"), + + /** + * [老]角色分组删除 + */ + OLD_OMS_ROLE_GROUP__DELETE("OLD_OMS_ROLE_GROUP__DELETE", "[老]角色分组删除"), + + /** + * [老]权限点删除 + */ + OLD_OMS_SAAS_FEATURE__DELETE("OLD_OMS_SAAS_FEATURE__DELETE", "[老]权限点删除"), + + /** + * [老]权限点新增/更新 + */ + OLD_OMS_SAAS_FEATURE__SAVE_OR_UPDATE("OLD_OMS_SAAS_FEATURE__SAVE_OR_UPDATE", "[老]权限点新增/更新"), + /** * oms后台添加API */ diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/RowPermissionEnum.java b/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/RowPermissionEnum.java index 483175d7..729eb70f 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/RowPermissionEnum.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/common/enums/RowPermissionEnum.java @@ -18,14 +18,16 @@ public enum RowPermissionEnum { DEPARTMENT_SUBORDINATE(4, "本部门及以下数据"), - UNIT_ONLY(5, "仅本单位数据"), + UNIT_ONLY(5, "仅本单位数据(包含班组)"), UNIT_DIRECT_SUBORDINATE(6, "本单位及下级直属单位数据"), UNIT_COOPERATE_SUBORDINATE(7, "本单位及下级协同(直属+合作)单位数据"), UNIT_ALL_SUBORDINATE(8, "本单位及以下协同(直属+合作)单位数据"), - WORKSPACE(9, "本项目数据"), + WORKSPACE(9, "本项目部数据"), + + UNIT_ONLY_EXCLUDE_TEAM(10, "仅本单位数据(不包含班组)"), ; @@ -41,7 +43,7 @@ public enum RowPermissionEnum { public static List listRowPermissionForNotWorkspace() { return Lists.newArrayList(SELF_ONLY, SELF_SUBORDINATE, - DEPARTMENT_ONLY, DEPARTMENT_SUBORDINATE, UNIT_ONLY); + DEPARTMENT_ONLY, DEPARTMENT_SUBORDINATE, UNIT_ONLY, UNIT_ONLY_EXCLUDE_TEAM); } } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/DataObjectApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/DataObjectApi.java index fcf9572f..f6f07c1e 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/DataObjectApi.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/DataObjectApi.java @@ -2,11 +2,7 @@ package cn.axzo.tyr.client.feign; import cn.axzo.basics.common.page.PageResult; import cn.axzo.framework.domain.web.result.ApiResult; -import cn.axzo.tyr.client.common.annotation.RepeatedSubmit; -import cn.axzo.tyr.client.model.req.CreateDataObjectReq; -import cn.axzo.tyr.client.model.req.DeleteDataObjectReq; -import cn.axzo.tyr.client.model.req.EditDataObjectReq; -import cn.axzo.tyr.client.model.req.PageDataObjectReq; +import cn.axzo.tyr.client.model.req.*; import cn.axzo.tyr.client.model.res.DataObjectRes; import cn.axzo.tyr.client.model.res.EnumRes; import cn.axzo.tyr.client.model.res.SimpleDataObjectRes; @@ -28,7 +24,6 @@ public interface DataObjectApi { @PostMapping("/api/dataObject/create") ApiResult createDataObject(@RequestBody @Valid CreateDataObjectReq req); - /** * 修改数据对象 * @param req @@ -63,4 +58,12 @@ public interface DataObjectApi { */ @GetMapping("/api/dataObject/get") ApiResult getDataObject(@RequestParam Long dataObjectId); + + /** + * 根据租户范围、数据对象code查询数据对象 + * @param req + * @return + */ + @PostMapping("/api/dataObject/query") + ApiResult queryDataObject(@RequestBody @Valid QueryDataObjectReq req); } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PermissionPointApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PermissionPointApi.java index 3e5e6cc3..e2b5a5be 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PermissionPointApi.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/PermissionPointApi.java @@ -1,6 +1,7 @@ package cn.axzo.tyr.client.feign; import cn.axzo.framework.domain.web.result.ApiResult; +import cn.axzo.tyr.client.model.permission.DeletePermissionPointRequest; import cn.axzo.tyr.client.model.permission.PermissionPointDTO; import cn.axzo.tyr.client.model.permission.PermissionPointListQueryRequest; import cn.axzo.tyr.client.model.permission.PermissionPointMoveRequest; @@ -16,6 +17,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; +import javax.validation.Valid; import java.util.List; /** @@ -48,6 +50,10 @@ public interface PermissionPointApi { @PostMapping(value = "/api/v1/permissionPoint/delete/{permissionId}") ApiResult> deletePermissionPoint(@PathVariable Long permissionId); + /** 删除权限点 **/ + @PostMapping(value = "/api/v1/permissionPoint/delete/v2/deletePermissionPoint") + ApiResult> deletePermissionPointV2(@Valid @RequestBody DeletePermissionPointRequest request); + /** 位置移动 **/ @PostMapping(value = "/api/v1/permissionPoint/move") 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 b9923753..e32682ea 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 @@ -2,7 +2,16 @@ package cn.axzo.tyr.client.feign; import cn.axzo.framework.domain.web.result.ApiPageResult; import cn.axzo.framework.domain.web.result.ApiResult; -import cn.axzo.tyr.client.model.product.*; +import cn.axzo.tyr.client.model.product.OldUpdateFeatureRelationRequestV2; +import cn.axzo.tyr.client.model.product.ProductAddReq; +import cn.axzo.tyr.client.model.product.ProductDetailReq; +import cn.axzo.tyr.client.model.product.ProductFeatureRelationSearchReq; +import cn.axzo.tyr.client.model.product.ProductFeatureRelationUpdateReq; +import cn.axzo.tyr.client.model.product.ProductFeatureRelationVO; +import cn.axzo.tyr.client.model.product.ProductSearchListReq; +import cn.axzo.tyr.client.model.product.ProductSearchPageReq; +import cn.axzo.tyr.client.model.product.ProductUpdateReq; +import cn.axzo.tyr.client.model.product.ProductVO; import cn.axzo.tyr.client.model.req.ProductSaveReq; import cn.axzo.tyr.client.model.req.UpdateProductStatusReq; import cn.axzo.tyr.client.model.res.GovernmentTerminalResp; @@ -102,6 +111,16 @@ public interface ProductApi { @PostMapping("api/auth/product/feature/relation/update") ApiResult updateFeatureRelation(@Validated @RequestBody List req); + /** + * 更新产品与权限点的关联关系 + *

携带操作人员信息 + * + * @param req {@link ProductFeatureRelationUpdateReq} + * @return + */ + @PostMapping("api/auth/product/feature/relation/v2/update") + ApiResult updateFeatureRelationV2(@Validated @RequestBody OldUpdateFeatureRelationRequestV2 req); + /** * 查询指定工作台关联的服务包下的产品权限点 * diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/SaasRoleGroupApi.java b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/SaasRoleGroupApi.java index 69882603..c8f029f9 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/feign/SaasRoleGroupApi.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/feign/SaasRoleGroupApi.java @@ -5,6 +5,7 @@ import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.tyr.client.model.req.ListSaasRoleGroupParam; import cn.axzo.tyr.client.model.req.PageSaasRoleGroupParam; import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq; +import cn.axzo.tyr.client.model.req.SaasRoleGroupDeleteRequest; import cn.axzo.tyr.client.model.req.UpdateRoleGroupOffsetReq; import cn.axzo.tyr.client.model.res.SaasRoleGroupDTO; import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO; @@ -57,6 +58,14 @@ public interface SaasRoleGroupApi { @PostMapping("/api/saasRoleGroup/delete") ApiResult delete(@RequestParam @NotEmpty List ids); + /** + * 删除角色分组 + * @param request 角色分组ID + * @return 返回删除角色分组状态 + */ + @PostMapping("/api/saasRoleGroup/v2/delete") + ApiResult deleteV2(@RequestBody @Valid SaasRoleGroupDeleteRequest request); + /** * * 通过categoryCode查询分组 diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/data/object/AttributePermissionBO.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/data/object/AttributePermissionBO.java index 775a8c82..fe04cf30 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/data/object/AttributePermissionBO.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/data/object/AttributePermissionBO.java @@ -15,7 +15,7 @@ public class AttributePermissionBO { private Integer sort; // 序号 private String attrName; //字段名 private String attrCode; // 字段code - private Integer visibilityScope; // 字段值查看范围 1:仅本人数据 2:本人及下属数据 3:仅本部门数据 4:本部门及以下数据 5:仅本单位数据 6:本单位及下级直属单位数据 7:本单位及下级协同(直属+合作)单位数据 8:本单位及以下协同(直属+合作)单位数据 9:本项目数据 10:同行级数据权限 + private Integer visibilityScope; // 字段值查看范围 1:仅本人数据 2:本人及下属数据 3:仅本部门数据 4:本部门及以下数据 5:仅本单位数据(包含班组) 6:本单位及下级直属单位数据 7:本单位及下级协同(直属+合作)单位数据 8:本单位及以下协同(直属+合作)单位数据 9:本项目部数据 10:同行级数据权限 11:仅本单位数据(不包含班组) private Integer isUnmaskable; // 是否可脱敏 1-不可操作脱敏 2-可操作脱敏 private Integer isEditable; // 是否可编辑 1-不可编辑 2-可编辑 } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/data/object/DataObjectRuleBO.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/data/object/DataObjectRuleBO.java index 69267443..1688ebc9 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/data/object/DataObjectRuleBO.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/data/object/DataObjectRuleBO.java @@ -39,10 +39,19 @@ public class DataObjectRuleBO { * 岗位/角色id */ private List relationId; + /** + * 岗位code + */ + private List relationCodes; + /** + * 岗位列表 + */ + private List jobs; /** * 行级数据权限(单选) 1:仅本人数据 2:本人及下属数据 3:仅本部门数据 4:本部门及以下数据 - * 5:仅本单位数据 6:本单位及下级直属单位数据 7:本单位及下级协同(直属+合作)单位数据 8:本单位及以下协同(直属+合作)单位数据 9:本项目数据 + * 5:仅本单位数据(包含班组) 6:本单位及下级直属单位数据 7:本单位及下级协同(直属+合作)单位数据 8:本单位及以下协同(直属+合作)单位数据 + * 9:本项目部数据 10:仅本单位数据(不包含班组) */ private Integer rowPermission; /** @@ -50,4 +59,12 @@ public class DataObjectRuleBO { */ private List attributePermissionBOList; + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class JobInfo{ + private Long id; + private String code; + } } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/DeletePermissionPointRequest.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/DeletePermissionPointRequest.java new file mode 100644 index 00000000..a24a28da --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/DeletePermissionPointRequest.java @@ -0,0 +1,19 @@ +package cn.axzo.tyr.client.model.permission; + +import cn.axzo.tyr.client.model.vo.OperatorRequest; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotNull; + +/** + * @author yanglin + */ +@Setter +@Getter +public class DeletePermissionPointRequest extends OperatorRequest { + + @NotNull + private Long permissionId; + +} \ No newline at end of file diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointDTO.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointDTO.java index 2c5959a8..f425b8b6 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointDTO.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/permission/PermissionPointDTO.java @@ -1,5 +1,6 @@ package cn.axzo.tyr.client.model.permission; +import cn.axzo.tyr.client.model.vo.Operator; import lombok.Data; import javax.validation.constraints.NotBlank; @@ -160,6 +161,12 @@ public class PermissionPointDTO { /** 业务编码 **/ private String businessNo; + private Operator operator; + + public Operator determineOperator() { + return operator == null ? Operator.absent() : operator; + } + public Long mergeFitOuTypeBit() { if (this.fitOuTypeList == null || this.fitOuTypeList.isEmpty()) { return null; diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/product/OldUpdateFeatureRelationRequestV2.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/product/OldUpdateFeatureRelationRequestV2.java new file mode 100644 index 00000000..81276b75 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/product/OldUpdateFeatureRelationRequestV2.java @@ -0,0 +1,25 @@ +package cn.axzo.tyr.client.model.product; + +import cn.axzo.tyr.client.model.vo.OperatorRequest; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author yanglin + */ +@Setter +@Getter +public class OldUpdateFeatureRelationRequestV2 extends OperatorRequest { + + private List relations; + private Map externalLogs = new ConcurrentHashMap<>(); + + public void addExternalLogThreadSafe(String key, Object value) { + externalLogs.put(key, value); + } + +} \ No newline at end of file diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/product/ProductUpdateReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/product/ProductUpdateReq.java index fef6bc42..07891792 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/product/ProductUpdateReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/product/ProductUpdateReq.java @@ -1,5 +1,6 @@ package cn.axzo.tyr.client.model.product; +import cn.axzo.tyr.client.model.vo.Operator; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -69,4 +70,9 @@ public class ProductUpdateReq { */ private List ouTypes; + private Operator operator; + + public Operator determineOperator() { + return operator == null ? Operator.absent() : operator; + } } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/FeatureResourceTreeSaveReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/FeatureResourceTreeSaveReq.java index f5c00c4a..e87303ad 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/FeatureResourceTreeSaveReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/FeatureResourceTreeSaveReq.java @@ -52,9 +52,6 @@ public class FeatureResourceTreeSaveReq extends BaseFeatureResourceDO { /** 页面组件对象 **/ private List componentSaveReqList; - /** 页面及组件权限对象 **/ - private List permissions; - @NotNull(message = "操作人ID不能为空") private Long operatorId; diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/ListPermissionFeatureReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/ListPermissionFeatureReq.java index 5d524012..66c0b1c6 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/ListPermissionFeatureReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/ListPermissionFeatureReq.java @@ -1,5 +1,6 @@ package cn.axzo.tyr.client.model.req; +import cn.axzo.tyr.client.common.enums.FeatureResourceStatus; import cn.axzo.tyr.client.common.enums.FeatureResourceType; import cn.axzo.tyr.client.common.enums.PageElementFeatureResourceRelationTypeEnum; import cn.axzo.tyr.client.model.base.WorkspaceOUPair; @@ -61,4 +62,9 @@ public class ListPermissionFeatureReq { * 查询父组件code下的有权限的uniCode */ private String parentUniCode; + + /** + * 显示或者隐藏,如果父节点是隐藏,则子节点也会隐藏 + */ + private FeatureResourceStatus status; } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/ListPermissionFromRoleGroupReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/ListPermissionFromRoleGroupReq.java index dd07edee..f6245c80 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/ListPermissionFromRoleGroupReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/ListPermissionFromRoleGroupReq.java @@ -44,6 +44,12 @@ public class ListPermissionFromRoleGroupReq { /** 角色组ID **/ private List roleGroupIds; + /** + * 原接口使用方有的需要2,有的需要3,当时加这个出了问题,默认为3 + * 1-仅查当前code 2-对应code角色组及子级角色组 3-仅对应code角色组的子级 + */ + private Integer categoryType; + @Data @Builder @AllArgsConstructor diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/ListRoleReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/ListRoleReq.java index 20688036..90300b78 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/ListRoleReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/ListRoleReq.java @@ -1,11 +1,13 @@ package cn.axzo.tyr.client.model.req; +import cn.axzo.tyr.client.model.roleuser.req.ListRoleUserRelationParam; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; import java.util.List; +import java.util.Set; @Data @SuperBuilder @@ -72,4 +74,19 @@ public class ListRoleReq { * 是否需要角色对应的用户信息 */ private Boolean needRoleUser; + /** + * 是否需要预设角色,因为预设角色的workspaceId和ouId为-1 + */ + private Boolean needPresetRole; + + /** + * workspaceId和ouId配对查询 + * 例如:((workspaceId = ## and ouId = ##) or (workspaceId = ## and ouId = ##)) + */ + private List workspaceOuPairs; + + /** + * 角色权限码 + */ + private Set roleCodes; } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageSaasFeatureResourceReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageSaasFeatureResourceReq.java index 45593a09..3740a40f 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageSaasFeatureResourceReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageSaasFeatureResourceReq.java @@ -4,7 +4,6 @@ import cn.axzo.foundation.dao.support.wrapper.CriteriaField; import cn.axzo.foundation.dao.support.wrapper.Operator; import cn.axzo.foundation.page.IPageReq; import cn.axzo.foundation.page.PageResp; -import cn.axzo.tyr.client.common.enums.FeatureResourceType; import cn.axzo.tyr.client.common.enums.PageElementFeatureResourceRelationTypeEnum; import lombok.AllArgsConstructor; import lombok.Builder; @@ -77,6 +76,9 @@ public class PageSaasFeatureResourceReq implements IPageReq { @CriteriaField(ignore = true) private Boolean needPageElement; + @CriteriaField(field = "status", operator = Operator.EQ) + private Integer status; + /** * 菜单跟页面元素绑定的类型 */ diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PermissionOperateLogReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PermissionOperateLogReq.java index dfa5c3a4..1d67e8a5 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PermissionOperateLogReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PermissionOperateLogReq.java @@ -29,10 +29,12 @@ public class PermissionOperateLogReq implements Serializable { @NotBlank(message = "表名不能为空") private String tableName; - @NotNull(message = "操作人ID不能为空") - @Min(value = 1, message = "操作人ID有误") +// @NotNull(message = "操作人ID不能为空") +// @Min(value = 1, message = "操作人ID有误") private Long operatorId; + private String operatorName; + @NotBlank(message = "场景不能为空") private String scene; @@ -41,4 +43,6 @@ public class PermissionOperateLogReq implements Serializable { private Object requestData; private Object operateData; + + private JSONObject ext; } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/QueryDataObjectReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/QueryDataObjectReq.java new file mode 100644 index 00000000..152f8124 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/QueryDataObjectReq.java @@ -0,0 +1,32 @@ +package cn.axzo.tyr.client.model.req; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; + +/** + * @author likunpeng + * @version 1.0 + * @date 2024/6/3 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class QueryDataObjectReq implements Serializable { + + /** + * 数据对象code + */ + @NotBlank(message = "数据对象code不能为空") + private String dataObjectCode; + + /** + * 租户范围 1:单位租户 2:项目租户 3:政务监管平台 6:OMS + */ + private Integer tenantScope; +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaasRoleGroupDeleteRequest.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaasRoleGroupDeleteRequest.java new file mode 100644 index 00000000..2f35f0e6 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/SaasRoleGroupDeleteRequest.java @@ -0,0 +1,20 @@ +package cn.axzo.tyr.client.model.req; + +import cn.axzo.tyr.client.model.vo.OperatorRequest; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotEmpty; +import java.util.List; + +/** + * @author yanglin + */ +@Setter +@Getter +public class SaasRoleGroupDeleteRequest extends OperatorRequest { + + @NotEmpty(message = "ids不能为空") + private List ids; + +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/TreePermissionReq.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/TreePermissionReq.java index 0cf9dfb4..6f57bed7 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/TreePermissionReq.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/req/TreePermissionReq.java @@ -1,5 +1,6 @@ package cn.axzo.tyr.client.model.req; +import cn.axzo.tyr.client.common.enums.FeatureResourceStatus; import cn.axzo.tyr.client.common.enums.FeatureResourceType; import cn.axzo.tyr.client.common.enums.PageElementFeatureResourceRelationTypeEnum; import cn.axzo.tyr.client.model.base.WorkspaceOUPair; @@ -73,4 +74,9 @@ public class TreePermissionReq { * 默认会增加config配置的默认权限,不需要就传true */ private Boolean excludeDefaultPermission; + + /** + * 显示或者隐藏,如果父节点是隐藏,则子节点也会隐藏 + */ + private FeatureResourceStatus status; } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/ListPermissionFromRoleGroupResp.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/ListPermissionFromRoleGroupResp.java index a97a7523..d2547c25 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/ListPermissionFromRoleGroupResp.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/res/ListPermissionFromRoleGroupResp.java @@ -57,6 +57,11 @@ public class ListPermissionFromRoleGroupResp { */ private String roleName; + /** + * 角色编码 + */ + private String roleCode; + /** * 权限集ID */ diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/dto/SaasRoleUserV2DTO.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/dto/SaasRoleUserV2DTO.java index db940fbf..3d2cb4ff 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/dto/SaasRoleUserV2DTO.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/dto/SaasRoleUserV2DTO.java @@ -85,6 +85,8 @@ public class SaasRoleUserV2DTO { */ private String roleType; + private String roleCode; + private Long workspaceId; private Long ownerOuId; diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/req/ListRoleUserRelationParam.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/req/ListRoleUserRelationParam.java index d901dd58..b5e6a2f0 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/req/ListRoleUserRelationParam.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/req/ListRoleUserRelationParam.java @@ -11,6 +11,7 @@ import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; import java.util.List; +import java.util.Set; @SuperBuilder @Data @@ -27,6 +28,18 @@ public class ListRoleUserRelationParam { @CriteriaField(field = "ouId", operator = Operator.EQ) private Long ouId; + /** + * 是否显示 + */ + @CriteriaField(ignore = true) + private Boolean isDisplay; + + /** + * 是否启用 + */ + @CriteriaField(ignore = true) + private Boolean enabled; + /** * 身份类型 1:工人 2:从业人员 3:班组长 4:运营人员 5:政务人员 */ @@ -94,6 +107,12 @@ public class ListRoleUserRelationParam { @CriteriaField(ignore = true) private Boolean needPermission; + /** + * 角色权限码 + */ + @CriteriaField(ignore = true) + private Set roleCodes; + @Data @Builder @NoArgsConstructor diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/req/PageRoleUserRelationParam.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/req/PageRoleUserRelationParam.java index 01a2af54..4949d781 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/req/PageRoleUserRelationParam.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/req/PageRoleUserRelationParam.java @@ -2,11 +2,13 @@ package cn.axzo.tyr.client.model.roleuser.req; import cn.axzo.foundation.dao.support.wrapper.CriteriaField; import cn.axzo.foundation.page.IPageReq; +import cn.axzo.foundation.page.PageResp; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; +import java.util.Collections; import java.util.List; @SuperBuilder @@ -26,4 +28,13 @@ public class PageRoleUserRelationParam extends ListRoleUserRelationParam impleme */ @CriteriaField(ignore = true) List sort; + + public PageResp toEmpty() { + return PageResp.builder() + .current(this.getPage()) + .size(this.getPageSize()) + .total(0) + .data(Collections.emptyList()) + .build(); + } } diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/vo/Operator.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/vo/Operator.java new file mode 100644 index 00000000..ca039c7f --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/vo/Operator.java @@ -0,0 +1,42 @@ +package cn.axzo.tyr.client.model.vo; + +import cn.axzo.framework.auth.domain.ContextInfo; +import cn.axzo.framework.auth.domain.ContextInfoHolder; +import cn.axzo.framework.auth.domain.UserInfo; +import lombok.Data; + +/** + * @author yanglin + */ +@Data +public class Operator { + + private String realName; + private Long personId; + + /** + * For a gateway like yoke + */ + public static Operator fromAuthContext() { + ContextInfo ctx = ContextInfoHolder.get(); + if (ctx == null) { + return absent(); + } + UserInfo userInfo = ctx.getUserInfo(); + if (userInfo == null) { + return absent(); + } + Operator operator = new Operator(); + operator.setRealName(userInfo.getRealName()); + operator.setPersonId(userInfo.getPersonId()); + return operator; + } + + public static Operator absent() { + Operator operator = new Operator(); + operator.setRealName(""); + operator.setPersonId(0L); + return operator; + } + +} \ No newline at end of file diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/vo/OperatorRequest.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/vo/OperatorRequest.java new file mode 100644 index 00000000..55667726 --- /dev/null +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/vo/OperatorRequest.java @@ -0,0 +1,18 @@ +package cn.axzo.tyr.client.model.vo; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author yanglin + */ +@Setter +@Getter +public class OperatorRequest { + + private Operator operator; + + public Operator determineOperator() { + return operator == null ? Operator.absent() : operator; + } +} diff --git a/tyr-api/src/main/java/cn/axzo/tyr/client/model/vo/SaasRoleGroupVO.java b/tyr-api/src/main/java/cn/axzo/tyr/client/model/vo/SaasRoleGroupVO.java index 65340683..87f1152e 100644 --- a/tyr-api/src/main/java/cn/axzo/tyr/client/model/vo/SaasRoleGroupVO.java +++ b/tyr-api/src/main/java/cn/axzo/tyr/client/model/vo/SaasRoleGroupVO.java @@ -70,4 +70,10 @@ public class SaasRoleGroupVO { * 上级分组id */ private Long parentId; + + private Operator operator; + + public Operator determineOperator() { + return operator == null ? Operator.absent() : operator; + } } diff --git a/tyr-server/pom.xml b/tyr-server/pom.xml index ac8c62dd..7b7f6217 100644 --- a/tyr-server/pom.xml +++ b/tyr-server/pom.xml @@ -138,6 +138,12 @@ apisix-plat-api 2.0.0-SNAPSHOT + + + com.aliyun + alibaba-dingtalk-service-sdk + 2.0.0 + diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/common/util/DingTalkUtil.java b/tyr-server/src/main/java/cn/axzo/tyr/server/common/util/DingTalkUtil.java new file mode 100644 index 00000000..1839c2c3 --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/common/util/DingTalkUtil.java @@ -0,0 +1,68 @@ +package cn.axzo.tyr.server.common.util; + + +import cn.hutool.core.util.StrUtil; +import com.dingtalk.api.DefaultDingTalkClient; +import com.dingtalk.api.DingTalkClient; +import com.dingtalk.api.request.OapiRobotSendRequest; +import com.dingtalk.api.response.OapiRobotSendResponse; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Base64; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +/** + * @author wangsiqian + * @since 2024/07/30 + */ +@Slf4j +public class DingTalkUtil { + + /** + * 发送消息 + * + * @author wangsiqian + * @date 2024-07-30 + */ + public static void sendMessage(String content, String accessToken, String secret) { + Long timestamp = System.currentTimeMillis(); + String sign = getSign(timestamp, secret); + if (StrUtil.isBlank(sign)) { + return; + } + + String url = StrUtil.format("https://oapi.dingtalk.com/robot/send?access_token={}&sign={}×tamp={}", + accessToken, sign, String.valueOf(timestamp)); + DingTalkClient client = new DefaultDingTalkClient(url); + + OapiRobotSendRequest req = new OapiRobotSendRequest(); + OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text(); + text.setContent(content); + OapiRobotSendRequest.At at = new OapiRobotSendRequest.At(); + at.setIsAtAll(false); + req.setMsgtype("text"); + req.setText(text); + req.setAt(at); + try { + OapiRobotSendResponse response = client.execute(req); + log.info("发送钉钉消息结果:{}", response); + } catch (Exception error) { + log.info("发送钉钉消息失败:{}", error.getMessage()); + } + } + + private static String getSign(Long timestamp, String secret) { + try { + String stringToSign = timestamp + "\n" + secret; + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); + byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8)); + return URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8"); + } catch (Exception ignored) { + return ""; + } + } +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/PrivateController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/PrivateController.java index a495da22..fc1845b8 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/PrivateController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/PrivateController.java @@ -25,13 +25,16 @@ import cn.axzo.tyr.client.model.res.SaasRoleRes; import cn.axzo.tyr.client.model.roleuser.req.ListRoleUserRelationParam; import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO; import cn.axzo.tyr.client.model.vo.SaveOrUpdateRoleVO; +import cn.axzo.tyr.server.event.inner.SendDingTalkHandler; import cn.axzo.tyr.server.event.outer.CacheWorkspaceProductHandler; +import cn.axzo.tyr.server.event.payload.SaasFeatureResourceUpsertPayload; import cn.axzo.tyr.server.event.payload.ServicePkgProductCreatedPayload; import cn.axzo.tyr.server.job.CacheProductFeatureResourceJob; import cn.axzo.tyr.server.job.CacheProductPermissionJob; import cn.axzo.tyr.server.job.CacheRoleFeatureResourceJob; import cn.axzo.tyr.server.job.CacheRolePermissionJob; import cn.axzo.tyr.server.job.CacheSaasFeatureJob; +import cn.axzo.tyr.server.job.CacheWorkspaceProductJob; import cn.axzo.tyr.server.repository.dao.ProductModuleDao; import cn.axzo.tyr.server.repository.dao.SaasFeatureDao; import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao; @@ -54,7 +57,9 @@ import cn.axzo.tyr.server.repository.entity.SaasRoleGroup; import cn.axzo.tyr.server.repository.entity.SaasRoleGroupRelation; import cn.axzo.tyr.server.service.ProductFeatureRelationService; import cn.axzo.tyr.server.service.ProductPermissionCacheService; +import cn.axzo.tyr.server.service.ProductSaasFeatureResourceCacheService; import cn.axzo.tyr.server.service.RolePermissionCacheService; +import cn.axzo.tyr.server.service.RoleSaasFeatureResourceCacheService; import cn.axzo.tyr.server.service.RoleService; import cn.axzo.tyr.server.service.SaasCommonDictService; import cn.axzo.tyr.server.service.SaasFeatureResourceService; @@ -169,6 +174,12 @@ public class PrivateController { private SaasRoleUserRelationService saasRoleUserRelationService; @Autowired private ProductModuleDao productModuleDao; + @Autowired + private CacheWorkspaceProductJob cacheWorkspaceProductJob; + @Autowired + private RoleSaasFeatureResourceCacheService roleSaasFeatureResourceCacheService; + @Autowired + private SendDingTalkHandler sendDingTalkHandler; /** * 统一层级的roleGroup按照id升序,sort从1递增 @@ -623,12 +634,24 @@ public class PrivateController { return featureCodeUtil.resolveFeatureCode(request.getFeatureCodes()); } - @PostMapping("/api/private/workspaceProduct/store") - public Object storeWorkspaceProduct(@RequestBody ProductSearchListReq request) throws Exception { + @PostMapping("/api/private/productPermission/store") + public Object storeProductPermission(@RequestBody ProductSearchListReq request) throws Exception { cacheProductPermissionJob.execute(JSON.toJSONString(request)); return "ok"; } + @PostMapping("/api/private/workspaceProduct/store") + public Object storeWorkspaceProduct(@RequestBody WorkspaceProductService.StoreWorkspaceProductParam request) throws Exception { + workspaceProductService.storeWorkspaceProduct(request); + return "ok"; + } + + @PostMapping("/api/private/workspaceProduct/job") + public Object storeWorkspaceProductJob() throws Exception { + cacheWorkspaceProductJob.execute(null); + return "ok"; + } + @PostMapping("/api/private/workspaceProduct/list") public Object listWorkspaceProduct(@RequestBody WorkspaceProductService.WorkspaceProductParam request) { return workspaceProductService.listWorkspaceProductCached(request); @@ -805,11 +828,21 @@ public class PrivateController { .build(); List allFeatures = saasFeatureResourceService.listCache(listSaasFeatureResourceCache).get(request.getTerminal()); - List roles = listRole(request); + List roles = listRole(ListRoleUserRelationParam.builder() + .personId(request.getPersonId()) + .workspaceOuPairs(Lists.newArrayList(ListRoleUserRelationParam.WorkspaceOuPair.builder() + .workspaceId(request.getWorkspaceId()) + .ouId(request.getOuId()) + .build())) + .needRole(true) + .build()); List productPermissions = listWorkspaceProductPermission(request); - List products = listProduct(productPermissions); + List productIds = productPermissions.stream() + .map(WorkspaceProductService.ProductPermission::getProductId) + .collect(Collectors.toList()); + List products = listProduct(productIds); Map> rolePermissions = listRolePermission(roles); @@ -820,6 +853,75 @@ public class PrivateController { .build()); } + @PostMapping("/api/private/featureResource/check") + public ApiResult checkFeatureResource(@RequestBody @Validated CheckFeatureResourceParam request) { + + SaasFeatureResourceService.ListSaasFeatureResourceCache listSaasFeatureResourceCache = SaasFeatureResourceService.ListSaasFeatureResourceCache.builder() + .terminals(Sets.newHashSet(request.getTerminal())) + .build(); + List allFeatures = saasFeatureResourceService.listCache(listSaasFeatureResourceCache).get(request.getTerminal()); + + List roles = listRole(ListRoleUserRelationParam.builder() + .personId(request.getPersonId()) + .workspaceOuPairs(Lists.newArrayList(ListRoleUserRelationParam.WorkspaceOuPair.builder() + .workspaceId(request.getWorkspaceId()) + .ouId(request.getOuId()) + .build())) + .needRole(true) + .build()); + + List productFeatureSources = listWorkspaceProductFeatureResource(request); + + List productIds = productFeatureSources.stream() + .map(WorkspaceProductService.ProductFeatureSource::getProductId) + .collect(Collectors.toList()); + List products = listProduct(productIds); + + Map> roleFeatureResources = listRoleFeatureResource(roles); + + return ApiResult.ok(CheckFeatureResourceDTO.builder() + .products(products) + .roles(roles) + .uniCodeCheckResults(resolveUniCode(request, productFeatureSources, roleFeatureResources, roles, allFeatures)) + .build()); + } + + private UniCodeCheckResult resolveAdminRoleFeature(List adminRoles, + List productFeatureResources) { + if (CollectionUtils.isEmpty(adminRoles)) { + return UniCodeCheckResult.builder() + .authPermission(false) + .reasons(Lists.newArrayList("没有管理员角色")) + .build(); + + } + + List reasons = Lists.newArrayList(); + Boolean authPermission = false; + + for (Role adminRole : adminRoles) { + + List adminPermissions = productFeatureResources.stream() + .filter(e -> Objects.equals(e.getCooperateType(), adminRole.getCooperateType().toString())) + .collect(Collectors.toList()); + + if (CollectionUtils.isNotEmpty(adminPermissions)) { + reasons.add("角色Id:" + adminRole.getRoleId() + + ";角色名字:" + adminRole.getRoleName() + + ";单位类型:" + adminRole.getCooperateType() + ";是管理员角色,有该权限code权限"); + authPermission = true; + } else { + reasons.add("角色Id:" + adminRole.getRoleId() + + ";角色名字:" + adminRole.getRoleName() + + ";单位类型:" + adminRole.getCooperateType() + ";没有该权限code权限"); + } + } + return UniCodeCheckResult.builder() + .authPermission(authPermission) + .reasons(reasons) + .build(); + } + private FeatureCodeCheckResult resolveAdminRole(List adminRoles, List productPermissions) { if (CollectionUtils.isEmpty(adminRoles)) { @@ -904,6 +1006,54 @@ public class PrivateController { .build(); } + private UniCodeCheckResult resolveNormalRoleFeature(List normalRoles, + List productFeatureResources, + Map> rolePermissions, + String uniCode) { + if (CollectionUtils.isEmpty(normalRoles)) { + return UniCodeCheckResult.builder() + .authPermission(false) + .reasons(Lists.newArrayList("没有普通角色")) + .build(); + + } + + List reasons = Lists.newArrayList(); + Boolean authPermission = false; + + for (Role normalRole : normalRoles) { + List normalRolepermissions = rolePermissions.getOrDefault(normalRole.getRoleId(), Lists.newArrayList()) + .stream() + .filter(e -> Objects.equals(e.getUniCode(), uniCode)) + .collect(Collectors.toList()); + + Set productCooperateTypes = productFeatureResources.stream() + .map(e -> e.getCooperateType()) + .collect(Collectors.toSet()); + + if (CollectionUtils.isEmpty(normalRolepermissions)) { + reasons.add("角色Id:" + normalRole.getRoleId() + + ";角色名字:" + normalRole.getRoleName() + + ";单位类型:" + normalRole.getCooperateType() + ";没有该权限code权限"); + } else if (productCooperateTypes.contains(normalRole.getCooperateType().toString())) { + reasons.add("角色Id:" + normalRole.getRoleId() + + ";角色名字:" + normalRole.getRoleName() + + ";单位类型:" + normalRole.getCooperateType() + ";有该权限code权限;有该权限的产品的单位类型有" + + JSON.toJSONString(productCooperateTypes)); + authPermission = true; + } else { + reasons.add("角色Id:" + normalRole.getRoleId() + + ";角色名字:" + normalRole.getRoleName() + + ";单位类型:" + normalRole.getCooperateType() + ";有该权限code权限;有该权限的产品的单位类型有" + + JSON.toJSONString(productCooperateTypes)); + } + } + return UniCodeCheckResult.builder() + .authPermission(authPermission) + .reasons(reasons) + .build(); + } + private FeatureCodeCheckResult resolveNotAuth(List productPermissions, String featureCode, List allFeatures) { @@ -959,6 +1109,61 @@ public class PrivateController { } } + private UniCodeCheckResult resolveNotAuthFeature(List productFeatureResources, + String uniCode, + List allFeatures) { + // 直接配置成免授权的权限点 + List notAuthFeatures = allFeatures.stream() + .filter(SaasFeatureResourceService.SaasFeatureResourceCache::isNotAuth) + .collect(Collectors.toList()); + + // 子节点是免授权的权限点 + Set parentNotAuthFeatureIds = notAuthFeatures.stream() + .map(e -> Optional.ofNullable(e.getParentIds()) + .map(f -> { + f.add(e.getFeatureId()); + return f; + }) + .orElseGet(() -> Sets.newHashSet(e.getFeatureId()))) + .flatMap(Collection::stream) + .collect(Collectors.toSet()); + + Set notAuthFeatureIds = notAuthFeatures.stream() + .map(SaasFeatureResourceService.SaasFeatureResourceCache::getFeatureId) + .collect(Collectors.toSet()); + + if (CollectionUtils.isEmpty(parentNotAuthFeatureIds) && CollectionUtils.isEmpty(notAuthFeatureIds)) { + return UniCodeCheckResult.builder() + .authPermission(false) + .reasons(Lists.newArrayList("没有免授权权限点")) + .build(); + } + + Set productFeatureIds = productFeatureResources.stream() + .filter(e -> Objects.equals(e.getUniCode(), uniCode)) + .map(ProductSaasFeatureResourceCacheService.FeatureResourceDTO::getFeatureId) + .collect(Collectors.toSet()); + + + + if (!Sets.intersection(notAuthFeatureIds, productFeatureIds).isEmpty()) { + return UniCodeCheckResult.builder() + .authPermission(true) + .reasons(Lists.newArrayList("权限点是免授权")) + .build(); + } else if (!Sets.intersection(parentNotAuthFeatureIds, productFeatureIds).isEmpty()) { + return UniCodeCheckResult.builder() + .authPermission(true) + .reasons(Lists.newArrayList("权限点的子节点是免授权")) + .build(); + } else { + return UniCodeCheckResult.builder() + .authPermission(false) + .reasons(Lists.newArrayList("权限点不是免授权")) + .build(); + } + } + private List resolveFeatureCode(CheckPermissionParam checkPermissionParam, List productPermissions, Map> rolePermissions, @@ -1022,6 +1227,68 @@ public class PrivateController { .collect(Collectors.toList()); } + private List resolveUniCode(CheckFeatureResourceParam checkFeatureResourceParam, + List productFeatureSources, + Map> roleFeatureResources, + List roles, + List allFeatures) { + Map> productFeatureResourceMap = productFeatureSources.stream() + .map(WorkspaceProductService.ProductFeatureSource::getFeatureResources) + .flatMap(Collection::stream) + .collect(Collectors.groupingBy(ProductSaasFeatureResourceCacheService.FeatureResourceDTO::getUniCode)); + List adminRoles = roles.stream() + .filter(e -> RoleTypeEnum.isAdmin(e.getRoleType())) + .collect(Collectors.toList()); + + List normalRoles = roles.stream() + .filter(e -> !RoleTypeEnum.isAdmin(e.getRoleType())) + .collect(Collectors.toList()); + + return checkFeatureResourceParam.getUniCodes().stream() + .map(uniCode -> { + List featureResources = productFeatureResourceMap.get(uniCode); + if (CollectionUtils.isEmpty(featureResources)) { + return UniCodeCheckResult.builder() + .uniCode(uniCode) + .authPermission(false) + .reasons(Lists.newArrayList("项目没有配置产品及权限")) + .build(); + } + + if (CollectionUtils.isEmpty(roles)) { + return UniCodeCheckResult.builder() + .uniCode(uniCode) + .authPermission(false) + .reasons(Lists.newArrayList("用户在项目里没有任何角色")) + .build(); + } + + UniCodeCheckResult adminRoleCheckResult = resolveAdminRoleFeature(adminRoles, featureResources); + + UniCodeCheckResult normalRoleCheckResult = resolveNormalRoleFeature(normalRoles, featureResources, roleFeatureResources, uniCode); + + UniCodeCheckResult notAuthCheckResult = resolveNotAuthFeature(featureResources, uniCode, allFeatures); + + Boolean authPermission = BooleanUtils.isTrue(adminRoleCheckResult.getAuthPermission()) + || BooleanUtils.isTrue(normalRoleCheckResult.getAuthPermission()) + || BooleanUtils.isTrue(notAuthCheckResult.getAuthPermission()); + + List adminRoleReasons = adminRoleCheckResult.getReasons(); + List normalRoleReasons = normalRoleCheckResult.getReasons(); + List notAuthReasons = notAuthCheckResult.getReasons(); + + adminRoleReasons.addAll(normalRoleReasons); + adminRoleReasons.addAll(notAuthReasons); + + return UniCodeCheckResult.builder() + .uniCode(uniCode) + .authPermission(authPermission) + .reasons(adminRoleReasons) + .build(); + }) + .collect(Collectors.toList()); + } + private Map> listRolePermission(List roles) { if (CollectionUtils.isEmpty(roles)) { @@ -1034,15 +1301,23 @@ public class PrivateController { return rolePermissionCacheService.list(listRolePermissionParam); } - private List listProduct(List productPermissions) { + private Map> listRoleFeatureResource(List roles) { - if (CollectionUtils.isEmpty(productPermissions)) { - return Collections.emptyList(); + if (CollectionUtils.isEmpty(roles)) { + return Collections.emptyMap(); } - List productIds = productPermissions.stream() - .map(WorkspaceProductService.ProductPermission::getProductId) - .collect(Collectors.toList()); + RoleSaasFeatureResourceCacheService.ListRoleSaasFeatureResourceParam listRolePermissionParam = RoleSaasFeatureResourceCacheService.ListRoleSaasFeatureResourceParam.builder() + .roleIds(roles.stream().map(Role::getRoleId).collect(Collectors.toSet())) + .build(); + return roleSaasFeatureResourceCacheService.list(listRolePermissionParam); + } + + private List listProduct(List productIds) { + + if (CollectionUtils.isEmpty(productIds)) { + return Collections.emptyList(); + } return productModuleDao.listByIds(productIds).stream() .filter(productModule -> Objects.equals(productModule.getIsDelete(),0L)) @@ -1064,16 +1339,18 @@ public class PrivateController { .collect(Collectors.toList()); } - private List listRole(CheckPermissionParam request) { - ListRoleUserRelationParam listRoleUserRelationParam = ListRoleUserRelationParam.builder() - .personId(request.getPersonId()) - .workspaceOuPairs(Lists.newArrayList(ListRoleUserRelationParam.WorkspaceOuPair.builder() - .workspaceId(request.getWorkspaceId()) - .ouId(request.getOuId()) - .build())) - .needRole(true) + private List listWorkspaceProductFeatureResource(CheckFeatureResourceParam request) { + WorkspaceProductService.ListWorkspaceProductFeatureSourceCacheParam listWorkspaceProductFeatureSourceCacheParam = WorkspaceProductService.ListWorkspaceProductFeatureSourceCacheParam + .builder() + .workspaceIds(Sets.newHashSet(request.getWorkspaceId())) .build(); + return workspaceProductService.listWorkspaceProductFeatureResourceCached(listWorkspaceProductFeatureSourceCacheParam).stream() + .map(WorkspaceProductService.WorkspaceProductFeatureSource::getProductFeatureSources) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + } + private List listRole(ListRoleUserRelationParam listRoleUserRelationParam) { return saasRoleUserRelationService.listV2(listRoleUserRelationParam).stream() .filter(e -> e.getSaasRole() != null) .collect(Collectors.toList()) @@ -1087,6 +1364,15 @@ public class PrivateController { .collect(Collectors.toList()); } + @PostMapping("/api/private/dingtalk/send") + public Object sendUpsertDingTalk(@RequestBody SaasFeatureResourceUpsertPayload request) { + Event event = Event.builder() + .data(request) + .build(); + sendDingTalkHandler.onFeatureResourceUpsert(event, null); + return "ok"; + } + @Data @Builder @NoArgsConstructor @@ -1109,6 +1395,28 @@ public class PrivateController { private String terminal; } + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class CheckFeatureResourceParam { + + @NotNull(message = "ouId不能为空") + private Long ouId; + + @NotNull(message = "workspaceId不能为空") + private Long workspaceId; + + @NotEmpty(message = "uniCodes不能为空") + private Set uniCodes; + + @NotNull(message = "personId不能为空") + private Long personId; + + @NotBlank(message = "terminal不能为空") + private String terminal; + } + @Data @Builder @NoArgsConstructor @@ -1122,6 +1430,19 @@ public class PrivateController { private List featureCodeCheckResults; } + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class CheckFeatureResourceDTO { + + private List products; + + private List roles; + + private List uniCodeCheckResults; + } + @Data @Builder @NoArgsConstructor @@ -1160,6 +1481,18 @@ public class PrivateController { private Boolean authPermission; } + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class UniCodeCheckResult { + private String uniCode; + + private List reasons; + + private Boolean authPermission; + } + @Data @Builder @NoArgsConstructor diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/data/object/DataObjectController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/data/object/DataObjectController.java index e8366555..e0fb5b4e 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/data/object/DataObjectController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/data/object/DataObjectController.java @@ -1,6 +1,5 @@ package cn.axzo.tyr.server.controller.data.object; -import cn.axzo.basics.auth.enums.WorkspaceTypeWithLegacyEnum; import cn.axzo.basics.common.page.PageResult; import cn.axzo.framework.domain.ServiceException; import cn.axzo.framework.domain.web.result.ApiResult; @@ -10,12 +9,8 @@ import cn.axzo.tyr.client.common.enums.EnumTypeEnum; import cn.axzo.tyr.client.common.enums.ReturnCodeEnum; import cn.axzo.tyr.client.common.enums.RowPermissionEnum; import cn.axzo.tyr.client.common.enums.TenantScopeEnum; -import cn.axzo.tyr.client.common.enums.WorkspaceJoinType; import cn.axzo.tyr.client.feign.DataObjectApi; -import cn.axzo.tyr.client.model.req.CreateDataObjectReq; -import cn.axzo.tyr.client.model.req.DeleteDataObjectReq; -import cn.axzo.tyr.client.model.req.EditDataObjectReq; -import cn.axzo.tyr.client.model.req.PageDataObjectReq; +import cn.axzo.tyr.client.model.req.*; import cn.axzo.tyr.client.model.res.DataObjectRes; import cn.axzo.tyr.client.model.res.EnumRes; import cn.axzo.tyr.client.model.res.SimpleDataObjectRes; @@ -91,4 +86,8 @@ public class DataObjectController implements DataObjectApi { return ApiResult.ok(dataObjectService.getDataObject(dataObjectId)); } + @Override + public ApiResult queryDataObject(QueryDataObjectReq req) { + return ApiResult.ok(dataObjectService.queryDataObject(req)); + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PermissionPointController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PermissionPointController.java index f94b1bee..baf0f1fc 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PermissionPointController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/permission/PermissionPointController.java @@ -2,6 +2,7 @@ package cn.axzo.tyr.server.controller.permission; import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.tyr.client.feign.PermissionPointApi; +import cn.axzo.tyr.client.model.permission.DeletePermissionPointRequest; import cn.axzo.tyr.client.model.permission.PermissionPointDTO; import cn.axzo.tyr.client.model.permission.PermissionPointListQueryRequest; import cn.axzo.tyr.client.model.permission.PermissionPointMoveRequest; @@ -59,6 +60,9 @@ public class PermissionPointController implements PermissionPointApi { return ApiResult.ok(permissionPointService.delete(permissionId)); } + @Override public ApiResult> deletePermissionPointV2(DeletePermissionPointRequest request) { + return ApiResult.ok(permissionPointService.deleteV2(request)); + } @Override public ApiResult move(PermissionPointMoveRequest request) { diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/product/ProductController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/product/ProductController.java index 316874ee..297726fd 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/product/ProductController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/product/ProductController.java @@ -3,7 +3,16 @@ package cn.axzo.tyr.server.controller.product; import cn.axzo.framework.domain.web.result.ApiPageResult; import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.tyr.client.feign.ProductApi; -import cn.axzo.tyr.client.model.product.*; +import cn.axzo.tyr.client.model.product.OldUpdateFeatureRelationRequestV2; +import cn.axzo.tyr.client.model.product.ProductAddReq; +import cn.axzo.tyr.client.model.product.ProductDetailReq; +import cn.axzo.tyr.client.model.product.ProductFeatureRelationSearchReq; +import cn.axzo.tyr.client.model.product.ProductFeatureRelationUpdateReq; +import cn.axzo.tyr.client.model.product.ProductFeatureRelationVO; +import cn.axzo.tyr.client.model.product.ProductSearchListReq; +import cn.axzo.tyr.client.model.product.ProductSearchPageReq; +import cn.axzo.tyr.client.model.product.ProductUpdateReq; +import cn.axzo.tyr.client.model.product.ProductVO; import cn.axzo.tyr.client.model.req.ProductSaveReq; import cn.axzo.tyr.client.model.req.UpdateProductStatusReq; import cn.axzo.tyr.client.model.res.GovernmentTerminalResp; @@ -127,6 +136,14 @@ public class ProductController implements ProductApi { return productFeatureRelationService.updateFeatureRelation(req); } + @Override + public ApiResult updateFeatureRelationV2(OldUpdateFeatureRelationRequestV2 req) { + if(CollectionUtils.isEmpty(req.getRelations())) { + return ApiResult.ok(false); + } + permissionCacheService.markTempDisable(PermissionCacheKey.builder().disableAll(true).build()); + return productFeatureRelationService.updateFeatureRelationV2(req); + } @Override public ApiResult>> queryProductFeatureRelationByWorkspace(Set workspaceIds) { diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/role/SaasRoleGroupController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/role/SaasRoleGroupController.java index e2b2789c..9118d20d 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/role/SaasRoleGroupController.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/role/SaasRoleGroupController.java @@ -8,6 +8,7 @@ import cn.axzo.tyr.client.feign.SaasRoleGroupApi; import cn.axzo.tyr.client.model.req.ListSaasRoleGroupParam; import cn.axzo.tyr.client.model.req.PageSaasRoleGroupParam; import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq; +import cn.axzo.tyr.client.model.req.SaasRoleGroupDeleteRequest; import cn.axzo.tyr.client.model.req.UpdateRoleGroupOffsetReq; import cn.axzo.tyr.client.model.res.SaasRoleGroupDTO; import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO; @@ -56,6 +57,12 @@ public class SaasRoleGroupController implements SaasRoleGroupApi { return ApiResult.ok(roleGroups.get(0)); } + @Override + public ApiResult deleteV2(SaasRoleGroupDeleteRequest request) { + saasRoleGroupService.deleteV2(request); + return ApiResult.ok(); + } + @Override public ApiResult delete(List ids) { saasRoleGroupService.delete(ids); diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRolePermissionHandler.java b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRolePermissionHandler.java index 093166c1..b902d524 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRolePermissionHandler.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRolePermissionHandler.java @@ -26,6 +26,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; @@ -73,12 +74,16 @@ public class CacheRolePermissionHandler implements InitializingBean { log.info("begin cached role permission handler rocketmq event: {}", event); RolePermissionCreatedPayload payload = event.normalizedData(RolePermissionCreatedPayload.class); - if (CollectionUtils.isEmpty(payload.getRoleIds())) { - return; - } + // 影响角色权限入口的代码没法简单重构,导致发送的roleIds可能不准确,所以一旦有角色权限的更新事件后,全量更新角色权限,角色权限数量不多 + // 后续收口了代码就准确根据角色去更新缓存 +// if (CollectionUtils.isEmpty(payload.getRoleIds())) { +// return; +// } RoleService.ListSaasRoleParam listSaasRoleParam = RoleService.ListSaasRoleParam.builder() - .roleIds(Lists.newArrayList(payload.getRoleIds())) + .roleIds(Optional.ofNullable(payload.getRoleIds()) + .map(Lists::newArrayList) + .orElse(null)) .needPermissionRelation(true) .build(); List roles = roleService.list(listSaasRoleParam); diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRoleSaasFeatureResourceHandler.java b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRoleSaasFeatureResourceHandler.java index be92484b..1c9875ea 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRoleSaasFeatureResourceHandler.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/CacheRoleSaasFeatureResourceHandler.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; @@ -68,12 +69,16 @@ public class CacheRoleSaasFeatureResourceHandler implements InitializingBean { log.info("begin cached role saasFeatureResource handler rocketmq event: {}", event); RolePermissionCreatedPayload payload = event.normalizedData(RolePermissionCreatedPayload.class); - if (CollectionUtils.isEmpty(payload.getRoleIds())) { - return; - } + // 影响角色权限入口的代码没法简单重构,导致发送的roleIds可能不准确,所以一旦有角色权限的更新事件后,全量更新角色权限,角色权限数量不多 + // 后续收口了代码就准确根据角色去更新缓存 +// if (CollectionUtils.isEmpty(payload.getRoleIds())) { +// return; +// } RoleService.ListSaasRoleParam listSaasRoleParam = RoleService.ListSaasRoleParam.builder() - .roleIds(Lists.newArrayList(payload.getRoleIds())) + .roleIds(Optional.ofNullable(payload.getRoleIds()) + .map(Lists::newArrayList) + .orElse(null)) .needPermissionRelation(true) .type(NEW_FEATURE) .build(); diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/SendDingTalkHandler.java b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/SendDingTalkHandler.java new file mode 100644 index 00000000..9e6484c0 --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/event/inner/SendDingTalkHandler.java @@ -0,0 +1,78 @@ +package cn.axzo.tyr.server.event.inner; + +import cn.axzo.framework.auth.domain.TerminalInfo; +import cn.axzo.framework.rocketmq.Event; +import cn.axzo.framework.rocketmq.EventConsumer; +import cn.axzo.tyr.server.common.util.DingTalkUtil; +import cn.axzo.tyr.server.event.payload.SaasFeatureResourceUpsertPayload; +import cn.axzo.tyr.server.repository.entity.SaasFeatureResource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.Objects; +import java.util.Optional; + +@Slf4j +@Component +public class SendDingTalkHandler implements InitializingBean { + + @Autowired + private EventConsumer eventConsumer; + @Value("${spring.profiles.active}") + private String env; + + // 语音助手菜单变更通知,@沈尚只是临时的方案,对方接入MQ成本高,所以没改成配置 + private static final String ACCESS_TOKEN = "11cdf26d77211ee887184844910bf249b94aa2675c7ce36d75a7aa87d619490f"; + private static final String SECRET = "SEC3c1be9e4fe4cc09f16eb4b2eebf91659f21d5bdfb1d764b52f3e47825e6bed3f"; + + + public void onFeatureResourceUpsert(Event event, EventConsumer.Context context) { + log.info("begin send dingTalk rocketmq event: {}", event); + SaasFeatureResourceUpsertPayload payload = event.normalizedData(SaasFeatureResourceUpsertPayload.class); + + if (Objects.isNull(payload.getAction())) { + return; + } + + if (Objects.isNull(payload.getNewValue()) && Objects.isNull(payload.getOldValue())) { + return; + } + + // 现在沈尚那边只关心CMP的code有更新的情况 + String terminal = Optional.ofNullable(payload.getNewValue()) + .map(SaasFeatureResource::getTerminal) + .orElseGet(() -> payload.getOldValue().getTerminal()); + + if (!Objects.equals(terminal, TerminalInfo.NT_CMP_APP_GENERAL)) { + return; + } + + if (Objects.equals(payload.getAction(), SaasFeatureResource.Action.UPDATE) && + Objects.equals(payload.getNewValue().getUniCode(), payload.getOldValue().getUniCode())) { + return; + } + + StringBuilder sb = new StringBuilder(); + sb.append("环境:" + env + "\n"); + sb.append("操作:" + payload.getAction() + "\n"); + if (Objects.equals(payload.getAction(), SaasFeatureResource.Action.CREATE)) { + sb.append("新code:" + payload.getNewValue().getUniCode()); + } else if (Objects.equals(payload.getAction(), SaasFeatureResource.Action.UPDATE)) { + sb.append("新code:" + payload.getNewValue().getUniCode() + "\n"); + sb.append("旧code:" + payload.getOldValue().getUniCode()); + } else if (Objects.equals(payload.getAction(), SaasFeatureResource.Action.DELETE)) { + sb.append("旧code:" + payload.getOldValue().getUniCode()); + } + + DingTalkUtil.sendMessage(sb.toString(), ACCESS_TOKEN, SECRET); + log.info("end send dingTalk rocketmq event: {}", event); + } + + @Override + public void afterPropertiesSet() throws Exception { + eventConsumer.registerHandler(EventTypeEnum.SAAS_FEATURE_RESOURCE_UPSERT.getEventCode(), this::onFeatureResourceUpsert); + } +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/event/payload/SaasFeatureResourceUpsertPayload.java b/tyr-server/src/main/java/cn/axzo/tyr/server/event/payload/SaasFeatureResourceUpsertPayload.java index 1cdcbafb..1cae0180 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/event/payload/SaasFeatureResourceUpsertPayload.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/event/payload/SaasFeatureResourceUpsertPayload.java @@ -1,5 +1,6 @@ package cn.axzo.tyr.server.event.payload; +import cn.axzo.tyr.server.repository.entity.SaasFeatureResource; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -14,5 +15,12 @@ import java.util.Set; @AllArgsConstructor public class SaasFeatureResourceUpsertPayload implements Serializable { + // 只有tyr消费,触发更新缓存,同步等很多批量操作要全部重构收口代码后,才能好修改这个payload private Set terminals; + + private SaasFeatureResource oldValue; + + private SaasFeatureResource newValue; + + private SaasFeatureResource.Action action; } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheSaasFeatureJob.java b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheSaasFeatureJob.java index 6c48dc91..b667eb0d 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheSaasFeatureJob.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheSaasFeatureJob.java @@ -1,5 +1,6 @@ package cn.axzo.tyr.server.job; +import cn.axzo.tyr.client.common.enums.FeatureResourceStatus; import cn.axzo.tyr.client.model.enums.DelegatedType; import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq; import cn.axzo.tyr.client.model.res.PageElementResp; @@ -96,6 +97,7 @@ public class CacheSaasFeatureJob extends IJobHandler { .notAuth(SaasFeatureResource.AuthType.isAllRole(e.getAuthType())) .parentIds(e.resolvePath()) .uniCode(e.getUniCode()) + .status(e.getStatus()) .version(Optional.ofNullable(e.getSaasPageElements()) .map(pageElement -> pageElement.stream() .findFirst() diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheWorkspaceProductJob.java b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheWorkspaceProductJob.java new file mode 100644 index 00000000..e50788e6 --- /dev/null +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/job/CacheWorkspaceProductJob.java @@ -0,0 +1,66 @@ +package cn.axzo.tyr.server.job; + +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; +import cn.axzo.tyr.server.service.WorkspaceProductService; +import cn.axzo.tyr.server.utils.RpcInternalUtil; +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.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +@Slf4j +@Component +public class CacheWorkspaceProductJob extends IJobHandler { + + @Autowired + private WorkspaceProductService workspaceProductService; + @Autowired + private ServicePkgClient servicePkgClient; + + @Override + @XxlJob("CacheWorkspaceProductJob") + public ReturnT execute(String s) throws Exception { + + log.info("start CacheWorkspaceProductJob, s:{}", s); + + // 全量更新所有项目的产品数量比较大,所以这里只从缓存中的项目去更新产品 + Map> allWorkspaceProducts = workspaceProductService.listAllWorkspaceProductCached(); + + Set workspaceIds = allWorkspaceProducts.keySet(); + + if (CollectionUtils.isEmpty(workspaceIds)) { + return ReturnT.SUCCESS; + } + + List servicePkgDetailRes = RpcInternalUtil.rpcListProcessor(() -> servicePkgClient.getServicePkgDetailBySpaceId(workspaceIds), + "查询项目的产品", workspaceIds).getData(); + + List workspaceProducts = servicePkgDetailRes.stream() + .map(e -> WorkspaceProductService.WorkspaceProductDTO.builder() + .workspaceId(e.getSpaceId()) + .productIds(Optional.ofNullable(e.getProducts()) + .map(products -> products.stream() + .map(ServicePkgProduct::getProductId) + .collect(Collectors.toSet())) + .orElse(null)) + .build()) + .collect(Collectors.toList()); + + WorkspaceProductService.StoreWorkspaceProductParam storeWorkspaceProductParam = WorkspaceProductService.StoreWorkspaceProductParam.builder() + .workspaceProducts(workspaceProducts) + .build(); + workspaceProductService.storeWorkspaceProduct(storeWorkspaceProductParam); + return ReturnT.SUCCESS; + } +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPgroupPermissionRelationDao.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPgroupPermissionRelationDao.java index 7ce3db6c..f59c2b39 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPgroupPermissionRelationDao.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/dao/SaasPgroupPermissionRelationDao.java @@ -15,6 +15,8 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation.NEW_FEATURE; + @Repository public class SaasPgroupPermissionRelationDao extends ServiceImpl { @@ -59,6 +61,7 @@ public class SaasPgroupPermissionRelationDao extends ServiceImpl * 岗位id/角色id */ private Long relationId; + /** + * 岗位编码 + */ + private String relationCode; } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasFeatureResource.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasFeatureResource.java index 448a4146..a3420f41 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasFeatureResource.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasFeatureResource.java @@ -198,4 +198,14 @@ public class SaasFeatureResource extends BaseEntity { return Objects.equals(ALL_ROLE.getValue(), authType); } } + + @Getter + @AllArgsConstructor + public enum Action { + DELETE( "删除操作"), + CREATE( "创建操作"), + UPDATE( "更新操作"); + + private String desc; + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPgroupPermissionRelationOperateLog.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPgroupPermissionRelationOperateLog.java index ddf61fbd..a8feb86e 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPgroupPermissionRelationOperateLog.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/entity/SaasPgroupPermissionRelationOperateLog.java @@ -2,7 +2,10 @@ package cn.axzo.tyr.server.repository.entity; import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; import cn.axzo.tyr.client.common.enums.PermissionRelationOperateLogSceneEnum; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler; import lombok.*; /** @@ -15,7 +18,7 @@ import lombok.*; @Builder @ToString @EqualsAndHashCode(callSuper = true) -@TableName("saas_pgroup_permission_relation_operate_log") +@TableName(value = "saas_pgroup_permission_relation_operate_log", autoResultMap = true) public class SaasPgroupPermissionRelationOperateLog extends BaseEntity { /** @@ -63,4 +66,7 @@ public class SaasPgroupPermissionRelationOperateLog extends BaseEntity { "WHERE path LIKE CONCAT(#{pathPrefix},'%') ") void updateChildrenPath(Long updater, String pathPrefix, String newPathPrefix); + @Select("SELECT * FROM saas_feature WHERE id = #{id}") + SaasFeature getByIdDeleteAware(@Param("id") Long id); } \ No newline at end of file diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasRoleGroupMapper.java b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasRoleGroupMapper.java index e6c7c56d..f083db31 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasRoleGroupMapper.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/repository/mapper/SaasRoleGroupMapper.java @@ -3,9 +3,21 @@ package cn.axzo.tyr.server.repository.mapper; import cn.axzo.tyr.server.repository.entity.SaasRoleGroup; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; @Mapper public interface SaasRoleGroupMapper extends BaseMapper { + @Select("") + List getByIdsDeleteAware( + @Param("ids") List ids); + } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/DataObjectService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/DataObjectService.java index dd9de34d..75672788 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/DataObjectService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/DataObjectService.java @@ -4,6 +4,7 @@ import cn.axzo.basics.common.page.PageResult; import cn.axzo.tyr.client.model.req.CreateDataObjectReq; import cn.axzo.tyr.client.model.req.EditDataObjectReq; import cn.axzo.tyr.client.model.req.PageDataObjectReq; +import cn.axzo.tyr.client.model.req.QueryDataObjectReq; import cn.axzo.tyr.client.model.res.DataObjectRes; import cn.axzo.tyr.client.model.res.SimpleDataObjectRes; @@ -17,4 +18,6 @@ public interface DataObjectService { PageResult pageDataObject(PageDataObjectReq req); DataObjectRes getDataObject(Long dataObjectId); + + DataObjectRes queryDataObject(QueryDataObjectReq req); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/PermissionPointService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/PermissionPointService.java index 21604155..1a543d3f 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/PermissionPointService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/PermissionPointService.java @@ -1,5 +1,6 @@ package cn.axzo.tyr.server.service; +import cn.axzo.tyr.client.model.permission.DeletePermissionPointRequest; import cn.axzo.tyr.client.model.permission.PermissionPointDTO; import cn.axzo.tyr.client.model.permission.PermissionPointListQueryRequest; import cn.axzo.tyr.client.model.permission.PermissionPointMoveRequest; @@ -42,6 +43,9 @@ public interface PermissionPointService { /** 删除权限点 返回business_no **/ List delete(Long permissionId); + /** 删除权限点 返回business_no **/ + List deleteV2(DeletePermissionPointRequest request); + /** 位置移动-父级和排序 **/ void move(PermissionPointMoveRequest request); diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/ProductFeatureRelationService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/ProductFeatureRelationService.java index fdb2febc..d0c0b630 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/ProductFeatureRelationService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/ProductFeatureRelationService.java @@ -2,6 +2,7 @@ package cn.axzo.tyr.server.service; import cn.axzo.foundation.page.PageResp; import cn.axzo.framework.domain.web.result.ApiResult; +import cn.axzo.tyr.client.model.product.OldUpdateFeatureRelationRequestV2; import cn.axzo.tyr.client.model.product.ProductFeatureRelationSearchReq; import cn.axzo.tyr.client.model.product.ProductFeatureRelationUpdateReq; import cn.axzo.tyr.client.model.product.ProductFeatureRelationVO; @@ -25,6 +26,8 @@ public interface ProductFeatureRelationService extends IService updateFeatureRelation(List req); + ApiResult updateFeatureRelationV2(OldUpdateFeatureRelationRequestV2 request); + /** * 更新产品功能权限关系,仅支持saas_feature_resource功能点 * 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 2c6921fe..f8ca3353 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 @@ -19,6 +19,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.res.SaasRoleRes; +import cn.axzo.tyr.client.model.roleuser.req.ListRoleUserRelationParam; import cn.axzo.tyr.client.model.vo.DeleteRoleVO; import cn.axzo.tyr.client.model.vo.SaasRoleAndGroupVO; import cn.axzo.tyr.client.model.vo.SaasRoleCategoryVO; @@ -138,6 +139,12 @@ public interface RoleService extends IService { @CriteriaField(field = "id", operator = Operator.NE) private Long idNE; + /** + * 角色权限码 + */ + @CriteriaField(field = "roleCode", operator = Operator.IN) + private Set roleCodes; + /** * 权限点从saas_feature_resource表查询 */ @@ -166,6 +173,12 @@ public interface RoleService extends IService { @CriteriaField(ignore = true) private Boolean needPermissionRelation; + /** + * 是否需要预设角色,因为预设角色的workspaceId和ouId为-1 + */ + @CriteriaField(ignore = true) + private Boolean needPresetRole; + /** * 查询菜单树节点类型 */ @@ -184,6 +197,13 @@ public interface RoleService extends IService { @CriteriaField(ignore = true) private String terminal; + /** + * workspaceId和ouId配对查询 + * 例如:((workspaceId = ## and ouId = ##) or (workspaceId = ## and ouId = ##)) + */ + @CriteriaField(ignore = true) + private List workspaceOuPairs; + @CriteriaField(field = "workspaceId", operator = Operator.EQ) private Long workspaceId; diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasFeatureResourceService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasFeatureResourceService.java index f2a94322..10ec91e5 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasFeatureResourceService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasFeatureResourceService.java @@ -1,119 +1,126 @@ -package cn.axzo.tyr.server.service; - -import cn.axzo.foundation.page.PageResp; -import cn.axzo.tyr.client.model.req.DeleteFeatureResourceReq; -import cn.axzo.tyr.client.model.req.FeatureResourceTreeSaveReq; -import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq; -import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq; -import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode; -import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp; -import cn.axzo.tyr.server.model.ResourcePermission; -import cn.axzo.tyr.server.model.ResourcePermissionQueryDTO; -import cn.axzo.tyr.server.repository.entity.SaasFeatureResource; -import com.baomidou.mybatisplus.extension.service.IService; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * 功能资源服务 - * - * @version V1.0 - * @author: ZhanSiHu - * @date: 2024/4/3 10:17 - */ -public interface SaasFeatureResourceService extends IService { - - Long saveOrUpdateMenu(FeatureResourceTreeSaveReq req); - - void updateFeatureAuthType(Long featureId, Integer authType); - - /**递归的**/ - List batchListDescendant(List featureIds); - - SaasFeatureResource featureResourceById(Long featureId); - - FeatureResourceTreeNode getTreeFeatureDescendant(Long featureId, Integer featureType); - - /**菜单重排序**/ - void reorderMenuFeature(Long featureId, Integer offset); - - /** 根据ID查询导航菜单页面信息 仅可显示 - 限制查询字段 **/ - List listNavByIds(List featureIds, List featureTypes); - - /** 资源权限通用查询 **/ - List permissionQuery(ResourcePermissionQueryDTO param); - - /** 查询资源树 **/ - List getTree(GetFeatureResourceTreeReq req); - - SaasFeatureResource getByCode(String featureCode); - - Set listAuthFree(); - - List listByParentIdAndTerminalAndIds(Long parentId, String terminal, List featureIds); - - List list(PageSaasFeatureResourceReq param); - - PageResp page(PageSaasFeatureResourceReq param); - - void deleteFeatureResource(DeleteFeatureResourceReq param); - - void storeCache(StoreSaasFeatureResourceCache param); - - Map> listCache(ListSaasFeatureResourceCache param); - - @Data - @Builder - @NoArgsConstructor - @AllArgsConstructor - class StoreSaasFeatureResourceCache { - - private List saasFeatureResources; - } - - @Data - @Builder - @NoArgsConstructor - @AllArgsConstructor - class SaasFeatureResourceDTO { - private String terminal; - - private List features; - } - - @Data - @Builder - @NoArgsConstructor - @AllArgsConstructor - class ListSaasFeatureResourceCache { - - private Set terminals; - } - - @Data - @Builder - @NoArgsConstructor - @AllArgsConstructor - class SaasFeatureResourceCache { - - private Long featureId; - - private boolean notAuth; - - private Set parentIds; - - private String uniCode; - - /** - * 客户端版本号 - * 在根据版本号查询菜单树权限的时候需要 - */ - private Integer version; - } -} +package cn.axzo.tyr.server.service; + +import cn.axzo.foundation.page.PageResp; +import cn.axzo.tyr.client.model.req.DeleteFeatureResourceReq; +import cn.axzo.tyr.client.model.req.FeatureResourceTreeSaveReq; +import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq; +import cn.axzo.tyr.client.model.req.PageSaasFeatureResourceReq; +import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode; +import cn.axzo.tyr.client.model.res.SaasFeatureResourceResp; +import cn.axzo.tyr.server.model.ResourcePermission; +import cn.axzo.tyr.server.model.ResourcePermissionQueryDTO; +import cn.axzo.tyr.server.repository.entity.SaasFeatureResource; +import com.baomidou.mybatisplus.extension.service.IService; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 功能资源服务 + * + * @version V1.0 + * @author: ZhanSiHu + * @date: 2024/4/3 10:17 + */ +public interface SaasFeatureResourceService extends IService { + + Long saveOrUpdateMenu(FeatureResourceTreeSaveReq req); + + void updateFeatureAuthType(Long featureId, Integer authType); + + /**递归的**/ + List batchListDescendant(List featureIds); + + SaasFeatureResource featureResourceById(Long featureId); + + FeatureResourceTreeNode getTreeFeatureDescendant(Long featureId, Integer featureType); + + /**菜单重排序**/ + void reorderMenuFeature(Long featureId, Integer offset); + + /** 根据ID查询导航菜单页面信息 仅可显示 - 限制查询字段 **/ + List listNavByIds(List featureIds, List featureTypes); + + /** 资源权限通用查询 **/ + List permissionQuery(ResourcePermissionQueryDTO param); + + /** 查询资源树 **/ + List getTree(GetFeatureResourceTreeReq req); + + SaasFeatureResource getByCode(String featureCode); + + Set listAuthFree(); + + List listByParentIdAndTerminalAndIds(Long parentId, String terminal, List featureIds); + + List list(PageSaasFeatureResourceReq param); + + PageResp page(PageSaasFeatureResourceReq param); + + void deleteFeatureResource(DeleteFeatureResourceReq param); + + void storeCache(StoreSaasFeatureResourceCache param); + + Map> listCache(ListSaasFeatureResourceCache param); + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + class StoreSaasFeatureResourceCache { + + private List saasFeatureResources; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + class SaasFeatureResourceDTO { + private String terminal; + + private List features; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + class ListSaasFeatureResourceCache { + + private Set terminals; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + class SaasFeatureResourceCache { + + private Long featureId; + + private boolean notAuth; + + private Set parentIds; + + private String uniCode; + + /** + * 客户端版本号 + * 在根据版本号查询菜单树限的时候需要 + */ + private Integer version; + + /** + * 1、展示 + * 0、隐藏 + * FeatureResourceStatus + */ + private Integer status; + } +} diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasRoleGroupService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasRoleGroupService.java index 24029253..36958eb8 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasRoleGroupService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/SaasRoleGroupService.java @@ -4,6 +4,7 @@ import cn.axzo.foundation.page.PageResp; import cn.axzo.tyr.client.model.req.ListSaasRoleGroupParam; import cn.axzo.tyr.client.model.req.PageSaasRoleGroupParam; import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq; +import cn.axzo.tyr.client.model.req.SaasRoleGroupDeleteRequest; import cn.axzo.tyr.client.model.res.SaasRoleGroupDTO; import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO; import cn.axzo.tyr.server.repository.entity.SaasRoleGroup; @@ -32,6 +33,8 @@ public interface SaasRoleGroupService extends IService { void delete(List ids); + void deleteV2(SaasRoleGroupDeleteRequest request); + /** * 分组CODE查询角色分组 * @param categoryCode diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/WorkspaceProductService.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/WorkspaceProductService.java index 494b8098..b84067c0 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/WorkspaceProductService.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/WorkspaceProductService.java @@ -9,6 +9,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; +import java.util.Map; import java.util.Set; public interface WorkspaceProductService { @@ -43,6 +44,8 @@ public interface WorkspaceProductService { */ List listWorkspaceProductFeatureResourceCached(ListWorkspaceProductFeatureSourceCacheParam param); + Map> listAllWorkspaceProductCached(); + @Data @Builder @NoArgsConstructor diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/DataObjectServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/DataObjectServiceImpl.java index a18ea7e2..c9d27339 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/DataObjectServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/DataObjectServiceImpl.java @@ -1,5 +1,6 @@ package cn.axzo.tyr.server.service.impl; +import cn.axzo.basics.common.constant.enums.DeleteEnum; import cn.axzo.basics.common.exception.ServiceException; import cn.axzo.basics.common.page.PageResult; import cn.axzo.tyr.client.common.enums.ReturnCodeEnum; @@ -16,6 +17,7 @@ import cn.axzo.tyr.client.model.data.object.RuleScopeQueryBO; import cn.axzo.tyr.client.model.req.CreateDataObjectReq; import cn.axzo.tyr.client.model.req.EditDataObjectReq; import cn.axzo.tyr.client.model.req.PageDataObjectReq; +import cn.axzo.tyr.client.model.req.QueryDataObjectReq; import cn.axzo.tyr.client.model.res.DataObjectRes; import cn.axzo.tyr.client.model.res.SimpleDataObjectRes; import cn.axzo.tyr.server.repository.dao.DataObjectAttrDao; @@ -31,13 +33,17 @@ import cn.axzo.tyr.server.repository.entity.DataObjectRuleScope; import cn.axzo.tyr.server.service.DataObjectService; import cn.axzo.tyr.server.utils.mapper.DataObjectMapper; import cn.hutool.core.collection.CollUtil; +import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.metadata.IPage; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import groovy.lang.Tuple2; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionTemplate; import javax.annotation.Resource; @@ -64,6 +70,7 @@ public class DataObjectServiceImpl implements DataObjectService { private TransactionTemplate transactionTemplate; @Override + @Transactional(rollbackFor = Exception.class) public Long createDataObject(CreateDataObjectReq req) { // 校验 // objectName、objectCode不能重复 @@ -88,6 +95,7 @@ public class DataObjectServiceImpl implements DataObjectService { } List dataObjectRules = DataObjectMapper.INSTANCE.ruleBOs2Rules(req.getDataObjectRuleBOList()); + handleJobs(dataObjectRules, req.getDataObjectRuleBOList()); int size = (CollUtil.isNotEmpty(defaultDataObjectRules) ? defaultDataObjectRules.size() : 0) + (CollUtil.isNotEmpty(dataObjectRules) ? dataObjectRules.size() : 0); @@ -167,6 +175,7 @@ public class DataObjectServiceImpl implements DataObjectService { } @Override + @Transactional(rollbackFor = Exception.class) public void editDataObject(EditDataObjectReq req) { // 对象属性名和code不能重复 checkObjectAttrNameOrCodeUnique(req.getAttrs()); @@ -196,6 +205,7 @@ public class DataObjectServiceImpl implements DataObjectService { } List dataObjectRules = DataObjectMapper.INSTANCE.ruleBOs2Rules(req.getDataObjectRuleBOList()); + handleJobs(dataObjectRules, req.getDataObjectRuleBOList()); int size = (CollUtil.isNotEmpty(defaultDataObjectRules) ? defaultDataObjectRules.size() : 0) + (CollUtil.isNotEmpty(dataObjectRules) ? dataObjectRules.size() : 0); List generalObjectRuleList = new ArrayList<>(size); @@ -235,6 +245,7 @@ public class DataObjectServiceImpl implements DataObjectService { } @Override + @Transactional(rollbackFor = Exception.class) public void deleteDataObject(Long dataObjectId, Long updateBy) { List idList = Collections.singletonList(dataObjectId); transactionTemplate.executeWithoutResult(status -> { @@ -274,87 +285,22 @@ public class DataObjectServiceImpl implements DataObjectService { if (Objects.isNull(dataObject)) { throw new cn.axzo.framework.domain.ServiceException(ReturnCodeEnum.DATA_NOT_EXIST.getMessage()); } - DataObjectRes res = DataObjectMapper.INSTANCE.dataObject2DataObjectRes(dataObject); - // 获取数据对象字段 - DataObjectAttrQueryBO bo1 = DataObjectAttrQueryBO.builder().dataObjectId(dataObjectId).build(); - List objectAttrList = dataObjectAttrDao.listByBO(bo1); - Map attrMap; - if (CollUtil.isNotEmpty(objectAttrList)) { - List attributeBOS = DataObjectMapper.INSTANCE.dataObjectAttrs2AttributeBOs(objectAttrList); - List attributeBOList = attributeBOS.stream().sorted(Comparator.comparing(AttributeBO::getSort)).collect(Collectors.toList()); - res.setAttrs(attributeBOList); - attrMap = attributeBOList.stream().collect(Collectors.toMap(AttributeBO::getAttrCode, AttributeBO::getAttrName, (a, b) -> a)); - } else { - attrMap = null; + return buildDataObjectRes(dataObject); + } + + @Override + public DataObjectRes queryDataObject(QueryDataObjectReq req) { + List dataObjects = dataObjectDao.lambdaQuery() + .eq(DataObject::getIsDelete, DeleteEnum.NORMAL.getValue()) + .eq(StringUtils.isNotBlank(req.getDataObjectCode()), DataObject::getDataObjectCode, req.getDataObjectCode()) + .eq(Objects.nonNull(req.getTenantScope()), DataObject::getTenantScope, req.getTenantScope()) + .list(); + if (CollectionUtils.isEmpty(dataObjects)) { + log.warn("数据权限记录不存在,param:{}", JSON.toJSONString(req)); + return null; } - - // 获取数据对象规则 - DataObjectRuleQueryBO bo2 = DataObjectRuleQueryBO.builder().dataObjectId(dataObjectId).build(); - List dataObjectRules = dataObjectRuleDao.listByBO(bo2); - if (CollUtil.isNotEmpty(dataObjectRules)) { - res.setDataObjectRuleBOList(new ArrayList<>(dataObjectRules.size() - 1)); - dataObjectRules.forEach(e -> { - if (YesNoEnum.YES.getValue().equals(e.getIsDefault())) { - DefaultDataObjectRuleBO ruleBO = DataObjectMapper.INSTANCE.rule2DefaultRuleBO(e); - res.setDefaultDataObjectRuleBO(ruleBO); - } else { - DataObjectRuleBO ruleBO = DataObjectMapper.INSTANCE.rule2RuleBO(e); - res.getDataObjectRuleBOList().add(ruleBO); - } - }); - if (CollUtil.isNotEmpty(res.getDataObjectRuleBOList())) { - List sortedRuleList = res.getDataObjectRuleBOList().stream().sorted(Comparator.comparing(DataObjectRuleBO::getSort)).collect(Collectors.toList()); - res.setDataObjectRuleBOList(sortedRuleList); - } - } - - - // 获取数据对象规则字段 - RuleAttrQueryBO bo3 = RuleAttrQueryBO.builder().dataObjectId(dataObjectId).build(); - List ruleAttrList = dataObjectRuleAttrDao.listByBO(bo3); - if (CollUtil.isNotEmpty(attrMap) && CollUtil.isNotEmpty(ruleAttrList)) { - Map> ruleAttrMap = ruleAttrList.stream().collect(Collectors.groupingBy(DataObjectRuleAttr::getDataObjectRuleId)); - // 默认 - List ruleAttrList1 = ruleAttrMap.get(res.getDefaultDataObjectRuleBO().getDataObjectRuleId()); - if (CollUtil.isNotEmpty(ruleAttrList1)) { - List permissionBOs = DataObjectMapper.INSTANCE.ruleAttrs2AttrPermissionBOs(ruleAttrList1); - permissionBOs.forEach(e -> e.setAttrName(attrMap.get(e.getAttrCode()))); - List permissionBOList = permissionBOs.stream().sorted(Comparator.comparing(AttributePermissionBO::getSort)).collect(Collectors.toList()); - res.getDefaultDataObjectRuleBO().setAttributePermissionBOList(permissionBOList); - } - - //自定义 - if (CollUtil.isNotEmpty(res.getDataObjectRuleBOList())) { - res.getDataObjectRuleBOList().forEach(e -> buildRuleAttr(attrMap, ruleAttrMap, e)); - } - } - - // 获取数据对象规则范围 - RuleScopeQueryBO bo4 = RuleScopeQueryBO.builder().dataObjectId(dataObjectId).build(); - List scopeList = dataObjectRuleScopeDao.listByBO(bo4); - if (CollUtil.isNotEmpty(scopeList)) { - Map> scopeMap = scopeList.stream().collect(Collectors.groupingBy(DataObjectRuleScope::getDataObjectRuleId)); - // 默认 - List defaultScopeList = scopeMap.get(res.getDefaultDataObjectRuleBO().getDataObjectRuleId()); - if (CollUtil.isNotEmpty(defaultScopeList)) { - List relationIdList = defaultScopeList.stream().map(DataObjectRuleScope::getRelationId).collect(Collectors.toList()); - res.getDefaultDataObjectRuleBO().setRelationId(relationIdList); - } - - //自定义 - if (CollUtil.isNotEmpty(res.getDataObjectRuleBOList())) { - res.getDataObjectRuleBOList().forEach(e -> { - List scopeList1 = scopeMap.get(e.getDataObjectRuleId()); - if (CollUtil.isNotEmpty(scopeList1)) { - List relationIdList = scopeList1.stream().map(DataObjectRuleScope::getRelationId).collect(Collectors.toList()); - e.setRelationId(relationIdList); - } - }); - } - } - - return res; + return buildDataObjectRes(dataObjects.get(0)); } private static void buildRuleAttr(Map attrMap, Map> ruleAttrMap, DataObjectRuleBO e) { @@ -428,4 +374,114 @@ public class DataObjectServiceImpl implements DataObjectService { } } } + + private DataObjectRes buildDataObjectRes(DataObject dataObject) { + DataObjectRes res = DataObjectMapper.INSTANCE.dataObject2DataObjectRes(dataObject); + + // 获取数据对象字段 + DataObjectAttrQueryBO bo1 = DataObjectAttrQueryBO.builder().dataObjectId(dataObject.getId()).build(); + List objectAttrList = dataObjectAttrDao.listByBO(bo1); + Map attrMap; + if (CollUtil.isNotEmpty(objectAttrList)) { + List attributeBOS = DataObjectMapper.INSTANCE.dataObjectAttrs2AttributeBOs(objectAttrList); + List attributeBOList = attributeBOS.stream().sorted(Comparator.comparing(AttributeBO::getSort)).collect(Collectors.toList()); + res.setAttrs(attributeBOList); + attrMap = attributeBOList.stream().collect(Collectors.toMap(AttributeBO::getAttrCode, AttributeBO::getAttrName, (a, b) -> a)); + } else { + attrMap = null; + } + + // 获取数据对象规则 + DataObjectRuleQueryBO bo2 = DataObjectRuleQueryBO.builder().dataObjectId(dataObject.getId()).build(); + List dataObjectRules = dataObjectRuleDao.listByBO(bo2); + if (CollUtil.isNotEmpty(dataObjectRules)) { + res.setDataObjectRuleBOList(new ArrayList<>(dataObjectRules.size() - 1)); + dataObjectRules.forEach(e -> { + if (YesNoEnum.YES.getValue().equals(e.getIsDefault())) { + DefaultDataObjectRuleBO ruleBO = DataObjectMapper.INSTANCE.rule2DefaultRuleBO(e); + res.setDefaultDataObjectRuleBO(ruleBO); + } else { + DataObjectRuleBO ruleBO = DataObjectMapper.INSTANCE.rule2RuleBO(e); + res.getDataObjectRuleBOList().add(ruleBO); + } + }); + if (CollUtil.isNotEmpty(res.getDataObjectRuleBOList())) { + List sortedRuleList = res.getDataObjectRuleBOList().stream().sorted(Comparator.comparing(DataObjectRuleBO::getSort)).collect(Collectors.toList()); + res.setDataObjectRuleBOList(sortedRuleList); + } + } + + + // 获取数据对象规则字段 + RuleAttrQueryBO bo3 = RuleAttrQueryBO.builder().dataObjectId(dataObject.getId()).build(); + List ruleAttrList = dataObjectRuleAttrDao.listByBO(bo3); + if (CollUtil.isNotEmpty(attrMap) && CollUtil.isNotEmpty(ruleAttrList)) { + Map> ruleAttrMap = ruleAttrList.stream().collect(Collectors.groupingBy(DataObjectRuleAttr::getDataObjectRuleId)); + // 默认 + List ruleAttrList1 = ruleAttrMap.get(res.getDefaultDataObjectRuleBO().getDataObjectRuleId()); + if (CollUtil.isNotEmpty(ruleAttrList1)) { + List permissionBOs = DataObjectMapper.INSTANCE.ruleAttrs2AttrPermissionBOs(ruleAttrList1); + permissionBOs.forEach(e -> e.setAttrName(attrMap.get(e.getAttrCode()))); + List permissionBOList = permissionBOs.stream().sorted(Comparator.comparing(AttributePermissionBO::getSort)).collect(Collectors.toList()); + res.getDefaultDataObjectRuleBO().setAttributePermissionBOList(permissionBOList); + } + + //自定义 + if (CollUtil.isNotEmpty(res.getDataObjectRuleBOList())) { + res.getDataObjectRuleBOList().forEach(e -> buildRuleAttr(attrMap, ruleAttrMap, e)); + } + } + + // 获取数据对象规则范围 + RuleScopeQueryBO bo4 = RuleScopeQueryBO.builder().dataObjectId(dataObject.getId()).build(); + List scopeList = dataObjectRuleScopeDao.listByBO(bo4); + if (CollUtil.isNotEmpty(scopeList)) { + Map> scopeMap = scopeList.stream().collect(Collectors.groupingBy(DataObjectRuleScope::getDataObjectRuleId)); + // 默认 + List defaultScopeList = scopeMap.get(res.getDefaultDataObjectRuleBO().getDataObjectRuleId()); + if (CollUtil.isNotEmpty(defaultScopeList)) { + List relationIdList = defaultScopeList.stream().map(DataObjectRuleScope::getRelationId).collect(Collectors.toList()); + res.getDefaultDataObjectRuleBO().setRelationId(relationIdList); + } + + //自定义 + if (CollUtil.isNotEmpty(res.getDataObjectRuleBOList())) { + res.getDataObjectRuleBOList().forEach(e -> { + List scopeList1 = scopeMap.get(e.getDataObjectRuleId()); + if (CollUtil.isNotEmpty(scopeList1)) { + List relationIdList = scopeList1.stream().map(DataObjectRuleScope::getRelationId).collect(Collectors.toList()); + e.setRelationId(relationIdList); + e.setRelationCodes(scopeList1.stream().map(DataObjectRuleScope::getRelationCode).filter(StringUtils::isNotBlank).collect(Collectors.toList())); + } + }); + } + } + + return res; + } + + private void handleJobs(List dataObjectRules, List dataObjectRuleBOList) { + if (CollectionUtils.isEmpty(dataObjectRules) || CollectionUtils.isEmpty(dataObjectRuleBOList)) { + return; + } + + Map jobInfoMap = Maps.newHashMap(); + for (DataObjectRuleBO ruleBO : dataObjectRuleBOList) { + if (1 == ruleBO.getRuleScopeType() && CollectionUtils.isNotEmpty(ruleBO.getJobs())) { + ruleBO.getJobs().forEach(e -> { + jobInfoMap.put(e.getId(), e); + }); + } + } + + for (DataObjectRule rule : dataObjectRules) { + if (1 == rule.getRuleScopeType() && CollectionUtils.isNotEmpty(rule.getDataObjectRuleScopeList())) { + rule.getDataObjectRuleScopeList().forEach(e -> { + if (Objects.nonNull(e.getRelationId()) && jobInfoMap.containsKey(e.getRelationId())) { + e.setRelationCode(jobInfoMap.get(e.getRelationId()).getCode()); + } + }); + } + } + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/DataResourceServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/DataResourceServiceImpl.java index 0273bd77..e7ceeb53 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/DataResourceServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/DataResourceServiceImpl.java @@ -30,6 +30,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Objects; @@ -48,6 +49,7 @@ public class DataResourceServiceImpl implements DataResourceService { private final SaasFeatureDao saasFeatureDao; private final SaasFeatureDataResourceDao saasFeatureDataResourceDao; @Override + @Transactional(rollbackFor = Exception.class) public void create(CreateDataResourceParam param) { DataResource existDataResource = dataResourceDao.lambdaQuery() .eq(DataResource::getResourceCode, param.getResourceCode()) @@ -72,6 +74,7 @@ public class DataResourceServiceImpl implements DataResourceService { } @Override + @Transactional(rollbackFor = Exception.class) public boolean delete(DeleteDataResourceParam param) { DataResource dataResource = dataResourceDao.getById(param.getId()); if (Objects.nonNull(dataResource)) { @@ -109,6 +112,7 @@ public class DataResourceServiceImpl implements DataResourceService { } @Override + @Transactional(rollbackFor = Exception.class) public boolean update(UpdateDataResourceParam param) { DataResource dataResource = new DataResource(); BeanUtils.copyProperties(param, dataResource); @@ -116,6 +120,7 @@ public class DataResourceServiceImpl implements DataResourceService { } @Override + @Transactional(rollbackFor = Exception.class) public void createDataResourceSaasFeature(DataResourceSaasFeatureParam param) { DataResource existDataResource = dataResourceDao.lambdaQuery() .eq(DataResource::getResourceCode, param.getResourceCode()) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/FeatureResourceSyncServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/FeatureResourceSyncServiceImpl.java index fcced913..c97a8a99 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/FeatureResourceSyncServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/FeatureResourceSyncServiceImpl.java @@ -39,6 +39,7 @@ import org.slf4j.MDC; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.*; import java.util.Collections; @@ -131,6 +132,7 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic } @Override + @Transactional(rollbackFor = Exception.class) public void syncFromBase(ResourceSyncReq req) { req.setTraceId(MDC.get(Constants.CTX_LOG_ID_MDC)); if (req.getIds().size() > 1) { @@ -241,6 +243,16 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic baseResource.setCreateBy(operatorId); baseResource.setUpdateBy(operatorId); newResource(baseResource, parent); + + Event event = Event.builder() + .targetType(SAAS_FEATURE_RESOURCE_TARGET_TYPE) + .eventCode(SAAS_FEATURE_RESOURCE_UPSERT.getEventCode()) + .data(SaasFeatureResourceUpsertPayload.builder() + .newValue(featureResourceDao.getById(baseResource.getId())) + .action(SaasFeatureResource.Action.CREATE) + .build()) + .build(); + mqProducer.send(event); } else { //更新 - 恢复不能变更的数据 baseResource.setId(resource.getId()); @@ -251,6 +263,17 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic baseResource.setUpdateBy(operatorId); baseResource.setAppItemId(resource.getAppItemId()); featureResourceDao.updateById(baseResource); + + Event event = Event.builder() + .targetType(SAAS_FEATURE_RESOURCE_TARGET_TYPE) + .eventCode(SAAS_FEATURE_RESOURCE_UPSERT.getEventCode()) + .data(SaasFeatureResourceUpsertPayload.builder() + .newValue(featureResourceDao.getById(baseResource.getId())) + .oldValue(resource) + .action(SaasFeatureResource.Action.UPDATE) + .build()) + .build(); + mqProducer.send(event); } // 处理资源关联的权限 @@ -353,13 +376,11 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic logResourceBindRoleDO.setRoleCodes(saasRoles.stream().filter(e -> existRoleIds.contains(e.getId())).map(SaasRole::getRoleCode).collect(Collectors.toList())); } + // 同步这里不要求效率,没有角色id,全部刷新,也不容易找这个 Event event = Event.builder() .targetType(ROLE_PERMISSION_TARGET_TYPE) .eventCode(ROLE_PERMISSION_CREATED.getEventCode()) .data(RolePermissionCreatedPayload.builder() - .roleIds(saasRoles.stream() - .map(SaasRole::getId) - .collect(Collectors.toSet())) .build()) .build(); mqProducer.send(event); diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionPointServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionPointServiceImpl.java index 31b42688..ac20abdb 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionPointServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionPointServiceImpl.java @@ -4,6 +4,7 @@ import cn.axzo.basics.common.BeanMapper; import cn.axzo.basics.common.util.StopWatchUtil; import cn.axzo.basics.common.util.TreeUtil; import cn.axzo.framework.domain.web.code.BaseCode; +import cn.axzo.tyr.client.common.enums.PermissionRelationOperateLogSceneEnum; import cn.axzo.framework.rocketmq.Event; import cn.axzo.tyr.client.model.dict.request.BasicDictNodeReq; import cn.axzo.tyr.client.model.dict.request.BasicDictQueryReq; @@ -13,6 +14,16 @@ import cn.axzo.tyr.client.model.enums.DictTypeFiledEnum; import cn.axzo.tyr.client.model.enums.DictWorkSpaceTypeEnum; import cn.axzo.tyr.client.model.enums.FeatureDataType; import cn.axzo.tyr.client.model.enums.FeatureType; +import cn.axzo.tyr.client.model.permission.DeletePermissionPointRequest; +import cn.axzo.tyr.client.model.permission.PermissionPointDTO; +import cn.axzo.tyr.client.model.permission.PermissionPointListQueryRequest; +import cn.axzo.tyr.client.model.permission.PermissionPointMoveRequest; +import cn.axzo.tyr.client.model.permission.PermissionPointTreeNode; +import cn.axzo.tyr.client.model.permission.PermissionPointTreeQueryReq; +import cn.axzo.tyr.client.model.permission.PermissionPointVO; +import cn.axzo.tyr.client.model.req.PermissionOperateLogReq; +import cn.axzo.tyr.client.model.req.QueryPermissionByIdsReq; +import cn.axzo.tyr.client.model.res.SimplePermissionPointResp; import cn.axzo.tyr.client.model.permission.PermissionPointDTO; import cn.axzo.tyr.client.model.permission.PermissionPointListQueryRequest; import cn.axzo.tyr.client.model.permission.PermissionPointMoveRequest; @@ -28,8 +39,10 @@ import cn.axzo.tyr.server.repository.dao.SaasFeatureDao; import cn.axzo.tyr.server.repository.dao.SaasPgroupPermissionRelationDao; import cn.axzo.tyr.server.repository.dao.SaasProductModuleFeatureRelationDao; import cn.axzo.tyr.server.repository.entity.SaasFeature; +import cn.axzo.tyr.server.repository.mapper.SaasFeatureMapper; import cn.axzo.tyr.server.service.PermissionPointService; import cn.axzo.tyr.server.service.SaasBasicDictService; +import cn.axzo.tyr.server.service.SaasPgroupPermissionRelationOperateLogService; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.Wrapper; @@ -38,6 +51,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Collections; @@ -51,6 +67,24 @@ import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; +import static cn.axzo.tyr.client.model.enums.FeatureType.BUTTON; +import static cn.axzo.tyr.client.model.enums.FeatureType.MODULE; +import static cn.axzo.tyr.server.common.constants.PermissionConstant.FEATURE_BIZ_NO_PREFIX; +import static cn.axzo.tyr.server.common.constants.PermissionConstant.FEATURE_PATH_DELIMITER; +import static cn.axzo.tyr.server.common.constants.PermissionConstant.FEATURE_TOP_BIZ_NO; +import static cn.axzo.tyr.server.common.constants.PermissionConstant.FEATURE_TOP_PATH; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + import static cn.axzo.tyr.client.model.enums.FeatureType.BUTTON; import static cn.axzo.tyr.client.model.enums.FeatureType.MODULE; import static cn.axzo.tyr.server.common.constants.PermissionConstant.FEATURE_BIZ_NO_PREFIX; @@ -71,10 +105,13 @@ import static cn.axzo.tyr.server.event.inner.EventTypeEnum.SAAS_FEATURE_UPSERT; @Service public class PermissionPointServiceImpl implements PermissionPointService { + private final SaasFeatureMapper saasFeatureMapper; private final SaasFeatureDao saasFeatureDao; private final SaasBasicDictService saasBasicDictService; private final SaasPgroupPermissionRelationDao saasPgroupPermissionRelationDao; private final SaasProductModuleFeatureRelationDao saasProductModuleFeatureRelationDao; + private final SaasPgroupPermissionRelationOperateLogService saasPgroupPermissionRelationOperateLogService; + private final TransactionTemplate transactionTemplate; private final MqProducer mqProducer; private static final String TARGET_TYPE = "saasFeatureId"; @@ -331,6 +368,7 @@ public class PermissionPointServiceImpl implements PermissionPointService { } @Override + @Transactional(rollbackFor = Exception.class) public PermissionPointDTO save(PermissionPointDTO dto) { if (dto.getId() == null) { return doInsert(dto); @@ -350,6 +388,11 @@ public class PermissionPointServiceImpl implements PermissionPointService { this.saasFeatureDao.updateById(saasFeature); //返回一些要用的数据 dto.setBusinessNo(feature.getBusinessNo()); + try { + saveOperateLogForInsertOrUpdate(dto, feature.getId()); + } catch (Exception e) { + log.warn("error save operate log", e); + } sendMsg(SaasFeatureUpsertPayload.builder() .id(dto.getId()) @@ -389,6 +432,11 @@ public class PermissionPointServiceImpl implements PermissionPointService { dto.setBusinessNo(saasFeature.getBusinessNo()); //调整排序 - 兼容处理老数据,数据规范化 changeSort(saasFeature, saasFeature.getSort()); + try { + saveOperateLogForInsertOrUpdate(dto, saasFeature.getId()); + } catch (Exception e) { + log.warn("error save operate log", e); + } sendMsg(SaasFeatureUpsertPayload.builder() .id(dto.getId()) @@ -397,6 +445,18 @@ public class PermissionPointServiceImpl implements PermissionPointService { return dto; } + private void saveOperateLogForInsertOrUpdate(PermissionPointDTO request, Long permissionId) { + SaasFeature feature = saasFeatureDao.getById(permissionId); + PermissionOperateLogReq log = new PermissionOperateLogReq(); + log.setTableName(SaasPgroupPermissionRelationOperateLogServiceImpl.TABLE_NAME_SAAS_FEATURE); + log.setScene(PermissionRelationOperateLogSceneEnum.OLD_OMS_SAAS_FEATURE__SAVE_OR_UPDATE.getValue()); + log.setSceneId(permissionId + ""); + log.setOperatorId(request.determineOperator().getPersonId()); + log.setRequestData(request); + log.setOperateData(feature); + saasPgroupPermissionRelationOperateLogService.save(log); + } + private void checkParentType(FeatureType featureType, SaasFeature parent) { //检查父级元素类型 switch (featureType) { @@ -425,9 +485,21 @@ public class PermissionPointServiceImpl implements PermissionPointService { } } - @Transactional(rollbackFor = Throwable.class) @Override - public List delete(Long permissionPointId) { + @SuppressWarnings({ + "SpringTransactionalMethodCallsInspection", + "It's good, we use transaction template" + }) + public List delete(Long permissionId) { + DeletePermissionPointRequest request = new DeletePermissionPointRequest(); + request.setPermissionId(permissionId); + return transactionTemplate.execute(unused -> deleteV2(request)); + } + + @Override + @Transactional(rollbackFor = Throwable.class) + public List deleteV2(DeletePermissionPointRequest request) { + Long permissionPointId = request.getPermissionId(); List delIds = new ArrayList<>(); List bizNoList = new ArrayList<>(); SaasFeature feature = getAndCheck(permissionPointId); @@ -453,6 +525,12 @@ public class PermissionPointServiceImpl implements PermissionPointService { //删除关联数据 this.saasPgroupPermissionRelationDao.removeByPermissionPointIds(delIds); this.saasProductModuleFeatureRelationDao.removeByPermissionPointIds(delIds); + try { + // 记这条主记录的日志就够了 + saveOperateLogForDelete(request); + } catch (Exception e) { + log.warn("error save operate log", e); + } sendMsg(SaasFeatureUpsertPayload.builder() .id(feature.getId()) @@ -461,8 +539,20 @@ public class PermissionPointServiceImpl implements PermissionPointService { return bizNoList; } + private void saveOperateLogForDelete(DeletePermissionPointRequest request) { + SaasFeature deletedFeature = saasFeatureMapper.getByIdDeleteAware(request.getPermissionId()); + PermissionOperateLogReq log = new PermissionOperateLogReq(); + log.setTableName(SaasPgroupPermissionRelationOperateLogServiceImpl.TABLE_NAME_SAAS_FEATURE); + log.setScene(PermissionRelationOperateLogSceneEnum.OLD_OMS_SAAS_FEATURE__DELETE.getValue()); + log.setSceneId(request.getPermissionId() + ""); + log.setOperatorId(request.determineOperator().getPersonId()); + log.setRequestData(request); + log.setOperateData(deletedFeature); + saasPgroupPermissionRelationOperateLogService.save(log); + } @Override + @Transactional(rollbackFor = Exception.class) public void move(PermissionPointMoveRequest request) { SaasFeature feature = getAndCheck(request.getPermissionId()); changeParent(feature, request); diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionQueryServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionQueryServiceImpl.java index 8a332750..637e1011 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionQueryServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/PermissionQueryServiceImpl.java @@ -13,6 +13,7 @@ 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; import cn.axzo.tyr.client.common.enums.FeatureResourceAuthType; +import cn.axzo.tyr.client.common.enums.FeatureResourceStatus; import cn.axzo.tyr.client.common.enums.FeatureResourceType; import cn.axzo.tyr.client.common.enums.RoleTypeEnum; import cn.axzo.tyr.client.model.base.FeatureResourceExtraDO; @@ -523,6 +524,7 @@ public class PermissionQueryServiceImpl implements PermissionQueryService { .uniCodes(req.getUniCodes()) .versionMax(req.getVersionMax()) .parentUniCode(req.getParentUniCode()) + .status(req.getStatus()) .build(); Set featureIds = listUserPermissionFeatureIds(treePermissionReq); @@ -839,6 +841,18 @@ public class PermissionQueryServiceImpl implements PermissionQueryService { || treePermissionReq.getVersionMax().compareTo(f.getVersion()) > -1) .collect(Collectors.toList()); + // 查询显示的菜单,需要过滤掉隐藏的节点,如果父节点隐藏,则下面所有子节点也需要过滤掉 + if (Objects.equals(treePermissionReq.getStatus(), FeatureResourceStatus.NORMAL)) { + Set normalFeatureIds = allFeatureResources.stream() + .filter(e -> Objects.equals(e.getStatus(), FeatureResourceStatus.NORMAL.getCode())) + .map(SaasFeatureResourceService.SaasFeatureResourceCache::getFeatureId) + .collect(Collectors.toSet()); + + allFeatureResources = allFeatureResources.stream() + .filter(e -> normalFeatureIds.contains(e.getFeatureId()) && normalFeatureIds.containsAll(e.getParentIds())) + .collect(Collectors.toList()); + } + if (StringUtils.isBlank(treePermissionReq.getParentUniCode())) { return allFeatureResources; } @@ -847,7 +861,8 @@ public class PermissionQueryServiceImpl implements PermissionQueryService { .filter(e -> Objects.equals(e.getUniCode(), treePermissionReq.getParentUniCode())) .map(SaasFeatureResourceService.SaasFeatureResourceCache::getFeatureId) .findFirst(); - return parentId.map(aLong -> allFeatureResources.stream() + final List finalFeatureResources = allFeatureResources; + return parentId.map(aLong -> finalFeatureResources.stream() .filter(e -> e.getParentIds().contains(aLong)) .collect(Collectors.toList())) .orElse(Collections.emptyList()); @@ -862,11 +877,17 @@ public class PermissionQueryServiceImpl implements PermissionQueryService { } List saasRoleUsers = listUserPermission(treePermissionReq); + if (CollectionUtils.isEmpty(saasRoleUsers)) { + return Collections.emptySet(); + } Map> roleFeatureResourceMap = listRoleFeatureResource(saasRoleUsers, treePermissionReq); List workspaceProductFeatureSources = listWorkspaceProducts(treePermissionReq); + if (CollectionUtils.isEmpty(workspaceProductFeatureSources)) { + return Collections.emptySet(); + } //免授权 Set authFreeFeatureIds = allFeatureResources.stream() .filter(e -> BooleanUtils.isTrue(e.isNotAuth())) diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductFeatureRelationServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductFeatureRelationServiceImpl.java index 8e0f0258..ca88d8ce 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductFeatureRelationServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductFeatureRelationServiceImpl.java @@ -11,11 +11,14 @@ 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; import cn.axzo.tyr.client.common.enums.FeatureResourceType; +import cn.axzo.tyr.client.common.enums.PermissionRelationOperateLogSceneEnum; +import cn.axzo.tyr.client.model.product.OldUpdateFeatureRelationRequestV2; import cn.axzo.tyr.client.model.product.ProductFeatureRelationSearchReq; import cn.axzo.tyr.client.model.product.ProductFeatureRelationUpdateReq; import cn.axzo.tyr.client.model.product.ProductFeatureRelationVO; import cn.axzo.tyr.client.model.req.FeatureIdPair; import cn.axzo.tyr.client.model.req.PageProductFeatureRelationReq; +import cn.axzo.tyr.client.model.req.PermissionOperateLogReq; import cn.axzo.tyr.server.config.MqProducer; import cn.axzo.tyr.server.event.payload.ProductPermissionCreatedPayload; import cn.axzo.tyr.server.repository.dao.ProductModuleDao; @@ -28,6 +31,7 @@ import cn.axzo.tyr.server.repository.entity.SaasFeatureResource; import cn.axzo.tyr.server.repository.entity.SaasProductModuleFeatureRelation; import cn.axzo.tyr.server.repository.mapper.SaasProductModuleFeatureRelationMapper; import cn.axzo.tyr.server.service.ProductFeatureRelationService; +import cn.axzo.tyr.server.service.SaasPgroupPermissionRelationOperateLogService; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.StopWatch; import cn.hutool.core.util.StrUtil; @@ -55,6 +59,7 @@ import java.util.stream.Collectors; import static cn.axzo.tyr.server.event.inner.EventTypeEnum.PRODUCT_PERMISSION_CREATED; import static cn.axzo.tyr.server.util.RpcInternalUtil.checkAndGetData; +import static java.util.stream.Collectors.joining; /** * 产品与权限点的 Service 接口实现 @@ -72,6 +77,7 @@ public class ProductFeatureRelationServiceImpl extends ServiceImpl updateFeatureRelation(List req) { + OldUpdateFeatureRelationRequestV2 requestV2 = new OldUpdateFeatureRelationRequestV2(); + requestV2.setRelations(req); + requestV2.setOperator(null); + return updateFeatureRelationV2(requestV2); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public ApiResult updateFeatureRelationV2(OldUpdateFeatureRelationRequestV2 request) { + if (CollectionUtils.isEmpty(request.getRelations())) { + return ApiResult.ok(false); + } + List req = request.getRelations(); List productIds = req.stream().map(ProductFeatureRelationUpdateReq::getProductModuleId).distinct().collect(Collectors.toList()); if (!CollectionUtils.isEmpty(productIds)) { saasProductModuleFeatureRelationDao.remove(new LambdaQueryWrapper() @@ -107,10 +126,37 @@ public class ProductFeatureRelationServiceImpl extends ServiceImpl saveList) { + String productModuleIds = saveList.stream() + .map(BaseEntity::getId) + .distinct() + .map(String::valueOf) + .collect(joining(",")); + productModuleIds = org.apache.commons.lang3.StringUtils.truncate(productModuleIds, 254); + PermissionOperateLogReq log = new PermissionOperateLogReq(); + log.setTableName(SaasPgroupPermissionRelationOperateLogServiceImpl.TABLE_NAME_PRODUCT_MODULE_FEATURE_RELATION); + log.setScene(PermissionRelationOperateLogSceneEnum.OLD_OMS_PRODUCT_PERMISSION_POINT__SAVE_BATCH.getValue()); + log.setSceneId(productModuleIds); + log.setOperatorId(request.determineOperator().getPersonId()); + log.setRequestData(request); + log.setOperateData(saveList); + saasPgroupPermissionRelationOperateLogService.save(log); + } + @Override @Transactional(rollbackFor = Exception.class) public void updateFeatureResourceRelation(List req, int relationType) { diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductPermissionCacheServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductPermissionCacheServiceImpl.java index ba3d97bb..6e1415b6 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductPermissionCacheServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductPermissionCacheServiceImpl.java @@ -21,6 +21,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.BooleanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisTemplate; @@ -39,6 +40,7 @@ import static cn.axzo.tyr.server.config.exception.BizResultCode.REDIS_PRODUCT_NO @Slf4j @Service +@RefreshScope public class ProductPermissionCacheServiceImpl implements ProductPermissionCacheService { private static final String PRODUCT_PERMISSION_KEY = "product:permission:%s"; @@ -51,8 +53,8 @@ public class ProductPermissionCacheServiceImpl implements ProductPermissionCache private CacheProductPermissionHandler cacheProductPermissionHandler; /** 产品权限缓存过期时间 **/ - @Value("${product.permission.expire:180}") - private Long expireInDays; + @Value("${product.permission.expire.minutes:14}") + private Long expireInMinutes; @Override public Map> list(ListProductPermissionParam param) { @@ -136,7 +138,7 @@ public class ProductPermissionCacheServiceImpl implements ProductPermissionCache // 存在hash中部分key移除,为了处理快,直接把redisKey删除掉,修改不频繁 redisTemplate.delete(redisKey); RedisClient.HashOps.hPutAll(redisKey, redisValues); - redisTemplate.expire(redisKey, expireInDays, TimeUnit.DAYS); + redisTemplate.expire(redisKey, expireInMinutes, TimeUnit.MINUTES); log.info("succeed to store product permission: redisKey:{} value:{}", redisKey, redisValues); } return null; diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductSaasFeatureResourceCacheServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductSaasFeatureResourceCacheServiceImpl.java index 9bad1442..97d7c6cc 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductSaasFeatureResourceCacheServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductSaasFeatureResourceCacheServiceImpl.java @@ -17,6 +17,7 @@ import com.google.common.collect.Streams; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisTemplate; @@ -36,6 +37,7 @@ import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation. @Slf4j @Service +@RefreshScope public class ProductSaasFeatureResourceCacheServiceImpl implements ProductSaasFeatureResourceCacheService { private static final String PRODUCT_SAAS_FEATURE_RESOURCE_KEY = "product:feature:resource:%s"; @@ -47,8 +49,8 @@ public class ProductSaasFeatureResourceCacheServiceImpl implements ProductSaasFe @Autowired private CacheProductSaasFeatureResourceHandler cacheProductSaasFeatureResourceHandler; - @Value("${product.feature.resouce.expire:180}") - private Long expireInDays; + @Value("${product.feature.resouce.expire.minutes:14}") + private Long expireInMinutes; @Override public Map> list(ListProductFeatureResourceParam param) { @@ -82,7 +84,7 @@ public class ProductSaasFeatureResourceCacheServiceImpl implements ProductSaasFe // 存在hash中部分key移除,为了处理快,直接把redisKey删除掉,修改不频繁 redisTemplate.delete(redisKey); RedisClient.HashOps.hPutAll(redisKey, redisValues); - redisTemplate.expire(redisKey, expireInDays, TimeUnit.DAYS); + redisTemplate.expire(redisKey, expireInMinutes, TimeUnit.MINUTES); log.info("succeed to store product featureResource: redisKey:{} value:{}", redisKey, redisValues); } return null; diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductServiceImpl.java index d84898e6..c4d76d41 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/ProductServiceImpl.java @@ -15,20 +15,31 @@ import cn.axzo.tyr.client.model.dict.request.BasicDictQueryReq; import cn.axzo.tyr.client.model.dict.response.BasicDictNodeResp; import cn.axzo.tyr.client.model.enums.ProductModuleCategoryEnum; import cn.axzo.tyr.client.model.enums.WorkspaceTypeCodeEnum; -import cn.axzo.tyr.client.model.product.*; +import cn.axzo.tyr.client.model.product.ProductAddReq; +import cn.axzo.tyr.client.model.product.ProductFeatureRelationSearchReq; +import cn.axzo.tyr.client.model.product.ProductFeatureRelationUpdateReq; +import cn.axzo.tyr.client.model.product.ProductFeatureRelationVO; +import cn.axzo.tyr.client.model.product.ProductSearchListReq; +import cn.axzo.tyr.client.model.product.ProductSearchPageReq; +import cn.axzo.tyr.client.model.product.ProductUpdateReq; +import cn.axzo.tyr.client.model.product.ProductVO; +import cn.axzo.tyr.client.model.req.PermissionOperateLogReq; import cn.axzo.tyr.client.model.req.ProductSaveReq; import cn.axzo.tyr.client.model.req.UpdateProductStatusReq; import cn.axzo.tyr.client.model.res.GovernmentTerminalResp; import cn.axzo.tyr.client.model.res.WorkspaceProductResp; import cn.axzo.tyr.server.model.RelationOperateLogProductBindResourceDO; -import cn.axzo.tyr.server.model.RelationOperateLogResourceBindElementDO; +import cn.axzo.tyr.server.repository.dao.ProductModuleDao; import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao; import cn.axzo.tyr.server.repository.entity.ProductModule; -import cn.axzo.tyr.server.repository.dao.ProductModuleDao; import cn.axzo.tyr.server.repository.entity.SaasFeatureResource; import cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelationOperateLog; import cn.axzo.tyr.server.repository.entity.SaasProductModuleFeatureRelation; -import cn.axzo.tyr.server.service.*; +import cn.axzo.tyr.server.service.ProductFeatureRelationService; +import cn.axzo.tyr.server.service.ProductService; +import cn.axzo.tyr.server.service.SaasBasicDictService; +import cn.axzo.tyr.server.service.SaasFeatureResourceService; +import cn.axzo.tyr.server.service.SaasPgroupPermissionRelationOperateLogService; import cn.axzo.tyr.server.util.RpcInternalUtil; import cn.azxo.framework.common.constatns.Constants; import cn.hutool.core.collection.CollectionUtil; @@ -46,7 +57,14 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; @@ -152,6 +170,7 @@ public class ProductServiceImpl implements ProductService { } @Override + @Transactional(rollbackFor = Exception.class) public ApiResult add(ProductAddReq req) { Optional optProduct = productModuleDao.lambdaQuery() .eq(ProductModule::getProductName, req.getProductName()) @@ -168,6 +187,7 @@ public class ProductServiceImpl implements ProductService { } @Override + @Transactional(rollbackFor = Exception.class) public ApiResult update(ProductUpdateReq req) { Optional optProduct = productModuleDao.lambdaQuery() .eq(ProductModule::getProductName, req.getProductName()) @@ -181,10 +201,27 @@ public class ProductServiceImpl implements ProductService { productModule.setOuType(org.apache.commons.lang3.StringUtils.join(req.getOuTypes(),",")); } productModuleDao.updateById(productModule); + try { + saveOperateLogForUpdateProduct(req, productModule); + } catch (Exception e) { + log.warn("error save operate log", e); + } return ApiResult.ok(BeanMapper.copyBeanIgnoreNull(productModule, ProductVO.class)); } + private void saveOperateLogForUpdateProduct(ProductUpdateReq req, ProductModule productModule) { + PermissionOperateLogReq log = new PermissionOperateLogReq(); + log.setTableName(SaasPgroupPermissionRelationOperateLogServiceImpl.TABLE_NAME_PRODUCT); + log.setScene(PermissionRelationOperateLogSceneEnum.OLD_OMS_PRODUCT__UPDATE.getValue()); + log.setSceneId(productModule.getId() + ""); + log.setOperatorId(req.determineOperator().getPersonId()); + log.setRequestData(req); + log.setOperateData(productModule); + saasPgroupPermissionRelationOperateLogService.save(log); + } + @Override + @Transactional(rollbackFor = Exception.class) public ApiResult delete(Long id) { ProductModule productModule = productModuleDao.getById(id); AssertUtil.isTrue(Objects.nonNull(productModule), "产品不存在"); diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RolePermissionCacheServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RolePermissionCacheServiceImpl.java index a237d7f9..43ac0dbb 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RolePermissionCacheServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RolePermissionCacheServiceImpl.java @@ -16,6 +16,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.BooleanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisOperations; @@ -35,6 +36,7 @@ import static cn.axzo.tyr.server.config.exception.BizResultCode.REDIS_ROLE_NOT_N @Slf4j @Service +@RefreshScope public class RolePermissionCacheServiceImpl implements RolePermissionCacheService { private static final String ROLE_PERMISSION_KEY = "role:permission:%s"; @@ -48,8 +50,8 @@ public class RolePermissionCacheServiceImpl implements RolePermissionCacheServic /** 角色权限缓存过期时间 **/ - @Value("${role.permission.expire:180}") - private Long expireInDays; + @Value("${role.permission.expire.minutes:14}") + private Long expireInMinutes; @Override public Map> list(ListRolePermissionParam param) { @@ -131,7 +133,7 @@ public class RolePermissionCacheServiceImpl implements RolePermissionCacheServic // 存在hash中部分key移除,为了处理快,直接把redisKey删除掉,修改不频繁 redisTemplate.delete(redisKey); RedisClient.HashOps.hPutAll(redisKey, redisValues); - redisTemplate.expire(redisKey, expireInDays, TimeUnit.DAYS); + redisTemplate.expire(redisKey, expireInMinutes, TimeUnit.MINUTES); log.info("succeed to store role permission: redisKey:{} value:{}", redisKey, redisValues); } return null; diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleSaasFeatureResourceCacheServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleSaasFeatureResourceCacheServiceImpl.java index 3d150979..f63f3e02 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleSaasFeatureResourceCacheServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/RoleSaasFeatureResourceCacheServiceImpl.java @@ -16,6 +16,7 @@ import com.google.common.collect.Streams; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisOperations; @@ -36,6 +37,7 @@ import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation. @Slf4j @Service +@RefreshScope public class RoleSaasFeatureResourceCacheServiceImpl implements RoleSaasFeatureResourceCacheService { private static final String ROLE_SAAS_FEATURE_RESOURCE_KEY = "role:feature:resource:%s"; @@ -49,8 +51,8 @@ public class RoleSaasFeatureResourceCacheServiceImpl implements RoleSaasFeatureR /** 角色菜单缓存过期时间 **/ - @Value("${role.feature.resource.expire:180}") - private Long expireInDays; + @Value("${role.feature.resource.expire.minutes:14}") + private Long expireInMinutes; @Override public Map> list(ListRoleSaasFeatureResourceParam param) { @@ -84,7 +86,7 @@ public class RoleSaasFeatureResourceCacheServiceImpl implements RoleSaasFeatureR // 存在hash中部分key移除,为了处理快,直接把redisKey删除掉,修改不频繁 redisTemplate.delete(redisKey); RedisClient.HashOps.hPutAll(redisKey, redisValues); - redisTemplate.expire(redisKey, expireInDays, TimeUnit.DAYS); + redisTemplate.expire(redisKey, expireInMinutes, TimeUnit.MINUTES); log.info("succeed to store role featureResource: redisKey:{} value:{}", redisKey, redisValues); } return null; 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 a8e97a67..aa7d50e2 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 @@ -140,6 +140,11 @@ import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation. public class RoleServiceImpl extends ServiceImpl implements RoleService { + private static final ListRoleUserRelationParam.WorkspaceOuPair PRESET_WORKSPACE_OU_PAIR = ListRoleUserRelationParam.WorkspaceOuPair.builder() + .ouId(-1L) + .workspaceId(-1L) + .build(); + @Autowired SaasRoleUserRelationDao roleUserRelationDao; @Autowired @@ -443,6 +448,37 @@ public class RoleServiceImpl extends ServiceImpl .type(OLD_FEATURE) .build(); saasPgroupPermissionRelationService.saveOrUpdate(upsertPermissionRelationParam); + try { + saveOperateLog4RoleBindFeature(saveOrUpdateRole); + } catch (Exception e) { + log.warn("save operate log error", e); + } + } + + private void saveOperateLog4RoleBindFeature(SaveOrUpdateRoleVO saveOrUpdateRole) { + SaasRole saasRole = saasRoleDao.getById(saveOrUpdateRole.getId()); + List uniCodes = null; + if (CollectionUtils.isNotEmpty(saveOrUpdateRole.getPermissionIds())) { + uniCodes = saasFeatureResourceDao.lambdaQuery().in(BaseEntity::getId, saveOrUpdateRole.getPermissionIds()).list().stream().map(SaasFeatureResource::getUniCode).collect(Collectors.toList()); + } + + RelationOperateLogRoleBindResourceDO operateAfter = RelationOperateLogRoleBindResourceDO.builder() + .uniCodes(uniCodes) + .roleCode(saasRole.getRoleCode()) + .build(); + SaasPgroupPermissionRelationOperateLog operateLog = SaasPgroupPermissionRelationOperateLog.builder() + .tableName(SaasPgroupPermissionRelationOperateLogServiceImpl.TABLE_NAME_ROLE) + .scene(PermissionRelationOperateLogSceneEnum.OLD_OMS_ROLE_BIND_FEATURE.getValue()) + .sceneId(saasRole.getRoleCode()) + .createBy(saveOrUpdateRole.getOperatorId()) + .createByName(saveOrUpdateRole.getOperatorName()) + .traceId(MDC.get(Constants.CTX_LOG_ID_MDC)) + .requestData(Objects.isNull(saveOrUpdateRole) ? null : JSONObject.toJSONString(saveOrUpdateRole)) + .operateData(JSONObject.toJSONString(Lists.newArrayList(operateAfter))) + .createByRole(JSONObject.toJSONString(saasPgroupPermissionRelationOperateLogService.getPersonBasicRoles(saveOrUpdateRole.getOperatorId()))) + .build(); + + saasPgroupPermissionRelationOperateLogService.batchSave(Lists.newArrayList(operateLog)); } /** @@ -1181,7 +1217,23 @@ public class RoleServiceImpl extends ServiceImpl public cn.axzo.foundation.page.PageResp page(PageSaasRoleParam param) { QueryWrapper wrapper = QueryWrapperHelper.fromBean(param, SaasRole.class); wrapper.eq("is_delete", 0); - + List workspaceOuPairs = Lists.newArrayList(); + if (Boolean.TRUE.equals(param.getNeedPresetRole())) { + workspaceOuPairs.add(PRESET_WORKSPACE_OU_PAIR); + } + CollectionUtils.addAll(workspaceOuPairs, Optional.ofNullable(param.getWorkspaceOuPairs()) + .map(List::listIterator) + .orElseGet(Collections::emptyListIterator)); + if (CollectionUtils.isNotEmpty(workspaceOuPairs)) { + wrapper.and(j -> { + for (ListRoleUserRelationParam.WorkspaceOuPair workspaceOuPair : workspaceOuPairs) { + j.or(k -> { + k.eq(Objects.nonNull(workspaceOuPair.getOuId()), "owner_ou_id", workspaceOuPair.getOuId()); + k.eq(Objects.nonNull(workspaceOuPair.getWorkspaceId()), "workspace_id", workspaceOuPair.getWorkspaceId()); + }); + } + }); + } IPage page = this.page(PageConverter.toMybatis(param, SaasRole.class), wrapper); Map> saasRoleGroups = listRoleGroups(param, page.getRecords()); @@ -1338,9 +1390,44 @@ public class RoleServiceImpl extends ServiceImpl return saasRoleGroupRes; } + private Set resolveUpsertRoleIds(List req) { + if (CollectionUtils.isEmpty(req)) { + return Collections.emptySet(); + } + + Set newRoleIds = req.stream() + .map(FeatureRoleRelationReq.RelationRoleSettings::getRoleIds) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .collect(Collectors.toSet()); + + List featureIds = req.stream() + .map(FeatureRoleRelationReq.RelationRoleSettings::getFeatureId) + .collect(Collectors.toList()); + PagePgroupPermissionRelationReq pagePgroupPermissionRelationReq = PagePgroupPermissionRelationReq.builder() + .featureIds(featureIds) + .build(); + List groupIds = saasPgroupPermissionRelationService.list(pagePgroupPermissionRelationReq).stream() + .map(SaasPgroupPermissionRelation::getGroupId) + .collect(Collectors.toList()); + + if (CollectionUtils.isEmpty(groupIds)) { + return newRoleIds; + } + + Set oldRoleIds = saasPgroupRoleRelationDao.listByGroupIds(groupIds).stream() + .map(SaasPgroupRoleRelation::getRoleId) + .collect(Collectors.toSet()); + newRoleIds.addAll(oldRoleIds); + return newRoleIds; + } + @Override @Transactional(rollbackFor = Exception.class) public void saveOrUpdateFeatureRoleRelation(List req, Long operatorId) { + // 查询权限点的历史角色,发送mq + Set allRoleIds = resolveUpsertRoleIds(req); + for (FeatureRoleRelationReq.RelationRoleSettings item : req) { saasFeatureResourceService.updateFeatureAuthType(item.getFeatureId(), item.getAuthType()); if (CollectionUtil.isEmpty(item.getRoleIds()) || item.getAuthType() == 0) { @@ -1411,6 +1498,15 @@ public class RoleServiceImpl extends ServiceImpl .build()) .build(); mqProducer.send(event); + + // 待收口后,这个事件需要放在角色权限的upsert方法里 + mqProducer.send(Event.builder() + .targetType("saasFeatureResourceId") + .eventCode(ROLE_PERMISSION_CREATED.getEventCode()) + .data(RolePermissionCreatedPayload.builder() + .roleIds(allRoleIds) + .build()) + .build()); } @Override 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 9953557e..7fb3dd6e 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 @@ -357,12 +357,14 @@ public class RoleUserService implements SaasRoleUserService { } @Override + @Transactional(rollbackFor = Exception.class) public void removeWorkspaceOuAllUserRole(Long workspaceId, Long ouId) { saasRoleDao.removeWorkspaceOuAllRole(workspaceId, ouId); roleUserRelationDao.removeWorkspaceOuAllUserRole(workspaceId, ouId); } @Override + @Transactional(rollbackFor = Exception.class) public void grantOrUngrantWorkerLeader(GantOrUnGantaWorkerLeaderRoleReq req) { Boolean grant = req.getGrant(); // 授权 diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasBasicDictServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasBasicDictServiceImpl.java index d99c244b..192e223f 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasBasicDictServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasBasicDictServiceImpl.java @@ -15,6 +15,7 @@ import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.*; import java.util.stream.Collectors; @@ -103,6 +104,7 @@ public class SaasBasicDictServiceImpl implements SaasBasicDictService { * @return */ @Override + @Transactional(rollbackFor = Exception.class) public Long create(BasicDictCreateReq req) { SaasBasicDict parent = saasBasicDictDao.getById(req.getParentId()); if (Objects.isNull(parent)) { @@ -145,6 +147,7 @@ public class SaasBasicDictServiceImpl implements SaasBasicDictService { } @Override + @Transactional(rollbackFor = Exception.class) public Boolean update(BasicDictUpdateReq req) { BasicDictNodeResp currentNode = getById(req.getId()); if (Objects.isNull(currentNode)) { @@ -166,6 +169,7 @@ public class SaasBasicDictServiceImpl implements SaasBasicDictService { } @Override + @Transactional(rollbackFor = Exception.class) public Boolean updateStauts(BasicDictUpdateStatusReq req) { return saasBasicDictDao.updateStatus(req); } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java index e62f504b..1e6ee960 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasFeatureResourceServiceImpl.java @@ -68,6 +68,7 @@ import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisTemplate; @@ -101,6 +102,7 @@ import static cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation. */ @Slf4j @Service +@RefreshScope @RequiredArgsConstructor public class SaasFeatureResourceServiceImpl extends ServiceImpl implements SaasFeatureResourceService { @@ -119,8 +121,8 @@ public class SaasFeatureResourceServiceImpl extends ServiceImpl redisTemplate; /** 菜单树过期时间 **/ - @Value("${saas.feature.resource.expire:180}") - private Long expireInDays; + @Value("${saas.feature.resource.expire.minutes:14}") + private Long expireInMinutes; private static final String SAAS_FEATURE_RESOURCE_KEY = "saas:feature:resource:%s"; @@ -268,8 +270,19 @@ public class SaasFeatureResourceServiceImpl extends ServiceImpl personProfileDtos = RpcInternalUtil.rpcListProcessor(() -> userProfileServiceApi.getPersonProfiles(Lists.newArrayList(req.getOperatorId())), "查询用户信息", req.getOperatorId()).getData(); - PersonProfileDto operator = CollectionUtils.isEmpty(personProfileDtos) ? null : personProfileDtos.get(0); + String realName = req.getOperatorId() == null ? "" : Optional.ofNullable(getPersonProfileDto(req)).map(PersonProfileDto::getRealName).orElse(""); SaasPgroupPermissionRelationOperateLog operateLog = SaasPgroupPermissionRelationOperateLog.builder() .tableName(req.getTableName()) .scene(req.getScene()) .sceneId(req.getSceneId()) - .createBy(req.getOperatorId()) - .createByName(Objects.isNull(operator) ? "" : operator.getRealName()) + .createBy(ObjectUtils.firstNonNull(req.getOperatorId(), 0L)) + .createByName(StringUtils.firstNonBlank(realName, req.getOperatorName(), "")) .traceId(MDC.get(Constants.CTX_LOG_ID_MDC)) .requestData(Objects.nonNull(req.getRequestData()) ? JSONObject.toJSONString(req.getRequestData()) : null) .operateData(Objects.nonNull(req.getOperateData()) ? JSONObject.toJSONString(req.getOperateData()) : null) .createByRole(JSONObject.toJSONString(getPersonBasicRoles(req.getOperatorId()))) + .ext(req.getExt()) .build(); batchSave(Lists.newArrayList(operateLog)); } + + private PersonProfileDto getPersonProfileDto(PermissionOperateLogReq req) { + List personProfileDtos = RpcInternalUtil.rpcListProcessor(() -> userProfileServiceApi.getPersonProfiles(Lists.newArrayList(req.getOperatorId())), "查询用户信息", req.getOperatorId()).getData(); + PersonProfileDto operator = CollectionUtils.isEmpty(personProfileDtos) ? null : personProfileDtos.get(0); + return operator; + } } diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasRoleGroupServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasRoleGroupServiceImpl.java index 43c536aa..296a37a5 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasRoleGroupServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasRoleGroupServiceImpl.java @@ -2,26 +2,35 @@ package cn.axzo.tyr.server.service.impl; import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum; import cn.axzo.basics.common.exception.ServiceException; -import cn.axzo.foundation.exception.Axssert; import cn.axzo.foundation.dao.support.converter.PageConverter; import cn.axzo.foundation.dao.support.mysql.QueryWrapperHelper; +import cn.axzo.foundation.exception.Axssert; import cn.axzo.foundation.page.PageResp; +import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; +import cn.axzo.tyr.client.common.enums.PermissionRelationOperateLogSceneEnum; import cn.axzo.tyr.client.model.req.ListSaasRoleGroupParam; import cn.axzo.tyr.client.model.req.PageSaasRoleGroupParam; +import cn.axzo.tyr.client.model.req.PermissionOperateLogReq; import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq; +import cn.axzo.tyr.client.model.req.SaasRoleGroupDeleteRequest; import cn.axzo.tyr.client.model.res.SaasRoleGroupDTO; import cn.axzo.tyr.client.model.res.SaasRoleRes; import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO; +import cn.axzo.tyr.server.model.BasicRoleDO; import cn.axzo.tyr.server.repository.dao.SaasRoleGroupDao; import cn.axzo.tyr.server.repository.dao.SaasRoleGroupRelationDao; +import cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelationOperateLog; import cn.axzo.tyr.server.repository.entity.SaasRoleGroup; import cn.axzo.tyr.server.repository.entity.SaasRoleGroupRelation; import cn.axzo.tyr.server.repository.mapper.SaasRoleGroupMapper; import cn.axzo.tyr.server.service.RoleService; +import cn.axzo.tyr.server.service.SaasPgroupPermissionRelationOperateLogService; import cn.axzo.tyr.server.service.SaasRoleGroupRelationService; import cn.axzo.tyr.server.service.SaasRoleGroupService; +import cn.azxo.framework.common.constatns.Constants; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; +import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -31,8 +40,10 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; +import org.slf4j.MDC; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Arrays; @@ -54,10 +65,13 @@ import static cn.axzo.tyr.server.config.exception.BizResultCode.CANT_DELETE_ROLE @Service public class SaasRoleGroupServiceImpl extends ServiceImpl implements SaasRoleGroupService { + + private final SaasRoleGroupMapper saasRoleGroupMapper; private final SaasRoleGroupDao saasRoleGroupDao; private final SaasRoleGroupRelationDao saasRoleGroupRelationDao; private final SaasRoleGroupRelationService saasRoleGroupRelationService; private final RoleService roleService; + private final SaasPgroupPermissionRelationOperateLogService saasPgroupPermissionRelationOperateLogService; @Override public List getList(QuerySaasRoleGroupReq req) { @@ -126,18 +140,45 @@ public class SaasRoleGroupServiceImpl extends ServiceImpl ids) { + SaasRoleGroupDeleteRequest request = new SaasRoleGroupDeleteRequest(); + request.setIds(ids); + deleteV2(request); + } + /** * 只有当分组下面角色为空合分组下没有其他分组时才能删除 - * @param ids + * @param request */ @Override - public void delete(List ids) { + public void deleteV2(SaasRoleGroupDeleteRequest request) { + List ids = request.getIds(); if (CollectionUtils.isEmpty(ids)) { return; } @@ -156,6 +197,41 @@ public class SaasRoleGroupServiceImpl extends ServiceImpl ids = request.getIds(); + if (CollectionUtils.isEmpty(ids)) { + return; + } + Map id2Group = saasRoleGroupMapper.getByIdsDeleteAware(ids) + .stream() + .collect(Collectors.toMap(BaseEntity::getId, Function.identity())); + ArrayList logs = new ArrayList<>(); + List personBasicRoles = saasPgroupPermissionRelationOperateLogService + .getPersonBasicRoles(request.determineOperator().getPersonId()); + for (Long id : ids) { + SaasRoleGroup group = id2Group.get(id); + SaasPgroupPermissionRelationOperateLog log = SaasPgroupPermissionRelationOperateLog.builder() + .tableName(SaasPgroupPermissionRelationOperateLogServiceImpl.TABLE_NAME_SAAS_ROLE_GROUP) + .scene(PermissionRelationOperateLogSceneEnum.OLD_OMS_ROLE_GROUP__DELETE.getValue()) + .sceneId(id + "") + .createBy(request.determineOperator().getPersonId()) + .createByName(request.determineOperator().getRealName()) + .traceId(MDC.get(Constants.CTX_LOG_ID_MDC)) + .requestData(JSONObject.toJSONString(request)) + .operateData(JSONObject.toJSONString(group)) + .createByRole(JSONObject.toJSONString(personBasicRoles)) + .build(); + logs.add(log); + } + saasPgroupPermissionRelationOperateLogService.batchSave(logs); } private SaasRoleGroup validAndBuildGroup(SaasRoleGroupVO req) { diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasRoleUserRelationServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasRoleUserRelationServiceImpl.java index d207802d..77b7a3d4 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasRoleUserRelationServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasRoleUserRelationServiceImpl.java @@ -9,6 +9,7 @@ import cn.axzo.foundation.dao.support.mysql.QueryWrapperHelper; import cn.axzo.framework.domain.page.PageResp; import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; import cn.axzo.tyr.client.common.enums.RoleTypeEnum; +import cn.axzo.tyr.client.model.res.SaasRoleRes; import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserDTO; import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserV2DTO; import cn.axzo.tyr.client.model.roleuser.req.ListRoleUserRelationParam; @@ -29,6 +30,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.BooleanUtils; import org.springframework.beans.BeanUtils; @@ -43,6 +45,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; @@ -152,6 +155,12 @@ public class SaasRoleUserRelationServiceImpl extends ServiceImpl roleIds = resolveRoleIds(param); + if (!CollectionUtils.isEmpty(param.getRoleCodes()) && CollectionUtils.isEmpty(roleIds)) { + return param.toEmpty(); + } + wrapper.in(!CollectionUtils.isEmpty(roleIds), "role_id", roleIds); + IPage page = this.page(PageConverter.toMybatis(param, SaasRoleUserRelation.class), wrapper); Map saasRoleUsers = listSaasRoleUser(param, page.getRecords()); @@ -161,6 +170,28 @@ public class SaasRoleUserRelationServiceImpl extends ServiceImpl from(record, saasRoleUsers, saasRoles)); } + private Set resolveRoleIds(PageRoleUserRelationParam param) { + if (CollectionUtils.isEmpty(param.getRoleCodes())) { + return Optional.ofNullable(param.getRoleIds()) + .map(Sets::newHashSet) + .orElseGet(Sets::newHashSet); + } + RoleService.ListSaasRoleParam listSaasRoleParam = RoleService.ListSaasRoleParam.builder() + .roleCodes(param.getRoleCodes()) + .build(); + Set roleIds = roleService.list(listSaasRoleParam).stream() + .map(SaasRoleRes::getId) + .collect(Collectors.toSet()); + + if (CollectionUtils.isEmpty(param.getRoleIds())) { + return roleIds; + } + + return param.getRoleIds().stream() + .filter(roleIds::contains) + .collect(Collectors.toSet()); + } + private Map listSaasRoleUser(PageRoleUserRelationParam param, List saasRoleUserRelations) { if (CollectionUtils.isEmpty(saasRoleUserRelations) || BooleanUtils.isNotTrue(param.getNeedUsers())) { @@ -238,6 +269,8 @@ public class SaasRoleUserRelationServiceImpl extends ServiceImpl pairs = BeanMapper.copyList(req.getWorkspaceAndOU(), IdentityAuthReq.WorkspaceOuPair.class); request.setWorkspaceOusPairs(pairs); + request.setFeatureCode(Sets.newHashSet(req.getCodes())); IdentityAuthRes authRes = this.findIdentityAuthMix(request); - HashSet codeSet = new HashSet<>(req.getCodes()); - //比较code return authRes.getPermissions().stream() - .anyMatch(e -> e.getPermissionPoint() - .stream() - .anyMatch(p -> codeSet.contains(p.getFeatureCode()))); + .anyMatch(e -> CollectionUtil.isNotEmpty(e.getPermissionPoint())); } @Data @@ -869,7 +866,9 @@ public class TyrSaasAuthServiceImpl implements TyrSaasAuthService { @Override public List listAuthByResourceAndRoleGroup(ListPermissionFromRoleGroupReq listPermissionFromRoleGroupReq) { //确定角色group_id: code对应角色组及其下级 - List groups = roleGroupService.listByCodes(Collections.singletonList(listPermissionFromRoleGroupReq.getCategoryCode()), 3); + Integer categoryType = Optional.ofNullable(listPermissionFromRoleGroupReq.getCategoryType()) + .orElse(3); + List groups = roleGroupService.listByCodes(Collections.singletonList(listPermissionFromRoleGroupReq.getCategoryCode()), categoryType); if (CollectionUtil.isEmpty(groups)) { log.warn("no role group found for code :{}", listPermissionFromRoleGroupReq.getCategoryCode()); return Collections.emptyList(); diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/WorkspaceProductServiceImpl.java b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/WorkspaceProductServiceImpl.java index 3ce49afd..ecf78d73 100644 --- a/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/WorkspaceProductServiceImpl.java +++ b/tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/WorkspaceProductServiceImpl.java @@ -2,7 +2,7 @@ package cn.axzo.tyr.server.service.impl; import cn.axzo.foundation.exception.Axssert; import cn.axzo.pokonyan.config.mybatisplus.BaseEntity; -import cn.axzo.pokonyan.config.redis.RedisUtil; +import cn.axzo.pokonyan.config.redis.RedisClient; 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; @@ -22,12 +22,9 @@ import com.google.common.collect.Sets; import com.google.common.collect.Streams; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.dao.DataAccessException; -import org.springframework.data.redis.core.RedisOperations; -import org.springframework.data.redis.core.SessionCallback; +import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; @@ -36,6 +33,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -45,6 +43,7 @@ import static cn.axzo.tyr.server.config.exception.BizResultCode.WORKSPACE_ID_NOT @Slf4j @Service +@RefreshScope public class WorkspaceProductServiceImpl implements WorkspaceProductService { @Autowired @@ -62,10 +61,10 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService { /** 授权缓存过期时间 **/ - @Value("${workspace.product.expire:90}") - private Long expireInDays; + @Value("${workspace.product.expire.minutes:14}") + private Long expireInMinutes; - private static final String WORKSPACE_PRODUCT_KEY = "workspace:product:%s"; + private static final String WORKSPACE_PRODUCT_KEY = "workspace:product"; @Override public List listWorkspaceProduct(WorkspaceProductParam param) { @@ -182,35 +181,28 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService { public void storeWorkspaceProduct(StoreWorkspaceProductParam param) { Axssert.checkNotEmpty(param.getWorkspaceProducts(), REDIS_PRODUCT_NOT_NULL); - - redisTemplate.executePipelined(new SessionCallback() { - @Override - public Object execute(RedisOperations operations) throws DataAccessException { - - for (WorkspaceProductDTO workspaceProduct : param.getWorkspaceProducts()) { - String redisKey = getKey(workspaceProduct.getWorkspaceId()); - RedisUtil.StringValueOps.setEx(redisKey, JSON.toJSONString(workspaceProduct.getProductIds()), - expireInDays, TimeUnit.DAYS); - } - - return null; - } - }); + Map redisValues = param.getWorkspaceProducts().stream() + .collect(Collectors.toMap(e -> e.getWorkspaceId().toString(), e -> Optional.ofNullable(e.getProductIds()) + .map(JSON::toJSONString) + .orElseGet(() -> JSON.toJSONString(Sets.newHashSet())))); + String redisKey = getKey(); + RedisClient.HashOps.hPutAll(redisKey, redisValues); + redisTemplate.expire(redisKey, expireInMinutes, TimeUnit.MINUTES); + log.info("succeed to workspace product: redisKey:{} value:{}", redisKey, redisValues); } private Map> listWorkspaceProduct(ListWorkspaceProductParam param) { Axssert.checkNotEmpty(param.getWorkspaceIds(), WORKSPACE_ID_NOT_NULL); - List redisKeys = param.getWorkspaceIds().stream() - .map(this::getKey) - .collect(Collectors.toList()); - List redisValues = redisTemplate.opsForValue().multiGet(redisKeys); + List redisValues = RedisClient.HashOps.hMultiGet(getKey(), param.getWorkspaceIds().stream() + .map(String::valueOf) + .collect(Collectors.toList())); return Streams.zip(param.getWorkspaceIds().stream(), redisValues.stream(), (workspaceId, redisValue) -> { - if (StringUtils.isBlank(redisValue)) { + if (Objects.isNull(redisValue)) { return null; } @@ -220,6 +212,7 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService { .collect(Collectors.toSet()); return Pair.of(workspaceId, productIds); + }) .filter(Objects::nonNull) .collect(Collectors.toMap(Pair::getKey, Pair::getValue)); @@ -273,8 +266,8 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService { storeWorkspaceProduct(storeWorkspaceProductParam); } - private String getKey(Object... params) { - return String.format(WORKSPACE_PRODUCT_KEY, params); + private String getKey() { + return String.format(WORKSPACE_PRODUCT_KEY); } @Override @@ -396,4 +389,15 @@ public class WorkspaceProductServiceImpl implements WorkspaceProductService { }) .collect(Collectors.toList()); } + + @Override + public Map> listAllWorkspaceProductCached() { + + return RedisClient.HashOps.hGetAll(getKey()).entrySet() + .stream() + .collect(Collectors.toMap(e -> Long.valueOf(e.getKey().toString()), e -> JSON.parseArray(e.getValue().toString()) + .stream() + .map(productId -> Long.valueOf(productId.toString())) + .collect(Collectors.toSet()))); + } } diff --git a/tyr-server/src/main/resources/mapper/TyrSaasAuthMapper.xml b/tyr-server/src/main/resources/mapper/TyrSaasAuthMapper.xml index 9bf4878f..c71deec3 100644 --- a/tyr-server/src/main/resources/mapper/TyrSaasAuthMapper.xml +++ b/tyr-server/src/main/resources/mapper/TyrSaasAuthMapper.xml @@ -118,6 +118,7 @@ t1.code roleGroupCode, t3.id roleId, t3.name roleName, + t3.role_code roleCode, t4.group_id permissionGroupId FROM