Merge branch 'master' into feature/REQ-1902-yangheng

This commit is contained in:
yangheng 2024-04-23 09:54:00 +08:00
commit d8788fc476
90 changed files with 3343 additions and 460 deletions

View File

@ -0,0 +1,26 @@
package cn.axzo.tyr.client.common.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
/**
* @author tanjie@axzo.cn
* @date 2024/1/9 17:07
*/
public enum RoleResourceTypeEnum {
UNIT(1, "单位"),
NODE(2, "组织节点")
;
@Getter
@EnumValue
@JsonValue
public final Integer code;
public final String desc;
RoleResourceTypeEnum(Integer code, String desc){
this.code = code;
this.desc = desc;
}
}

View File

@ -0,0 +1,37 @@
package cn.axzo.tyr.client.common.enums;
import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
/**
* position code
* @author tanjie@axzo.cn
* @date 2022/7/4 10:51
*/
public enum SaasPositionEnum {
PLAT_TEAM_OWNER("plat_teamowner", "平台级班组长"),
PLAT_ACTING_MONITOR("plat_actingmonitor", "班组管理员"),
PLAT_GROUP_LEADER("plat_groupleader", "平台级小组长"),
WORKSPACE_TEAM_OWNER("workspace_teamowner", "工作台级班组长"),
WORKSPACE_ACTING_MONITOR("workspace_actingmonitor", "工作台级代班长"),
WORKSPACE_GROUP_LEADER("workspace_groupleader", "工作台级小组长"),;
@Getter
@EnumValue
@JsonValue
private final String code;
@Getter
private final String desc;
SaasPositionEnum(String value, String desc) {
this.code = value;
this.desc = desc;
}
public static SaasPositionEnum getValueByCode(String code) {
return ArrayUtil.firstMatch((o) -> o.getCode().equals(code), values());
}
}

View File

@ -14,7 +14,8 @@ import java.util.EnumSet;
/**
* 单位与工作台的参建类型
*
* 与协同关系保持一致
* cn.axzo.maokai.common.enums.SaasCooperateShipCooperateTypeEnum
* @author tanjie@axzo.cn
* @date 2023/10/13 17:55
*/
@ -29,6 +30,11 @@ public enum WorkspaceJoinType implements IBaseCreateEnum<WorkspaceJoinType> {
PROFESSIONAL_SUBCONTRACTING(5, "专业分包"),
AXZ_PLATFORM(6, "OMS平台"),
ENT_GENERAL(7, "企业通用"),
ENT_TEAM(8, "企业班组"),
PROJ_TEAM(9, "项目班组"),
ENT_GROUP(10, "企业小组"),
PROJ_GROUP(11, "项目小组"),
OTHER(30, "其他"),
;
@EnumValue
@JsonValue

View File

@ -7,6 +7,8 @@ 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.QueryPermissionByIdsReq;
import cn.axzo.tyr.client.model.res.SimplePermissionPointResp;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@ -69,4 +71,9 @@ public interface PermissionPointApi {
**/
@GetMapping(value = "/api/v1/permissionPoint/getChildByParentId/{id}")
ApiResult<List<PermissionPointDTO>> getChildByParentId(@PathVariable Long id);
/** 根据ID查询权限点 **/
@PostMapping(value = "/api/v1/permissionPoint/listPermissionByIds")
ApiResult<List<SimplePermissionPointResp>> listPermissionByIds(@RequestBody QueryPermissionByIdsReq req);
}

View File

@ -4,6 +4,7 @@ import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq;
import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
@ -50,4 +51,15 @@ public interface SaasRoleGroupApi {
@PostMapping("/api/saasRoleGroup/delete")
ApiResult<Void> delete(@RequestParam @NotEmpty List<Long> ids);
/**
*
* 通过categoryCode查询分组
* @param categoryCodes #{@link cn.axzo.tyr.client.common.enums.SaasPositionEnum}
*
* @return
*/
@GetMapping("/api/saasRoleGroup/listByCategoryCode")
ApiResult<List<SaasRoleGroupVO>> listByCategoryCode(@RequestParam("categoryCode") List<String> categoryCodes);
}

View File

@ -3,12 +3,15 @@ package cn.axzo.tyr.client.feign;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.model.req.CheckIdentityPermissionReq;
import cn.axzo.tyr.client.model.req.IdentityAuthReq;
import cn.axzo.tyr.client.model.req.BatchListIdentityFromPermissionReq;
import cn.axzo.tyr.client.model.req.ListIdentityFromPermissionReq;
import cn.axzo.tyr.client.model.req.ListPermissionFromFeatureReq;
import cn.axzo.tyr.client.model.req.ListPermissionFromIdentityReq;
import cn.axzo.tyr.client.model.req.ListPermissionFromRoleGroupReq;
import cn.axzo.tyr.client.model.req.PermissionCacheReq;
import cn.axzo.tyr.client.model.req.WorkspacePermissionIdentityReq;
import cn.axzo.tyr.client.model.res.IdentityAuthRes;
import cn.axzo.tyr.client.model.res.ListIdentityFromPermissionResp;
import cn.axzo.tyr.client.model.res.ListPermissionFromRoleGroupResp;
import cn.axzo.tyr.client.model.res.QueryIdentityByPermissionResp;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
@ -86,7 +89,23 @@ public interface TyrSaasAuthApi {
@PostMapping("/api/v2/auth/batchListIdentityFromPermission")
ApiResult<List<ListIdentityFromPermissionResp>> batchListIdentityFromPermission(@RequestBody List<ListIdentityFromPermissionReq> req);
/** 查询工作台下有权限的人 **/
@PostMapping("/api/v2/auth/listWorkspacePermissionIdentity")
ApiResult<List<ListIdentityFromPermissionResp>> listWorkspacePermissionIdentity(@RequestBody WorkspacePermissionIdentityReq req);
/** 暂时禁用权限缓存,至缓存失效 - 实现刷新 **/
@PostMapping("/api/v2/auth/tempDisableAuthCache")
ApiResult<Void> tempDisableAuthCache(@Valid @RequestBody PermissionCacheReq req);
/**
*
* 通过资源ID资源类型角色分类 查询权限
* @param listPermissionFromRoleGroupReq
* @return
*/
@PostMapping("/api/v1/auth/listIdentityFromRoleGroupCategoryCode")
ApiResult<List<ListPermissionFromRoleGroupResp>> listAuthByResourceAndRoleGroup(@RequestBody @Valid ListPermissionFromRoleGroupReq listPermissionFromRoleGroupReq);
}

View File

@ -7,6 +7,10 @@ import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Collection;
import java.util.List;
/**
* @author honghao.zhang
@ -17,4 +21,13 @@ public interface TyrSaasFeatureApi {
@PostMapping("/api/saasFeature/permission/codes")
ApiResult<FeaturePermissionRes> listPermissionCodes(@RequestBody @Validated FeaturePermissionReq req);
/**
* 通过 {@code appItemId} 获取 {@code featureId}
*
* @param appItemIds 应用子级条目id集合
* @return {@code featureId} 列表
*/
@PostMapping("/api/saasFeature/featureId/list")
ApiResult<List<Long>> listAppFeatureIds(@RequestParam("appItemIds") Collection<Long> appItemIds);
}

View File

@ -6,11 +6,14 @@ import cn.axzo.tyr.client.model.req.QueryByIdentityIdTypeReq;
import cn.axzo.tyr.client.model.req.QueryRoleByNameReq;
import cn.axzo.tyr.client.model.req.QuerySaasRoleReq;
import cn.axzo.tyr.client.model.req.RoleWithUserQueryReq;
import cn.axzo.tyr.client.model.req.ChangeGroupLeaderRoleReq;
import cn.axzo.tyr.client.model.res.IsSuperAdminRes;
import cn.axzo.tyr.client.model.res.QueryBatchByIdentityIdTypeRes;
import cn.axzo.tyr.client.model.res.QueryRoleByNameResp;
import cn.axzo.tyr.client.model.res.RoleWithUserRes;
import cn.axzo.tyr.client.model.vo.SaasRoleAndGroupVO;
import cn.axzo.tyr.client.model.vo.SaasRoleCategoryVO;
import cn.axzo.tyr.client.model.vo.SaasRoleGroupCodeVO;
import cn.axzo.tyr.client.model.vo.SaasRoleVO;
import cn.axzo.tyr.client.model.vo.SaveOrUpdateRoleVO;
import org.springframework.cloud.openfeign.FeignClient;
@ -118,4 +121,23 @@ public interface TyrSaasRoleApi {
@GetMapping("/api/saasRole/queryByWorkspaceType")
ApiResult<List<SaasRoleAndGroupVO>> queryInitRoleByWorkspaceId(@RequestParam("workspaceType") String workspaceType);
/**
* 通过角色分组Code查询标准角色
*/
@GetMapping("/api/saasRole/queryByCategoryCode")
ApiResult<List<SaasRoleCategoryVO>> queryByCategoryCode(@RequestParam("categoryCodes") List<String> categoryCodes);
/**
* 通过角色GroupCode查询标准角色
*/
@GetMapping("/api/saasRole/queryByCodes")
ApiResult<List<SaasRoleGroupCodeVO>> queryByCodes(@RequestParam("codes") List<String> codes);
/**
*
* @param req
* @return
*/
@PostMapping("api/saasRole/changeGroupLeaderRole")
ApiResult<Void> changeGroupLeaderRole(@RequestBody @Valid List<ChangeGroupLeaderRoleReq> req);
}

View File

@ -31,6 +31,21 @@ public interface TyrSaasRoleUserApi {
ApiResult<Void> saveOrUpdate(@RequestBody @Valid RoleUserReq req);
/**
* 授权或者取消授权平台班组长和项目内班组长角色
*/
@PostMapping("/api/saas-role-user/grant-or-ungrant-worker-leader")
ApiResult<Void> grantOrUngrantWorkerLeader(@RequestBody @Valid GantOrUnGantaWorkerLeaderRoleReq req);
/**
* 授权或者取消授权班组管理员或者项目代班长小组长
*
* @return
*/
@PostMapping("/api/saas-role-user/grant-or-ungrant-worker-manager")
ApiResult<Void> grantOrUngrantWorkerManager(@RequestBody @Valid WorkerManagerRoleUserReq req);
/**
* 保存/更新 用户的角色每次传入新的角色ID时都会覆盖原来的所有角色
* 此接口不能修改非管理员角色

View File

@ -2,6 +2,7 @@ package cn.axzo.tyr.client.model.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
import java.util.Arrays;
@ -17,22 +18,22 @@ public enum DictWorkSpaceTypeEnum {
/**
* 企业工作台
*/
ENT("ent", "企业工作台"),
ENT("ent", "企业工作台", 7,1),
/**
* 项目部工作台
*/
PROJ("proj", "项目部工作台"),
PROJ("proj", "项目部工作台",1,2),
/**
* OMS工作台
*/
OMS("oms", "OMS工作台"),
OMS("oms", "OMS工作台",6,6),
/**
* 班组工作台
*/
TEAM("team","班组工作台")
TEAM("team","班组工作台",0,0)
;
@EnumValue
@ -41,6 +42,12 @@ public enum DictWorkSpaceTypeEnum {
private final String description;
@Getter
private final Integer superAdminProductType;
@Getter
private final Integer workspaceType;
public String getValue() {
return value;
}
@ -49,9 +56,11 @@ public enum DictWorkSpaceTypeEnum {
return description;
}
DictWorkSpaceTypeEnum(String value, String description) {
DictWorkSpaceTypeEnum(String value, String description, Integer superAdminProductType, Integer workspaceType) {
this.value = value;
this.description = description;
this.superAdminProductType = superAdminProductType;
this.workspaceType = workspaceType;
}
/**
@ -63,4 +72,13 @@ public enum DictWorkSpaceTypeEnum {
public static DictWorkSpaceTypeEnum getByValue(String value) {
return Arrays.stream(values()).filter(l -> l.getValue().equals(value)).findFirst().orElse(null);
}
/**
* 通过workspaceType值获取枚举类型
*
* @param workspaceType 工作台类型
* @return
*/
public static DictWorkSpaceTypeEnum getByValueWorkspaceType(Integer workspaceType) {
return Arrays.stream(values()).filter(l -> l.getWorkspaceType().equals(workspaceType)).findFirst().orElse(null);
}
}

View File

@ -32,6 +32,9 @@ public enum IdentityType implements IEnum{
public static IdentityType getIdentityType(Integer code) {
if (code == null) {
return null;
}
IdentityType[] values = values();
for (IdentityType item : values) {
if (item.getCode().equals(code)) {

View File

@ -0,0 +1,28 @@
package cn.axzo.tyr.client.model.enums;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import java.util.HashMap;
import java.util.Map;
@AllArgsConstructor
@NoArgsConstructor
public enum WorkerLeaderRoleEnum {
ENT_TEAM_MANAGER(1, "平台班组长"),
PROJ_TEAM_MANAGER(2, "项目内班组长");
private Integer code;
private String desc;
private static final Map<Integer, WorkerLeaderRoleEnum> MAPPING = new HashMap<>();
static {
for (WorkerLeaderRoleEnum workerLeaderRoleEnum : WorkerLeaderRoleEnum.values()) {
MAPPING.put(workerLeaderRoleEnum.code, workerLeaderRoleEnum);
}
}
public static WorkerLeaderRoleEnum apply(Integer code) {
return code == null ? null :MAPPING.get(code);
}
}

View File

@ -0,0 +1,46 @@
package cn.axzo.tyr.client.model.req;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ChangeGroupLeaderRoleReq {
/**
* 小组nodeId
*/
@NotNull
private Long groupNodeId;
/**
* 工作台id
*/
private Long workspaceId;
/**
* 小组长Personid
*/
@NotNull
private Long groupLeaderPersonId;
/**
* 团队Id
*/
private Long ouId;
/**
* 小组长身份id
*/
private Long groupLeaderIdentityId;
/**
* 权限名列表
*/
@NotEmpty
private List<Long> roleIdList = Lists.newArrayList();
}

View File

@ -30,13 +30,13 @@ public class CheckIdentityPermissionReq {
*/
private List<OUWorkspacePair> workspaceAndOU;
/** 人员ID **/
private Long personId;
/**
* 身份Id不能为空
*/
@NotNull(message = "身份ID不能为空")
private Long identityId;
@NotNull(message = "身份类型不能为空")
private IdentityType identityType;
/**

View File

@ -27,15 +27,15 @@ public class FeaturePermissionReq {
Long workspaceId;
/**
* 工作台类型
* 工作台类型 - 废弃
*/
@NotNull
@Deprecated
private Integer workspaceType;
/**
* 使用{@link WorkspaceJoinType}
* 使用{@link WorkspaceJoinType} - 废弃
*/
@NotNull
@Deprecated
private Integer workspaceJoinType;
/**
@ -50,11 +50,12 @@ public class FeaturePermissionReq {
*/
String terminal;
@NotNull
@Min(value = 1)
Long identityId;
@NotNull
@Min(value = 0)
Integer identityType;
/** 人员ID - 优先于identity **/
Long personId;
}

View File

@ -4,6 +4,7 @@ import cn.axzo.framework.auth.domain.TerminalInfo;
import cn.axzo.tyr.client.common.enums.WorkspaceJoinType;
import cn.axzo.tyr.client.model.enums.FeatureType;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.hutool.core.collection.CollectionUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -17,6 +18,12 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static cn.axzo.tyr.client.common.enums.WorkspaceJoinType.ENT_GROUP;
import static cn.axzo.tyr.client.common.enums.WorkspaceJoinType.ENT_TEAM;
import static cn.axzo.tyr.client.common.enums.WorkspaceJoinType.PROJ_GROUP;
import static cn.axzo.tyr.client.common.enums.WorkspaceJoinType.PROJ_TEAM;
/**
* @author tanjie@axzo.cn
@ -28,11 +35,14 @@ import java.util.Set;
@NoArgsConstructor
public class IdentityAuthReq {
@NotNull
/** 身份ID - 不能和人员ID同时为空**/
private Long identityId;
@NotNull
/** 身份类型 **/
private IdentityType identityType;
/** 人员ID 优先于身份- 不能和身份同时为空 **/
private Long personId;
/**
*<pre>
* 防止数据量过多工作台与单位必传
@ -59,6 +69,20 @@ public class IdentityAuthReq {
/** 指定角色ID - 预览用,不需要用户已配置角色 **/
private Set<Long> specifyRoleIds;
/** 是否使用缓存 - 默认true **/
@Builder.Default
private boolean useCache = true;
public void distinctOUWorkspacePair() {
if (CollectionUtil.isEmpty(this.workspaceOusPairs)) {
return;
}
Set<String> distinctSet = new HashSet<>();
this.workspaceOusPairs = this.workspaceOusPairs.stream()
.filter(p -> distinctSet.add(p.getOuId() + "-" + p.getWorkspaceId()))
.collect(Collectors.toList());
}
@Data
@Builder
@ -69,17 +93,17 @@ public class IdentityAuthReq {
@NotNull
private Long workspaceId;
@NotNull
@Deprecated
/** 基于角色标签查询逻辑不再用该参数 **/
private Integer workspaceType;
@NotNull
private Long ouId;
/**
* 使用{@link WorkspaceJoinType}
*/
@NotNull
@Deprecated
/** 基于角色标签查询逻辑不再用该参数 **/
private Integer workspaceJoinType;
}
}

View File

@ -31,8 +31,8 @@ public class ListIdentityFromPermissionReq {
@NotNull(message = "工作台不能为空")
private Long workspaceId;
/** 参建单位类型 **/
@NotNull(message = "参建单位类型不能为空")
/** 参建单位类型 - 废弃 直接依赖角色上类型 **/
@Deprecated
private Integer workspaceJoinType;
/**

View File

@ -0,0 +1,59 @@
package cn.axzo.tyr.client.model.req;
import cn.axzo.tyr.client.common.enums.SaasPositionEnum;
import cn.axzo.tyr.client.model.enums.IdentityType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 通过角色分组及分类查询人员的权限
* @author tanjie@axzo.cn
* @date 2024/1/5 14:26
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ListPermissionFromRoleGroupReq {
private List<Long> identityIds;
private IdentityType identityType;
private List<Long> personIds;
/**
* 分组CODE 代班长班组管理员小组长
* #{@link SaasPositionEnum#getCode()}
*/
@NotNull
private String categoryCode;
private List<WorkspaceOuPair> workspaceOuPairs;
@Builder.Default
private Boolean findFeatureInfo = false;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class WorkspaceOuPair {
private Long workspaceId;
private Long ouId;
private Long resourceId;
private Integer resourceType;
}
}

View File

@ -14,15 +14,18 @@ import javax.validation.constraints.NotNull;
@Data
public class OUWorkspacePair {
/** 工作台ID **/
@NotNull
@NotNull(message = "工作台ID不能为空")
private Long workspaceId;
/** 工作台类型 **/
@NotNull
/** 工作台类型 - 直接依赖角色标签 不需要传了 **/
@Deprecated
private Integer workspaceType;
/** 企业组织ID **/
@NotNull
@NotNull(message = "OUId不能为空")
private Long ouId;
/** 参建类型 **/
@NotNull
/** 参建类型 - 直接依赖角色标签 不需要传了 **/
@Deprecated
private Integer workspaceJoinType;
}

View File

@ -0,0 +1,28 @@
package cn.axzo.tyr.client.model.req;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 权限缓存处理请求
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/1/2 18:36
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PermissionCacheReq {
private Long personId;
private Long identityId;
private Integer identityType;
private Boolean disableAll;
}

View File

@ -19,4 +19,6 @@ public class QueryByIdentityIdTypeReq {
Long workspaceId;
Long ouId;
Long personId;
}

View File

@ -0,0 +1,38 @@
package cn.axzo.tyr.client.model.req;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
import java.util.Set;
/**
* 根据ID查询权限点
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/1/3 13:57
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class QueryPermissionByIdsReq {
@NotEmpty(message = "权限点ID不能为空")
private Set<Long> ids;
/** 是否包含父节点 - 默认false **/
@Builder.Default
private boolean includeParent = false;
/** 是否包含子节点 - 默认false **/
@Builder.Default
private boolean includeChildren = false;
/** 是否构建树型结构 - 默认false **/
@Builder.Default
private boolean buildTree = false;
}

View File

@ -22,7 +22,6 @@ public class QuerySaasPermissionGroupReq extends PageRequest {
/**
* 角色id
*/
@NotEmpty(message = "角色id必填")
private List<Long> roleIds;
/**

View File

@ -0,0 +1,23 @@
package cn.axzo.tyr.client.model.req;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/1/17 11:03
*/
@Data
public class WorkspacePermissionIdentityReq {
/** 工作台ID **/
@NotNull
private Long workspaceId;
/** 权限点CODE **/
@NotNull
private List<String> featureCodes;
}

View File

@ -24,6 +24,7 @@ import java.util.List;
public class IdentityAuthRes {
private Long identity;
private IdentityType identityType;
private Long personId;
@Builder.Default
private List<WorkspacePermission> permissions=new ArrayList<>();
@ -59,7 +60,7 @@ public class IdentityAuthRes {
// private FeatureType featureType;
// private String terminal;
private String terminal;
}

View File

@ -1,9 +1,11 @@
package cn.axzo.tyr.client.model.res;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
/**
@ -14,6 +16,7 @@ import java.util.List;
* @date: 2023/10/20 18:03
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ListIdentityFromPermissionResp {
@ -22,16 +25,21 @@ public class ListIdentityFromPermissionResp {
private Long workspaceId;
@Builder.Default
private boolean freePermission = false;
private List<UserVO> users;
@Builder.Default
private List<UserVO> users = new ArrayList<>();
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class UserVO {
private Long ouId;
private Long identityId;
private Integer identityType;

View File

@ -0,0 +1,73 @@
package cn.axzo.tyr.client.model.res;
import cn.axzo.tyr.client.model.enums.IdentityType;
import lombok.Data;
import java.util.List;
import java.util.Set;
/**
* 通过角色分组及分类查询人员的权限
*
* @author tanjie@axzo.cn
* @date 2024/1/5 14:26
*/
@Data
public class ListPermissionFromRoleGroupResp {
private Long identityId;
private IdentityType identityType;
private Long personId;
private Long ouId;
private Long workspaceId;
/**
* 平台班组ID
*/
private Long teamOuId;
private Long resourceId;
private Integer resourceType;
/**
* 分类名称
*/
private String roleGroupName;
/**
* 分类CODE
*/
private String roleGroupCode;
/**
* 角色ID
*/
private String roleId;
/**
* 角色名称
*/
private String roleName;
/**
* 权限集ID
*/
private Long permissionGroupId;
/**
* 权限点信息 按钮级别
*/
private Set<Long> simpleFeatureInfos;
}

View File

@ -27,5 +27,7 @@ public class QueryBatchByIdentityIdTypeRes {
List<SaasRoleVO> role;
Long personId;
}

View File

@ -0,0 +1,21 @@
package cn.axzo.tyr.client.model.res;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 权限点基础信息
* @author tanjie@axzo.cn
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class SimpleFeatureInfo {
private Long featureId;
private String featureCode;
}

View File

@ -0,0 +1,67 @@
package cn.axzo.tyr.client.model.res;
import cn.axzo.basics.common.model.IBaseTree;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 权限点 - 字段简化
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/1/3 11:52
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SimplePermissionPointResp implements IBaseTree<SimplePermissionPointResp, Long> {
/** 权限点ID **/
private Long id;
/** 权限点名称 **/
private String name;
/** 权限点编码 **/
private String code;
/** 权限点所属端 **/
private String terminal;
/** 上级权限点ID **/
private Long parentId;
/** 子节点 **/
private List<SimplePermissionPointResp> children;
@JsonIgnore
@Override
public Long getNodeCode() {
return id;
}
@JsonIgnore
@Override
public Long getParentNodeCode() {
return parentId;
}
@JsonIgnore
@Override
public List<SimplePermissionPointResp> getNodeChildren() {
return children;
}
@JsonIgnore
@Override
public void setNodeChildren(List<SimplePermissionPointResp> nodeChildren) {
this.children = nodeChildren;
}
}

View File

@ -0,0 +1,24 @@
package cn.axzo.tyr.client.model.roleuser.dto;
import cn.axzo.tyr.client.model.enums.IdentityType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author tanjie@axzo.cn
* @date 2024/1/10 10:38
*/
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class IdentityInfo {
private Long personId;
private Long identityId;
private IdentityType identityType;
}

View File

@ -0,0 +1,60 @@
package cn.axzo.tyr.client.model.roleuser.req;
import cn.axzo.tyr.client.model.enums.WorkerLeaderRoleEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
/**
* 授权或者取消授权接口
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class GantOrUnGantaWorkerLeaderRoleReq {
/**
* 工作台id
*/
@NotNull
private Long workspaceId;
/**
* 团队单位id
*/
@NotNull
private Long ouId;
/**
* 平台班组id
*/
@NotNull
private Long teamOuId;
/**
* 身份id
*/
@NotNull
private Long identityId;
/**
* 自然人id
*/
@NotNull
private Long personId;
/**
* true 授权
* false 取消授权
*/
@NotNull
private Boolean grant;
@NotNull
private WorkerLeaderRoleEnum workerLeaderRoleEnum;
}

View File

@ -33,7 +33,6 @@ public class RoleUserParam extends PageRequest {
* personId
* 模型里面把personId删除了,用身份id查
*/
@Deprecated
private Long personId;
/**

View File

@ -0,0 +1,89 @@
package cn.axzo.tyr.client.model.roleuser.req;
import cn.axzo.tyr.client.common.enums.SaasPositionEnum;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.enums.WorkerLeaderRoleEnum;
import cn.axzo.tyr.client.model.roleuser.dto.IdentityInfo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* 授权或者取消授权班组管理员代班长接口
*
* @author tanjie@axzo.cn
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class WorkerManagerRoleUserReq {
private List<ManagerInfo> managerInfos;
/**
* 这个字段在设置后续产品重构了班组管理员代班长相关功能的时候要替换成ROLE ID
* 现在保留权限集ID是因为只是做统一权限角色查询链路先暂时不变REQ-2046)
*/
private List<Long> permissionGroupId;
/**
* 角色ID 会与权限集ID取并集
*/
private Collection<Long> roleId;
private IdentityType identityType;
@NotNull
private Integer resourceType;
// -------------
/**
* 是否取消授权
*/
@Builder.Default
private boolean ungrant = false;
/**
* 是否取消所有权限是的话则不消费permissionGroupId
*/
@Builder.Default
private boolean isUngrantAll = false;
/**
* 取消所有授权的角色分组 saas role group 上的categoryCode;
* 只有在isUngrantAll时生效
* #{@link SaasPositionEnum}
*/
private String roleGroupCategoryCode;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class ManagerInfo {
@NotNull
private Long ouId;
@NotNull
private Long workspaceId;
/**
* #{@link cn.axzo.tyr.client.common.enums.RoleResourceTypeEnum }
*/
@NotNull
private Long resourceId;
@Builder.Default
private List<IdentityInfo> identityInfos = new ArrayList<>();
}
}

View File

@ -0,0 +1,28 @@
package cn.axzo.tyr.client.model.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import javax.validation.constraints.NotBlank;
import java.util.Date;
import java.util.List;
/**
* 标准角色与其分组数据
* @author tanjie@axzo.cn
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
public class SaasRoleCategoryVO {
private String categoryCode;
private List<SaasRoleGroupCodeVO> roleGroupCodeVOList;
}

View File

@ -0,0 +1,18 @@
package cn.axzo.tyr.client.model.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
public class SaasRoleGroupCodeVO {
private String code;
private List<SaasRoleVO> roleInfos;
}

View File

@ -55,6 +55,13 @@ public class SaasRoleGroupVO {
*/
private Integer sort;
private String code;
/**
* 分组CODE
*/
private String categoryCode;
private Date createAt;
private Date updateAt;

View File

@ -31,6 +31,11 @@ public class SaasRoleVO {
*/
private String name;
/**
* 角色所对应的产品属性
*/
private Integer productUnitType;
/**
* 角色类型 init 标准 common 自定义角色 admin管理员 super_admin 超管
*/
@ -59,7 +64,6 @@ public class SaasRoleVO {
private Date createAt;
private Date updateAt;
/**
* 获取角色对应所用的菜单不管例外
*

View File

@ -22,7 +22,11 @@
</properties>
<dependencies>
<dependency>
<groupId>cn.axzo.basics</groupId>
<artifactId>basics-auth-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>cn.axzo.tyr</groupId>
<artifactId>tyr-api</artifactId>
@ -92,6 +96,12 @@
<artifactId>feign-httpclient</artifactId>
<version>${feign-httpclient.version}</version>
</dependency>
<dependency>
<groupId>cn.axzo.maokai</groupId>
<artifactId>maokai-api</artifactId>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -37,4 +37,19 @@ public class ExecutorConfig {
executor.prestartCoreThread();
return executor;
}
/**
* 用户角色清理任务线程池
* @return
*/
@Bean
public ExecutorService userRoleCleanExecutor() {
new ThreadPoolExecutor.CallerRunsPolicy();
int coreSize = 5;
ThreadPoolExecutor executor = new ThreadPoolExecutor(coreSize, 10, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100), new NamedThreadFactory("user-role-clean-job-", false), new ThreadPoolExecutor.CallerRunsPolicy());
executor.prestartCoreThread();
return executor;
}
}

View File

@ -33,6 +33,9 @@ public class FeignConfig implements RequestInterceptor, EnvironmentAware {
@Value("${thronesEnvUrl:http://dev-app.axzo.cn/thrones}")
private String thronesEnvUrl;
@Value("${maokaiEnvUrl:http://dev-app.axzo.cn/maokai}")
private String maokaiEnvUrl;
private static String POD_NAMESPACE;
static {
@ -53,6 +56,7 @@ public class FeignConfig implements RequestInterceptor, EnvironmentAware {
url = url.replace("http://msg-center:8080", msgCenterEnvUrl);
url = url.replace("http://workflow-engine:8080", workflowEnvUrl);
url = url.replace("http://thrones", thronesEnvUrl);
url = url.replace("http://maokai:8080", maokaiEnvUrl);
String profile = environment.getProperty("spring.profiles.active");
if(Objects.equals(profile, "test") && url.contains("dev-app.axzo.cn")) {
url = url.replace("dev-app", "test-api");

View File

@ -1,16 +1,24 @@
package cn.axzo.tyr.server.controller.auth;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.feign.TyrSaasAuthApi;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.req.CheckIdentityPermissionReq;
import cn.axzo.tyr.client.model.req.IdentityAuthReq;
import cn.axzo.tyr.client.model.req.BatchListIdentityFromPermissionReq;
import cn.axzo.tyr.client.model.req.ListIdentityFromPermissionReq;
import cn.axzo.tyr.client.model.req.ListPermissionFromFeatureReq;
import cn.axzo.tyr.client.model.req.ListPermissionFromIdentityReq;
import cn.axzo.tyr.client.model.req.ListPermissionFromRoleGroupReq;
import cn.axzo.tyr.client.model.req.PermissionCacheReq;
import cn.axzo.tyr.client.model.req.WorkspacePermissionIdentityReq;
import cn.axzo.tyr.client.model.res.IdentityAuthRes;
import cn.axzo.tyr.client.model.res.ListIdentityFromPermissionResp;
import cn.axzo.tyr.client.model.res.ListPermissionFromRoleGroupResp;
import cn.axzo.tyr.client.model.res.QueryIdentityByPermissionResp;
import cn.axzo.tyr.server.model.PermissionCacheKey;
import cn.axzo.tyr.server.service.PermissionCacheService;
import cn.axzo.tyr.server.service.TyrSaasAuthService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -29,6 +37,7 @@ import java.util.List;
public class TyrSaasAuthController implements TyrSaasAuthApi {
private final TyrSaasAuthService tyrSaasAuthService;
private final PermissionCacheService permissionCacheService;
@Override
public ApiResult<Boolean> hasPermissionForIdentity(CheckIdentityPermissionReq req) {
@ -47,11 +56,21 @@ public class TyrSaasAuthController implements TyrSaasAuthApi {
@Override
public ApiResult<IdentityAuthRes> findIdentityAuth(@Valid IdentityAuthReq identityAuthReq) {
return ApiResult.ok(tyrSaasAuthService.findIdentityAuth(identityAuthReq));
//单独做下参数校验
if (identityAuthReq.getPersonId() == null
&& (identityAuthReq.getIdentityId() == null || identityAuthReq.getIdentityType() == null)) {
AssertUtil.fail("自然人ID和身份ID/Type不能同时为空");
}
return ApiResult.ok(tyrSaasAuthService.findIdentityAuthMix(identityAuthReq));
}
@Override
public ApiResult<Boolean> hasPermissionForIdentityV2(CheckIdentityPermissionReq req) {
//单独做下参数校验
if (req.getPersonId() == null
&& (req.getIdentityId() == null || req.getIdentityType() == null)) {
AssertUtil.fail("自然人ID和身份ID/Type不能同时为空");
}
return ApiResult.ok(tyrSaasAuthService.hasPermissionForIdentityV2(req));
}
@ -65,4 +84,24 @@ public class TyrSaasAuthController implements TyrSaasAuthApi {
return ApiResult.ok(tyrSaasAuthService.batchListIdentityFromPermission(req));
}
@Override
public ApiResult<List<ListIdentityFromPermissionResp>> listWorkspacePermissionIdentity(WorkspacePermissionIdentityReq req) {
return ApiResult.ok(tyrSaasAuthService.listWorkspacePermissionIdentity(req));
}
@Override
public ApiResult<Void> tempDisableAuthCache(PermissionCacheReq req) {
permissionCacheService.markTempDisable(PermissionCacheKey.builder()
.disableAll(req.getDisableAll())
.personId(req.getPersonId())
.identityId(req.getIdentityId())
.identityType(IdentityType.getIdentityType(req.getIdentityType()))
.build());
return ApiResult.ok();
}
@Override
public ApiResult<List<ListPermissionFromRoleGroupResp>> listAuthByResourceAndRoleGroup(ListPermissionFromRoleGroupReq listPermissionFromRoleGroupReq) {
return ApiResult.ok(tyrSaasAuthService.listAuthByResourceAndRoleGroup(listPermissionFromRoleGroupReq));
}
}

View File

@ -8,6 +8,8 @@ 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.QueryPermissionByIdsReq;
import cn.axzo.tyr.client.model.res.SimplePermissionPointResp;
import cn.axzo.tyr.server.service.PermissionPointService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -80,4 +82,9 @@ public class PermissionPointController implements PermissionPointApi {
public ApiResult<List<PermissionPointDTO>> getChildByParentId(Long id) {
return ApiResult.ok(permissionPointService.getChildByParentId(id));
}
@Override
public ApiResult<List<SimplePermissionPointResp>> listPermissionByIds(QueryPermissionByIdsReq req) {
return ApiResult.ok(permissionPointService.listPermissionByIds(req));
}
}

View File

@ -9,6 +9,9 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collection;
import java.util.List;
/**
* @author honghao.zhang
* @since 2023/10/18 18:30
@ -24,4 +27,9 @@ public class TyrSaasFeatureController implements TyrSaasFeatureApi {
public ApiResult<FeaturePermissionRes> listPermissionCodes(FeaturePermissionReq req) {
return ApiResult.ok(saasFeatureService.listPermissionCodes(req));
}
@Override
public ApiResult<List<Long>> listAppFeatureIds(Collection<Long> appItemIds) {
return ApiResult.ok(saasFeatureService.listAppFeatureIds(appItemIds));
}
}

View File

@ -11,12 +11,13 @@ 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.server.model.PermissionCacheKey;
import cn.axzo.tyr.server.service.PermissionCacheService;
import cn.axzo.tyr.server.service.ProductFeatureRelationService;
import cn.axzo.tyr.server.service.ProductService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@ -36,6 +37,7 @@ public class ProductController implements ProductApi {
private final ProductService productService;
private final ProductFeatureRelationService productFeatureRelationService;
private final PermissionCacheService permissionCacheService;
/**
* 获取产品基础信息的列表
*
@ -124,6 +126,7 @@ public class ProductController implements ProductApi {
if(CollectionUtils.isEmpty(req)) {
return ApiResult.ok(false);
}
permissionCacheService.markTempDisable(PermissionCacheKey.builder().disableAll(true).build());
return productFeatureRelationService.updateFeatureRelation(req);
}

View File

@ -8,13 +8,19 @@ import cn.axzo.tyr.client.model.req.QueryByIdentityIdTypeReq;
import cn.axzo.tyr.client.model.req.QueryRoleByNameReq;
import cn.axzo.tyr.client.model.req.QuerySaasRoleReq;
import cn.axzo.tyr.client.model.req.RoleWithUserQueryReq;
import cn.axzo.tyr.client.model.req.ChangeGroupLeaderRoleReq;
import cn.axzo.tyr.client.model.res.IsSuperAdminRes;
import cn.axzo.tyr.client.model.res.QueryBatchByIdentityIdTypeRes;
import cn.axzo.tyr.client.model.res.QueryRoleByNameResp;
import cn.axzo.tyr.client.model.res.RoleWithUserRes;
import cn.axzo.tyr.client.model.vo.SaasRoleAndGroupVO;
import cn.axzo.tyr.client.model.vo.SaasRoleCategoryVO;
import cn.axzo.tyr.client.model.vo.SaasRoleGroupCodeVO;
import cn.axzo.tyr.client.model.vo.SaasRoleVO;
import cn.axzo.tyr.client.model.vo.SaveOrUpdateRoleVO;
import cn.axzo.tyr.server.model.PermissionCacheKey;
import cn.axzo.tyr.server.repository.dao.SaasRoleUserRelationDao;
import cn.axzo.tyr.server.service.PermissionCacheService;
import cn.axzo.tyr.server.service.RoleService;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
@ -39,10 +45,16 @@ public class SaasRoleController implements TyrSaasRoleApi {
@Autowired
RoleService roleService;
@Autowired
PermissionCacheService permissionCacheService;
@Autowired
private SaasRoleUserRelationDao saasRoleUserRelationDao;
@Override
public ApiResult<Long> saveOrUpdate(SaveOrUpdateRoleVO saveOrUpdateRole) {
return ApiResult.ok(roleService.saveOrUpdate(saveOrUpdateRole));
Long result = roleService.saveOrUpdate(saveOrUpdateRole);
permissionCacheService.markTempDisable(PermissionCacheKey.builder().disableAll(true).build());
return ApiResult.ok(result);
}
@Override
@ -66,6 +78,7 @@ public class SaasRoleController implements TyrSaasRoleApi {
@Override
public ApiResult<Void> deleteRole(List<Long> roleIds, Long workSpaceId, Long outId) {
roleService.deleteRole(roleIds, workSpaceId, outId);
permissionCacheService.markTempDisable(PermissionCacheKey.builder().disableAll(true).build());
return ApiResult.ok();
}
@ -104,4 +117,20 @@ public class SaasRoleController implements TyrSaasRoleApi {
return ApiResult.ok(roleService.queryInitRoleByWorkspaceId(workspaceType));
}
@Override
public ApiResult<List<SaasRoleCategoryVO>> queryByCategoryCode(List<String> categoryCodes) {
return ApiResult.ok(roleService.queryByCategoryCode(categoryCodes));
}
@Override
public ApiResult<List<SaasRoleGroupCodeVO>> queryByCodes(List<String> codes) {
return ApiResult.ok(roleService.queryByCodes(codes));
}
@Override
public ApiResult<Void> changeGroupLeaderRole(List<ChangeGroupLeaderRoleReq> reqs) {
roleService.changeGroupLeaderRole(reqs);
return ApiResult.ok();
}
}

View File

@ -50,4 +50,10 @@ public class SaasRoleGroupController implements SaasRoleGroupApi {
saasRoleGroupService.delete(ids);
return ApiResult.ok();
}
@Override
public ApiResult<List<SaasRoleGroupVO>> listByCategoryCode(List<String> categoryCode) {
return ApiResult.ok(saasRoleGroupService.listByCategoryCode(categoryCode));
}
}

View File

@ -5,16 +5,19 @@ import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.tyr.client.feign.TyrSaasRoleUserApi;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserDTO;
import cn.axzo.tyr.client.model.roleuser.dto.SuperAminInfoResp;
import cn.axzo.tyr.client.model.roleuser.req.*;
import cn.axzo.tyr.server.model.PermissionCacheKey;
import cn.axzo.tyr.server.repository.dao.SaasRoleUserRelationDao;
import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation;
import cn.axzo.tyr.server.service.PermissionCacheService;
import cn.axzo.tyr.server.service.SaasRoleUserRelationService;
import cn.axzo.tyr.server.service.SaasRoleUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@ -33,10 +36,29 @@ public class RoleUserController implements TyrSaasRoleUserApi {
private final SaasRoleUserService saasRoleUserService;
private final SaasRoleUserRelationService saasRoleUserRelationService;
private final SaasRoleUserRelationDao saasRoleUserRelationDao;
private final PermissionCacheService permissionCacheService;
@Override
public ApiResult<Void> saveOrUpdate(@Valid RoleUserReq req) {
saasRoleUserService.saveOrUpdate(req);
permissionCacheService.markTempDisable(PermissionCacheKey.builder()
.personId(req.getPersonId())
.identityId(req.getIdentityId())
.identityType(req.getIdentityType())
.build());
return ApiResult.ok();
}
@Override
public ApiResult<Void> grantOrUngrantWorkerLeader(GantOrUnGantaWorkerLeaderRoleReq req) {
saasRoleUserService.grantOrUngrantWorkerLeader(req);
return ApiResult.ok();
}
@Override
public ApiResult<Void> grantOrUngrantWorkerManager(WorkerManagerRoleUserReq req) {
saasRoleUserService.grantOrUngrantWorkerManager(req);
return ApiResult.ok();
}
@ -44,6 +66,11 @@ public class RoleUserController implements TyrSaasRoleUserApi {
public ApiResult<Void> batchSaveOrUpdate(List<RoleUserReq> req) {
for (RoleUserReq roleUserReq : req) {
saasRoleUserService.saveOrUpdate(roleUserReq);
permissionCacheService.markTempDisable(PermissionCacheKey.builder()
.personId(roleUserReq.getPersonId())
.identityId(roleUserReq.getIdentityId())
.identityType(roleUserReq.getIdentityType())
.build());
}
return ApiResult.ok();
}
@ -62,6 +89,11 @@ public class RoleUserController implements TyrSaasRoleUserApi {
@Override
public ApiResult<Void> createSuperAdminRole(CreateSuperAdminRoleParam param) {
saasRoleUserService.createSuperAdminRole(param);
permissionCacheService.markTempDisable(PermissionCacheKey.builder()
.personId(param.getNaturalPersonId())
.identityId(param.getIdentityId())
.identityType(param.getIdentityType())
.build());
return ApiResult.ok();
}
@ -89,10 +121,18 @@ public class RoleUserController implements TyrSaasRoleUserApi {
*/
public ApiResult removeRoleUserRelation(@RequestBody @Valid List<Long> ids){
AssertUtil.isTrue(!CollectionUtils.isEmpty(ids),"用户角色关联id不能为空");
List<SaasRoleUserRelation> relations = saasRoleUserRelationDao.listByIds(ids);
saasRoleUserRelationDao.lambdaUpdate()
.in(BaseEntity::getId,ids)
.setSql(" is_delete = id")
.update();
for (SaasRoleUserRelation relation : relations) {
permissionCacheService.markTempDisable(PermissionCacheKey.builder()
.personId(relation.getNaturalPersonId())
.identityId(relation.getIdentityId())
.identityType(IdentityType.getIdentityType(relation.getIdentityType()))
.build());
}
return ApiResult.ok();
}

View File

@ -0,0 +1,131 @@
package cn.axzo.tyr.server.job;
import cn.axzo.basics.common.util.NumberUtil;
import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
import cn.axzo.tyr.server.repository.entity.SaasFeature;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.core.log.XxlJobLogger;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 检查处理权限点数据
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/1/31 11:54
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class SaasFeatureCheckJobHandler extends IJobHandler {
private final SaasFeatureDao saasFeatureDao;
@XxlJob("saasFeatureCheckJobHandler")
@Override
public ReturnT<String> execute(String jsonParam) throws Exception {
XxlJobLogger.log("start saas feature check job with parma:{}", jsonParam);
JobParam jobParam = StrUtil.isBlank(jsonParam) ? new JobParam() : JSONObject.parseObject(jsonParam, JobParam.class);
Map<Long, Long> idMap = getAllIds();
checkAndProcess(jobParam, idMap);
XxlJobLogger.log("all saas feature process complete");
return ReturnT.SUCCESS;
}
private void checkAndProcess(JobParam jobParam, Map<Long, Long> idMap) {
Long page = 0L;
while (true) {
XxlJobLogger.log("------------> query feature for page:{}", page);
IPage<SaasFeature> featurePage = pageQueryFeature(jobParam.featureIds, page, jobParam.pageSize);
List<SaasFeature> features = featurePage.getRecords();
if (CollectionUtil.isEmpty(features)) {
XxlJobLogger.log("no features data found");
break;
}
for (SaasFeature feature : features) {
String newPath = concatPath(feature.getId(), idMap);
Long parentId = idMap.get(feature.getId());
if (StrUtil.equals(newPath, feature.getPath())
&& (!NumberUtil.isPositiveNumber(parentId) || idMap.containsKey(parentId))) {
//检查parent path
continue;
}
Long newParentId = idMap.containsKey(parentId) ? parentId : 0;
updateFeature(feature.getId(), newParentId, newPath);
XxlJobLogger.log("fix feature path/parent for:{} path: {} --> {}, parentId:{} -> {}",
feature.getId(), feature.getPath(), newPath, parentId, newParentId);
}
page++;
XxlJobLogger.log("-------------> feature check process batch complete");
}
}
private void updateFeature(Long id, Long newParentId, String newPath) {
saasFeatureDao.lambdaUpdate()
.set(SaasFeature::getParentId, newParentId).set(SaasFeature::getPath, newPath)
.eq(SaasFeature::getId, id)
.update();
}
private String concatPath(Long id, Map<Long, Long> idMap) {
if (!NumberUtil.isPositiveNumber(id)) {
return "/0/";
}
Long parentId = idMap.get(id);
if (!NumberUtil.isPositiveNumber(parentId)) {
return "/0/";
}
if (!idMap.containsKey(parentId)) {
return "/0/";
}
if (parentId.equals(id)) {
//防数据导致死循环
return "/0/";
}
return concatPath(parentId, idMap) + parentId + "/";
}
private IPage<SaasFeature> pageQueryFeature(List<Long> featureIds, Long page, Long pageSize) {
return saasFeatureDao.lambdaQuery()
.select(SaasFeature::getId, SaasFeature::getPath)
.in(CollectionUtil.isNotEmpty(featureIds), SaasFeature::getId, featureIds)
.page(new Page<>(page, pageSize));
}
/** 权限点ID映射 id -> parentId **/
private Map<Long, Long> getAllIds() {
//拿到所有的ID和对应的parent id
XxlJobLogger.log("get all feature id and parent");
return saasFeatureDao.lambdaQuery()
.select(SaasFeature::getId, SaasFeature::getParentId)
.list()
.stream()
.collect(Collectors.toMap(SaasFeature::getId, SaasFeature::getParentId));
}
@Data
public static class JobParam {
private List<Long> featureIds = new ArrayList<>();
private Long pageSize = 20L;
}
}

View File

@ -0,0 +1,208 @@
package cn.axzo.tyr.server.job;
import cn.axzo.basics.common.BeanMapper;
import cn.axzo.basics.common.util.NumberUtil;
import cn.axzo.maokai.api.client.CooperateShipQueryApi;
import cn.axzo.maokai.api.vo.request.PersonIdentityCheckReq;
import cn.axzo.pokonyan.config.redis.RedisClient;
import cn.axzo.pokonyan.config.redis.RedisUtil;
import cn.axzo.tyr.server.repository.dao.SaasRoleUserRelationDao;
import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation;
import cn.axzo.tyr.server.util.RpcInternalUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.core.log.XxlJobLogger;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 用户角色关系清理任务
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/3/4 10:09
*/
@Slf4j
@Component
public class UserRoleRelationCleanJob extends IJobHandler {
private static final String CACHE_KEY = "tyr:job:u-r-r-c";
private volatile boolean runFlag = false;
@Qualifier("userRoleCleanExecutor")
@Autowired
private ExecutorService userRoleCleanExecutor;
@Autowired
private SaasRoleUserRelationDao roleUserRelationDao;
@Autowired
private CooperateShipQueryApi cooperateShipQueryApi;
@XxlJob("userRoleRelationCleanJob")
@Override
public ReturnT<String> execute(String param) throws Exception {
StopWatch watch = new StopWatch("userRoleRelationCleanJob");
XxlJobLogger.log("start user role relation clean job param{}", param);
CleanTarget cleanParam = parseParam(param);
//加载待处理数据
watch.start("load and check data");
loadCleanTarget(cleanParam);
watch.stop();
watch.start("do clean");
runFlag = true;
XxlJobLogger.log("start to clean user role relation");
while (runFlag) {
CleanTarget target = getTarget();
if (target == null) {
XxlJobLogger.log("all clean target are processed");
break;
}
//防数据库锁竞争 删除不做并发
doClean(target);
}
watch.stop();
XxlJobLogger.log("user role relation clean job finish, cost:{} seconds", watch.getTotalTimeSeconds());
return ReturnT.SUCCESS;
}
private CleanTarget getTarget() {
try {
String cacheTarget = RedisClient.ListOps.lRightPop(CACHE_KEY);
XxlJobLogger.log("---------> user role relation need to clean for:{} <----------", cacheTarget);
return StrUtil.isBlank(cacheTarget) ? null : JSON.parseObject(cacheTarget, CleanTarget.class);
} catch (Exception ex) {
XxlJobLogger.log("get cached data error:{}", ex.getMessage());
}
return null;
}
@Override
public void destroy() throws InvocationTargetException, IllegalAccessException {
this.runFlag = false;
super.destroy();
}
private void doClean(CleanTarget target) {
try {
roleUserRelationDao.cleanTargetRelation(target);
} catch (Exception ex) {
XxlJobLogger.log("clean target:{} error", JSON.toJSONString(target));
log.warn("clean target:{} error", JSON.toJSONString(target), ex);
}
}
private void loadCleanTarget(CleanTarget cleanParam) throws InterruptedException {
XxlJobLogger.log("clear cache data");
RedisClient.KeyOps.delete(CACHE_KEY);
XxlJobLogger.log("load and check clean target data from db");
SaasRoleUserRelation condition = new SaasRoleUserRelation();
condition.setOuId(cleanParam.getOuId());
condition.setWorkspaceId(cleanParam.getWorkspaceId());
condition.setNaturalPersonId(cleanParam.getPersonId());
Page<SaasRoleUserRelation> countInfo = roleUserRelationDao.batListCleanRelation(condition, new Page<>(1, 10));
if (!NumberUtil.isPositiveNumber(countInfo.getTotal())) {
XxlJobLogger.log("no data found to check");
return;
}
final CountDownLatch latch = new CountDownLatch((int) countInfo.getTotal());
int page = 1;
while (true) {
XxlJobLogger.log(" load data page:{} ", page);
Page<SaasRoleUserRelation> pageResult = roleUserRelationDao.batListCleanRelation(condition, new Page<>(page++, cleanParam.getPageSize()));
List<SaasRoleUserRelation> records = pageResult.getRecords();
if (CollectionUtil.isEmpty(records)) {
break;
}
for (SaasRoleUserRelation relation : records) {
CompletableFuture.runAsync(() -> checkAndCache(relation, latch), userRoleCleanExecutor);
}
}
//等数据检查完成
latch.await(30, TimeUnit.MINUTES);
}
private void checkAndCache(SaasRoleUserRelation relation, CountDownLatch latch) {
//检查person profile是否存在 ?
//检查人是否还在工作台
try {
CleanTarget target = CleanTarget.builder()
.ouId(relation.getOuId())
.workspaceId(relation.getWorkspaceId())
.personId(relation.getNaturalPersonId())
.identityId(relation.getIdentityId())
.identityType(relation.getIdentityType())
.build();
PersonIdentityCheckReq checkReq = BeanMapper.copyBean(target, PersonIdentityCheckReq.class);
Boolean exists = RpcInternalUtil.rpcProcessor(() -> cooperateShipQueryApi.checkPersonIdentity(checkReq),
"check identity in workspace", checkReq).getData();
if (exists) {
return;
}
//直接删除会导致分页不准
RedisClient.ListOps.lLeftPush(CACHE_KEY, JSON.toJSONString(target));
} catch (Exception ex) {
XxlJobLogger.log("check user role relation error:{}", ex.getMessage());
} finally {
latch.countDown();
}
}
private CleanTarget parseParam(String param) {
if (StrUtil.isBlank(param)) {
return new CleanTarget();
}
CleanTarget jobParam = JSON.parseObject(param, CleanTarget.class);
if (!NumberUtil.isPositiveNumber(jobParam.getPageSize())) {
jobParam.setPageSize(100);
}
return jobParam;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class CleanTarget {
private Long ouId;
private Long workspaceId;
private Long personId;
private Long identityId;
private Integer identityType;
private Integer pageSize = 20;
}
}

View File

@ -0,0 +1,27 @@
package cn.axzo.tyr.server.model;
import cn.axzo.tyr.server.service.impl.TyrSaasAuthServiceImpl;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 通过工作台过滤角色的权限
* #{@link TyrSaasAuthServiceImpl#filterAuthByRoleAndProduct()}
* @author tanjie@axzo.cn
* @date 2024/1/8 14:16
*/
@AllArgsConstructor
@Data
@NoArgsConstructor
@Builder
public class FilterRoleAuth {
private Long roleId;
private Long workspaceId;
}

View File

@ -0,0 +1,51 @@
package cn.axzo.tyr.server.model;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.server.util.KeyUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 权限缓存key
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/1/2 18:36
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PermissionCacheKey {
private Long personId;
private Long identityId;
private IdentityType identityType;
private Long workspaceId;
private Long ouId;
private Boolean disableAll;
public String buildAuthKey() {
return personId == null ? KeyUtil.buildKeyBySeparator("auth-i", identityId, identityType.getCode(), ouId, workspaceId)
: KeyUtil.buildKeyBySeparator("auth-p", personId, ouId, workspaceId);
}
public String buildPersonDisableKey() {
return KeyUtil.buildKeyBySeparator("auth-d-p", personId);
}
public String buildIdentityDisableKey() {
return KeyUtil.buildKeyBySeparator("auth-d-i", identityId, identityType.getCode());
}
public static String buildAllDisableKey() {
return "auth-disable-all";
}
}

View File

@ -0,0 +1,49 @@
package cn.axzo.tyr.server.model;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.roleuser.dto.IdentityInfo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* @author tanjie@axzo.cn
* @date 2024/1/9 17:00
*/
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class RoleUserInfo {
private Set<Long> roleId;
private IdentityType identityType;
private Integer resourceType;
private List<RoleUserResourceInfo> roleUserResourceInfos;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public static class RoleUserResourceInfo {
private Long ouId;
private Long workspaceId;
/**
* #{@link cn.axzo.tyr.client.common.enums.RoleResourceTypeEnum }
*/
private Long resourceId;
@Builder.Default
private List<IdentityInfo> identityInfos = new ArrayList<>();
}
}

View File

@ -0,0 +1,28 @@
package cn.axzo.tyr.server.repository.dao;
import cn.axzo.tyr.client.model.enums.IdentityType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Set;
/**
* @author axzo
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class RemoveRoleUserByResource {
private IdentityType identityType;
private Long resourceId;
private int resourceType;
private List<Long> identityId;
private Long workspaceId;
private Long ouId;
private Set<Long> roleId;
}

View File

@ -32,5 +32,17 @@ public class SaasPgroupRoleRelationDao extends ServiceImpl<SaasPgroupRoleRelatio
.set(BaseEntity::getIsDelete, TableIsDeleteEnum.DELETE.value)
.update();
}
public List<SaasPgroupRoleRelation> findByRoleIds(Collection<Long> roleIds) {
return lambdaQuery()
.in(SaasPgroupRoleRelation::getRoleId, roleIds)
.list();
}
public List<SaasPgroupRoleRelation> listByGroupIds(List<Long> permissionGroupId) {
return lambdaQuery()
.in(SaasPgroupRoleRelation::getGroupId, permissionGroupId).list();
}
}

View File

@ -25,5 +25,13 @@ public class SaasProductModuleFeatureRelationDao extends ServiceImpl<SaasProduct
this.remove(new LambdaQueryWrapper<SaasProductModuleFeatureRelation>()
.in(SaasProductModuleFeatureRelation::getFeatureId, permissionPointIds));
}
public void removeByProductId(List<Long> productId) {
if (CollectionUtil.isEmpty(productId)) {
return;
}
this.remove(new LambdaQueryWrapper<SaasProductModuleFeatureRelation>()
.in(SaasProductModuleFeatureRelation::getProductModuleId, productId));
}
}

View File

@ -105,5 +105,15 @@ public class SaasRoleDao extends ServiceImpl<SaasRoleMapper, SaasRole> {
.setSql(" is_delete = id")
.update();
}
public List<SaasRole> findInitRole(Set<Long> roleIds) {
if (CollectionUtils.isEmpty(roleIds)) {
return new ArrayList<>();
}
return lambdaQuery().in(BaseEntity::getId, roleIds)
.eq(BaseEntity::getIsDelete, TableIsDeleteEnum.NORMAL)
.eq(SaasRole::getRoleType, RoleTypeEnum.INIT.getValue())
.list();
}
}

View File

@ -5,6 +5,7 @@ import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq;
import cn.axzo.tyr.server.repository.entity.SaasRoleGroup;
import cn.axzo.tyr.server.repository.mapper.SaasRoleGroupMapper;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections.CollectionUtils;
@ -50,5 +51,14 @@ public class SaasRoleGroupDao extends ServiceImpl<SaasRoleGroupMapper, SaasRoleG
.update();
}
public List<SaasRoleGroup> listByCategoryCode(List<String> categoryCode) {
return lambdaQuery().eq(BaseEntity::getIsDelete, 0L)
.in(SaasRoleGroup::getCategoryCode, categoryCode).list();
}
public List<SaasRoleGroup> listByCodes(List<String> codes) {
return lambdaQuery().eq(BaseEntity::getIsDelete, 0L)
.in(SaasRoleGroup::getCode, codes).list();
}
}

View File

@ -2,6 +2,7 @@ package cn.axzo.tyr.server.repository.dao;
import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.tyr.server.repository.entity.SaasPgroupRoleRelation;
import cn.axzo.tyr.server.repository.entity.SaasRoleGroupRelation;
import cn.axzo.tyr.server.repository.mapper.SaasRoleGroupRelationMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@ -9,8 +10,10 @@ import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Repository;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
@Repository
public class SaasRoleGroupRelationDao extends ServiceImpl<SaasRoleGroupRelationMapper, SaasRoleGroupRelation> {
@ -26,7 +29,10 @@ public class SaasRoleGroupRelationDao extends ServiceImpl<SaasRoleGroupRelationM
.update();
}
public List<SaasRoleGroupRelation> getByGroupIds(List<Long> groupIds) {
public List<SaasRoleGroupRelation> getByGroupIds(Collection<Long> groupIds) {
if (CollectionUtils.isEmpty(groupIds)) {
return new ArrayList<>();
}
return lambdaQuery().in(SaasRoleGroupRelation::getSaasRoleGroupId, groupIds)
.eq(BaseEntity::getIsDelete, 0)
.list();
@ -41,5 +47,7 @@ public class SaasRoleGroupRelationDao extends ServiceImpl<SaasRoleGroupRelationM
.set(BaseEntity::getIsDelete,1L)
.update();
}
}

View File

@ -2,17 +2,27 @@ package cn.axzo.tyr.server.repository.dao;
import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.tyr.client.common.enums.RoleResourceTypeEnum;
import cn.axzo.tyr.client.model.BaseWorkspaceModel;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.roleuser.dto.IdentityInfo;
import cn.axzo.tyr.server.job.UserRoleRelationCleanJob;
import cn.axzo.tyr.server.model.RoleUserInfo;
import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation;
import cn.axzo.tyr.server.repository.mapper.SaasRoleUserRelationMapper;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@Repository
public class SaasRoleUserRelationDao extends ServiceImpl<SaasRoleUserRelationMapper, SaasRoleUserRelation> {
@ -27,13 +37,34 @@ public class SaasRoleUserRelationDao extends ServiceImpl<SaasRoleUserRelationMap
.list();
}
public void deleteByRoldId(List<Long> roleId) {
public List<SaasRoleUserRelation> queryByPersonId(Long personId, Long workspaceId, Long ouId) {
return this.lambdaQuery()
.eq(SaasRoleUserRelation::getNaturalPersonId, personId)
.eq(null != workspaceId, SaasRoleUserRelation::getWorkspaceId, workspaceId)
.eq(null != ouId, SaasRoleUserRelation::getOuId, ouId)
.eq(BaseEntity::getIsDelete, TableIsDeleteEnum.NORMAL.value)
.list();
}
public void deleteByRoleId(List<Long> roleId) {
lambdaUpdate()
.in(SaasRoleUserRelation::getRoleId,roleId)
.set(BaseEntity::getIsDelete,TableIsDeleteEnum.DELETE.value)
.update();
}
public void deleteById(List<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return;
}
lambdaUpdate()
.eq(SaasRoleUserRelation::getIsDelete, TableIsDeleteEnum.NORMAL.value)
.in(SaasRoleUserRelation::getId, ids)
.setSql("is_delete = id")
.update();
}
/**
* 若未传入roleId会导致用户所以角色都被清除
* @param baseWorkspaceModel
@ -63,9 +94,11 @@ public class SaasRoleUserRelationDao extends ServiceImpl<SaasRoleUserRelationMap
* @param ouIds
* @return
*/
public List<SaasRoleUserRelation> queryByWorkspaceIdOrOu(Long identityId, IdentityType identityType, Set<Long> workspaceIds, Set<Long> ouIds) {
return lambdaQuery().eq(SaasRoleUserRelation::getIdentityId, identityId)
.eq(SaasRoleUserRelation::getIdentityType, identityType)
public List<SaasRoleUserRelation> queryByWorkspaceIdOrOu(Long personId, Long identityId, IdentityType identityType, Set<Long> workspaceIds, Set<Long> ouIds) {
return lambdaQuery()
.eq(Objects.nonNull(personId), SaasRoleUserRelation::getNaturalPersonId, personId)
.eq(Objects.nonNull(identityId), SaasRoleUserRelation::getIdentityId, identityId)
.eq(Objects.nonNull(identityType), SaasRoleUserRelation::getIdentityType, identityType)
.in(CollectionUtil.isNotEmpty(workspaceIds), SaasRoleUserRelation::getWorkspaceId, workspaceIds)
.in(CollectionUtil.isNotEmpty(ouIds), SaasRoleUserRelation::getOuId, ouIds)
.list();
@ -79,5 +112,75 @@ public class SaasRoleUserRelationDao extends ServiceImpl<SaasRoleUserRelationMap
.setSql(" is_delete = id")
.update();
}
/**
* 删除平台班组长项目内班组长角色
*/
public void removeWorkerLeaderRole(Long identityId, IdentityType identityType, Long workspaceId, Long ouId) {
lambdaUpdate()
.eq(SaasRoleUserRelation::getIdentityId, identityId)
.eq(SaasRoleUserRelation::getIdentityType, identityType)
.eq(SaasRoleUserRelation::getWorkspaceId, workspaceId)
.eq(SaasRoleUserRelation::getOuId, ouId)
.eq(SaasRoleUserRelation::getIsDelete, TableIsDeleteEnum.NORMAL.value)
.setSql(" is_delete = id")
.update();
}
public List<SaasRoleUserRelation> findByResource(RoleUserInfo req) {
List<RoleUserInfo.RoleUserResourceInfo> roleUserResourceInfos = req.getRoleUserResourceInfos();
Set<Long> workspaceIds = roleUserResourceInfos.stream().map(RoleUserInfo.RoleUserResourceInfo::getWorkspaceId).collect(Collectors.toSet());
Set<Long> ouIds = roleUserResourceInfos.stream().map(RoleUserInfo.RoleUserResourceInfo::getOuId).collect(Collectors.toSet());
Set<Long> identityIds = roleUserResourceInfos.stream().map(RoleUserInfo.RoleUserResourceInfo::getIdentityInfos).flatMap(List::stream).map(IdentityInfo::getIdentityId).distinct().collect(Collectors.toSet());
Set<Long> resourceIds = roleUserResourceInfos.stream().map(RoleUserInfo.RoleUserResourceInfo::getResourceId).collect(Collectors.toSet());
return lambdaQuery()
.eq(SaasRoleUserRelation::getIdentityType, req.getIdentityType().getCode())
.in(CollectionUtil.isNotEmpty(req.getRoleId()), SaasRoleUserRelation::getRoleId, req.getRoleId())
.in(CollectionUtil.isNotEmpty(ouIds),SaasRoleUserRelation::getOuId,ouIds)
.in(CollectionUtil.isNotEmpty(identityIds),SaasRoleUserRelation::getIdentityId,identityIds)
.in(CollectionUtil.isNotEmpty(workspaceIds),SaasRoleUserRelation::getWorkspaceId,workspaceIds)
.in(CollectionUtil.isNotEmpty(resourceIds),SaasRoleUserRelation::getResourceId,resourceIds)
.eq(SaasRoleUserRelation::getResourceType, req.getResourceType())
.in(SaasRoleUserRelation::getRoleId,req.getRoleId())
.list();
}
public List<SaasRoleUserRelation> findValidByNodeResource(Long personId, Long nodeId, Long roleId) {
return lambdaQuery()
.eq(SaasRoleUserRelation::getIsDelete, TableIsDeleteEnum.NORMAL.value)
.eq(SaasRoleUserRelation::getResourceType, RoleResourceTypeEnum.NODE.code)
.eq(Objects.nonNull(nodeId), SaasRoleUserRelation::getResourceId, nodeId)
.eq(Objects.nonNull(personId), SaasRoleUserRelation::getNaturalPersonId, personId)
.eq(Objects.nonNull(roleId), SaasRoleUserRelation::getRoleId, roleId)
.list();
}
public void removeByResource(RemoveRoleUserByResource req) {
List<Long> identityId = req.getIdentityId();
lambdaUpdate()
.eq(SaasRoleUserRelation::getIdentityType, req.getIdentityType().getCode())
.in(SaasRoleUserRelation::getRoleId,req.getRoleId())
.eq(SaasRoleUserRelation::getOuId, req.getOuId())
.in(CollectionUtil.isNotEmpty(identityId), SaasRoleUserRelation::getIdentityId, identityId)
.eq(SaasRoleUserRelation::getWorkspaceId, req.getWorkspaceId())
.eq(SaasRoleUserRelation::getResourceType, req.getResourceType())
.eq(SaasRoleUserRelation::getResourceId, req.getResourceId())
.setSql(" is_delete = id").update();
}
public Page<SaasRoleUserRelation> batListCleanRelation(SaasRoleUserRelation cleanParam, IPage<SaasRoleUserRelation> page) {
return this.baseMapper.batListCleanRelation(page, cleanParam);
}
public void cleanTargetRelation(UserRoleRelationCleanJob.CleanTarget target) {
this.remove(new LambdaQueryWrapper<SaasRoleUserRelation>()
.eq(SaasRoleUserRelation::getOuId, target.getOuId())
.eq(SaasRoleUserRelation::getWorkspaceId, target.getWorkspaceId())
.eq(SaasRoleUserRelation::getIdentityId, target.getIdentityId())
.eq(SaasRoleUserRelation::getIdentityType, target.getIdentityType()));
}
}

View File

@ -1,6 +1,7 @@
package cn.axzo.tyr.server.repository.entity;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
@ -8,6 +9,11 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* <p>
@ -166,4 +172,13 @@ public class SaasFeature extends BaseEntity<SaasFeature> implements Serializable
private Integer delegatedType;
public Set<Long> splitPath() {
if (StrUtil.isBlank(this.path)) {
return Collections.emptySet();
}
return StrUtil.split(this.path, "/").stream()
.filter(x -> StrUtil.isNotBlank(x) && !StrUtil.equals(x, "0"))
.map(Long::valueOf)
.collect(Collectors.toSet());
}
}

View File

@ -47,6 +47,11 @@ public class SaasRole extends BaseEntity<SaasRole> {
private Long ownerOuId;
/**
* 产品单位类型
* 1:总包 2:建设单位 3:监理单位 4:劳务分包 5:专业分包 6:OMS通用 7:企业通用 8:企业内班组 9:项目内班组
*/
private Integer productUnitType;
/**
* 创建者

View File

@ -59,6 +59,17 @@ public class SaasRoleGroup extends BaseEntity<SaasRoleGroup> implements Serializ
@TableField("sort")
private Integer sort;
/**
* 分组CODE
*/
private String code;
/**
* 分类CODE, 用于代班长小组长的权限分类
*/
private String categoryCode;
/**
* 获取主键值
*

View File

@ -57,4 +57,7 @@ public class SaasRoleWithUser {
* relation 工作台Id
*/
private Long relationWorkspaceId;
private Integer productUnitType;
}

View File

@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Set;
@ -23,5 +24,8 @@ public interface SaasRoleMapper extends BaseMapper<SaasRole> {
Page<SaasRole> pageQueryForOUWorkspace(IPage<SaasRole> page, Long ouId, Long workspaceId, Integer workspaceJoinType);
List<SaasRole> listForOUWorkspace(Long ouId, Long workspaceId, Integer workspaceJoinType);
List<SaasRole> listRoleByFeatures(@Param("featureIds") Set<Long> featureIds);
}

View File

@ -1,12 +1,15 @@
package cn.axzo.tyr.server.repository.mapper;
import cn.axzo.tyr.server.repository.entity.SaasRole;
import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface SaasRoleUserRelationMapper extends BaseMapper<SaasRoleUserRelation> {
Page<SaasRoleUserRelation> batListCleanRelation(IPage<SaasRoleUserRelation> page, @Param("param") SaasRoleUserRelation cleanParam);
}

View File

@ -1,5 +1,8 @@
package cn.axzo.tyr.server.repository.mapper;
import cn.axzo.tyr.client.model.req.ListPermissionFromRoleGroupReq;
import cn.axzo.tyr.client.model.res.ListIdentityFromPermissionResp;
import cn.axzo.tyr.client.model.res.ListPermissionFromRoleGroupResp;
import cn.axzo.tyr.server.repository.entity.ProductFeatureInfo;
import cn.axzo.tyr.server.repository.entity.ProductFeatureQuery;
import cn.axzo.tyr.server.repository.entity.RolePermission;
@ -21,4 +24,5 @@ public interface TyrSaasAuthMapper {
List<ProductFeatureInfo> listProductFeature(@Param("query") ProductFeatureQuery query);
List<ListPermissionFromRoleGroupResp> listAuthByResourceAndRoleGroup(@Param("req") ListPermissionFromRoleGroupReq query);
}

View File

@ -0,0 +1,26 @@
package cn.axzo.tyr.server.service;
import cn.axzo.tyr.client.model.res.IdentityAuthRes;
import cn.axzo.tyr.server.model.PermissionCacheKey;
/**
* 授权缓存服务
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/1/3 17:21
*/
public interface PermissionCacheService {
/** 缓存开关 **/
boolean cacheDisable(PermissionCacheKey key);
/** 从缓存获取权限 **/
IdentityAuthRes.WorkspacePermission getPermissionFromCache(PermissionCacheKey key);
/** 缓存权限 **/
void cachePermission(PermissionCacheKey key, IdentityAuthRes.WorkspacePermission permission);
/** 标记缓存暂时不可用 - 等缓存全部失效 **/
void markTempDisable(PermissionCacheKey key);
}

View File

@ -6,6 +6,8 @@ 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.QueryPermissionByIdsReq;
import cn.axzo.tyr.client.model.res.SimplePermissionPointResp;
import cn.axzo.tyr.server.repository.entity.SaasFeature;
import java.util.List;
@ -56,6 +58,8 @@ public interface PermissionPointService {
/** 根据code查询权限点, terminal可为空 **/
List<SaasFeature> listNodeWithChildrenByCode(String featureCode, String terminal);
List<SaasFeature> listNodeWithChildrenByCodes(List<String> featureCodes, String terminal);
/**
* 根据CODE查询详情
* @param code
@ -68,4 +72,7 @@ public interface PermissionPointService {
* @return
*/
List<PermissionPointDTO> getChildByParentId(Long parentId);
/** 根据ID查询权限点 **/
List<SimplePermissionPointResp> listPermissionByIds(QueryPermissionByIdsReq req);
}

View File

@ -35,4 +35,6 @@ public interface ProductFeatureRelationService {
/** 数据清洗 **/
boolean refreshFeature(Integer workspaceType, Long productId);
void removeByProductId(Long productId);
}

View File

@ -8,6 +8,8 @@ import cn.axzo.tyr.client.model.res.QueryBatchByIdentityIdTypeRes;
import cn.axzo.tyr.client.model.res.QueryRoleByNameResp;
import cn.axzo.tyr.client.model.res.RoleWithUserRes;
import cn.axzo.tyr.client.model.vo.SaasRoleAndGroupVO;
import cn.axzo.tyr.client.model.vo.SaasRoleCategoryVO;
import cn.axzo.tyr.client.model.vo.SaasRoleGroupCodeVO;
import cn.axzo.tyr.client.model.vo.SaasRoleVO;
import cn.axzo.tyr.client.model.vo.SaveOrUpdateRoleVO;
import cn.axzo.tyr.server.repository.entity.SaasRole;
@ -54,7 +56,7 @@ public interface RoleService {
* @param userRoleInfoMap
* @return 按钮级别权限点ID
*/
Set<Long> filterPermissionPoint(Set<SaasRoleVO> role, TyrSaasAuthServiceImpl.UserRoleInfoMap userRoleInfoMap);
Set<Long> filterPermissionPoint(Set<SaasRoleVO> role, TyrSaasAuthServiceImpl.OUWRoleInfo userRoleInfoMap);
/**
* 通过角色名字获取角色信息
@ -86,4 +88,17 @@ public interface RoleService {
* @param outId 待删除角色所属单位ID
*/
void deleteRole(List<Long> roleIds,Long workSpaceId,Long outId);
List<SaasRole> queryRoleByFeatures(Set<Long> matchedFeatureIds);
List<SaasRole> getByIds(Set<Long> ids);
List<SaasRoleCategoryVO> queryByCategoryCode(List<String> categoryCodes);
List<SaasRoleGroupCodeVO> queryByCodes(List<String> codes);
void changeGroupLeaderRole(List<ChangeGroupLeaderRoleReq> reqs);
/** 查询超管和管理员角色 **/
List<SaasRole> listAdmins(Long workspaceId, Long ouId);
}

View File

@ -3,6 +3,9 @@ package cn.axzo.tyr.server.service;
import cn.axzo.tyr.client.model.req.FeaturePermissionReq;
import cn.axzo.tyr.client.model.res.FeaturePermissionRes;
import java.util.Collection;
import java.util.List;
/**
* @author honghao.zhang
* @since 2023/10/18 18:25
@ -10,4 +13,12 @@ import cn.axzo.tyr.client.model.res.FeaturePermissionRes;
public interface SaasFeatureService {
FeaturePermissionRes listPermissionCodes(FeaturePermissionReq req);
/**
* 通过 {@code appItemId} 获取 {@code featureId}
*
* @param appItemIds 应用子级条目id集合
* @return {@code featureId} 列表
*/
List<Long> listAppFeatureIds(Collection<Long> appItemIds);
}

View File

@ -25,4 +25,11 @@ public interface SaasRoleGroupService {
Long saveOrUpdate(SaasRoleGroupVO req);
void delete(List<Long> ids);
/**
* 分组CODE查询角色分组
* @param categoryCode
* @return
*/
List<SaasRoleGroupVO> listByCategoryCode(List<String> categoryCode);
}

View File

@ -42,7 +42,7 @@ public interface SaasRoleUserService {
* @param ouIds
* @return
*/
List<SaasRoleUserRelation> queryByWorkspaceIdOrOu(Long identityId, IdentityType identityType, Set<Long> workspaceIds, Set<Long> ouIds);
List<SaasRoleUserRelation> queryByWorkspaceIdOrOu(Long personId, Long identityId, IdentityType identityType, Set<Long> workspaceIds, Set<Long> ouIds);
/**
* workpaceId + ownerOuId + roleId + 手机号 + 姓名 赋予角色支持角色赋予的同时 角色创建
@ -71,4 +71,17 @@ public interface SaasRoleUserService {
* 删除单位参与的工作台的所有的人员与角色 目前主要是用于移除参与单位的地方
*/
void removeWorkspaceOuAllUserRole(Long workspaceId, Long ouId);
/**
* 授权或者取消授权平台班组长和项目内班组长角色
*/
void grantOrUngrantWorkerLeader(GantOrUnGantaWorkerLeaderRoleReq req);
/**
* 授权或者取消授权班组管理员项目代班长
* @param req
*/
void grantOrUngrantWorkerManager(WorkerManagerRoleUserReq req);
}

View File

@ -1,13 +1,17 @@
package cn.axzo.tyr.server.service;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.req.CheckIdentityPermissionReq;
import cn.axzo.tyr.client.model.req.IdentityAuthReq;
import cn.axzo.tyr.client.model.req.BatchListIdentityFromPermissionReq;
import cn.axzo.tyr.client.model.req.ListIdentityFromPermissionReq;
import cn.axzo.tyr.client.model.req.ListPermissionFromFeatureReq;
import cn.axzo.tyr.client.model.req.ListPermissionFromIdentityReq;
import cn.axzo.tyr.client.model.req.ListPermissionFromRoleGroupReq;
import cn.axzo.tyr.client.model.req.WorkspacePermissionIdentityReq;
import cn.axzo.tyr.client.model.res.IdentityAuthRes;
import cn.axzo.tyr.client.model.res.ListIdentityFromPermissionResp;
import cn.axzo.tyr.client.model.res.ListPermissionFromRoleGroupResp;
import cn.axzo.tyr.client.model.res.QueryIdentityByPermissionResp;
import java.util.List;
@ -27,16 +31,24 @@ public interface TyrSaasAuthService {
//------------------上面权限接口为2023/10月未上线前提供的接口在此日期之后的接口统一使用下面的接口---------------------------
/**
* 查询指定人的权限
* @param identityAuthReq
* @return
*/
IdentityAuthRes findIdentityAuth(IdentityAuthReq identityAuthReq);
boolean hasPermissionForIdentityV2(CheckIdentityPermissionReq req);
ListIdentityFromPermissionResp listIdentityFromPermission(ListIdentityFromPermissionReq req);
List<ListIdentityFromPermissionResp> batchListIdentityFromPermission(List<ListIdentityFromPermissionReq> req);
/**
* 查询指定人的权限
* @param identityAuthReq
* @return
*/
IdentityAuthRes findIdentityAuthMix(IdentityAuthReq identityAuthReq);
List<ListIdentityFromPermissionResp> listWorkspacePermissionIdentity(WorkspacePermissionIdentityReq req);
/**
* 通过资源信息获取权限
* @param listPermissionFromRoleGroupReq
* @return
*/
List<ListPermissionFromRoleGroupResp> listAuthByResourceAndRoleGroup(ListPermissionFromRoleGroupReq listPermissionFromRoleGroupReq);
}

View File

@ -0,0 +1,98 @@
package cn.axzo.tyr.server.service.impl;
import cn.axzo.pokonyan.config.redis.RedisUtil;
import cn.axzo.tyr.client.model.res.IdentityAuthRes;
import cn.axzo.tyr.server.model.PermissionCacheKey;
import cn.axzo.tyr.server.service.PermissionCacheService;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* 授权缓存服务实现
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/1/3 17:22
*/
@Slf4j
@Service
@RefreshScope
public class PermissionCacheServiceImpl implements PermissionCacheService {
/** 缓存权限信息开关 **/
@Value("${axzo.cache.auth.enable:true}")
private boolean enable = true;
/** 授权缓存过期时间 **/
@Value("${axzo.cache.auth.expire:30}")
private Long expireInMinutes;
@Override
public boolean cacheDisable(PermissionCacheKey key) {
//缓存开关关闭 或者 标记为临时不可用
return !enable || tempDisable(key);
}
private boolean tempDisable(PermissionCacheKey key) {
//服务包关联产品变化 - 产品下权限点变化 - 角色配置的权限变化 - 用户角色变化 - 权限点类型变化
String allDisable = RedisUtil.StringValueOps.get(PermissionCacheKey.buildAllDisableKey());
if (StrUtil.isNotBlank(allDisable)) {
return true;
}
if (Objects.nonNull(key.getPersonId())) {
String personDisable = RedisUtil.StringValueOps.get(key.buildPersonDisableKey());
return StrUtil.isNotBlank(personDisable);
}
if (Objects.nonNull(key.getIdentityId()) && Objects.nonNull(key.getIdentityType())) {
String identityDisable = RedisUtil.StringValueOps.get(key.buildIdentityDisableKey());
return StrUtil.isNotBlank(identityDisable);
}
return false;
}
@Override
public IdentityAuthRes.WorkspacePermission getPermissionFromCache(PermissionCacheKey key) {
String permission = RedisUtil.StringValueOps.get(key.buildAuthKey());
return permission == null ? null : JSONObject.parseObject(permission,
IdentityAuthRes.WorkspacePermission.class);
}
@Override
public void cachePermission(PermissionCacheKey key, IdentityAuthRes.WorkspacePermission permission) {
RedisUtil.StringValueOps.setEx(key.buildAuthKey(),
JSONObject.toJSONString(permission, SerializerFeature.DisableCircularReferenceDetect),
expireInMinutes, TimeUnit.MINUTES);
}
@Override
public void markTempDisable(PermissionCacheKey key) {
try {
if (BooleanUtil.isTrue(key.getDisableAll())) {
RedisUtil.StringValueOps.setEx(PermissionCacheKey.buildAllDisableKey(), "1", expireInMinutes, TimeUnit.MINUTES);
return;
}
if (Objects.nonNull(key.getPersonId())) {
RedisUtil.StringValueOps.setEx(key.buildPersonDisableKey(), "1", expireInMinutes, TimeUnit.MINUTES);
}
if (Objects.nonNull(key.getIdentityId()) && Objects.nonNull(key.getIdentityType())) {
RedisUtil.StringValueOps.setEx(key.buildIdentityDisableKey(), "1", expireInMinutes, TimeUnit.MINUTES);
}
} catch (Exception ex) {
log.error("mark permission refresh error", ex);
}
}
}

View File

@ -9,6 +9,9 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import cn.axzo.tyr.client.model.enums.FeatureDataType;
import cn.axzo.tyr.client.model.req.QueryPermissionByIdsReq;
import cn.axzo.tyr.client.model.res.SimplePermissionPointResp;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.lang.Opt;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -20,10 +23,6 @@ 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.framework.domain.web.result.ApiResult;
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.model.dict.request.BasicDictNodeReq;
import cn.axzo.tyr.client.model.dict.request.BasicDictQueryReq;
import cn.axzo.tyr.client.model.dict.response.BasicDictNodeResp;
@ -32,31 +31,18 @@ import cn.axzo.tyr.client.model.enums.DictTypeFiledEnum;
import cn.axzo.tyr.client.model.enums.DictWorkSpaceTypeEnum;
import cn.axzo.tyr.client.model.enums.FeatureType;
import cn.axzo.tyr.client.model.permission.*;
import cn.axzo.tyr.client.model.product.ProductFeatureRelationVO;
import cn.axzo.tyr.server.common.util.Throws;
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.service.PermissionPointService;
import cn.axzo.tyr.server.service.ProductFeatureRelationService;
import cn.axzo.tyr.server.service.SaasBasicDictService;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
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.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
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.*;
import static cn.axzo.tyr.server.util.RpcInternalUtil.checkAndGetData;
/**
@ -565,8 +551,13 @@ public class PermissionPointServiceImpl implements PermissionPointService {
@Override
public List<SaasFeature> listNodeWithChildrenByCode(String featureCode, String terminal) {
return listNodeWithChildrenByCodes(Collections.singletonList(featureCode), terminal);
}
@Override
public List<SaasFeature> listNodeWithChildrenByCodes(List<String> featureCodes, String terminal) {
List<SaasFeature> currentFeatrureList = saasFeatureDao.list(new LambdaQueryWrapper<SaasFeature>()
.eq(SaasFeature::getFeatureCode, featureCode)
.in(SaasFeature::getFeatureCode, featureCodes)
.eq(StrUtil.isNotBlank(terminal), SaasFeature::getTerminal, terminal));
//button过滤-如果全是按钮则不查子级
Set<String> pathsWithoutButton = currentFeatrureList.stream()
@ -600,4 +591,56 @@ public class PermissionPointServiceImpl implements PermissionPointService {
List<SaasFeature> feature = saasFeatureDao.getChildByParentId(parentId);
return BeanMapper.copyList(feature, PermissionPointDTO.class);
}
@Override
public List<SimplePermissionPointResp> listPermissionByIds(QueryPermissionByIdsReq req) {
//查所有节点 - 按需过滤
List<SimplePermissionPointResp> result = new ArrayList<>();
List<SaasFeature> allPermissions = saasFeatureDao.list(new LambdaQueryWrapper<SaasFeature>()
.select(SaasFeature::getId,
SaasFeature::getFeatureCode,
SaasFeature::getFeatureName,
SaasFeature::getParentId,
SaasFeature::getPath,
SaasFeature::getTerminal));
Set<Long> parentIds = new HashSet<>();
for (SaasFeature permission : allPermissions) {
if (req.getIds().contains(permission.getId())) {
//匹配查询的节点ID
result.add(toSimplePermission(permission));
if (req.isIncludeParent()) {
//通过path汇总parent
parentIds.addAll(permission.splitPath());
}
} else if (req.isIncludeChildren()) {
//path匹配查询节点ID - 子节点
boolean isChildren = permission.splitPath().stream().anyMatch(id -> req.getIds().contains(id));
if (isChildren) {
result.add(toSimplePermission(permission));
}
}
}
if (!parentIds.isEmpty()) {
//加入所有父级节点
result.addAll(allPermissions.stream()
.filter(p -> parentIds.contains(p.getId()))
.map(this::toSimplePermission)
.collect(Collectors.toList()));
}
return result;
}
private SimplePermissionPointResp toSimplePermission(SaasFeature permission) {
return SimplePermissionPointResp.builder()
.id(permission.getId())
.code(permission.getFeatureCode())
.name(permission.getFeatureName())
.parentId(permission.getParentId())
.terminal(permission.getTerminal())
.build();
}
}

View File

@ -1,6 +1,7 @@
package cn.axzo.tyr.server.service.impl;
import cn.axzo.basics.common.BeanMapper;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.thrones.client.saas.ServicePkgClient;
@ -10,6 +11,7 @@ import cn.axzo.tyr.client.model.permission.PermissionPointTreeNode;
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.server.repository.dao.ProductModuleDao;
import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
import cn.axzo.tyr.server.repository.entity.ProductFeatureQuery;
import cn.axzo.tyr.server.repository.entity.SaasFeature;
@ -31,6 +33,8 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -59,6 +63,7 @@ public class ProductFeatureRelationServiceImpl implements ProductFeatureRelation
private final SaasProductModuleFeatureRelationDao saasProductModuleFeatureRelationDao;
private final ServicePkgClient servicePkgClient;
private final SaasFeatureDao saasFeatureDao;
private final ProductModuleDao productModuleDao;
@Override
public ApiResult<List<ProductFeatureRelationVO>> featureList(ProductFeatureRelationSearchReq req) {
@ -93,6 +98,9 @@ public class ProductFeatureRelationServiceImpl implements ProductFeatureRelation
@Override
public ApiResult<List<ProductFeatureRelationVO>> featureListByProduct(List<Long> productIds) {
if (CollectionUtil.isEmpty(productIds)) {
return ApiResult.ok(Collections.emptyList());
}
List<SaasProductModuleFeatureRelation> list = saasProductModuleFeatureRelationDao.lambdaQuery()
.select(SaasProductModuleFeatureRelation::getFeatureId
,SaasProductModuleFeatureRelation::getProductModuleId
@ -109,24 +117,35 @@ public class ProductFeatureRelationServiceImpl implements ProductFeatureRelation
StopWatch stopWatch = StopWatch.create(" get product by workspace");
if (CollectionUtil.isEmpty(workspaceId)) {
return new HashMap<>();
return Collections.emptyMap();
}
stopWatch.start(" get service pkg by work space id");
List<ServicePkgDetailRes> servicePkgDetailRes = checkAndGetData(servicePkgClient.getServicePkgDetailBySpaceId(workspaceId));
if (CollectionUtil.isEmpty(servicePkgDetailRes)) {
return new HashMap<>();
return Collections.emptyMap();
}
stopWatch.stop();
stopWatch.start("get feature list by product");
List<Long> productIds = servicePkgDetailRes.stream().map(ServicePkgDetailRes::getProducts).flatMap(List::stream).map(ServicePkgProduct::getProductId).distinct().collect(Collectors.toList());
long l = System.currentTimeMillis();
List<Long> productIds = servicePkgDetailRes.stream()
.map(ServicePkgDetailRes::getProducts)
.filter(CollectionUtil::isNotEmpty)
.flatMap(List::stream)
.map(ServicePkgProduct::getProductId)
.distinct().collect(Collectors.toList());
if (CollectionUtil.isEmpty(productIds)) {
log.warn("no product found for workspace :{}", workspaceId);
return Collections.emptyMap();
}
// 已被删除产品过滤一层
productIds = productModuleDao.listByIds(productIds).stream().filter(productModule -> Objects.equals(productModule.getIsDelete(),0L)).map(BaseEntity::getId).distinct().collect(Collectors.toList());
ApiResult<List<ProductFeatureRelationVO>> listProductFeatureRelation = featureListByProduct(productIds);
if (listProductFeatureRelation.isError() || CollectionUtil.isEmpty(listProductFeatureRelation.getData())) {
log.warn("获取产品对应菜单失败producIds :{} result:{}", productIds, listProductFeatureRelation);
return new HashMap<>();
log.warn("no product features found for productIds :{} result:{}", productIds, listProductFeatureRelation);
return Collections.emptyMap();
}
System.out.println("System.currentTimeMillis() - l = " + (System.currentTimeMillis() - l));
// KEY=product id
Map<Long, List<ProductFeatureRelationVO>> cache = listProductFeatureRelation.getData()
.stream()
@ -210,4 +229,8 @@ public class ProductFeatureRelationServiceImpl implements ProductFeatureRelation
}
@Override
public void removeByProductId(Long productId) {
saasProductModuleFeatureRelationDao.removeByProductId(Collections.singletonList(productId));
}
}

View File

@ -12,6 +12,7 @@ import cn.axzo.tyr.client.model.product.ProductUpdateReq;
import cn.axzo.tyr.client.model.product.ProductVO;
import cn.axzo.tyr.server.repository.entity.ProductModule;
import cn.axzo.tyr.server.repository.dao.ProductModuleDao;
import cn.axzo.tyr.server.service.ProductFeatureRelationService;
import cn.axzo.tyr.server.service.ProductService;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
@ -38,6 +39,7 @@ import java.util.stream.Collectors;
@Service
public class ProductServiceImpl implements ProductService {
private final ProductModuleDao productModuleDao;
private final ProductFeatureRelationService productFeatureRelationService;
@Override
public ApiResult<List<ProductVO>> list(ProductSearchListReq req) {
@ -130,6 +132,9 @@ public class ProductServiceImpl implements ProductService {
.eq(ProductModule::getId, id)
.set(ProductModule::getIsDelete, id)
.update();
// 删除产品与权限点对应关系
productFeatureRelationService.removeByProductId(id);
return ApiResult.ok(BeanMapper.copyBean(productModule, ProductVO.class));
}
}

View File

@ -4,45 +4,81 @@ import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum;
import cn.axzo.basics.common.exception.ServiceException;
import cn.axzo.framework.domain.page.PageResp;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.tyr.client.common.enums.RoleResourceTypeEnum;
import cn.axzo.tyr.client.common.enums.RoleTypeEnum;
import cn.axzo.tyr.client.model.BaseWorkspaceModel;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.enums.PermissionGroupType;
import cn.axzo.tyr.client.model.permission.PermissionPointTreeNode;
import cn.axzo.tyr.client.model.req.*;
import cn.axzo.tyr.client.model.req.ChangeGroupLeaderRoleReq;
import cn.axzo.tyr.client.model.req.QueryByIdentityIdTypeReq;
import cn.axzo.tyr.client.model.req.QueryRoleByNameReq;
import cn.axzo.tyr.client.model.req.QuerySaasPermissionGroupReq;
import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq;
import cn.axzo.tyr.client.model.req.QuerySaasRoleReq;
import cn.axzo.tyr.client.model.req.RoleWithUserQueryReq;
import cn.axzo.tyr.client.model.res.IsSuperAdminRes;
import cn.axzo.tyr.client.model.res.QueryBatchByIdentityIdTypeRes;
import cn.axzo.tyr.client.model.res.QueryRoleByNameResp;
import cn.axzo.tyr.client.model.res.RoleWithUserRes;
import cn.axzo.tyr.client.model.vo.SaasPermissionGroupVO;
import cn.axzo.tyr.client.model.vo.SaasRoleAndGroupVO;
import cn.axzo.tyr.client.model.vo.SaasRoleCategoryVO;
import cn.axzo.tyr.client.model.vo.SaasRoleGroupCodeVO;
import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO;
import cn.axzo.tyr.client.model.vo.SaasRoleVO;
import cn.axzo.tyr.client.model.vo.SaveOrUpdateRoleVO;
import cn.axzo.tyr.server.repository.dao.*;
import cn.axzo.tyr.server.repository.entity.*;
import cn.axzo.tyr.server.service.*;
import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
import cn.axzo.tyr.server.repository.dao.SaasPermissionGroupDao;
import cn.axzo.tyr.server.repository.dao.SaasPgroupRoleRelationDao;
import cn.axzo.tyr.server.repository.dao.SaasRoleDao;
import cn.axzo.tyr.server.repository.dao.SaasRoleGroupDao;
import cn.axzo.tyr.server.repository.dao.SaasRoleGroupRelationDao;
import cn.axzo.tyr.server.repository.dao.SaasRoleUserRelationDao;
import cn.axzo.tyr.server.repository.entity.SaasFeature;
import cn.axzo.tyr.server.repository.entity.SaasPermissionGroup;
import cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation;
import cn.axzo.tyr.server.repository.entity.SaasPgroupRoleRelation;
import cn.axzo.tyr.server.repository.entity.SaasRole;
import cn.axzo.tyr.server.repository.entity.SaasRoleGroup;
import cn.axzo.tyr.server.repository.entity.SaasRoleGroupRelation;
import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation;
import cn.axzo.tyr.server.repository.entity.SaasRoleWithUser;
import cn.axzo.tyr.server.service.PermissionGroupService;
import cn.axzo.tyr.server.service.RoleService;
import cn.axzo.tyr.server.service.SaasPgroupPermissionRelationService;
import cn.axzo.tyr.server.service.SaasRoleGroupRelationService;
import cn.axzo.tyr.server.service.SaasRoleGroupService;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
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.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.function.Consumer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import static org.codehaus.groovy.runtime.DefaultGroovyMethods.collect;
import java.util.stream.Stream;
/**
* 角色
@ -53,6 +89,7 @@ import static org.codehaus.groovy.runtime.DefaultGroovyMethods.collect;
*/
@Slf4j
@RequiredArgsConstructor
@RefreshScope
@Service
public class RoleServiceImpl implements RoleService {
@ -81,18 +118,22 @@ public class RoleServiceImpl implements RoleService {
@Autowired
SaasRoleUserRelationDao saasRoleUserRelationDao;
@Autowired
RoleUserService roleUserService;
@Autowired
RoleUserService roleUserService;
@Autowired
SaasRoleGroupRelationDao saasRoleGroupRelationDao;
@Value("${groupLeader.code:projectTeamGPLeader}")
private String groupLeaderCode;
@Override
public List<SaasRoleVO> queryByIdentityIdType(Long identityId, Integer identityType, Long workspaceId, Long ouId, Boolean includePermissionGroup) {
// 查询人关联的角色id
List<Long> roleIds = roleUserRelationDao.query(identityId, identityType, workspaceId, ouId).stream().map(SaasRoleUserRelation::getRoleId).collect(Collectors.toList());
if (CollectionUtils.isEmpty(roleIds)) {
return new ArrayList<>();
}
return getByIds(roleIds, null, null,null, includePermissionGroup,null);
}
@Override
public List<SaasRoleVO> queryByIdentityIdType(Long identityId, Integer identityType, Long workspaceId, Long ouId, Boolean includePermissionGroup) {
// 查询人关联的角色id
List<Long> roleIds = roleUserRelationDao.query(identityId, identityType, workspaceId, ouId).stream().map(SaasRoleUserRelation::getRoleId).collect(Collectors.toList());
if (CollectionUtils.isEmpty(roleIds)) {
return new ArrayList<>();
}
return getByIds(roleIds, null, null, null, includePermissionGroup, null);
}
/**
* 根据id查询权限详情包含权限组合权限集(底层基础方法)
@ -100,20 +141,20 @@ public class RoleServiceImpl implements RoleService {
* @return
*/
@Override
public List<SaasRoleVO> getByIds(List<Long> roleIds, Integer isCommon, List<Long> workspaceId, List<Long> ouId, Boolean includePermissionGroup,Boolean includeSpecialRole) {
if (CollectionUtils.isEmpty(roleIds)) {
return new ArrayList<>();
}
if (includePermissionGroup == null) {
includePermissionGroup = false;
}
if (includeSpecialRole == null) {
includeSpecialRole = true;
}
if (!includeSpecialRole) {
List<Long> specialRole = roleUserService.getSpecialRole();
roleIds = roleIds.stream().filter(e -> !specialRole.contains(e)).collect(Collectors.toList());
}
public List<SaasRoleVO> getByIds(List<Long> roleIds, Integer isCommon, List<Long> workspaceId, List<Long> ouId, Boolean includePermissionGroup, Boolean includeSpecialRole) {
if (CollectionUtils.isEmpty(roleIds)) {
return new ArrayList<>();
}
if (includePermissionGroup == null) {
includePermissionGroup = false;
}
if (includeSpecialRole == null) {
includeSpecialRole = true;
}
if (!includeSpecialRole) {
List<Long> specialRole = roleUserService.getSpecialRole();
roleIds = roleIds.stream().filter(e -> !specialRole.contains(e)).collect(Collectors.toList());
}
// 查询角色信息
List<SaasRole> roles = saasRoleDao.lambdaQuery().in(BaseEntity::getId, roleIds).list();
// 查询权限集
@ -195,30 +236,47 @@ public class RoleServiceImpl implements RoleService {
if (CollectionUtils.isEmpty(groupRelation)) {
return new ArrayList<>();
}
}
// 查询角色
List<SaasRole> list = saasRoleDao.lambdaQuery()
.in(CollectionUtils.isNotEmpty(req.getIds()), BaseEntity::getId, req.getIds())
.in(CollectionUtils.isNotEmpty(groupRelation), BaseEntity::getId, groupRelation.stream().map(SaasRoleGroupRelation::getRoleId).collect(Collectors.toList()))
.in(CollectionUtils.isNotEmpty(req.getRoleType()), SaasRole::getRoleType, req.getRoleType())
.in(CollectionUtils.isEmpty(req.getIds()) && CollectionUtils.isNotEmpty(req.getWorkspaceId()),SaasRole::getWorkspaceId,req.getWorkspaceId())
.in(CollectionUtils.isEmpty(req.getIds()) && CollectionUtils.isNotEmpty(req.getOuId()),SaasRole::getOwnerOuId,req.getOuId())
.orderByDesc(BaseEntity::getId)
.list();
return getByIds(list.stream().map(BaseEntity::getId).collect(Collectors.toList()), req.getIsCommon(),req.getWorkspaceId(),req.getOuId(),req.getIncludePermissionGroup(),req.getIncludeSpecialRole());
}
}
// 查询角色
List<SaasRole> list = saasRoleDao.lambdaQuery()
.in(CollectionUtils.isNotEmpty(req.getIds()), BaseEntity::getId, req.getIds())
.in(CollectionUtils.isNotEmpty(groupRelation), BaseEntity::getId, groupRelation.stream().map(SaasRoleGroupRelation::getRoleId).collect(Collectors.toList()))
.in(CollectionUtils.isNotEmpty(req.getRoleType()), SaasRole::getRoleType, req.getRoleType())
.in(CollectionUtils.isEmpty(req.getIds()) && CollectionUtils.isNotEmpty(req.getWorkspaceId()), SaasRole::getWorkspaceId, req.getWorkspaceId())
.in(CollectionUtils.isEmpty(req.getIds()) && CollectionUtils.isNotEmpty(req.getOuId()), SaasRole::getOwnerOuId, req.getOuId())
.orderByDesc(BaseEntity::getId)
.list();
return getByIds(list.stream().map(BaseEntity::getId).collect(Collectors.toList()), req.getIsCommon(), req.getWorkspaceId(), req.getOuId(), req.getIncludePermissionGroup(), req.getIncludeSpecialRole());
}
@Override
public List<QueryBatchByIdentityIdTypeRes> queryBatchByIdentityIdType(List<QueryByIdentityIdTypeReq> req) {
List<QueryBatchByIdentityIdTypeRes> result = new ArrayList<>();
req.stream().distinct().forEach(e -> {
result.add(QueryBatchByIdentityIdTypeRes.builder()
.identityId(e.getIdentityId())
.identityType(e.getIdentityType())
.workspaceId(e.getWorkspaceId())
.ouId(e.getOuId())
.role(queryByIdentityIdType(e.getIdentityId(), e.getIdentityType(), e.getWorkspaceId(), e.getOuId(), false))
.build());
if (e.getPersonId() != null) {
List<Long> roleIds = roleUserRelationDao.queryByPersonId(e.getPersonId(), e.getWorkspaceId(), e.getOuId())
.stream()
.map(SaasRoleUserRelation::getRoleId)
.collect(Collectors.toList());
List<SaasRoleVO> saasRoles = getByIds(roleIds, null, null, null, false, null);
result.add(QueryBatchByIdentityIdTypeRes.builder()
.identityId(e.getIdentityId())
.identityType(e.getIdentityType())
.workspaceId(e.getWorkspaceId())
.ouId(e.getOuId())
.personId(e.getPersonId())
.role(saasRoles)
.build());
} else {
result.add(QueryBatchByIdentityIdTypeRes.builder()
.identityId(e.getIdentityId())
.identityType(e.getIdentityType())
.workspaceId(e.getWorkspaceId())
.ouId(e.getOuId())
.role(queryByIdentityIdType(e.getIdentityId(), e.getIdentityType(), e.getWorkspaceId(), e.getOuId(), false))
.build());
}
});
return result;
}
@ -376,6 +434,7 @@ public class RoleServiceImpl implements RoleService {
saasRole.setWorkspaceId(saveOrUpdateRole.getWorkspaceId());
saasRole.setOwnerOuId(saveOrUpdateRole.getOwnerOuId());
saasRole.setWorkspaceType(Integer.parseInt(saveOrUpdateRole.getGroupTree().get(0).getWorkspaceTypeCode()));
saasRole.setProductUnitType(setProductUnitType(saveOrUpdateRole.getGroupTree().get(0)));
saasRole.setUpdateBy(saveOrUpdateRole.getOperatorId());
saasRole.setUpdateAt(now);
String message = "角色校验异常";
@ -429,6 +488,16 @@ public class RoleServiceImpl implements RoleService {
return saasRole;
}
/**
* 产品单位类型
*/
private Integer setProductUnitType(SaveOrUpdateRoleVO.GroupInfoVO groupInfoVO) {
SaasRoleGroup saasRoleGroup = saasRoleGroupDao.lambdaQuery()
.in(SaasRoleGroup::getId, groupInfoVO.getId())
.eq(SaasRoleGroup::getIsDelete, TableIsDeleteEnum.NORMAL.value).one();
return Integer.parseInt(saasRoleGroup.getOuTypeCode());
}
private void validFeature(List<Long> featureIds) {
if (CollectionUtils.isEmpty(featureIds)) {
return;
@ -507,7 +576,7 @@ public class RoleServiceImpl implements RoleService {
}
@Override
public Set<Long> filterPermissionPoint(Set<SaasRoleVO> role, TyrSaasAuthServiceImpl.UserRoleInfoMap userRoleInfoMap) {
public Set<Long> filterPermissionPoint(Set<SaasRoleVO> role, TyrSaasAuthServiceImpl.OUWRoleInfo userRoleInfoMap) {
// 按钮级别权限点ID
Set<Long> result = new HashSet<>();
if (CollectionUtils.isEmpty(role)) {
@ -518,7 +587,7 @@ public class RoleServiceImpl implements RoleService {
if (role.stream().anyMatch(r -> Objects.equals(RoleTypeEnum.INIT.getValue(), r.getRoleType()))) {
List<SaasRoleGroupVO> roleGroupList = saasRoleGroupService.getList(QuerySaasRoleGroupReq.builder()
.workspaceTypeCode(Collections.singletonList(userRoleInfoMap.getWorkspaceType().toString()))
.ouTypeCode(Collections.singletonList(userRoleInfoMap.getWorkspaceJoinType().getValue().toString()))
// .ouTypeCode(Collections.singletonList(userRoleInfoMap.getWorkspaceJoinType().getValue().toString()))
.build());
initRoleId = roleGroupList.stream().map(SaasRoleGroupVO::getRoleIds).filter(CollectionUtil::isNotEmpty).flatMap(List::stream).collect(Collectors.toSet());
}
@ -695,7 +764,215 @@ public class RoleServiceImpl implements RoleService {
throw new cn.axzo.basics.common.exception.ServiceException("当前角色已被用户使用,无法删除!");
}
saasRoleDao.delete(roleIds);
roleUserRelationDao.deleteByRoldId(roleIds);
roleUserRelationDao.deleteByRoleId(roleIds);
roleGroupRelationDao.deleteGroupRelation(roleIds);
}
@Override
public List<SaasRole> queryRoleByFeatures(Set<Long> matchedFeatureIds) {
return saasRoleDao.getBaseMapper().listRoleByFeatures(matchedFeatureIds);
}
@Override
public List<SaasRole> getByIds(Set<Long> ids) {
return saasRoleDao.listByIds(ids);
}
@Override
public List<SaasRoleCategoryVO> queryByCategoryCode(List<String> categoryCodes) {
if (CollectionUtils.isEmpty(categoryCodes)) {
return new ArrayList<>();
}
List<SaasRoleCategoryVO> result = new ArrayList<>();
List<SaasRoleGroup> saasRoleGroups = saasRoleGroupDao.listByCategoryCode(categoryCodes);
Set<Long> roleGroupId = saasRoleGroups.stream().map(BaseEntity::getId).collect(Collectors.toSet());
List<SaasRoleGroupRelation> roleGroupRelations = saasRoleGroupRelationDao.getByGroupIds(roleGroupId);
Map<Long, List<SaasRoleGroupRelation>> groupByGroupId = roleGroupRelations.stream().collect(Collectors.groupingBy(SaasRoleGroupRelation::getSaasRoleGroupId));
Set<Long> roleIds = roleGroupRelations.stream().map(SaasRoleGroupRelation::getRoleId).collect(Collectors.toSet());
List<SaasPgroupRoleRelation> saasPgroupRoleRelations = saasPgroupRoleRelationDao.findByRoleIds(roleIds);
Map<Long, List<SaasPgroupRoleRelation>> rolePermissionMap = saasPgroupRoleRelations.stream().collect(Collectors.groupingBy(SaasPgroupRoleRelation::getRoleId));
List<Long> permissionIds = saasPgroupRoleRelations.stream().map(SaasPgroupRoleRelation::getGroupId).distinct().collect(Collectors.toList());
if (CollectionUtils.isEmpty(roleIds) || CollectionUtils.isEmpty(permissionIds)) {
return new ArrayList<>();
}
// 原数据
List<SaasRole> roleInfos = getByIds(roleIds);
List<SaasPermissionGroup> permissionGroups = saasPermissionGroupDao.listByIds(permissionIds);
Map<Long, SaasRole> roleMap = roleInfos.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));
Map<Long, SaasPermissionGroup> permissionGroupMap = permissionGroups.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));
Map<String, List<SaasRoleGroup>> groupsByCategory = saasRoleGroups.stream().collect(Collectors.groupingBy(SaasRoleGroup::getCategoryCode));
return groupsByCategory.entrySet().stream()
.map(entry -> {
SaasRoleCategoryVO saasRoleCategoryVO = new SaasRoleCategoryVO();
saasRoleCategoryVO.setCategoryCode(entry.getKey());
Map<String, List<SaasRoleGroup>> groupsByCode = entry.getValue().stream().collect(Collectors.groupingBy(SaasRoleGroup::getCode));
List<SaasRoleGroupCodeVO> saasRoleGroupCodeVOList = groupsByCode.entrySet().stream().map(g -> {
SaasRoleGroupCodeVO saasRoleGroupCodeVO = new SaasRoleGroupCodeVO();
saasRoleGroupCodeVO.setCode(g.getKey());
List<Long> groupIdList = g.getValue().stream().map(SaasRoleGroup::getId).collect(Collectors.toList());
List<SaasRoleGroupRelation> roleGroupRelationList = groupIdList.stream().map(groupByGroupId::get)
.flatMap((Function<List<SaasRoleGroupRelation>, Stream<SaasRoleGroupRelation>>) saasRoleGroupRelations -> saasRoleGroupRelations.stream().map(saasRoleGroupRelation -> saasRoleGroupRelation))
.collect(Collectors.toList());
List<Long> roleIdList = roleGroupRelationList.stream().map(SaasRoleGroupRelation::getRoleId).collect(Collectors.toList());
List<SaasRole> roleList = roleIdList.stream().map(roleMap::get).collect(Collectors.toList());
List<SaasRoleVO> saasRoleVOList = BeanUtil.copyToList(roleList, SaasRoleVO.class);
saasRoleVOList.forEach(e -> {
List<Long> permissionList = rolePermissionMap.get(e.getId()).stream().map(SaasPgroupRoleRelation::getGroupId).collect(Collectors.toList());
List<SaasPermissionGroup> saasPermissionGroupList = permissionList.stream().map(permissionGroupMap::get).collect(Collectors.toList());
e.setPermissionGroup(BeanUtil.copyToList(saasPermissionGroupList, SaasPermissionGroupVO.class));
});
saasRoleGroupCodeVO.setRoleInfos(saasRoleVOList);
return saasRoleGroupCodeVO;
}).collect(Collectors.toList());
saasRoleCategoryVO.setRoleGroupCodeVOList(saasRoleGroupCodeVOList);
return saasRoleCategoryVO;
})
.collect(Collectors.toList());
}
@Override
public List<SaasRoleGroupCodeVO> queryByCodes(List<String> codes) {
if (CollectionUtils.isEmpty(codes)) {
return new ArrayList<>();
}
List<SaasRoleGroup> saasRoleGroups = saasRoleGroupDao.listByCodes(codes);
if (CollUtil.isEmpty(saasRoleGroups)) {
return new ArrayList<>();
}
Set<Long> roleGroupId = saasRoleGroups.stream().map(BaseEntity::getId).collect(Collectors.toSet());
List<SaasRoleGroupRelation> roleGroupRelations = saasRoleGroupRelationDao.getByGroupIds(roleGroupId);
if (CollUtil.isEmpty(roleGroupRelations)) {
return new ArrayList<>();
}
Set<Long> roleIds = roleGroupRelations.stream().map(SaasRoleGroupRelation::getRoleId).collect(Collectors.toSet());
List<SaasRole> roles = saasRoleDao.findInitRole(roleIds);
Map<Long, String> groupMap = saasRoleGroups.stream().collect(Collectors.toMap(SaasRoleGroup::getId, SaasRoleGroup::getCode, (a, b) -> a));
Map<Long, List<SaasRoleGroupRelation>> relationMap = roleGroupRelations.stream().collect(Collectors.groupingBy(SaasRoleGroupRelation::getSaasRoleGroupId));
Map<Long, SaasRole> roleMap = roles.stream().collect(Collectors.toMap(SaasRole::getId, Function.identity(), (a, b) -> a));
List<SaasRoleGroupCodeVO> result = Lists.newArrayListWithCapacity(saasRoleGroups.size());
groupMap.forEach((key, value) -> {
SaasRoleGroupCodeVO vo = new SaasRoleGroupCodeVO();
vo.setCode(value);
List<SaasRoleGroupRelation> relations = relationMap.get(key);
if (CollUtil.isNotEmpty(relations)) {
List<Long> roleIdList = relations.stream().map(SaasRoleGroupRelation::getRoleId).collect(Collectors.toList());
List<SaasRole> roleList = roleIdList.stream().map(roleId -> roleMap.get(roleId)).collect(Collectors.toList());
List<SaasRoleVO> saasRoleVOS = BeanUtil.copyToList(roleList, SaasRoleVO.class);
vo.setRoleInfos(saasRoleVOS);
}
result.add(vo);
});
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void changeGroupLeaderRole(List<ChangeGroupLeaderRoleReq> reqs) {
List<SaasRoleGroupCodeVO> voList = queryByCodes(Lists.newArrayList(groupLeaderCode));
if (CollUtil.isEmpty(voList) || CollUtil.isEmpty(voList.get(0).getRoleInfos())) {
log.warn("can't find group_role_relation.code: {}", groupLeaderCode);
return;
}
List<Long> baseRoleIds = voList.get(0).getRoleInfos().stream().map(SaasRoleVO::getId).collect(Collectors.toList());
List<SaasRoleUserRelation> userRelationList = reqs.stream().map(req -> {
List<SaasRoleUserRelation> nowRelations = saasRoleUserRelationDao.findValidByNodeResource(req.getGroupLeaderPersonId(), req.getGroupNodeId(), null);
Map<Long, SaasRoleUserRelation> relationMap = nowRelations.stream().collect(Collectors.toMap(SaasRoleUserRelation::getRoleId, Function.identity(), (a, b) -> a));
List<Long> roleIdList = req.getRoleIdList();
if (CollUtil.isNotEmpty(roleIdList)) {
roleIdList = roleIdList.stream().filter(baseRoleIds::contains).collect(Collectors.toList());
if (CollUtil.isNotEmpty(nowRelations)) {
List<SaasRoleUserRelation> resList = Lists.newArrayList();
// 都不为空 既增又减
Set<Long> nowRoles = nowRelations.stream().map(SaasRoleUserRelation::getRoleId).collect(Collectors.toSet());
// nowRoles -A , newRoles - B
// A-B 减少的权限
Set<Long> newRoles = roleIdList.stream().filter(Objects::nonNull).collect(Collectors.toSet());
Set<Long> deductRoles = Sets.difference(nowRoles, newRoles);
if (CollUtil.isNotEmpty(deductRoles)) {
List<SaasRoleUserRelation> deductRelations = deductRoles.stream().map(relationMap::get).filter(Objects::nonNull).collect(Collectors.toList());
deductRelations.forEach(relation -> relation.setIsDelete(relation.getId()));
resList.addAll(deductRelations);
}
// B - A 增加的权限
Set<Long> addRoles = Sets.difference(newRoles, nowRoles);
if (CollUtil.isNotEmpty(addRoles)) {
List<SaasRoleUserRelation> addRelations = addRoles.stream().map(roleId -> {
SaasRoleUserRelation userRelation = new SaasRoleUserRelation();
userRelation.setIdentityId(req.getGroupLeaderIdentityId());
userRelation.setRoleId(roleId);
userRelation.setIdentityType(IdentityType.WORKER.getCode());
userRelation.setNaturalPersonId(req.getGroupLeaderPersonId());
userRelation.setWorkspaceId(req.getWorkspaceId());
userRelation.setOuId(req.getOuId());
userRelation.setResourceType(RoleResourceTypeEnum.NODE.code);
userRelation.setResourceId(req.getGroupNodeId());
return userRelation;
}).collect(Collectors.toList());
resList.addAll(addRelations);
}
return resList;
} else {
// nowRelations 为空 则只增不减
return roleIdList.stream().map(e -> {
SaasRoleUserRelation userRelation = new SaasRoleUserRelation();
userRelation.setIdentityId(req.getGroupLeaderIdentityId());
userRelation.setRoleId(e);
userRelation.setIdentityType(IdentityType.WORKER.getCode());
userRelation.setNaturalPersonId(req.getGroupLeaderPersonId());
userRelation.setWorkspaceId(req.getWorkspaceId());
userRelation.setOuId(req.getOuId());
userRelation.setResourceType(RoleResourceTypeEnum.NODE.code);
userRelation.setResourceId(req.getGroupNodeId());
return userRelation;
}).collect(Collectors.toList());
}
}
if (CollUtil.isNotEmpty(nowRelations)) {
// newRelations 为空 则只减不增
nowRelations.forEach(relation -> relation.setIsDelete(relation.getId()));
}
return nowRelations;
}).filter(CollUtil::isNotEmpty).flatMap(List<SaasRoleUserRelation>::stream).collect(Collectors.toList());
if (CollUtil.isEmpty(userRelationList)) {
return;
}
// 没有权限就把查到的权限全删了
// 已经有的就不再save了 业务唯一键personId+resourceId+roleId(+id?)
List<SaasRoleUserRelation> addList = userRelationList.stream().filter(e -> TableIsDeleteEnum.NORMAL.value.equals(e.getIsDelete())).collect(Collectors.toList());
List<Long> deductList = userRelationList.stream()
.filter(e -> !TableIsDeleteEnum.NORMAL.value.equals(e.getIsDelete()))
.map(SaasRoleUserRelation::getId).collect(Collectors.toList());
saasRoleUserRelationDao.saveOrUpdateBatch(addList);
saasRoleUserRelationDao.deleteById(deductList);
}
@Override
public List<SaasRole> listAdmins(Long workspaceId, Long ouId) {
return saasRoleDao.lambdaQuery()
.eq(Objects.nonNull(workspaceId), SaasRole::getWorkspaceId, workspaceId)
.eq(Objects.nonNull(ouId), SaasRole::getOwnerOuId, ouId)
.and(w -> {w.eq(SaasRole::getRoleType, RoleTypeEnum.SUPER_ADMIN.getValue())
.or().eq(SaasRole::getRoleType, RoleTypeEnum.ADMIN.getValue());})
.list();
}
}

View File

@ -3,19 +3,36 @@ 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.basics.common.util.AssertUtil;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.pokonyan.util.KeysUtil;
import cn.axzo.tyr.client.common.enums.RoleResourceTypeEnum;
import cn.axzo.tyr.client.common.enums.RoleTypeEnum;
import cn.axzo.tyr.client.model.BaseWorkspaceModel;
import cn.axzo.tyr.client.model.enums.DictWorkSpaceTypeEnum;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.enums.WorkerLeaderRoleEnum;
import cn.axzo.tyr.client.model.roleuser.dto.IdentityInfo;
import cn.axzo.tyr.client.model.roleuser.dto.SuperAminInfoResp;
import cn.axzo.tyr.client.model.roleuser.req.CreateSuperAdminRoleParam;
import cn.axzo.tyr.client.model.roleuser.req.GantOrUnGantaWorkerLeaderRoleReq;
import cn.axzo.tyr.client.model.roleuser.req.RoleUserReq;
import cn.axzo.tyr.client.model.roleuser.req.SuperAdminParam;
import cn.axzo.tyr.client.model.roleuser.req.WorkerManagerRoleUserReq;
import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO;
import cn.axzo.tyr.server.model.RoleUserInfo;
import cn.axzo.tyr.server.repository.dao.RemoveRoleUserByResource;
import cn.axzo.tyr.server.repository.dao.SaasPgroupRoleRelationDao;
import cn.axzo.tyr.server.repository.dao.SaasRoleDao;
import cn.axzo.tyr.server.repository.dao.SaasRoleGroupRelationDao;
import cn.axzo.tyr.server.repository.dao.SaasRoleUserRelationDao;
import cn.axzo.tyr.server.repository.entity.SaasPgroupRoleRelation;
import cn.axzo.tyr.server.repository.entity.SaasRole;
import cn.axzo.tyr.server.repository.entity.SaasRoleGroupRelation;
import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation;
import cn.axzo.tyr.server.service.SaasRoleGroupService;
import cn.axzo.tyr.server.service.SaasRoleUserService;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
@ -45,10 +62,17 @@ public class RoleUserService implements SaasRoleUserService {
private final SaasRoleUserRelationDao roleUserRelationDao;
private final SaasRoleDao saasRoleDao;
private final SaasPgroupRoleRelationDao saasPgroupRoleRelationDao;
private final SaasRoleGroupService saasRoleGroupService;
private final SaasRoleGroupRelationDao saasRoleGroupRelationDao;
// 单位类型默认角色关系,后面可以座位管理员的逻辑进行迭代
@Value("#{${participateUnitDefaultRoleId:{}}}")
public Map<Integer,Long> participateUnitDefaultRoleId;
@Value("${platWorkerLeaderRoleId:100000}")
private Long entWorkerLeaderRoleId;
@Value("${platWorkerLeaderRoleId:100001}")
private Long projWorkerLeaderRoleId;
/**
* 获取分包负责人等特殊角色
@ -87,10 +111,6 @@ public class RoleUserService implements SaasRoleUserService {
List<Long> adminRole = existsRole.stream().filter(e -> RoleTypeEnum.getRoleType(e.getRoleType()).isAdminRole()).mapToLong(SaasRole::getId).boxed().collect(Collectors.toList());
// 排除管理员角色(普通角色) 这里用过滤的方式是为了防止脏数据产生(saas_role_user_relation表有用户数据但是角色表已经被删除)
notAdminRole = existsRoleUser.stream().mapToLong(SaasRoleUserRelation::getRoleId).boxed().filter(roleId -> !adminRole.contains(roleId)).collect(Collectors.toList());
// 排除分包负责人等角色
if (CollectionUtils.isNotEmpty(notAdminRole) && participateUnitDefaultRoleId != null && participateUnitDefaultRoleId.size() > 0) {
notAdminRole = notAdminRole.stream().filter(e-> !participateUnitDefaultRoleId.values().contains(e)).collect(Collectors.toList());
}
}
BaseWorkspaceModel workspaceModel = BaseWorkspaceModel.builder()
.workspaceId(req.getWorkspaceId()).ouId(req.getOuId())
@ -149,8 +169,8 @@ public class RoleUserService implements SaasRoleUserService {
}
@Override
public List<SaasRoleUserRelation> queryByWorkspaceIdOrOu(Long identityId, IdentityType identityType, Set<Long> workspaceIds, Set<Long> ouIds) {
return roleUserRelationDao.queryByWorkspaceIdOrOu(identityId, identityType, workspaceIds, ouIds);
public List<SaasRoleUserRelation> queryByWorkspaceIdOrOu(Long personId, Long identityId, IdentityType identityType, Set<Long> workspaceIds, Set<Long> ouIds) {
return roleUserRelationDao.queryByWorkspaceIdOrOu(personId, identityId, identityType, workspaceIds, ouIds);
}
@Override
@ -169,12 +189,14 @@ public class RoleUserService implements SaasRoleUserService {
saasRole.setOwnerOuId(param.getOuId());
saasRole.setRoleType(RoleTypeEnum.SUPER_ADMIN.getValue());
saasRole.setIsDelete(0L);
DictWorkSpaceTypeEnum dictWorkSpaceTypeEnum = DictWorkSpaceTypeEnum.getByValueWorkspaceType(param.getWorkspaceType());
saasRole.setProductUnitType(dictWorkSpaceTypeEnum == null ? 0 : dictWorkSpaceTypeEnum.getSuperAdminProductType());
checkRoleName(RoleTypeEnum.SUPER_ADMIN.getDesc(), param.getWorkspaceId(), param.getOuId());
saasRoleDao.save(saasRole);
}
//删除当前超管角色
roleUserRelationDao.deleteByRoldId(Lists.newArrayList(saasRole.getId()));
roleUserRelationDao.deleteByRoleId(Lists.newArrayList(saasRole.getId()));
//新增关联关系
SaasRoleUserRelation saasRoleUserRelation = new SaasRoleUserRelation();
@ -265,8 +287,8 @@ public class RoleUserService implements SaasRoleUserService {
return new ArrayList<>();
}
return roleUserRelationDao.list(new LambdaQueryWrapper<SaasRoleUserRelation>()
.eq(SaasRoleUserRelation::getOuId, ouId)
.eq(SaasRoleUserRelation::getWorkspaceId, workspaceId)
.eq(Objects.nonNull(ouId), SaasRoleUserRelation::getOuId, ouId)
.eq(Objects.nonNull(workspaceId), SaasRoleUserRelation::getWorkspaceId, workspaceId)
.in(SaasRoleUserRelation::getRoleId, roleIds));
}
@ -276,4 +298,151 @@ public class RoleUserService implements SaasRoleUserService {
roleUserRelationDao.removeWorkspaceOuAllUserRole(workspaceId, ouId);
}
@Override
public void grantOrUngrantWorkerLeader(GantOrUnGantaWorkerLeaderRoleReq req) {
Boolean grant = req.getGrant();
// 授权
if(Objects.equals(grant, Boolean.TRUE)){
SaasRoleUserRelation saasRoleUserRelation = new SaasRoleUserRelation();
saasRoleUserRelation.setIdentityId(req.getIdentityId());
saasRoleUserRelation.setIdentityType(IdentityType.WORKER_LEADER.getCode());
saasRoleUserRelation.setNaturalPersonId(req.getPersonId());
saasRoleUserRelation.setOuId(req.getOuId());
saasRoleUserRelation.setWorkspaceId(req.getWorkspaceId());
saasRoleUserRelation.setResourceType(RoleResourceTypeEnum.UNIT.code);
saasRoleUserRelation.setResourceId(req.getTeamOuId());
if(Objects.equals(req.getWorkerLeaderRoleEnum(), WorkerLeaderRoleEnum.ENT_TEAM_MANAGER)){
// 平台班组长
saasRoleUserRelation.setRoleId(entWorkerLeaderRoleId);
}else{
// 项目内班组长
saasRoleUserRelation.setRoleId(projWorkerLeaderRoleId);
}
roleUserRelationDao.save(saasRoleUserRelation);
}else{
// 取消授权
roleUserRelationDao.removeWorkerLeaderRole(req.getIdentityId(), IdentityType.WORKER_LEADER, req.getWorkspaceId(), req.getOuId());
}
}
@Override
@Transactional
public void grantOrUngrantWorkerManager(WorkerManagerRoleUserReq req) {
// 查询出角色ID
List<SaasPgroupRoleRelation> saasPgroupRoleRelations = new ArrayList<>(); // NPE
if (CollectionUtil.isNotEmpty(req.getPermissionGroupId())) {
saasPgroupRoleRelations = saasPgroupRoleRelationDao.listByGroupIds(req.getPermissionGroupId());
}
List<SaasRole> roleInfos = new ArrayList<>();
if (CollectionUtil.isNotEmpty(saasPgroupRoleRelations)) {
roleInfos.addAll(saasRoleDao.findInitRole(saasPgroupRoleRelations.stream().map(SaasPgroupRoleRelation::getRoleId).collect(Collectors.toSet())));
}
if (CollectionUtil.isNotEmpty(req.getRoleId())) {
roleInfos.addAll(saasRoleDao.listByIds(req.getRoleId()));
}
RoleUserInfo roleUserBaseInfo = RoleUserInfo.builder()
.roleUserResourceInfos(req.getManagerInfos().stream().map(e -> RoleUserInfo.RoleUserResourceInfo
.builder()
.workspaceId(e.getWorkspaceId())
.ouId(e.getOuId())
.resourceId(e.getResourceId())
.identityInfos(e.getIdentityInfos())
.build()).collect(Collectors.toList()))
.roleId(roleInfos.stream().map(BaseEntity::getId).collect(Collectors.toSet()))
.identityType(req.getIdentityType())
.resourceType(req.getResourceType())
.build();
// 授权
if (!req.isUngrant()) {
if (CollectionUtil.isEmpty(roleUserBaseInfo.getRoleUserResourceInfos())) {
throw new ServiceException("grant team manager error, not found person info");
}
if (CollectionUtil.isEmpty(saasPgroupRoleRelations)|| CollectionUtil.isEmpty(roleInfos)) {
log.warn("warn: grant team manager permission error, not found permissions info");
// 未指定授权哪些角色
return;
}
List<SaasRoleUserRelation> exist = roleUserRelationDao.findByResource(roleUserBaseInfo);
Set<String> existKey = exist.stream().map(e -> KeysUtil.createKey(e.getNaturalPersonId(), e.getOuId(), e.getWorkspaceId(), e.getResourceId(), e.getResourceType(),e.getRoleId())).collect(Collectors.toSet());
// 防止重复插入数据过滤一次原始数据
roleUserRelationDao.saveBatch(
// 第一个维度基础信息
roleUserBaseInfo.getRoleUserResourceInfos().stream().map(e -> {
// 第二个维度
return e.getIdentityInfos().stream().map(identityInfo -> {
// 第三个维度角色
return roleUserBaseInfo.getRoleId().stream().map(roleId -> {
if (existKey.contains(KeysUtil.createKey(identityInfo.getPersonId(), e.getOuId(), e.getWorkspaceId(), e.getResourceId(), roleUserBaseInfo.getResourceType(), roleId))) {
return null;
}
SaasRoleUserRelation saasRoleUserRelation = new SaasRoleUserRelation();
saasRoleUserRelation.setIdentityId(identityInfo.getIdentityId());
saasRoleUserRelation.setIdentityType(req.getIdentityType().getCode());
saasRoleUserRelation.setRoleId(roleId);
saasRoleUserRelation.setNaturalPersonId(identityInfo.getPersonId());
saasRoleUserRelation.setOuId(e.getOuId());
saasRoleUserRelation.setWorkspaceId(e.getWorkspaceId());
saasRoleUserRelation.setResourceType(roleUserBaseInfo.getResourceType());
saasRoleUserRelation.setResourceId(e.getResourceId());
return saasRoleUserRelation;
}).filter(Objects::nonNull).collect(Collectors.toList());
}).flatMap(List::stream).collect(Collectors.toList());
}).flatMap(List::stream).collect(Collectors.toList())
);
return;
}
// 取消授权
if (!req.isUngrantAll()) {
if (CollectionUtil.isEmpty(saasPgroupRoleRelations)) {
// 未指定取消授权哪些角色
return;
}
batchRemoveByRoleUserInfo(roleUserBaseInfo);
return;
}
// 取消所有权限
String categoryCode = req.getRoleGroupCategoryCode();
if (StrUtil.isBlank(categoryCode)) {
throw new ServiceException("不支持清除该人员所有角色,请指定分组");
}
List<SaasRoleGroupVO> saasRoleGroupVO = saasRoleGroupService.listByCategoryCode(Lists.newArrayList(categoryCode));
List<SaasRoleGroupRelation> roleGroupRelations = saasRoleGroupRelationDao.getByGroupIds(saasRoleGroupVO.stream().map(SaasRoleGroupVO::getId).distinct().collect(Collectors.toList()));
Set<Long> roleIds = roleGroupRelations.stream().map(SaasRoleGroupRelation::getRoleId).collect(Collectors.toSet());
if (CollectionUtil.isEmpty(roleIds)) {
return;
}
roleUserBaseInfo.setRoleId(roleIds);
batchRemoveByRoleUserInfo(roleUserBaseInfo);
}
private void batchRemoveByRoleUserInfo(RoleUserInfo roleUserBaseInfo) {
roleUserBaseInfo.getRoleUserResourceInfos().forEach(e -> {
roleUserRelationDao.removeByResource(RemoveRoleUserByResource.builder()
.ouId(e.getOuId())
.workspaceId(e.getWorkspaceId())
.resourceId(e.getResourceId())
.resourceType(roleUserBaseInfo.getResourceType())
.identityId(e.getIdentityInfos().stream().map(IdentityInfo::getIdentityId).distinct().collect(Collectors.toList()))
.identityType(roleUserBaseInfo.getIdentityType())
.roleId(roleUserBaseInfo.getRoleId())
.build());
});
}
}

View File

@ -1,20 +1,30 @@
package cn.axzo.tyr.server.service.impl;
import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.req.FeaturePermissionReq;
import cn.axzo.tyr.client.model.req.IdentityAuthReq;
import cn.axzo.tyr.client.model.res.FeaturePermissionRes;
import cn.axzo.tyr.client.model.res.IdentityAuthRes;
import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
import cn.axzo.tyr.server.repository.entity.SaasFeature;
import cn.axzo.tyr.server.service.SaasFeatureService;
import cn.axzo.tyr.server.service.TyrSaasAuthService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
@ -26,33 +36,64 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
public class SaasFeatureServiceImpl implements SaasFeatureService {
private final SaasFeatureDao saasFeatureDao;
private final TyrSaasAuthService tyrSaasAuthService;
@Override
public FeaturePermissionRes listPermissionCodes(FeaturePermissionReq req) {
//单独做下参数校验
if (req.getPersonId() == null
&& (req.getIdentityId() == null || req.getIdentityType() == null)) {
AssertUtil.fail("自然人ID和身份ID/Type不能同时为空");
}
FeaturePermissionRes featurePermissionRes = new FeaturePermissionRes();
IdentityAuthReq authReq = new IdentityAuthReq();
if (StringUtils.hasText(req.getTerminal())) {
authReq.setTerminal(Lists.newArrayList());
if (StrUtil.isNotBlank(req.getTerminal())) {
authReq.setTerminal(Collections.singletonList(req.getTerminal()));
}
authReq.setIdentityId(req.getIdentityId());
authReq.setIdentityType(IdentityType.getIdentityType(req.getIdentityType()));
authReq.setPersonId(req.getPersonId());
IdentityAuthReq.WorkspaceOuPair workspaceOuPair = new IdentityAuthReq.WorkspaceOuPair();
workspaceOuPair.setWorkspaceId(req.getWorkspaceId());
workspaceOuPair.setOuId(req.getOuId());
workspaceOuPair.setWorkspaceType(req.getWorkspaceType());
workspaceOuPair.setWorkspaceJoinType(req.getWorkspaceJoinType());
authReq.setWorkspaceOusPairs(Lists.newArrayList(workspaceOuPair));
IdentityAuthRes identityAuthRes = tyrSaasAuthService.findIdentityAuth(authReq);
IdentityAuthRes identityAuthRes = tyrSaasAuthService.findIdentityAuthMix(authReq);
List<IdentityAuthRes.WorkspacePermission> workspacePermissionList = identityAuthRes.getPermissions();
if (CollUtil.isNotEmpty(workspacePermissionList)) {
IdentityAuthRes.WorkspacePermission workspacePermission = workspacePermissionList.get(0);
featurePermissionRes.setSuperAdmin(workspacePermission.isSuperAdmin());
featurePermissionRes.setPermissionCodes(workspacePermission.getPermissionPoint()
.stream().map(IdentityAuthRes.PermissionPoint::getFeatureCode).collect(Collectors.toSet()));
.stream()
.map(IdentityAuthRes.PermissionPoint::getFeatureCode)
.collect(Collectors.toSet()));
}
return featurePermissionRes;
}
@Override
public List<Long> listAppFeatureIds(Collection<Long> appItemIds) {
if (CollectionUtils.isEmpty(appItemIds)) {
log.info("appItemIds is empty.");
return Collections.emptyList();
}
List<SaasFeature> saasFeatures = saasFeatureDao.lambdaQuery()
.in(SaasFeature::getLinkType, Lists.newArrayList(LINK_TYPE_UNIAPP, LINK_TYPE_NATIVE))
.in(SaasFeature::getIsDelete, TableIsDeleteEnum.NORMAL.value)
.list();
return saasFeatures.stream()
.filter(UNI_APP_ITEM_ID_FILTER)
.filter(e -> appItemIds.contains(Long.parseLong(e.getMicroAppItemId())))
.map(SaasFeature::getId)
.collect(Collectors.toList());
}
// 小程序
private static final Integer LINK_TYPE_UNIAPP = 2;
// 原生
private static final Integer LINK_TYPE_NATIVE = 4;
private static final Predicate<SaasFeature> UNI_APP_ITEM_ID_FILTER = e ->
StringUtils.hasText(e.getMicroAppItemId()) && NumberUtil.isNumber(e.getMicroAppItemId().trim());
}

View File

@ -158,4 +158,9 @@ public class SaasRoleGroupServiceImpl implements SaasRoleGroupService {
saasRoleGroup.setOuId(req.getOuId() != null ? req.getOuId() : -1L);
return saasRoleGroup;
}
@Override
public List<SaasRoleGroupVO> listByCategoryCode(List<String> categoryCode) {
return BeanUtil.copyToList(saasRoleGroupDao.listByCategoryCode(categoryCode), SaasRoleGroupVO.class);
}
}

View File

@ -4,6 +4,7 @@ import cn.axzo.basics.common.BeanMapper;
import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum;
import cn.axzo.framework.domain.page.PageResp;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.tyr.client.common.enums.RoleTypeEnum;
import cn.axzo.tyr.client.model.roleuser.dto.SaasRoleUserDTO;
import cn.axzo.tyr.client.model.roleuser.req.RoleUserParam;
import cn.axzo.tyr.server.repository.dao.SaasRoleDao;
@ -15,7 +16,6 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@ -53,19 +53,21 @@ public class SaasRoleUserRelationServiceImpl implements SaasRoleUserRelationServ
.in(SaasRole::getId, saasRoleUserRelations.stream().map(SaasRoleUserRelation::getRoleId).collect(Collectors.toSet()))
.list().stream().collect(Collectors.toMap(SaasRole::getId, Function.identity()));
return saasRoleUserRelations.stream().map(e -> {
SaasRoleUserDTO userRole = BeanUtil.copyProperties(e, SaasRoleUserDTO.class);
SaasRole role = roleMap.get(userRole.getRoleId());
if (Objects.nonNull(role)) {
userRole.setRoleName(role.getName());
userRole.setDescription(role.getDescription());
}
return userRole;
}).collect(Collectors.toList());
return saasRoleUserRelations.stream()
.filter(e -> roleMap.containsKey(e.getRoleId()))
.map(e -> {
SaasRoleUserDTO userRole = BeanUtil.copyProperties(e, SaasRoleUserDTO.class);
SaasRole role = roleMap.get(userRole.getRoleId());
userRole.setRoleName(role.getName());
userRole.setDescription(role.getDescription());
userRole.setRoleType(RoleTypeEnum.getRoleType(role.getRoleType()));
return userRole;
}).collect(Collectors.toList());
}
private LambdaQueryChainWrapper<SaasRoleUserRelation> buildWrapper(RoleUserParam param) {
return saasRoleUserRelationDao.lambdaQuery()
.eq(Objects.nonNull(param.getPersonId()), SaasRoleUserRelation::getNaturalPersonId, param.getPersonId())
.eq(Objects.nonNull(param.getIdentityId()), SaasRoleUserRelation::getIdentityId, param.getIdentityId())
.eq(Objects.nonNull(param.getIdentityType()), SaasRoleUserRelation::getIdentityType, param.getIdentityType())
.eq(Objects.nonNull(param.getWorkspaceId()), SaasRoleUserRelation::getWorkspaceId, param.getWorkspaceId())

View File

@ -34,6 +34,7 @@
r.`name` AS roleName,
r.role_type AS roleType,
r.workspace_id AS workspaceId,
r.product_unit_type AS productUnitType,
ru.identity_id AS identityId,
ru.identity_type AS identityType,
ru.natural_person_id AS naturalPersonId,
@ -114,4 +115,15 @@
<include refid="sql-queryForOUWorkspace"/>
</select>
<select id="listRoleByFeatures" resultType="cn.axzo.tyr.server.repository.entity.SaasRole">
SELECT DISTINCT r.id, r.`NAME`, r.product_unit_type AS productUnitType
FROM saas_pgroup_permission_relation pg, saas_pgroup_role_relation rg, saas_role r
WHERE pg.is_delete = 0 AND rg.is_delete = 0 AND r.is_delete = 0
AND pg.group_id = rg.group_id AND rg.role_id = r.id
AND pg.feature_id IN
<foreach collection="featureIds" open="(" close=")" separator="," index="index" item="item">
#{item, jdbcType=NUMERIC}
</foreach>
</select>
</mapper>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.axzo.tyr.server.repository.mapper.SaasRoleUserRelationMapper">
<select id="batListCleanRelation" resultType="cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation">
SELECT DISTINCT ou_id AS ouId, workspace_id AS workspaceId,
natural_person_id AS naturalPersonId,
identity_id AS identityId, identity_type AS identityType
FROM saas_role_user_relation
WHERE is_delete = 0
<if test="param.ouId !=0 and param.ouId != null">
AND ou_id = #{param.ouId}
</if>
<if test="param.workspaceId !=0 and param.workspaceId != null">
AND workspace_id = #{param.workspaceId}
</if>
<if test="param.naturalPersonId !=0 and param.naturalPersonId != null">
AND natural_person_id = #{param.naturalPersonId}
</if>
</select>
</mapper>

View File

@ -75,4 +75,103 @@
#{item, jdbcType=VARCHAR}
</foreach>
</select>
<resultMap id="workerPositionEx"
type="cn.axzo.tyr.client.model.res.ListPermissionFromRoleGroupResp">
<result property="identityId" column="identityId"/>
<result property="identityType" column="identityType"/>
<result property="personId" column="personId"/>
<result property="ouId" column="ouId"/>
<result property="workspaceId" column="workspaceId"/>
<result property="teamOuId" column="teamOuId"/>
<result property="roleGroupName" column="roleGroupName"/>
<result property="roleGroupCode" column="roleGroupCode"/>
<result property="roleGroupName" column="roleGroupName"/>
<result property="roleId" column="roleId"/>
<result property="roleName" column="roleName"/>
<result property="permissionGroupId" column="permissionGroupId"/>
<collection property="simpleFeatureInfos"
ofType="cn.axzo.tyr.client.model.res.SimpleFeatureInfo">
<result property="featureId" column="featureId"/>
<result property="featureCode" column="featureCode"/>
</collection>
</resultMap>
<select id="listAuthByResourceAndRoleGroup" resultType="cn.axzo.tyr.client.model.res.ListPermissionFromRoleGroupResp">
SELECT
t5.identity_id identityId,
t5.identity_type identityType,
t5.natural_person_id personId,
t5.ou_id ouId,
t5.workspace_Id workspaceId,
t5.resource_id teamOuId,
t5.resource_id resourceId,
t5.resource_type resourceType,
t1.category_code categoryCode,
t1.name roleGroupName,
t1.code roleGroupCode,
t3.id roleId,
t3.name roleName,
t4.group_id permissionGroupId
FROM
saas_role_group t1
INNER JOIN saas_role_group_relation t2 ON t1.id = t2.saas_role_group_id
INNER JOIN saas_role t3 ON t2.role_id = t3.id
INNER JOIN saas_pgroup_role_relation T4 ON t3.id = t4.role_id
INNER JOIN saas_role_user_relation t5 ON t3.id = t5.role_id
WHERE
t1.category_code = #{req.categoryCode}
AND T1.IS_DELETE = 0 AND T2.IS_DELETE = 0 AND T3.IS_DELETE=0 AND T4.IS_DELETE = 0 AND T5.IS_DELETE = 0
<if test="req.identityIds != null ">
<foreach collection="req.identityIds" item="identity" open=" and t5.identity_id IN ( " close=" ) " separator=" , ">
#{identity}
</foreach>
</if>
<if test="req.personIds != null ">
<foreach collection="req.personIds" item="personId" open=" and t5.natural_person_id IN ( " close=" ) " separator=" , ">
#{personId}
</foreach>
</if>
<if test="req.identityType != null ">
AND T5.identity_type =#{req.identityType}
</if>
<if test="req.workspaceOuPairs != null and req.workspaceOuPairs.size()>0">
AND
<foreach collection="req.workspaceOuPairs" index="index" item="ouIdAndWorkspaceId" open="(" close=")"
separator=") or ( ">
1=1
<if test="ouIdAndWorkspaceId.workspaceId !=null">
and t5.workspace_id = #{ouIdAndWorkspaceId.workspaceId}
</if>
<if test="ouIdAndWorkspaceId.ouId !=null">
and t5.ou_id = #{ouIdAndWorkspaceId.ouId}
</if>
<if test="ouIdAndWorkspaceId.resourceId !=null">
and t5.resource_id = #{ouIdAndWorkspaceId.resourceId}
</if>
<if test="ouIdAndWorkspaceId.resourceType !=null">
and t5.resource_type = #{ouIdAndWorkspaceId.resourceType}
</if>
</foreach>
</if>
</select>
</mapper>

View File

@ -1,8 +1,10 @@
package cn.axzo.tyr.server.permission;
import cn.axzo.tyr.server.job.ProductFeatureRefreshJobHandler;
import cn.axzo.tyr.server.job.UserRoleRelationCleanJob;
import cn.axzo.tyr.server.model.ProductFeatureRefreshParam;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@ -16,6 +18,8 @@ import org.springframework.boot.test.context.SpringBootTest;
public class JobTest {
@Autowired
private ProductFeatureRefreshJobHandler productFeatureRefreshJobHandler;
@Autowired
private UserRoleRelationCleanJob userRoleRelationCleanJob;
@Test
public void testProductFeatureRefresh() throws Exception {
@ -24,4 +28,15 @@ public class JobTest {
param.setProductId(1007L);
productFeatureRefreshJobHandler.execute(JSON.toJSONString(param));
}
@Test
public void testUserRoleCleanJob() throws Exception {
UserRoleRelationCleanJob.CleanTarget param = UserRoleRelationCleanJob.CleanTarget.builder()
//.ouId(1L)
//.workspaceId(31L)
.personId(5367L)
.build();
userRoleRelationCleanJob.execute(JSON.toJSONString(param));
}
}

View File

@ -13,6 +13,7 @@ import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
import cn.axzo.tyr.server.repository.dao.SaasRoleDao;
import cn.axzo.tyr.server.repository.dao.SaasRoleUserRelationDao;
import cn.axzo.tyr.server.repository.entity.SaasRole;
import cn.axzo.tyr.server.service.RoleService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.junit.jupiter.api.Test;
@ -42,6 +43,9 @@ public class RoleUserTest {
@Autowired
private SaasRoleDao saasRoleDao;
@Autowired
private RoleService roleService;
@Test
public void testList() {
saasRoleUserRelationDao.deleteByUser(BaseWorkspaceModel.builder()
@ -77,5 +81,10 @@ public class RoleUserTest {
System.out.println(JSON.toJSONString(page));
}
@Test
public void testListAdmin() {
roleService.listAdmins(111L, 22L);
}
}