Merge branch 'feature/REQ-2227' into 'master'

Feature/req 2227

See merge request universal/infrastructure/backend/tyr!35
This commit is contained in:
谭杰 2024-04-24 10:27:26 +00:00
commit 5bfe2768a9
117 changed files with 5851 additions and 147 deletions

View File

@ -0,0 +1,42 @@
package cn.axzo.tyr.client.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* 功能资源授权类型
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/8 17:57
*/
@Getter
@AllArgsConstructor
public enum FeatureResourceAuthType {
ALL_ROLE(0, "全部角色"),
GRANT_ROLE(1, "指定角色"),
;
private static final Map<Integer, FeatureResourceAuthType> MAPPING = new HashMap<>();
static {
Arrays.stream(FeatureResourceAuthType.values()).forEach(t -> MAPPING.put(t.code, t));
}
private final Integer code;
private final String desc;
public FeatureResourceAuthType getByCode(Integer code) {
return MAPPING.get(code);
}
public boolean apply(Integer code) {
return this.code.equals(code);
}
}

View File

@ -0,0 +1,42 @@
package cn.axzo.tyr.client.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* 功能资源状态
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/8 17:37
*/
@Getter
@AllArgsConstructor
public enum FeatureResourceStatus {
HIDE(0, "隐藏"),
NORMAL(1, "展示"),
;
private static final Map<Integer, FeatureResourceStatus> MAPPING = new HashMap<>();
static {
Arrays.stream(FeatureResourceStatus.values()).forEach(t -> MAPPING.put(t.code, t));
}
private final Integer code;
private final String desc;
public FeatureResourceStatus getByCode(Integer code) {
return MAPPING.get(code);
}
public boolean apply(Integer code) {
return this.code.equals(code);
}
}

View File

@ -0,0 +1,61 @@
package cn.axzo.tyr.client.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 功能资源类型
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/3 11:35
*/
@Getter
@AllArgsConstructor
public enum FeatureResourceType {
MENU(1, "菜单"),
PAGE(2, "页面"),
APP_ENTRY(3, "应用入口"),
COMPONENT(4, "组件"),
;
private static final Map<Integer, FeatureResourceType> MAPPING = new HashMap<>();
static {
Arrays.stream(FeatureResourceType.values()).forEach(t -> MAPPING.put(t.code, t));
}
private final Integer code;
private final String desc;
public FeatureResourceType getByCode(Integer code) {
return MAPPING.get(code);
}
public boolean apply(Integer code) {
return this.code.equals(code);
}
public static boolean applyPage(Integer code) {
return PAGE.apply(code) || APP_ENTRY.apply(code);
}
public static List<Integer> navTypes() {
return Arrays.asList(FeatureResourceType.MENU.getCode(),
FeatureResourceType.PAGE.getCode(),
FeatureResourceType.APP_ENTRY.getCode());
}
public static List<Integer> pageTypes() {
return Arrays.asList(
FeatureResourceType.PAGE.getCode(),
FeatureResourceType.APP_ENTRY.getCode());
}
}

View File

@ -6,6 +6,8 @@ import lombok.Getter;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -18,11 +20,12 @@ import java.util.stream.Collectors;
@AllArgsConstructor
public enum RoleTypeEnum {
//角色类型common 普通角色 super_admin超级管理员(禁止删除) admin子管理员(禁止删除) init初始化内置角色
//角色类型common 普通角色 super_admin超级管理员(禁止删除) admin子管理员(禁止删除) init初始化内置角色 auto_own自定义角色(禁止删除)<承载向用户单独分配的自定义权限>
COMMON("common", "普通角色",false),
SUPER_ADMIN("super_admin", "超级管理员",true),
ADMIN("admin", "子管理员",true),
INIT("init", "初始化内置角色",false);
INIT("init", "初始化内置角色",false),
AUTO_OWN("auto_own", "自定义角色",false);
@EnumValue
private final String value;
@ -43,4 +46,14 @@ public enum RoleTypeEnum {
return isAdmin;
}
public static boolean isAdmin(String roleType) {
return Optional.ofNullable(getRoleType(roleType))
.map(RoleTypeEnum::isAdminRole)
.orElse(false);
}
public boolean apply(String value) {
return Objects.equals(this.value, value);
}
}

View File

@ -0,0 +1,61 @@
package cn.axzo.tyr.client.feign;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq;
import cn.axzo.tyr.client.model.req.ResourceSyncReq;
import cn.axzo.tyr.client.model.req.FeatureResourceTreeSaveReq;
import cn.axzo.tyr.client.model.res.FeatureResourceDetailResp;
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
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;
import javax.validation.Valid;
import java.util.List;
/**
* 功能资源API接口
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/3 10:03
*/
@FeignClient(name = "tyr", url = "${axzo.service.tyr:http://tyr:8080}")
public interface FeatureResourceApi {
/** 根据ID获取要同步的功能资源树详情 **/
@GetMapping("/api/featureResource/sync/getTreeById")
ApiResult<List<FeatureResourceTreeNode>> getSyncTreeById(@RequestParam Long id);
/** 从基准环境同步接口功能资源 **/
@PostMapping("/api/featureResource/sync/fromBase")
ApiResult<Void> syncFromBase(@RequestBody @Valid ResourceSyncReq req);
@PostMapping("/api/featureResource/saveOrUpdate")
ApiResult<Long> saveMenu(@RequestBody FeatureResourceTreeSaveReq req);
/** 查询功能资源树 **/
@PostMapping("/api/featureResource/getTree")
ApiResult<List<FeatureResourceTreeNode>> getTree(@RequestBody @Valid GetFeatureResourceTreeReq req);
/** 删除菜单/页面/组件 **/
@PostMapping("/api/featureResource/delete")
ApiResult<Void> deleteFeatureResource(@RequestParam Long featureId, @RequestParam Long operatorId);
/** 重排序菜单/页面/组件 **/
@PostMapping("/api/featureResource/reorder")
ApiResult<Void> reorderFeatureTree(@RequestParam Long featureId, @RequestParam Integer offset);
/** 菜单详情 **/
@PostMapping("/api/featureResource/detail")
ApiResult<FeatureResourceTreeNode> detail(@RequestParam Long featureId);
/** 从基准环境查询功能资源树 **/
@PostMapping("/api/featureResource/getBaseTree")
ApiResult<List<FeatureResourceTreeNode>> getBaseTree(@RequestBody @Valid GetFeatureResourceTreeReq req);
}

View File

@ -0,0 +1,37 @@
package cn.axzo.tyr.client.feign;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.model.req.NavTreeReq;
import cn.axzo.tyr.client.model.req.PagePermissionReq;
import cn.axzo.tyr.client.model.req.PagePermissionResp;
import cn.axzo.tyr.client.model.req.PermissionCheckReq;
import cn.axzo.tyr.client.model.res.NavTreeResp;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
import java.util.List;
/**
* 权限服务接口
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/7 16:18
*/
@FeignClient(name = "tyr", url = "${axzo.service.tyr:http://tyr:8080}")
public interface PermissionQueryApi {
/** 返回有权限的导航菜单页面 **/
@PostMapping(value = "/api/v3/permission/query/getNavTree")
ApiResult<List<NavTreeResp>> getNavTree(@RequestBody @Valid NavTreeReq req);
/** 页面权限详情:页面自身及所有下级 **/
@PostMapping(value = "/api/v3/permission/query/getPagePermission")
ApiResult<List<PagePermissionResp>> getPagePermission(@RequestBody @Valid PagePermissionReq req);
/** 鉴权接口 **/
@PostMapping(value = "/api/v3/permission/query/hasPermission")
ApiResult<Boolean> hasPermission(@RequestBody @Valid PermissionCheckReq req);
}

View File

@ -0,0 +1,25 @@
package cn.axzo.tyr.client.feign;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.model.req.CommonDictQueryReq;
import cn.axzo.tyr.client.model.res.CommonDictResp;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
/**
* @author chenwenjian
* @date 2023/9/6 15:33
* @description 企业字典api
* @modifiedBy
* @version: 1.0
*/
@FeignClient(name = "tyr", url = "${axzo.service.tyr:http://tyr:8080}")
public interface SaasCommonDictApi {
@PostMapping("/api/commonDict/query")
ApiResult<List<CommonDictResp>> query(@RequestBody CommonDictQueryReq req);
}

View File

@ -2,6 +2,7 @@ package cn.axzo.tyr.client.feign;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq;
import cn.axzo.tyr.client.model.req.UpdateRoleGroupOffsetReq;
import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@ -9,6 +10,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.util.List;
@ -61,5 +63,13 @@ public interface SaasRoleGroupApi {
@GetMapping("/api/saasRoleGroup/listByCategoryCode")
ApiResult<List<SaasRoleGroupVO>> listByCategoryCode(@RequestParam("categoryCode") List<String> categoryCodes);
/**
* 更新角色分组的位置
* 向下移动则找到后面位置的分组替换sort
* 向上移动则找到前面位置的分组替换sort
* @param request
* @return
*/
@PostMapping("/api/role/group/offset/update")
ApiResult<Void> updateRoleGroupOffset(@Valid @RequestBody UpdateRoleGroupOffsetReq request);
}

View File

@ -1,16 +1,25 @@
package cn.axzo.tyr.client.feign;
import cn.axzo.framework.domain.web.result.ApiListResult;
import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.model.req.ChangeGroupLeaderRoleReq;
import cn.axzo.tyr.client.model.req.FeatureRoleRelationReq;
import cn.axzo.tyr.client.model.req.PageRoleReq;
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.req.TreeRoleReq;
import cn.axzo.tyr.client.model.req.UpdateRoleOffsetReq;
import cn.axzo.tyr.client.model.res.FeatureRoleRelationResp;
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.RoleTreeRes;
import cn.axzo.tyr.client.model.res.RoleWithUserRes;
import cn.axzo.tyr.client.model.res.SaasRoleRes;
import cn.axzo.tyr.client.model.vo.DeleteRoleVO;
import cn.axzo.tyr.client.model.vo.SaasRoleAndGroupVO;
import cn.axzo.tyr.client.model.vo.SaasRoleCategoryVO;
import cn.axzo.tyr.client.model.vo.SaasRoleGroupCodeVO;
@ -41,6 +50,15 @@ public interface TyrSaasRoleApi {
@PostMapping("/api/saasRole/saveOrUpdate")
ApiResult<Long> saveOrUpdate(@RequestBody @Validated SaveOrUpdateRoleVO saveOrUpdateRole);
/** OMS编辑菜单时给角色赋权限 **/
@PostMapping("/api/saasRoleGroup/relation/saveOrUpdate")
ApiResult<Long> saveOrUpdateFeatureRoleRelation(@RequestBody @Validated FeatureRoleRelationReq saasFeatureRoleRelationReq);
/** 角色和组件页面的关联关系 **/
@PostMapping("/api/saasRoleGroup/relation/query")
ApiResult<FeatureRoleRelationResp> queryFeatureRoleRelation(@RequestParam Long featureId);
/**
* 根据id查询详情
*/
@ -59,8 +77,7 @@ public interface TyrSaasRoleApi {
* 删除
*/
@PostMapping("/api/saasRole/delete")
@Deprecated
ApiResult<Void> delete(@RequestBody List<Long> id);
ApiResult<Void> delete(@RequestBody DeleteRoleVO request);
/**
@ -140,4 +157,30 @@ public interface TyrSaasRoleApi {
*/
@PostMapping("api/saasRole/changeGroupLeaderRole")
ApiResult<Void> changeGroupLeaderRole(@RequestBody @Valid List<ChangeGroupLeaderRoleReq> req);
/**
* 查询角色树
* @param req
* @return
*/
@PostMapping("/api/saasRole/tree")
ApiListResult<RoleTreeRes> treeSaasRole(@RequestBody @Valid TreeRoleReq req);
/**
* 更新角色的位置
* 向下移动则找到后面位置的分组替换sort
* 向上移动则找到前面位置的分组替换sort
* @param request
* @return
*/
@PostMapping("/api/saasRole/offset/update")
ApiResult<Void> updateRoleOffset(@Valid @RequestBody UpdateRoleOffsetReq request);
/**
* 角色page接口
* @param request
* @return
*/
@PostMapping("/api/saasRole/page")
ApiPageResult<SaasRoleRes> page(@RequestBody PageRoleReq request);
}

View File

@ -1,12 +1,11 @@
package cn.axzo.tyr.client.feign;
import cn.axzo.basics.common.page.PageRequest;
import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.model.roleuser.dto.GetUserAutoOwnRoleResp;
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.azxo.framework.common.model.CommonResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -103,4 +102,15 @@ public interface TyrSaasRoleUserApi {
@PostMapping("/api/saas-role-user/get-special-role")
ApiResult<List<Long>> getSpecialRole();
/**
* 保存/更新 用户自定义权限每次传入新的featureIds都会覆盖原来的所有featureIds
*/
@PostMapping("/api/saas-role-user/save-or-update-auto-own-role")
ApiResult<Void> saveOrUpdateAutoOwnRole(@RequestBody @Valid AutoOwnRoleUserReq req);
/**
* 查询用户自定义角色和权限
*/
@PostMapping("/api/saas-role-user/get-auto-own-role")
ApiResult<GetUserAutoOwnRoleResp> getUserAutoOwnRole(@RequestBody @Valid GetUserAutoOwnRoleReq req);
}

View File

@ -0,0 +1,41 @@
package cn.axzo.tyr.client.model.base;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class BaseFeatureResourceDO {
/**
* 资源ID 新增时为null编辑时必传
**/
private Long id;
/** 上级资源ID **/
private Long parentId;
/** 资源名称 **/
private String featureName;
/** 资源类型 1-菜单 2-页面 3-应用入口 4-组件 **/
private Integer featureType;
/** 资源编码 **/
private String featureCode;
/** 状态 0-隐藏 1-显示 **/
private Integer status;
/** 图标 **/
private String icon;
/** 端类型 **/
private String terminal;
/** 组件类型 **/
private Integer componentType;
}

View File

@ -0,0 +1,28 @@
package cn.axzo.tyr.client.model.base;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* OU Workspace对
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/7 16:28
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WorkspaceOUPair {
private Long ouId;
private Long workspaceId;
private String buildKey() {
return ouId + "-" + workspaceId;
}
}

View File

@ -0,0 +1,26 @@
package cn.axzo.tyr.client.model.req;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 通用字典查询请求参数
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/3/26 17:03
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CommonDictQueryReq {
private String scope;
private List<String> codes;
}

View File

@ -0,0 +1,26 @@
package cn.axzo.tyr.client.model.req;
import cn.axzo.tyr.client.model.base.BaseFeatureResourceDO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.util.ArrayList;
import java.util.List;
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class FeatureComponentSaveReq extends BaseFeatureResourceDO {
/** 子级是否需要鉴权 0-不鉴权 1-鉴权 **/
private Integer subAuthType;
/** 路由地址 **/
private String linkUrl;
/** 子级组件 **/
private List<FeatureComponentSaveReq> children = new ArrayList<>();
}

View File

@ -0,0 +1,22 @@
package cn.axzo.tyr.client.model.req;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class FeatureResourceTreeQuery {
/** 查询搜索关键字 **/
private String keyword;
/** 端 **/
private String terminal;
/** 展示状态 默认不传返回全部 0-隐藏 1-显示 **/
private Integer status;
}

View File

@ -0,0 +1,62 @@
package cn.axzo.tyr.client.model.req;
import cn.axzo.tyr.client.model.base.BaseFeatureResourceDO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class FeatureResourceTreeSaveReq extends BaseFeatureResourceDO {
/** 跳转类型 1-站内跳转 2-站外跳转 **/
private Integer redirectType;
/** 路由地址 **/
private String linkUrl;
/** 路由类型 1-PC 2-小程序 3-原生 **/
private Integer linkType;
/** APP适配参数 **/
private String linkExt;
/** 小程序ID **/
private Integer appItemId;
/** 授权类型 0-全部角色 1-指定角色 **/
private Integer authType;
/** 页面组件对象 **/
private List<FeatureComponentSaveReq> componentSaveReqList;
/** 页面及组件权限对象 **/
private List<RolePermissionSaveReq> permissions;
@NotNull(message = "操作人ID不能为空")
private Long operatorId;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class RolePermissionSaveReq {
/**
* 角色ID
**/
private Long roleId;
/**
* 资源编码
**/
private List<String> featureCode;
}
}

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 javax.validation.constraints.NotNull;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class FeatureRoleRelationReq {
@NotNull(message = "操作人不能为空")
private Long operatorId;
@NotEmpty(message = "配置信息不能为空")
private List<RelationRoleSettings> roleSettings;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class RelationRoleSettings {
/** 功能Id **/
private Long featureId;
/** 应用的角色Id列表 **/
private List<Long> roleIds;
/** 授权类型 0-全部角色 1-指定角色 **/
private Integer authType;
}
}

View File

@ -0,0 +1,30 @@
package cn.axzo.tyr.client.model.req;
import lombok.*;
import java.util.List;
/**
* @author likunpeng
* @version 1.0
* @date 2024/4/9
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class GetFeatureResourceTreeReq {
/** 查询搜索关键字 **/
private String keyword;
/** 端 **/
private List<String> terminals;
/** 展示状态 默认不传返回全部 0-隐藏 1-显示 **/
private Integer status;
/** feature类型列表 **/
private List<Integer> featureTypes;
}

View File

@ -41,6 +41,9 @@ public class ListPermissionFromRoleGroupReq {
@Builder.Default
private Boolean findFeatureInfo = false;
/** 角色组ID **/
private List<Long> roleGroupIds;
@Data
@Builder
@AllArgsConstructor

View File

@ -0,0 +1,34 @@
package cn.axzo.tyr.client.model.req;
import cn.axzo.tyr.client.model.base.WorkspaceOUPair;
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;
/**
* NavTreeReq
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/7 17:38
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class NavTreeReq {
@NotNull(message = "人员ID不能为空")
private Long personId;
/** 登录端 **/
@NotNull(message = "登录端不能为空")
private String terminal;
@NotEmpty(message = "单位标识对不能为空")
private List<WorkspaceOUPair> workspaceOUPairs;
}

View File

@ -0,0 +1,38 @@
package cn.axzo.tyr.client.model.req;
import cn.axzo.tyr.client.model.base.WorkspaceOUPair;
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;
/**
* 页面权限查询请求
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/9 16:09
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PagePermissionReq {
@NotNull(message = "权限码不能为空")
private String featureCode;
@NotNull(message = "人员ID不能为空")
private Long personId;
/** 登录端 **/
@NotNull(message = "登录端不能为空")
private String terminal;
@NotEmpty(message = "单位标识对不能为空")
private List<WorkspaceOUPair> workspaceOUPairs;
}

View File

@ -0,0 +1,26 @@
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/4/9 16:14
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PagePermissionResp {
/** 权限ID **/
private Long featureId;
/** 权限编码 **/
private String featureCode;
}

View File

@ -0,0 +1,30 @@
package cn.axzo.tyr.client.model.req;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PageRoleReq {
private List<Long> roleIds;
private Boolean needPermission;
private Boolean needRoleGroup;
private Integer page;
private Integer pageSize;
/**
* 排序使用示例createAt__DESC
*/
private List<String> sort;
}

View File

@ -0,0 +1,39 @@
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 javax.validation.constraints.NotNull;
import java.util.List;
/**
* 权限校验请求
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/9 14:17
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PermissionCheckReq {
@NotNull(message = "人员ID不能为空")
private Long personId;
@NotEmpty(message = "权限code不能为空")
private List<String> featureCodes;
@NotNull(message = "单位ID不能为空")
private Long ouId;
@NotNull(message = "租户ID不能为空")
private Long workspaceId;
/** 登录端 **/
private String terminal;
}

View File

@ -0,0 +1,36 @@
package cn.axzo.tyr.client.model.req;
import cn.axzo.tyr.client.model.base.WorkspaceOUPair;
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;
/**
* 权限查询请求
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/7 16:23
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PermissionQueryReq {
@NotNull(message = "人员ID不能为空")
private Long personId;
@NotEmpty(message = "单位标识对不能为空")
private List<WorkspaceOUPair> workspaceOUPairs;
private String terminal;
private List<String> featureCodes;
}

View File

@ -44,4 +44,6 @@ public class QuerySaasRoleGroupReq {
* 被那些角色使用到的分组
*/
private List<Long> roleIds;
private Long parentId;
}

View File

@ -68,6 +68,26 @@ public class QuerySaasRoleReq {
*/
private Boolean includeSpecialRole;
/**
* '是否显示'
*/
private Boolean isDisplay;
/**
* '是否启用'
*/
private Boolean enabled;
/**
* 角色类型common 自定义角色 admin管理员 init标准角色
*/
private List<String> roleTypesNotIn;
/**
* 产品单位类型
* 1:总包 2:建设单位 3:监理单位 4:劳务分包 5:专业分包 6:OMS通用 7:企业通用 8:企业内班组 9:项目内班组
*/
private Integer productUnitType;
public QuerySaasRoleReq buildDefault() {
if (this.workspaceId == null) {
this.workspaceId = new ArrayList<>();

View File

@ -0,0 +1,32 @@
package cn.axzo.tyr.client.model.req;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 功能资源同步请求
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/7 11:31
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ResourceSyncReq {
/** 同步资源ID **/
@NotEmpty(message = "要同步的资源ID不能为空")
private List<Long> ids;
/** 操作人personId **/
@NotNull(message = "操作人ID不能为空")
private Long operatorId;
}

View File

@ -0,0 +1,54 @@
package cn.axzo.tyr.client.model.req;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TreeRoleReq {
private String workspaceTypeCode;
private Boolean needRole;
private Integer workspaceType;
/**
* '是否显示'
*/
private Boolean isDisplay;
/**
* 项目部id(不传或者传-1查询的是标准分组)
*/
private List<Long> workspaceIds;
/**
* 单位id(不传或者传-1查询的是标准分组)
*/
private List<Long> ouIds;
/**
* 会转成workspaceTypeCode去过滤根节点
* NT_OMS_WEB -> 6
* NT_CMS_WEB_GENERAL -> 1,2
* NT_CMP_APP_GENERAL -> 1,2
*/
private String terminal;
/**
* '是否启用'
*/
private Boolean enabled;
/**
* 角色类型common 普通角色 super_admin超级管理员(禁止删除) admin子管理员(禁止删除) init初始化内置角色
*/
private List<String> roleTypes;
}

View File

@ -0,0 +1,27 @@
package cn.axzo.tyr.client.model.req;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UpdateRoleGroupOffsetReq {
/**
* 角色分组id
*/
@NotNull(message = "id不能为空")
private Long id;
/**
* 偏移量:向上移就是负数例如上移一位-1向下移就是正数例如下移一位1
*/
@NotNull(message = "offset不能为空")
private Integer offset;
}

View File

@ -0,0 +1,27 @@
package cn.axzo.tyr.client.model.req;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UpdateRoleOffsetReq {
/**
* 角色id
*/
@NotNull(message = "id不能为空")
private Long id;
/**
* 偏移量:向上移就是负数例如上移一位-1向下移就是正数例如下移一位1
*/
@NotNull(message = "offset不能为空")
private Integer offset;
}

View File

@ -0,0 +1,37 @@
package cn.axzo.tyr.client.model.res;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 通用字典响应
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/3/26 17:04
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CommonDictResp {
private Long id;
/**
* 业务域
*/
private String scope;
/**
* 字典编码
*/
private String dictCode;
/**
* 字典值
*/
private String dictValue;
}

View File

@ -0,0 +1,139 @@
package cn.axzo.tyr.client.model.res;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.io.Serializable;
import java.util.Date;
/**
* 功能资源DTO
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/3 10:34
*/
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class FeatureResourceDTO implements Serializable {
private static final long serialVersionUID = 1L;
/** 主键ID **/
private Long id;
/**
* 资源编码-权限码
*/
private String featureCode;
/**
* 资源名称
*/
private String featureName;
/**
* 资源类型1-菜单 2-页面 3-应用入口 4-组件
*/
private Integer featureType;
/**
* 资源所属端
*/
private String terminal;
/**
* 组件细分类型 1-跳转子页面 2-跳转公共组件 3-弹出窗口 4-下拉项 5-操作按钮 6-数据卡片 7-站外跳转
*/
private Integer componentType;
/**
* 上级资源ID
*/
private Long parentId;
/**
* 资源ID层级路径 逗号分隔
*/
private String path;
/**
* 展示顺序
*/
private Integer displayOrder;
/**
* 资源状态 0-隐藏 1-展示
*/
private Integer status;
/**
* 资源图标
*/
private String icon;
/**
* 跳转类型 1-站内跳转 2-站外跳转
*/
private Integer redirectType;
/**
* 资源跳转URI
*/
private String linkUrl;
/**
* 路由类型1-PC 2-小程序 3-原生
*/
private Integer linkType;
/**
* APP适配参数
*/
private String linkExt;
/**
* 小程序id
*/
private Integer appItemId;
/**
* 资源同步版本
*/
private Integer syncVersion;
/**
* 扩展字段
*/
private String extra;
/**
* 授权类型0-全部角色 1-指定角色
*/
private Integer authType;
/**
* 子级鉴权类型 0-不鉴权1-鉴权
*/
private Integer subAuthType;
/** 创建时间 **/
private Date createAt;
/** 更新时间 **/
private Date updateAt;
/**
* 创建人
*/
private Long createBy;
/**
* 更新人
*/
private Long updateBy;
}

View File

@ -0,0 +1,63 @@
package cn.axzo.tyr.client.model.res;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class FeatureResourceDetailResp {
private Long id;
/** 上级ID **/
private Long parentId;
/** 资源名称 **/
private String featureName;
/** 资源类型 1-菜单 2-页面 3-应用入口 4-组件 **/
private Integer featureType;
/** 资源编码 **/
private String featureCode;
/** 图标 **/
private String icon;
/** 状态 0-隐藏 1-显示 **/
private Integer status;
/*- for page -*/
/** 跳转类型 1-站内跳转 2-站外跳转 **/
private Integer redirectType;
/** 路由地址 **/
private String linkUrl;
/** 授权类型 0-全部角色 1-指定角色 **/
private Integer authType;
/** 链接类型 1-PC 2-小程序 3-APP **/
private Integer linkType;
/** APP扩展适配参数 **/
private String linkExt;
/** 小程序ID **/
private Long appItemId;
/** 页面组件 **/
private List<FeatureResourceTreeNode> components;
private List<ResourceRolePermissionResp> rolePermissions;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class ResourceRolePermissionResp {
private Long roleId;
private List<String> featureCode;
}
}

View File

@ -0,0 +1,49 @@
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.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.util.List;
/**
* 功能资源树形节点
* 全属性 复用需要注意
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/3 17:00
*/
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class FeatureResourceTreeNode extends FeatureResourceDTO implements IBaseTree<FeatureResourceTreeNode, Long> {
private List<FeatureResourceTreeNode> children;
@JsonIgnore
@Override
public Long getNodeCode() {
return super.getId();
}
@JsonIgnore
@Override
public Long getParentNodeCode() {
return super.getParentId();
}
@JsonIgnore
@Override
public List<FeatureResourceTreeNode> getNodeChildren() {
return this.children;
}
@Override
public void setNodeChildren(List<FeatureResourceTreeNode> nodeChildren) {
this.children = nodeChildren;
}
}

View File

@ -0,0 +1,24 @@
package cn.axzo.tyr.client.model.res;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class FeatureRoleRelationResp {
/** 功能Id **/
private Long featureId;
/** 应用的角色Id列表 **/
private List<Long> roleIds;
/** 授权类型 0-全部角色 1-指定角色 **/
private Integer authType;
}

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/4/7 15:20
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class NavTreeResp implements IBaseTree<NavTreeResp, Long> {
//APP侧需要扩展返回必要的数据
/** 资源ID **/
private Long id;
/** 资源编码 **/
private String featureCode;
/** 资源名称 **/
private String featureName;
/** 资源类型 **/
private Integer featureType;
/** 上级ID **/
private Long parentId;
/** 页面路由 **/
private String linkUrl;
/** 图标 **/
private String icon;
/** 子级 **/
private List<NavTreeResp> children;
@JsonIgnore
@Override
public Long getNodeCode() {
return id;
}
@JsonIgnore
@Override
public Long getParentNodeCode() {
return parentId;
}
@JsonIgnore
@Override
public List<NavTreeResp> getNodeChildren() {
return children;
}
@Override
public void setNodeChildren(List<NavTreeResp> nodeChildren) {
this.children = nodeChildren;
}
}

View File

@ -0,0 +1,49 @@
package cn.axzo.tyr.client.model.res;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RoleTreeRes {
/**
* id
*/
private Long id;
/**
* 根节点的code
*/
private String workspaceTypeCode;
private String workspaceType;
/**
* 名字
*/
private String name;
/**
* 类型ROLE_GROUP(分组)ROLE(角色)ROOT(根节点)
*/
private String type;
/**
* 是否显示
*/
private Boolean isDisplay;
private List<RoleTreeRes> children;
/**
* id跟type拼接因为前端组件所有节点的id不能重复
*/
private String idStr;
}

View File

@ -26,6 +26,15 @@ public class RoleWithUserRes {
/** 角色下用户 **/
private List<UserVO> users;
/**
* '是否显示'
*/
private Boolean isDisplay;
/**
* '是否启用'
*/
private Boolean enabled;
@Data
public static class UserVO {

View File

@ -0,0 +1,20 @@
package cn.axzo.tyr.client.model.res;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SaasPermissionRes {
private Long id;
/**
* 资源编码-权限码
*/
private String featureCode;
}

View File

@ -0,0 +1,60 @@
package cn.axzo.tyr.client.model.res;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SaasRoleGroupRes {
private Long id;
/**
* 工作台类型字典code
*/
private String workspaceTypeCode;
/**
* 单位类型字典code
*/
private String ouTypeCode;
/**
* 名称
*/
private String name;
/**
* 所属工作台id
*/
private Long workspaceId;
/**
* 所属单位id
*/
private Long ouId;
/**
* 排序
*/
private Integer sort;
/**
* 分组CODE
*/
private String code;
/**
* 分类CODE, 用于代班长小组长的权限分类
*/
private String categoryCode;
/**
* 上级分组id
*/
private Long parentId;
}

View File

@ -0,0 +1,110 @@
package cn.axzo.tyr.client.model.res;
import cn.axzo.tyr.client.model.vo.SaasPermissionGroupVO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SaasRoleRes {
private Long id;
/**
* 角色名称
*/
private String name;
/**
* 角色描述
*/
private String description;
/**
* 角色类型common 普通角色 super_admin超级管理员(禁止删除) admin子管理员(禁止删除) init初始化内置角色
*/
private String roleType;
private Long workspaceId;
/**
* 废弃
*/
@Deprecated
private Integer workspaceType;
private Long ownerOuId;
/**
* 产品单位类型
* 1:总包 2:建设单位 3:监理单位 4:劳务分包 5:专业分包 6:OMS通用 7:企业通用 8:企业内班组 9:项目内班组
*/
private Integer productUnitType;
/**
* 创建者
*/
private Long createBy;
/**
* 更新者
*/
private Long updateBy;
/**
* 来源的模版角色id(1052上线后可删除)
*/
@Deprecated
private Long fromPreRoleId;
/**
* 适用单位类型 1:总包 2:建设单位 4:监理单位 8:劳务分包 16:专业分包 0都可以用 只会挂在最末级
* (1052上线后可删除)
*/
@Deprecated
private Long fitOuTypeBit;
/**
* '角色编码'
*/
private String roleCode;
/**
* '是否显示'
*/
private Boolean isDisplay;
/**
* '是否启用'
*/
private Boolean enabled;
/**
* 排序
*/
private Integer sort;
/**
* 是否删除
*/
private Long isDelete;
private Date createAt;
private Date updateAt;
/**
* 角色组
*/
private List<SaasRoleGroupRes> saasRoleGroups;
/**
* 角色权限
*/
private List<SaasPermissionRes> saasPermissions;
}

View File

@ -0,0 +1,32 @@
package cn.axzo.tyr.client.model.roleuser.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author likunpeng
* @version 1.0
* @date 2024/4/3
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class GetUserAutoOwnRoleResp {
public static final GetUserAutoOwnRoleResp EMPTY = GetUserAutoOwnRoleResp.builder().build();
/**
* 角色ID
*/
private Long roleId;
/**
* 资源ID列表
*/
private List<Long> featureIds;
}

View File

@ -84,4 +84,14 @@ public class SaasRoleUserDTO {
* 资源Id
*/
private Long resourceId;
/**
* 是否展示角色
*/
private Boolean displayRole;
/**
* '是否启用'
*/
private Boolean enabled;
}

View File

@ -0,0 +1,69 @@
package cn.axzo.tyr.client.model.roleuser.req;
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.Set;
/**
* @author likunpeng
* @date 2024/4/2
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class AutoOwnRoleUserReq {
/**
* 工作台id
*/
@NotNull
private Long workspaceId;
/**
* 单位id
*/
@NotNull
private Long ouId;
/**
* 身份id
*/
@NotNull
private Long identityId;
/**
* 自然人id
*/
@NotNull
private Long personId;
/**
* 身份类型
*/
@NotNull
private IdentityType identityType;
/**
* 操作人
*/
@NotNull
private Long operatorId;
/**
* 自定义角色ID
*/
@NotNull
private Long roleId;
/**
* 资源ID列表
*/
private Set<Long> featureIds;
}

View File

@ -0,0 +1,38 @@
package cn.axzo.tyr.client.model.roleuser.req;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
/**
* @author likunpeng
* @date 2024/4/2
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class GetUserAutoOwnRoleReq {
/**
* 工作台id
*/
@NotNull
private Long workspaceId;
/**
* 单位id
*/
@NotNull
private Long ouId;
/**
* 自然人id
*/
@NotNull
private Long personId;
}

View File

@ -0,0 +1,36 @@
package cn.axzo.tyr.client.model.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DeleteRoleVO {
/**
* 待删除角色集合
*/
@NotEmpty(message = "roleIds不能为空")
private List<Long> roleIds;
/**
* 待删除角色所属workSpaceId 历史接口需要
*/
private Long workSpaceId;
/**
* 待删除角色所属单位ID 历史接口需要
*/
private Long outId;
/**
* 历史接口对已经有user绑定到role有进行check不能删除
*/
private boolean needUsedCheck;
}

View File

@ -66,4 +66,8 @@ public class SaasRoleGroupVO {
private Date updateAt;
/**
* 上级分组id
*/
private Long parentId;
}

View File

@ -64,6 +64,26 @@ public class SaasRoleVO {
private Date createAt;
private Date updateAt;
/**
* '角色编码'
*/
private String roleCode;
/**
* '是否显示'
*/
private Boolean isDisplay;
/**
* '是否启用'
*/
private Boolean enabled;
/**
* 排序
*/
private Integer sort;
/**
* 获取角色对应所用的菜单不管例外
*

View File

@ -1,14 +1,18 @@
package cn.axzo.tyr.client.model.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Set;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SaveOrUpdateRoleVO {
/**
@ -42,10 +46,14 @@ public class SaveOrUpdateRoleVO {
/**
* 角色分组
*/
@NotEmpty
@Valid
private List<GroupInfoVO> groupTree;
/**
* 产品单位类型
* 1:总包 2:建设单位 3:监理单位 4:劳务分包 5:专业分包 6:OMS通用 7:企业通用 8:企业内班组 9:项目内班组
*/
private Integer productUnitType;
private String permissionGroupName;
private String permissionGroupDescription;
@ -57,23 +65,42 @@ public class SaveOrUpdateRoleVO {
/**
* 选中的权限点id
* cms再使用后面都会切到使用permissionIds
*/
@NotNull(message = "权限点ID不能为空")
@Deprecated
private List<Long> selectedPPIds;
/**
* 新的oms权限
*/
private Set<Long> permissionIds;
/**
* '角色编码'
*/
private String roleCode;
/**
* '是否显示'
*/
private Boolean isDisplay;
/**
* '是否启用'
*/
private Boolean enabled;
private Integer sort;
@Data
public static class GroupInfoVO {
/**
* 角色分组id
*/
@NotNull(message = "角色分组ID不能为空")
private Long id;
/**
* 项目部类型字典code
*/
@NotNull(message = "workspaceTypeCode不能为空")
private String workspaceTypeCode;
}
}

View File

@ -101,6 +101,26 @@
<artifactId>maokai-api</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.pokonyan</groupId>
<artifactId>pokonyan</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.0.202</version>
<scope>test</scope>
</dependency>
<!-- 内嵌redis server-->
<dependency>
<groupId>com.github.caryyu</groupId>
<artifactId>spring-embedded-redis-server</artifactId>
<version>1.1</version>
<type>pom</type>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -1,55 +1,44 @@
package cn.axzo.tyr.server;
import cn.axzo.tyr.server.job.CMSRoleJobHandler;
import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import cn.axzo.tyr.server.job.OMSRoleJobHandler;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.EnableAsync;
@Slf4j
@EnableAsync
@EnableCaching
@EnableDiscoveryClient
//@EnableFeignClients
@MapperScan(value = {"cn.axzo.tyr.server.repository.mapper"})
@SpringBootApplication(scanBasePackages = "cn.axzo")
public class TyrApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(TyrApplication.class, args);
Environment env = run.getEnvironment();
log.info(
"--------------------------------------------------------------------------------------------------------------------\n" +
"Application 【{}】 is running on 【{}】 environment!\n" +
"Api Local: \thttp://127.0.0.1:{}\n" +
"Mysql: \t{}\t username:{}\n" +
"Redis: \t{}:{}\t database:{}\n" +
"RabbitMQ: \t{}\t username:{}",
env.getProperty("spring.application.name"),
env.getProperty("spring.profiles.active"),
env.getProperty("server.port"),
env.getProperty("spring.datasource.url"),
env.getProperty("spring.datasource.username"),
env.getProperty("spring.redis.host"),
env.getProperty("spring.redis.port"),
env.getProperty("spring.redis.database"),
env.getProperty("spring.rabbitmq.addresses"),
env.getProperty("spring.rabbitmq.username") +
"\n----------------------------------------------------------");
// try {
// test();
// } catch (Exception e) {
// e.printStackTrace();
// }
"--------------------------------------------------------------------------------------------------------------------\n" +
"Application 【{}】 is running on 【{}】 environment!\n" +
"Api Local: \thttp://127.0.0.1:{}\n" +
"Mysql: \t{}\t username:{}\n" +
"Redis: \t{}:{}\t database:{}\n" +
"RabbitMQ: \t{}\t username:{}",
env.getProperty("spring.application.name"),
env.getProperty("spring.profiles.active"),
env.getProperty("server.port"),
env.getProperty("spring.datasource.url"),
env.getProperty("spring.datasource.username"),
env.getProperty("spring.redis.host"),
env.getProperty("spring.redis.port"),
env.getProperty("spring.redis.database"),
env.getProperty("spring.rabbitmq.addresses"),
env.getProperty("spring.rabbitmq.username") +
"\n----------------------------------------------------------");
}
// public static void test() throws Exception {
// CMSRoleJobHandler executor = SpringUtil.getBean(CMSRoleJobHandler.class);
// executor.execute(null);
// }
}

View File

@ -0,0 +1,14 @@
package cn.axzo.tyr.server.common.constants;
/**
* 缓存常量
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/8 17:50
*/
public class CacheConstant {
/** 免授权缓存KEY **/
public static final String KEY_AUTH_FREE = "tyr:auth-free";
}

View File

@ -22,7 +22,7 @@ public class ExecutorConfig {
* 权限定制线程池
* @return
*/
@Bean
@Bean("authExecutor")
public ExecutorService authExecutor() {
new ThreadPoolExecutor.CallerRunsPolicy();
int coreSize = 5;
@ -43,7 +43,7 @@ public class ExecutorConfig {
* 用户角色清理任务线程池
* @return
*/
@Bean
@Bean("userRoleCleanExecutor")
public ExecutorService userRoleCleanExecutor() {
new ThreadPoolExecutor.CallerRunsPolicy();
int coreSize = 5;
@ -52,4 +52,18 @@ public class ExecutorConfig {
executor.prestartCoreThread();
return executor;
}
/**
* 异步处理线程池 - 不需要等待处理结束
* @return
*/
@Bean("asyncExecutor")
public ExecutorService asyncExecutor() {
new ThreadPoolExecutor.CallerRunsPolicy();
int coreSize = 5;
ThreadPoolExecutor executor = new ThreadPoolExecutor(coreSize, 10, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100), new NamedThreadFactory("sync-task-", false), new ThreadPoolExecutor.CallerRunsPolicy());
executor.prestartCoreThread();
return executor;
}
}

View File

@ -22,7 +22,7 @@ import java.util.Objects;
**/
@Component
@Slf4j
@Profile({"dev", "local"})
@Profile({"dev", "test", "local", "pre", "live"})
public class FeignConfig implements RequestInterceptor, EnvironmentAware {
private Environment environment;
@Value("${msgCenterEnvUrl:http://dev-app.axzo.cn/msg-center}")
@ -61,6 +61,12 @@ public class FeignConfig implements RequestInterceptor, EnvironmentAware {
if(Objects.equals(profile, "test") && url.contains("dev-app.axzo.cn")) {
url = url.replace("dev-app", "test-api");
}
if(Objects.equals(profile, "pre") && url.contains("dev-app.axzo.cn")) {
url = url.replace("dev-app", "pre-api");
}
if(Objects.equals(profile, "live") && url.contains("dev-app.axzo.cn")) {
url = url.replace("dev-app", "live-api");
}
requestTemplate.target(url);
Field field = ReflectUtil.getField(target.getClass(), "url");
field.setAccessible(true);

View File

@ -17,15 +17,18 @@ import static cn.axzo.tyr.server.config.GlobalConfig.FeignClientConstant.*;
*/
@Configuration
@EnableFeignClients(basePackages = {
WORKFLOW_ENGINE
WORKFLOW_ENGINE,
INNER_FEIGN
})
public class GlobalConfig {
/**
* 第三方Feign
*/
public class FeignClientConstant {
public static class FeignClientConstant {
public static final String WORKFLOW_ENGINE = "cn.axzo.workflow.client.feign.bpmn";
public static final String INNER_FEIGN = "cn.axzo.tyr.server.inner.feign";
}
/**

View File

@ -0,0 +1,151 @@
package cn.axzo.tyr.server.controller;
import cn.axzo.tyr.client.model.req.CommonDictQueryReq;
import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq;
import cn.axzo.tyr.client.model.res.CommonDictResp;
import cn.axzo.tyr.client.model.res.SaasRoleRes;
import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO;
import cn.axzo.tyr.server.repository.dao.SaasRoleGroupRelationDao;
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.service.RoleService;
import cn.axzo.tyr.server.service.SaasCommonDictService;
import cn.axzo.tyr.server.service.SaasRoleGroupService;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@RestController
@RequiredArgsConstructor
public class PrivateController {
@Autowired
private SaasCommonDictService saasCommonDictService;
@Autowired
private SaasRoleGroupService saasRoleGroupService;
@Autowired
private SaasRoleGroupRelationDao saasRoleGroupRelationDao;
@Autowired
private RoleService roleService;
/**
* 统一层级的roleGroup按照id升序sort从1递增
* @return
* @throws Exception
*/
@PostMapping("/api/private/role/group/sort/refresh")
public Object refreshRoleGroupSort() {
List<CommonDictResp> commonDicts = saasCommonDictService.query(CommonDictQueryReq.builder()
.scope("role")
.build());
if (CollectionUtils.isEmpty(commonDicts)) {
return "ok";
}
Map<String, List<SaasRoleGroupVO>> roleGroups = saasRoleGroupService.getList(QuerySaasRoleGroupReq.builder()
.workspaceTypeCode(Lists.transform(commonDicts, CommonDictResp::getDictCode))
.build())
.stream()
.collect(Collectors.groupingBy(SaasRoleGroupVO::getWorkspaceTypeCode));
roleGroups.entrySet()
.forEach(e -> {
List<SaasRoleGroupVO> saasRoleGroups = e.getValue().stream()
.sorted(Comparator.comparing(SaasRoleGroupVO::getId))
.collect(Collectors.toList());
List<SaasRoleGroup> update = IntStream.range(0, saasRoleGroups.size())
.mapToObj(i -> {
SaasRoleGroupVO saasRoleGroup = saasRoleGroups.get(i);
SaasRoleGroup result = SaasRoleGroup.builder()
.sort(i + 1)
.build();
result.setId(saasRoleGroup.getId());
return result;
})
.collect(Collectors.toList());
saasRoleGroupService.updateBatchById(update);
});
return "ok";
}
/**
* 刷新role的sort
* @return
* @throws Exception
*/
@PostMapping("/api/private/role/sort/refresh")
public Object refreshRoleSort() {
List<CommonDictResp> commonDicts = saasCommonDictService.query(CommonDictQueryReq.builder()
.scope("role")
.build());
if (CollectionUtils.isEmpty(commonDicts)) {
return "ok";
}
List<SaasRoleGroupVO> roleGroups = saasRoleGroupService.getList(QuerySaasRoleGroupReq.builder()
.workspaceTypeCode(Lists.transform(commonDicts, CommonDictResp::getDictCode))
.build());
List<Long> roleGroupIds = roleGroups.stream().map(SaasRoleGroupVO::getId).collect(Collectors.toList());
if (CollectionUtils.isEmpty(roleGroupIds)) {
return "ok";
}
List<SaasRoleGroupRelation> saasRoleGroupRelations = saasRoleGroupRelationDao.getByGroupIds(roleGroupIds);
if (CollectionUtils.isEmpty(saasRoleGroupRelations)) {
return "ok";
}
Map<Long, SaasRoleRes> saasRoles = roleService.list(RoleService.ListSaasRoleParam.builder()
.roleIds(Lists.transform(saasRoleGroupRelations, SaasRoleGroupRelation::getRoleId))
.build())
.stream()
.collect(Collectors.toMap(SaasRoleRes::getId, Function.identity()));
List<SaasRole> updateSaasRoles = saasRoleGroupRelations.stream()
.collect(Collectors.groupingBy(SaasRoleGroupRelation::getSaasRoleGroupId))
.values()
.stream()
.map(e -> {
List<SaasRoleRes> sortedRoles = e.stream()
.map(rr -> saasRoles.get(rr.getRoleId()))
.filter(Objects::nonNull)
.sorted(Comparator.comparing(SaasRoleRes::getId))
.collect(Collectors.toList());
List<SaasRole> update = IntStream.range(0, sortedRoles.size())
.mapToObj(i -> {
SaasRoleRes saasRole = sortedRoles.get(i);
SaasRole result = new SaasRole();
result.setSort(i + 1);
result.setId(saasRole.getId());
return result;
})
.collect(Collectors.toList());
return update;
})
.flatMap(Collection::stream)
.collect(Collectors.toList());
roleService.updateBatchById(updateSaasRoles);
return "ok";
}
}

View File

@ -0,0 +1,32 @@
package cn.axzo.tyr.server.controller.dict;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.feign.SaasCommonDictApi;
import cn.axzo.tyr.client.model.req.CommonDictQueryReq;
import cn.axzo.tyr.client.model.res.CommonDictResp;
import cn.axzo.tyr.server.service.SaasCommonDictService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 同用字典服务接口
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/3/26 17:37
*/
@Slf4j
@RestController
@RequiredArgsConstructor
public class SaasCommonDictController implements SaasCommonDictApi {
private final SaasCommonDictService commonDictService;
@Override
public ApiResult<List<CommonDictResp>> query(CommonDictQueryReq req) {
return ApiResult.ok(commonDictService.query(req));
}
}

View File

@ -0,0 +1,88 @@
package cn.axzo.tyr.server.controller.permission;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.feign.FeatureResourceApi;
import cn.axzo.tyr.client.model.req.FeatureResourceTreeSaveReq;
import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq;
import cn.axzo.tyr.client.model.req.ResourceSyncReq;
import cn.axzo.tyr.client.model.res.FeatureResourceDetailResp;
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
import cn.axzo.tyr.server.service.FeatureResourceSyncService;
import cn.axzo.tyr.server.service.SaasFeatureResourceService;
import cn.hutool.core.collection.CollectionUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 功能资源接口实现
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/3 10:06
*/
@Slf4j
@RestController
@RequiredArgsConstructor
public class FeatureResourceController implements FeatureResourceApi {
private final FeatureResourceSyncService featureResourceSyncService;
private final SaasFeatureResourceService featureResourceService;
@Override
public ApiResult<List<FeatureResourceTreeNode>> getSyncTreeById(Long id) {
return ApiResult.ok(featureResourceSyncService.getSyncTreeById(id));
}
@Override
public ApiResult<Void> syncFromBase(ResourceSyncReq req) {
if (CollectionUtil.isEmpty(req.getIds())) {
log.warn("no ids to sync from base env");
return ApiResult.ok();
}
featureResourceSyncService.syncFromBase(req);
return ApiResult.ok();
}
@Override
public ApiResult<Long> saveMenu(FeatureResourceTreeSaveReq req) {
log.info("save feature resource req : " + req.toString());
Long featureId = featureResourceService.saveOrUpdateMenu(req);
log.info("save feature resource resp : " + featureId.toString());
return ApiResult.ok(featureId);
}
@Override
public ApiResult<Void> deleteFeatureResource(Long featureId, Long operatorId) {
log.info("deleteFeatureResource featureId : {}, operatorId : {}", featureId, operatorId);
featureResourceService.deleteMenuFeature(featureId, operatorId);
return ApiResult.ok();
}
@Override
public ApiResult<Void> reorderFeatureTree(Long featureId, Integer offset) {
log.info("reorderFeatureTree featureId : {}, offset : {}", featureId, offset);
featureResourceService.reorderMenuFeature(featureId, offset);
return ApiResult.ok();
}
@Override
public ApiResult<FeatureResourceTreeNode> detail(Long featureId) {
// 详情只查子集组件
return ApiResult.ok(featureResourceService.getTreeFeatureDescendant(featureId, null));
}
@Override
public ApiResult<List<FeatureResourceTreeNode>> getTree(GetFeatureResourceTreeReq req) {
return ApiResult.ok(featureResourceService.getTree(req));
}
@Override
public ApiResult<List<FeatureResourceTreeNode>> getBaseTree(GetFeatureResourceTreeReq req) {
return ApiResult.ok(featureResourceSyncService.getBaseTree(req));
}
}

View File

@ -0,0 +1,45 @@
package cn.axzo.tyr.server.controller.permission;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.feign.PermissionQueryApi;
import cn.axzo.tyr.client.model.req.NavTreeReq;
import cn.axzo.tyr.client.model.req.PagePermissionReq;
import cn.axzo.tyr.client.model.req.PagePermissionResp;
import cn.axzo.tyr.client.model.req.PermissionCheckReq;
import cn.axzo.tyr.client.model.res.NavTreeResp;
import cn.axzo.tyr.server.service.PermissionQueryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 权限接口实现
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/7 17:29
*/
@Slf4j
@RestController
@RequiredArgsConstructor
public class PermissionQueryController implements PermissionQueryApi {
private final PermissionQueryService permissionService;
@Override
public ApiResult<List<NavTreeResp>> getNavTree(NavTreeReq req) {
return ApiResult.ok(permissionService.getNavTree(req));
}
@Override
public ApiResult<List<PagePermissionResp>> getPagePermission(PagePermissionReq req) {
return ApiResult.ok(permissionService.getPagePermission(req));
}
@Override
public ApiResult<Boolean> hasPermission(PermissionCheckReq req) {
return ApiResult.ok(permissionService.hasPermission(req));
}
}

View File

@ -1,35 +1,68 @@
package cn.axzo.tyr.server.controller.role;
import cn.axzo.basics.common.exception.ServiceException;
import cn.axzo.framework.domain.web.result.ApiListResult;
import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.feign.TyrSaasRoleApi;
import cn.axzo.tyr.client.model.enums.DictWorkSpaceTypeEnum;
import cn.axzo.tyr.client.model.req.ChangeGroupLeaderRoleReq;
import cn.axzo.tyr.client.model.req.CommonDictQueryReq;
import cn.axzo.tyr.client.model.req.FeatureRoleRelationReq;
import cn.axzo.tyr.client.model.req.PageRoleReq;
import cn.axzo.tyr.client.model.req.QueryByIdentityIdTypeReq;
import cn.axzo.tyr.client.model.req.QueryRoleByNameReq;
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.req.ChangeGroupLeaderRoleReq;
import cn.axzo.tyr.client.model.req.TreeRoleReq;
import cn.axzo.tyr.client.model.req.UpdateRoleOffsetReq;
import cn.axzo.tyr.client.model.res.CommonDictResp;
import cn.axzo.tyr.client.model.res.FeatureRoleRelationResp;
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.RoleTreeRes;
import cn.axzo.tyr.client.model.res.RoleWithUserRes;
import cn.axzo.tyr.client.model.res.SaasRoleRes;
import cn.axzo.tyr.client.model.vo.DeleteRoleVO;
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.model.PermissionCacheKey;
import cn.axzo.tyr.server.repository.dao.SaasRoleGroupRelationDao;
import cn.axzo.tyr.server.repository.dao.SaasRoleUserRelationDao;
import cn.axzo.tyr.server.repository.entity.SaasRole;
import cn.axzo.tyr.server.repository.entity.SaasRoleGroupRelation;
import cn.axzo.tyr.server.service.PermissionCacheService;
import cn.axzo.tyr.server.service.RoleService;
import cn.axzo.tyr.server.service.SaasCommonDictService;
import cn.axzo.tyr.server.service.SaasRoleGroupRelationService;
import cn.axzo.tyr.server.service.SaasRoleGroupService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 权限
@ -49,6 +82,33 @@ public class SaasRoleController implements TyrSaasRoleApi {
PermissionCacheService permissionCacheService;
@Autowired
private SaasRoleUserRelationDao saasRoleUserRelationDao;
@Autowired
private SaasCommonDictService saasCommonDictService;
@Autowired
private SaasRoleGroupService saasRoleGroupService;
@Autowired
private SaasRoleGroupRelationDao saasRoleGroupRelationDao;
@Autowired
private SaasRoleGroupRelationService saasRoleGroupRelationService;
/**
* 角色组里面parentId = 0
*/
private static final Long ROOT_ROLE_GROUP_PARENT_ID = 0L;
private static final String ROOT_TYPE = "ROOT";
private static final String ROLE_TYPE = "ROLE";
private static final String ROLE_GROUP_TYPE = "ROLE_GROUP";
/**
* 没有统一维护的地方
*/
private static final Map<String, List<String>> TERMINAL_WORKSPACE_CODES = Maps.newHashMap();
static {
TERMINAL_WORKSPACE_CODES.put("NT_OMS_WEB", Lists.newArrayList("6"));
TERMINAL_WORKSPACE_CODES.put("NT_CMS_WEB_GENERAL", Lists.newArrayList("1", "2"));
TERMINAL_WORKSPACE_CODES.put("NT_CMP_APP_GENERAL", Lists.newArrayList("1", "2"));
}
@Override
public ApiResult<Long> saveOrUpdate(SaveOrUpdateRoleVO saveOrUpdateRole) {
@ -57,6 +117,17 @@ public class SaasRoleController implements TyrSaasRoleApi {
return ApiResult.ok(result);
}
@Override
public ApiResult<Long> saveOrUpdateFeatureRoleRelation(FeatureRoleRelationReq saasFeatureRoleRelationReq) {
roleService.saveOrUpdateFeatureRoleRelation(saasFeatureRoleRelationReq.getRoleSettings(), saasFeatureRoleRelationReq.getOperatorId());
return ApiResult.ok();
}
@Override
public ApiResult<FeatureRoleRelationResp> queryFeatureRoleRelation(Long featureId) {
return ApiResult.ok(roleService.queryFeatureRoleRelation(featureId));
}
@Override
public ApiResult<SaasRoleVO> getById(Long id) {
QuerySaasRoleReq query = QuerySaasRoleReq.builder()
@ -77,13 +148,21 @@ public class SaasRoleController implements TyrSaasRoleApi {
@Override
public ApiResult<Void> deleteRole(List<Long> roleIds, Long workSpaceId, Long outId) {
roleService.deleteRole(roleIds, workSpaceId, outId);
DeleteRoleVO deleteRoleParam = DeleteRoleVO.builder()
.roleIds(roleIds)
.workSpaceId(workSpaceId)
.outId(outId)
.needUsedCheck(true)
.build();
roleService.deleteRole(deleteRoleParam);
permissionCacheService.markTempDisable(PermissionCacheKey.builder().disableAll(true).build());
return ApiResult.ok();
}
@Override
public ApiResult<Void> delete(List<Long> roleIds) {
public ApiResult<Void> delete(DeleteRoleVO reqeust) {
roleService.deleteRole(reqeust);
permissionCacheService.markTempDisable(PermissionCacheKey.builder().disableAll(true).build());
return ApiResult.ok();
}
@ -133,4 +212,249 @@ public class SaasRoleController implements TyrSaasRoleApi {
roleService.changeGroupLeaderRole(reqs);
return ApiResult.ok();
}
@Override
public ApiListResult<RoleTreeRes> treeSaasRole(TreeRoleReq req) {
// 因为根节点在roleGroup里面没有都是workspaceTypeCode描述是放在字典表里
List<CommonDictResp> commonDicts = listRootRole(req);
List<RoleTreeRes> roots = commonDicts.stream()
.map(e -> RoleTreeRes.builder()
.id(e.getId())
.workspaceTypeCode(e.getDictCode())
.name(e.getDictValue())
.type(ROOT_TYPE)
.idStr(e.getId() + ":" + ROOT_TYPE)
.workspaceType(DictWorkSpaceTypeEnum.getByValueWorkspaceType(Integer.valueOf(e.getDictCode())).getValue())
.build())
.collect(Collectors.toList());
Map<String, List<RoleTreeRes>> roleGroups = listRoleGroupTree(commonDicts, req);
List<RoleTreeRes> result = roots.stream()
.peek(root -> root.setChildren(roleGroups.get(root.getWorkspaceTypeCode())))
.collect(Collectors.toList());
return ApiListResult.ok(result);
}
@Override
public ApiResult<Void> updateRoleOffset(UpdateRoleOffsetReq request) {
if (request.getOffset() != 1 && request.getOffset() != -1) {
throw new ServiceException("暂时只支持移动一个位置");
}
SaasRole saasRole = roleService.getById(request.getId());
if (saasRole == null) {
throw new ServiceException("角色信息不存在");
}
List<SaasRoleGroupRelation> saasRoleGroupRelations = saasRoleGroupRelationService.list(SaasRoleGroupRelationService.ListSaasRoleGroupRelationParam.builder()
.roleIds(Lists.newArrayList(saasRole.getId()))
.build());
if (CollectionUtils.isEmpty(saasRoleGroupRelations)) {
throw new ServiceException("角色分组信息不存在");
}
if (saasRoleGroupRelations.size() != 1) {
throw new ServiceException("角色分组信息不唯一,请检查异常");
}
List<SaasRoleGroupRelation> saasRoleGroupRelationAll = saasRoleGroupRelationService.list(SaasRoleGroupRelationService.ListSaasRoleGroupRelationParam.builder()
.saasRoleGroupIds(Lists.transform(saasRoleGroupRelations, SaasRoleGroupRelation::getSaasRoleGroupId))
.build());
List<SaasRoleRes> saasRoles = roleService.list(RoleService.ListSaasRoleParam.builder()
.roleIds(Lists.transform(saasRoleGroupRelationAll, SaasRoleGroupRelation::getRoleId))
.build())
.stream()
.sorted(Comparator.comparing(SaasRoleRes::getSort))
.collect(Collectors.toList());
SaasRoleRes exchangeRole = findExchangeRole(request, saasRoles);
if (exchangeRole == null) {
throw new ServiceException("未找到可以移动的位置");
}
SaasRole newSaasRole = new SaasRole();
newSaasRole.setId(saasRole.getId());
newSaasRole.setSort(exchangeRole.getSort());
roleService.updateById(newSaasRole);
SaasRole oldSaasRole = new SaasRole();
oldSaasRole.setId(exchangeRole.getId());
oldSaasRole.setSort(saasRole.getSort());
roleService.updateById(oldSaasRole);
return ApiResult.ok();
}
@Override
public ApiPageResult<SaasRoleRes> page(PageRoleReq request) {
RoleService.PageSaasRoleParam param = RoleService.PageSaasRoleParam.builder().build();
BeanUtils.copyProperties(request, param);
Page<SaasRoleRes> page = roleService.page(param);
return ApiPageResult.ok(page.getRecords(), page.getTotal(), (int) page.getCurrent(), (int) page.getSize());
}
/**
* 只支持移动一位
* @param request
* @param roles
* @return
*/
private SaasRoleRes findExchangeRole(UpdateRoleOffsetReq request,
List<SaasRoleRes> roles) {
List<Long> ids = roles.stream()
.map(SaasRoleRes::getId)
.collect(Collectors.toList());
int currentIndex = ids.indexOf(request.getId());
// 下移一位
if (request.getOffset() == 1) {
int exchangeIndex = currentIndex + 1;
if (roles.size() > exchangeIndex) {
return roles.get(exchangeIndex);
}
} else if (request.getOffset() == -1) {
if (currentIndex == 0) {
return null;
}
int exchangeIndex = currentIndex - 1;
return roles.get(exchangeIndex);
}
return null;
}
/**
* 查询角色
* Map<角色分组Id, List<RoleTreeRes>>
* @param roleGroups
* @param req
* @return
*/
private Map<Long, List<RoleTreeRes>> listRole(List<SaasRoleGroupVO> roleGroups,
TreeRoleReq req) {
List<Long> roleGroupIds = roleGroups.stream().map(SaasRoleGroupVO::getId).collect(Collectors.toList());
if (CollectionUtils.isEmpty(roleGroupIds) || BooleanUtils.isNotTrue(req.getNeedRole())) {
return Collections.emptyMap();
}
List<SaasRoleGroupRelation> saasRoleGroupRelations = saasRoleGroupRelationDao.getByGroupIds(roleGroupIds);
Map<Long, SaasRoleRes> saasRoles = roleService.list(RoleService.ListSaasRoleParam.builder()
.roleIds(Lists.transform(saasRoleGroupRelations, SaasRoleGroupRelation::getRoleId))
.isDisplay(req.getIsDisplay())
.workspaceType(req.getWorkspaceType())
.workspaceIds(req.getWorkspaceIds())
.ouIds(req.getOuIds())
.enabled(req.getEnabled())
.roleTypes(req.getRoleTypes())
.build())
.stream()
.collect(Collectors.toMap(SaasRoleRes::getId, Function.identity()));
return saasRoleGroupRelations.stream()
.collect(Collectors.groupingBy(SaasRoleGroupRelation::getSaasRoleGroupId))
.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()
.stream()
.map(value -> saasRoles.get(value.getRoleId()))
.filter(Objects::nonNull)
.sorted(Comparator.comparing(SaasRoleRes::getSort))
.map(this::toRoleTree)
.filter(Objects::nonNull)
.collect(Collectors.toList())));
}
private Map<String, List<RoleTreeRes>> listRoleGroupTree(List<CommonDictResp> commonDicts,
TreeRoleReq req) {
if (CollectionUtils.isEmpty(commonDicts)) {
return Collections.emptyMap();
}
List<SaasRoleGroupVO> roleGroups = saasRoleGroupService.getRoleGroupList(QuerySaasRoleGroupReq.builder()
.workspaceTypeCode(Lists.transform(commonDicts, CommonDictResp::getDictCode))
.workspaceIds(req.getWorkspaceIds())
.ouIds(req.getOuIds())
.build())
.stream()
.sorted(Comparator.comparing(e -> Optional.ofNullable(e.getSort()).orElse(1)))
.collect(Collectors.toList());
Map<Long, List<RoleTreeRes>> roles = listRole(roleGroups, req);
Map<String, List<RoleTreeRes>> rootRoleGroups = roleGroups.stream()
.filter(e -> Objects.equals(e.getParentId(), ROOT_ROLE_GROUP_PARENT_ID))
.collect(Collectors.groupingBy(SaasRoleGroupVO::getWorkspaceTypeCode,
LinkedHashMap::new,
Collectors.mapping(this::toRoleTree, Collectors.toList())));
rootRoleGroups.values().forEach(e -> e.forEach(root -> appendChildren(root, roleGroups, roles)));
return rootRoleGroups;
}
private RoleTreeRes toRoleTree(SaasRoleGroupVO roleGroup) {
return RoleTreeRes.builder()
.workspaceTypeCode(roleGroup.getWorkspaceTypeCode())
.id(roleGroup.getId())
.name(roleGroup.getName())
.type(ROLE_GROUP_TYPE)
.idStr(roleGroup.getId() + ":" + ROLE_GROUP_TYPE)
.build();
}
private RoleTreeRes toRoleTree(SaasRoleRes role) {
if (role == null) {
return null;
}
return RoleTreeRes.builder()
.id(role.getId())
.name(role.getName())
.type(ROLE_TYPE)
.idStr(role.getId() + ":" + ROLE_TYPE)
.isDisplay(role.getIsDisplay())
.build();
}
private void appendChildren(RoleTreeRes rootRoleGroup,
List<SaasRoleGroupVO> roleGroups,
Map<Long, List<RoleTreeRes>> roles) {
if (rootRoleGroup == null) {
return;
}
// 因为children可能是role或者roleGroup
List<RoleTreeRes> childrenRoleGroups = roleGroups.stream()
.filter(p -> Objects.equals(p.getParentId(), rootRoleGroup.getId()))
.map(this::toRoleTree)
.collect(Collectors.toList());
List<RoleTreeRes> childrenRoles = roles.get(rootRoleGroup.getId());
if (CollectionUtils.isNotEmpty(childrenRoles)) {
childrenRoleGroups.addAll(childrenRoles);
}
rootRoleGroup.setChildren(childrenRoleGroups);
childrenRoleGroups.forEach(e -> appendChildren(e, roleGroups, roles));
}
private List<CommonDictResp> listRootRole(TreeRoleReq req) {
CommonDictQueryReq commonDictQueryReq = CommonDictQueryReq.builder()
.codes(StringUtils.isBlank(req.getWorkspaceTypeCode()) ? null : Lists.newArrayList(req.getWorkspaceTypeCode()))
.scope("role")
.build();
if (StringUtils.isNotBlank(req.getTerminal())) {
List<String> workspaceTypeCodes = TERMINAL_WORKSPACE_CODES.get(req.getTerminal());
if (CollectionUtils.isEmpty(workspaceTypeCodes)) {
return Collections.emptyList();
}
commonDictQueryReq.setCodes(workspaceTypeCodes);
}
return saasCommonDictService.query(commonDictQueryReq);
}
}

View File

@ -4,6 +4,7 @@ import cn.axzo.basics.common.exception.ServiceException;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.feign.SaasRoleGroupApi;
import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq;
import cn.axzo.tyr.client.model.req.UpdateRoleGroupOffsetReq;
import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO;
import cn.axzo.tyr.server.service.SaasRoleGroupService;
import com.google.common.collect.Lists;
@ -12,7 +13,9 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.web.bind.annotation.RestController;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@RestController
@ -56,4 +59,62 @@ public class SaasRoleGroupController implements SaasRoleGroupApi {
return ApiResult.ok(saasRoleGroupService.listByCategoryCode(categoryCode));
}
@Override
public ApiResult<Void> updateRoleGroupOffset(UpdateRoleGroupOffsetReq request) {
if (request.getOffset() != 1 && request.getOffset() != -1) {
throw new ServiceException("暂时只支持移动一个位置");
}
SaasRoleGroupVO saasRoleGroup = getById(request.getId()).getData();
List<SaasRoleGroupVO> roleGroupList = saasRoleGroupService.getRoleGroupList(QuerySaasRoleGroupReq.builder()
.parentId(saasRoleGroup.getParentId())
.workspaceTypeCode(Lists.newArrayList(saasRoleGroup.getWorkspaceTypeCode()))
.build())
.stream()
.sorted(Comparator.comparing(SaasRoleGroupVO::getSort))
.collect(Collectors.toList());
SaasRoleGroupVO exchangeRoleGroup = findExchangeRoleGroup(request, roleGroupList);
if (exchangeRoleGroup == null) {
throw new ServiceException("未找到可以移动的位置");
}
saasRoleGroupService.saveOrUpdate(SaasRoleGroupVO.builder()
.id(saasRoleGroup.getId())
.sort(exchangeRoleGroup.getSort())
.build());
saasRoleGroupService.saveOrUpdate(SaasRoleGroupVO.builder()
.id(exchangeRoleGroup.getId())
.sort(saasRoleGroup.getSort())
.build());
return ApiResult.ok();
}
/**
* 只支持移动一位
* @param request
* @param roleGroupList
* @return
*/
private SaasRoleGroupVO findExchangeRoleGroup(UpdateRoleGroupOffsetReq request,
List<SaasRoleGroupVO> roleGroupList) {
List<Long> ids = roleGroupList.stream()
.map(SaasRoleGroupVO::getId)
.collect(Collectors.toList());
int currentIndex = ids.indexOf(request.getId());
// 下移一位
if (request.getOffset() == 1) {
int exchangeIndex = currentIndex + 1;
if (roleGroupList.size() > exchangeIndex) {
return roleGroupList.get(exchangeIndex);
}
} else if (request.getOffset() == -1) {
if (currentIndex == 0) {
return null;
}
int exchangeIndex = currentIndex - 1;
return roleGroupList.get(exchangeIndex);
}
return null;
}
}

View File

@ -6,6 +6,7 @@ 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.GetUserAutoOwnRoleResp;
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.*;
@ -119,6 +120,7 @@ public class RoleUserController implements TyrSaasRoleUserApi {
* 根据id删除用户角色关联关系
* @return
*/
@Override
public ApiResult removeRoleUserRelation(@RequestBody @Valid List<Long> ids){
AssertUtil.isTrue(!CollectionUtils.isEmpty(ids),"用户角色关联id不能为空");
List<SaasRoleUserRelation> relations = saasRoleUserRelationDao.listByIds(ids);
@ -140,6 +142,7 @@ public class RoleUserController implements TyrSaasRoleUserApi {
* 获取分包负责人等特殊角色
* @return
*/
@Override
public ApiResult<List<Long>> getSpecialRole() {
return ApiResult.ok(saasRoleUserService.getSpecialRole());
}
@ -148,4 +151,15 @@ public class RoleUserController implements TyrSaasRoleUserApi {
public ApiPageResult<SaasRoleUserDTO> pageQuery(RoleUserParam param) {
return ApiPageResult.ok(saasRoleUserRelationService.pageQuery(param));
}
@Override
public ApiResult<Void> saveOrUpdateAutoOwnRole(AutoOwnRoleUserReq req) {
saasRoleUserService.saveOrUpdateAutoOwnRole(req);
return ApiResult.ok();
}
@Override
public ApiResult<GetUserAutoOwnRoleResp> getUserAutoOwnRole(GetUserAutoOwnRoleReq req) {
return ApiResult.ok(saasRoleUserService.getUserAutoOwnRole(req));
}
}

View File

@ -0,0 +1,35 @@
package cn.axzo.tyr.server.inner.feign;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq;
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
import cn.axzo.tyr.client.model.res.NavTreeResp;
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;
import javax.validation.Valid;
import java.util.List;
/**
* 基准环境功能资源接口
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/3 10:25
*/
@FeignClient(name = "tyr", url = "${axzo.service.base.tyr:https://pre-api.axzo.cn/tyr}")
public interface BaseFeatureResourceApi {
/** 从基准环境同步接口功能资源 - 批量限制20条 **/
@GetMapping("/api/featureResource/sync/getTreeById")
ApiResult<List<FeatureResourceTreeNode>> getSyncTreeById(@RequestParam Long id);
/** 从基准环境拉取资源树 **/
@PostMapping("/api/featureResource/getTree")
ApiResult<List<FeatureResourceTreeNode>> getTree(@RequestBody @Valid GetFeatureResourceTreeReq req);
}

View File

@ -0,0 +1,8 @@
/**
* 不对外提供的接口调用feign封装
*
* @author: ZhanSiHu
* @date: 2024/4/3 10:24
* @version V1.0
*/
package cn.axzo.tyr.server.inner;

View File

@ -0,0 +1,26 @@
package cn.axzo.tyr.server.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Set;
/**
* 权限对象
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/8 11:09
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PermissionDO {
private Long ouId;
private Long workspaceId;
private Set<Long> featureIds;
private boolean superAdmin;
}

View File

@ -0,0 +1,56 @@
package cn.axzo.tyr.server.model;
import cn.axzo.tyr.client.model.base.WorkspaceOUPair;
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.ArrayList;
import java.util.List;
import java.util.Set;
/**
* 权限查询上下文
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/8 11:04
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PermissionQueryContext {
/** 用户标识 **/
private UserIdentity userIdentity;
/** 权限范围 **/
private List<WorkspaceOUPair> workspaceOUPairs;
/** 登录端 **/
private String terminal;
/** 预览角色ID **/
private List<Long> previewRoleIds;
/** 资源ID **/
private Set<Long> featureIds;
public PermissionQueryContext appendPersonId(Long personId) {
if (this.userIdentity == null) {
this.userIdentity = new UserIdentity();
}
this.userIdentity.setPersonId(personId);
return this;
}
public PermissionQueryContext appendOuWorkspace(Long ouId, Long workspaceId) {
if (this.workspaceOUPairs == null) {
this.workspaceOUPairs = new ArrayList<>();
}
this.workspaceOUPairs.add(WorkspaceOUPair.builder().ouId(ouId).workspaceId(workspaceId).build());
return this;
}
}

View File

@ -0,0 +1,30 @@
package cn.axzo.tyr.server.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 资源权限
* feature简化权限相关属性
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/8 17:11
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ResourcePermission {
private Long id;
private Long parentId;
private String featureCode;
private Integer featureType;
private Integer authType;
}

View File

@ -0,0 +1,36 @@
package cn.axzo.tyr.server.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 资源权限查询
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/8 17:10
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ResourcePermissionQueryDTO {
private List<Long> ids;
private List<Integer> featureTypes;
private List<String> featureCodes;
private List<String> terminals;
private List<Integer> authTypes;
/** 路径包含 **/
private Long inPath;
}

View File

@ -0,0 +1,24 @@
package cn.axzo.tyr.server.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 角色权限关联
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/8 14:50
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RoleFeatureRelation {
private Long roleId;
private Long featureId;
}

View File

@ -0,0 +1,32 @@
package cn.axzo.tyr.server.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Set;
/**
* 角色和权限
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/8 14:16
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RoleWithFeature {
private Long roleId;
private String roleName;
private String roleType;
private Integer productUnitType;
private Set<Long> featureIds;
}

View File

@ -0,0 +1,24 @@
package cn.axzo.tyr.server.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 用户标识对象
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/8 10:59
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserIdentity {
private Long personId;
private Long identityId;
private Integer identityType;
}

View File

@ -0,0 +1,26 @@
package cn.axzo.tyr.server.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 租户产品权限关系
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/8 15:56
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WorkspaceFeatureRelation {
private Long workspaceId;
private Integer productUnitType;
private Long featureId;
}

View File

@ -0,0 +1,15 @@
package cn.axzo.tyr.server.model.convert;
import cn.axzo.maokai.api.vo.request.UpdateNodeWorkerReq;
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface SaasFeatureResourceConvert {
SaasFeatureResourceConvert INSTANCE = Mappers.getMapper(SaasFeatureResourceConvert.class);
FeatureResourceTreeNode convert(SaasFeatureResource req);
}

View File

@ -0,0 +1,19 @@
package cn.axzo.tyr.server.repository.dao;
import cn.axzo.tyr.server.repository.entity.SaasCommonDict;
import cn.axzo.tyr.server.repository.mapper.SaasCommonDictMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 通用字典表 服务实现类
* </p>
*
* @author ZhanSiHu
* @since 2024-03-26
*/
@Service
public class SaasCommonDictDao extends ServiceImpl<SaasCommonDictMapper, SaasCommonDict> {
}

View File

@ -0,0 +1,46 @@
package cn.axzo.tyr.server.repository.dao;
import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum;
import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq;
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
import cn.axzo.tyr.server.repository.mapper.SaasFeatureResourceMapper;
import cn.azxo.framework.common.utils.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Objects;
/**
* <p>
* 功能资源表 服务实现类
* </p>
*
* @author AXZO
* @since 2024-04-03
*/
@Repository
public class SaasFeatureResourceDao extends ServiceImpl<SaasFeatureResourceMapper, SaasFeatureResource> {
public SaasFeatureResource getByCode(String featureCode) {
return this.lambdaQuery().eq(SaasFeatureResource::getFeatureCode, featureCode).one();
}
public void replacePath(String oldPath, String newPath) {
this.baseMapper.replacePath(oldPath, newPath);
}
public List<SaasFeatureResource> getByResourceTreeParam(GetFeatureResourceTreeReq req) {
return this.lambdaQuery().select(SaasFeatureResource::getId, SaasFeatureResource::getFeatureCode,
SaasFeatureResource::getFeatureName, SaasFeatureResource::getFeatureType,
SaasFeatureResource::getTerminal, SaasFeatureResource::getParentId,
SaasFeatureResource::getDisplayOrder)
.eq(SaasFeatureResource::getIsDelete, TableIsDeleteEnum.NORMAL.value)
.in(CollectionUtils.isNotEmpty(req.getTerminals()), SaasFeatureResource::getTerminal, req.getTerminals())
.eq(Objects.nonNull(req.getStatus()), SaasFeatureResource::getStatus, req.getStatus())
.in(CollectionUtils.isNotEmpty(req.getFeatureTypes()), SaasFeatureResource::getFeatureType, req.getFeatureTypes())
.list();
}
}

View File

@ -4,6 +4,7 @@ import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation;
import cn.axzo.tyr.server.repository.mapper.SaasPgroupPermissionRelationMapper;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections.CollectionUtils;
@ -11,6 +12,7 @@ import org.springframework.stereotype.Repository;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@Repository
@ -38,5 +40,26 @@ public class SaasPgroupPermissionRelationDao extends ServiceImpl<SaasPgroupPermi
.set(BaseEntity::getIsDelete, TableIsDeleteEnum.DELETE.value)
.update();
}
public void removeByFeatureIdAndGroupIds(Long featureId, List<Long> groupIds, Long operatorId) {
if (featureId != null && !CollectionUtil.isEmpty(groupIds)) {
lambdaUpdate()
.eq(SaasPgroupPermissionRelation::getFeatureId, featureId)
.in(SaasPgroupPermissionRelation::getGroupId, groupIds)
.set(SaasPgroupPermissionRelation::getUpdateBy, operatorId)
.set(BaseEntity::getIsDelete, TableIsDeleteEnum.DELETE.value)
.update();
}
}
public List<SaasPgroupPermissionRelation> queryByFeatureIds(List<Long> featureIds) {
if (featureIds == null) {
return Collections.emptyList();
}
return lambdaQuery()
.in(SaasPgroupPermissionRelation::getFeatureId,featureIds)
.eq(BaseEntity::getIsDelete, TableIsDeleteEnum.NORMAL.value)
.list();
}
}

View File

@ -5,6 +5,7 @@ import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.tyr.client.common.enums.RoleTypeEnum;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.req.RoleWithUserQueryReq;
import cn.axzo.tyr.server.model.RoleFeatureRelation;
import cn.axzo.tyr.server.repository.entity.SaasRole;
import cn.axzo.tyr.server.repository.entity.SaasRoleWithUser;
import cn.axzo.tyr.server.repository.mapper.SaasRoleMapper;
@ -115,5 +116,9 @@ public class SaasRoleDao extends ServiceImpl<SaasRoleMapper, SaasRole> {
.eq(SaasRole::getRoleType, RoleTypeEnum.INIT.getValue())
.list();
}
public List<RoleFeatureRelation> listFeatureByIds(Set<Long> roleIds, Set<Long> featureIds) {
return this.baseMapper.listFeatureByIds(roleIds, featureIds);
}
}

View File

@ -13,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Objects;
@Repository
public class SaasRoleGroupDao extends ServiceImpl<SaasRoleGroupMapper, SaasRoleGroup> {
@ -37,6 +38,7 @@ public class SaasRoleGroupDao extends ServiceImpl<SaasRoleGroupMapper, SaasRoleG
.in(CollectionUtils.isNotEmpty(req.getWorkspaceTypeCode()), SaasRoleGroup::getWorkspaceTypeCode, req.getWorkspaceTypeCode())
.in(CollectionUtils.isNotEmpty(req.getWorkspaceIds()), SaasRoleGroup::getWorkspaceId, req.getWorkspaceIds())
.in(CollectionUtils.isNotEmpty(req.getOuIds()), SaasRoleGroup::getOuId, req.getOuIds())
.eq(Objects.nonNull(req.getParentId()), SaasRoleGroup::getParentId, req.getParentId())
.eq(BaseEntity::getIsDelete, TableIsDeleteEnum.NORMAL.value);
if(CollectionUtils.isNotEmpty(req.getOuTypeCode())){
eq.last(" AND (" + condition.substring(0, condition.length() - 2) + ")");
@ -51,6 +53,8 @@ public class SaasRoleGroupDao extends ServiceImpl<SaasRoleGroupMapper, SaasRoleG
.update();
}
/** 弃用category_code 通过角色组层级实现 **/
@Deprecated
public List<SaasRoleGroup> listByCategoryCode(List<String> categoryCode) {
return lambdaQuery().eq(BaseEntity::getIsDelete, 0L)
.in(SaasRoleGroup::getCategoryCode, categoryCode).list();

View File

@ -0,0 +1,41 @@
package cn.axzo.tyr.server.repository.entity;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 通用字典表
* </p>
*
* @author ZhanSiHu
* @since 2024-03-26
*/
@Getter
@Setter
@TableName("saas_common_dict")
public class SaasCommonDict extends BaseEntity<SaasCommonDict> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 业务域
*/
private String scope;
/**
* 字典编码
*/
private String dictCode;
/**
* 字典值
*/
private String dictValue;
}

View File

@ -0,0 +1,144 @@
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.Data;
import lombok.NoArgsConstructor;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 功能资源表
* </p>
*
* @author AXZO
* @since 2024-04-03
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("saas_feature_resource")
public class SaasFeatureResource extends BaseEntity<SaasFeature> {
private static final long serialVersionUID = 1L;
/**
* 资源编码-权限码
*/
private String featureCode;
/**
* 资源名称
*/
private String featureName;
/**
* 资源类型1-菜单 2-页面 3-应用入口 4-组件
*/
private Integer featureType;
/**
* 资源所属端
*/
private String terminal;
/**
* 组件细分类型 1-跳转子页面 2-跳转公共组件 3-弹出窗口 4-下拉项 5-操作按钮 6-数据卡片 7-站外跳转
*/
private Integer componentType;
/**
* 上级资源ID
*/
private Long parentId;
/**
* 资源ID层级路径 逗号分隔
*/
private String path;
/**
* 展示顺序
*/
private Integer displayOrder;
/**
* 资源状态 0-隐藏 1-展示
*/
private Integer status;
/**
* 资源图标
*/
private String icon;
/**
* 跳转类型 1-站内跳转 2-站外跳转
*/
private Integer redirectType;
/**
* 资源跳转URI
*/
private String linkUrl;
/**
* 路由类型1-PC 2-小程序 3-原生
*/
private Integer linkType;
/**
* APP适配参数
*/
private String linkExt;
/**
* 小程序id
*/
private Integer appItemId;
/**
* 资源同步版本
*/
private Integer syncVersion;
/**
* 扩展字段
*/
private String extra;
/**
* 授权类型0-全部角色 1-指定角色
*/
private Integer authType;
/**
* 子级鉴权类型 0-不鉴权1-鉴权
*/
private Integer subAuthType;
/**
* 创建人
*/
private Long createBy;
/**
* 更新人
*/
private Long updateBy;
public List<Long> splitPath() {
if (StrUtil.isBlank(this.path)) {
return Collections.emptyList();
}
return StrUtil.split(this.path, ",").stream().map(Long::valueOf).collect(Collectors.toList());
}
}

View File

@ -1,6 +1,7 @@
package cn.axzo.tyr.server.repository.entity;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.EqualsAndHashCode;
import lombok.Getter;
@ -76,6 +77,24 @@ public class SaasRole extends BaseEntity<SaasRole> {
@Deprecated
private Long fitOuTypeBit;
/**
* '角色编码'
*/
private String roleCode;
/**
* '是否显示'
*/
private Boolean isDisplay;
/**
* '是否启用'
*/
private Boolean enabled;
/**
* 排序
*/
private Integer sort;
/**
* 获取主键值
*

View File

@ -3,8 +3,11 @@ package cn.axzo.tyr.server.repository.entity;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
@ -19,6 +22,9 @@ import java.io.Serializable;
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SaasRoleGroup extends BaseEntity<SaasRoleGroup> implements Serializable {
private static final long serialVersionUID = 972205950455439772L;
@ -69,6 +75,10 @@ public class SaasRoleGroup extends BaseEntity<SaasRoleGroup> implements Serializ
*/
private String categoryCode;
/**
* 上级分组id
*/
private Long parentId;
/**
* 获取主键值

View File

@ -0,0 +1,16 @@
package cn.axzo.tyr.server.repository.mapper;
import cn.axzo.tyr.server.repository.entity.SaasCommonDict;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 通用字典表 Mapper 接口
* </p>
*
* @author ZhanSiHu
* @since 2024-03-26
*/
public interface SaasCommonDictMapper extends BaseMapper<SaasCommonDict> {
}

View File

@ -0,0 +1,22 @@
package cn.axzo.tyr.server.repository.mapper;
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
/**
* <p>
* 功能资源表 Mapper 接口
* </p>
*
* @author AXZO
* @since 2024-04-03
*/
public interface SaasFeatureResourceMapper extends BaseMapper<SaasFeatureResource> {
@Update("UPDATE saas_feature_resource" +
" SET path = REPLACE(path, #{oldPath}, #{newPath})" +
" WHERE is_delete = 0 AND path LIKE CONCAT(#{oldPath}, '%')")
void replacePath(@Param("oldPath") String oldPath, @Param("newPath") String newPath);
}

View File

@ -1,6 +1,7 @@
package cn.axzo.tyr.server.repository.mapper;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.server.model.RoleFeatureRelation;
import cn.axzo.tyr.server.repository.entity.SaasRole;
import cn.axzo.tyr.server.repository.entity.SaasRoleWithUser;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@ -27,5 +28,6 @@ public interface SaasRoleMapper extends BaseMapper<SaasRole> {
List<SaasRole> listRoleByFeatures(@Param("featureIds") Set<Long> featureIds);
List<RoleFeatureRelation> listFeatureByIds(@Param("roleIds") Set<Long> roleIds, @Param("featureIds") Set<Long> featureIds);
}

View File

@ -0,0 +1,23 @@
package cn.axzo.tyr.server.service;
import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq;
import cn.axzo.tyr.client.model.req.ResourceSyncReq;
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
import java.util.List;
/**
* 功能资源同步服务
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/8 10:09
*/
public interface FeatureResourceSyncService {
List<FeatureResourceTreeNode> getSyncTreeById(Long id);
void syncFromBase(ResourceSyncReq req);
List<FeatureResourceTreeNode> getBaseTree(GetFeatureResourceTreeReq req);
}

View File

@ -0,0 +1,26 @@
package cn.axzo.tyr.server.service;
import cn.axzo.tyr.client.model.req.NavTreeReq;
import cn.axzo.tyr.client.model.req.PagePermissionReq;
import cn.axzo.tyr.client.model.req.PagePermissionResp;
import cn.axzo.tyr.client.model.req.PermissionCheckReq;
import cn.axzo.tyr.client.model.res.NavTreeResp;
import java.util.List;
/**
* 权限服务接口
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/7 17:33
*/
public interface PermissionQueryService {
/** 获取导航菜单页面 **/
List<NavTreeResp> getNavTree(NavTreeReq req);
boolean hasPermission(PermissionCheckReq req);
List<PagePermissionResp> getPagePermission(PagePermissionReq req);
}

View File

@ -1,20 +1,38 @@
package cn.axzo.tyr.server.service;
import cn.axzo.framework.domain.page.PageResp;
import cn.axzo.pokonyan.dao.page.IPageParam;
import cn.axzo.pokonyan.dao.wrapper.CriteriaField;
import cn.axzo.pokonyan.dao.wrapper.Operator;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.req.*;
import cn.axzo.tyr.client.model.req.ChangeGroupLeaderRoleReq;
import cn.axzo.tyr.client.model.req.FeatureRoleRelationReq;
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.res.FeatureRoleRelationResp;
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.res.SaasRoleRes;
import cn.axzo.tyr.client.model.vo.DeleteRoleVO;
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.RoleWithFeature;
import cn.axzo.tyr.server.repository.entity.SaasRole;
import cn.axzo.tyr.server.repository.entity.SaasRoleWithUser;
import cn.axzo.tyr.server.service.impl.TyrSaasAuthServiceImpl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.util.List;
import java.util.Set;
@ -26,7 +44,7 @@ import java.util.Set;
* @author: ZhanSiHu
* @date: 2023/9/6 15:51
*/
public interface RoleService {
public interface RoleService extends IService<SaasRole> {
List<SaasRoleVO> queryByIdentityIdType(Long identityId, Integer identityType,Long workspaceId,Long ouId, Boolean includePermissionGroup);
@ -83,11 +101,9 @@ public interface RoleService {
/**
* 删除角色列表
* @param roleIds 待删除角色集合
* @param workSpaceId 待删除角色所属workSpaceId
* @param outId 待删除角色所属单位ID
* @param deleteRoleParam
*/
void deleteRole(List<Long> roleIds,Long workSpaceId,Long outId);
void deleteRole(DeleteRoleVO deleteRoleParam);
List<SaasRole> queryRoleByFeatures(Set<Long> matchedFeatureIds);
@ -101,4 +117,73 @@ public interface RoleService {
/** 查询超管和管理员角色 **/
List<SaasRole> listAdmins(Long workspaceId, Long ouId);
List<SaasRoleRes> list(ListSaasRoleParam param);
Page<SaasRoleRes> page(PageSaasRoleParam param);
void saveOrUpdateFeatureRoleRelation(List<FeatureRoleRelationReq.RelationRoleSettings> req, Long operatorId);
FeatureRoleRelationResp queryFeatureRoleRelation(Long featureId);
@SuperBuilder
@Data
@NoArgsConstructor
@AllArgsConstructor
class ListSaasRoleParam {
@CriteriaField(field = "id", operator = Operator.IN)
private List<Long> roleIds;
@CriteriaField(field = "workspaceType", operator = Operator.EQ)
private Integer workspaceType;
@CriteriaField(field = "isDisplay", operator = Operator.EQ)
private Boolean isDisplay;
@CriteriaField(field = "roleCode", operator = Operator.EQ)
private String roleCode;
@CriteriaField(field = "workspaceId", operator = Operator.IN)
private List<Long> workspaceIds;
@CriteriaField(field = "ownerOuId", operator = Operator.IN)
private List<Long> ouIds;
@CriteriaField(field = "enabled", operator = Operator.EQ)
private Boolean enabled;
@CriteriaField(field = "roleType", operator = Operator.IN)
private List<String> roleTypes;
@CriteriaField(field = "id", operator = Operator.NE)
private Long idNE;
@CriteriaField(ignore = true)
private Boolean needPermission;
@CriteriaField(ignore = true)
private Boolean needRoleGroup;
}
@SuperBuilder
@Data
@NoArgsConstructor
@AllArgsConstructor
class PageSaasRoleParam extends ListSaasRoleParam implements IPageParam {
@CriteriaField(ignore = true)
Integer page;
@CriteriaField(ignore = true)
Integer pageSize;
/**
* 排序使用示例createTime__DESC
*/
@CriteriaField(ignore = true)
List<String> sort;
}
List<RoleWithFeature> listWithFeatures(Set<Long> roleIds, Set<Long> featureIds);
}

View File

@ -0,0 +1,17 @@
package cn.axzo.tyr.server.service;
import cn.axzo.tyr.client.model.req.CommonDictQueryReq;
import cn.axzo.tyr.client.model.res.CommonDictResp;
import java.util.List;
/**
* 通用字典服务
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/3/26 17:40
*/
public interface SaasCommonDictService {
List<CommonDictResp> query(CommonDictQueryReq req);
}

View File

@ -0,0 +1,54 @@
package cn.axzo.tyr.server.service;
import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq;
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
import cn.axzo.tyr.server.model.ResourcePermission;
import cn.axzo.tyr.server.model.ResourcePermissionQueryDTO;
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
import cn.axzo.tyr.client.model.req.FeatureResourceTreeSaveReq;
import io.swagger.models.auth.In;
import java.util.List;
import java.util.Set;
/**
* 功能资源服务
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/3 10:17
*/
public interface SaasFeatureResourceService {
Long saveOrUpdateMenu(FeatureResourceTreeSaveReq req);
void updateFeatureAuthType(Long featureId, Integer authType);
/**递归的**/
List<SaasFeatureResource> listDescendant(Long featureId);
SaasFeatureResource featureResourceById(Long featureId);
FeatureResourceTreeNode getTreeFeatureDescendant(Long featureId, Integer featureType);
/**删除指定菜单**/
void deleteMenuFeature(Long featureId, Long operatorId);
/**菜单重排序**/
void reorderMenuFeature(Long featureId, Integer offset);
/** 根据ID查询导航菜单页面信息 仅可显示 - 限制查询字段 **/
List<SaasFeatureResource> listNavByIds(List<Long> featureIds, List<Integer> featureTypes);
/** 资源权限通用查询 **/
List<ResourcePermission> permissionQuery(ResourcePermissionQueryDTO param);
/** 查询资源树 **/
List<FeatureResourceTreeNode> getTree(GetFeatureResourceTreeReq req);
SaasFeatureResource getByCode(String featureCode);
Set<Long> listAuthFree();
List<SaasFeatureResource> listNavMenu(String terminal);
}

View File

@ -6,4 +6,6 @@ import java.util.List;
public interface SaasPgroupPermissionRelationService {
void saveOrUpdate(List<Long> groupIds, List<SaasPgroupPermissionRelation> relations);
void deleteByFeatureIds(List<Long> featureIds);
}

View File

@ -1,9 +1,55 @@
package cn.axzo.tyr.server.service;
import cn.axzo.pokonyan.dao.page.IPageParam;
import cn.axzo.pokonyan.dao.wrapper.CriteriaField;
import cn.axzo.pokonyan.dao.wrapper.Operator;
import cn.axzo.tyr.server.repository.entity.SaasRoleGroupRelation;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.util.List;
public interface SaasRoleGroupRelationService {
public interface SaasRoleGroupRelationService extends IService<SaasRoleGroupRelation> {
void saveOrUpdate(List<SaasRoleGroupRelation> relations);
List<SaasRoleGroupRelation> list(ListSaasRoleGroupRelationParam param);
Page<SaasRoleGroupRelation> page(PageSaasRoleGroupRelationParam param);
@SuperBuilder
@Data
@NoArgsConstructor
@AllArgsConstructor
class ListSaasRoleGroupRelationParam {
@CriteriaField(field = "roleId", operator = Operator.IN)
private List<Long> roleIds;
@CriteriaField(field = "saasRoleGroupId", operator = Operator.IN)
private List<Long> saasRoleGroupIds;
}
@SuperBuilder
@Data
@NoArgsConstructor
@AllArgsConstructor
class PageSaasRoleGroupRelationParam extends ListSaasRoleGroupRelationParam implements IPageParam {
@CriteriaField(ignore = true)
Integer page;
@CriteriaField(ignore = true)
Integer pageSize;
/**
* 排序使用示例createTime__DESC
*/
@CriteriaField(ignore = true)
List<String> sort;
}
}

View File

@ -2,6 +2,8 @@ package cn.axzo.tyr.server.service;
import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq;
import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO;
import cn.axzo.tyr.server.repository.entity.SaasRoleGroup;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
@ -10,7 +12,7 @@ import java.util.List;
* @description
* @date 2023/12/1 16:37
*/
public interface SaasRoleGroupService {
public interface SaasRoleGroupService extends IService<SaasRoleGroup> {
List<SaasRoleGroupVO> getList(QuerySaasRoleGroupReq req);
@ -32,4 +34,11 @@ public interface SaasRoleGroupService {
* @return
*/
List<SaasRoleGroupVO> listByCategoryCode(List<String> categoryCode);
/**
* 根据code查询角色组
* @param codes 角色组编码
* @param type 1-仅查当前code 2-对应code角色组及子级角色组 3-仅对应code角色组的子级
* **/
List<SaasRoleGroup> listByCodes(List<String> codes, int type);
}

View File

@ -1,6 +1,7 @@
package cn.axzo.tyr.server.service;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.roleuser.dto.GetUserAutoOwnRoleResp;
import cn.axzo.tyr.client.model.roleuser.dto.SuperAminInfoResp;
import cn.axzo.tyr.client.model.roleuser.req.*;
import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation;
@ -84,4 +85,16 @@ public interface SaasRoleUserService {
*/
void grantOrUngrantWorkerManager(WorkerManagerRoleUserReq req);
/**
* 保存/更新 用户自定义角色权限
* @param req
*/
void saveOrUpdateAutoOwnRole(AutoOwnRoleUserReq req);
/**
* 查询用户自定义角色和权限
* @param req
* @return
*/
GetUserAutoOwnRoleResp getUserAutoOwnRole(GetUserAutoOwnRoleReq req);
}

View File

@ -0,0 +1,181 @@
package cn.axzo.tyr.server.service.impl;
import cn.axzo.basics.common.BeanMapper;
import cn.axzo.basics.common.util.TreeUtil;
import cn.axzo.tyr.client.common.enums.FeatureResourceType;
import cn.axzo.tyr.client.model.req.GetFeatureResourceTreeReq;
import cn.axzo.tyr.client.model.req.ResourceSyncReq;
import cn.axzo.tyr.client.model.res.FeatureResourceTreeNode;
import cn.axzo.tyr.server.inner.feign.BaseFeatureResourceApi;
import cn.axzo.tyr.server.repository.dao.SaasFeatureResourceDao;
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
import cn.axzo.tyr.server.service.FeatureResourceSyncService;
import cn.axzo.tyr.server.util.RpcInternalUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
/**
* 功能资源同步服务实现
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/8 10:09
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncService {
private final SaasFeatureResourceDao featureResourceDao;
private final BaseFeatureResourceApi baseFeatureResourceApi;
private final SaasFeatureResourceCacheService saasFeatureResourceCacheService;
@Qualifier("asyncExecutor")
@Autowired
private ExecutorService asyncExecutor;
@Override
public List<FeatureResourceTreeNode> getSyncTreeById(Long id) {
//选中同步的数据
SaasFeatureResource resource = featureResourceDao.lambdaQuery()
.eq(SaasFeatureResource::getId, id)
.one();
if (resource == null) {
return Collections.emptyList();
}
//找到所有上级 - 包含自己
List<SaasFeatureResource> resourceList = featureResourceDao.lambdaQuery()
.in(SaasFeatureResource::getId, resource.splitPath())
.list();
//resourceList.add(resource);
//如果是页面或应用入口-同时返回所有页面组件
if (FeatureResourceType.applyPage(resource.getFeatureType())) {
List<SaasFeatureResource> componentList = featureResourceDao.lambdaQuery()
.eq(SaasFeatureResource::getFeatureType, FeatureResourceType.COMPONENT.getCode())
.apply("FIND_IN_SET(" + id + ", path)")
.list();
resourceList.addAll(componentList);
}
List<FeatureResourceTreeNode> dtoList = BeanMapper.copyList(resourceList, FeatureResourceTreeNode.class);
return TreeUtil.buildTree(dtoList);
}
@Override
public void syncFromBase(ResourceSyncReq req) {
if (req.getIds().size() > 1) {
//超过一个异步处理
CompletableFuture.runAsync(() -> doSyncFromBase(req), asyncExecutor).whenComplete((t, ex) -> saasFeatureResourceCacheService.clearCache());
return;
}
doSyncFromBase(req);
saasFeatureResourceCacheService.clearCache();
}
private void doSyncFromBase(ResourceSyncReq req) {
//TODO:@Zhan 并发处理同一个parent下同批查询
//处理数据缓存避免同级节点上级重复处理 - 上级code查询
final Map<Long, String> codeCache = new ConcurrentHashMap<>();
for (Long id : req.getIds()) {
//获取基准环境配置数据:同步某个ID的数据 需要同步处理它所有上级及下级组件
List<FeatureResourceTreeNode> syncList = RpcInternalUtil.rpcProcessor(() -> baseFeatureResourceApi.getSyncTreeById(id),
"get base sync tree by id", id).getData();
syncResourceProcess(syncList, codeCache, req.getOperatorId());
}
}
@Override
public List<FeatureResourceTreeNode> getBaseTree(GetFeatureResourceTreeReq req) {
return RpcInternalUtil.rpcProcessor(() -> baseFeatureResourceApi.getTree(req),
"get resource tree from base env", req).getData();
}
private void syncResourceProcess(List<FeatureResourceTreeNode> syncList, Map<Long, String> codeCache, Long operatorId) {
for (FeatureResourceTreeNode treeNode : syncList) {
if (codeCache.containsKey(treeNode.getId())) {
//已处理过
log.info("already sync resource:{}", treeNode.getId());
//递归子节点
if (CollectionUtil.isNotEmpty(treeNode.getChildren())) {
syncResourceProcess(treeNode.getChildren(), codeCache, operatorId);
}
continue;
}
//缓存code
codeCache.put(treeNode.getId(), treeNode.getFeatureCode());
SaasFeatureResource baseResource = BeanMapper.copyBean(treeNode, SaasFeatureResource.class);
//修正数据
String parentCode = codeCache.get(baseResource.getParentId());
fixData(baseResource, parentCode);
SaasFeatureResource resource = featureResourceDao.getByCode(treeNode.getFeatureCode());
if (resource == null) {
//新增
baseResource.setCreateBy(operatorId);
baseResource.setUpdateBy(operatorId);
newResource(baseResource);
} else {
//更新 - 恢复不能变更的数据
baseResource.setId(resource.getId());
baseResource.setPath(baseResource.getPath() + "," + resource.getId());
baseResource.setUpdateBy(operatorId);
baseResource.setAppItemId(resource.getAppItemId());
featureResourceDao.updateById(baseResource);
if (!StrUtil.equals(baseResource.getPath(), resource.getPath())) {
//层级变化
log.info("replace path from old:{} to new:{}", resource.getPath(), baseResource.getPath());
featureResourceDao.replacePath(resource.getPath(), baseResource.getPath());
}
}
//递归子节点
if (CollectionUtil.isNotEmpty(treeNode.getChildren())) {
syncResourceProcess(treeNode.getChildren(), codeCache, operatorId);
}
}
}
/** 修正当前环境的数据 parentId path **/
private void fixData(SaasFeatureResource resource, String parentCode) {
if (StrUtil.isBlank(parentCode)) {
resource.setParentId(0L);
resource.setPath("0");
} else {
//找当前环境的parent
SaasFeatureResource parent = featureResourceDao.getByCode(parentCode);
if (parent == null) {
resource.setParentId(0L);
resource.setPath("0");
} else {
resource.setParentId(parent.getId());
resource.setPath(parent.getPath());
}
}
}
private void newResource(SaasFeatureResource resource) {
featureResourceDao.save(resource);
//path追加自身ID
resource.setPath(resource.getPath() + "," + resource.getId());
featureResourceDao.updateById(resource);
}
}

View File

@ -0,0 +1,348 @@
package cn.axzo.tyr.server.service.impl;
import cn.axzo.basics.common.BeanMapper;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.basics.common.util.NumberUtil;
import cn.axzo.basics.common.util.TreeUtil;
import cn.axzo.framework.auth.domain.TerminalInfo;
import cn.axzo.maokai.common.enums.SaasCooperateShipCooperateTypeEnum;
import cn.axzo.tyr.client.common.enums.FeatureResourceAuthType;
import cn.axzo.tyr.client.common.enums.FeatureResourceType;
import cn.axzo.tyr.client.common.enums.RoleTypeEnum;
import cn.axzo.tyr.client.model.base.WorkspaceOUPair;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.req.IdentityAuthReq;
import cn.axzo.tyr.client.model.req.NavTreeReq;
import cn.axzo.tyr.client.model.req.PagePermissionReq;
import cn.axzo.tyr.client.model.req.PagePermissionResp;
import cn.axzo.tyr.client.model.req.PermissionCheckReq;
import cn.axzo.tyr.client.model.res.IdentityAuthRes;
import cn.axzo.tyr.client.model.res.NavTreeResp;
import cn.axzo.tyr.server.model.PermissionDO;
import cn.axzo.tyr.server.model.PermissionQueryContext;
import cn.axzo.tyr.server.model.ResourcePermission;
import cn.axzo.tyr.server.model.ResourcePermissionQueryDTO;
import cn.axzo.tyr.server.model.RoleWithFeature;
import cn.axzo.tyr.server.model.UserIdentity;
import cn.axzo.tyr.server.model.WorkspaceFeatureRelation;
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation;
import cn.axzo.tyr.server.service.PermissionQueryService;
import cn.axzo.tyr.server.service.RoleService;
import cn.axzo.tyr.server.service.SaasFeatureResourceService;
import cn.axzo.tyr.server.service.TyrSaasAuthService;
import cn.axzo.tyr.server.util.KeyUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 权限查询服务实现
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/4/7 17:54
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class PermissionQueryServiceImpl implements PermissionQueryService {
private final SaasFeatureResourceService featureResourceService;
private final RoleUserService roleUserService;
private final RoleService roleService;
private final TyrSaasAuthService saasAuthService;
@Override
public List<NavTreeResp> getNavTree(NavTreeReq req) {
//构造参数
PermissionQueryContext context = PermissionQueryContext.builder()
.terminal(req.getTerminal())
.workspaceOUPairs(req.getWorkspaceOUPairs())
.build()
.appendPersonId(req.getPersonId());
//查询权限
List<PermissionDO> permissions = queryUserPermission(context);
// List<PermissionDO> permissions = queryAllPermission(context);
if (CollectionUtil.isEmpty(permissions)) {
return Collections.emptyList();
}
List<Long> featureIds = permissions.stream()
.map(PermissionDO::getFeatureIds)
.flatMap(Set::stream)
.collect(Collectors.toList());
//反查资源信息-仅页面
List<SaasFeatureResource> resourceList = featureResourceService.listNavByIds(featureIds, FeatureResourceType.pageTypes());
//查所有上级菜单
List<Long> menuIds = resourceList.stream()
.map(SaasFeatureResource::splitPath)
.flatMap(List::stream)
.collect(Collectors.toList());
List<SaasFeatureResource> menus = featureResourceService.listNavByIds(menuIds, Collections.singletonList(FeatureResourceType.MENU.getCode()));
resourceList.addAll(menus);
//去重-排序
Set<Long> distinctSet = new HashSet<>();
List<SaasFeatureResource> finalResources = resourceList.stream()
.filter(r -> distinctSet.add(r.getId()))
.sorted(Comparator.comparingInt(SaasFeatureResource::getDisplayOrder))
.collect(Collectors.toList());
//组装导航树
List<NavTreeResp> navTreeList = TreeUtil.buildTree(BeanMapper.copyList(finalResources, NavTreeResp.class));
//过滤顶级孤儿节点
return navTreeList.stream().filter(t -> !NumberUtil.isPositiveNumber(t.getParentId())).collect(Collectors.toList());
}
@Override
public boolean hasPermission(PermissionCheckReq req) {
//这里暂时硬编码-非OMS端鉴权请求 直接转老接口处理
if (!StrUtil.equals("NT_OMS_WEB" ,req.getTerminal())) {
return hasPermissionV2(req);
}
//权限编码转ID
List<ResourcePermission> resourcePermissions = featureResourceService.permissionQuery(
ResourcePermissionQueryDTO.builder().featureCodes(req.getFeatureCodes()).build());
if (CollectionUtil.isEmpty(resourcePermissions)) {
log.warn("no feature resource found for codes:{}", req.getFeatureCodes());
return false;
}
PermissionQueryContext context = PermissionQueryContext.builder()
.terminal(req.getTerminal())
.build()
.appendPersonId(req.getPersonId())
.appendOuWorkspace(req.getOuId(), req.getWorkspaceId());
//查询权限
List<PermissionDO> permissions = queryUserPermission(context);
Set<Long> featureIds = permissions.stream().map(PermissionDO::getFeatureIds).flatMap(Set::stream).collect(Collectors.toSet());
//是否任意一个有授权
return resourcePermissions.stream().anyMatch(r -> featureIds.contains(r.getId()));
}
private boolean hasPermissionV2(PermissionCheckReq req) {
//包装请求老鉴权接口
IdentityAuthReq authReq = IdentityAuthReq.builder()
.personId(req.getPersonId())
.workspaceOusPairs(Collections.singletonList(IdentityAuthReq.WorkspaceOuPair.builder()
.workspaceId(req.getWorkspaceId())
.ouId(req.getOuId()).build()))
.featureCode(new HashSet<>(req.getFeatureCodes()))
.terminal(StringUtils.isBlank(req.getTerminal()) ? null : Collections.singletonList(req.getTerminal()))
.build();
IdentityAuthRes.WorkspacePermission permissions = saasAuthService.findIdentityAuthMix(authReq).getPermissions().get(0);
return CollectionUtil.isNotEmpty(permissions.getPermissionPoint());
}
@Override
public List<PagePermissionResp> getPagePermission(PagePermissionReq req) {
//这里没有区分是否为页面的组件或菜单树下级 同时包含了页面自身
//权限编码转ID
SaasFeatureResource page = featureResourceService.getByCode(req.getFeatureCode());
AssertUtil.notNull(page, "权限码不存在");
//所有子级
ResourcePermissionQueryDTO param = ResourcePermissionQueryDTO.builder().inPath(page.getId()).build();
List<ResourcePermission> resourceList = featureResourceService.permissionQuery(param);
PermissionQueryContext context = PermissionQueryContext.builder()
.terminal(req.getTerminal())
.workspaceOUPairs(req.getWorkspaceOUPairs())
.build()
.appendPersonId(req.getPersonId());
//查询权限
List<PermissionDO> permissions = queryUserPermission(context);
// List<PermissionDO> permissions = queryAllPermission(context);
Set<Long> featureIds = permissions.stream().map(PermissionDO::getFeatureIds).flatMap(Set::stream).collect(Collectors.toSet());
//权限过滤
return resourceList.stream()
.filter(r -> featureIds.contains(r.getId()))
.map(r -> PagePermissionResp.builder()
.featureId(r.getId())
.featureCode(r.getFeatureCode()).build())
.collect(Collectors.toList());
}
private List<PermissionDO> queryAllPermission(PermissionQueryContext context) {
//mock 调试用 返回全部权限
List<WorkspaceFeatureRelation> workspaceFeatureRelations = listWorkspaceFeatureRelations(context);
if (CollectionUtil.isEmpty(workspaceFeatureRelations)) {
return Collections.emptyList();
}
Set<Long> featureIds = workspaceFeatureRelations.stream()
.map(WorkspaceFeatureRelation::getFeatureId)
.collect(Collectors.toSet());
PermissionDO permission = PermissionDO.builder().featureIds(featureIds).build();
return Collections.singletonList(permission);
}
private List<PermissionDO> queryUserPermission(PermissionQueryContext context) {
//查询用户具有的角色
List<SaasRoleUserRelation> userRoleRelations = listRoleUserRelations(context);
if (CollectionUtil.isEmpty(userRoleRelations)) {
log.warn("no user role relation found");
return Collections.emptyList();
}
//查询租户产品权限点
List<WorkspaceFeatureRelation> workspaceFeatureRelations = listWorkspaceFeatureRelations(context);
Set<Long> roleIds = userRoleRelations.stream().map(SaasRoleUserRelation::getRoleId).collect(Collectors.toSet());
//查询角色权限
List<RoleWithFeature> roles = roleService.listWithFeatures(roleIds, context.getFeatureIds());
//取交集确定权限
return buildFinalPermission(userRoleRelations, workspaceFeatureRelations, roles);
}
private List<PermissionDO> buildFinalPermission(List<SaasRoleUserRelation> userRoleRelations,
List<WorkspaceFeatureRelation> workspaceFeatureRelations,
List<RoleWithFeature> roles) {
//mapping
Map<Long, RoleWithFeature> roleMap = roles.stream()
.collect(Collectors.toMap(RoleWithFeature::getRoleId, Function.identity()));
Map<Long, List<WorkspaceFeatureRelation>> workspaceMap = workspaceFeatureRelations.stream()
.collect(Collectors.groupingBy(WorkspaceFeatureRelation::getWorkspaceId));
//免授权
Set<Long> authFreeFeatureIds = featureResourceService.listAuthFree();
//按拥有的角色构建权限结果
Map<String, PermissionDO> result = new HashMap<>();
for (SaasRoleUserRelation relation : userRoleRelations) {
RoleWithFeature role = roleMap.get(relation.getRoleId());
if (role == null) {
log.warn("no role found for id:{}", relation.getRoleId());
continue;
}
List<WorkspaceFeatureRelation> allFeatures = workspaceMap.get(relation.getWorkspaceId());
if (CollectionUtil.isEmpty(allFeatures)) {
log.warn("no workspace product feature found for id:{}", relation.getWorkspaceId());
continue;
}
String key = relation.getWorkspaceId() + "-" + relation.getOuId();
PermissionDO permission = result.getOrDefault(key,
PermissionDO.builder()
.ouId(relation.getOuId())
.workspaceId(relation.getWorkspaceId())
.featureIds(new HashSet<>()).build());
if (RoleTypeEnum.isAdmin(role.getRoleType())) {
//管理员和超管类权限
permission.getFeatureIds().addAll(buildAdminPermission(role, allFeatures));
if (RoleTypeEnum.SUPER_ADMIN.apply(role.getRoleType())) {
//超管标记
permission.setSuperAdmin(true);
}
} else {
//普通角色权限
permission.getFeatureIds().addAll(buildNormalPermission(role, allFeatures, authFreeFeatureIds));
}
result.put(key, permission);
}
return new ArrayList<>(result.values());
}
private List<Long> buildNormalPermission(RoleWithFeature role, List<WorkspaceFeatureRelation> allFeatures, Set<Long> authFreeFeatureIds) {
//普通角色角色同类型的租户产品权限已分配 且角色上已分配 + 免授权
Set<Long> roleFeatures = role.getFeatureIds();
return allFeatures.stream()
.filter(f -> Objects.equals(f.getProductUnitType(), role.getProductUnitType())
|| !NumberUtil.isPositiveNumber(role.getProductUnitType()))
.map(WorkspaceFeatureRelation::getFeatureId)
.filter(id -> roleFeatures.contains(id) || authFreeFeatureIds.contains(id))
.collect(Collectors.toList());
}
private List<Long> buildAdminPermission(RoleWithFeature role, List<WorkspaceFeatureRelation> allFeatures) {
//超管和管理员 直接取和角色类型匹配的租户产品权限
return allFeatures.stream()
.filter(f -> Objects.equals(f.getProductUnitType(), role.getProductUnitType())
|| !NumberUtil.isPositiveNumber(role.getProductUnitType()))
.map(WorkspaceFeatureRelation::getFeatureId)
.collect(Collectors.toList());
}
private List<WorkspaceFeatureRelation> listWorkspaceFeatureRelations(PermissionQueryContext context) {
//TODO:@Zhan 本期没做产品权限配置这里暂时先查询所有OMS资源作为已配置产品权限
List<ResourcePermission> permissions = featureResourceService.permissionQuery(ResourcePermissionQueryDTO.builder()
.terminals(Collections.singletonList(TerminalInfo.NT_OMS_WEB))
.build());
List<WorkspaceFeatureRelation> result = new ArrayList<>();
for (WorkspaceOUPair ow : context.getWorkspaceOUPairs()) {
List<WorkspaceFeatureRelation> owPermission = permissions.stream()
.map(p -> WorkspaceFeatureRelation.builder()
.workspaceId(ow.getWorkspaceId())
.productUnitType(SaasCooperateShipCooperateTypeEnum.OMS.code)
.featureId(p.getId())
.build())
.collect(Collectors.toList());
result.addAll(owPermission);
}
return result;
}
private List<SaasRoleUserRelation> listRoleUserRelations(PermissionQueryContext context) {
if (CollectionUtil.isNotEmpty(context.getPreviewRoleIds())) {
//指定了角色 则不需要去查用户角色关系
log.info("mock specify roles relation");
return mockRoleUserRelation(context);
}
//查询人员角色关系
Set<Long> workspaceIds = new HashSet<>();
Set<Long> ouIds = new HashSet<>();
Set<String> owKeys = new HashSet<>();
List<WorkspaceOUPair> workspaceOUPairs = context.getWorkspaceOUPairs();
workspaceOUPairs.forEach(ow -> {
workspaceIds.add(ow.getWorkspaceId());
ouIds.add(ow.getOuId());
owKeys.add(KeyUtil.buildKeyBySeparator(ow.getWorkspaceId(), ow.getOuId()));
});
UserIdentity userIdentity = context.getUserIdentity();
List<SaasRoleUserRelation> relations = roleUserService.queryByWorkspaceIdOrOu(userIdentity.getPersonId(),
userIdentity.getIdentityId(), IdentityType.getIdentityType(userIdentity.getIdentityType()), workspaceIds, ouIds);
if (CollectionUtil.isEmpty(relations)) {
log.warn("no user role relations found");
return relations;
}
//工作台和单位需成对查询 对结果二次过滤
return relations.stream()
.filter(roleUserService -> owKeys.contains(
KeyUtil.buildKeyBySeparator(roleUserService.getWorkspaceId(), roleUserService.getOuId())))
.collect(Collectors.toList());
}
private List<SaasRoleUserRelation> mockRoleUserRelation(PermissionQueryContext context) {
final List<SaasRoleUserRelation> relations = new ArrayList<>();
List<WorkspaceOUPair> workspaceOUPairs = context.getWorkspaceOUPairs();
// mock 看做已有指定的角色
for (WorkspaceOUPair ow : workspaceOUPairs) {
List<SaasRoleUserRelation> mockRelations = context.getPreviewRoleIds().stream().map(id -> {
SaasRoleUserRelation relation = new SaasRoleUserRelation();
relation.setRoleId(id);
relation.setOuId(ow.getOuId());
relation.setWorkspaceId(ow.getWorkspaceId());
relation.setIdentityId(context.getUserIdentity().getIdentityId());
relation.setIdentityType(context.getUserIdentity().getIdentityType());
// 使用角色ID替代不需要在查询一次
relation.setId(id);
return relation;
}).collect(Collectors.toList());
relations.addAll(mockRelations);
}
return relations;
}
}

View File

@ -4,22 +4,30 @@ 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.pokonyan.dao.converter.PageConverter;
import cn.axzo.pokonyan.dao.mysql.QueryWrapperHelper;
import cn.axzo.tyr.client.common.enums.RoleResourceTypeEnum;
import cn.axzo.tyr.client.common.enums.RoleTypeEnum;
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.ChangeGroupLeaderRoleReq;
import cn.axzo.tyr.client.model.req.FeatureRoleRelationReq;
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.FeatureRoleRelationResp;
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.res.SaasPermissionRes;
import cn.axzo.tyr.client.model.res.SaasRoleGroupRes;
import cn.axzo.tyr.client.model.res.SaasRoleRes;
import cn.axzo.tyr.client.model.vo.DeleteRoleVO;
import cn.axzo.tyr.client.model.vo.SaasPermissionGroupVO;
import cn.axzo.tyr.client.model.vo.SaasRoleAndGroupVO;
import cn.axzo.tyr.client.model.vo.SaasRoleCategoryVO;
@ -27,14 +35,20 @@ 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.model.ResourcePermission;
import cn.axzo.tyr.server.model.ResourcePermissionQueryDTO;
import cn.axzo.tyr.server.model.RoleFeatureRelation;
import cn.axzo.tyr.server.model.RoleWithFeature;
import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
import cn.axzo.tyr.server.repository.dao.SaasPermissionGroupDao;
import cn.axzo.tyr.server.repository.dao.SaasPgroupPermissionRelationDao;
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.SaasFeatureResource;
import cn.axzo.tyr.server.repository.entity.SaasPermissionGroup;
import cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation;
import cn.axzo.tyr.server.repository.entity.SaasPgroupRoleRelation;
@ -43,8 +57,10 @@ 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.repository.mapper.SaasRoleMapper;
import cn.axzo.tyr.server.service.PermissionGroupService;
import cn.axzo.tyr.server.service.RoleService;
import cn.axzo.tyr.server.service.SaasFeatureResourceService;
import cn.axzo.tyr.server.service.SaasPgroupPermissionRelationService;
import cn.axzo.tyr.server.service.SaasRoleGroupRelationService;
import cn.axzo.tyr.server.service.SaasRoleGroupService;
@ -52,15 +68,24 @@ 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.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
@ -68,8 +93,10 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -91,7 +118,8 @@ import java.util.stream.Stream;
@RequiredArgsConstructor
@RefreshScope
@Service
public class RoleServiceImpl implements RoleService {
public class RoleServiceImpl extends ServiceImpl<SaasRoleMapper, SaasRole>
implements RoleService {
@Autowired
SaasRoleUserRelationDao roleUserRelationDao;
@ -119,9 +147,13 @@ public class RoleServiceImpl implements RoleService {
@Autowired
SaasRoleUserRelationDao saasRoleUserRelationDao;
@Autowired
SaasPgroupPermissionRelationDao saasPgroupPermissionRelationDao;
@Autowired
RoleUserService roleUserService;
@Autowired
SaasRoleGroupRelationDao saasRoleGroupRelationDao;
@Autowired
SaasFeatureResourceService saasFeatureResourceService;
@Value("${groupLeader.code:projectTeamGPLeader}")
private String groupLeaderCode;
@ -244,6 +276,10 @@ public class RoleServiceImpl implements RoleService {
.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())
.eq(Objects.nonNull(req.getIsDisplay()), SaasRole::getIsDisplay, req.getIsDisplay())
.eq(Objects.nonNull(req.getEnabled()), SaasRole::getEnabled, req.getEnabled())
.notIn(CollectionUtils.isNotEmpty(req.getRoleTypesNotIn()), SaasRole::getRoleType, req.getRoleTypesNotIn())
.eq(Objects.nonNull(req.getProductUnitType()), SaasRole::getProductUnitType, req.getProductUnitType())
.orderByDesc(BaseEntity::getId)
.list();
return getByIds(list.stream().map(BaseEntity::getId).collect(Collectors.toList()), req.getIsCommon(), req.getWorkspaceId(), req.getOuId(), req.getIncludePermissionGroup(), req.getIncludeSpecialRole());
@ -294,7 +330,11 @@ public class RoleServiceImpl implements RoleService {
SaasRole saasRole = validAndBuildRole(saveOrUpdateRole, now);
//验证权限集信息
SaasPermissionGroup saasPermissionGroup = validPermissionGroupCommon(saveOrUpdateRole);
// TODO 旧的权限,待权限切完后就下掉
validFeature(saveOrUpdateRole.getSelectedPPIds());
// 新的权限
validPermission(saveOrUpdateRole.getPermissionIds());
saasRoleDao.saveOrUpdate(saasRole);
// 新增或者保存分组和角色映射关系
@ -318,16 +358,24 @@ public class RoleServiceImpl implements RoleService {
if (Objects.isNull(saveOrUpdateRole.getId())) {
saasPgroupRoleRelationDao.save(pgrr);
}
// 保存权限集和权限点映射关系
List<SaasPgroupPermissionRelation> pgpRelations = Optional.ofNullable(saveOrUpdateRole.getSelectedPPIds()).orElse(new ArrayList<>()).stream().map(ppId -> {
SaasPgroupPermissionRelation target = new SaasPgroupPermissionRelation();
target.setGroupId(saasPermissionGroup.getId());
target.setFeatureId(ppId);
target.setCreateBy(saveOrUpdateRole.getOperatorId());
target.setUpdateBy(saveOrUpdateRole.getOperatorId());
return target;
}).collect(Collectors.toList());
saasPgroupPermissionRelationService.saveOrUpdate(Lists.newArrayList(saasPermissionGroup.getId()), pgpRelations);
if (CollectionUtils.isNotEmpty(saveOrUpdateRole.getSelectedPPIds())
|| CollectionUtils.isNotEmpty(saveOrUpdateRole.getPermissionIds())) {
List<Long> pids = Optional.ofNullable(saveOrUpdateRole.getSelectedPPIds())
.orElseGet(() -> Lists.newArrayList(saveOrUpdateRole.getPermissionIds()));
// 保存权限集和权限点映射关系
List<SaasPgroupPermissionRelation> pgpRelations = pids.stream().map(ppId -> {
SaasPgroupPermissionRelation target = new SaasPgroupPermissionRelation();
target.setGroupId(saasPermissionGroup.getId());
target.setFeatureId(ppId);
target.setCreateBy(saveOrUpdateRole.getOperatorId());
target.setUpdateBy(saveOrUpdateRole.getOperatorId());
return target;
}).collect(Collectors.toList());
saasPgroupPermissionRelationService.saveOrUpdate(Lists.newArrayList(saasPermissionGroup.getId()), pgpRelations);
}
return saasRole.getId();
}
@ -416,8 +464,43 @@ public class RoleServiceImpl implements RoleService {
return saasRoleDao.listRoleUserByPermissionGroup(permissionGroupIdList, workspaceIds);
}
private void checkRoleCode(SaveOrUpdateRoleVO saveOrUpdateRole) {
if (StringUtils.isBlank(saveOrUpdateRole.getRoleCode())) {
return;
}
List<SaasRoleRes> oldSaasRoles = this.list(ListSaasRoleParam.builder()
.roleCode(saveOrUpdateRole.getRoleCode())
.idNE(saveOrUpdateRole.getId())
.build());
if (CollectionUtils.isNotEmpty(oldSaasRoles)) {
throw new ServiceException("角色编码已存在");
}
}
/**
*
* @param saveOrUpdateRole
* @return
*/
private Integer resolveWorkspaceType(SaveOrUpdateRoleVO saveOrUpdateRole) {
if (CollectionUtils.isNotEmpty(saveOrUpdateRole.getGroupTree())) {
String workspaceTypeCode = saveOrUpdateRole.getGroupTree().get(0).getWorkspaceTypeCode();
if (StringUtils.isBlank(workspaceTypeCode)) {
throw new ServiceException("角色分组workspaceType不能为空");
}
return Integer.parseInt(workspaceTypeCode);
}
if (saveOrUpdateRole.getWorkspaceType() == null) {
throw new ServiceException("角色workspaceType不能为空");
}
return saveOrUpdateRole.getWorkspaceType();
}
private SaasRole validAndBuildRole(SaveOrUpdateRoleVO saveOrUpdateRole, Date now) {
SaasRole saasRole;
checkRoleCode(saveOrUpdateRole);
if (Objects.isNull(saveOrUpdateRole.getId())) {
saasRole = new SaasRole();
saasRole.setCreateBy(saveOrUpdateRole.getOperatorId());
@ -428,15 +511,19 @@ public class RoleServiceImpl implements RoleService {
throw new ServiceException("角色不存在");
}
}
saasRole.setRoleCode(saveOrUpdateRole.getRoleCode());
saasRole.setIsDisplay(saveOrUpdateRole.getIsDisplay());
saasRole.setEnabled(saveOrUpdateRole.getEnabled());
saasRole.setName(saveOrUpdateRole.getName());
saasRole.setDescription(saasRole.getDescription());
saasRole.setRoleType(saveOrUpdateRole.getRoleType());
saasRole.setWorkspaceId(saveOrUpdateRole.getWorkspaceId());
saasRole.setOwnerOuId(saveOrUpdateRole.getOwnerOuId());
saasRole.setWorkspaceType(Integer.parseInt(saveOrUpdateRole.getGroupTree().get(0).getWorkspaceTypeCode()));
saasRole.setProductUnitType(setProductUnitType(saveOrUpdateRole.getGroupTree().get(0)));
Integer workspaceType = resolveWorkspaceType(saveOrUpdateRole);
saasRole.setWorkspaceType(workspaceType);
saasRole.setUpdateBy(saveOrUpdateRole.getOperatorId());
saasRole.setUpdateAt(now);
saasRole.setProductUnitType(setProductUnitType(saveOrUpdateRole));
String message = "角色校验异常";
List<SaasRoleGroupRelation> relations = Lists.newArrayList();
//系统预设角色分组 同分组内角色名称不能重复
@ -447,11 +534,11 @@ public class RoleServiceImpl implements RoleService {
message = "同一角色分组内,角色名称不能重复!";
} else {
//自定义角色 同一个企业单位 同一个工作台 角色名称不能为空
String currentWorkspaceCode = saveOrUpdateRole.getGroupTree().get(0).getWorkspaceTypeCode();
List<Long> systemAndCustomWorkspaceCodes = new ArrayList<>();
systemAndCustomWorkspaceCodes.add(Long.valueOf(currentWorkspaceCode));
systemAndCustomWorkspaceCodes.add(Long.valueOf(workspaceType));
systemAndCustomWorkspaceCodes.add(-1L);
List<Long> systemAndCustomOuIds = new ArrayList<>();
systemAndCustomOuIds.add(saveOrUpdateRole.getOwnerOuId());
systemAndCustomOuIds.add(-1L);
@ -485,17 +572,52 @@ public class RoleServiceImpl implements RoleService {
}
});
}
assembleSort(saveOrUpdateRole, saasRole);
return saasRole;
}
private void assembleSort(SaveOrUpdateRoleVO saveOrUpdateRole, SaasRole saasRole) {
if (saveOrUpdateRole.getSort() != null) {
saasRole.setSort(saveOrUpdateRole.getSort());
return;
}
// 新增时且没有传sort时才自动维护一个最大的sort
if (saasRole.getId() != null || CollectionUtils.isEmpty(saveOrUpdateRole.getGroupTree())) {
return;
}
List<SaasRoleGroupRelation> saasRoleGroupRelations = saasRoleGroupRelationDao.getByGroupIds(Lists.transform(saveOrUpdateRole.getGroupTree(), SaveOrUpdateRoleVO.GroupInfoVO::getId));
if (CollectionUtils.isEmpty(saasRoleGroupRelations)) {
saasRole.setSort(1);
return;
}
Optional<SaasRole> last = this.lambdaQuery()
.in(SaasRole::getId, Lists.transform(saasRoleGroupRelations, SaasRoleGroupRelation::getRoleId))
.eq(SaasRole::getIsDelete, TableIsDeleteEnum.NORMAL.value)
.orderByDesc(SaasRole::getSort)
.last("limit 1")
.list()
.stream()
.findFirst();
saasRole.setSort(last.map(e -> e.getSort() == null ? 1 : e.getSort() + 1).orElse(1));
}
/**
* 产品单位类型
*/
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 Integer setProductUnitType(SaveOrUpdateRoleVO saveOrUpdateRoleVO) {
if (CollectionUtils.isNotEmpty(saveOrUpdateRoleVO.getGroupTree())) {
SaasRoleGroup saasRoleGroup = saasRoleGroupDao.lambdaQuery()
.in(SaasRoleGroup::getId, saveOrUpdateRoleVO.getGroupTree().get(0).getId())
.eq(SaasRoleGroup::getIsDelete, TableIsDeleteEnum.NORMAL.value).one();
return Integer.parseInt(saasRoleGroup.getOuTypeCode());
}
return saveOrUpdateRoleVO.getProductUnitType();
}
private void validFeature(List<Long> featureIds) {
@ -634,6 +756,8 @@ public class RoleServiceImpl implements RoleService {
roleWithUser.setRoleId(role.getId());
roleWithUser.setRoleName(role.getName());
roleWithUser.setRoleType(role.getRoleType());
roleWithUser.setIsDisplay(role.getIsDisplay());
roleWithUser.setEnabled(role.getEnabled());
List<SaasRoleUserRelation> relations = relationMap.get(role.getId());
if (CollectionUtil.isNotEmpty(relations)) {
@ -752,20 +876,26 @@ public class RoleServiceImpl implements RoleService {
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteRole(List<Long> roleIds, Long workSpaceId, Long ouId) {
List<SaasRoleUserRelation> saasRoleUserRelations = roleUserRelationDao.lambdaQuery()
.in(CollectionUtil.isNotEmpty(roleIds), SaasRoleUserRelation::getRoleId, roleIds)
.eq(workSpaceId != null, SaasRoleUserRelation::getWorkspaceId, workSpaceId)
.eq(ouId != null, SaasRoleUserRelation::getOuId, ouId)
.eq(BaseEntity::getIsDelete, TableIsDeleteEnum.NORMAL.value)
.list();
public void deleteRole(DeleteRoleVO deleteRoleParam) {
if (CollectionUtil.isNotEmpty(saasRoleUserRelations)) {
throw new cn.axzo.basics.common.exception.ServiceException("当前角色已被用户使用,无法删除!");
if (BooleanUtils.isTrue(deleteRoleParam.isNeedUsedCheck())) {
List<SaasRoleUserRelation> saasRoleUserRelations = roleUserRelationDao.lambdaQuery()
.in(CollectionUtil.isNotEmpty(deleteRoleParam.getRoleIds()), SaasRoleUserRelation::getRoleId, deleteRoleParam.getRoleIds())
.eq(deleteRoleParam.getWorkSpaceId() != null, SaasRoleUserRelation::getWorkspaceId, deleteRoleParam.getWorkSpaceId())
.eq(deleteRoleParam.getOutId() != null, SaasRoleUserRelation::getOuId, deleteRoleParam.getOutId())
.eq(BaseEntity::getIsDelete, TableIsDeleteEnum.NORMAL.value)
.list();
if (CollectionUtil.isNotEmpty(saasRoleUserRelations)) {
throw new cn.axzo.basics.common.exception.ServiceException("当前角色已被用户使用,无法删除!");
}
}
saasRoleDao.delete(roleIds);
roleUserRelationDao.deleteByRoleId(roleIds);
roleGroupRelationDao.deleteGroupRelation(roleIds);
saasRoleDao.delete(deleteRoleParam.getRoleIds());
// 未根据id进行更新会存在死锁的风险但是角色的操作频率很低可以先不考虑
roleUserRelationDao.deleteByRoleId(deleteRoleParam.getRoleIds());
roleGroupRelationDao.deleteGroupRelation(deleteRoleParam.getRoleIds());
saasPgroupRoleRelationDao.deleteByRoleId(deleteRoleParam.getRoleIds());
}
@Override
@ -783,9 +913,11 @@ public class RoleServiceImpl implements RoleService {
if (CollectionUtils.isEmpty(categoryCodes)) {
return new ArrayList<>();
}
List<SaasRoleCategoryVO> result = new ArrayList<>();
List<SaasRoleGroup> saasRoleGroups = saasRoleGroupDao.listByCategoryCode(categoryCodes);
//category code转code 查询对应code及子级
List<SaasRoleGroup> saasRoleGroups = saasRoleGroupService.listByCodes(categoryCodes, 3);
//查询角色组相关角色及配置的权限
Set<Long> roleGroupId = saasRoleGroups.stream().map(BaseEntity::getId).collect(Collectors.toSet());
List<SaasRoleGroupRelation> roleGroupRelations = saasRoleGroupRelationDao.getByGroupIds(roleGroupId);
@ -806,7 +938,21 @@ public class RoleServiceImpl implements RoleService {
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));
//按查询的code分组所有group
Map<Long, List<SaasRoleGroup>> allGroupMap = saasRoleGroups.stream().collect(Collectors.groupingBy(SaasRoleGroup::getParentId));
List<SaasRoleGroup> categoryRoleGroups = saasRoleGroupService.listByCodes(categoryCodes, 1);
Map<String, SaasRoleGroup> categoryMap = categoryRoleGroups.stream().collect(Collectors.toMap(SaasRoleGroup::getCode, Function.identity()));
Map<String, List<SaasRoleGroup>> groupsByCategory = new HashMap<>();
for (Map.Entry<String, SaasRoleGroup> entry : categoryMap.entrySet()) {
SaasRoleGroup parent = entry.getValue();
List<SaasRoleGroup> groups = groupsByCategory.getOrDefault(entry.getKey(), new ArrayList<>());
List<SaasRoleGroup> children = allGroupMap.get(parent.getId());
if (CollectionUtil.isNotEmpty(children)) {
groups.addAll(children);
}
groupsByCategory.put(entry.getKey(), groups);
}
return groupsByCategory.entrySet().stream()
.map(entry -> {
@ -820,6 +966,7 @@ public class RoleServiceImpl implements RoleService {
List<Long> groupIdList = g.getValue().stream().map(SaasRoleGroup::getId).collect(Collectors.toList());
List<SaasRoleGroupRelation> roleGroupRelationList = groupIdList.stream().map(groupByGroupId::get)
.filter(Objects::nonNull)
.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());
@ -975,4 +1122,260 @@ public class RoleServiceImpl implements RoleService {
.or().eq(SaasRole::getRoleType, RoleTypeEnum.ADMIN.getValue());})
.list();
}
@Override
public List<RoleWithFeature> listWithFeatures(Set<Long> roleIds, Set<Long> featureIds) {
List<RoleWithFeature> result = new ArrayList<>();
List<SaasRole> roles = saasRoleDao.lambdaQuery()
.in(SaasRole::getId, roleIds)
.eq(SaasRole::getEnabled, true)
.list();
if (CollectionUtil.isEmpty(roles)) {
log.warn("no enabled roles found for ids:{}", roles);
return result;
}
List<RoleFeatureRelation> relations = saasRoleDao.listFeatureByIds(roleIds, featureIds);
Map<Long, Set<Long>> mapping = relations.stream()
.collect(Collectors.groupingBy(RoleFeatureRelation::getRoleId,
Collectors.mapping(RoleFeatureRelation::getFeatureId, Collectors.toSet())));
for (SaasRole role : roles) {
result.add(RoleWithFeature.builder()
.roleId(role.getId())
.roleName(role.getName())
.roleType(role.getRoleType())
.productUnitType(role.getProductUnitType())
.featureIds(mapping.getOrDefault(role.getId(), Collections.emptySet()))
.build());
}
return result;
}
@Override
public List<SaasRoleRes> list(ListSaasRoleParam param) {
return PageConverter.drainAll(pageNumber -> {
PageSaasRoleParam pageParam = PageSaasRoleParam.builder().build();
BeanUtils.copyProperties(param, pageParam);
pageParam.setPage(pageNumber);
pageParam.setPageSize(500);
return page(pageParam);
});
}
@Override
public Page<SaasRoleRes> page(PageSaasRoleParam param) {
QueryWrapper<SaasRole> wrapper = QueryWrapperHelper.fromBean(param, SaasRole.class);
wrapper.eq("is_delete", 0);
Page<SaasRole> page = this.page(PageConverter.convertToMybatis(param, SaasRole.class), wrapper);
Map<Long, List<SaasRoleGroupRes>> saasRoleGroups = listRoleGroups(param, page.getRecords());
Map<Long, List<SaasPermissionRes>> saasPermissions = listRolePermissions(param, page.getRecords());
return PageConverter.convert(page, (record) -> from(record,
saasRoleGroups,
saasPermissions));
}
private SaasRoleRes from(SaasRole saasRole,
Map<Long, List<SaasRoleGroupRes>> saasRoleGroups,
Map<Long, List<SaasPermissionRes>> saasPermissions) {
SaasRoleRes saasRoleRes = SaasRoleRes.builder().build();
BeanUtils.copyProperties(saasRole, saasRoleRes);
saasRoleRes.setSaasRoleGroups(saasRoleGroups.get(saasRoleRes.getId()));
saasRoleRes.setSaasPermissions(saasPermissions.get(saasRoleRes.getId()));
return saasRoleRes;
}
private Map<Long, List<SaasPermissionRes>> listRolePermissions(PageSaasRoleParam param,
List<SaasRole> saasRoles) {
if (CollectionUtils.isEmpty(saasRoles) || BooleanUtils.isNotTrue(param.getNeedPermission())) {
return Collections.emptyMap();
}
List<SaasPgroupRoleRelation> saasPgroupRoleRelations = saasPgroupRoleRelationDao.findByRoleIds(Lists.transform(saasRoles, SaasRole::getId));
if (CollectionUtils.isEmpty(saasPgroupRoleRelations)) {
return Collections.emptyMap();
}
List<SaasPgroupPermissionRelation> saasPgroupPermissionRelations = saasPgroupPermissionRelationDao.lambdaQuery()
.in(SaasPgroupPermissionRelation::getGroupId, Lists.transform(saasPgroupRoleRelations, SaasPgroupRoleRelation::getGroupId))
.eq(SaasPgroupPermissionRelation::getIsDelete, TableIsDeleteEnum.NORMAL.value)
.list();
if (CollectionUtils.isEmpty(saasPgroupPermissionRelations)) {
return Collections.emptyMap();
}
Map<Long, SaasPermissionRes> resourcePermissions = saasFeatureResourceService.permissionQuery(ResourcePermissionQueryDTO.builder()
.ids(Lists.transform(saasPgroupPermissionRelations, SaasPgroupPermissionRelation::getFeatureId))
.build())
.stream()
.map(e -> SaasPermissionRes.builder().id(e.getId()).featureCode(e.getFeatureCode()).build())
.collect(Collectors.toMap(SaasPermissionRes::getId, Function.identity()));
Map<Long, List<Long>> pgroupPermissions = saasPgroupPermissionRelations.stream()
.collect(Collectors.groupingBy(SaasPgroupPermissionRelation::getGroupId,
Collectors.mapping(SaasPgroupPermissionRelation::getFeatureId, Collectors.toList())));
return saasPgroupRoleRelations.stream()
.map(e -> {
List<Long> permissionIds = pgroupPermissions.get(e.getGroupId());
if (CollectionUtils.isEmpty(permissionIds)) {
return null;
}
return permissionIds.stream()
.map(permissionId -> {
SaasPermissionRes saasPermissionRes = resourcePermissions.get(permissionId);
return SaasPermissionWrapper.from(e, saasPermissionRes);
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
})
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.collect(Collectors.groupingBy(SaasPermissionWrapper::getRoleId,
Collectors.mapping(e -> SaasPermissionRes.builder().id(e.getId()).featureCode(e.getFeatureCode()).build(),
Collectors.toList())));
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
static class SaasPermissionWrapper {
private Long id;
/**
* 资源编码-权限码
*/
private String featureCode;
private Long roleId;
public static SaasPermissionWrapper from(SaasPgroupRoleRelation saasPgroupRoleRelation,
SaasPermissionRes saasPermissionRes) {
if (saasPermissionRes == null) {
return null;
}
return SaasPermissionWrapper.builder()
.id(saasPermissionRes.getId())
.featureCode(saasPermissionRes.getFeatureCode())
.roleId(saasPgroupRoleRelation.getRoleId())
.build();
}
}
private Map<Long, List<SaasRoleGroupRes>> listRoleGroups(PageSaasRoleParam param,
List<SaasRole> saasRoles) {
if (CollectionUtils.isEmpty(saasRoles) || BooleanUtils.isNotTrue(param.getNeedRoleGroup())) {
return Collections.emptyMap();
}
List<SaasRoleGroupRelation> roleGroupRelations = saasRoleGroupRelationDao.lambdaQuery()
.in(SaasRoleGroupRelation::getRoleId, Lists.transform(saasRoles, SaasRole::getId))
.eq(SaasRoleGroupRelation::getIsDelete, TableIsDeleteEnum.NORMAL.value)
.list();
if (CollectionUtils.isEmpty(roleGroupRelations)) {
return Collections.emptyMap();
}
Map<Long, SaasRoleGroup> saasRoleGroups = saasRoleGroupDao.query(QuerySaasRoleGroupReq.builder()
.ids(Lists.transform(roleGroupRelations, SaasRoleGroupRelation::getSaasRoleGroupId))
.build())
.stream()
.collect(Collectors.toMap(SaasRoleGroup::getId, Function.identity()));
return roleGroupRelations.stream()
.filter(e -> saasRoleGroups.get(e.getSaasRoleGroupId()) != null)
.collect(Collectors.groupingBy(SaasRoleGroupRelation::getRoleId,
Collectors.mapping(e -> {
SaasRoleGroup saasRoleGroup = saasRoleGroups.get(e.getSaasRoleGroupId());
return toRoleGroupRes(saasRoleGroup);
}, Collectors.toList())));
}
private SaasRoleGroupRes toRoleGroupRes(SaasRoleGroup saasRoleGroup) {
if (saasRoleGroup == null) {
return null;
}
SaasRoleGroupRes saasRoleGroupRes = SaasRoleGroupRes.builder().build();
BeanUtils.copyProperties(saasRoleGroup, saasRoleGroupRes);
return saasRoleGroupRes;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void saveOrUpdateFeatureRoleRelation(List<FeatureRoleRelationReq.RelationRoleSettings> req, Long operatorId) {
for (FeatureRoleRelationReq.RelationRoleSettings item : req) {
saasFeatureResourceService.updateFeatureAuthType(item.getFeatureId(), item.getAuthType());
if (CollectionUtil.isEmpty(item.getRoleIds()) || item.getAuthType() == 0) {
saasPgroupPermissionRelationDao.removeByPermissionPointIds(Collections.singletonList(item.getFeatureId()));
} else {
List<Long> existGroupIds = saasPgroupPermissionRelationDao.queryByFeatureIds(Collections.singletonList(item.getFeatureId()))
.stream().map(SaasPgroupPermissionRelation::getGroupId).collect(Collectors.toList());
List<Long> groupIds = saasPgroupRoleRelationDao.findByRoleIds(item.getRoleIds())
.stream().map(SaasPgroupRoleRelation::getGroupId).collect(Collectors.toList());
List<Long> insertGroupIds = groupIds.stream().filter(role -> !existGroupIds.contains(role)).collect(Collectors.toList());
List<Long> deleteGroupIds = existGroupIds.stream().filter(role -> !groupIds.contains(role)).collect(Collectors.toList());
// 新增的
if (CollectionUtils.isNotEmpty(insertGroupIds)) {
List<SaasPgroupPermissionRelation> insertRelation = new ArrayList<>();
insertGroupIds.forEach(groupId -> {
SaasPgroupPermissionRelation relation = new SaasPgroupPermissionRelation();
relation.setFeatureId(item.getFeatureId());
relation.setGroupId(groupId);
relation.setCreateBy(operatorId);
insertRelation.add(relation);
});
saasPgroupPermissionRelationDao.saveBatch(insertRelation);
}
// 删除的
if (CollectionUtils.isNotEmpty(deleteGroupIds)) {
saasPgroupPermissionRelationDao.removeByFeatureIdAndGroupIds(item.getFeatureId(), deleteGroupIds, operatorId);
}
}
}
}
@Override
public FeatureRoleRelationResp queryFeatureRoleRelation(Long featureId) {
SaasFeatureResource featureResource = saasFeatureResourceService.featureResourceById(featureId);
Assert.notNull(featureResource, "菜单不存在");
FeatureRoleRelationResp resp = new FeatureRoleRelationResp();
resp.setFeatureId(featureId);
resp.setAuthType(featureResource.getAuthType());
List<SaasPgroupPermissionRelation> pgroupPermissionRelations = saasPgroupPermissionRelationDao.queryByFeatureIds(Collections.singletonList(featureId));
if (CollectionUtil.isNotEmpty(pgroupPermissionRelations)) {
List<Long> groupIds = pgroupPermissionRelations.stream().map(SaasPgroupPermissionRelation::getGroupId).collect(Collectors.toList());
List<SaasPgroupRoleRelation> relations = saasPgroupRoleRelationDao.listByGroupIds(groupIds);
if (CollectionUtil.isNotEmpty(relations)) {
List<Long> roleIds = relations.stream().map(SaasPgroupRoleRelation::getRoleId).collect(Collectors.toList());
resp.setRoleIds(roleIds);
}
}
return resp;
}
private void validPermission(Set<Long> permissionIds) {
if (CollectionUtils.isEmpty(permissionIds)) {
return;
}
List<ResourcePermission> resourcePermissions = saasFeatureResourceService.permissionQuery(ResourcePermissionQueryDTO.builder()
.ids(Lists.newArrayList(permissionIds))
.build());
if (permissionIds.size() != resourcePermissions.size()) {
permissionIds.removeAll(resourcePermissions.stream().map(ResourcePermission::getId).collect(Collectors.toSet()));
throw new ServiceException(String.format("权限点 %s 信息错误", permissionIds));
}
}
}

View File

@ -11,32 +11,25 @@ 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.GetUserAutoOwnRoleResp;
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.roleuser.req.*;
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.repository.dao.*;
import cn.axzo.tyr.server.repository.entity.*;
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 cn.hutool.json.JSONUtil;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
@ -65,6 +58,7 @@ public class RoleUserService implements SaasRoleUserService {
private final SaasPgroupRoleRelationDao saasPgroupRoleRelationDao;
private final SaasRoleGroupService saasRoleGroupService;
private final SaasRoleGroupRelationDao saasRoleGroupRelationDao;
private final SaasPgroupPermissionRelationDao saasPgroupPermissionRelationDao;
// 单位类型默认角色关系,后面可以座位管理员的逻辑进行迭代
@Value("#{${participateUnitDefaultRoleId:{}}}")
@ -74,6 +68,9 @@ public class RoleUserService implements SaasRoleUserService {
@Value("${platWorkerLeaderRoleId:100001}")
private Long projWorkerLeaderRoleId;
@Value("#{${axzo.role.superAdmin}}")
private Map<Integer, String> superAdminCodes;
/**
* 获取分包负责人等特殊角色
* @return
@ -103,14 +100,18 @@ public class RoleUserService implements SaasRoleUserService {
// 查询用户所有角色
List<SaasRoleUserRelation> existsRoleUser = roleUserRelationDao.query(req.getIdentityId(), req.getIdentityType().getCode(), req.getWorkspaceId(), req.getOuId());
// 当前用户非超管的角色
List<Long> notAdminRole = Collections.emptyList();
// 当前用户非超管自定义的角色
List<Long> notAdminAndAutoOwnRole = Collections.emptyList();
if (CollectionUtils.isNotEmpty(existsRoleUser)) {
List<SaasRole> existsRole = saasRoleDao.listByIds(existsRoleUser.stream().mapToLong(SaasRoleUserRelation::getRoleId).boxed().collect(Collectors.toList()));
// 管理员角色
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());
// 自定义角色
Long autoOwnRole = existsRole.stream().filter(e -> RoleTypeEnum.AUTO_OWN.equals(RoleTypeEnum.getRoleType(e.getRoleType()))).findFirst().map(SaasRole::getId).orElse(0L);
log.info("personId:{} autoOwnRole:{} adminRole:{}", req.getPersonId(), autoOwnRole, JSONUtil.toJsonStr(adminRole));
// 排除管理员角色自定义角色(普通角色) 这里用过滤的方式是为了防止脏数据产生(saas_role_user_relation表有用户数据但是角色表已经被删除)
notAdminAndAutoOwnRole = existsRoleUser.stream().mapToLong(SaasRoleUserRelation::getRoleId).boxed().filter(roleId -> !adminRole.contains(roleId))
.filter(roleId -> !autoOwnRole.equals(roleId)).collect(Collectors.toList());
}
BaseWorkspaceModel workspaceModel = BaseWorkspaceModel.builder()
.workspaceId(req.getWorkspaceId()).ouId(req.getOuId())
@ -118,20 +119,20 @@ public class RoleUserService implements SaasRoleUserService {
.build();
// 删除现有非管理员的角色
if (CollectionUtils.isNotEmpty(notAdminRole)) {
if (CollectionUtils.isNotEmpty(notAdminAndAutoOwnRole)) {
//如果该接口支持 权限回收那么参数UpdateRoleIds就是待删除的权限合集
if (req.isRecycleModel()) {
notAdminRole.clear();
notAdminAndAutoOwnRole.clear();
//回收角色权限,只移除用户传参的权限
notAdminRole.addAll(req.getUpdateRoleIds());
roleUserRelationDao.deleteByUser(workspaceModel, notAdminRole);
notAdminAndAutoOwnRole.addAll(req.getUpdateRoleIds());
roleUserRelationDao.deleteByUser(workspaceModel, notAdminAndAutoOwnRole);
return;
}
roleUserRelationDao.deleteByUser(workspaceModel, notAdminRole);
roleUserRelationDao.deleteByUser(workspaceModel, notAdminAndAutoOwnRole);
}
if(req.isMergeExistsRoles()){
//合并新的角色和老的角色
updateRoleIds.addAll(notAdminRole);
updateRoleIds.addAll(notAdminAndAutoOwnRole);
}
// 清空所有角色
if (CollectionUtil.isEmpty(updateRoleIds)) {
@ -144,7 +145,6 @@ public class RoleUserService implements SaasRoleUserService {
saasRoleUserRelation.setIdentityType(req.getIdentityType().getCode());
saasRoleUserRelation.setRoleId(e);
saasRoleUserRelation.setNaturalPersonId(req.getPersonId());
saasRoleUserRelation.setNaturalPersonId(req.getPersonId());
saasRoleUserRelation.setOuId(req.getOuId());
saasRoleUserRelation.setWorkspaceId(req.getWorkspaceId());
return saasRoleUserRelation;
@ -177,31 +177,29 @@ public class RoleUserService implements SaasRoleUserService {
@Transactional(rollbackFor = Exception.class)
public void createSuperAdminRole(CreateSuperAdminRoleParam param) {
//获取超管角色
SaasRole saasRole = saasRoleDao
.findRoleByTypeAndWorkspaceIdAndOuId(RoleTypeEnum.SUPER_ADMIN.getValue(),
param.getWorkspaceId(), param.getOuId());
if (saasRole == null) {
saasRole = new SaasRole();
saasRole.setDescription(RoleTypeEnum.SUPER_ADMIN.getDesc());
saasRole.setName(RoleTypeEnum.SUPER_ADMIN.getDesc());
saasRole.setWorkspaceId(param.getWorkspaceId());
saasRole.setWorkspaceType(param.getWorkspaceType());
saasRole.setOwnerOuId(param.getOuId());
saasRole.setRoleType(RoleTypeEnum.SUPER_ADMIN.getValue());
saasRole.setIsDelete(0L);
SaasRole superAdmin = findSuperAdmin(param.getWorkspaceId(), param.getOuId(), param.getWorkspaceType());
if (superAdmin == null) {
superAdmin = new SaasRole();
superAdmin.setDescription(RoleTypeEnum.SUPER_ADMIN.getDesc());
superAdmin.setName(RoleTypeEnum.SUPER_ADMIN.getDesc());
superAdmin.setWorkspaceId(param.getWorkspaceId());
superAdmin.setWorkspaceType(param.getWorkspaceType());
superAdmin.setOwnerOuId(param.getOuId());
superAdmin.setRoleType(RoleTypeEnum.SUPER_ADMIN.getValue());
superAdmin.setIsDelete(0L);
DictWorkSpaceTypeEnum dictWorkSpaceTypeEnum = DictWorkSpaceTypeEnum.getByValueWorkspaceType(param.getWorkspaceType());
saasRole.setProductUnitType(dictWorkSpaceTypeEnum == null ? 0 : dictWorkSpaceTypeEnum.getSuperAdminProductType());
superAdmin.setProductUnitType(dictWorkSpaceTypeEnum == null ? 0 : dictWorkSpaceTypeEnum.getSuperAdminProductType());
checkRoleName(RoleTypeEnum.SUPER_ADMIN.getDesc(), param.getWorkspaceId(), param.getOuId());
saasRoleDao.save(saasRole);
saasRoleDao.save(superAdmin);
}
//删除当前超管角色
roleUserRelationDao.deleteByRoleId(Lists.newArrayList(saasRole.getId()));
removeOldSuperAdmin(superAdmin.getId(), param.getWorkspaceId(), param.getOuId());
//新增关联关系
SaasRoleUserRelation saasRoleUserRelation = new SaasRoleUserRelation();
saasRoleUserRelation.setIdentityId(param.getIdentityId());
saasRoleUserRelation.setRoleId(saasRole.getId());
saasRoleUserRelation.setRoleId(superAdmin.getId());
saasRoleUserRelation.setIdentityType(param.getIdentityType().getCode());
saasRoleUserRelation.setNaturalPersonId(param.getNaturalPersonId());
saasRoleUserRelation.setOuId(param.getOuId());
@ -209,6 +207,30 @@ public class RoleUserService implements SaasRoleUserService {
roleUserRelationDao.save(saasRoleUserRelation);
}
private void removeOldSuperAdmin(Long id, Long workspaceId, Long ouId) {
roleUserRelationDao.remove(new LambdaQueryWrapper<SaasRoleUserRelation>()
.eq(SaasRoleUserRelation::getRoleId, id)
.eq(SaasRoleUserRelation::getWorkspaceId, workspaceId)
.eq(SaasRoleUserRelation::getOuId, ouId));
}
private SaasRole findSuperAdmin(Long workspaceId, Long ouId, Integer workspaceType) {
//优先取租户超管 没有再取标准角色超管
//租户超管
SaasRole superAdmin = saasRoleDao
.findRoleByTypeAndWorkspaceIdAndOuId(RoleTypeEnum.SUPER_ADMIN.getValue(),
workspaceId, ouId);
if (superAdmin != null) {
return superAdmin;
}
//标准角超管
String superAdminCode = superAdminCodes.get(workspaceType);
if (StrUtil.isBlank(superAdminCode)) {
throw new ServiceException("租户类型[" + workspaceType + "]未配置超管编码");
}
return saasRoleDao.lambdaQuery().eq(SaasRole::getRoleCode, superAdminCode).one();
}
private void checkRoleName(String name, Long workspaceId, Long ouId) {
List<SaasRole> saasRoles = saasRoleDao.listCommonRoleByNameAndWorkspaceIdAndOuId(name,
workspaceId, ouId);
@ -430,6 +452,90 @@ public class RoleUserService implements SaasRoleUserService {
}
@Override
@Transactional(rollbackFor = Exception.class)
public void saveOrUpdateAutoOwnRole(AutoOwnRoleUserReq req) {
SaasRole role = saasRoleDao.getById(req.getRoleId());
AssertUtil.notNull(role, "未配置自定义角色");
AssertUtil.isTrue(RoleTypeEnum.AUTO_OWN.equals(RoleTypeEnum.getRoleType(role.getRoleType())), "未配置自定义角色");
// 查询用户已存在角色
List<SaasRoleUserRelation> existsRoleUser = roleUserRelationDao.queryByPersonId(req.getPersonId(), req.getWorkspaceId(), req.getOuId());
Long autoOwnRoleId = null;
if (CollectionUtils.isNotEmpty(existsRoleUser)) {
List<Long> autoOwnRoles = existsRoleUser.stream().filter(e -> role.getId().equals(e.getRoleId())).mapToLong(SaasRoleUserRelation::getRoleId).boxed().collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(autoOwnRoles)) {
autoOwnRoleId = autoOwnRoles.get(0);
if (autoOwnRoles.size() > 1) {
log.warn("personId:{} ouId:{} workspaceId:{} has {} auto_own roles", req.getPersonId(), req.getOuId(), req.getWorkspaceId(), autoOwnRoles.size());
}
}
}
if (Objects.isNull(autoOwnRoleId)) {
SaasRoleUserRelation saasRoleUserRelation = new SaasRoleUserRelation();
saasRoleUserRelation.setIdentityId(req.getIdentityId());
saasRoleUserRelation.setIdentityType(req.getIdentityType().getCode());
saasRoleUserRelation.setRoleId(role.getId());
saasRoleUserRelation.setNaturalPersonId(req.getPersonId());
saasRoleUserRelation.setOuId(req.getOuId());
saasRoleUserRelation.setWorkspaceId(req.getWorkspaceId());
roleUserRelationDao.save(saasRoleUserRelation);
}
List<SaasPgroupRoleRelation> saasPgroupRoleRelations = saasPgroupRoleRelationDao.findByRoleIds(Sets.newHashSet(role.getId()));
AssertUtil.notEmpty(saasPgroupRoleRelations, "角色权限集不存在");
Long permissionGroupId = saasPgroupRoleRelations.get(0).getGroupId();
List<SaasPgroupPermissionRelation> saasPgroupPermissionRelations = saasPgroupPermissionRelationDao.lambdaQuery()
.eq(SaasPgroupPermissionRelation::getGroupId, permissionGroupId).eq(SaasPgroupPermissionRelation::getIsDelete, TableIsDeleteEnum.NORMAL.value).list();
// 新增是以featureIds维度新增删除是以SaasPgroupPermissionRelation的id维度删除
Set<Long> insertFeatureIds = getInsertFeatureIds(req.getFeatureIds(), saasPgroupPermissionRelations);
Set<Long> deleteIds = getDeleteIds(req.getFeatureIds(), saasPgroupPermissionRelations);
if (CollectionUtils.isNotEmpty(insertFeatureIds)) {
saasPgroupPermissionRelationDao.saveBatch(insertFeatureIds.stream().map(e -> {
SaasPgroupPermissionRelation relation = new SaasPgroupPermissionRelation();
relation.setGroupId(permissionGroupId);
relation.setFeatureId(e);
relation.setCreateBy(req.getOperatorId());
relation.setUpdateBy(req.getOperatorId());
return relation;
}).collect(Collectors.toList()));
}
if (CollectionUtils.isNotEmpty(deleteIds)) {
saasPgroupPermissionRelationDao.removeByIds(deleteIds);
}
}
@Override
public GetUserAutoOwnRoleResp getUserAutoOwnRole(GetUserAutoOwnRoleReq req) {
// 查询用户所有角色
List<SaasRoleUserRelation> existsRoleUser = roleUserRelationDao.queryByPersonId(req.getPersonId(), req.getWorkspaceId(), req.getOuId());
if (CollectionUtils.isEmpty(existsRoleUser)) {
return GetUserAutoOwnRoleResp.EMPTY;
}
List<SaasRole> existsAutoOwnRoles = saasRoleDao.listByIds(existsRoleUser.stream().mapToLong(SaasRoleUserRelation::getRoleId).boxed().collect(Collectors.toList()))
.stream().filter(e -> RoleTypeEnum.AUTO_OWN.equals(RoleTypeEnum.getRoleType(e.getRoleType()))).collect(Collectors.toList());
if (CollectionUtils.isEmpty(existsAutoOwnRoles)) {
log.info("personId:{} ouId:{} workspaceId:{} has not auto_own roles", req.getPersonId(), req.getOuId(), req.getWorkspaceId());
return GetUserAutoOwnRoleResp.EMPTY;
}
List<SaasPgroupRoleRelation> saasPgroupRoleRelations = saasPgroupRoleRelationDao.findByRoleIds(Sets.newHashSet(existsAutoOwnRoles.get(0).getId()));
if (CollectionUtils.isEmpty(saasPgroupRoleRelations)) {
return GetUserAutoOwnRoleResp.EMPTY;
}
List<SaasPgroupPermissionRelation> saasPgroupPermissionRelations = saasPgroupPermissionRelationDao.lambdaQuery()
.eq(SaasPgroupPermissionRelation::getGroupId, saasPgroupRoleRelations.get(0).getGroupId())
.eq(SaasPgroupPermissionRelation::getIsDelete, TableIsDeleteEnum.NORMAL.value).list();
return CollectionUtils.isEmpty(saasPgroupPermissionRelations) ? GetUserAutoOwnRoleResp.EMPTY : GetUserAutoOwnRoleResp.builder()
.roleId(existsAutoOwnRoles.get(0).getId())
.featureIds(saasPgroupPermissionRelations.stream().map(SaasPgroupPermissionRelation::getFeatureId).collect(Collectors.toList()))
.build();
}
private void batchRemoveByRoleUserInfo(RoleUserInfo roleUserBaseInfo) {
roleUserBaseInfo.getRoleUserResourceInfos().forEach(e -> {
@ -445,4 +551,25 @@ public class RoleUserService implements SaasRoleUserService {
});
}
private Set<Long> getInsertFeatureIds(Set<Long> featureIds, List<SaasPgroupPermissionRelation> existsPgroupPermissionRelations) {
if (CollectionUtils.isEmpty(featureIds)) {
return Collections.emptySet();
}
if (CollectionUtils.isEmpty(existsPgroupPermissionRelations)) {
return featureIds;
}
Set<Long> existsFeatureIds = existsPgroupPermissionRelations.stream().map(SaasPgroupPermissionRelation::getFeatureId).collect(Collectors.toSet());
return featureIds.stream().filter(e -> !existsFeatureIds.contains(e)).collect(Collectors.toSet());
}
private Set<Long> getDeleteIds(Set<Long> featureIds, List<SaasPgroupPermissionRelation> existsPgroupPermissionRelations) {
if (CollectionUtils.isEmpty(existsPgroupPermissionRelations)) {
return Collections.emptySet();
}
if (CollectionUtils.isEmpty(featureIds)) {
return existsPgroupPermissionRelations.stream().map(SaasPgroupPermissionRelation::getId).collect(Collectors.toSet());
}
return existsPgroupPermissionRelations.stream().filter(e -> !featureIds.contains(e.getFeatureId())).map(SaasPgroupPermissionRelation::getId).collect(Collectors.toSet());
}
}

View File

@ -0,0 +1,44 @@
package cn.axzo.tyr.server.service.impl;
import cn.axzo.basics.common.BeanMapper;
import cn.axzo.tyr.client.model.req.CommonDictQueryReq;
import cn.axzo.tyr.client.model.res.CommonDictResp;
import cn.axzo.tyr.server.repository.dao.SaasCommonDictDao;
import cn.axzo.tyr.server.repository.entity.SaasCommonDict;
import cn.axzo.tyr.server.service.SaasCommonDictService;
import cn.hutool.core.collection.CollectionUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* 通用字典服务实现
*
* @version V1.0
* @author: ZhanSiHu
* @date: 2024/3/26 17:40
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class SaasCommonDictServiceImpl implements SaasCommonDictService {
private final SaasCommonDictDao commonDictDao;
@Override
public List<CommonDictResp> query(CommonDictQueryReq req) {
List<SaasCommonDict> list = commonDictDao.lambdaQuery()
.eq(Objects.nonNull(req.getScope()), SaasCommonDict::getScope, req.getScope())
.in(CollectionUtil.isNotEmpty(req.getCodes()), SaasCommonDict::getDictCode, req.getCodes())
.list();
if (CollectionUtil.isEmpty(list)) {
return Collections.emptyList();
}
return BeanMapper.copyList(list, CommonDictResp.class);
}
}

Some files were not shown because too many files have changed in this diff Show More