🎉 4.8.0.RELEASE 新增接口权限模块,增强系统安全性

This commit is contained in:
smallchill 2026-01-15 00:50:19 +08:00
parent 652d8e61e4
commit 1172a5d382
45 changed files with 1080 additions and 741 deletions

View File

@ -1,5 +1,5 @@
<p align="center">
<img src="https://img.shields.io/badge/Release-V4.7.0-blue.svg" alt="Downloads">
<img src="https://img.shields.io/badge/Release-V4.8.0-blue.svg" alt="Downloads">
<img src="https://img.shields.io/badge/JDK-17+-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-2025-blue.svg" alt="Coverage Status">
@ -37,39 +37,44 @@
|----------------------|------------|
| Java | 17+ |
| NodeJS | 18+ |
| Spring | 6.2.11 |
| Spring Boot | 3.5.6 |
| Spring Cloud | 2025.0.0 |
| Spring Cloud Alibaba | 2023.0.3.3 |
| Nacos Alibaba | 3.1.0 |
| Spring | 6.2.15 |
| Spring Boot | 3.5.9 |
| Spring Cloud | 2025.0.1 |
| Spring Cloud Alibaba | 2025.0.0.0 |
| Nacos Alibaba | 3.1.1 |
| Mybatis Plus | 3.5.19 |
## 工程结构
```
SpringBlade
├── blade-auth -- 授权服务提供
├── blade-common -- 常用工具封装包
├── blade-gateway -- Spring Cloud 网关
├── blade-ops -- 运维中心
├ ├── blade-admin -- spring-cloud后台管理
├ ├── blade-develop -- 代码生成
├ ├── blade-report -- 报表模块
├ ├── blade-resource -- 资源模块
├ ├── blade-seata-order -- seata分布式事务demo
├ ├── blade-seata-storage -- seata分布式事务demo
├── blade-service -- 业务模块
├ ├── blade-demo -- 示例模块
├ ├── blade-desk -- 工作台模块
├ ├── blade-log -- 日志模块
├ └── blade-system -- 系统模块
├── blade-service-api -- 业务模块api封装
├ ├── blade-demo-api -- 示例api
├ ├── blade-desk-api -- 工作台api
├ ├── blade-dict-api -- 字典api
├ ├── blade-scope-api -- 权限api
├ ├── blade-system-api -- 系统api
└── └── blade-user-api -- 用户api
├── src/main/java/org/springblade
│ ├── Application.java -- 启动类
│ ├── common -- 公共模块
│ │ ├── cache -- 缓存配置
│ │ ├── config -- 系统配置
│ │ ├── constant -- 常量定义
│ │ ├── launch -- 启动配置
│ │ └── tool -- 工具类
│ ├── core -- 核心模块
│ │ ├── log -- 日志拓展
│ │ └── secure -- 安全拓展
│ └── modules -- 业务模块
│ ├── auth -- 认证授权模块
│ ├── desk -- 工作台模块
│ ├── develop -- 代码生成模块
│ ├── resource -- 资源管理模块
│ └── system -- 系统管理模块
├── src/main/resources
│ ├── application.yml -- 主配置文件
│ ├── application-dev.yml -- 开发环境配置
│ ├── application-test.yml -- 测试环境配置
│ ├── application-prod.yml -- 生产环境配置
│ └── config -- 其他配置文件
├── doc -- 文档目录
│ ├── script -- 启动脚本
│ └── sql -- 数据库脚本
└── pom.xml -- Maven配置文件
```
## 官方信息

View File

@ -33,4 +33,14 @@ public interface CommonConstant {
*/
String DEFAULT_PASSWORD = "123456";
/**
* 数据权限类型
*/
Integer DATA_SCOPE_CATEGORY = 1;
/**
* 接口权限类型
*/
Integer API_SCOPE_CATEGORY = 2;
}

View File

@ -24,7 +24,9 @@ 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.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.constant.RoleConstant;
import org.springblade.core.tool.utils.Func;
import org.springblade.develop.entity.Datasource;
import org.springblade.develop.service.IDatasourceService;
@ -42,6 +44,7 @@ import java.util.List;
@AllArgsConstructor
@RequestMapping("/datasource")
@Tag(name = "数据源配置表", description = "数据源配置表接口")
@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
public class DatasourceController extends BladeController {
private IDatasourceService datasourceService;

View File

@ -18,6 +18,10 @@
<groupId>org.springblade</groupId>
<artifactId>blade-core-secure</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-starter-datascope</artifactId>

View File

@ -0,0 +1,78 @@
/**
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.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.cache.utils.CacheUtil;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.system.feign.IApiScopeClient;
import java.util.List;
import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
/**
* 接口权限缓存
*
* @author Chill
*/
public class ApiScopeCache {
private static final String SCOPE_CACHE_ROLE = "apiScope:role:";
private static final String SCOPE_CACHE_CODE = "apiScope:code:";
private static IApiScopeClient apiScopeClient;
private static IApiScopeClient getApiScopeClient() {
if (apiScopeClient == null) {
apiScopeClient = SpringUtil.getBean(IApiScopeClient.class);
}
return apiScopeClient;
}
/**
* 获取接口权限地址
*
* @param roleId 角色id
* @return permissions
*/
public static List<String> permissionPath(String roleId) {
List<String> permissions = CacheUtil.get(SYS_CACHE, SCOPE_CACHE_ROLE, roleId, List.class);
if (permissions == null) {
permissions = getApiScopeClient().permissionPath(roleId);
CacheUtil.put(SYS_CACHE, SCOPE_CACHE_ROLE, roleId, permissions);
}
return permissions;
}
/**
* 获取接口权限信息
*
* @param permission 权限编号
* @param roleId 角色id
* @return permissions
*/
public static List<String> permissionCode(String permission, String roleId) {
List<String> permissions = CacheUtil.get(SYS_CACHE, SCOPE_CACHE_CODE, permission + StringPool.COLON + roleId, List.class);
if (permissions == null) {
permissions = getApiScopeClient().permissionCode(permission, roleId);
CacheUtil.put(SYS_CACHE, SCOPE_CACHE_CODE, permission + StringPool.COLON + roleId, permissions);
}
return permissions;
}
}

View File

@ -15,13 +15,17 @@
*/
package org.springblade.system.cache;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.datascope.model.DataScopeModel;
import org.springblade.core.tool.utils.*;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.system.feign.IDataScopeClient;
import java.util.List;
import static org.springblade.core.tool.utils.CacheUtil.SYS_CACHE;
import static org.springblade.core.cache.utils.CacheUtil.SYS_CACHE;
/**

View File

@ -15,10 +15,11 @@
*/
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.core.secure.handler.IPermissionHandler;
import org.springblade.system.handler.ApiScopePermissionHandler;
import org.springblade.system.handler.DataScopeModelHandler;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Bean;
@ -39,4 +40,9 @@ public class ScopeConfiguration {
return new DataScopeModelHandler();
}
@Bean
public IPermissionHandler permissionHandler() {
return new ApiScopePermissionHandler();
}
}

View File

@ -0,0 +1,56 @@
/**
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.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.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 = IApiScopeClientFallback.class)
public interface IApiScopeClient {
String API_PREFIX = "/feign/client/api-scope";
String PERMISSION_PATH = API_PREFIX + "/permission-path";
String PERMISSION_CODE = API_PREFIX + "/permission-code";
/**
* 获取接口权限地址
*
* @param roleId 角色id
* @return permissions
*/
@GetMapping(PERMISSION_PATH)
List<String> permissionPath(@RequestParam("roleId") String roleId);
/**
* 获取接口权限信息
*
* @param permission 权限编号
* @param roleId 角色id
* @return permissions
*/
@GetMapping(PERMISSION_CODE)
List<String> permissionCode(@RequestParam("permission") String permission, @RequestParam("roleId") String roleId);
}

View File

@ -0,0 +1,38 @@
/**
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.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.springframework.stereotype.Component;
import java.util.List;
/**
* IApiScopeClientFallback
*
* @author Chill
*/
@Component
public class IApiScopeClientFallback implements IApiScopeClient {
@Override
public List<String> permissionPath(String roleId) {
return null;
}
@Override
public List<String> permissionCode(String permission, String roleId) {
return null;
}
}

View File

@ -0,0 +1,62 @@
/**
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.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.secure.BladeUser;
import org.springblade.core.secure.handler.IPermissionHandler;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.WebUtil;
import jakarta.servlet.http.HttpServletRequest;
import java.util.List;
import static org.springblade.system.cache.ApiScopeCache.*;
/**
* 接口权限校验类
*
* @author Chill
*/
public class ApiScopePermissionHandler implements IPermissionHandler {
@Override
public boolean permissionAll() {
HttpServletRequest request = WebUtil.getRequest();
BladeUser user = AuthUtil.getUser();
if (request == null || user == null) {
return false;
}
String uri = request.getRequestURI();
List<String> paths = permissionPath(user.getRoleId());
if (paths == null || paths.isEmpty()) {
return false;
}
return paths.stream().anyMatch(uri::contains);
}
@Override
public boolean hasPermission(String permission) {
HttpServletRequest request = WebUtil.getRequest();
BladeUser user = AuthUtil.getUser();
if (request == null || user == null) {
return false;
}
List<String> codes = permissionCode(permission, user.getRoleId());
return codes != null && !codes.isEmpty();
}
}

View File

@ -0,0 +1,72 @@
/**
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.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.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.mp.base.BaseEntity;
import java.io.Serial;
/**
* 实体类
*
* @author BladeX
*/
@Data
@TableName("blade_scope_api")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "ApiScope对象")
public class ApiScope extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 菜单主键
*/
@Schema(description = "菜单主键")
private Long menuId;
/**
* 资源编号
*/
@Schema(description = "资源编号")
private String resourceCode;
/**
* 接口权限名称
*/
@Schema(description = "接口权限名称")
private String scopeName;
/**
* 接口权限字段
*/
@Schema(description = "接口权限字段")
private String scopePath;
/**
* 接口权限类型
*/
@Schema(description = "接口权限类型")
private Integer scopeType;
/**
* 接口权限备注
*/
@Schema(description = "接口权限备注")
private String remark;
}

View File

@ -47,6 +47,12 @@ public class RoleScope implements Serializable {
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 权限类型
*/
@Schema(description = "权限类型")
private Integer scopeCategory;
/**
* 权限id
*/

View File

@ -0,0 +1,41 @@
/**
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.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.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.system.entity.ApiScope;
import java.io.Serial;
/**
* 视图实体类
*
* @author Chill
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "ApiScopeVO对象")
public class ApiScopeVO extends ApiScope {
@Serial
private static final long serialVersionUID = 1L;
/**
* 规则类型名
*/
private String scopeTypeName;
}

View File

@ -31,4 +31,6 @@ public class CheckedTreeVO {
private List<String> dataScope;
private List<String> apiScope;
}

View File

@ -35,4 +35,6 @@ public class GrantTreeVO implements Serializable {
private List<MenuVO> dataScope;
private List<MenuVO> apiScope;
}

View File

@ -44,4 +44,7 @@ public class GrantVO implements Serializable {
@Schema(description = "dataScopeIds集合")
private List<Long> dataScopeIds;
@Schema(description = "apiScopeIds集合")
private List<Long> apiScopeIds;
}

View File

@ -0,0 +1,119 @@
/**
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.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.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.cache.utils.CacheUtil;
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.Func;
import org.springblade.system.entity.ApiScope;
import org.springblade.system.service.IApiScopeService;
import org.springblade.system.vo.ApiScopeVO;
import org.springblade.system.wrapper.ApiScopeWrapper;
import org.springframework.web.bind.annotation.*;
import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
/**
* 接口权限控制器
*
* @author BladeX
*/
@RestController
@AllArgsConstructor
@RequestMapping("/api-scope")
@Tag(name = "接口权限", description = "接口权限")
public class ApiScopeController extends BladeController {
private final IApiScopeService apiScopeService;
/**
* 详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入dataScope")
public R<ApiScope> detail(ApiScope dataScope) {
ApiScope detail = apiScopeService.getOne(Condition.getQueryWrapper(dataScope));
return R.data(detail);
}
/**
* 分页
*/
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入dataScope")
public R<IPage<ApiScopeVO>> list(ApiScope dataScope, Query query) {
IPage<ApiScope> pages = apiScopeService.page(Condition.getPage(query), Condition.getQueryWrapper(dataScope));
return R.data(ApiScopeWrapper.build().pageVO(pages));
}
/**
* 新增
*/
@PostMapping("/save")
@ApiOperationSupport(order = 3)
@Operation(summary = "新增", description = "传入dataScope")
public R save(@Valid @RequestBody ApiScope dataScope) {
CacheUtil.clear(SYS_CACHE);
return R.status(apiScopeService.save(dataScope));
}
/**
* 修改
*/
@PostMapping("/update")
@ApiOperationSupport(order = 4)
@Operation(summary = "修改", description = "传入dataScope")
public R update(@Valid @RequestBody ApiScope dataScope) {
CacheUtil.clear(SYS_CACHE);
return R.status(apiScopeService.updateById(dataScope));
}
/**
* 新增或修改
*/
@PostMapping("/submit")
@ApiOperationSupport(order = 5)
@Operation(summary = "新增或修改", description = "传入dataScope")
public R submit(@Valid @RequestBody ApiScope dataScope) {
CacheUtil.clear(SYS_CACHE);
return R.status(apiScopeService.saveOrUpdate(dataScope));
}
/**
* 删除
*/
@PostMapping("/remove")
@ApiOperationSupport(order = 6)
@Operation(summary = "逻辑删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
CacheUtil.clear(SYS_CACHE);
return R.status(apiScopeService.deleteLogic(Func.toLongList(ids)));
}
}

View File

@ -17,15 +17,16 @@ package org.springblade.system.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.cache.utils.CacheUtil;
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;
@ -33,9 +34,8 @@ import org.springblade.system.vo.DataScopeVO;
import org.springblade.system.wrapper.DataScopeWrapper;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
import static org.springblade.core.cache.utils.CacheUtil.SYS_CACHE;
import static org.springblade.core.tool.utils.CacheUtil.SYS_CACHE;
/**
* 数据权限控制器

View File

@ -187,6 +187,7 @@ public class MenuController extends BladeController {
GrantTreeVO vo = new GrantTreeVO();
vo.setMenu(menuService.grantTree(user));
vo.setDataScope(menuService.grantDataScopeTree(user));
vo.setApiScope(menuService.grantApiScopeTree(user));
return R.data(vo);
}
@ -200,6 +201,7 @@ public class MenuController extends BladeController {
CheckedTreeVO vo = new CheckedTreeVO();
vo.setMenu(menuService.roleTreeKeys(roleIds));
vo.setDataScope(menuService.dataScopeTreeKeys(roleIds));
vo.setApiScope(menuService.apiScopeTreeKeys(roleIds));
return R.data(vo);
}

View File

@ -26,11 +26,11 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.mp.support.Condition;
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.utils.CacheUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.entity.Role;
import org.springblade.system.service.IRoleService;
@ -42,7 +42,8 @@ import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import static org.springblade.core.tool.utils.CacheUtil.SYS_CACHE;
import static org.springblade.core.cache.utils.CacheUtil.SYS_CACHE;
/**
* 控制器
@ -134,14 +135,14 @@ public class RoleController extends BladeController {
}
/**
* 设置菜单权限
* 设置角色权限
*/
@PostMapping("/grant")
@ApiOperationSupport(order = 7)
@Operation(summary = "权限设置", description = "传入roleId集合以及menuId集合")
public R grant(@RequestBody GrantVO grantVO) {
CacheUtil.clear(SYS_CACHE);
boolean temp = roleService.grant(grantVO.getRoleIds(), grantVO.getMenuIds(), grantVO.getDataScopeIds());
boolean temp = roleService.grant(grantVO.getRoleIds(), grantVO.getMenuIds(), grantVO.getDataScopeIds(), grantVO.getApiScopeIds());
return R.status(temp);
}
}

View File

@ -31,8 +31,10 @@ 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.secure.BladeUser;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.constant.RoleConstant;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.entity.Tenant;
@ -76,6 +78,7 @@ public class TenantController extends BladeController {
@Parameter(name = "contactNumber", description = "联系电话", in = ParameterIn.QUERY, schema = @Schema(type = "string"))
})
@Operation(summary = "分页", description = "传入tenant")
@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
public R<IPage<Tenant>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> tenant, Query query, BladeUser bladeUser) {
QueryWrapper<Tenant> queryWrapper = Condition.getQueryWrapper(tenant, Tenant.class);
IPage<Tenant> pages = tenantService.page(Condition.getPage(query), (!bladeUser.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID)) ? queryWrapper.lambda().eq(Tenant::getTenantId, bladeUser.getTenantId()) : queryWrapper);

View File

@ -302,4 +302,14 @@ public class UserController {
return R.success("操作成功");
}
/**
* 修改基本信息
*/
@PostMapping("/update-info")
@ApiOperationSupport(order = 17)
@Operation(summary = "修改基本信息", description = "传入User")
public R updateInfo(@RequestBody User user) {
return R.status(userService.updateUserInfo(user));
}
}

View File

@ -0,0 +1,60 @@
/**
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.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 io.swagger.v3.oas.annotations.Hidden;
import lombok.RequiredArgsConstructor;
import org.springblade.core.tool.utils.Func;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.springblade.core.secure.constant.PermissionConstant.permissionAllStatement;
import static org.springblade.core.secure.constant.PermissionConstant.permissionCodeStatement;
/**
* 接口权限Feign实现类
*
* @author Chill
*/
@Hidden
@RestController
@RequiredArgsConstructor
public class ApiScopeClient implements IApiScopeClient {
private final JdbcTemplate jdbcTemplate;
@Override
@GetMapping(PERMISSION_PATH)
public List<String> permissionPath(String roleId) {
List<Long> roleIds = Func.toLongList(roleId);
return jdbcTemplate.queryForList(permissionAllStatement(roleIds.size()), String.class, roleIds.toArray());
}
@Override
@GetMapping(PERMISSION_CODE)
public List<String> permissionCode(String permission, String roleId) {
List<Object> args = new ArrayList<>(Collections.singletonList(permission));
List<Long> roleIds = Func.toLongList(roleId);
args.addAll(roleIds);
return jdbcTemplate.queryForList(permissionCodeStatement(roleIds.size()), String.class, args.toArray());
}
}

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.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.ApiScope;
/**
* Mapper 接口
*
* @author BladeX
*/
public interface ApiScopeMapper extends BaseMapper<ApiScope> {
}

View File

@ -86,6 +86,21 @@ public interface MenuMapper extends BaseMapper<Menu> {
*/
List<MenuVO> grantDataScopeTreeByRole(List<Long> roleId);
/**
* 接口权限授权树形结构
*
* @return
*/
List<MenuVO> grantApiScopeTree();
/**
* 接口权限授权树形结构
*
* @param roleId
* @return
*/
List<MenuVO> grantApiScopeTreeByRole(List<Long> roleId);
/**
* 顶部菜单树形结构
*

View File

@ -271,6 +271,106 @@
AND menu_id IS NOT NULL
</select>
<select id="grantApiScopeTree" 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_api 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_api
WHERE
is_deleted = 0
AND menu_id IS NOT NULL
</select>
<select id="grantApiScopeTreeByRole" 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_api 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_api
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-2099, Chill Zhuang 庄骞 (bladejava@qq.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.ApiScope;
/**
* 服务类
*
* @author BladeX
*/
public interface IApiScopeService extends BaseService<ApiScope> {
}

View File

@ -90,6 +90,14 @@ public interface IMenuService extends IService<Menu> {
*/
List<MenuVO> grantDataScopeTree(BladeUser user);
/**
* 接口权限授权树形结构
*
* @param user
* @return
*/
List<MenuVO> grantApiScopeTree(BladeUser user);
/**
* 默认选中节点
*
@ -106,6 +114,14 @@ public interface IMenuService extends IService<Menu> {
*/
List<String> dataScopeTreeKeys(String roleIds);
/**
* 接口权限默认选中节点
*
* @param roleIds
* @return
*/
List<String> apiScopeTreeKeys(String roleIds);
/**
* 获取配置的角色权限
*

View File

@ -50,11 +50,13 @@ public interface IRoleService extends IService<Role> {
/**
* 权限配置
*
* @param roleIds 角色id集合
* @param menuIds 菜单id集合
* @param roleIds 角色id集合
* @param menuIds 菜单id集合
* @param dataScopeIds 数据权限id集合
* @param apiScopeIds 接口权限id集合
* @return 是否成功
*/
boolean grant(@NotEmpty List<Long> roleIds, @NotEmpty List<Long> menuIds, List<Long> dataScopeIds);
boolean grant(@NotEmpty List<Long> roleIds, List<Long> menuIds, List<Long> dataScopeIds, List<Long> apiScopeIds);
/**
* 获取角色ID

View File

@ -35,11 +35,20 @@ public interface IUserService extends BaseService<User> {
/**
* 新增或修改用户
*
* @param user
* @return
*/
boolean submit(User user);
/**
* 修改用户基本信息
*
* @param user
* @return
*/
boolean updateUserInfo(User user);
/**
* 自定义分页
*

View File

@ -0,0 +1,33 @@
/**
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.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.ApiScope;
import org.springblade.system.mapper.ApiScopeMapper;
import org.springblade.system.service.IApiScopeService;
import org.springframework.stereotype.Service;
/**
* 服务实现类
*
* @author BladeX
*/
//@Master
@Service
public class ApiScopeServiceImpl extends BaseServiceImpl<ApiScopeMapper, ApiScope> implements IApiScopeService {
}

View File

@ -18,11 +18,11 @@ 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.cache.utils.CacheUtil;
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;
@ -55,7 +55,7 @@ public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements ID
@Override
public String getDeptIds(String tenantId, String deptNames) {
List<Dept> deptList = baseMapper.selectList(Wrappers.<Dept>query().lambda().eq(Dept::getTenantId, tenantId).in(Dept::getDeptName, Func.toStrList(deptNames)));
if (deptList != null && deptList.size() > 0) {
if (deptList != null && !deptList.isEmpty()) {
return deptList.stream().map(dept -> Func.toStr(dept.getId())).distinct().collect(Collectors.joining(","));
}
return null;

View File

@ -42,6 +42,9 @@ import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
import static org.springblade.common.constant.CommonConstant.API_SCOPE_CATEGORY;
import static org.springblade.common.constant.CommonConstant.DATA_SCOPE_CATEGORY;
/**
* 服务实现类
*
@ -147,6 +150,11 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IM
return ForestNodeMerger.merge(user.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID) ? baseMapper.grantDataScopeTree() : baseMapper.grantDataScopeTreeByRole(Func.toLongList(user.getRoleId())));
}
@Override
public List<MenuVO> grantApiScopeTree(BladeUser user) {
return ForestNodeMerger.merge(user.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID) ? baseMapper.grantApiScopeTree() : baseMapper.grantApiScopeTreeByRole(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)));
@ -155,7 +163,13 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IM
@Override
public List<String> dataScopeTreeKeys(String roleIds) {
List<RoleScope> roleScopes = roleScopeService.list(Wrappers.<RoleScope>query().lambda().in(RoleScope::getRoleId, Func.toLongList(roleIds)));
List<RoleScope> roleScopes = roleScopeService.list(Wrappers.<RoleScope>query().lambda().eq(RoleScope::getScopeCategory, DATA_SCOPE_CATEGORY).in(RoleScope::getRoleId, Func.toLongList(roleIds)));
return roleScopes.stream().map(roleScope -> Func.toStr(roleScope.getScopeId())).collect(Collectors.toList());
}
@Override
public List<String> apiScopeTreeKeys(String roleIds) {
List<RoleScope> roleScopes = roleScopeService.list(Wrappers.<RoleScope>query().lambda().eq(RoleScope::getScopeCategory, API_SCOPE_CATEGORY).in(RoleScope::getRoleId, Func.toLongList(roleIds)));
return roleScopes.stream().map(roleScope -> Func.toStr(roleScope.getScopeId())).collect(Collectors.toList());
}

View File

@ -40,6 +40,9 @@ import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static org.springblade.common.constant.CommonConstant.API_SCOPE_CATEGORY;
import static org.springblade.common.constant.CommonConstant.DATA_SCOPE_CATEGORY;
/**
* 服务实现类
*
@ -69,7 +72,11 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IR
}
@Override
public boolean grant(@NotEmpty List<Long> roleIds, @NotEmpty List<Long> menuIds, List<Long> dataScopeIds) {
public boolean grant(@NotEmpty List<Long> roleIds, List<Long> menuIds, List<Long> dataScopeIds, List<Long> apiScopeIds) {
return grantRoleMenu(roleIds, menuIds) && grantDataScope(roleIds, dataScopeIds) && grantApiScope(roleIds, apiScopeIds);
}
private boolean grantRoleMenu(List<Long> roleIds, List<Long> menuIds) {
// 删除角色配置的菜单集合
roleMenuService.remove(Wrappers.<RoleMenu>update().lambda().in(RoleMenu::getRoleId, roleIds));
// 组装配置
@ -82,27 +89,47 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IR
}));
// 新增配置
roleMenuService.saveBatch(roleMenus);
return true;
}
private boolean grantDataScope(List<Long> roleIds, List<Long> dataScopeIds) {
// 删除角色配置的数据权限集合
roleScopeService.remove(Wrappers.<RoleScope>update().lambda().in(RoleScope::getRoleId, roleIds));
roleScopeService.remove(Wrappers.<RoleScope>update().lambda().eq(RoleScope::getScopeCategory, DATA_SCOPE_CATEGORY).in(RoleScope::getRoleId, roleIds));
// 组装配置
List<RoleScope> roleDataScopes = new ArrayList<>();
roleIds.forEach(roleId -> dataScopeIds.forEach(scopeId -> {
RoleScope roleScope = new RoleScope();
roleScope.setScopeCategory(DATA_SCOPE_CATEGORY);
roleScope.setRoleId(roleId);
roleScope.setScopeId(scopeId);
roleDataScopes.add(roleScope);
}));
// 新增配置
roleScopeService.saveBatch(roleDataScopes);
return true;
}
private boolean grantApiScope(List<Long> roleIds, List<Long> apiScopeIds) {
// 删除角色配置的接口权限集合
roleScopeService.remove(Wrappers.<RoleScope>update().lambda().eq(RoleScope::getScopeCategory, API_SCOPE_CATEGORY).in(RoleScope::getRoleId, roleIds));
// 组装配置
List<RoleScope> roleApiScopes = new ArrayList<>();
roleIds.forEach(roleId -> apiScopeIds.forEach(scopeId -> {
RoleScope roleScope = new RoleScope();
roleScope.setScopeCategory(API_SCOPE_CATEGORY);
roleScope.setScopeId(scopeId);
roleScope.setRoleId(roleId);
roleApiScopes.add(roleScope);
}));
// 新增配置
roleScopeService.saveBatch(roleApiScopes);
return true;
}
@Override
public String getRoleIds(String tenantId, String roleNames) {
List<Role> roleList = baseMapper.selectList(Wrappers.<Role>query().lambda().eq(Role::getTenantId, tenantId).in(Role::getRoleName, Func.toStrList(roleNames)));
if (roleList != null && roleList.size() > 0) {
if (roleList != null && !roleList.isEmpty()) {
return roleList.stream().map(role -> Func.toStr(role.getId())).distinct().collect(Collectors.joining(","));
}
return null;

View File

@ -23,6 +23,7 @@ import lombok.AllArgsConstructor;
import org.springblade.common.constant.CommonConstant;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.secure.utils.SecureUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.*;
import org.springblade.system.entity.Tenant;
@ -67,6 +68,23 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
return saveOrUpdate(user);
}
@Override
public boolean updateUserInfo(User user) {
// 用户修改自身信息强制指定当前请求账号的ID
user.setId(SecureUtil.getUserId());
User currentUser = getById(user.getId());
if (currentUser == null) {
throw new ServiceException("用户不存在!");
}
// 用户修改自身信息强制忽略角色部门账号等字段
user.setRoleId(null);
user.setDeptId(null);
user.setAccount(null);
user.setPassword(null);
user.setUpdateTime(DateUtil.now());
return updateById(user);
}
@Override
public IPage<User> selectUserPage(IPage<User> page, User user) {
return page.setRecords(baseMapper.selectUserPage(page, user));

View File

@ -0,0 +1,52 @@
/**
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.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.ApiScope;
import org.springblade.system.service.IDictService;
import org.springblade.system.vo.ApiScopeVO;
import java.util.Objects;
/**
* 包装类,返回视图层所需的字段
*
* @author Chill
*/
public class ApiScopeWrapper extends BaseEntityWrapper<ApiScope, ApiScopeVO> {
private static IDictService dictService;
static {
dictService = SpringUtil.getBean(IDictService.class);
}
public static ApiScopeWrapper build() {
return new ApiScopeWrapper();
}
@Override
public ApiScopeVO entityVO(ApiScope dataScope) {
ApiScopeVO apiScopeVO = Objects.requireNonNull(BeanUtil.copyProperties(dataScope, ApiScopeVO.class));
String scopeTypeName = dictService.getValue("api_scope_type", dataScope.getScopeType());
apiScopeVO.setScopeTypeName(scopeTypeName);
return apiScopeVO;
}
}

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.ApiScopeMapper">
</mapper>

View File

@ -67,13 +67,13 @@ knife4j:
language: zh_cn
enableFooter: false
enableFooterCustom: true
footerCustomContent: Copyright © 2025 SpringBlade All Rights Reserved
footerCustomContent: Copyright © 2026 SpringBlade All Rights Reserved
#swagger配置信息
swagger:
title: SpringBlade 接口文档系统
description: SpringBlade 接口文档系统
version: 4.7.0
version: 4.8.0
license: Powered By SpringBlade
licenseUrl: https://bladex.cn
terms-of-service-url: https://bladex.cn

File diff suppressed because one or more lines are too long

View File

@ -1,47 +0,0 @@
-- ----------------------------
-- Table structure for blade_top_menu
-- ----------------------------
CREATE TABLE `blade_top_menu` (
`id` bigint NOT NULL COMMENT '主键',
`tenant_id` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '租户id',
`code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '顶部菜单编号',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '顶部菜单名',
`source` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '顶部菜单资源',
`path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '顶部菜单路由',
`sort` int NULL DEFAULT NULL COMMENT '顶部菜单排序',
`create_user` bigint NULL DEFAULT NULL COMMENT '创建人',
`create_dept` bigint NULL DEFAULT NULL COMMENT '创建部门',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_user` bigint NULL DEFAULT NULL COMMENT '修改人',
`update_time` datetime NULL DEFAULT NULL COMMENT '修改时间',
`status` int NULL DEFAULT 1 COMMENT '状态',
`is_deleted` int NULL DEFAULT 0 COMMENT '是否已删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '顶部菜单表';
-- ----------------------------
-- Table structure for blade_top_menu_setting
-- ----------------------------
CREATE TABLE `blade_top_menu_setting` (
`id` bigint NOT NULL COMMENT '主键',
`top_menu_id` bigint NULL DEFAULT NULL COMMENT '顶部菜单主键',
`menu_id` bigint NULL DEFAULT NULL COMMENT '菜单主键',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '顶部菜单配置表';
-- ----------------------------
-- 菜单数据新增
-- ----------------------------
INSERT INTO `blade_menu` (`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`) VALUES (1123598815738675208, 1123598815738675203, 'topmenu', '顶部菜单', 'menu', '/system/topmenu', 'iconfont icon-canshu', 7, 1, 0, 1, NULL, 0);
INSERT INTO `blade_menu` (`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`) VALUES (1123598815738675313, 1123598815738675208, 'topmenu_add', '新增', 'add', '/system/topmenu/add', 'plus', 1, 2, 1, 1, NULL, 0);
INSERT INTO `blade_menu` (`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`) VALUES (1123598815738675314, 1123598815738675208, 'topmenu_edit', '修改', 'edit', '/system/topmenu/edit', 'form', 2, 2, 2, 1, NULL, 0);
INSERT INTO `blade_menu` (`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`) VALUES (1123598815738675315, 1123598815738675208, 'topmenu_delete', '删除', 'delete', '/api/blade-system/topmenu/remove', 'delete', 3, 2, 3, 1, NULL, 0);
INSERT INTO `blade_menu` (`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`) VALUES (1123598815738675316, 1123598815738675208, 'topmenu_view', '查看', 'view', '/system/topmenu/view', 'file-text', 4, 2, 2, 1, NULL, 0);
INSERT INTO `blade_menu` (`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`) VALUES (1123598815738675317, 1123598815738675208, 'topmenu_setting', '菜单配置', 'setting', NULL, 'setting', 5, 2, 1, 1, NULL, 0);
INSERT `blade_role_menu` (`id`, `menu_id`, `role_id`) VALUES (1977345456189423620, 1123598815738675208, 1123598816738675201);
INSERT `blade_role_menu` (`id`, `menu_id`, `role_id`) VALUES (1977345456189423621, 1123598815738675313, 1123598816738675201);
INSERT `blade_role_menu` (`id`, `menu_id`, `role_id`) VALUES (1977345456189423622, 1123598815738675314, 1123598816738675201);
INSERT `blade_role_menu` (`id`, `menu_id`, `role_id`) VALUES (1977345456189423623, 1123598815738675315, 1123598816738675201);
INSERT `blade_role_menu` (`id`, `menu_id`, `role_id`) VALUES (1977345456189423624, 1123598815738675316, 1123598816738675201);
INSERT `blade_role_menu` (`id`, `menu_id`, `role_id`) VALUES (1977345456189423625, 1123598815738675317, 1123598816738675201);

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,47 @@
-- ----------------------------
-- 角色权限表新增权限类型字段
-- ----------------------------
ALTER TABLE `blade_role_scope`
ADD COLUMN `scope_category` int NULL COMMENT '权限类型(1:数据权限、2:接口权限)' AFTER `id`,
MODIFY COLUMN `scope_id` bigint NULL DEFAULT NULL COMMENT '权限id' AFTER `id`;
-- ----------------------------
-- 角色权限表设置历史数据权限类型为1
-- ----------------------------
UPDATE `blade_role_scope` SET `scope_category` = 1 WHERE `scope_category` IS NULL;
-- ----------------------------
-- 创建接口权限表
-- ----------------------------
CREATE TABLE `blade_scope_api` (
`id` bigint NOT NULL COMMENT '主键',
`menu_id` bigint 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_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '接口权限地址',
`scope_type` int NULL DEFAULT NULL COMMENT '接口权限类型',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '接口权限备注',
`create_user` bigint NULL DEFAULT NULL COMMENT '创建人',
`create_dept` bigint NULL DEFAULT NULL COMMENT '创建部门',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_user` bigint NULL DEFAULT NULL COMMENT '修改人',
`update_time` datetime NULL DEFAULT NULL COMMENT '修改时间',
`status` int NULL DEFAULT 1 COMMENT '状态',
`is_deleted` int NULL DEFAULT 0 COMMENT '是否已删除',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '接口权限表';
-- ----------------------------
-- 字典表新增接口权限类型数据
-- ----------------------------
INSERT INTO `blade_dict` (`id`, `parent_id`, `code`, `dict_key`, `dict_value`, `sort`, `remark`, `is_deleted`) VALUES (1123598814738675237, 0, 'api_scope_type', '-1', '接口权限', 10, NULL, 0);
INSERT INTO `blade_dict` (`id`, `parent_id`, `code`, `dict_key`, `dict_value`, `sort`, `remark`, `is_deleted`) VALUES (1123598814738675238, 1123598814738675237, 'api_scope_type', '1', '系统接口', 1, NULL, 0);
INSERT INTO `blade_dict` (`id`, `parent_id`, `code`, `dict_key`, `dict_value`, `sort`, `remark`, `is_deleted`) VALUES (1123598814738675239, 1123598814738675237, 'api_scope_type', '2', '业务接口', 2, NULL, 0);
-- ----------------------------
-- 菜单表新增接口权限菜单
-- ----------------------------
INSERT INTO `blade_menu` (`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`) VALUES (1123598815738675311, 1123598815738675307, 'api_scope', '接口权限', 'menu', '/authority/apiscope', 'iconfont iconicon_send', 3, 1, 0, 1, NULL, 0);
INSERT INTO `blade_menu` (`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`) VALUES (1123598815738675312, 1123598815738675311, 'api_scope_setting', '权限配置', 'setting', NULL, 'setting', 1, 2, 2, 1, NULL, 0);
INSERT INTO `blade_role_menu` (`id`, `menu_id`, `role_id`) VALUES (2006703481530257413, 1123598815738675311, 1123598816738675201);
INSERT INTO `blade_role_menu` (`id`, `menu_id`, `role_id`) VALUES (2006703481530257414, 1123598815738675312, 1123598816738675201);

15
pom.xml
View File

@ -9,9 +9,9 @@
<packaging>pom</packaging>
<properties>
<revision>4.7.0</revision>
<revision>4.8.0</revision>
<blade.tool.version>4.7.0</blade.tool.version>
<blade.tool.version>4.8.0</blade.tool.version>
<java.version>17</java.version>
<maven.plugin.version>3.11.0</maven.plugin.version>
@ -78,17 +78,6 @@
<artifactId>blade-demo-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- SpringAdmin -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>3.4.1</version>
</dependency>
<!-- dynamic-datasource -->
<dependency>
<groupId>com.baomidou</groupId>

View File

@ -1,2 +1,2 @@
REGISTER=192.168.0.157/blade
TAG=4.7.0
TAG=4.8.0

View File

@ -152,7 +152,7 @@ spec:
spec:
containers:
- name: blade-admin
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-admin:4.7.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-admin:4.8.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:4.7.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-auth:4.8.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:4.7.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-desk:4.8.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:4.7.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-develop:4.8.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:4.7.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-gateway:4.8.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:4.7.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-log:4.8.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:4.7.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-report:4.8.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:4.7.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-resource:4.8.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:4.7.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-system:4.8.0'
args:
- '--spring.profiles.active=${PROFILE}'
- '--spring.cloud.nacos.config.server-addr=${NACOS_SERVER_ADDR}'
@ -2262,7 +2262,7 @@ spec:
spec:
containers:
- name: saber-web
image: 'swr.cn-east-2.myhuaweicloud.com/blade/saber-web:4.7.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/saber-web:4.8.0'
ports:
- name: web
containerPort: 80
@ -2487,7 +2487,7 @@ spec:
spec:
containers:
- name: blade-swagger
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-swagger:4.7.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/blade-swagger:4.8.0'
args:
- '--spring.profiles.active=${PROFILE}'
- '--spring.cloud.nacos.config.server-addr=${NACOS_SERVER_ADDR}'
@ -3515,7 +3515,7 @@ spec:
spec:
containers:
- name: mysql
image: 'swr.cn-east-2.myhuaweicloud.com/blade/saber-db:v4.7.0'
image: 'swr.cn-east-2.myhuaweicloud.com/blade/saber-db:v4.8.0'
ports:
- name: mysql
containerPort: 3306