🎉 3.2.0.RELEASE 新增灵活数据权限特性

This commit is contained in:
smallchill 2021-11-05 01:17:34 +08:00
parent d15f2236c1
commit 5914f6c133
75 changed files with 1826 additions and 200 deletions

View File

@ -1,9 +1,9 @@
<p align="center">
<img src="https://img.shields.io/badge/Release-V3.1.0-green.svg" alt="Downloads">
<img src="https://img.shields.io/badge/Release-V3.2.0-green.svg" alt="Downloads">
<img src="https://img.shields.io/badge/JDK-1.8+-green.svg" alt="Build Status">
<img src="https://img.shields.io/badge/license-Apache%202-blue.svg" alt="Build Status">
<img src="https://img.shields.io/badge/Spring%20Cloud-2020-blue.svg" alt="Coverage Status">
<img src="https://img.shields.io/badge/Spring%20Boot-2.5.2-blue.svg" alt="Downloads">
<img src="https://img.shields.io/badge/Spring%20Boot-2.5.6-blue.svg" alt="Downloads">
<a target="_blank" href="https://bladex.vip">
<img src="https://img.shields.io/badge/Author-Small%20Chill-ff69b4.svg" alt="Downloads">
</a>
@ -186,6 +186,3 @@ Apache Licence也是对商业应用友好的许可。使用者也可以在需要
<td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/springblade-swagger2.png"/></td>
</tr>
</table>
## 关注我们
![](https://images.gitee.com/uploads/images/2019/0330/065148_f0ada806_410595.jpeg)

View File

@ -8,7 +8,7 @@
<parent>
<artifactId>SpringBlade</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<artifactId>blade-auth</artifactId>

View File

@ -61,6 +61,7 @@ public class TokenUtil {
param.put(TokenConstant.OAUTH_ID, userInfo.getOauthId());
param.put(TokenConstant.USER_ID, Func.toStr(user.getId()));
param.put(TokenConstant.ROLE_ID, user.getRoleId());
param.put(TokenConstant.DEPT_ID, user.getDeptId());
param.put(TokenConstant.ACCOUNT, user.getAccount());
param.put(TokenConstant.USER_NAME, user.getAccount());
param.put(TokenConstant.ROLE_NAME, Func.join(userInfo.getRoles()));

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>SpringBlade</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>SpringBlade</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -61,7 +61,7 @@ public class AuthFilter implements GlobalFilter, Ordered {
ServerHttpResponse resp = exchange.getResponse();
String headerToken = exchange.getRequest().getHeaders().getFirst(AuthProvider.AUTH_KEY);
String paramToken = exchange.getRequest().getQueryParams().getFirst(AuthProvider.AUTH_KEY);
if (StringUtils.isAllBlank(headerToken, paramToken)) {
if (StringUtils.isBlank(headerToken) && StringUtils.isBlank(paramToken)) {
return unAuth(resp, "缺失令牌,鉴权失败");
}
String auth = StringUtils.isBlank(headerToken) ? paramToken : headerToken;

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>blade-ops</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>org.springblade</groupId>
<artifactId>blade-ops</artifactId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>org.springblade</groupId>
<artifactId>blade-ops</artifactId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>blade-ops</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>blade-ops</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>blade-ops</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>blade-ops</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,13 +5,13 @@
<parent>
<artifactId>SpringBlade</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>blade-ops</artifactId>
<name>${project.artifactId}</name>
<version>3.1.0</version>
<version>3.2.0</version>
<packaging>pom</packaging>
<modules>
<module>blade-admin</module>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>blade-service-api</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>blade-service-api</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>blade-service-api</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>blade-service-api</artifactId>
<groupId>org.springblade</groupId>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>blade-scope-api</artifactId>
<name>${project.artifactId}</name>
<version>${blade.project.version}</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-secure</artifactId>
<version>${blade.tool.version}</version>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-datascope</artifactId>
<version>${blade.tool.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,92 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.cache;
import org.springblade.core.datascope.model.DataScopeModel;
import org.springblade.core.tool.utils.*;
import org.springblade.system.feign.IDataScopeClient;
import java.util.List;
import static org.springblade.core.tool.utils.CacheUtil.SYS_CACHE;
/**
* 数据权限缓存
*
* @author Chill
*/
public class DataScopeCache {
private static final String SCOPE_CACHE_CODE = "dataScope:code:";
private static final String SCOPE_CACHE_CLASS = "dataScope:class:";
private static final String DEPT_CACHE_ANCESTORS = "dept:ancestors:";
private static IDataScopeClient dataScopeClient;
private static IDataScopeClient getDataScopeClient() {
if (dataScopeClient == null) {
dataScopeClient = SpringUtil.getBean(IDataScopeClient.class);
}
return dataScopeClient;
}
/**
* 获取数据权限
*
* @param mapperId 数据权限mapperId
* @param roleId 用户角色集合
* @return DataScopeModel
*/
public static DataScopeModel getDataScopeByMapper(String mapperId, String roleId) {
DataScopeModel dataScope = CacheUtil.get(SYS_CACHE, SCOPE_CACHE_CLASS, mapperId + StringPool.COLON + roleId, DataScopeModel.class);
if (dataScope == null || !dataScope.getSearched()) {
dataScope = getDataScopeClient().getDataScopeByMapper(mapperId, roleId);
CacheUtil.put(SYS_CACHE, SCOPE_CACHE_CLASS, mapperId + StringPool.COLON + roleId, dataScope);
}
return StringUtil.isNotBlank(dataScope.getResourceCode()) ? dataScope : null;
}
/**
* 获取数据权限
*
* @param code 数据权限资源编号
* @return DataScopeModel
*/
public static DataScopeModel getDataScopeByCode(String code) {
DataScopeModel dataScope = CacheUtil.get(SYS_CACHE, SCOPE_CACHE_CODE, code, DataScopeModel.class);
if (dataScope == null || !dataScope.getSearched()) {
dataScope = getDataScopeClient().getDataScopeByCode(code);
CacheUtil.put(SYS_CACHE, SCOPE_CACHE_CODE, code, dataScope);
}
return StringUtil.isNotBlank(dataScope.getResourceCode()) ? dataScope : null;
}
/**
* 获取部门子级
*
* @param deptId 部门id
* @return deptIds
*/
public static List<Long> getDeptAncestors(Long deptId) {
List ancestors = CacheUtil.get(SYS_CACHE, DEPT_CACHE_ANCESTORS, deptId, List.class);
if (CollectionUtil.isEmpty(ancestors)) {
ancestors = getDataScopeClient().getDeptAncestors(deptId);
CacheUtil.put(SYS_CACHE, DEPT_CACHE_ANCESTORS, deptId, ancestors);
}
return ancestors;
}
}

View File

@ -0,0 +1,42 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.config;
import lombok.AllArgsConstructor;
import org.springblade.core.datascope.handler.ScopeModelHandler;
import org.springblade.core.secure.config.RegistryConfiguration;
import org.springblade.system.handler.DataScopeModelHandler;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 公共封装包配置类
*
* @author Chill
*/
@Configuration
@AllArgsConstructor
@AutoConfigureBefore(RegistryConfiguration.class)
public class ScopeConfiguration {
@Bean
public ScopeModelHandler scopeModelHandler() {
return new DataScopeModelHandler();
}
}

View File

@ -0,0 +1,71 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.feign;
import org.springblade.core.datascope.model.DataScopeModel;
import org.springblade.core.launch.constant.AppConstant;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
/**
* 数据权限Feign接口类
*
* @author Chill
*/
@FeignClient(
value = AppConstant.APPLICATION_SYSTEM_NAME,
fallback = IDataScopeClientFallback.class
)
public interface IDataScopeClient {
String API_PREFIX = "/client/data-scope";
String GET_DATA_SCOPE_BY_MAPPER = API_PREFIX + "/by-mapper";
String GET_DATA_SCOPE_BY_CODE = API_PREFIX + "/by-code";
String GET_DEPT_ANCESTORS = API_PREFIX + "/dept-ancestors";
/**
* 获取数据权限
*
* @param mapperId 数据权限mapperId
* @param roleId 用户角色集合
* @return DataScopeModel
*/
@GetMapping(GET_DATA_SCOPE_BY_MAPPER)
DataScopeModel getDataScopeByMapper(@RequestParam("mapperId") String mapperId, @RequestParam("roleId") String roleId);
/**
* 获取数据权限
*
* @param code 数据权限资源编号
* @return DataScopeModel
*/
@GetMapping(GET_DATA_SCOPE_BY_CODE)
DataScopeModel getDataScopeByCode(@RequestParam("code") String code);
/**
* 获取部门子级
*
* @param deptId 部门id
* @return deptIds
*/
@GetMapping(GET_DEPT_ANCESTORS)
List<Long> getDeptAncestors(@RequestParam("deptId") Long deptId);
}

View File

@ -0,0 +1,44 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.feign;
import org.springblade.core.datascope.model.DataScopeModel;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* IDataScopeClientFallback
*
* @author Chill
*/
@Component
public class IDataScopeClientFallback implements IDataScopeClient {
@Override
public DataScopeModel getDataScopeByMapper(String mapperId, String roleId) {
return null;
}
@Override
public DataScopeModel getDataScopeByCode(String code) {
return null;
}
@Override
public List<Long> getDeptAncestors(Long deptId) {
return null;
}
}

View File

@ -0,0 +1,64 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.handler;
import org.springblade.core.datascope.handler.ScopeModelHandler;
import org.springblade.core.datascope.model.DataScopeModel;
import org.springblade.system.cache.DataScopeCache;
import java.util.List;
/**
* 通用数据权限规则
*
* @author Chill
*/
public class DataScopeModelHandler implements ScopeModelHandler {
/**
* 获取数据权限
*
* @param mapperId 数据权限mapperId
* @param roleId 用户角色集合
* @return DataScopeModel
*/
@Override
public DataScopeModel getDataScopeByMapper(String mapperId, String roleId) {
return DataScopeCache.getDataScopeByMapper(mapperId, roleId);
}
/**
* 获取数据权限
*
* @param code 数据权限资源编号
* @return DataScopeModel
*/
@Override
public DataScopeModel getDataScopeByCode(String code) {
return DataScopeCache.getDataScopeByCode(code);
}
/**
* 获取部门子级
*
* @param deptId 部门id
* @return deptIds
*/
@Override
public List<Long> getDeptAncestors(Long deptId) {
return DataScopeCache.getDeptAncestors(deptId);
}
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>blade-service-api</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -0,0 +1,97 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.BaseEntity;
/**
* 实体类
*
* @author BladeX
*/
@Data
@TableName("blade_scope_data")
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "DataScope对象", description = "DataScope对象")
public class DataScope extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ApiModelProperty(value = "主键")
@TableId(value = "id", type = IdType.ASSIGN_ID)
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/**
* 菜单主键
*/
@ApiModelProperty(value = "菜单主键")
private Long menuId;
/**
* 资源编号
*/
@ApiModelProperty(value = "资源编号")
private String resourceCode;
/**
* 数据权限名称
*/
@ApiModelProperty(value = "数据权限名称")
private String scopeName;
/**
* 数据权限可见字段
*/
@ApiModelProperty(value = "数据权限可见字段")
private String scopeField;
/**
* 数据权限类名
*/
@ApiModelProperty(value = "数据权限类名")
private String scopeClass;
/**
* 数据权限字段
*/
@ApiModelProperty(value = "数据权限字段")
private String scopeColumn;
/**
* 数据权限类型
*/
@ApiModelProperty(value = "数据权限类型")
private Integer scopeType;
/**
* 数据权限值域
*/
@ApiModelProperty(value = "数据权限值域")
private String scopeValue;
/**
* 数据权限备注
*/
@ApiModelProperty(value = "数据权限备注")
private String remark;
}

View File

@ -60,6 +60,12 @@ public class Dept implements Serializable {
@JsonSerialize(using = ToStringSerializer.class)
private Long parentId;
/**
* 祖级机构主键
*/
@ApiModelProperty(value = "祖级机构主键")
private String ancestors;
/**
* 部门名
*/

View File

@ -0,0 +1,64 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 实体类
*
* @author Chill
*/
@Data
@TableName("blade_role_scope")
@ApiModel(value = "RoleScope对象", description = "RoleScope对象")
public class RoleScope implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@JsonSerialize(using = ToStringSerializer.class)
@ApiModelProperty(value = "主键")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 权限id
*/
@JsonSerialize(using = ToStringSerializer.class)
@ApiModelProperty(value = "权限id")
private Long scopeId;
/**
* 角色id
*/
@JsonSerialize(using = ToStringSerializer.class)
@ApiModelProperty(value = "角色id")
private Long roleId;
}

View File

@ -0,0 +1,34 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.vo;
import lombok.Data;
import java.util.List;
/**
* CheckedTreeVO
*
* @author Chill
*/
@Data
public class CheckedTreeVO {
private List<String> menu;
private List<String> dataScope;
}

View File

@ -0,0 +1,38 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.vo;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.system.entity.DataScope;
/**
* 视图实体类
*
* @author Chill
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "DataScopeVO对象", description = "DataScopeVO对象")
public class DataScopeVO extends DataScope {
private static final long serialVersionUID = 1L;
/**
* 规则类型名
*/
private String scopeTypeName;
}

View File

@ -0,0 +1,36 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.vo;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* GrantTreeVO
*
* @author Chill
*/
@Data
public class GrantTreeVO implements Serializable {
private static final long serialVersionUID = 1L;
private List<MenuVO> menu;
private List<MenuVO> dataScope;
}

View File

@ -36,4 +36,7 @@ public class GrantVO implements Serializable {
@ApiModelProperty(value = "menuIds集合")
private List<Long> menuIds;
@ApiModelProperty(value = "dataScopeIds集合")
private List<Long> dataScopeIds;
}

View File

@ -56,6 +56,12 @@ public class MenuVO extends Menu implements INode {
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<INode> children;
/**
* 是否有子孙节点
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private Boolean hasChildren;
@Override
public List<INode> getChildren() {
if (this.children == null) {

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>blade-service-api</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,13 +5,13 @@
<parent>
<artifactId>SpringBlade</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>blade-service-api</artifactId>
<name>${project.artifactId}</name>
<version>3.1.0</version>
<version>3.2.0</version>
<packaging>pom</packaging>
<description>SpringBlade 微服务API集合</description>
@ -20,6 +20,7 @@
<module>blade-dict-api</module>
<module>blade-system-api</module>
<module>blade-user-api</module>
<module>blade-scope-api</module>
<module>blade-demo-api</module>
</modules>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>blade-service</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>org.springblade</groupId>
<artifactId>blade-service</artifactId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -22,7 +22,7 @@ public class BladeDemoTest {
@Test
public void contextLoads() {
int count = noticeService.count();
Long count = noticeService.count();
System.out.println("notice数量[" + count + "] 个");
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>blade-service</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>blade-service</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -0,0 +1,120 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.CacheUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.entity.DataScope;
import org.springblade.system.service.IDataScopeService;
import org.springblade.system.vo.DataScopeVO;
import org.springblade.system.wrapper.DataScopeWrapper;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import static org.springblade.core.tool.utils.CacheUtil.SYS_CACHE;
/**
* 数据权限控制器
*
* @author BladeX
*/
@RestController
@AllArgsConstructor
@RequestMapping("/data-scope")
@Api(value = "数据权限", tags = "数据权限")
public class DataScopeController extends BladeController {
private final IDataScopeService dataScopeService;
/**
* 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@ApiOperation(value = "详情", notes = "传入dataScope")
public R<DataScope> detail(DataScope dataScope) {
DataScope detail = dataScopeService.getOne(Condition.getQueryWrapper(dataScope));
return R.data(detail);
}
/**
* 分页
*/
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@ApiOperation(value = "分页", notes = "传入dataScope")
public R<IPage<DataScopeVO>> list(DataScope dataScope, Query query) {
IPage<DataScope> pages = dataScopeService.page(Condition.getPage(query), Condition.getQueryWrapper(dataScope));
return R.data(DataScopeWrapper.build().pageVO(pages));
}
/**
* 新增
*/
@PostMapping("/save")
@ApiOperationSupport(order = 3)
@ApiOperation(value = "新增", notes = "传入dataScope")
public R save(@Valid @RequestBody DataScope dataScope) {
CacheUtil.clear(SYS_CACHE);
return R.status(dataScopeService.save(dataScope));
}
/**
* 修改
*/
@PostMapping("/update")
@ApiOperationSupport(order = 4)
@ApiOperation(value = "修改", notes = "传入dataScope")
public R update(@Valid @RequestBody DataScope dataScope) {
CacheUtil.clear(SYS_CACHE);
return R.status(dataScopeService.updateById(dataScope));
}
/**
* 新增或修改
*/
@PostMapping("/submit")
@ApiOperationSupport(order = 5)
@ApiOperation(value = "新增或修改", notes = "传入dataScope")
public R submit(@Valid @RequestBody DataScope dataScope) {
CacheUtil.clear(SYS_CACHE);
return R.status(dataScopeService.saveOrUpdate(dataScope));
}
/**
* 删除
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 6)
@ApiOperation(value = "逻辑删除", notes = "传入ids")
public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
CacheUtil.clear(SYS_CACHE);
return R.status(dataScopeService.deleteLogic(Func.toLongList(ids)));
}
}

View File

@ -96,11 +96,8 @@ public class DeptController extends BladeController {
@PostMapping("/submit")
@ApiOperationSupport(order = 4)
@ApiOperation(value = "新增或修改", notes = "传入dept")
public R submit(@Valid @RequestBody Dept dept, BladeUser user) {
if (Func.isEmpty(dept.getId())) {
dept.setTenantId(user.getTenantId());
}
return R.status(deptService.saveOrUpdate(dept));
public R submit(@Valid @RequestBody Dept dept) {
return R.status(deptService.submit(dept));
}
/**

View File

@ -28,6 +28,8 @@ import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.entity.Menu;
import org.springblade.system.service.IMenuService;
import org.springblade.system.vo.CheckedTreeVO;
import org.springblade.system.vo.GrantTreeVO;
import org.springblade.system.vo.MenuVO;
import org.springblade.system.wrapper.MenuWrapper;
import org.springframework.web.bind.annotation.*;
@ -74,17 +76,48 @@ public class MenuController extends BladeController {
@ApiOperationSupport(order = 2)
@ApiOperation(value = "列表", notes = "传入menu")
public R<List<MenuVO>> list(@ApiIgnore @RequestParam Map<String, Object> menu) {
@SuppressWarnings("unchecked")
List<Menu> list = menuService.list(Condition.getQueryWrapper(menu, Menu.class).lambda().orderByAsc(Menu::getSort));
return R.data(MenuWrapper.build().listNodeVO(list));
}
/**
* 菜单列表
*/
@GetMapping("/menu-list")
@ApiImplicitParams({
@ApiImplicitParam(name = "code", value = "菜单编号", paramType = "query", dataType = "string"),
@ApiImplicitParam(name = "name", value = "菜单名称", paramType = "query", dataType = "string")
})
@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
@ApiOperationSupport(order = 3)
@ApiOperation(value = "菜单列表", notes = "传入menu")
public R<List<MenuVO>> menuList(@ApiIgnore @RequestParam Map<String, Object> menu) {
List<Menu> list = menuService.list(Condition.getQueryWrapper(menu, Menu.class).lambda().eq(Menu::getCategory, 1).orderByAsc(Menu::getSort));
return R.data(MenuWrapper.build().listNodeVO(list));
}
/**
* 懒加载菜单列表
*/
@GetMapping("/lazy-menu-list")
@ApiImplicitParams({
@ApiImplicitParam(name = "code", value = "菜单编号", paramType = "query", dataType = "string"),
@ApiImplicitParam(name = "name", value = "菜单名称", paramType = "query", dataType = "string")
})
@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
@ApiOperationSupport(order = 4)
@ApiOperation(value = "懒加载菜单列表", notes = "传入menu")
public R<List<MenuVO>> lazyMenuList(Long parentId, @ApiIgnore @RequestParam Map<String, Object> menu) {
List<MenuVO> list = menuService.lazyMenuList(parentId, menu);
return R.data(MenuWrapper.build().listNodeLazyVO(list));
}
/**
* 新增或修改
*/
@PostMapping("/submit")
@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
@ApiOperationSupport(order = 3)
@ApiOperationSupport(order = 5)
@ApiOperation(value = "新增或修改", notes = "传入menu")
public R submit(@Valid @RequestBody Menu menu) {
return R.status(menuService.saveOrUpdate(menu));
@ -96,7 +129,7 @@ public class MenuController extends BladeController {
*/
@PostMapping("/remove")
@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
@ApiOperationSupport(order = 4)
@ApiOperationSupport(order = 6)
@ApiOperation(value = "删除", notes = "传入ids")
public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
return R.status(menuService.removeByIds(Func.toLongList(ids)));
@ -106,7 +139,7 @@ public class MenuController extends BladeController {
* 前端菜单数据
*/
@GetMapping("/routes")
@ApiOperationSupport(order = 5)
@ApiOperationSupport(order = 7)
@ApiOperation(value = "前端菜单数据", notes = "前端菜单数据")
public R<List<MenuVO>> routes(BladeUser user) {
List<MenuVO> list = menuService.routes((user == null || user.getUserId() == 0L) ? null : user.getRoleId());
@ -117,7 +150,7 @@ public class MenuController extends BladeController {
* 前端按钮数据
*/
@GetMapping("/buttons")
@ApiOperationSupport(order = 6)
@ApiOperationSupport(order = 8)
@ApiOperation(value = "前端按钮数据", notes = "前端按钮数据")
public R<List<MenuVO>> buttons(BladeUser user) {
List<MenuVO> list = menuService.buttons(user.getRoleId());
@ -128,7 +161,7 @@ public class MenuController extends BladeController {
* 获取菜单树形结构
*/
@GetMapping("/tree")
@ApiOperationSupport(order = 7)
@ApiOperationSupport(order = 9)
@ApiOperation(value = "树形结构", notes = "树形结构")
public R<List<MenuVO>> tree() {
List<MenuVO> tree = menuService.tree();
@ -139,27 +172,33 @@ public class MenuController extends BladeController {
* 获取权限分配树形结构
*/
@GetMapping("/grant-tree")
@ApiOperationSupport(order = 8)
@ApiOperationSupport(order = 10)
@ApiOperation(value = "权限分配树形结构", notes = "权限分配树形结构")
public R<List<MenuVO>> grantTree(BladeUser user) {
return R.data(menuService.grantTree(user));
public R<GrantTreeVO> grantTree(BladeUser user) {
GrantTreeVO vo = new GrantTreeVO();
vo.setMenu(menuService.grantTree(user));
vo.setDataScope(menuService.grantDataScopeTree(user));
return R.data(vo);
}
/**
* 获取权限分配树形结构
*/
@GetMapping("/role-tree-keys")
@ApiOperationSupport(order = 9)
@ApiOperationSupport(order = 11)
@ApiOperation(value = "角色所分配的树", notes = "角色所分配的树")
public R<List<String>> roleTreeKeys(String roleIds) {
return R.data(menuService.roleTreeKeys(roleIds));
public R<CheckedTreeVO> roleTreeKeys(String roleIds) {
CheckedTreeVO vo = new CheckedTreeVO();
vo.setMenu(menuService.roleTreeKeys(roleIds));
vo.setDataScope(menuService.dataScopeTreeKeys(roleIds));
return R.data(vo);
}
/**
* 获取配置的角色权限
*/
@GetMapping("auth-routes")
@ApiOperationSupport(order = 10)
@ApiOperationSupport(order = 12)
@ApiOperation(value = "菜单的角色权限")
public R<List<Kv>> authRoutes(BladeUser user) {
if (Func.isEmpty(user) || user.getUserId() == 0L) {

View File

@ -25,6 +25,7 @@ import org.springblade.core.secure.BladeUser;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.node.INode;
import org.springblade.core.tool.utils.CacheUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.entity.Role;
import org.springblade.system.service.IRoleService;
@ -38,6 +39,8 @@ import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import static org.springblade.core.tool.utils.CacheUtil.SYS_CACHE;
/**
* 控制器
*
@ -89,27 +92,41 @@ public class RoleController extends BladeController {
return R.data(tree);
}
/**
* 获取指定角色树形结构
*/
@GetMapping("/tree-by-id")
@ApiOperationSupport(order = 4)
@ApiOperation(value = "树形结构", notes = "树形结构")
public R<List<RoleVO>> treeById(Long roleId, BladeUser bladeUser) {
Role role = roleService.getById(roleId);
List<RoleVO> tree = roleService.tree(Func.notNull(role) ? role.getTenantId() : bladeUser.getTenantId());
return R.data(tree);
}
/**
* 新增或修改
*/
@PostMapping("/submit")
@ApiOperationSupport(order = 4)
@ApiOperationSupport(order = 5)
@ApiOperation(value = "新增或修改", notes = "传入role")
public R submit(@Valid @RequestBody Role role, BladeUser user) {
CacheUtil.clear(SYS_CACHE);
if (Func.isEmpty(role.getId())) {
role.setTenantId(user.getTenantId());
}
return R.status(roleService.saveOrUpdate(role));
}
/**
* 删除
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 5)
@ApiOperationSupport(order = 6)
@ApiOperation(value = "删除", notes = "传入ids")
public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
CacheUtil.clear(SYS_CACHE);
return R.status(roleService.removeByIds(Func.toLongList(ids)));
}
@ -117,11 +134,11 @@ public class RoleController extends BladeController {
* 设置菜单权限
*/
@PostMapping("/grant")
@ApiOperationSupport(order = 6)
@ApiOperationSupport(order = 7)
@ApiOperation(value = "权限设置", notes = "传入roleId集合以及menuId集合")
public R grant(@RequestBody GrantVO grantVO) {
boolean temp = roleService.grant(grantVO.getRoleIds(), grantVO.getMenuIds());
CacheUtil.clear(SYS_CACHE);
boolean temp = roleService.grant(grantVO.getRoleIds(), grantVO.getMenuIds(), grantVO.getDataScopeIds());
return R.status(temp);
}
}

View File

@ -0,0 +1,106 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.feign;
import lombok.RequiredArgsConstructor;
import org.springblade.core.datascope.constant.DataScopeConstant;
import org.springblade.core.datascope.model.DataScopeModel;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.Func;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 数据权限Feign实现类
*
* @author Chill
*/
@ApiIgnore
@RestController
@RequiredArgsConstructor
public class DataScopeClient implements IDataScopeClient {
private static final DataScopeModel SEARCHED_DATA_SCOPE_MODEL = new DataScopeModel(Boolean.TRUE);
private final JdbcTemplate jdbcTemplate;
/**
* 获取数据权限
*
* @param mapperId 数据权限mapperId
* @param roleId 用户角色集合
* @return DataScopeModel
*/
@Override
@GetMapping(GET_DATA_SCOPE_BY_MAPPER)
public DataScopeModel getDataScopeByMapper(String mapperId, String roleId) {
List<Object> args = new ArrayList<>(Collections.singletonList(mapperId));
List<Long> roleIds = Func.toLongList(roleId);
args.addAll(roleIds);
// 增加searched字段防止未配置的参数重复读库导致缓存击穿
// 后续若有新增配置则会清空缓存重新加载
DataScopeModel dataScope;
List<DataScopeModel> list = jdbcTemplate.query(DataScopeConstant.dataByMapper(roleIds.size()), args.toArray(), new BeanPropertyRowMapper<>(DataScopeModel.class));
if (CollectionUtil.isNotEmpty(list)) {
dataScope = list.iterator().next();
dataScope.setSearched(Boolean.TRUE);
} else {
dataScope = SEARCHED_DATA_SCOPE_MODEL;
}
return dataScope;
}
/**
* 获取数据权限
*
* @param code 数据权限资源编号
* @return DataScopeModel
*/
@Override
@GetMapping(GET_DATA_SCOPE_BY_CODE)
public DataScopeModel getDataScopeByCode(String code) {
// 增加searched字段防止未配置的参数重复读库导致缓存击穿
// 后续若有新增配置则会清空缓存重新加载
DataScopeModel dataScope;
List<DataScopeModel> list = jdbcTemplate.query(DataScopeConstant.DATA_BY_CODE, new Object[]{code}, new BeanPropertyRowMapper<>(DataScopeModel.class));
if (CollectionUtil.isNotEmpty(list)) {
dataScope = list.iterator().next();
dataScope.setSearched(Boolean.TRUE);
} else {
dataScope = SEARCHED_DATA_SCOPE_MODEL;
}
return dataScope;
}
/**
* 获取部门子级
*
* @param deptId 部门id
* @return deptIds
*/
@Override
@GetMapping(GET_DEPT_ANCESTORS)
public List<Long> getDeptAncestors(Long deptId) {
return jdbcTemplate.queryForList(DataScopeConstant.DATA_BY_DEPT, new Object[]{deptId}, Long.class);
}
}

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.system.entity.DataScope;
/**
* Mapper 接口
*
* @author BladeX
*/
public interface DataScopeMapper extends BaseMapper<DataScope> {
}

View File

@ -0,0 +1,5 @@
<?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="org.springblade.system.mapper.DataScopeMapper">
</mapper>

View File

@ -22,6 +22,7 @@ import org.springblade.system.entity.Menu;
import org.springblade.system.vo.MenuVO;
import java.util.List;
import java.util.Map;
/**
* Mapper 接口
@ -39,6 +40,15 @@ public interface MenuMapper extends BaseMapper<Menu> {
*/
List<MenuVO> selectMenuPage(IPage page, MenuVO menu);
/**
* 懒加载菜单列表
*
* @param parentId
* @param param
* @return
*/
List<MenuVO> lazyMenuList(Long parentId, Map<String, Object> param);
/**
* 树形结构
*
@ -61,6 +71,21 @@ public interface MenuMapper extends BaseMapper<Menu> {
*/
List<MenuVO> grantTreeByRole(List<Long> roleId);
/**
* 数据权限授权树形结构
*
* @return
*/
List<MenuVO> grantDataScopeTree();
/**
* 数据权限授权树形结构
*
* @param roleId
* @return
*/
List<MenuVO> grantDataScopeTreeByRole(List<Long> roleId);
/**
* 所有菜单
*

View File

@ -19,6 +19,23 @@
<result column="is_deleted" property="isDeleted"/>
</resultMap>
<resultMap id="menuVOResultMap" type="org.springblade.system.vo.MenuVO">
<id column="id" property="id"/>
<result column="code" property="code"/>
<result column="parent_id" property="parentId"/>
<result column="name" property="name"/>
<result column="alias" property="alias"/>
<result column="path" property="path"/>
<result column="source" property="source"/>
<result column="sort" property="sort"/>
<result column="category" property="category"/>
<result column="action" property="action"/>
<result column="is_open" property="isOpen"/>
<result column="remark" property="remark"/>
<result column="is_deleted" property="isDeleted"/>
<result column="has_children" property="hasChildren"/>
</resultMap>
<resultMap id="treeNodeResultMap" type="org.springblade.core.tool.node.TreeNode">
<id column="id" property="id"/>
<result column="parent_id" property="parentId"/>
@ -37,6 +54,35 @@
select * from blade_menu where is_deleted = 0
</select>
<select id="lazyMenuList" resultMap="menuVOResultMap">
SELECT
menu.*,
(
SELECT
CASE WHEN count( 1 ) > 0 THEN 1 ELSE 0 END
FROM
blade_menu
WHERE
parent_id = menu.id AND is_deleted = 0 AND category = 1
) AS "has_children"
FROM
blade_menu menu
WHERE menu.is_deleted = 0 AND menu.category = 1
<if test="param1!=null">
and menu.parent_id = #{param1}
</if>
<if test="param2.name!=null and param2.name!=''">
and menu.name like concat(concat('%', #{param2.name}),'%')
</if>
<if test="param2.code!=null and param2.code!=''">
and menu.code like concat(concat('%', #{param2.code}),'%')
</if>
<if test="param2.alias!=null and param2.alias!=''">
and menu.alias like concat(concat('%', #{param2.alias}),'%')
</if>
ORDER BY menu.sort
</select>
<select id="tree" resultMap="treeNodeResultMap">
select id, parent_id, name as title, id as 'value', id as 'key' from blade_menu where is_deleted = 0 and category = 1
</select>
@ -127,6 +173,104 @@
)
</select>
<select id="grantDataScopeTree" resultMap="treeNodeResultMap">
SELECT
*
FROM
(
SELECT
id,
parent_id,
NAME AS title,
id AS "value",
id AS "key"
FROM
blade_menu
WHERE
category = 1
AND is_deleted = 0
AND id IN ( SELECT menu_id FROM blade_scope_data WHERE is_deleted = 0 AND menu_id IS NOT NULL )
) menu
UNION ALL
SELECT
id,
menu_id AS parent_id,
scope_name AS title,
id AS "value",
id AS "key"
FROM
blade_scope_data
WHERE
is_deleted = 0
AND menu_id IS NOT NULL
</select>
<select id="grantDataScopeTreeByRole" resultMap="treeNodeResultMap">
SELECT
*
FROM
(
SELECT
id,
parent_id,
NAME AS title,
id AS "value",
id AS "key"
FROM
blade_menu
WHERE
category = 1
AND is_deleted = 0
AND id IN ( SELECT menu_id FROM blade_scope_data WHERE is_deleted = 0 AND menu_id IS NOT NULL )
AND (
id IN (
select menu_id from blade_role_menu where role_id in
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
)
OR id IN (
select parent_id from blade_menu where is_deleted = 0
and id in ( select menu_id from blade_role_menu where role_id in
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach> )
)
)
) menu
UNION ALL
SELECT
id,
menu_id AS parent_id,
scope_name AS title,
id AS "value",
id AS "key"
FROM
blade_scope_data
WHERE
is_deleted = 0
AND (
menu_id IN (
select menu_id from blade_role_menu where role_id in
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
)
OR menu_id IN (
select parent_id from blade_menu where is_deleted = 0
and id in ( select menu_id from blade_role_menu where role_id in
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach> )
)
)
AND menu_id IS NOT NULL
</select>
<select id="authRoutes" resultType="org.springblade.system.dto.MenuDTO">
SELECT
GROUP_CONCAT(r.role_alias) as alias,

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.system.entity.RoleScope;
/**
* Mapper 接口
*
* @author Chill
*/
public interface RoleScopeMapper extends BaseMapper<RoleScope> {
}

View File

@ -0,0 +1,12 @@
<?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="org.springblade.system.mapper.RoleScopeMapper">
<!-- 通用查询映射结果 -->
<resultMap id="roleMenuResultMap" type="org.springblade.system.entity.RoleScope">
<id column="id" property="id"/>
<result column="scope_id" property="scopeId"/>
<result column="role_id" property="roleId"/>
</resultMap>
</mapper>

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.service;
import org.springblade.core.mp.base.BaseService;
import org.springblade.system.entity.DataScope;
/**
* 服务类
*
* @author BladeX
*/
public interface IDataScopeService extends BaseService<DataScope> {
}

View File

@ -63,4 +63,12 @@ public interface IDeptService extends IService<Dept> {
*/
List<String> getDeptNames(String deptIds);
/**
* 提交
*
* @param dept
* @return
*/
boolean submit(Dept dept);
}

View File

@ -23,6 +23,7 @@ import org.springblade.system.entity.Menu;
import org.springblade.system.vo.MenuVO;
import java.util.List;
import java.util.Map;
/**
* 服务类
@ -40,6 +41,15 @@ public interface IMenuService extends IService<Menu> {
*/
IPage<MenuVO> selectMenuPage(IPage<MenuVO> page, MenuVO menu);
/**
* 懒加载菜单列表
*
* @param parentId
* @param param
* @return
*/
List<MenuVO> lazyMenuList(Long parentId, Map<String, Object> param);
/**
* 菜单树形结构
*
@ -71,6 +81,14 @@ public interface IMenuService extends IService<Menu> {
*/
List<MenuVO> grantTree(BladeUser user);
/**
* 数据权限授权树形结构
*
* @param user
* @return
*/
List<MenuVO> grantDataScopeTree(BladeUser user);
/**
* 默认选中节点
*
@ -79,6 +97,14 @@ public interface IMenuService extends IService<Menu> {
*/
List<String> roleTreeKeys(String roleIds);
/**
* 默认选中节点
*
* @param roleIds
* @return
*/
List<String> dataScopeTreeKeys(String roleIds);
/**
* 获取配置的角色权限
*

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springblade.system.entity.RoleScope;
/**
* 服务类
*
* @author Chill
*/
public interface IRoleScopeService extends IService<RoleScope> {
}

View File

@ -54,7 +54,7 @@ public interface IRoleService extends IService<Role> {
* @param menuIds 菜单id集合
* @return 是否成功
*/
boolean grant(@NotEmpty List<Long> roleIds, @NotEmpty List<Long> menuIds);
boolean grant(@NotEmpty List<Long> roleIds, @NotEmpty List<Long> menuIds, List<Long> dataScopeIds);
/**
* 获取角色ID

View File

@ -0,0 +1,32 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.service.impl;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.system.entity.DataScope;
import org.springblade.system.mapper.DataScopeMapper;
import org.springblade.system.service.IDataScopeService;
import org.springframework.stereotype.Service;
/**
* 服务实现类
*
* @author BladeX
*/
@Service
public class DataScopeServiceImpl extends BaseServiceImpl<DataScopeMapper, DataScope> implements IDataScopeService {
}

View File

@ -18,8 +18,13 @@ package org.springblade.system.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.utils.SecureUtil;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.node.ForestNodeMerger;
import org.springblade.core.tool.utils.CacheUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.system.entity.Dept;
import org.springblade.system.mapper.DeptMapper;
import org.springblade.system.service.IDeptService;
@ -61,4 +66,25 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
return baseMapper.getDeptNames(Func.toLongArray(deptIds));
}
@Override
public boolean submit(Dept dept) {
CacheUtil.clear(CacheUtil.SYS_CACHE);
if (Func.isEmpty(dept.getParentId())) {
dept.setTenantId(SecureUtil.getTenantId());
dept.setParentId(BladeConstant.TOP_PARENT_ID);
dept.setAncestors(String.valueOf(BladeConstant.TOP_PARENT_ID));
}
if (dept.getParentId() > 0) {
Dept parent = getById(dept.getParentId());
if (Func.toLong(dept.getParentId()) == Func.toLong(dept.getId())) {
throw new ServiceException("父节点不可选择自身!");
}
dept.setTenantId(parent.getTenantId());
String ancestors = parent.getAncestors() + StringPool.COMMA + dept.getParentId();
dept.setAncestors(ancestors);
}
dept.setIsDeleted(BladeConstant.DB_NOT_DELETED);
return saveOrUpdate(dept);
}
}

View File

@ -70,7 +70,7 @@ public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements ID
@CacheEvict(cacheNames = {DICT_LIST, DICT_VALUE}, allEntries = true)
public boolean submit(Dict dict) {
LambdaQueryWrapper<Dict> lqw = Wrappers.<Dict>query().lambda().eq(Dict::getCode, dict.getCode()).eq(Dict::getDictKey, dict.getDictKey());
Integer cnt = baseMapper.selectCount((Func.isEmpty(dict.getId())) ? lqw : lqw.notIn(Dict::getId, dict.getId()));
Long cnt = baseMapper.selectCount((Func.isEmpty(dict.getId())) ? lqw : lqw.notIn(Dict::getId, dict.getId()));
if (cnt > 0) {
throw new ServiceException("当前字典键值已存在!");
}

View File

@ -28,9 +28,11 @@ import org.springblade.core.tool.utils.StringUtil;
import org.springblade.system.dto.MenuDTO;
import org.springblade.system.entity.Menu;
import org.springblade.system.entity.RoleMenu;
import org.springblade.system.entity.RoleScope;
import org.springblade.system.mapper.MenuMapper;
import org.springblade.system.service.IMenuService;
import org.springblade.system.service.IRoleMenuService;
import org.springblade.system.service.IRoleScopeService;
import org.springblade.system.vo.MenuVO;
import org.springblade.system.wrapper.MenuWrapper;
import org.springframework.stereotype.Service;
@ -47,13 +49,23 @@ import java.util.stream.Collectors;
@AllArgsConstructor
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {
IRoleMenuService roleMenuService;
private final IRoleMenuService roleMenuService;
private final IRoleScopeService roleScopeService;
private final static String PARENT_ID = "parentId";
@Override
public IPage<MenuVO> selectMenuPage(IPage<MenuVO> page, MenuVO menu) {
return page.setRecords(baseMapper.selectMenuPage(page, menu));
}
@Override
public List<MenuVO> lazyMenuList(Long parentId, Map<String, Object> param) {
if (Func.isEmpty(Func.toStr(param.get(PARENT_ID)))) {
parentId = null;
}
return baseMapper.lazyMenuList(parentId, param);
}
@Override
public List<MenuVO> routes(String roleId) {
if (StringUtil.isBlank(roleId)) {
@ -94,12 +106,23 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IM
return ForestNodeMerger.merge(user.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID) ? baseMapper.grantTree() : baseMapper.grantTreeByRole(Func.toLongList(user.getRoleId())));
}
@Override
public List<MenuVO> grantDataScopeTree(BladeUser user) {
return ForestNodeMerger.merge(user.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID) ? baseMapper.grantDataScopeTree() : baseMapper.grantDataScopeTreeByRole(Func.toLongList(user.getRoleId())));
}
@Override
public List<String> roleTreeKeys(String roleIds) {
List<RoleMenu> roleMenus = roleMenuService.list(Wrappers.<RoleMenu>query().lambda().in(RoleMenu::getRoleId, Func.toLongList(roleIds)));
return roleMenus.stream().map(roleMenu -> Func.toStr(roleMenu.getMenuId())).collect(Collectors.toList());
}
@Override
public List<String> dataScopeTreeKeys(String roleIds) {
List<RoleScope> roleScopes = roleScopeService.list(Wrappers.<RoleScope>query().lambda().in(RoleScope::getRoleId, Func.toLongList(roleIds)));
return roleScopes.stream().map(roleScope -> Func.toStr(roleScope.getScopeId())).collect(Collectors.toList());
}
@Override
public List<Kv> authRoutes(BladeUser user) {
if (Func.isEmpty(user)) {

View File

@ -44,7 +44,7 @@ public class RegionServiceImpl extends ServiceImpl<RegionMapper, Region> impleme
@Override
public boolean submit(Region region) {
Integer cnt = baseMapper.selectCount(Wrappers.<Region>query().lambda().eq(Region::getCode, region.getCode()));
Long cnt = baseMapper.selectCount(Wrappers.<Region>query().lambda().eq(Region::getCode, region.getCode()));
if (cnt > 0) {
return this.updateById(region);
}
@ -79,7 +79,7 @@ public class RegionServiceImpl extends ServiceImpl<RegionMapper, Region> impleme
@Override
public boolean removeRegion(String id) {
Integer cnt = baseMapper.selectCount(Wrappers.<Region>query().lambda().eq(Region::getParentCode, id));
Long cnt = baseMapper.selectCount(Wrappers.<Region>query().lambda().eq(Region::getParentCode, id));
if (cnt > 0) {
throw new ServiceException("请先删除子节点!");
}

View File

@ -0,0 +1,32 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springblade.system.entity.RoleScope;
import org.springblade.system.mapper.RoleScopeMapper;
import org.springblade.system.service.IRoleScopeService;
import org.springframework.stereotype.Service;
/**
* 服务实现类
*
* @author Chill
*/
@Service
public class RoleScopeServiceImpl extends ServiceImpl<RoleScopeMapper, RoleScope> implements IRoleScopeService {
}

View File

@ -26,8 +26,10 @@ import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.entity.Role;
import org.springblade.system.entity.RoleMenu;
import org.springblade.system.entity.RoleScope;
import org.springblade.system.mapper.RoleMapper;
import org.springblade.system.service.IRoleMenuService;
import org.springblade.system.service.IRoleScopeService;
import org.springblade.system.service.IRoleService;
import org.springblade.system.vo.RoleVO;
import org.springframework.stereotype.Service;
@ -48,7 +50,8 @@ import java.util.stream.Collectors;
@AllArgsConstructor
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {
IRoleMenuService roleMenuService;
private final IRoleMenuService roleMenuService;
private final IRoleScopeService roleScopeService;
@Override
public IPage<RoleVO> selectRolePage(IPage<RoleVO> page, RoleVO role) {
@ -66,7 +69,7 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IR
}
@Override
public boolean grant(@NotEmpty List<Long> roleIds, @NotEmpty List<Long> menuIds) {
public boolean grant(@NotEmpty List<Long> roleIds, @NotEmpty List<Long> menuIds, List<Long> dataScopeIds) {
// 删除角色配置的菜单集合
roleMenuService.remove(Wrappers.<RoleMenu>update().lambda().in(RoleMenu::getRoleId, roleIds));
// 组装配置
@ -78,7 +81,22 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IR
roleMenus.add(roleMenu);
}));
// 新增配置
return roleMenuService.saveBatch(roleMenus);
roleMenuService.saveBatch(roleMenus);
// 删除角色配置的数据权限集合
roleScopeService.remove(Wrappers.<RoleScope>update().lambda().in(RoleScope::getRoleId, roleIds));
// 组装配置
List<RoleScope> roleDataScopes = new ArrayList<>();
roleIds.forEach(roleId -> dataScopeIds.forEach(scopeId -> {
RoleScope roleScope = new RoleScope();
roleScope.setRoleId(roleId);
roleScope.setScopeId(scopeId);
roleDataScopes.add(roleScope);
}));
// 新增配置
roleScopeService.saveBatch(roleDataScopes);
return true;
}
@Override

View File

@ -0,0 +1,53 @@
/**
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springblade.system.wrapper;
import org.springblade.core.mp.support.BaseEntityWrapper;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.system.entity.DataScope;
import org.springblade.system.service.IDictService;
import org.springblade.system.vo.DataScopeVO;
import java.util.Objects;
/**
* 包装类,返回视图层所需的字段
*
* @author Chill
*/
public class DataScopeWrapper extends BaseEntityWrapper<DataScope, DataScopeVO> {
private static IDictService dictService;
static {
dictService = SpringUtil.getBean(IDictService.class);
}
public static DataScopeWrapper build() {
return new DataScopeWrapper();
}
@Override
public DataScopeVO entityVO(DataScope dataScope) {
DataScopeVO dataScopeVO = Objects.requireNonNull(BeanUtil.copy(dataScope, DataScopeVO.class));
String scopeTypeName = dictService.getValue("data_scope_type", dataScope.getScopeType());
dataScopeVO.setScopeTypeName(scopeTypeName);
return dataScopeVO;
}
}

View File

@ -80,4 +80,8 @@ public class MenuWrapper extends BaseEntityWrapper<Menu, MenuVO> {
return ForestNodeMerger.merge(collect);
}
public List<MenuVO> listNodeLazyVO(List<MenuVO> list) {
return ForestNodeMerger.merge(list);
}
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>blade-service</artifactId>
<groupId>org.springblade</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -60,7 +60,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
if (Func.isNotEmpty(user.getPassword())) {
user.setPassword(DigestUtil.encrypt(user.getPassword()));
}
Integer cnt = baseMapper.selectCount(Wrappers.<User>query().lambda().eq(User::getTenantId, user.getTenantId()).eq(User::getAccount, user.getAccount()));
Long cnt = baseMapper.selectCount(Wrappers.<User>query().lambda().eq(User::getTenantId, user.getTenantId()).eq(User::getAccount, user.getAccount()));
if (cnt > 0) {
throw new ServiceException("当前用户已存在!");
}

View File

@ -7,12 +7,12 @@
<parent>
<groupId>org.springblade</groupId>
<artifactId>SpringBlade</artifactId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<artifactId>blade-service</artifactId>
<name>${project.artifactId}</name>
<version>3.1.0</version>
<version>3.2.0</version>
<packaging>pom</packaging>
<description>SpringBlade 微服务集合</description>
@ -30,6 +30,11 @@
<artifactId>blade-common</artifactId>
<version>${blade.project.version}</version>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-scope-api</artifactId>
<version>${blade.project.version}</version>
</dependency>
</dependencies>
<build>

View File

@ -10,10 +10,10 @@ blade:
datasource:
demo:
master:
url: jdbc:mysql://localhost:3306/bladex?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
url: jdbc:mysql://localhost:3306/blade?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
username: root
password: root
slave:
url: jdbc:mysql://localhost:3306/bladex_slave?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
url: jdbc:mysql://localhost:3306/blade_slave?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
username: root
password: root

View File

@ -69,7 +69,7 @@ knife4j:
swagger:
title: SpringBlade 接口文档系统
description: SpringBlade 接口文档系统
version: 3.1.0
version: 3.2.0
license: Powered By SpringBlade
licenseUrl: https://bladex.vip
terms-of-service-url: https://bladex.vip

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,115 @@
-- ----------------------------
-- 创建数据权限表
-- ----------------------------
CREATE TABLE `blade_scope_data` (
`id` bigint(20) NOT NULL COMMENT '主键',
`menu_id` bigint(20) NULL DEFAULT NULL COMMENT '菜单主键',
`resource_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '资源编号',
`scope_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '数据权限名称',
`scope_field` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '数据权限字段',
`scope_class` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '数据权限类名',
`scope_column` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '数据权限字段',
`scope_type` int(2) NULL DEFAULT NULL COMMENT '数据权限类型',
`scope_value` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '数据权限值域',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '数据权限备注',
`create_user` bigint(20) NULL DEFAULT NULL COMMENT '创建人',
`create_dept` bigint(20) NULL DEFAULT NULL COMMENT '创建部门',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`update_user` bigint(20) NULL DEFAULT NULL COMMENT '修改人',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
`status` int(2) NULL DEFAULT NULL COMMENT '状态',
`is_deleted` int(2) NULL DEFAULT NULL COMMENT '是否已删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据权限表';
-- ----------------------------
-- 创建数据权限角色表
-- ----------------------------
DROP TABLE IF EXISTS `blade_role_scope`;
CREATE TABLE `blade_role_scope` (
`id` bigint(20) NOT NULL COMMENT '主键',
`scope_id` bigint(20) NULL DEFAULT NULL COMMENT '数据权限id',
`role_id` bigint(20) NULL DEFAULT NULL COMMENT '角色id',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;
SET FOREIGN_KEY_CHECKS = 1;
-- ----------------------------
-- 部门表增加字段
-- ----------------------------
ALTER TABLE `blade_dept`
ADD COLUMN `ancestors` varchar(2000) NULL COMMENT '祖级列表' AFTER `parent_id`;
UPDATE `blade_dept` SET `tenant_id` = '000000', `parent_id` = 0, `ancestors` = '0', `dept_name` = '刀锋科技', `full_name` = '江苏刀锋科技有限公司', `sort` = 1, `remark` = NULL, `is_deleted` = 0 WHERE `id` = 1123598813738675201;
UPDATE `blade_dept` SET `tenant_id` = '000000', `parent_id` = 1123598813738675201, `ancestors` = '0,1123598813738675201', `dept_name` = '常州刀锋', `full_name` = '常州刀锋科技有限公司', `sort` = 1, `remark` = NULL, `is_deleted` = 0 WHERE `id` = 1123598813738675202;
UPDATE `blade_dept` SET `tenant_id` = '000000', `parent_id` = 1123598813738675201, `ancestors` = '0,1123598813738675201', `dept_name` = '苏州刀锋', `full_name` = '苏州刀锋科技有限公司', `sort` = 1, `remark` = NULL, `is_deleted` = 0 WHERE `id` = 1123598813738675203;
-- ----------------------------
-- 增加字典项
-- ----------------------------
INSERT INTO `blade_dict`(`id`, `parent_id`, `code`, `dict_key`, `dict_value`, `sort`, `remark`, `is_deleted`) VALUES (1123598814738675231, 0, 'data_scope_type', -1, '数据权限', 8, NULL, 0);
INSERT INTO `blade_dict`(`id`, `parent_id`, `code`, `dict_key`, `dict_value`, `sort`, `remark`, `is_deleted`) VALUES (1123598814738675232, 1123598814738675231, 'data_scope_type', 1, '全部可见', 1, NULL, 0);
INSERT INTO `blade_dict`(`id`, `parent_id`, `code`, `dict_key`, `dict_value`, `sort`, `remark`, `is_deleted`) VALUES (1123598814738675233, 1123598814738675231, 'data_scope_type', 2, '本人可见', 2, NULL, 0);
INSERT INTO `blade_dict`(`id`, `parent_id`, `code`, `dict_key`, `dict_value`, `sort`, `remark`, `is_deleted`) VALUES (1123598814738675234, 1123598814738675231, 'data_scope_type', 3, '所在机构可见', 3, NULL, 0);
INSERT INTO `blade_dict`(`id`, `parent_id`, `code`, `dict_key`, `dict_value`, `sort`, `remark`, `is_deleted`) VALUES (1123598814738675235, 1123598814738675231, 'data_scope_type', 4, '所在机构及子级可见', 4, NULL, 0);
INSERT INTO `blade_dict`(`id`, `parent_id`, `code`, `dict_key`, `dict_value`, `sort`, `remark`, `is_deleted`) VALUES (1123598814738675236, 1123598814738675231, 'data_scope_type', 5, '自定义', 5, NULL, 0);
-- ----------------------------
-- 增加权限管理模块
-- ----------------------------
INSERT INTO `blade_menu`(`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`) VALUES (1123598815738675307, 0, 'authority', '权限管理', 'menu', '/authority', 'iconfont icon-bofangqi-suoping', 98, 1, 0, 1, '', 0);
-- ----------------------------
-- 角色管理迁移至权限管理
-- ----------------------------
DELETE FROM `blade_menu` WHERE ID = 1123598815738675208;
INSERT INTO `blade_menu`(`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`) VALUES (1123598815738675308, 1123598815738675307, 'role', '角色管理', 'menu', '/authority/role', 'iconfont iconicon_boss', 1, 1, 0, 1, NULL, 0);
UPDATE `blade_menu` SET `parent_id` = 1123598815738675308, `code` = 'role_add', `name` = '新增', `alias` = 'add', `path` = '/authority/role/add', `source` = 'plus', `sort` = 1, `category` = 2, `action` = 1, `is_open` = 1, `remark` = NULL, `is_deleted` = 0 WHERE `id` = 1123598815738675241;
UPDATE `blade_menu` SET `parent_id` = 1123598815738675308, `code` = 'role_edit', `name` = '修改', `alias` = 'edit', `path` = '/authority/role/edit', `source` = 'form', `sort` = 2, `category` = 2, `action` = 2, `is_open` = 1, `remark` = NULL, `is_deleted` = 0 WHERE `id` = 1123598815738675242;
UPDATE `blade_menu` SET `parent_id` = 1123598815738675308, `code` = 'role_delete', `name` = '删除', `alias` = 'delete', `path` = '/api/blade-system/role/remove', `source` = 'delete', `sort` = 3, `category` = 2, `action` = 3, `is_open` = 1, `remark` = NULL, `is_deleted` = 0 WHERE `id` = 1123598815738675243;
UPDATE `blade_menu` SET `parent_id` = 1123598815738675308, `code` = 'role_view', `name` = '查看', `alias` = 'view', `path` = '/authority/role/view', `source` = 'file-text', `sort` = 4, `category` = 2, `action` = 2, `is_open` = 1, `remark` = NULL, `is_deleted` = 0 WHERE `id` = 1123598815738675244;
-- ----------------------------
-- 增加数据权限及接口权限独立菜单
-- ----------------------------
INSERT INTO `blade_menu`(`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`) VALUES (1123598815738675309, 1123598815738675307, 'data_scope', '数据权限', 'menu', '/authority/datascope', 'iconfont icon-shujuzhanshi2', 2, 1, 0, 1, '', 0);
INSERT INTO `blade_menu`(`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`) VALUES (1123598815738675310, 1123598815738675309, 'data_scope_setting', '权限配置', 'setting', NULL, 'setting', 1, 2, 2, 1, NULL, 0);
-- ----------------------------
-- 增加数据权限及菜单权限
-- ----------------------------
INSERT INTO `blade_role_menu`(`id`, `menu_id`, `role_id`) VALUES (1455363615489028098, 1123598815738675307, 1123598816738675201);
INSERT INTO `blade_role_menu`(`id`, `menu_id`, `role_id`) VALUES (1455363615505805313, 1123598815738675309, 1123598816738675201);
INSERT INTO `blade_role_menu`(`id`, `menu_id`, `role_id`) VALUES (1455363615518388225, 1123598815738675310, 1123598816738675201);
-- ----------------------------
-- 增加create_dept字段并赋默认值
-- ----------------------------
ALTER TABLE `blade_client`
ADD COLUMN `create_dept` bigint(20) NULL COMMENT '创建部门' AFTER `create_user`;
ALTER TABLE `blade_notice`
ADD COLUMN `create_dept` bigint(20) NULL COMMENT '创建部门' AFTER `create_user`;
ALTER TABLE `blade_param`
ADD COLUMN `create_dept` bigint(20) NULL COMMENT '创建部门' AFTER `create_user`;
ALTER TABLE `blade_tenant`
ADD COLUMN `create_dept` bigint(20) NULL COMMENT '创建部门' AFTER `create_user`;
ALTER TABLE `blade_user`
ADD COLUMN `create_dept` bigint(20) NULL COMMENT '创建部门' AFTER `create_user`;
UPDATE `blade_client` SET create_dept = 1123598813738675201 WHERE create_dept IS NULL;
UPDATE `blade_notice` SET create_dept = 1123598813738675201 WHERE create_dept IS NULL;
UPDATE `blade_param` SET create_dept = 1123598813738675201 WHERE create_dept IS NULL;
UPDATE `blade_tenant` SET create_dept = 1123598813738675201 WHERE create_dept IS NULL;
UPDATE `blade_user` SET create_dept = 1123598813738675201 WHERE create_dept IS NULL;

16
pom.xml
View File

@ -5,29 +5,29 @@
<groupId>org.springblade</groupId>
<artifactId>SpringBlade</artifactId>
<version>3.1.0</version>
<version>3.2.0</version>
<packaging>pom</packaging>
<properties>
<blade.tool.version>3.1.0</blade.tool.version>
<blade.project.version>3.1.0</blade.project.version>
<blade.tool.version>3.2.0</blade.tool.version>
<blade.project.version>3.2.0</blade.project.version>
<java.version>1.8</java.version>
<maven.plugin.version>3.8.1</maven.plugin.version>
<swagger.version>2.10.5</swagger.version>
<swagger.models.version>1.6.2</swagger.models.version>
<knife4j.version>2.0.8</knife4j.version>
<knife4j.version>2.0.9</knife4j.version>
<protostuff.version>1.6.0</protostuff.version>
<captcha.version>1.6.2</captcha.version>
<easyexcel.version>2.2.6</easyexcel.version>
<mica.auto.version>1.2.5</mica.auto.version>
<alibaba.cloud.version>2021.1</alibaba.cloud.version>
<alibaba.nacos.version>2.0.2</alibaba.nacos.version>
<spring.boot.admin.version>2.4.2</spring.boot.admin.version>
<alibaba.nacos.version>2.0.3</alibaba.nacos.version>
<spring.boot.admin.version>2.5.3</spring.boot.admin.version>
<spring.plugin.version>2.0.0.RELEASE</spring.plugin.version>
<spring.boot.version>2.5.2</spring.boot.version>
<spring.cloud.version>2020.0.3</spring.cloud.version>
<spring.boot.version>2.5.6</spring.boot.version>
<spring.cloud.version>2020.0.4</spring.cloud.version>
<spring.platform.version>Cairo-SR8</spring.platform.version>
<!-- 推荐使用Harbor -->

View File

@ -1,2 +1,2 @@
REGISTER=192.168.0.157/blade
TAG=3.1.0
TAG=3.2.0

View File

@ -152,7 +152,7 @@ spec:
spec:
containers:
- name: blade-admin
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-admin:3.1.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-admin:3.2.0'
args:
- '--spring.profiles.active=${PROFILE}'
- '--spring.cloud.nacos.config.server-addr=${NACOS_SERVER_ADDR}'
@ -386,7 +386,7 @@ spec:
spec:
containers:
- name: blade-auth
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-auth:3.1.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-auth:3.2.0'
args:
- '--spring.profiles.active=${PROFILE}'
- '--spring.cloud.nacos.config.server-addr=${NACOS_SERVER_ADDR}'
@ -625,7 +625,7 @@ spec:
spec:
containers:
- name: blade-desk
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-desk:3.1.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-desk:3.2.0'
args:
- '--spring.profiles.active=${PROFILE}'
- '--spring.cloud.nacos.config.server-addr=${NACOS_SERVER_ADDR}'
@ -864,7 +864,7 @@ spec:
spec:
containers:
- name: blade-develop
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-develop:3.1.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-develop:3.2.0'
args:
- '--spring.profiles.active=${PROFILE}'
- '--spring.cloud.nacos.config.server-addr=${NACOS_SERVER_ADDR}'
@ -1096,7 +1096,7 @@ spec:
spec:
containers:
- name: blade-gateway
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-gateway:3.1.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-gateway:3.2.0'
args:
- '--spring.profiles.active=${PROFILE}'
- '--spring.cloud.nacos.config.server-addr=${NACOS_SERVER_ADDR}'
@ -1331,7 +1331,7 @@ spec:
spec:
containers:
- name: blade-log
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-log:3.1.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-log:3.2.0'
args:
- '--spring.profiles.active=${PROFILE}'
- '--spring.cloud.nacos.config.server-addr=${NACOS_SERVER_ADDR}'
@ -1565,7 +1565,7 @@ spec:
spec:
containers:
- name: blade-report
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-report:3.1.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-report:3.2.0'
args:
- '--spring.profiles.active=${PROFILE}'
- '--spring.cloud.nacos.config.server-addr=${NACOS_SERVER_ADDR}'
@ -1799,7 +1799,7 @@ spec:
spec:
containers:
- name: blade-resource
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-resource:3.1.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-resource:3.2.0'
args:
- '--spring.profiles.active=${PROFILE}'
- '--spring.cloud.nacos.config.server-addr=${NACOS_SERVER_ADDR}'
@ -2033,7 +2033,7 @@ spec:
spec:
containers:
- name: blade-system
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-system:3.1.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-system:3.2.0'
args:
- '--spring.profiles.active=${PROFILE}'
- '--spring.cloud.nacos.config.server-addr=${NACOS_SERVER_ADDR}'
@ -2267,7 +2267,7 @@ spec:
spec:
containers:
- name: blade-user
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-user:3.1.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-user:3.2.0'
args:
- '--spring.profiles.active=${PROFILE}'
- '--spring.cloud.nacos.config.server-addr=${NACOS_SERVER_ADDR}'
@ -2496,7 +2496,7 @@ spec:
spec:
containers:
- name: saber-web
image: 'swr.cn-east-2.myhuaweicloud.com/blade/saber-web:3.1.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/saber-web:3.2.0'
ports:
- name: web
containerPort: 80
@ -2721,7 +2721,7 @@ spec:
spec:
containers:
- name: blade-swagger
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-swagger:3.1.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-swagger:3.2.0'
args:
- '--spring.profiles.active=${PROFILE}'
- '--spring.cloud.nacos.config.server-addr=${NACOS_SERVER_ADDR}'
@ -3749,7 +3749,7 @@ spec:
spec:
containers:
- name: mysql
image: 'swr.cn-east-2.myhuaweicloud.com/blade/saber-db:v3.1.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/saber-db:v3.2.0'
ports:
- name: mysql
containerPort: 3306