diff --git a/platform-web-ui/src/utils/index.ts b/platform-web-ui/src/utils/index.ts index 1aebdcd..7c6da58 100644 --- a/platform-web-ui/src/utils/index.ts +++ b/platform-web-ui/src/utils/index.ts @@ -173,13 +173,14 @@ export const chinaAreaDeepQuery = (areaCode: number) => { } /** 将权限树形结构扁平化为一维数组,用于权限查询 */ -export const flatTreeToCascaderOption = (arr: any[], {value = "id", label = "label", children = "children"}) => { +export const flatTreeToCascaderOption = (arr: any[], { value = "id", label = "label", disabled = "disabled", children = "children" }) => { const result: CascaderOption[] = [] const deep = (arr1: any[], arr2: CascaderOption[]) => { arr1.forEach((item: any) => { const temp: CascaderOption = { value: item[value], - label: item[label] + label: item[label], + disabled: item[disabled] } arr2.push(temp) if (item[children] && item[children].length > 0) { diff --git a/server/common/src/main/java/com/xaaef/molly/common/consts/DataScopeConst.java b/server/common/src/main/java/com/xaaef/molly/common/consts/DataScopeConst.java index 65a6ac4..bf2b8db 100644 --- a/server/common/src/main/java/com/xaaef/molly/common/consts/DataScopeConst.java +++ b/server/common/src/main/java/com/xaaef/molly/common/consts/DataScopeConst.java @@ -1,26 +1,47 @@ package com.xaaef.molly.common.consts; - /** *

+ * *

* - * @author Wang Chen Chen - * @version 1.0.1 - * @date 2024/8/13 15:15 + * @author WangChenChen + * @version 1.0.0 + * @date 2024/10/28 下午6:37 */ + public class DataScopeConst { /** - * 数据范围(1:全部数据权限 2:自定数据权限 3:仅本部门数据权限 4:本部门及以下数据权限) + * 全部数据权限 */ - public static final Integer All = 1; + public static final int DATA_SCOPE_ALL = 1; - public static final Integer CUSTOM = 2; + /** + * 自定数据权限 + */ + public static final int DATA_SCOPE_CUSTOM = 2; - public static final Integer ONLY_ME = 3; + /** + * 部门数据权限 + */ + public static final int DATA_SCOPE_DEPT = 3; + + /** + * 部门及以下数据权限 + */ + public static final int DATA_SCOPE_DEPT_AND_CHILD = 4; + + /** + * 仅本人数据权限 + */ + public static final int DATA_SCOPE_SELF = 5; + + /** + * 数据权限过滤关键字 + */ + public static final String DATA_SCOPE = "dataScope"; - public static final Integer ME_AND_CHILD = 4; } diff --git a/server/internal-api/src/main/java/com/xaaef/molly/internal/dto/PmsRoleDTO.java b/server/internal-api/src/main/java/com/xaaef/molly/internal/dto/PmsRoleDTO.java index ebb30ed..193fb75 100644 --- a/server/internal-api/src/main/java/com/xaaef/molly/internal/dto/PmsRoleDTO.java +++ b/server/internal-api/src/main/java/com/xaaef/molly/internal/dto/PmsRoleDTO.java @@ -40,6 +40,6 @@ public class PmsRoleDTO implements java.io.Serializable { /** * 数据范围 */ - private Integer dataScope; + private int dataScope; } diff --git a/server/molly-cms/src/main/java/com/xaaef/molly/corems/entity/CmsProject.java b/server/molly-cms/src/main/java/com/xaaef/molly/corems/entity/CmsProject.java index 95102aa..aa23fc7 100644 --- a/server/molly-cms/src/main/java/com/xaaef/molly/corems/entity/CmsProject.java +++ b/server/molly-cms/src/main/java/com/xaaef/molly/corems/entity/CmsProject.java @@ -9,7 +9,7 @@ import com.xaaef.molly.common.valid.ValidCreate; import com.xaaef.molly.common.valid.ValidDelete; import com.xaaef.molly.common.valid.ValidUpdate; import com.xaaef.molly.internal.dto.PmsDeptDTO; -import com.xaaef.molly.tenant.base.BaseEntity; +import com.xaaef.molly.tenant.base.ParamBaseEntity; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; @@ -36,7 +36,7 @@ import lombok.experimental.Accessors; @Accessors(chain = true) @AllArgsConstructor @NoArgsConstructor -public class CmsProject extends BaseEntity { +public class CmsProject extends ParamBaseEntity { /** * 项目ID diff --git a/server/molly-cms/src/main/java/com/xaaef/molly/corems/mapper/CmsProjectMapper.java b/server/molly-cms/src/main/java/com/xaaef/molly/corems/mapper/CmsProjectMapper.java index a6b76ca..9263bbb 100644 --- a/server/molly-cms/src/main/java/com/xaaef/molly/corems/mapper/CmsProjectMapper.java +++ b/server/molly-cms/src/main/java/com/xaaef/molly/corems/mapper/CmsProjectMapper.java @@ -2,11 +2,14 @@ package com.xaaef.molly.corems.mapper; import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.xaaef.molly.corems.entity.CmsProject; import com.xaaef.molly.corems.entity.TenantAndProject; +import com.xaaef.molly.tenant.ds.DataScope; import org.apache.ibatis.annotations.Param; import java.util.Collection; +import java.util.List; import java.util.Set; @@ -42,4 +45,25 @@ public interface CmsProjectMapper extends BaseMapper { // 根据 租户的数据名称 查询 项目列表。如: molly_master 、molly_google Set selectListByTenantDbName(Collection tenantDbNameList); + + /** + * 根据条件分页查询数据 + */ + @DataScope() + List selectProjectList(@Param("p") CmsProject user); + + + /** + * 根据条件分页查询数据 + */ + @DataScope() + IPage selectProjectPage(IPage page, @Param("p") CmsProject user); + + + /** + * 根据条件分页查询数据 + */ + @DataScope() + IPage selectSimpleProjectPage(IPage page, @Param("p") CmsProject user); + } diff --git a/server/molly-cms/src/main/java/com/xaaef/molly/corems/service/impl/CmsProjectServiceImpl.java b/server/molly-cms/src/main/java/com/xaaef/molly/corems/service/impl/CmsProjectServiceImpl.java index ce5e8d0..196987a 100644 --- a/server/molly-cms/src/main/java/com/xaaef/molly/corems/service/impl/CmsProjectServiceImpl.java +++ b/server/molly-cms/src/main/java/com/xaaef/molly/corems/service/impl/CmsProjectServiceImpl.java @@ -1,6 +1,5 @@ package com.xaaef.molly.corems.service.impl; -import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -22,12 +21,12 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.Collection; -import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -import static com.xaaef.molly.auth.jwt.JwtSecurityUtils.*; +import static com.xaaef.molly.auth.jwt.JwtSecurityUtils.encryptPassword; +import static com.xaaef.molly.auth.jwt.JwtSecurityUtils.matchesPassword; import static com.xaaef.molly.common.consts.ConfigDataConst.DEFAULT_PROJECT_PASSWORD; import static com.xaaef.molly.common.consts.MbpConst.PROJECT_ID; @@ -56,19 +55,15 @@ public class CmsProjectServiceImpl extends BaseServiceImpl pageKeywords(ProjectQueryPO params) { - var wrapper = super.getKeywordsQueryWrapper(params, - List.of(CmsProject::getProjectName, CmsProject::getLinkman)); + var project = new CmsProject(); + if (StrUtil.isNotBlank(params.getKeywords())) { + project.setProjectName(params.getKeywords()); + } if (params.getDeptId() != null && params.getDeptId() > 0L) { - if (CollectionUtil.contains(getLoginUser().getHaveDeptIds(), params.getDeptId())) { - wrapper.lambda().in(CmsProject::getDeptId, params.getDeptId()); - } else { - wrapper.lambda().in(CmsProject::getDeptId, getLoginUser().getHaveDeptIds()); - } - } else { - wrapper.lambda().in(CmsProject::getDeptId, getLoginUser().getHaveDeptIds()); + project.setDeptId(params.getDeptId()); } Page pageRequest = Page.of(params.getPageIndex(), params.getPageSize()); - Page result = super.page(pageRequest, wrapper); + var result = baseMapper.selectProjectPage(pageRequest, project); if (params.isIncludeCauu()) { reflectionFill(result.getRecords()); } @@ -143,25 +138,14 @@ public class CmsProjectServiceImpl extends BaseServiceImpl simplePageKeywords(SearchPO po) { - var wrapper = super.getKeywordsQueryWrapper(po, - List.of(CmsProject::getProjectName, CmsProject::getLinkman) - ) - .lambda() - .select( - List.of( - CmsProject::getProjectId, CmsProject::getProjectName, - CmsProject::getLinkman, CmsProject::getAreaCode, CmsProject::getAddress - ) - ) - .eq(CmsProject::getStatus, StatusEnum.NORMAL.getCode()) - .orderByAsc(CmsProject::getSort, CmsProject::getCreateTime); - // 非系统用户和管理员用户。根据所在部门,查询项目列表 - if (!isMasterUser() && !isAdminUser()) { - wrapper.in(CmsProject::getDeptId, getLoginUser().getHaveDeptIds()); + public IPage simplePageKeywords(SearchPO params) { + var project = new CmsProject(); + if (StrUtil.isNotBlank(params.getKeywords())) { + project.setProjectName(params.getKeywords()); } - Page pageRequest = Page.of(po.getPageIndex(), po.getPageSize()); - return super.page(pageRequest, wrapper); + project.setStatus(StatusEnum.NORMAL.getCode()); + Page pageRequest = Page.of(params.getPageIndex(), params.getPageSize()); + return baseMapper.selectSimpleProjectPage(pageRequest, project); } diff --git a/server/molly-cms/src/main/resources/mapper/CmsProjectMapper.xml b/server/molly-cms/src/main/resources/mapper/CmsProjectMapper.xml index bfd4e3e..a10fd0f 100644 --- a/server/molly-cms/src/main/resources/mapper/CmsProjectMapper.xml +++ b/server/molly-cms/src/main/resources/mapper/CmsProjectMapper.xml @@ -4,6 +4,25 @@ "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + + + + + + + + + + + + + + + + + + + - SELECT DISTINCT TABLE_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = (SELECT DATABASE()) AND COLUMN_NAME = #{column} + SELECT DISTINCT TABLE_NAME + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = (SELECT DATABASE()) + AND COLUMN_NAME = #{column} @@ -41,4 +63,49 @@ + + + + AND pro.project_id = #{p.projectId} + + + AND pro.`status` = #{p.status} + + + AND CONCAT(pro.project_name, pro.linkman, pro.contactNumber, pro.address) LIKE + CONCAT('%',#{p.projectName},'%') + + + AND (pro.dept_id = #{p.deptId} OR pro.dept_id IN ( SELECT t.dept_id FROM pms_dept t WHERE + find_in_set(#{p.deptId}, ancestors) )) + + + ${p.params.dataScope} + + + + + + + + + + + + + diff --git a/server/molly-pms/src/main/java/com/xaaef/molly/perms/controller/PmsRoleController.java b/server/molly-pms/src/main/java/com/xaaef/molly/perms/controller/PmsRoleController.java index b21677b..b3b76fb 100644 --- a/server/molly-pms/src/main/java/com/xaaef/molly/perms/controller/PmsRoleController.java +++ b/server/molly-pms/src/main/java/com/xaaef/molly/perms/controller/PmsRoleController.java @@ -56,9 +56,7 @@ public class PmsRoleController { @Operation(summary = "分页", description = "分页 查询所有") @GetMapping("/query") public JsonResult> pageQuery(SearchPO params) { - var page = baseService.pageKeywords( - params, List.of(PmsRole::getRoleName, PmsRole::getDescription) - ); + var page = baseService.pageKeywords(params); return JsonResult.success(page.getTotal(), page.getRecords()); } diff --git a/server/molly-pms/src/main/java/com/xaaef/molly/perms/entity/PmsDept.java b/server/molly-pms/src/main/java/com/xaaef/molly/perms/entity/PmsDept.java index b11d03a..ebd8928 100644 --- a/server/molly-pms/src/main/java/com/xaaef/molly/perms/entity/PmsDept.java +++ b/server/molly-pms/src/main/java/com/xaaef/molly/perms/entity/PmsDept.java @@ -7,7 +7,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.xaaef.molly.common.consts.RegexConst; import com.xaaef.molly.common.valid.ValidCreate; import com.xaaef.molly.common.valid.ValidUpdate; -import com.xaaef.molly.tenant.base.BaseEntity; +import com.xaaef.molly.tenant.base.ParamBaseEntity; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -34,7 +34,7 @@ import lombok.experimental.Accessors; @Accessors(chain = true) @AllArgsConstructor @NoArgsConstructor -public class PmsDept extends BaseEntity { +public class PmsDept extends ParamBaseEntity { /** * 部门 ID diff --git a/server/molly-pms/src/main/java/com/xaaef/molly/perms/entity/PmsRole.java b/server/molly-pms/src/main/java/com/xaaef/molly/perms/entity/PmsRole.java index 831e788..6ed7235 100644 --- a/server/molly-pms/src/main/java/com/xaaef/molly/perms/entity/PmsRole.java +++ b/server/molly-pms/src/main/java/com/xaaef/molly/perms/entity/PmsRole.java @@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.xaaef.molly.common.valid.ValidCreate; import com.xaaef.molly.common.valid.ValidUpdate; -import com.xaaef.molly.tenant.base.BaseEntity; +import com.xaaef.molly.tenant.base.ParamBaseEntity; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -33,7 +33,7 @@ import java.util.Set; @Accessors(chain = true) @AllArgsConstructor @NoArgsConstructor -public class PmsRole extends BaseEntity { +public class PmsRole extends ParamBaseEntity { /** * 角色 ID @@ -65,7 +65,7 @@ public class PmsRole extends BaseEntity { private String description; /** - * 数据范围(1:全部数据权限 2:自定数据权限 3:仅本部门数据权限 4:本部门及以下数据权限) + * 数据范围(1:全部数据权限 2:自定数据权限 3:仅本部门数据权限 4:本部门及以下数据权限 5:仅自己的权限) */ @Schema(description = "数据范围", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "数据范围,必须填写", groups = {ValidCreate.class}) diff --git a/server/molly-pms/src/main/java/com/xaaef/molly/perms/entity/PmsUser.java b/server/molly-pms/src/main/java/com/xaaef/molly/perms/entity/PmsUser.java index 5d6578b..4046740 100644 --- a/server/molly-pms/src/main/java/com/xaaef/molly/perms/entity/PmsUser.java +++ b/server/molly-pms/src/main/java/com/xaaef/molly/perms/entity/PmsUser.java @@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import com.xaaef.molly.common.consts.RegexConst; import com.xaaef.molly.common.valid.ValidCreate; import com.xaaef.molly.common.valid.ValidUpdate; -import com.xaaef.molly.tenant.base.BaseEntity; +import com.xaaef.molly.tenant.base.ParamBaseEntity; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.*; import lombok.*; @@ -37,7 +37,7 @@ import java.util.Set; @Accessors(chain = true) @AllArgsConstructor @NoArgsConstructor -public class PmsUser extends BaseEntity { +public class PmsUser extends ParamBaseEntity { /** * 用户ID diff --git a/server/molly-pms/src/main/java/com/xaaef/molly/perms/mapper/PmsDeptMapper.java b/server/molly-pms/src/main/java/com/xaaef/molly/perms/mapper/PmsDeptMapper.java index fc9a371..44b7d6e 100644 --- a/server/molly-pms/src/main/java/com/xaaef/molly/perms/mapper/PmsDeptMapper.java +++ b/server/molly-pms/src/main/java/com/xaaef/molly/perms/mapper/PmsDeptMapper.java @@ -1,7 +1,9 @@ package com.xaaef.molly.perms.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.xaaef.molly.perms.entity.PmsDept; +import com.xaaef.molly.tenant.ds.DataScope; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; @@ -87,4 +89,23 @@ public interface PmsDeptMapper extends BaseMapper { Set selectDeptIdByRuleIds(Set roleIds); + /** + * 根据条件分页查询数据 + */ + @DataScope() + IPage selectDeptPage(IPage page, @Param("p") PmsDept role); + + + /** + * 根据条件列表查询数据 + */ + @DataScope() + List selectDeptList(@Param("p") PmsDept dept); + + + @DataScope() + Set selectDeptIdList(@Param("p") PmsDept dept); + + + } diff --git a/server/molly-pms/src/main/java/com/xaaef/molly/perms/mapper/PmsRoleMapper.java b/server/molly-pms/src/main/java/com/xaaef/molly/perms/mapper/PmsRoleMapper.java index 48811a0..bc232b5 100644 --- a/server/molly-pms/src/main/java/com/xaaef/molly/perms/mapper/PmsRoleMapper.java +++ b/server/molly-pms/src/main/java/com/xaaef/molly/perms/mapper/PmsRoleMapper.java @@ -1,9 +1,11 @@ package com.xaaef.molly.perms.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.xaaef.molly.common.domain.LinkedTarget; import com.xaaef.molly.perms.entity.PmsRole; import com.xaaef.molly.perms.entity.PmsRoleProxy; +import com.xaaef.molly.tenant.ds.DataScope; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; @@ -78,4 +80,20 @@ public interface PmsRoleMapper extends BaseMapper { @Param("deptIds") Set deptIds); + + /** + * 根据条件列表查询数据 + */ + @DataScope() + List selectRoleList(@Param("p") PmsRole role); + + + /** + * 根据条件分页查询数据 + */ + @DataScope() + IPage selectRolePage(IPage page, @Param("p") PmsRole role); + + + } \ No newline at end of file diff --git a/server/molly-pms/src/main/java/com/xaaef/molly/perms/mapper/PmsUserMapper.java b/server/molly-pms/src/main/java/com/xaaef/molly/perms/mapper/PmsUserMapper.java index c4e75e2..2de3b6f 100644 --- a/server/molly-pms/src/main/java/com/xaaef/molly/perms/mapper/PmsUserMapper.java +++ b/server/molly-pms/src/main/java/com/xaaef/molly/perms/mapper/PmsUserMapper.java @@ -1,7 +1,9 @@ package com.xaaef.molly.perms.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.xaaef.molly.perms.entity.PmsUser; +import com.xaaef.molly.tenant.ds.DataScope; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Param; @@ -32,4 +34,20 @@ public interface PmsUserMapper extends BaseMapper { @Param("dbNameList") Set dbNameList, @Param("userIdList") Set userIdList); + + + /** + * 根据条件列表查询数据 + */ + @DataScope() + List selectUserList(@Param("p") PmsUser user); + + + /** + * 根据条件分页查询数据 + */ + @DataScope() + IPage selectUserPage(IPage page, @Param("p") PmsUser user); + + } \ No newline at end of file diff --git a/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/PmsDeptService.java b/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/PmsDeptService.java index afe12c2..7c03b88 100644 --- a/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/PmsDeptService.java +++ b/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/PmsDeptService.java @@ -24,7 +24,7 @@ public interface PmsDeptService extends BaseService { /** * 分页查询 */ - IPage pageKeywords(SearchParentPO po); + IPage pageKeywords(SearchParentPO params); /** diff --git a/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/PmsRoleService.java b/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/PmsRoleService.java index 83401bb..1e674dc 100644 --- a/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/PmsRoleService.java +++ b/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/PmsRoleService.java @@ -20,6 +20,7 @@ import java.util.Set; public interface PmsRoleService extends BaseService { + IPage pageKeywords(SearchPO params); diff --git a/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/impl/PmsDeptServiceImpl.java b/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/impl/PmsDeptServiceImpl.java index b5906ec..ca4c3b3 100644 --- a/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/impl/PmsDeptServiceImpl.java +++ b/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/impl/PmsDeptServiceImpl.java @@ -51,31 +51,57 @@ public class PmsDeptServiceImpl extends BaseServiceImpl private final ApiCmsProjectService projectService; @Override - public IPage pageKeywords(SearchParentPO po) { - var wrapper = super.getKeywordsQueryWrapper( - po, - List.of( - PmsDept::getDeptName, PmsDept::getDescription, - PmsDept::getLeader, PmsDept::getLeaderMobile - ) - ); - if (po.getParentId() != null) { - wrapper.lambda().eq(PmsDept::getParentId, po.getParentId()); + public IPage pageKeywords(SearchParentPO params) { + var dept = new PmsDept(); + if (StrUtil.isNotBlank(params.getKeywords())) { + dept.setDeptName(params.getKeywords()); } - Page pageRequest = Page.of(po.getPageIndex(), po.getPageSize()); - return super.page(pageRequest, wrapper); + if (params.getParentId() != null && params.getParentId() > 0) { + dept.setParentId(params.getParentId()); + } + Page pageRequest = Page.of(params.getPageIndex(), params.getPageSize()); + var result = baseMapper.selectDeptPage(pageRequest, dept); + if (params.isIncludeCauu()) { + reflectionFill(result.getRecords()); + } + return result; } @Override public List> treeNode() { - var nodeList = this.list().stream().map(r -> { - var node = new TreeNode<>(r.getDeptId(), r.getParentId(), r.getDeptName(), r.getSort()); - var targetMap = new HashMap(); - BeanUtil.beanToMap(r, targetMap, CopyOptions.create().setIgnoreNullValue(true)); - node.setExtra(targetMap); - return node; - }).collect(Collectors.toList()); + final var deptList = baseMapper.selectDeptList(new PmsDept()); + // 获取 部门的 所有祖籍节点 + var ancestors = deptList.stream() + .filter(a -> StrUtil.isNotBlank(a.getAncestors())) + .map(a -> a.getAncestors().split(StrUtil.COMMA)) + .flatMap(Stream::of) + .filter(StrUtil::isNotBlank) + .map(Long::parseLong) + .filter(a -> a > 0) + .collect(Collectors.toSet()); + // 移除已经存在的节点 + if (!ancestors.isEmpty()) { + var c1 = deptList.stream().map(PmsDept::getDeptId).collect(Collectors.toSet()); + ancestors.removeAll(c1); + } + var disableMaps = new HashMap(); + if (!ancestors.isEmpty()) { + this.listByIds(ancestors) + .forEach(d -> { + disableMaps.put(d.getDeptId(), true); + deptList.add(d); + }); + } + var nodeList = deptList.stream() + .map(r -> { + var node = new TreeNode<>(r.getDeptId(), r.getParentId(), r.getDeptName(), r.getSort()); + var targetMap = new HashMap(); + BeanUtil.beanToMap(r, targetMap, CopyOptions.create().setIgnoreNullValue(true)); + targetMap.put("disabled", disableMaps.getOrDefault(r.getDeptId(), false)); + node.setExtra(targetMap); + return node; + }).collect(Collectors.toList()); return TreeUtil.build(nodeList, 0L); } diff --git a/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/impl/PmsRoleServiceImpl.java b/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/impl/PmsRoleServiceImpl.java index 053cc0d..f9b4276 100644 --- a/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/impl/PmsRoleServiceImpl.java +++ b/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/impl/PmsRoleServiceImpl.java @@ -4,20 +4,19 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.lang.tree.TreeNode; import cn.hutool.core.lang.tree.TreeUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.metadata.IPage; -import com.xaaef.molly.common.consts.DataScopeConst; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.xaaef.molly.common.domain.LinkedTarget; import com.xaaef.molly.common.exception.BizException; import com.xaaef.molly.common.po.SearchPO; import com.xaaef.molly.common.util.TenantUtils; import com.xaaef.molly.internal.api.ApiSysMenuService; import com.xaaef.molly.internal.dto.SysMenuDTO; -import com.xaaef.molly.perms.entity.PmsDept; import com.xaaef.molly.perms.entity.PmsRole; import com.xaaef.molly.perms.entity.PmsRoleProxy; -import com.xaaef.molly.perms.mapper.PmsDeptMapper; import com.xaaef.molly.perms.mapper.PmsRoleMapper; +import com.xaaef.molly.perms.service.PmsDeptService; import com.xaaef.molly.perms.service.PmsRoleService; import com.xaaef.molly.perms.vo.UpdateMenusVO; import com.xaaef.molly.tenant.base.service.impl.BaseServiceImpl; @@ -31,6 +30,8 @@ import java.io.Serializable; import java.util.*; import java.util.stream.Collectors; +import static com.xaaef.molly.common.consts.DataScopeConst.DATA_SCOPE_CUSTOM; + /** *

@@ -49,40 +50,39 @@ public class PmsRoleServiceImpl extends BaseServiceImpl private final ApiSysMenuService menuService; - private final PmsDeptMapper deptMapper; + private final PmsDeptService deptService; private final MultiTenantManager tenantManager; @Override public IPage pageKeywords(SearchPO params) { - var result = super.pageKeywords( - params, List.of(PmsRole::getRoleName, PmsRole::getDescription) - ); + Page pageRequest = Page.of(params.getPageIndex(), params.getPageSize()); + var sysRole = new PmsRole(); + if (StrUtil.isNotBlank(params.getKeywords())) { + sysRole.setDescription(params.getKeywords()); + } + var result = baseMapper.selectRolePage(pageRequest, sysRole); includeDept(result.getRecords()); + if (params.isIncludeCauu()) { + reflectionFill(result.getRecords()); + } return result; } + @Override + public List list() { + return baseMapper.selectRoleList(new PmsRole()); + } + + @Override public UpdateMenusVO listHaveDepts(Long roleId) { var result = new UpdateMenusVO() .setAll(new ArrayList<>()) .setHave(new HashSet<>()); - var w1 = new LambdaQueryWrapper() - .select(List.of(PmsDept::getDeptId, PmsDept::getDeptName, - PmsDept::getParentId, PmsDept::getSort)); - final var deptList = deptMapper.selectList(w1); - if (!deptList.isEmpty()) { - // 获取全部的菜单 - var all = deptList.stream() - .map(r -> new TreeNode<>( - r.getDeptId(), r.getParentId(), - r.getDeptName(), r.getSort()) - ) - .collect(Collectors.toList()); - result.setAll(TreeUtil.build(all, 0L)); - } + result.setAll(deptService.treeNode()); if (roleId > 0) { final var haveList = baseMapper.selectDeptIdByRoleIds(Set.of(roleId)); if (!haveList.isEmpty()) { @@ -98,7 +98,7 @@ public class PmsRoleServiceImpl extends BaseServiceImpl if (CollectionUtil.isNotEmpty(list)) { var roleIds = list .stream() - .filter(r -> Objects.equals(r.getDataScope(), DataScopeConst.CUSTOM)) + .filter(r -> Objects.equals(r.getDataScope(), DATA_SCOPE_CUSTOM)) .map(PmsRole::getRoleId) .collect(Collectors.toSet()); if (!roleIds.isEmpty()) { @@ -206,7 +206,7 @@ public class PmsRoleServiceImpl extends BaseServiceImpl @Transactional(rollbackFor = Exception.class) @Override public boolean save(PmsRole entity) { - if (entity.getDataScope() == 2) { + if (Objects.equals(entity.getDataScope(), DATA_SCOPE_CUSTOM)) { if (CollectionUtil.isEmpty(entity.getDeptIds())) { throw new RuntimeException("自定义数据权限,最少需要选择一个部门"); } @@ -221,7 +221,7 @@ public class PmsRoleServiceImpl extends BaseServiceImpl @Transactional(rollbackFor = Exception.class) @Override public boolean updateById(PmsRole entity) { - if (entity.getDataScope() == 2) { + if (Objects.equals(entity.getDataScope(), DATA_SCOPE_CUSTOM)) { if (CollectionUtil.isEmpty(entity.getDeptIds())) { throw new RuntimeException("自定义数据权限,最少需要选择一个部门"); } diff --git a/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/impl/PmsUserServiceImpl.java b/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/impl/PmsUserServiceImpl.java index 6922729..3f42987 100644 --- a/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/impl/PmsUserServiceImpl.java +++ b/server/molly-pms/src/main/java/com/xaaef/molly/perms/service/impl/PmsUserServiceImpl.java @@ -2,12 +2,13 @@ package com.xaaef.molly.perms.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; -import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.lang.tree.TreeNode; import cn.hutool.core.lang.tree.TreeUtil; +import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.xaaef.molly.auth.jwt.JwtLoginUser; import com.xaaef.molly.auth.jwt.JwtSecurityUtils; @@ -47,6 +48,7 @@ import java.util.stream.Collectors; import static com.xaaef.molly.auth.jwt.JwtSecurityUtils.*; import static com.xaaef.molly.common.consts.ConfigDataConst.DEFAULT_USER_PASSWORD; +import static com.xaaef.molly.common.consts.MbpConst.CREATE_TIME; import static com.xaaef.molly.common.enums.AdminFlag.NO; import static com.xaaef.molly.common.enums.MenuTypeEnum.BUTTON; import static com.xaaef.molly.common.enums.MenuTypeEnum.MENU; @@ -87,19 +89,16 @@ public class PmsUserServiceImpl extends BaseServiceImpl @Override public IPage pageKeywords(UserQueryPO params) { - var wrapper = super.getKeywordsQueryWrapper(params, - List.of(PmsUser::getUsername, PmsUser::getNickname)); - if (params.getDeptId() != null && params.getDeptId() > 0L) { - if (CollectionUtil.contains(getLoginUser().getHaveDeptIds(), params.getDeptId())) { - wrapper.lambda().in(PmsUser::getDeptId, params.getDeptId()); - } else { - wrapper.lambda().in(PmsUser::getDeptId, getLoginUser().getHaveDeptIds()); - } - } else { - wrapper.lambda().in(PmsUser::getDeptId, getLoginUser().getHaveDeptIds()); + var userParams = new PmsUser(); + if (NumberUtil.isValidNumber(params.getDeptId())) { + userParams.setDeptId(params.getDeptId()); + } + if (StringUtils.isNotBlank(params.getKeywords())) { + userParams.setNickname(params.getKeywords()); } Page pageRequest = Page.of(params.getPageIndex(), params.getPageSize()); - Page result = super.page(pageRequest, wrapper); + pageRequest.addOrder(OrderItem.desc(CREATE_TIME)); + IPage result = baseMapper.selectUserPage(pageRequest, userParams); if (params.isIncludeCauu()) { reflectionFill(result.getRecords()); } diff --git a/server/molly-pms/src/main/resources/mapper/PmsDeptMapper.xml b/server/molly-pms/src/main/resources/mapper/PmsDeptMapper.xml index e898ea6..a867e62 100644 --- a/server/molly-pms/src/main/resources/mapper/PmsDeptMapper.xml +++ b/server/molly-pms/src/main/resources/mapper/PmsDeptMapper.xml @@ -51,25 +51,30 @@ @@ -77,10 +82,10 @@ @@ -93,4 +98,40 @@ + + + + AND d.dept_id = #{p.deptId} + + + AND d.parent_id = #{p.parentId} + + + AND CONCAT(d.dept_name,d.leader,d.description) LIKE CONCAT('%',#{p.deptName},'%') + + + ${p.params.dataScope} + + + + + + + + + + + + diff --git a/server/molly-pms/src/main/resources/mapper/PmsRoleMapper.xml b/server/molly-pms/src/main/resources/mapper/PmsRoleMapper.xml index 7dbca63..490c4a0 100644 --- a/server/molly-pms/src/main/resources/mapper/PmsRoleMapper.xml +++ b/server/molly-pms/src/main/resources/mapper/PmsRoleMapper.xml @@ -16,9 +16,9 @@ - - role_id,role_name, + role_id + ,role_name, sort,`description`,create_time, create_user,last_update_time,last_update_user @@ -56,7 +56,7 @@ @@ -85,5 +85,49 @@ + + select distinct r.role_id, + r.role_name, + r.sort, + r.description, + r.data_scope, + r.create_time, + r.create_user, + r.last_update_time, + r.last_update_user + from pms_role r + left join pms_user_role ur on ur.role_id = r.role_id + left join pms_user u on u.user_id = ur.user_id + left join pms_dept d on u.dept_id = d.dept_id + + + + + + + AND r.role_id = #{p.roleId} + + + AND CONCAT(r.`role_name`,r.description) LIKE CONCAT('%',#{p.description},'%') + + + ${p.params.dataScope} + + + + + + + + + diff --git a/server/molly-pms/src/main/resources/mapper/PmsUserMapper.xml b/server/molly-pms/src/main/resources/mapper/PmsUserMapper.xml index 9603165..a64e06e 100644 --- a/server/molly-pms/src/main/resources/mapper/PmsUserMapper.xml +++ b/server/molly-pms/src/main/resources/mapper/PmsUserMapper.xml @@ -3,7 +3,7 @@ "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - + @@ -30,7 +30,7 @@ - SELECT user_id,avatar,nickname FROM ${item}.pms_user WHERE user_id IN @@ -40,4 +40,35 @@ + + + + AND u.user_id = #{p.userId} + + + AND CONCAT(u.`username`,u.nickname) LIKE CONCAT('%',#{p.nickname},'%') + + + AND (u.dept_id = #{p.deptId} OR u.dept_id IN ( SELECT t.dept_id FROM pms_dept t WHERE find_in_set(#{p.deptId}, ancestors) )) + + + ${p.params.dataScope} + + + + + + + + + + diff --git a/server/molly-service/src/main/resources/db/changelog/sql/pms_init.sql b/server/molly-service/src/main/resources/db/changelog/sql/pms_init.sql index 938ba22..d457bde 100644 --- a/server/molly-service/src/main/resources/db/changelog/sql/pms_init.sql +++ b/server/molly-service/src/main/resources/db/changelog/sql/pms_init.sql @@ -38,7 +38,7 @@ VALUES (10001, 0, '集团', '张集团', '15055555555', 1, '集团', '0', '2022- -- ---------------------------- INSERT INTO `pms_role` (`role_id`, `role_name`, `sort`, `data_scope`, `description`, `create_time`, `create_user`, `last_update_time`, `last_update_user`) -VALUES (10001, '管理员', 10, 4, '管理员', '2022-06-10 23:11:09', 19980817, '2022-06-10 23:11:09', 19980817), +VALUES (10001, '管理员', 10, 1, '管理员', '2022-06-10 23:11:09', 19980817, '2022-06-10 23:11:09', 19980817), (10002, '测试员', 20, 4, '测试员', '2023-11-09 10:11:49', 19980817, '2023-11-09 10:11:49', 19980817), (10003, '运营员', 30, 4, '运营员', '2023-11-09 10:12:01', 19980817, '2023-11-09 10:12:01', 19980817); diff --git a/server/molly-service/src/main/resources/db/changelog/sql/sys_dict_data.sql b/server/molly-service/src/main/resources/db/changelog/sql/sys_dict_data.sql index 903f982..4193cd2 100644 --- a/server/molly-service/src/main/resources/db/changelog/sql/sys_dict_data.sql +++ b/server/molly-service/src/main/resources/db/changelog/sql/sys_dict_data.sql @@ -67,7 +67,8 @@ VALUES (10042, 0, '全部数据权限', '1', 'sys_data_scope', 0, 19980817, '2024-08-13 10:19:18', 19980817, '2024-08-13 10:20:34'), (10043, 0, '自定数据权限', '2', 'sys_data_scope', 0, 19980817, '2024-08-13 10:19:39', 19980817, '2024-08-13 10:20:40'), (10044, 0, '仅本部门数据权限', '3', 'sys_data_scope', 0, 19980817, '2024-08-13 10:20:22', 19980817, '2024-08-13 10:20:22'), -(10045, 0, '本部门及以下数据权限', '4', 'sys_data_scope', 1, 19980817, '2024-08-13 10:20:29', 19980817, '2024-08-13 10:20:43'); +(10045, 0, '本部门及以下数据权限', '4', 'sys_data_scope', 1, 19980817, '2024-08-13 10:20:29', 19980817, '2024-08-13 10:20:43'), +(10046, 0, '仅本人数据权限', '5', 'sys_data_scope', 0, 19980817, '2024-08-13 10:20:29', 19980817, '2024-08-13 10:20:43'); SET FOREIGN_KEY_CHECKS = 1; diff --git a/server/molly-service/src/test/java/com/xaaef/molly/NoSpringTests.java b/server/molly-service/src/test/java/com/xaaef/molly/NoSpringTests.java index 7c0ab70..08dc49f 100644 --- a/server/molly-service/src/test/java/com/xaaef/molly/NoSpringTests.java +++ b/server/molly-service/src/test/java/com/xaaef/molly/NoSpringTests.java @@ -21,6 +21,19 @@ import io.swagger.v3.oas.annotations.media.Schema; import liquibase.integration.spring.MultiTenantSpringLiquibase; import lombok.*; import lombok.experimental.Accessors; +import net.sf.jsqlparser.expression.LongValue; +import net.sf.jsqlparser.expression.StringValue; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.expression.operators.conditional.OrExpression; +import net.sf.jsqlparser.expression.operators.relational.*; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.select.OrderByElement; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.statement.select.Select; +import net.sf.jsqlparser.util.SelectUtils; +import org.assertj.core.util.Sets; import org.junit.jupiter.api.Test; import org.springframework.core.io.FileSystemResourceLoader; @@ -34,7 +47,9 @@ import java.time.LocalTime; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.regex.Pattern; +import java.util.stream.Collectors; import java.util.stream.Stream; import static com.xaaef.molly.common.consts.LoginConst.*; @@ -271,4 +286,142 @@ public class NoSpringTests { } + @Test + public void test19() throws Exception { + // 单表全量 + Table table = new Table("test"); + Select select = SelectUtils.buildSelectFromTable(table); + System.err.println(select); // SELECT * FROM test + + // 指定列查询 + Select buildSelectFromTableAndExpressions = SelectUtils.buildSelectFromTableAndExpressions(new Table("test"), new Column("col1"), new Column("col2")); + System.err.println(buildSelectFromTableAndExpressions); // SELECT col1, col2 FROM test + + // WHERE = + EqualsTo equalsTo = new EqualsTo(); // 等于表达式 + equalsTo.setLeftExpression(new Column(table, "user_id")); // 设置表达式左边值 + equalsTo.setRightExpression(new StringValue("123456"));// 设置表达式右边值 + PlainSelect plainSelect = (PlainSelect) select.getSelectBody(); // 转换为更细化的Select对象 + plainSelect.setWhere(equalsTo); + System.err.println(plainSelect);// SELECT * FROM test WHERE test.user_id = '123456' + + // WHERE != <> + NotEqualsTo notEqualsTo = new NotEqualsTo(); + notEqualsTo.setLeftExpression(new Column(table, "user_id")); // 设置表达式左边值 + notEqualsTo.setRightExpression(new StringValue("123456"));// 设置表达式右边值 + PlainSelect plainSelectNot = (PlainSelect) select.getSelectBody(); + plainSelectNot.setWhere(notEqualsTo); + System.err.println(plainSelectNot);// SELECT * FROM test WHERE test.user_id <> '123456' + + // 其他运算符, 参考上面代码添加表达式即可 + GreaterThan gt = new GreaterThan(); // ">" + GreaterThanEquals geq = new GreaterThanEquals(); // ">=" + MinorThan mt = new MinorThan(); // "<" + MinorThanEquals leq = new MinorThanEquals();// "<=" + IsNullExpression isNull = new IsNullExpression(); // "is null" + isNull.setNot(true);// "is not null" + LikeExpression nlike = new LikeExpression(); + nlike.setNot(true); // "not like" + Between bt = new Between(); + bt.setNot(true);// "not between" + + // WHERE LIKE + LikeExpression likeExpression = new LikeExpression(); // 创建Like表达式对象 + likeExpression.setLeftExpression(new Column("username")); // 表达式左边 + likeExpression.setRightExpression(new StringValue("张%")); // 右边表达式 + PlainSelect plainSelectLike = (PlainSelect) select.getSelectBody(); + plainSelectLike.setWhere(likeExpression); + System.err.println(plainSelectLike); // SELECT * FROM test WHERE username LIKE '张%' + + // WHERE IN + Set deptIds = Sets.newLinkedHashSet(); // 创建IN范围的元素集合 + deptIds.add("0001"); + deptIds.add("0002"); + var itemsList = new ExpressionList(deptIds.stream().map(StringValue::new).collect(Collectors.toList())); // 把集合转变为JSQLParser需要的元素列表 + InExpression inExpression = new InExpression(new Column("dept_id "), itemsList); // 创建IN表达式对象,传入列名及IN范围列表 + PlainSelect plainSelectIn = (PlainSelect) select.getSelectBody(); + plainSelectIn.setWhere(inExpression); + System.err.println(plainSelectIn); // SELECT * FROM test WHERE dept_id IN ('0001', '0002') + + // WHERE BETWEEN AND + Between between = new Between(); + between.setBetweenExpressionStart(new LongValue(18)); // 设置起点值 + between.setBetweenExpressionEnd(new LongValue(30)); // 设置终点值 + between.setLeftExpression(new Column("age")); // 设置左边的表达式,一般为列 + PlainSelect plainSelectBetween = (PlainSelect) select.getSelectBody(); + plainSelectBetween.setWhere(between); + System.err.println(plainSelectBetween); // SELECT * FROM test WHERE age BETWEEN 18 AND 30 + + // WHERE AND 多个条件结合,都需要成立 + AndExpression andExpression = new AndExpression(); // AND 表达式 + andExpression.setLeftExpression(equalsTo); // AND 左边表达式 + andExpression.setRightExpression(between); // AND 右边表达式 + PlainSelect plainSelectAnd = (PlainSelect) select.getSelectBody(); + plainSelectAnd.setWhere(andExpression); + System.err.println(plainSelectAnd); // SELECT * FROM test WHERE test.user_id = '123456' AND age BETWEEN 18 AND 30 + + // WHERE OR 多个条件满足一个条件成立返回 + OrExpression orExpression = new OrExpression();// OR 表达式 + orExpression.setLeftExpression(equalsTo); // OR 左边表达式 + orExpression.setRightExpression(between); // OR 右边表达式 + PlainSelect plainSelectOr = (PlainSelect) select.getSelectBody(); + plainSelectOr.setWhere(orExpression); + System.err.println(plainSelectOr); // SELECT * FROM test WHERE test.user_id = '123456' OR age BETWEEN 18 AND 30 + + // ORDER BY 排序 + OrderByElement orderByElement = new OrderByElement(); // 创建排序对象 + orderByElement.isAsc(); // 设置升序排列 从小到大 + orderByElement.setExpression(new Column("col01")); // 设置排序字段 + PlainSelect plainSelectOrderBy = (PlainSelect) select.getSelectBody(); + plainSelectOrderBy.addOrderByElements(orderByElement); + System.err.println(plainSelectOrderBy); // SELECT * FROM test WHERE test.user_id = '123456' OR age BETWEEN 18 AND 30 ORDER BY col01 + } + + + @Test + public void test20() throws Exception { + // 单表全量 + Table table = new Table("test"); + Select select = SelectUtils.buildSelectFromTable(table); + System.err.println(select); // SELECT * FROM test + + EqualsTo equalsTo = new EqualsTo(); // 等于表达式 + equalsTo.setLeftExpression(new Column(table, "user_id")); // 设置表达式左边值 + equalsTo.setRightExpression(new StringValue("123456"));// 设置表达式右边值 + + final var in = CCJSqlParserUtil.parseExpression("u.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id in (1,2) )"); + PlainSelect plainSelectIn = (PlainSelect) select.getSelectBody(); + plainSelectIn.setWhere( + new AndExpression(equalsTo, new AndExpression(equalsTo, new AndExpression(equalsTo, in))) + ); + System.err.println(plainSelectIn); // SELECT * FROM test WHERE dept_id IN ('0001', '0002') + + + } + + @Test + public void test21() throws Exception { + Select childSelect = SelectUtils.buildSelectFromTableAndExpressions( + new Table("sys_role_dept"), + new Column("dept_id") + ); + Set deptIds = Set.of("10001", "10002", "10003"); + var itemsList = new ExpressionList<>(deptIds.stream().map(StringValue::new).collect(Collectors.toList())); + InExpression inExpression = new InExpression(new Column("dept_id "), itemsList); + childSelect.getPlainSelect().setWhere(inExpression); + System.err.println(childSelect); + + Select select = SelectUtils.buildSelectFromTable( + new Table("sys_role") + ); + + EqualsTo equalsTo = new EqualsTo(); // 等于表达式 + equalsTo.setLeftExpression(new Column("user_id")); // 设置表达式左边值 + equalsTo.setRightExpression(childSelect);// 设置表达式右边值 + + select.getPlainSelect().setWhere(equalsTo); + + System.err.println(select.getPlainSelect());// SELECT * FROM test WHERE test.user_id = '123456' + + } } diff --git a/server/plugins/auth-jwt/src/main/java/com/xaaef/molly/auth/service/impl/UserLoginServiceImpl.java b/server/plugins/auth-jwt/src/main/java/com/xaaef/molly/auth/service/impl/UserLoginServiceImpl.java index a28790b..a8cd3b0 100644 --- a/server/plugins/auth-jwt/src/main/java/com/xaaef/molly/auth/service/impl/UserLoginServiceImpl.java +++ b/server/plugins/auth-jwt/src/main/java/com/xaaef/molly/auth/service/impl/UserLoginServiceImpl.java @@ -12,7 +12,6 @@ import com.xaaef.molly.auth.service.JwtTokenService; import com.xaaef.molly.auth.service.LineCaptchaService; import com.xaaef.molly.auth.service.RsaAsymmetricCryptoService; import com.xaaef.molly.auth.service.UserLoginService; -import com.xaaef.molly.common.consts.DataScopeConst; import com.xaaef.molly.common.domain.CustomRequestInfo; import com.xaaef.molly.common.enums.AdminFlag; import com.xaaef.molly.common.enums.StatusEnum; @@ -38,6 +37,7 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import static com.xaaef.molly.common.consts.DataScopeConst.*; /** *

@@ -248,7 +248,7 @@ public class UserLoginServiceImpl implements UserLoginService { return Set.of(); } // 角色列表中是否包含 1.全部数据权限 - var isAll = target.getRoles().stream().anyMatch(a -> Objects.equals(a.getDataScope(), DataScopeConst.All)); + var isAll = target.getRoles().stream().anyMatch(a -> Objects.equals(a.getDataScope(), DATA_SCOPE_ALL)); if (isAll) { return deptService.listDeptIdByAll(); } @@ -256,7 +256,7 @@ public class UserLoginServiceImpl implements UserLoginService { var depsIds = new HashSet(); // 角色列表中是否包含 2.自定数据权限 var roleIds = target.getRoles().stream() - .filter(a -> Objects.equals(a.getDataScope(), DataScopeConst.CUSTOM)) + .filter(a -> Objects.equals(a.getDataScope(), DATA_SCOPE_CUSTOM)) .map(PmsRoleDTO::getRoleId).collect(Collectors.toSet()); if (!roleIds.isEmpty()) { var v1 = deptService.listDeptIdByRuleId(roleIds); @@ -264,13 +264,13 @@ public class UserLoginServiceImpl implements UserLoginService { } // 角色列表中是否包含 3.仅本部门数据权限 - var isOnlyMe = target.getRoles().stream().anyMatch(a -> Objects.equals(a.getDataScope(), DataScopeConst.ONLY_ME)); + var isOnlyMe = target.getRoles().stream().anyMatch(a -> Objects.equals(a.getDataScope(), DATA_SCOPE_DEPT)); if (isOnlyMe) { depsIds.add(target.getDeptId()); } // 角色列表中是否包含 4:本部门及以下数据权限 - var isMeAndChild = target.getRoles().stream().anyMatch(a -> Objects.equals(a.getDataScope(), DataScopeConst.ME_AND_CHILD)); + var isMeAndChild = target.getRoles().stream().anyMatch(a -> Objects.equals(a.getDataScope(), DATA_SCOPE_DEPT_AND_CHILD)); if (isMeAndChild) { var v1 = deptService.listChildIdByDeptId(target.getDeptId()); depsIds.addAll(v1); diff --git a/server/plugins/mbp-tenant/pom.xml b/server/plugins/mbp-tenant/pom.xml index ae9d569..8a68e3f 100644 --- a/server/plugins/mbp-tenant/pom.xml +++ b/server/plugins/mbp-tenant/pom.xml @@ -16,6 +16,11 @@ + + org.springframework.boot + spring-boot-starter-aop + + com.baomidou mybatis-plus-spring-boot3-starter diff --git a/server/plugins/mbp-tenant/src/main/java/com/xaaef/molly/tenant/base/ParamBaseEntity.java b/server/plugins/mbp-tenant/src/main/java/com/xaaef/molly/tenant/base/ParamBaseEntity.java new file mode 100644 index 0000000..fc82e85 --- /dev/null +++ b/server/plugins/mbp-tenant/src/main/java/com/xaaef/molly/tenant/base/ParamBaseEntity.java @@ -0,0 +1,44 @@ +package com.xaaef.molly.tenant.base; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Getter; +import lombok.Setter; + +import java.util.HashMap; +import java.util.Map; + +/** + *

+ * 项目基础类 + *

+ * + * @author WangChenChen + * @version 1.1 + * @date 2022/12/9 13:39 + */ + +@Getter +@Setter +public class ParamBaseEntity extends BaseEntity implements java.io.Serializable { + + /** + * 参数 + */ + @JsonIgnore + @TableField(exist = false) + private Map params; + + @JsonIgnore + public Map getParamsValue() { + if (params == null) { + params = new HashMap<>(); + } + return params; + } + + public void setParamsValue(Map params) { + this.params = params; + } + +} diff --git a/server/plugins/mbp-tenant/src/main/java/com/xaaef/molly/tenant/ds/DataScope.java b/server/plugins/mbp-tenant/src/main/java/com/xaaef/molly/tenant/ds/DataScope.java new file mode 100644 index 0000000..f3c8d64 --- /dev/null +++ b/server/plugins/mbp-tenant/src/main/java/com/xaaef/molly/tenant/ds/DataScope.java @@ -0,0 +1,24 @@ +package com.xaaef.molly.tenant.ds; + +import java.lang.annotation.*; + +/** + * 数据权限过滤注解 + */ + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DataScope { + + /** + * 部门的别名 + */ + String deptAlias() default "d"; + + /** + * 用户表的别名 + */ + String userAlias() default "u"; + +} \ No newline at end of file diff --git a/server/plugins/mbp-tenant/src/main/java/com/xaaef/molly/tenant/ds/DataScopeAspect.java b/server/plugins/mbp-tenant/src/main/java/com/xaaef/molly/tenant/ds/DataScopeAspect.java new file mode 100644 index 0000000..68f0a18 --- /dev/null +++ b/server/plugins/mbp-tenant/src/main/java/com/xaaef/molly/tenant/ds/DataScopeAspect.java @@ -0,0 +1,123 @@ +package com.xaaef.molly.tenant.ds; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.StrUtil; +import com.xaaef.molly.auth.jwt.JwtLoginUser; +import com.xaaef.molly.auth.jwt.JwtSecurityUtils; +import com.xaaef.molly.tenant.base.ParamBaseEntity; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Objects; + +import static com.xaaef.molly.common.consts.DataScopeConst.*; + +/** + * 数据过滤处理 + */ + +@Aspect +@Component +public class DataScopeAspect { + + + @Before("@annotation(controllerDataScope)") + public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable { + clearDataScope(point); + handleDataScope(point, controllerDataScope); + } + + + protected void handleDataScope(final JoinPoint joinPoint, DataScope ds) { + if (!JwtSecurityUtils.isAuthenticated()) { + return; + } + // 平台用户 和 租户管理员,禁用数据权限 + if (JwtSecurityUtils.isAdminUser() || JwtSecurityUtils.isMasterUser()) { + return; + } + // 获取当前的用户 + var currentUser = JwtSecurityUtils.getLoginUser(); + dataScopeFilter(joinPoint, currentUser, ds.deptAlias(), ds.userAlias()); + } + + + /** + * 数据范围过滤 + * + * @param joinPoint 切点 + * @param user 用户 + * @param deptAlias 部门别名 + * @param userAlias 用户别名 + */ + public static void dataScopeFilter(JoinPoint joinPoint, JwtLoginUser user, String deptAlias, String userAlias) { + StringBuilder sqlString = new StringBuilder(); + var conditions = new ArrayList(); + var scopeCustomIds = new ArrayList(); + user.getRoles().forEach(role -> { + if (Objects.equals(DATA_SCOPE_CUSTOM, role.getDataScope())) { + scopeCustomIds.add(Convert.toStr(role.getRoleId())); + } + }); + for (var role : user.getRoles()) { + var dataScope = role.getDataScope(); + if (conditions.contains(dataScope)) { + continue; + } + if (Objects.equals(DATA_SCOPE_ALL, dataScope)) { + sqlString = new StringBuilder(); + conditions.add(dataScope); + break; + } else if (Objects.equals(DATA_SCOPE_CUSTOM, dataScope)) { + if (scopeCustomIds.size() > 1) { + // 多个自定数据权限使用in查询,避免多次拼接。 + sqlString.append(StrUtil.format(" OR {}.dept_id IN ( SELECT dept_id FROM pms_role_dept WHERE role_id in ({}) ) ", deptAlias, String.join(",", scopeCustomIds))); + } else { + sqlString.append(StrUtil.format(" OR {}.dept_id IN ( SELECT dept_id FROM pms_role_dept WHERE role_id = {} ) ", deptAlias, role.getRoleId())); + } + } else if (Objects.equals(DATA_SCOPE_DEPT, dataScope)) { + sqlString.append(StrUtil.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId())); + } else if (Objects.equals(DATA_SCOPE_DEPT_AND_CHILD, dataScope)) { + sqlString.append(StrUtil.format(" OR {}.dept_id IN ( SELECT dept_id FROM pms_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", deptAlias, user.getDeptId(), user.getDeptId())); + } else if (Objects.equals(DATA_SCOPE_SELF, dataScope)) { + if (StrUtil.isNotBlank(userAlias)) { + sqlString.append(StrUtil.format(" OR {}.user_id = {} ", userAlias, user.getUserId())); + } else { + // 数据权限为仅本人且没有userAlias别名不查询任何数据 + sqlString.append(StrUtil.format(" OR {}.dept_id = 0 ", deptAlias)); + } + } + conditions.add(dataScope); + } + // 角色都不包含传递过来的权限字符,这个时候sqlString也会为空,所以要限制一下,不查询任何数据 + if (CollectionUtil.isEmpty(conditions)) { + sqlString.append(StrUtil.format(" OR {}.dept_id = 0 ", deptAlias)); + } + if (StrUtil.isNotBlank(sqlString.toString())) { + var params = Arrays.stream(joinPoint.getArgs()).filter(a -> a instanceof ParamBaseEntity).findFirst(); + if (params.isPresent()) { + var baseEntity = (ParamBaseEntity) params.get(); + baseEntity.getParamsValue().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")"); + } + } + } + + + /** + * 拼接权限sql前先清空params.dataScope参数防止注入 + */ + private void clearDataScope(final JoinPoint joinPoint) { + var params = Arrays.stream(joinPoint.getArgs()).filter(a -> a instanceof ParamBaseEntity).findFirst(); + if (params.isPresent()) { + var baseEntity = (ParamBaseEntity) params.get(); + baseEntity.getParamsValue().put(DATA_SCOPE, ""); + } + } + + +} \ No newline at end of file diff --git a/server/plugins/mbp-tenant/src/main/java/com/xaaef/molly/tenant/schema/SchemaInterceptor.java b/server/plugins/mbp-tenant/src/main/java/com/xaaef/molly/tenant/schema/SchemaInterceptor.java index 1e35202..e2c225b 100644 --- a/server/plugins/mbp-tenant/src/main/java/com/xaaef/molly/tenant/schema/SchemaInterceptor.java +++ b/server/plugins/mbp-tenant/src/main/java/com/xaaef/molly/tenant/schema/SchemaInterceptor.java @@ -10,6 +10,7 @@ import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.Statements; import net.sf.jsqlparser.util.TablesNamesFinder; import org.apache.ibatis.executor.statement.StatementHandler; @@ -92,7 +93,7 @@ public class SchemaInterceptor implements InnerInterceptor { } - private final static TablesNamesFinder TABLES_NAMES_FINDER = new TablesNamesFinder(); + private final static TablesNamesFinder TABLES_NAMES_FINDER = new TablesNamesFinder<>(); /** @@ -106,9 +107,8 @@ public class SchemaInterceptor implements InnerInterceptor { log.error("getTableListName: \n{}", e.getMessage()); return Set.of(); } - return statements.getStatements() - .stream() - .map(TABLES_NAMES_FINDER::getTableList) + return statements.stream() + .map(TABLES_NAMES_FINDER::getTables) .flatMap(Collection::stream) .collect(Collectors.toSet()); } diff --git a/server/pom.xml b/server/pom.xml index fc65c57..14afec3 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -38,7 +38,7 @@ UTF-8 UTF-8 - 0.9.28 + 0.10.3 1.0.6 @@ -54,13 +54,13 @@ 5.3.0 - 5.8.28 + 5.8.32 4.5.0 - 3.5.7 + 3.5.8 - 3.2.8 + 3.2.11 diff --git a/tenant-web-ui/src/utils/index.ts b/tenant-web-ui/src/utils/index.ts index a935267..1f71016 100644 --- a/tenant-web-ui/src/utils/index.ts +++ b/tenant-web-ui/src/utils/index.ts @@ -1,8 +1,8 @@ import dayjs from "dayjs" -import {removeConfigLayout} from "@/utils/cache/local-storage" +import { removeConfigLayout } from "@/utils/cache/local-storage" import chinaAreaJson from "@/assets/ChinaArea.json" -import {ISimpleProject} from "@/types/base" -import {CascaderOption} from "element-plus" +import { ISimpleProject } from "@/types/base" +import { CascaderOption } from "element-plus" //#region 格式化日期时间 export const DEFAULT_DATE_TIME_PATTERN = "YYYY-MM-DD HH:mm:ss" @@ -173,13 +173,14 @@ export const chinaAreaDeepQuery = (areaCode: number) => { } /** 将权限树形结构扁平化为一维数组,用于权限查询 */ -export const flatTreeToCascaderOption = (arr: any[], { value = "id", label = "label", children = "children" }) => { +export const flatTreeToCascaderOption = (arr: any[], { value = "id", label = "label", disabled = "disabled", children = "children" }) => { const result: CascaderOption[] = [] const deep = (arr1: any[], arr2: CascaderOption[]) => { arr1.forEach((item: any) => { const temp: CascaderOption = { value: item[value], - label: item[label] + label: item[label], + disabled: item[disabled] } arr2.push(temp) if (item[children] && item[children].length > 0) {