Merge branch 'feature/REQ-2186-2298'

# Conflicts:
#	tyr-api/src/main/java/cn/axzo/tyr/client/model/req/PageRoleReq.java
#	tyr-api/src/main/java/cn/axzo/tyr/client/model/roleuser/req/RoleUserReq.java
#	tyr-server/src/main/java/cn/axzo/tyr/server/controller/role/SaasRoleGroupController.java
#	tyr-server/src/main/java/cn/axzo/tyr/server/service/impl/SaasRoleGroupServiceImpl.java
This commit is contained in:
lilong 2024-06-05 19:45:21 +08:00
commit 7cfc3ee687
38 changed files with 657 additions and 33 deletions

View File

@ -24,6 +24,7 @@ public enum FeatureResourceType {
APP_ENTRY(3, "应用入口"),
COMPONENT(4, "组件"),
ROOT(5, "ROOT"),
GROUP(6, "分组"),
;
private static final Map<Integer, FeatureResourceType> MAPPING = new HashMap<>();
@ -52,7 +53,8 @@ public enum FeatureResourceType {
return Arrays.asList(FeatureResourceType.MENU.getCode(),
FeatureResourceType.PAGE.getCode(),
FeatureResourceType.APP_ENTRY.getCode(),
FeatureResourceType.ROOT.getCode());
FeatureResourceType.ROOT.getCode(),
FeatureResourceType.GROUP.getCode());
}
public static List<Integer> pageTypes() {

View File

@ -3,6 +3,7 @@ package cn.axzo.tyr.client.feign;
import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.model.roleuser.dto.GetUserAutoOwnRoleResp;
import cn.axzo.tyr.client.model.roleuser.dto.GetUserFeatureResourceIdsResp;
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.*;
@ -106,11 +107,17 @@ public interface TyrSaasRoleUserApi {
* 保存/更新 用户自定义权限每次传入新的featureIds都会覆盖原来的所有featureIds
*/
@PostMapping("/api/saas-role-user/save-or-update-auto-own-role")
ApiResult<Void> saveOrUpdateAutoOwnRole(@RequestBody @Valid AutoOwnRoleUserReq req);
ApiResult<Void> saveOrUpdateAutoOwnRole(@RequestBody @Valid AutoOwnRoleUserReq req);
/**
* 查询用户自定义角色和权限
*/
@PostMapping("/api/saas-role-user/get-auto-own-role")
ApiResult<GetUserAutoOwnRoleResp> getUserAutoOwnRole(@RequestBody @Valid GetUserAutoOwnRoleReq req);
ApiResult<GetUserAutoOwnRoleResp> getUserAutoOwnRole(@RequestBody @Valid GetUserAutoOwnRoleReq req);
/**
* 查询用户权限featureResourceId
*/
@PostMapping("/api/saas-role-user/get-user-feature-resource-ids")
ApiResult<GetUserFeatureResourceIdsResp> getUserFeatureResourceIds(@RequestBody @Valid GetUserFeatureResourceIdsReq req);
}

View File

@ -22,7 +22,7 @@ public class FeatureResourceTreeSaveReq extends BaseFeatureResourceDO {
/** 路由地址 **/
private String linkUrl;
/** 路由类型 1-PC 2-小程序 3-原生 **/
/** 路由类型 1-PC 2-小程序 3-原生 4-h5**/
private Integer linkType;
/** APP适配参数 **/
@ -34,6 +34,16 @@ public class FeatureResourceTreeSaveReq extends BaseFeatureResourceDO {
/** 授权类型 0-全部角色 1-指定角色 **/
private Integer authType;
/**
* 应用范围(租户类型)1:企业工作台 2;项目工作台
*/
private Long workspaceType;
/**
* 最低版本序列,主要支持版本灰度策略
*/
private Integer version;
/** 页面组件对象 **/
private List<FeatureComponentSaveReq> componentSaveReqList;

View File

@ -1,6 +1,7 @@
package cn.axzo.tyr.client.model.req;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@ -13,6 +14,8 @@ import java.util.List;
@AllArgsConstructor
public class PageRoleReq extends ListRoleReq {
private Integer page;
private Integer pageSize;

View File

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Set;
@Data
@AllArgsConstructor
@ -46,4 +47,6 @@ public class QuerySaasRoleGroupReq {
private List<Long> roleIds;
private Long parentId;
private Set<Long> parentIds;
}

View File

@ -38,7 +38,7 @@ public class FeatureResourceDTO implements Serializable {
private String featureName;
/**
* 资源类型1-菜单 2-页面 3-应用入口 4-组件
* 资源类型1-菜单 2-页面 3-应用入口 4-组件 5-root 6-分组
*/
private Integer featureType;
@ -88,7 +88,7 @@ public class FeatureResourceDTO implements Serializable {
private String linkUrl;
/**
* 路由类型1-PC 2-小程序 3-原生
* 路由类型1-PC 2-小程序 3-原生 4-h5
*/
private Integer linkType;
@ -136,4 +136,19 @@ public class FeatureResourceDTO implements Serializable {
* 更新人
*/
private Long updateBy;
/**
* 应用范围(租户类型)1:企业工作台 2;项目工作台
*/
private Long workspaceType;
/**
* 最低版本序列,主要支持版本灰度策略
*/
private Integer version;
/**
* 唯一编码用于pre环境菜单同步
*/
private String uniCode;
}

View File

@ -24,6 +24,8 @@ public class FeatureResourceTreeNode extends FeatureResourceDTO implements IBase
private List<FeatureResourceTreeNode> children;
private List<String> roleCodes;
@JsonIgnore
@Override
public Long getNodeCode() {

View File

@ -23,8 +23,21 @@ public class RoleTreeRes {
*/
private String workspaceTypeCode;
/**
* 租户类型
*/
private String workspaceType;
/**
* 租户id
*/
private Long workspaceId;
/**
* 单位id
*/
private Long ouId;
/**
* 名字
*/

View File

@ -0,0 +1,25 @@
package cn.axzo.tyr.client.model.roleuser.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Set;
/**
* @author likunpeng
* @version 1.0
* @date 2024/5/22
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class GetUserFeatureResourceIdsResp {
/**
* 资源ID列表
*/
private Set<Long> featureResourceIds;
}

View File

@ -6,6 +6,8 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author haiyangjin
* @date 2023/9/14
@ -94,4 +96,9 @@ public class SaasRoleUserDTO {
* '是否启用'
*/
private Boolean enabled;
/**
* 更新时间
*/
private Date updateAt;
}

View File

@ -0,0 +1,44 @@
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;
import java.util.List;
/**
* @author likunpeng
* @date 2024/4/2
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class GetUserFeatureResourceIdsReq {
/**
* 工作台id
*/
@NotNull(message = "workspaceId不能为空")
private Long workspaceId;
/**
* 单位id
*/
@NotNull(message = "ouId不能为空")
private Long ouId;
/**
* 自然人id
*/
@NotNull(message = "personId不能为空")
private Long personId;
/**
* 查询的角色类型列表
*/
private List<Long> roleIds;
}

View File

@ -69,6 +69,10 @@ public class RoleUserReq {
*/
private boolean isRecycleModel;
/**
* 操作人
*/
private Long operator;
/**
* 更新时是否覆盖特殊角色
* 这些角色id是在nacos上的配置在cms的单位管理-通讯录不会回显该角色

View File

@ -123,6 +123,11 @@
<type>pom</type>
</dependency>
<dependency>
<groupId>cn.axzo.foundation</groupId>
<artifactId>common-lib</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.axzo.basics</groupId>
<artifactId>basics-profiles-api</artifactId>

View File

@ -0,0 +1,16 @@
package cn.axzo.tyr.server.config.exception;
import cn.axzo.foundation.result.IResultCode;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum BizResultCode implements IResultCode {
CANT_DELETE_ROLE_GROUP("100001", "不能删除角色分组,当前角色分组下有子角色分组"),
ROLE_GROUP_NOT_FOUND("100002", "角色分组不存在");
private String errorCode;
private String errorMessage;
}

View File

@ -1,7 +1,8 @@
package cn.axzo.tyr.server.config.exception;
import cn.axzo.basics.common.exception.ServiceException;
import cn.axzo.foundation.exception.BusinessException;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.azxo.framework.common.model.CommonResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.util.CollectionUtils;
@ -48,4 +49,9 @@ public class ExceptionAdviceHandler {
return ApiResult.err(objectErrorDefaultMessage);
}
@ExceptionHandler(BusinessException.class)
public CommonResponse<Void> businessExceptionHandler(BusinessException e) {
log.warn("参数错误", e);
return CommonResponse.error(Integer.valueOf(e.getErrorCode()), e.getErrorMsg());
}
}

View File

@ -305,13 +305,6 @@ public class SaasRoleController implements TyrSaasRoleApi {
return ApiListResult.ok(roleService.list(param));
}
@Override
public ApiListResult<SaasRoleRes> list(ListRoleReq request) {
RoleService.ListSaasRoleParam param = RoleService.ListSaasRoleParam.builder().build();
BeanUtils.copyProperties(request, param);
return ApiListResult.ok(roleService.list(param));
}
/**
* 只支持移动一位
* @param request
@ -418,6 +411,8 @@ public class SaasRoleController implements TyrSaasRoleApi {
.name(roleGroup.getName())
.type(ROLE_GROUP_TYPE)
.idStr(roleGroup.getId() + ":" + ROLE_GROUP_TYPE)
.workspaceId(roleGroup.getWorkspaceId())
.ouId(roleGroup.getOuId())
.build();
}

View File

@ -1,6 +1,7 @@
package cn.axzo.tyr.server.controller.role;
import cn.axzo.basics.common.exception.ServiceException;
import cn.axzo.foundation.exception.Axssert;
import cn.axzo.foundation.page.PageResp;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.client.feign.SaasRoleGroupApi;
@ -10,6 +11,7 @@ import cn.axzo.tyr.client.model.req.QuerySaasRoleGroupReq;
import cn.axzo.tyr.client.model.req.UpdateRoleGroupOffsetReq;
import cn.axzo.tyr.client.model.res.SaasRoleGroupDTO;
import cn.axzo.tyr.client.model.vo.SaasRoleGroupVO;
import cn.axzo.tyr.server.repository.entity.SaasRoleGroup;
import cn.axzo.tyr.server.service.SaasRoleGroupService;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
@ -21,6 +23,8 @@ import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import static cn.axzo.tyr.server.config.exception.BizResultCode.ROLE_GROUP_NOT_FOUND;
@Slf4j
@RestController
@RequiredArgsConstructor
@ -68,28 +72,35 @@ public class SaasRoleGroupController implements SaasRoleGroupApi {
if (request.getOffset() != 1 && request.getOffset() != -1) {
throw new ServiceException("暂时只支持移动一个位置");
}
SaasRoleGroupVO saasRoleGroup = getById(request.getId()).getData();
SaasRoleGroup saasRoleGroup = saasRoleGroupService.getById(request.getId());
Axssert.checkNonNull(saasRoleGroup, ROLE_GROUP_NOT_FOUND);
List<SaasRoleGroupVO> roleGroupList = saasRoleGroupService.getRoleGroupList(QuerySaasRoleGroupReq.builder()
.parentId(saasRoleGroup.getParentId())
.workspaceTypeCode(Lists.newArrayList(saasRoleGroup.getWorkspaceTypeCode()))
.build())
List<SaasRoleGroup> roleGroupList = saasRoleGroupService.lambdaQuery()
.eq(SaasRoleGroup::getParentId, saasRoleGroup.getParentId())
.eq(SaasRoleGroup::getWorkspaceTypeCode, saasRoleGroup.getWorkspaceTypeCode())
.eq(SaasRoleGroup::getWorkspaceId, saasRoleGroup.getWorkspaceId())
.eq(SaasRoleGroup::getOuId, saasRoleGroup.getOuId())
.list()
.stream()
.sorted(Comparator.comparing(SaasRoleGroupVO::getSort))
.sorted(Comparator.comparing(SaasRoleGroup::getSort))
.collect(Collectors.toList());
SaasRoleGroupVO exchangeRoleGroup = findExchangeRoleGroup(request, roleGroupList);
SaasRoleGroup exchangeRoleGroup = findExchangeRoleGroup(request, roleGroupList);
if (exchangeRoleGroup == null) {
throw new ServiceException("未找到可以移动的位置");
}
saasRoleGroupService.saveOrUpdate(SaasRoleGroupVO.builder()
.id(saasRoleGroup.getId())
.sort(exchangeRoleGroup.getSort())
.workspaceId(saasRoleGroup.getWorkspaceId())
.ouId(saasRoleGroup.getOuId())
.build());
saasRoleGroupService.saveOrUpdate(SaasRoleGroupVO.builder()
.id(exchangeRoleGroup.getId())
.sort(saasRoleGroup.getSort())
.workspaceId(exchangeRoleGroup.getWorkspaceId())
.ouId(exchangeRoleGroup.getOuId())
.build());
return ApiResult.ok();
}
@ -110,10 +121,10 @@ public class SaasRoleGroupController implements SaasRoleGroupApi {
* @param roleGroupList
* @return
*/
private SaasRoleGroupVO findExchangeRoleGroup(UpdateRoleGroupOffsetReq request,
List<SaasRoleGroupVO> roleGroupList) {
private SaasRoleGroup findExchangeRoleGroup(UpdateRoleGroupOffsetReq request,
List<SaasRoleGroup> roleGroupList) {
List<Long> ids = roleGroupList.stream()
.map(SaasRoleGroupVO::getId)
.map(SaasRoleGroup::getId)
.collect(Collectors.toList());
int currentIndex = ids.indexOf(request.getId());
// 下移一位

View File

@ -7,6 +7,7 @@ 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.GetUserFeatureResourceIdsResp;
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.*;
@ -162,4 +163,9 @@ public class RoleUserController implements TyrSaasRoleUserApi {
public ApiResult<GetUserAutoOwnRoleResp> getUserAutoOwnRole(GetUserAutoOwnRoleReq req) {
return ApiResult.ok(saasRoleUserService.getUserAutoOwnRole(req));
}
@Override
public ApiResult<GetUserFeatureResourceIdsResp> getUserFeatureResourceIds(GetUserFeatureResourceIdsReq req) {
return ApiResult.ok(saasRoleUserService.getUserFeatureResourceIds(req));
}
}

View File

@ -0,0 +1,22 @@
package cn.axzo.tyr.server.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author likunpeng
* @version 1.0
* @date 2024/5/22
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class FeatureResourceRoleCodeDTO {
private Long featureResourceId;
private String roleCode;
}

View File

@ -2,14 +2,18 @@ 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.model.FeatureResourceRoleCodeDTO;
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
import cn.axzo.tyr.server.repository.mapper.SaasFeatureResourceMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* <p>
@ -39,4 +43,13 @@ public class SaasFeatureResourceDao extends ServiceImpl<SaasFeatureResourceMappe
.list();
}
public Map<Long, List<String>> getFeatureResourceRoleCodeMap(List<Long> featureResourceIds) {
if (org.apache.commons.collections4.CollectionUtils.isEmpty(featureResourceIds)) {
return Maps.newHashMap();
}
List<FeatureResourceRoleCodeDTO> featureResourceRoleCodes = this.baseMapper.listRoleCodes(featureResourceIds);
return org.apache.commons.collections4.CollectionUtils.emptyIfNull(featureResourceRoleCodes).stream()
.collect(Collectors.groupingBy(FeatureResourceRoleCodeDTO::getFeatureResourceId, Collectors.mapping(FeatureResourceRoleCodeDTO::getRoleCode, Collectors.toList())));
}
}

View File

@ -17,6 +17,7 @@ import org.springframework.stereotype.Repository;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@ -120,5 +121,15 @@ public class SaasRoleDao extends ServiceImpl<SaasRoleMapper, SaasRole> {
public List<RoleFeatureRelation> listFeatureByIds(Set<Long> roleIds, Set<Long> featureIds) {
return this.baseMapper.listFeatureByIds(roleIds, featureIds);
}
public List<SaasRole> listByRoleCodes(List<String> roleCodes) {
if (CollectionUtils.isEmpty(roleCodes)) {
return Collections.emptyList();
}
return lambdaQuery().in(SaasRole::getRoleCode, roleCodes)
.eq(BaseEntity::getIsDelete, TableIsDeleteEnum.NORMAL)
.eq(SaasRole::getRoleType, RoleTypeEnum.INIT.getValue())
.list();
}
}

View File

@ -39,6 +39,7 @@ public class SaasRoleGroupDao extends ServiceImpl<SaasRoleGroupMapper, SaasRoleG
.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())
.in(CollectionUtils.isNotEmpty(req.getParentIds()), SaasRoleGroup::getParentId, req.getParentIds())
.eq(BaseEntity::getIsDelete, TableIsDeleteEnum.NORMAL.value);
if(CollectionUtils.isNotEmpty(req.getOuTypeCode())){
eq.last(" AND (" + condition.substring(0, condition.length() - 2) + ")");

View File

@ -134,6 +134,21 @@ public class SaasFeatureResource extends BaseEntity<SaasFeature> {
*/
private Long updateBy;
/**
* 应用范围(租户类型)1:企业工作台 2;项目工作台
*/
private Long workspaceType;
/**
* 最低版本序列,主要支持版本灰度策略
*/
private Integer version;
/**
* 唯一编码用于pre环境菜单同步
*/
private String uniCode;
public List<Long> splitPath() {
if (StrUtil.isBlank(this.path)) {
return Collections.emptyList();

View File

@ -1,7 +1,12 @@
package cn.axzo.tyr.server.repository.mapper;
import cn.axzo.tyr.server.model.FeatureResourceRoleCodeDTO;
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;
import java.util.List;
/**
* <p>
@ -13,4 +18,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
*/
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);
List<FeatureResourceRoleCodeDTO> listRoleCodes(@Param("ids") List<Long> ids);
}

View File

@ -2,6 +2,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.GetUserFeatureResourceIdsResp;
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;
@ -97,4 +98,12 @@ public interface SaasRoleUserService {
* @return
*/
GetUserAutoOwnRoleResp getUserAutoOwnRole(GetUserAutoOwnRoleReq req);
/**
* 查询用户已有的功能资源
*
* @param req
* @return
*/
GetUserFeatureResourceIdsResp getUserFeatureResourceIds(GetUserFeatureResourceIdsReq req);
}

View File

@ -2,29 +2,41 @@ package cn.axzo.tyr.server.service.impl;
import cn.axzo.basics.common.BeanMapper;
import cn.axzo.basics.common.util.TreeUtil;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
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.dao.SaasPgroupPermissionRelationDao;
import cn.axzo.tyr.server.repository.dao.SaasPgroupRoleRelationDao;
import cn.axzo.tyr.server.repository.dao.SaasRoleDao;
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
import cn.axzo.tyr.server.repository.entity.SaasPgroupPermissionRelation;
import cn.axzo.tyr.server.repository.entity.SaasPgroupRoleRelation;
import cn.axzo.tyr.server.repository.entity.SaasRole;
import cn.axzo.tyr.server.service.FeatureResourceSyncService;
import cn.axzo.tyr.server.util.RpcInternalUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
/**
* 功能资源同步服务实现
@ -44,12 +56,20 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
private final SaasFeatureResourceCacheService saasFeatureResourceCacheService;
private final SaasRoleDao saasRoleDao;
private final SaasPgroupRoleRelationDao saasPgroupRoleRelationDao;
private final SaasPgroupPermissionRelationDao saasPgroupPermissionRelationDao;
@Qualifier("asyncExecutor")
@Autowired
private ExecutorService asyncExecutor;
@Override
public List<FeatureResourceTreeNode> getSyncTreeById(Long id) {
List<Long> allFeatureResourceIds = Lists.newArrayList(id);
//选中同步的数据
SaasFeatureResource resource = featureResourceDao.lambdaQuery()
.eq(SaasFeatureResource::getId, id)
@ -61,6 +81,7 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
List<SaasFeatureResource> resourceList = featureResourceDao.lambdaQuery()
.in(SaasFeatureResource::getId, resource.splitPath())
.list();
allFeatureResourceIds.addAll(CollectionUtils.emptyIfNull(resourceList).stream().map(BaseEntity::getId).collect(Collectors.toList()));
//resourceList.add(resource);
//如果是页面或应用入口-同时返回所有页面组件
if (FeatureResourceType.applyPage(resource.getFeatureType())) {
@ -68,9 +89,15 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
.eq(SaasFeatureResource::getFeatureType, FeatureResourceType.COMPONENT.getCode())
.apply("FIND_IN_SET(" + id + ", path)")
.list();
allFeatureResourceIds.addAll(CollectionUtils.emptyIfNull(componentList).stream().map(BaseEntity::getId).collect(Collectors.toList()));
resourceList.addAll(componentList);
}
Map<Long, List<String>> featureResourceRoleCodeMap = featureResourceDao.getFeatureResourceRoleCodeMap(allFeatureResourceIds);
List<FeatureResourceTreeNode> dtoList = BeanMapper.copyList(resourceList, FeatureResourceTreeNode.class);
dtoList.forEach(e -> {
e.setRoleCodes(featureResourceRoleCodeMap.get(e.getId()));
});
return TreeUtil.buildTree(dtoList);
}
@ -117,14 +144,18 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
continue;
}
//缓存code
codeCache.put(treeNode.getId(), treeNode.getFeatureCode());
codeCache.put(treeNode.getId(), treeNode.getUniCode());
SaasFeatureResource baseResource = BeanMapper.copyBean(treeNode, SaasFeatureResource.class);
//修正数据
String parentCode = codeCache.get(baseResource.getParentId());
SaasFeatureResource parent = StringUtils.isBlank(parentCode) ? null : featureResourceDao.getByCode(parentCode);
String parentUniCode = codeCache.get(baseResource.getParentId());
SaasFeatureResource parent = StringUtils.isBlank(parentUniCode) ? null : featureResourceDao.lambdaQuery()
.eq(SaasFeatureResource::getUniCode, parentUniCode)
.one();
SaasFeatureResource resource = featureResourceDao.getByCode(treeNode.getFeatureCode());
SaasFeatureResource resource = featureResourceDao.lambdaQuery()
.eq(SaasFeatureResource::getUniCode, treeNode.getUniCode())
.one();
if (resource == null) {
//新增
baseResource.setCreateBy(operatorId);
@ -141,6 +172,10 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
baseResource.setAppItemId(resource.getAppItemId());
featureResourceDao.updateById(baseResource);
}
// 处理资源关联的权限
doFeatureResourceRole(baseResource.getId(), treeNode.getRoleCodes(), operatorId);
//递归子节点
if (CollectionUtil.isNotEmpty(treeNode.getChildren())) {
syncResourceProcess(treeNode.getChildren(), codeCache, operatorId);
@ -166,4 +201,51 @@ public class FeatureResourceSyncServiceImpl implements FeatureResourceSyncServic
resource.setPath(parent.getPath() + resource.getId() + ",");
}
}
private void newResource(SaasFeatureResource resource) {
featureResourceDao.save(resource);
//path追加自身ID
if (resource.getParentId() < 0) {
resource.setPath(resource.getId().toString());
} else {
resource.setPath(resource.getPath() + "," + resource.getId());
}
featureResourceDao.updateById(resource);
}
private void doFeatureResourceRole(Long featureResourceId, List<String> roleCodes, Long operatorId) {
if (Objects.isNull(featureResourceId) || CollectionUtils.isEmpty(roleCodes)) {
return;
}
List<String> existRoleCodes = featureResourceDao.getFeatureResourceRoleCodeMap(Lists.newArrayList(featureResourceId))
.get(featureResourceId);
if (CollectionUtils.isNotEmpty(existRoleCodes)) {
roleCodes.removeAll(existRoleCodes);
}
if (CollectionUtils.isEmpty(roleCodes)) {
return;
}
List<SaasRole> saasRoles = saasRoleDao.listByRoleCodes(roleCodes);
if (CollectionUtils.isEmpty(saasRoles)) {
return;
}
List<Long> groupIds = saasPgroupRoleRelationDao.findByRoleIds(saasRoles.stream().map(BaseEntity::getId).collect(Collectors.toList()))
.stream().map(SaasPgroupRoleRelation::getGroupId).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(groupIds)) {
List<SaasPgroupPermissionRelation> insertRelation = new ArrayList<>();
groupIds.forEach(groupId -> {
SaasPgroupPermissionRelation relation = new SaasPgroupPermissionRelation();
relation.setFeatureId(featureResourceId);
relation.setGroupId(groupId);
relation.setCreateBy(operatorId);
insertRelation.add(relation);
});
saasPgroupPermissionRelationDao.saveBatch(insertRelation);
}
}
}

View File

@ -12,6 +12,7 @@ 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.GetUserFeatureResourceIdsResp;
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.AutoOwnRoleUserReq;
@ -183,6 +184,8 @@ public class RoleUserService implements SaasRoleUserService {
saasRoleUserRelation.setNaturalPersonId(req.getPersonId());
saasRoleUserRelation.setOuId(req.getOuId());
saasRoleUserRelation.setWorkspaceId(req.getWorkspaceId());
saasRoleUserRelation.setCreateBy(req.getOperator());
saasRoleUserRelation.setUpdateBy(req.getOperator());
return saasRoleUserRelation;
}).collect(Collectors.toList()));
@ -572,6 +575,32 @@ public class RoleUserService implements SaasRoleUserService {
.build();
}
@Override
public GetUserFeatureResourceIdsResp getUserFeatureResourceIds(GetUserFeatureResourceIdsReq req) {
// 查询用户所有角色
List<SaasRoleUserRelation> existsRoleUser = roleUserRelationDao.queryByPersonId(req.getPersonId(), req.getWorkspaceId(), req.getOuId());
if (CollectionUtils.isEmpty(existsRoleUser)) {
return null;
}
List<SaasRole> roles = saasRoleDao.listByIds(existsRoleUser.stream().mapToLong(SaasRoleUserRelation::getRoleId).boxed().collect(Collectors.toList()))
.stream().filter(e -> CollectionUtils.isEmpty(req.getRoleIds()) || req.getRoleIds().contains(e.getId())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(roles)) {
return null;
}
List<SaasPgroupRoleRelation> saasPgroupRoleRelations = saasPgroupRoleRelationDao.findByRoleIds(roles.stream().map(BaseEntity::getId).collect(Collectors.toSet()));
if (CollectionUtils.isEmpty(saasPgroupRoleRelations)) {
return null;
}
List<SaasPgroupPermissionRelation> saasPgroupPermissionRelations = saasPgroupPermissionRelationDao.lambdaQuery()
.in(SaasPgroupPermissionRelation::getGroupId, saasPgroupRoleRelations.stream().map(SaasPgroupRoleRelation::getGroupId).collect(Collectors.toList()))
.eq(SaasPgroupPermissionRelation::getIsDelete, TableIsDeleteEnum.NORMAL.value).list();
return GetUserFeatureResourceIdsResp.builder().featureResourceIds(saasPgroupPermissionRelations.stream()
.map(SaasPgroupPermissionRelation::getFeatureId).collect(Collectors.toSet())).build();
}
private void batchRemoveByRoleUserInfo(RoleUserInfo roleUserBaseInfo) {
roleUserBaseInfo.getRoleUserResourceInfos().forEach(e -> {

View File

@ -26,6 +26,8 @@ import cn.azxo.framework.common.utils.StringUtils;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.nacos.common.utils.UuidUtils;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
@ -169,6 +171,8 @@ public class SaasFeatureResourceServiceImpl implements SaasFeatureResourceServic
SaasFeatureResource maxOrderResource = parallelResources.stream().max(Comparator.comparingInt(SaasFeatureResource::getDisplayOrder)).orElse(new SaasFeatureResource());
baseResource.setDisplayOrder(maxOrderResource.getDisplayOrder() + 1);
}
// 生成唯一编码用于pre菜单同步
baseResource.setUniCode(UuidUtils.generateUuid());
newResource(baseResource, parent == null ? "" : parent.getPath());
} else {
//补充path
@ -417,9 +421,20 @@ public class SaasFeatureResourceServiceImpl implements SaasFeatureResourceServic
return rootNodes;
}
/**
* 菜单/页面/应用/分组权限码每个端唯一
* 组件权限码不校验唯一
* @param featureResource
*/
void validFeatureCode(SaasFeatureResource featureResource) {
if (Objects.equals(FeatureResourceType.COMPONENT.getCode(), featureResource.getFeatureType())) {
return;
}
Assert.notNull(featureResource.getFeatureCode(), "权限码code不能为空");
SaasFeatureResource exist = featureResourceDao.lambdaQuery()
.eq(SaasFeatureResource::getTerminal, featureResource.getTerminal())
.eq(SaasFeatureResource::getFeatureCode, featureResource.getFeatureCode())
.eq(BaseEntity::getIsDelete, 0)
.one();

View File

@ -2,6 +2,7 @@ package cn.axzo.tyr.server.service.impl;
import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum;
import cn.axzo.basics.common.exception.ServiceException;
import cn.axzo.foundation.exception.Axssert;
import cn.axzo.foundation.dao.support.converter.PageConverter;
import cn.axzo.foundation.dao.support.mysql.QueryWrapperHelper;
import cn.axzo.foundation.page.PageResp;
@ -37,6 +38,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -45,6 +47,8 @@ import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import static cn.axzo.tyr.server.config.exception.BizResultCode.CANT_DELETE_ROLE_GROUP;
@Slf4j
@RequiredArgsConstructor
@Service
@ -129,7 +133,7 @@ public class SaasRoleGroupServiceImpl extends ServiceImpl<SaasRoleGroupMapper, S
}
/**
* 只有当分组下面角色为空时才能删除
* 只有当分组下面角色为空合分组下没有其他分组时才能删除
* @param ids
*/
@Override
@ -144,6 +148,13 @@ public class SaasRoleGroupServiceImpl extends ServiceImpl<SaasRoleGroupMapper, S
if (relationCount > 0) {
throw new ServiceException("该角色分组有关联角色,不能进行删除!");
}
QuerySaasRoleGroupReq querySaasRoleGroupReq = QuerySaasRoleGroupReq.builder()
.parentIds(new HashSet<>(ids))
.build();
List<SaasRoleGroup> childrenRoleGroups = saasRoleGroupDao.query(querySaasRoleGroupReq);
Axssert.check(CollectionUtils.isEmpty(childrenRoleGroups), CANT_DELETE_ROLE_GROUP);
saasRoleGroupDao.delete(ids);
}
@ -207,7 +218,8 @@ public class SaasRoleGroupServiceImpl extends ServiceImpl<SaasRoleGroupMapper, S
.eq(SaasRoleGroup::getParentId, saasRoleGroup.getParentId())
.eq(SaasRoleGroup::getWorkspaceTypeCode, saasRoleGroup.getWorkspaceTypeCode())
.eq(SaasRoleGroup::getIsDelete, TableIsDeleteEnum.NORMAL.value)
.eq(SaasRoleGroup::getWorkspaceTypeCode, saasRoleGroup.getWorkspaceTypeCode())
.eq(SaasRoleGroup::getWorkspaceId, saasRoleGroup.getWorkspaceId())
.eq(SaasRoleGroup::getOuId, saasRoleGroup.getOuId())
.orderByDesc(SaasRoleGroup::getSort)
.last("limit 1")
.list()

View File

@ -14,6 +14,11 @@ spring:
include: swagger
main:
allow-bean-definition-overriding: true
lifecycle:
timeout-per-shutdown-phase: 30s
server:
shutdown: graceful
mybatis-plus:
type-enums-package: cn.axzo.tyr.client.model.enums

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.axzo.tyr.server.repository.mapper.SaasFeatureResourceMapper">
<select id="listRoleCodes" resultType="cn.axzo.tyr.server.model.FeatureResourceRoleCodeDTO">
SELECT fr.id AS featureResourceId, r.role_code AS roleCode
FROM saas_feature_resource fr
INNER JOIN saas_pgroup_permission_relation pr ON fr.id = pr.feature_id
INNER JOIN saas_pgroup_role_relation rr ON pr.group_id = rr.group_id
INNER JOIN saas_role r ON rr.role_id = r.id
WHERE fr.is_delete = 0 AND pr.is_delete = 0 AND rr.is_delete = 0 AND r.is_delete = 0
<if test="ids != null and ids.size>0">
and fr.id in
<foreach collection="ids" index="index" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</if>
</select>
</mapper>

View File

@ -1,5 +1,6 @@
package cn.axzo.tyr.base;
import cn.axzo.tyr.server.TyrApplication;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
@ -29,7 +30,7 @@ import java.nio.charset.StandardCharsets;
import java.util.List;
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = {TestConfig.class})
@SpringBootTest(classes = {TestConfig.class, TyrApplication.class})
@AutoConfigureMockMvc
@Transactional
@ActiveProfiles("unittest")

View File

@ -0,0 +1,83 @@
package cn.axzo.tyr.server.controller;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.tyr.base.BaseTest;
import cn.axzo.tyr.client.model.enums.IdentityType;
import cn.axzo.tyr.client.model.enums.WorkerLeaderRoleEnum;
import cn.axzo.tyr.client.model.roleuser.req.GantOrUnGantaWorkerLeaderRoleReq;
import cn.axzo.tyr.client.model.roleuser.req.RoleUserReq;
import cn.axzo.tyr.server.controller.roleuser.RoleUserController;
import cn.axzo.tyr.server.repository.dao.SaasRoleUserRelationDao;
import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation;
import cn.hutool.http.HttpStatus;
import com.google.common.collect.Sets;
import org.apache.commons.collections4.CollectionUtils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author likunpeng
* @version 1.0
* @date 2024/5/24
*/
public class RoleUserControllerTest extends BaseTest {
@Autowired
private RoleUserController roleUserController;
@Autowired
private SaasRoleUserRelationDao saasRoleUserRelationDao;
@Test
@Rollback
public void testSaveOrUpdate() {
Long workspaceId = 2L;
Long ouId = 1L;
Long identityId = 1L;
IdentityType identityType = IdentityType.PRACTITIONER;
RoleUserReq req = RoleUserReq.builder()
.workspaceId(workspaceId)
.ouId(ouId)
.identityId(identityId)
.updateRoleIds(Sets.newHashSet(1L))
.identityType(IdentityType.PRACTITIONER)
.build();
ApiResult<Void> apiResult = roleUserController.saveOrUpdate(req);
Assertions.assertEquals(apiResult.getCode(), HttpStatus.HTTP_OK, "保存用户权限误");
List<SaasRoleUserRelation> saasRoleUserRelations = saasRoleUserRelationDao.query(identityId, identityType.getCode(), workspaceId, ouId);
Assertions.assertTrue(CollectionUtils.isNotEmpty(saasRoleUserRelations), "用户权限未保存成功");
}
@Test
@Rollback
public void testGrantOrUngrantWorkerLeader() {
Long workspaceId = 2L;
Long ouId = 1L;
Long teamOuId = 1L;
Long identityId = 1L;
Long personId = 1L;
Long roleId = 100000L;
GantOrUnGantaWorkerLeaderRoleReq req = GantOrUnGantaWorkerLeaderRoleReq.builder()
.workspaceId(workspaceId)
.ouId(ouId)
.teamOuId(teamOuId)
.identityId(identityId)
.personId(personId)
.grant(Boolean.TRUE)
.workerLeaderRoleEnum(WorkerLeaderRoleEnum.ENT_TEAM_MANAGER)
.build();
ApiResult<Void> apiResult = roleUserController.grantOrUngrantWorkerLeader(req);
Assertions.assertEquals(apiResult.getCode(), HttpStatus.HTTP_OK, "授权平台班组长角色有误");
List<SaasRoleUserRelation> saasRoleUserRelations = saasRoleUserRelationDao.queryByPersonId(personId, workspaceId, ouId);
Assertions.assertTrue(CollectionUtils.isNotEmpty(saasRoleUserRelations), "授权平台班组长角色有误");
List<Long> roleIds = saasRoleUserRelations.stream().map(SaasRoleUserRelation::getRoleId).collect(Collectors.toList());
Assertions.assertTrue(roleIds.contains(roleId), "授权平台班组长角色有误");
}
}

View File

@ -2,11 +2,16 @@ package cn.axzo.tyr.server.permission;
import cn.axzo.tyr.base.BaseTest;
import cn.axzo.tyr.server.repository.dao.SaasFeatureDao;
import cn.axzo.tyr.server.repository.dao.SaasRoleUserRelationDao;
import cn.axzo.tyr.server.repository.entity.SaasFeature;
import cn.axzo.tyr.server.repository.entity.SaasRoleUserRelation;
import com.alibaba.fastjson.JSON;
import org.apache.commons.collections4.CollectionUtils;
import org.junit.Assert;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import java.util.Arrays;
import java.util.List;
@ -15,6 +20,8 @@ public class DemoTest extends BaseTest {
@Autowired
private SaasFeatureDao saasFeatureDao;
@Autowired
private SaasRoleUserRelationDao saasRoleUserRelationDao;
@Test
void test() {
@ -23,4 +30,19 @@ public class DemoTest extends BaseTest {
List<SaasFeature> saasFeatures = saasFeatureDao.list();
Assert.assertEquals(saasFeatures.size(), 1);
}
@Test
@Rollback
public void testDeleteUserRole() {
Long personId = 1L;
Long workspaceId = 1L;
Long ouId = 1L;
List<SaasRoleUserRelation> roleUserRelations = saasRoleUserRelationDao.queryByPersonId(personId, workspaceId, ouId);
Assertions.assertEquals(roleUserRelations.size(), 1, "personId:[" + personId + "]的权限数据有误");
saasRoleUserRelationDao.removeWorkspaceOuAllUserRole(workspaceId, ouId);
List<SaasRoleUserRelation> roleUserRelations2 = saasRoleUserRelationDao.queryByPersonId(personId, workspaceId, ouId);
Assertions.assertTrue(CollectionUtils.isEmpty(roleUserRelations2), "ouId:[" + ouId + "] workspaceId:[" + workspaceId + "]的权限数据有误");
}
}

View File

@ -0,0 +1,23 @@
package cn.axzo.tyr.server.service;
import cn.axzo.tyr.base.BaseTest;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
class RoleServiceTest extends BaseTest {
@Autowired
private RoleService roleService;
@Test
void list() {
}
}

View File

@ -31,4 +31,14 @@ xxl:
flush:
role1052:
saasPreTempalteIdOfProject: 5
saasPreTempalteIdOfOu: 43
saasPreTempalteIdOfOu: 43
axzo:
cache:
auth:
enable: false
expire: 30
# 菜单同步基准环境 不配默认为PRE
# service.base.tyr: https://test-api.axzo.cn/tyr
# 超管编码
role.superAdmin: '{1:"entSuperAdmin",2:"projSuperAdmin",6:"omsSuperAdmin"}'

View File

@ -1 +1,10 @@
select 1;
select 1;
-- saas_role 表初始化数据
INSERT INTO `saas_role` (`id`, `NAME`, `description`, `role_type`, `role_code`, `workspace_id`, `owner_ou_id`, `product_unit_type`, `workspace_type`, `is_delete`, `create_at`, `update_at`, `create_by`, `update_by`, `fit_ou_type_bit`, `fit_ou_node_type_bit`, `position_template_id`, `project_team_manage_role_resource_id`, `from_pre_role_id`, `job_code`, `is_display`, `enabled`, `sort`) VALUES (1, '代班长', '', 'common', '7722', 2, 1, 0, 2, 0, '2022-10-19 15:53:32', '2024-04-17 11:02:19', 0, 0, 32, 1, 2, 59, 0, '', 1, 1, 1);
-- saas_role_user_relation 表初始化数据
-- DemoTest.testDeleteUserRole 使用
INSERT INTO `saas_role_user_relation` (`id`, `identity_id`, `role_id`, `identity_type`, `natural_person_id`, `workspace_id`, `ou_id`, `resource_type`, `resource_id`, `is_delete`, `create_at`, `update_at`, `create_by`, `update_by`, `job_type`) VALUES (1, 2008231, 100001, 2, 1, 1, 1, 1, 9592, 0, '2024-05-22 18:23:40', '2024-05-22 18:23:39', 0, 0, 2);

View File

@ -54,3 +54,60 @@ CREATE TABLE `saas_feature` (
PRIMARY KEY (`id`),
KEY `IDX_CODE` (`feature_code`)
) ENGINE=InnoDB AUTO_INCREMENT=4618 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='saas-菜单页面表';
CREATE TABLE `saas_role_user_relation` (
`id` bigint NOT NULL AUTO_INCREMENT,
`identity_id` bigint NOT NULL DEFAULT '0' COMMENT '身份Id',
`role_id` bigint NOT NULL DEFAULT '0' COMMENT '角色Id',
`identity_type` tinyint NOT NULL DEFAULT '0' COMMENT '身份类型 1:工人 2:班组长 3:从业人员 4:监管人员 5:运营人员',
`natural_person_id` bigint NOT NULL DEFAULT '0' COMMENT '自然人Id',
`workspace_id` bigint NOT NULL DEFAULT '0' COMMENT '工作台Id',
`ou_id` bigint NOT NULL DEFAULT '0' COMMENT '所属单位Id',
`resource_type` tinyint NOT NULL DEFAULT '0' COMMENT '资源类型',
`resource_id` bigint NOT NULL DEFAULT '0' COMMENT '资源Id',
`is_delete` bigint NOT NULL DEFAULT '0' COMMENT '是否删除0否other是',
`create_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`create_by` bigint NOT NULL DEFAULT '0' COMMENT '创建者',
`update_by` bigint NOT NULL DEFAULT '0' COMMENT '更新者',
`job_type` int NOT NULL DEFAULT '2' COMMENT '岗位类型 1:主岗 2:兼岗',
PRIMARY KEY (`id`),
KEY `idx_ouId_spaceId_identityId` (`ou_id`,`workspace_id`,`identity_id`),
KEY `idx_role_id` (`role_id`)
) ENGINE=InnoDB AUTO_INCREMENT=214132 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='saas-角色用户关联表';
CREATE TABLE `saas_role` (
`id` bigint NOT NULL AUTO_INCREMENT,
`NAME` varchar(50) NOT NULL DEFAULT '' COMMENT '角色名称',
`description` varchar(200) NOT NULL DEFAULT '' COMMENT '角色描述',
`role_type` varchar(50) NOT NULL DEFAULT '' COMMENT '角色类型common 普通角色 super_admin超级管理员(禁止删除) admin子管理员(禁止删除) init初始化内置角色 ',
`role_code` varchar(64) NOT NULL DEFAULT '' COMMENT '角色编码',
`workspace_id` bigint NOT NULL DEFAULT '0' COMMENT '工作台Id',
`owner_ou_id` bigint NOT NULL DEFAULT '0' COMMENT '角色所属单位Id 可能是总包,也可能是分包',
`product_unit_type` tinyint NOT NULL DEFAULT '0' COMMENT '产品单位类型',
`workspace_type` tinyint DEFAULT '0' COMMENT '1:企业工作台 2;项目工作台',
`is_delete` bigint NOT NULL DEFAULT '0' COMMENT '是否删除0否other是',
`create_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`create_by` bigint NOT NULL DEFAULT '0' COMMENT '创建者',
`update_by` bigint NOT NULL DEFAULT '0' COMMENT '更新者',
`fit_ou_type_bit` int DEFAULT '1' COMMENT '适用单位类型-1:总包 2:建设单位 4:监理单位 8:劳务分包 16:专业分包,65535:全部',
`fit_ou_node_type_bit` int DEFAULT '65535' COMMENT '适用节点类型 1:部门 2:班组 4:小组,65535:全部',
`position_template_id` bigint DEFAULT '0' COMMENT '职位模板ID 若此字段不为0则为专属角色该角色专属于某个职位',
`project_team_manage_role_resource_id` bigint DEFAULT NULL COMMENT '主要用于代班长角色迁移字段: project_team_manage_role 表的ID',
`from_pre_role_id` bigint DEFAULT '0' COMMENT '来源的模版角色id',
`job_code` varchar(128) DEFAULT '' COMMENT '岗位字典中的编码',
`is_display` tinyint NOT NULL DEFAULT '1' COMMENT '是否显示',
`enabled` tinyint NOT NULL DEFAULT '1' COMMENT '是否启用',
`sort` int NOT NULL DEFAULT '0' COMMENT '排序',
PRIMARY KEY (`id`),
KEY `workspace_ou_idx` (`workspace_id`,`owner_ou_id`,`is_delete`),
KEY `ou_workspace_idx` (`owner_ou_id`,`workspace_id`,`is_delete`)
) ENGINE=InnoDB AUTO_INCREMENT=102623 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='saas-角色';
alter table saas_feature_resource
add column `workspace_type` tinyint DEFAULT '0' COMMENT '1:企业工作台 2;项目工作台' after `path`,
add column `version` int DEFAULT '0' COMMENT '最低版本序列,主要支持版本灰度策略' after `workspace_type`
add column `uni_code` varchar(64) not null default '' comment '唯一编码用于pre环境菜单同步' after `version`;