Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
299bec29e0 | ||
|
|
86bb9c2f2a | ||
|
|
121b6653ab | ||
|
|
9fc3990411 | ||
|
|
7a53390946 | ||
|
|
2e8a930b16 | ||
|
|
444c288079 | ||
|
|
669c8261f5 | ||
|
|
2b752f56e1 | ||
|
|
9b8858999c | ||
|
|
548919485c | ||
|
|
464ee5c738 | ||
|
|
623599998f | ||
|
|
37ba418f87 | ||
|
|
affcfb9234 | ||
|
|
add6362fb8 | ||
|
|
ea85ff64e1 | ||
|
|
f5ff5e4f54 | ||
|
|
2183f2d2f6 | ||
|
|
4e477d86c3 | ||
|
|
284eb0394d | ||
|
|
8e56270cf5 | ||
|
|
6b0c4bea49 | ||
|
|
9edd1c3e00 | ||
|
|
3f0cf9af78 | ||
|
|
ad8636ced0 | ||
|
|
03486448f1 | ||
|
|
5925263443 | ||
|
|
dc7cc0bd79 | ||
|
|
a805e90911 | ||
|
|
9225973cf8 | ||
|
|
3243a4b4e3 | ||
|
|
fd45c67416 | ||
|
|
75025818f5 | ||
|
|
0e954b2d1d | ||
|
|
07c840a55b | ||
|
|
55b7ffcb70 | ||
|
|
4594373799 | ||
|
|
df38332a7f | ||
|
|
ab4aa2f493 | ||
|
|
863ca9120c | ||
|
|
ebeca48061 | ||
|
|
7c21c9ceb4 | ||
|
|
49393ec3aa | ||
|
|
2cf2f7be5c | ||
|
|
02b79a1060 | ||
|
|
4bfe209ec0 | ||
|
|
a222ecd50d | ||
|
|
bdc48ac634 | ||
|
|
3947e6eca3 | ||
|
|
b4dccc642c | ||
|
|
7747c1b4bc | ||
|
|
46a0398a98 | ||
|
|
c129fa6191 | ||
|
|
aebe1b8cbb | ||
|
|
91e8dcb740 | ||
|
|
c26a528e8c | ||
|
|
96fcf8d447 | ||
|
|
0773c9275c | ||
|
|
907765831a | ||
|
|
d99350bdfb | ||
|
|
79bfc632a8 | ||
|
|
18f204936d | ||
|
|
874e2fd109 | ||
|
|
0448572932 | ||
|
|
e4185aea04 | ||
|
|
d8b5d0d345 | ||
|
|
f8cce152bc | ||
|
|
50debdd64b |
No files matched your search
@@ -45,7 +45,6 @@ buildNumber.properties
|
||||
####################### svn ##############################
|
||||
.svn
|
||||
|
||||
|
||||
####################### eclipse ##############################
|
||||
.project
|
||||
.settings
|
||||
|
||||
+6
-7
@@ -1,11 +1,10 @@
|
||||
FROM openjdk:8-jdk-alpine
|
||||
MAINTAINER crabc <creabc@qq.com>
|
||||
FROM eclipse-temurin:21-jdk-alpine
|
||||
LABEL version="4.0.0"
|
||||
|
||||
ADD crabc-admin.jar /app.jar
|
||||
COPY crabc-admin.jar /app.jar
|
||||
ENV LANG="en_US.UTF-8"
|
||||
EXPOSE 9377
|
||||
ENV db_url ${db_url}
|
||||
ENV db_user ${db_user}
|
||||
ENV db_pwd ${db_pwd}
|
||||
|
||||
CMD java -jar /app.jar --spring.datasource.url=${db_url} --spring.datasource.username=${db_user} --spring.datasource.password=${db_pwd}
|
||||
ENV DB_URL=${db_url} DB_USER=${db_user} DB_PWD=${db_pwd}
|
||||
|
||||
CMD ["java", "-jar", "/app.jar", "--spring.datasource.url=${DB_URL}", "--spring.datasource.username=${DB_USER}", "--spring.datasource.password=${DB_PWD}"]
|
||||
@@ -1,19 +1,25 @@
|
||||
|
||||
## 介绍
|
||||
**Crabc** 是低代码接口开发平台,企业级API管理系统,深度整合SpringBoot和Mybatis实现动态数据源和动态SQL。
|
||||
支持接入(mysql、oracle、postgresql、sqlserver、达梦、TiDB、es)等SQL或/NoSQL数据源,
|
||||
在编辑框内编写好SQL后即可快速生成Rest接口对外提供服务。支持Mybatis中if等标签语法、数据脱敏、
|
||||
以及复杂的多SQL执行并支持事务, 减少通用接口的SQL编写,让开发人员专注更复杂的业务逻辑实现。可通过插件的
|
||||
方式扩展支持其他的数据源。
|
||||
# 由来
|
||||
crabc由create + abc 组合而来,意在为项目系统构建的通用的接口底座。
|
||||
|
||||
# 介绍
|
||||
**crabc** 是接口快速开发平台,企业数据服务平台,sql2Api,深度整合SpringBoot和Mybatis实现动态数据源和动态SQL、函数和存储过程。
|
||||
支持接入(mysql、oracle、postgresql、sqlserver、达梦、TiDB、es和hive)等SQL或/NoSQL数据源,
|
||||
在线可视化编写SQL后即可快速生成接口对外提供服务,接口一键上下线。减少通用接口的SQL编写,让开发人员专注更复杂的业务逻辑实现。
|
||||
支持Mybatis中if等标签语法、数据脱敏、数据转换、国密加密、协同开发等功能,可集成微服务网关支持接入第三方接口、权限认证、限流、缓存、告警监控和统一日志等一站式API数据服务,
|
||||
助力于企业数据资产价值升级,成为企业数字化转型的重要推动力。
|
||||
|
||||

|
||||
## 功能
|
||||
- **工作台**:可视化编写SQL快速的对外发布成API接口,支持多SQL同时执行、Mybatis标签语法,实现动态SQL和动态标签
|
||||
- **数据源管理**:动态加载数据库,支持多种SQL/NoSQL数据库。
|
||||
- **应用列表**:Code认证、签名认证的应用创建管理以及对API调用在线授权。
|
||||
- **应用列表**:AppKey认证、签名认证的应用创建管理以及对API调用在线授权。
|
||||
- **接口列表**:查看开发中和已发布的API接口,可进行上下线管理,编辑升级等
|
||||
- **接口文档**:生成在线接口文档,支持在线测试。
|
||||
- **接口日志**:查看发布的接口被调用日志列表和请求详情。
|
||||
- **流控规则**:限流、缓存等。
|
||||
|
||||
## 接口开发流程
|
||||

|
||||
## 模块
|
||||
~~~
|
||||
cn.crabc
|
||||
@@ -27,10 +33,19 @@ cn.crabc
|
||||
├── db // SQL脚本
|
||||
├──pom.xml // 依赖
|
||||
~~~
|
||||
|
||||
## 数据库脚本
|
||||
数据库脚本文件可加QQ群文件中获取
|
||||
|
||||
## 版本说明
|
||||
dev分支框架SpringBoot已升级至3.x,jdk需17及以上版本 \
|
||||
dev分支框架SpringBoot已升级至3.5,jdk需17及以上版本 \
|
||||
2.x分支框架SpringBoot还是2.x
|
||||
|
||||
## 企业版
|
||||
https://pingapi.cn
|
||||
|
||||
## 企业版架构图
|
||||
|
||||
## 运行启动
|
||||
```
|
||||
1、先执行db/dml.sql脚本,创建库表和初始化数据
|
||||
@@ -48,9 +63,6 @@ github:https://github.com/pingapi/crabc-api
|
||||
已申请软件著作,开源版仅供个人学习使用 \
|
||||
企业版功能更强大,商用请加群联系\
|
||||
|
||||
## 企业版和开源版对比
|
||||
功能对比清单:https://www.crabc.cn/business/
|
||||
|
||||
## 源码地址
|
||||
github: https://github.com/pingapi/crabc-api \
|
||||
gitee: https://gitee.com/linebyte/crabc
|
||||
@@ -61,7 +73,7 @@ gitee: https://gitee.com/linebyte/crabc
|
||||
<dependency>
|
||||
<groupId>cn.crabc</groupId>
|
||||
<artifactId>crabc-spring-boot-starter</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>4.0.0</version>
|
||||
</dependency>
|
||||
```
|
||||
在程序启动类中添加下面注解
|
||||
@@ -72,13 +84,24 @@ gitee: https://gitee.com/linebyte/crabc
|
||||
|
||||
## Docker启动
|
||||
先执行db/dml.sql脚本,创建库表和初始化数据,建议mysql 8.0+版本
|
||||
|
||||
X86/AMD架构
|
||||
```
|
||||
docker pull crabc/crabc-admin:latest
|
||||
docker run -p 9377:9377 --env db_url=jdbc连接(如:jdbc:mysql://localhost:3306/crabc) --env db_user=数据库用户 --env db_pwd=数据库密码 -d --name crabc-admin crabc/crabc-admin:latest
|
||||
docker run -p 9377:9377 -e DB_URL=jdbc:mysql://localhost:3306/crabc -e DB_USER=root -e DB_PWD=root -d --name crabc-api crabc/crabc-api:latest
|
||||
```
|
||||
ARM架构
|
||||
```
|
||||
docker run -p 9377:9377 -e DB_URL=jdbc:mysql://localhost:3306/crabc -e DB_USER=root -e DB_PWD=root -d --name crabc-admin crabc/crabc-admin:latest
|
||||
```
|
||||
访问地址:http://127.0.0.1:9377
|
||||
账号密码:admin/admin123
|
||||
|
||||
_## Windows桌面运行
|
||||
先执行db/dml.sql脚本,创建库表和初始化数据,建议mysql 8.0+版本
|
||||
```
|
||||
java -jar crabc-api.jar --spring.datasource.url=jdbc:mysql://127.0.0.1:3306/crabc --spring.datasource.username=root --spring.datasource.password=root
|
||||
```
|
||||
|
||||
## 效果截图
|
||||
### 接口开发
|
||||

|
||||
@@ -88,27 +111,63 @@ docker run -p 9377:9377 --env db_url=jdbc连接(如:jdbc:mysql://localhost:330
|
||||

|
||||
#### 在线预览
|
||||

|
||||
#### 接口列表
|
||||

|
||||
#### 接口列表
|
||||

|
||||
#### 数据库类型
|
||||

|
||||
### 限流熔断
|
||||

|
||||
|
||||
## 交流群
|
||||
**进群前请先点【Star】谢谢**
|
||||
|
||||
QQ群(请先Star):748993036
|
||||
|
||||
商用咨询加微信 (请备注crabc)
|
||||
|
||||

|
||||
|
||||
## 产品使用登记
|
||||
以下为部分接入crabc-api的用户 ,<a href="https://gitee.com/linebyte/crabc/issues/IA98CA" target="_blank"> 点击进行登记</a>
|
||||
|
||||
| 公司机构 |
|
||||
|:-------------------|
|
||||
| 联通集团西部分公司 |
|
||||
| 青岛巴士科技有限公司 |
|
||||
| 阳光智维科技股份有限公司 |
|
||||
| 一步数据科技有限公司 |
|
||||
| 成都像素云图科技有限公司 |
|
||||
| 公司机构 |
|
||||
|:-------------|
|
||||
| 西部通信研究院 |
|
||||
| 青岛巴士科技有限公司 |
|
||||
| 阳光智维科技股份有限公司 |
|
||||
| 一步数据科技有限公司 |
|
||||
| 像素云图科技有限公司 |
|
||||
| 前景科技有限公司 |
|
||||
| 方寸图信息有限公司 |
|
||||
| 鹭栖技术信息公司 |
|
||||
| 循脉医疗科技有限公司 |
|
||||
| 云上贵州大数据有限公司 |
|
||||
| 巨元瀚洋有限公司 |
|
||||
|
||||
|
||||
## 交流群
|
||||
**进群前请先点 Star**
|
||||
|
||||
加微信进群 (备注crabc)
|
||||

|
||||
## 企业版和开源版对比
|
||||
| 功能 | 社区版 | 企业版 |
|
||||
|--------|------------------------------|-----------------------------------------------------------------------------------------------------------------------------|
|
||||
| 架构设计 | 单体 | 微服务 |
|
||||
| 接口创建模式 | SQL脚本 | SQL脚本、图表、接口转发 |
|
||||
| 动态标签 | 支持 | 支持 |
|
||||
| 动态路由 | 不支持 | 支持 |
|
||||
| 数据库 | SQL:mysql/oracle/postgresql/sqlserver <br>TiDB/OpenGauss/Doris | SQL:mysql/oracle/postgresql/sqlserver/tidb<br>/opengauss/doris/oceanbase/dm/gbase <br> NoSQL:es/mongodb <br> TSDB: TDengine |
|
||||
| 认证方式 | 无/Code认证/签名认证 | 无/Code认证/签名认证 |
|
||||
| SQL类型 | 查询SQL | 查询/插入/更新/删除等SQL |
|
||||
| 结果类型 | json | json/Excel |
|
||||
| 接口日志 | 支持 | 支持 |
|
||||
| 数据模型 | 不支持 | 支持 |
|
||||
| 协同开发 | 不支持 | 支持 |
|
||||
| 结果转换 | 不支持 | 支持 |
|
||||
| 接口市场 | 不支持 | 支持 |
|
||||
| 申请审批 | 不支持 | 支持 |
|
||||
| 接口授权 | 不支持 | 支持 |
|
||||
| 系统权限 | 不支持 | 支持 |
|
||||
| 用户管理 | 不支持 | 支持 |
|
||||
| 数据脱敏 | 不支持 | 支持 |
|
||||
| 版本管理 | 不支持 | 支持
|
||||
| 接口缓存 | 不支持 | 支持 |
|
||||
| 限流熔断 | 不支持 | 支持 |
|
||||
| IP控制 | 不支持 | 支持 |
|
||||
| 监控报表 | 支持 | 支持 |
|
||||
| 集群模式 | 不支持 | 支持 |
|
||||
@@ -5,14 +5,14 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cn.crabc</groupId>
|
||||
<artifactId>crabc-boot</artifactId>
|
||||
<artifactId>crabc-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>crabc-admin</artifactId>
|
||||
<properties>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
@@ -37,6 +37,16 @@
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<compilerArgs>
|
||||
<arg>-parameters</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
File renamed without changes.
+2
-12
@@ -13,7 +13,7 @@ spring:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
url: jdbc:mysql://127.0.0.1:3306/crabc?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: root
|
||||
password:
|
||||
# mybatis配置
|
||||
mybatis:
|
||||
# 搜索指定包别名
|
||||
@@ -25,14 +25,4 @@ mybatis:
|
||||
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
|
||||
pagehelper:
|
||||
autoRuntimeDialect: true # 开启多数据源分页识别
|
||||
|
||||
# es健康检查
|
||||
management:
|
||||
health:
|
||||
elasticsearch:
|
||||
enabled: false
|
||||
# 签名认证过期时间
|
||||
crabc:
|
||||
auth:
|
||||
expiresTime: 10
|
||||
autoRuntimeDialect: true # 开启多数据源分页识别
|
||||
File renamed without changes.
File renamed without changes.
@@ -3,7 +3,7 @@
|
||||
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>crabc-boot</artifactId>
|
||||
<artifactId>crabc-api</artifactId>
|
||||
<groupId>cn.crabc</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
@@ -12,8 +12,8 @@
|
||||
<artifactId>crabc-core</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -59,5 +59,17 @@
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<!-- Lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk18on</artifactId>
|
||||
<version>${jdk18on.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
package cn.crabc.core.app.api;
|
||||
|
||||
import cn.crabc.core.app.entity.BaseApiParam;
|
||||
import cn.crabc.core.app.entity.dto.ApiInfoDTO;
|
||||
import cn.crabc.core.app.enums.ResultTypeEnum;
|
||||
import cn.crabc.core.app.service.core.IBaseDataService;
|
||||
import cn.crabc.core.app.util.ApiThreadLocal;
|
||||
import cn.crabc.core.app.util.Result;
|
||||
import cn.crabc.core.datasource.constant.BaseConstant;
|
||||
import cn.crabc.core.datasource.enums.ErrorStatusEnum;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* API 接收处理层
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/web")
|
||||
public class ApiServiceController {
|
||||
|
||||
@Autowired
|
||||
private IBaseDataService baseDataService;
|
||||
|
||||
/**
|
||||
* API GET请求方法
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/**", method = {RequestMethod.GET, RequestMethod.DELETE})
|
||||
public Result getService(@RequestParam(required = false) Map<String, Object> paramMap, HttpServletResponse response) {
|
||||
ApiInfoDTO api = ApiThreadLocal.get();
|
||||
if (api == null) {
|
||||
response.setStatus(400);
|
||||
return Result.error(ErrorStatusEnum.API_INVALID.getCode(), ErrorStatusEnum.API_INVALID.getMassage());
|
||||
}
|
||||
|
||||
// 参数校验
|
||||
if (!validateParams(api, paramMap)) {
|
||||
response.setStatus(400);
|
||||
return Result.error(ErrorStatusEnum.PARAM_NOT_FOUNT.getCode(), ErrorStatusEnum.PARAM_NOT_FOUNT.getMassage());
|
||||
}
|
||||
|
||||
return executeApi(api, paramMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* API post请求
|
||||
*
|
||||
* @param paramMap
|
||||
* @param body
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/**", method = {RequestMethod.POST, RequestMethod.PUT})
|
||||
public Result postService(@RequestParam(required = false) Map<String, Object> paramMap, @RequestBody(required = false) Object body, HttpServletResponse response) {
|
||||
ApiInfoDTO api = ApiThreadLocal.get();
|
||||
if (api == null) {
|
||||
response.setStatus(400);
|
||||
return Result.error(ErrorStatusEnum.API_INVALID.getCode(), ErrorStatusEnum.API_INVALID.getMassage());
|
||||
}
|
||||
|
||||
// 合并请求参数
|
||||
Map<String, Object> mergedParams = mergeParams(paramMap, body);
|
||||
|
||||
// 参数校验
|
||||
if (!checkParams(api.getRequestParams(), mergedParams)) {
|
||||
response.setStatus(400);
|
||||
return Result.error(ErrorStatusEnum.PARAM_NOT_FOUNT.getCode(), ErrorStatusEnum.PARAM_NOT_FOUNT.getMassage());
|
||||
}
|
||||
|
||||
mergedParams.put(BaseConstant.PAGE_SETUP, api.getPageSetup());
|
||||
return executeApi(api, mergedParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验参数
|
||||
*
|
||||
* @param apiParams
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
public boolean checkParams(List<BaseApiParam> apiParams, Map<String, Object> paramMap) {
|
||||
if (apiParams == null || paramMap == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (BaseApiParam param : apiParams) {
|
||||
String paramName = param.getParamName();
|
||||
String paramType = param.getParamType();
|
||||
Object value = paramMap.get(paramName);
|
||||
|
||||
// 必填参数校验
|
||||
if ("Y".equals(param.getRequired()) && !paramMap.containsKey(paramName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Array类型参数处理
|
||||
if ("Array".equalsIgnoreCase(paramType)) {
|
||||
if (value == null || "".equals(value)) {
|
||||
return false;
|
||||
}
|
||||
String[] values = value.toString().split(",");
|
||||
paramMap.put(paramName, Arrays.asList(values));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证请求参数
|
||||
*/
|
||||
private boolean validateParams(ApiInfoDTO api, Map<String, Object> paramMap) {
|
||||
if (paramMap == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
paramMap.put(BaseConstant.PAGE_SETUP, api.getPageSetup() == null ? 0 : api.getPageSetup());
|
||||
|
||||
return checkParams(api.getRequestParams(), paramMap) &&
|
||||
!(api.getPageSetup() == 1 && !paramMap.containsKey(BaseConstant.PAGE_NUM));
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并请求参数
|
||||
*/
|
||||
private Map<String, Object> mergeParams(Map<String, Object> paramMap, Object body) {
|
||||
Map<String, Object> mergedParams = new HashMap<>();
|
||||
if (paramMap != null) {
|
||||
mergedParams.putAll(paramMap);
|
||||
}
|
||||
if (body instanceof Map) {
|
||||
mergedParams.putAll((Map<String, Object>) body);
|
||||
}
|
||||
return mergedParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行API调用
|
||||
*/
|
||||
private Result executeApi(ApiInfoDTO api, Map<String, Object> params) {
|
||||
Object data = baseDataService.execute(api.getDatasourceId().toString(), api.getDatasourceType(),
|
||||
api.getSchemaName(), api.getSqlScript(), params);
|
||||
|
||||
if (ResultTypeEnum.ONE.getName().equals(api.getResultType()) && data instanceof List) {
|
||||
List<Object> list = (List<Object>) data;
|
||||
return Result.success(list.isEmpty() ? null : list.get(0));
|
||||
}
|
||||
return Result.success(data);
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,34 @@
|
||||
package cn.crabc.core.app.config;
|
||||
|
||||
import cn.crabc.core.app.service.system.IBaseApiInfoService;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 加载数据
|
||||
*/
|
||||
@Component
|
||||
public class LoadingData implements InitializingBean {
|
||||
@Autowired
|
||||
private IBaseApiInfoService iBaseApiInfoService;
|
||||
|
||||
/**
|
||||
* 启动加载
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
iBaseApiInfoService.initApi();
|
||||
}
|
||||
|
||||
/**
|
||||
* 定时加载
|
||||
*/
|
||||
@Scheduled(cron = "${crabc.corn.api:0 0/5 * * * ?}") // 每5分钟全量加载一次
|
||||
public void task() {
|
||||
iBaseApiInfoService.initApi();
|
||||
}
|
||||
|
||||
}
|
||||
File renamed without changes.
+38
-43
@@ -122,6 +122,16 @@ public class ApiInfoController {
|
||||
return Result.success(apiInfoService.deleteApi(apiId, UserThreadLocal.getUserId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁发布接口
|
||||
* @param apiId
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping("/destroy/{apiId}")
|
||||
public Result destroy(@PathVariable Long apiId) {
|
||||
apiInfoService.destroyApiInfo(apiId);
|
||||
return Result.success();
|
||||
}
|
||||
/**
|
||||
* SQL解析
|
||||
*
|
||||
@@ -132,63 +142,48 @@ public class ApiInfoController {
|
||||
public Result sqlParse(@RequestBody SqlParseVO sqlParse) {
|
||||
SqlParseVO sqlParseVO = new SqlParseVO();
|
||||
String sql = sqlParse.getSqlScript();
|
||||
|
||||
// 去除末尾分号
|
||||
if (sql.endsWith(";")) {
|
||||
sql = sql.substring(0, sql.lastIndexOf(";"));
|
||||
}
|
||||
// 对</foreach>标签取值特殊处理
|
||||
Set<String> fields = new HashSet<>();
|
||||
|
||||
// 收集所有请求参数
|
||||
Set<String> paramNames = new HashSet<>();
|
||||
|
||||
// 解析foreach标签中的collection参数
|
||||
if (sql.contains("</foreach>")) {
|
||||
String regex = "collection='(.*?)'";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matcher = pattern.matcher(sql);
|
||||
while (matcher.find()) {
|
||||
String field = matcher.group(1);
|
||||
fields.add(field);
|
||||
}
|
||||
paramNames.addAll(SQLUtil.extractForeachParams(sql));
|
||||
}
|
||||
// 提取if标签里面的请求参数
|
||||
|
||||
// 解析if/when标签中的test条件参数
|
||||
if (sql.contains("<if ") || sql.contains("<when ")) {
|
||||
String regex = " test=['\"](\\w+)\\s*(?:!=|>=|<=|==|<|>|<|<=|>|>=)";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matcher = pattern.matcher(sql);
|
||||
while (matcher.find()) {
|
||||
String field = matcher.group(1);
|
||||
fields.add(field);
|
||||
}
|
||||
}
|
||||
String forRegex = "<foreach[\\s\\S]*?</foreach>";
|
||||
sql = sql.replaceAll(forRegex,"()");
|
||||
// 条件字段
|
||||
Set<String> paramNames = SQLUtil.parseParams(sql);
|
||||
if (!fields.isEmpty()) {
|
||||
paramNames.addAll(fields);
|
||||
paramNames.addAll(SQLUtil.extractIfParams(sql));
|
||||
}
|
||||
|
||||
// 移除foreach标签内容
|
||||
sql = sql.replaceAll("<foreach[\\s\\S]*?</foreach>", "()");
|
||||
|
||||
// 解析SQL中的参数
|
||||
paramNames.addAll(SQLUtil.parseParams(sql));
|
||||
sqlParseVO.setReqColumns(paramNames);
|
||||
// 返回字段
|
||||
|
||||
// 过滤SQL并补全条件
|
||||
sql = SQLUtil.sqlFilter(sql);
|
||||
// 判断去除标签后的 sql是否正确,自动补全条件
|
||||
if (sql.trim().toLowerCase().endsWith("from")) {
|
||||
sql = sql +" test ";
|
||||
}else if (sql.trim().toLowerCase().endsWith("where")) {
|
||||
sql = sql +" 1=1 ";
|
||||
}
|
||||
sql = SQLUtil.completeSql(sql);
|
||||
|
||||
// 解析返回字段
|
||||
Set<ColumnParseVo> resColumns = new HashSet<>();
|
||||
Set<String> resNames = SQLUtil.analyzeSQL(sql.trim(), sqlParse.getDatasourceType());
|
||||
if (resNames.isEmpty()){
|
||||
sql = SQLUtil.checkTable(sql, " test ");
|
||||
resNames = SQLUtil.analyzeSQL(sql.trim(), sqlParse.getDatasourceType());
|
||||
}
|
||||
Set<String> resNames = SQLUtil.parseResultColumns(sql, sqlParse.getDatasourceType());
|
||||
|
||||
// 构建返回字段信息
|
||||
for (String name : resNames) {
|
||||
if (name.startsWith("*")){
|
||||
continue;
|
||||
if (!name.startsWith("*")) {
|
||||
resColumns.add(SQLUtil.buildColumnInfo(name));
|
||||
}
|
||||
ColumnParseVo resColumn = new ColumnParseVo();
|
||||
resColumn.setColName(name);
|
||||
resColumn.setColType("String");
|
||||
resColumn.setItemIndex(0);
|
||||
resColumns.add(resColumn);
|
||||
}
|
||||
sqlParseVO.setResColumns(resColumns);
|
||||
|
||||
return Result.success(sqlParseVO);
|
||||
}
|
||||
|
||||
File renamed without changes.
+152
@@ -0,0 +1,152 @@
|
||||
package cn.crabc.core.app.controller;
|
||||
|
||||
import cn.crabc.core.app.entity.param.ApiTestParam;
|
||||
import cn.crabc.core.app.entity.vo.PreviewVO;
|
||||
import cn.crabc.core.app.enums.ResultTypeEnum;
|
||||
import cn.crabc.core.app.service.core.IBaseDataService;
|
||||
import cn.crabc.core.app.util.Result;
|
||||
import cn.crabc.core.datasource.enums.ErrorStatusEnum;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* API运行和测试
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/box/sys/test")
|
||||
public class ApiTestController {
|
||||
|
||||
@Autowired
|
||||
private IBaseDataService baseDataService;
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* 运行预览
|
||||
*
|
||||
* @param api
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/running")
|
||||
public Result runApiSql(@RequestBody ApiTestParam api) {
|
||||
if (api.getDatasourceId() == null) {
|
||||
return Result.error(ErrorStatusEnum.PARAM_NOT_FOUNT.getCode(), ErrorStatusEnum.PARAM_NOT_FOUNT.getMassage());
|
||||
}
|
||||
PreviewVO previewVO = baseDataService.sqlPreview(api.getDatasourceId(),api.getDatasourceType(), api.getSchemaName(), api.getSqlScript());
|
||||
return Result.success(previewVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在线测试API
|
||||
*
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/verify/{apiId}")
|
||||
public Result testApiSql(@PathVariable Long apiId, @RequestBody ApiTestParam params) throws Exception {
|
||||
// 参数校验
|
||||
if (params.getDatasourceId() == null) {
|
||||
return Result.error(ErrorStatusEnum.PARAM_NOT_FOUNT.getCode(), ErrorStatusEnum.PARAM_NOT_FOUNT.getMassage());
|
||||
}
|
||||
|
||||
// 设置默认数据源类型
|
||||
params.setDatasourceType(params.getDatasourceType() == null ? "mysql" : params.getDatasourceType());
|
||||
|
||||
try {
|
||||
// 构建参数Map
|
||||
Map<String, Object> paramsMap = buildParamsMap(params);
|
||||
|
||||
// 执行SQL
|
||||
Object data = baseDataService.execute(
|
||||
params.getDatasourceId(),
|
||||
params.getDatasourceType(),
|
||||
params.getSchemaName(),
|
||||
params.getSqlScript(),
|
||||
paramsMap
|
||||
);
|
||||
|
||||
// 处理返回结果
|
||||
return Result.success(formatResultData(data, params.getResultType()));
|
||||
|
||||
} catch (Exception e) {
|
||||
return Result.error("测试异常,请检查参数或者SQL是否正常!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建参数Map
|
||||
*/
|
||||
private Map<String, Object> buildParamsMap(ApiTestParam params) throws Exception {
|
||||
Map<String, Object> paramsMap = new HashMap<>();
|
||||
|
||||
// 处理body参数
|
||||
if (params.getBodyData() != null && params.getBodyData().startsWith("{")) {
|
||||
paramsMap = objectMapper.readValue(params.getBodyData(), HashMap.class);
|
||||
}
|
||||
|
||||
// 处理query参数
|
||||
Object requestParams = params.getRequestParams();
|
||||
if (requestParams instanceof Map) {
|
||||
Map<String, Object> queryParam = (Map<String, Object>) requestParams;
|
||||
if (validateParams(queryParam)) {
|
||||
paramsMap.putAll(queryParam);
|
||||
} else {
|
||||
throw new IllegalArgumentException("参数校验失败");
|
||||
}
|
||||
paramsMap.put("pageSetup", params.getPageSetup());
|
||||
} else if (requestParams instanceof List) {
|
||||
List<Map<String,Object>> paramsList = (List<Map<String, Object>>) requestParams;
|
||||
for (Map<String, Object> entry : paramsList) {
|
||||
if (validateParams(entry)) {
|
||||
paramsMap.put(entry.get("name").toString(), entry.get("value"));
|
||||
} else {
|
||||
throw new IllegalArgumentException("参数校验失败");
|
||||
}
|
||||
}
|
||||
if (paramsList.isEmpty()) {
|
||||
paramsMap.put("pageSetup", params.getPageSetup());
|
||||
}
|
||||
}
|
||||
return paramsMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化返回数据
|
||||
*/
|
||||
private String formatResultData(Object data, String resultType) throws Exception {
|
||||
if (ResultTypeEnum.ONE.getName().equals(resultType) && data instanceof List) {
|
||||
List<Object> list = (List<Object>) data;
|
||||
return objectMapper.writeValueAsString(Result.success(list.isEmpty() ? null : list.get(0)));
|
||||
}
|
||||
return objectMapper.writeValueAsString(Result.success(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并处理参数
|
||||
*/
|
||||
private boolean validateParams(Map<String, Object> params) {
|
||||
if (params == null || params.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String paramType = String.valueOf(params.get("paramType"));
|
||||
Object paramValue = params.get("value");
|
||||
|
||||
if ("Array".equalsIgnoreCase(paramType)) {
|
||||
if (paramValue == null || "".equals(paramValue)) {
|
||||
return false;
|
||||
}
|
||||
String[] values = paramValue.toString().split(",");
|
||||
params.put("value", Arrays.asList(values));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+20
-1
@@ -4,6 +4,8 @@ import cn.crabc.core.app.entity.BaseUser;
|
||||
import cn.crabc.core.app.entity.param.UserParam;
|
||||
import cn.crabc.core.app.service.system.IBaseUserService;
|
||||
import cn.crabc.core.app.util.*;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import org.apache.tomcat.util.codec.binary.Base64;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
@@ -13,6 +15,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -26,7 +29,8 @@ public class SysUserController {
|
||||
@Autowired
|
||||
@Qualifier("dataCache")
|
||||
Cache<String, Object> caffeineCache;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
@@ -75,6 +79,21 @@ public class SysUserController {
|
||||
BaseUser userInfo = iBaseUserService.getUserById(Long.parseLong(UserThreadLocal.getUserId()));
|
||||
return Result.success(userInfo);
|
||||
}
|
||||
/**
|
||||
* 用户菜单
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/menus")
|
||||
public Result userMenus(){
|
||||
// 固定菜单
|
||||
String menus ="[{\"name\":\"API Hub\",\"checked\":null,\"id\":2,\"parentId\":1,\"open\":null,\"path\":null,\"url\":\"/hub\",\"sort\":2,\"menuType\":1,\"code\":\"Home\",\"hidden\":false,\"permission\":\"/api/box/sys/user/info;/api/box/sys/user/menus;/api/box/sys/message/**;/api/box/sys/user/update/pwd\",\"subMenus\":[{\"name\":\"接口详情\",\"checked\":null,\"id\":7,\"parentId\":2,\"open\":null,\"path\":null,\"url\":\"/doc\",\"sort\":6,\"menuType\":1,\"code\":\"DataCatelogApiDetails\",\"hidden\":true,\"permission\":\"doc\",\"subMenus\":[]}]},{\"name\":\"工作台\",\"checked\":null,\"id\":3,\"parentId\":1,\"open\":null,\"path\":null,\"url\":\"/working\",\"sort\":3,\"menuType\":1,\"code\":\"DataService\",\"hidden\":false,\"permission\":\"/api/box/sys/common/**;/api/box/sys/api/info/**;/api/box/sys/metadata/**;/api/box/sys/test/**;/api/box/sys/group/**;/api/box/sys/user/check/name\",\"subMenus\":[]},{\"name\":\"服务台\",\"checked\":null,\"id\":4,\"parentId\":1,\"open\":null,\"path\":null,\"url\":\"/manage\",\"sort\":4,\"menuType\":1,\"code\":\"Manage\",\"hidden\":false,\"permission\":\"manage\",\"subMenus\":[{\"name\":\"应用管理\",\"checked\":null,\"id\":8,\"parentId\":4,\"open\":null,\"path\":null,\"url\":\"/manage/keys\",\"sort\":1,\"menuType\":1,\"code\":\"Application\",\"hidden\":true,\"permission\":\"/api/box/sys/app/**\",\"subMenus\":[]},{\"name\":\"接口列表\",\"checked\":null,\"id\":9,\"parentId\":4,\"open\":null,\"path\":null,\"url\":\"/manage/apis\",\"sort\":1,\"menuType\":1,\"code\":\"MyApi\",\"hidden\":true,\"permission\":\"/api/box/sys/api/info/**\",\"subMenus\":[]},{\"name\":\"日志管理\",\"checked\":null,\"id\":12,\"parentId\":4,\"open\":null,\"path\":null,\"url\":\"/manage/logs\",\"sort\":1,\"menuType\":1,\"code\":\"UseLog\",\"hidden\":true,\"permission\":\"/api/box/sys/api/log/**\",\"subMenus\":[{\"name\":\"日志列表\",\"checked\":null,\"id\":13,\"parentId\":12,\"open\":null,\"path\":null,\"url\":\"/manage/logs/list\",\"sort\":1,\"menuType\":1,\"code\":\"UseLogList\",\"hidden\":true,\"permission\":\"/api/box/sys/api/log/**\",\"subMenus\":[]},{\"name\":\"日志详情\",\"checked\":null,\"id\":14,\"parentId\":12,\"open\":null,\"path\":null,\"url\":\"/manage/logs/detail\",\"sort\":1,\"menuType\":1,\"code\":\"DetailUesLog\",\"hidden\":true,\"permission\":null,\"subMenus\":[]}]},{\"name\":\"分类管理\",\"checked\":null,\"id\":30,\"parentId\":4,\"open\":null,\"path\":null,\"url\":\"/manage/classification\",\"sort\":1,\"menuType\":1,\"code\":\"Classification\",\"hidden\":true,\"permission\":\"manage:classification\",\"subMenus\":[]},{\"name\":\"数据源\",\"checked\":null,\"id\":31,\"parentId\":4,\"open\":null,\"path\":null,\"url\":\"/manage/datasource\",\"sort\":1,\"menuType\":1,\"code\":\"DataSource\",\"hidden\":true,\"permission\":\"/api/box/sys/datasource/**;/api/box/sys/user/pubKey\",\"subMenus\":[]},{\"name\":\"密码重置\",\"checked\":null,\"id\":32,\"parentId\":4,\"open\":null,\"path\":null,\"url\":\"/manage/edit-pwd\",\"sort\":1,\"menuType\":1,\"code\":\"ChangePassword\",\"hidden\":true,\"permission\":\"/api/box/sys/user/update/pwd\",\"subMenus\":[]}]}]";
|
||||
try {
|
||||
List<Map<String, Object>> list = objectMapper.readValue(menus, List.class);
|
||||
return Result.success(list);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
package cn.crabc.core.app.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* API基本信息
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class BaseApiInfo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* api业务唯一ID
|
||||
*/
|
||||
private Long apiId;
|
||||
/**
|
||||
* 接口名称
|
||||
*/
|
||||
private String apiName;
|
||||
/**
|
||||
* 接口路径
|
||||
*/
|
||||
private String apiPath;
|
||||
/**
|
||||
* 请求方式 get、post、put、delete、aptch
|
||||
*/
|
||||
private String apiMethod;
|
||||
/**
|
||||
* API类型:sql、table
|
||||
*/
|
||||
private String apiType;
|
||||
/**
|
||||
* 授权类型:none、code、secret
|
||||
*/
|
||||
private String authType;
|
||||
/**
|
||||
* 接口状态:编辑edit、审批audit、发布release、销毁destroy
|
||||
*/
|
||||
private String apiStatus;
|
||||
|
||||
/**
|
||||
* 开放启用 1/0
|
||||
*/
|
||||
private Integer enabled;
|
||||
/**
|
||||
* 分组ID
|
||||
*/
|
||||
private Integer groupId;
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
private String tenantId;
|
||||
|
||||
/**
|
||||
* API描述
|
||||
*/
|
||||
private String remarks;
|
||||
|
||||
/**
|
||||
* 版本
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* sql类型,select、insert、update、delete
|
||||
*/
|
||||
private String sqlType;
|
||||
/**
|
||||
* 返回结果类型:one、array、excel
|
||||
*
|
||||
*/
|
||||
private String resultType;
|
||||
/**
|
||||
* sql语句脚本
|
||||
*/
|
||||
private String sqlScript;
|
||||
|
||||
/**
|
||||
* 是否显示脚本1/0
|
||||
*/
|
||||
private String showSqlScript;
|
||||
|
||||
/**
|
||||
* 分页设置,不分页:0、只分页:page、分页并统计:pageCount
|
||||
*/
|
||||
private Integer pageSetup;
|
||||
|
||||
/**
|
||||
* 数据源Id
|
||||
*/
|
||||
private Integer datasourceId;
|
||||
|
||||
/**
|
||||
* 数据源名称
|
||||
*/
|
||||
private String datasourceName;
|
||||
|
||||
/**
|
||||
* schema
|
||||
*/
|
||||
private String schemaName;
|
||||
|
||||
/**
|
||||
* 数据源类型
|
||||
*/
|
||||
private String datasourceType;
|
||||
|
||||
/**
|
||||
* 发布时间
|
||||
*/
|
||||
private Date releaseTime;
|
||||
|
||||
/**
|
||||
* 父级关联ID
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/** 分组名称 */
|
||||
private String groupName;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package cn.crabc.core.app.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* api访问日志
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class BaseApiLog implements Serializable {
|
||||
|
||||
private Long logId;
|
||||
/**
|
||||
* api业务唯一ID
|
||||
*/
|
||||
private Long apiId;
|
||||
/**
|
||||
* 接口名称
|
||||
*/
|
||||
private String apiName;
|
||||
/**
|
||||
* 接口路径
|
||||
*/
|
||||
private String apiPath;
|
||||
/**
|
||||
* 请求方式 get、post、put、delete、aptch
|
||||
*/
|
||||
private String apiMethod;
|
||||
/**
|
||||
* 授权类型:none、code、secret
|
||||
*/
|
||||
private String authType;
|
||||
private String appName;
|
||||
private String requestIp;
|
||||
private String queryParam;
|
||||
private String requestBody;
|
||||
private String responseBody;
|
||||
private Integer bodySize;
|
||||
private String requestStatus;
|
||||
private Date requestTime;
|
||||
private Date responseTime;
|
||||
private Long costTime;
|
||||
private Integer responseCode;
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
package cn.crabc.core.app.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* API参数
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class BaseApiParam {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 自增主键ID
|
||||
*/
|
||||
private Long paramId;
|
||||
|
||||
/** api主键 */
|
||||
private Long apiId;
|
||||
|
||||
/**
|
||||
* 参数名
|
||||
*/
|
||||
private String paramName;
|
||||
|
||||
/**
|
||||
* 映射字段名
|
||||
*/
|
||||
private String columnName;
|
||||
|
||||
/**
|
||||
* 参数模型,request,response
|
||||
*/
|
||||
private String paramModel;
|
||||
|
||||
/**
|
||||
* 是否必填
|
||||
*/
|
||||
private String required;
|
||||
|
||||
/**
|
||||
* 操作
|
||||
*/
|
||||
private String operation;
|
||||
|
||||
/**
|
||||
* 参数类型
|
||||
*/
|
||||
private String paramType;
|
||||
|
||||
/**
|
||||
* 参数默认值
|
||||
*/
|
||||
private String defaultValue;
|
||||
|
||||
/**
|
||||
* 参数示例值
|
||||
*/
|
||||
private String example;
|
||||
|
||||
/**
|
||||
* 参数备注
|
||||
*/
|
||||
private String paramDesc;
|
||||
|
||||
/**
|
||||
* 数据源Id
|
||||
*/
|
||||
private Integer datasourceId;
|
||||
|
||||
/**
|
||||
* schema
|
||||
*/
|
||||
private String schemaName;
|
||||
|
||||
/**
|
||||
* 表名
|
||||
*/
|
||||
private String tableName;
|
||||
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package cn.crabc.core.app.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* API SQL配置
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class BaseApiSql extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 自增主键ID
|
||||
*/
|
||||
private Long sqlId;
|
||||
|
||||
/** api主键 */
|
||||
private Long apiId;
|
||||
|
||||
/**
|
||||
* sql语句脚本
|
||||
*/
|
||||
private String sqlScript;
|
||||
|
||||
/**
|
||||
* 分页设置,不分页:0、只分页:page、分页并统计:pageCount
|
||||
*/
|
||||
private Integer pageSetup;
|
||||
|
||||
/**
|
||||
* 数据源Id
|
||||
*/
|
||||
private Integer datasourceId;
|
||||
|
||||
/**
|
||||
* schema
|
||||
*/
|
||||
private String schemaName;
|
||||
|
||||
/**
|
||||
* 数据源类型
|
||||
*/
|
||||
private String datasourceType;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package cn.crabc.core.app.entity;
|
||||
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 应用秘密
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class BaseApp extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 应用ID
|
||||
*/
|
||||
private Long appId;
|
||||
/**
|
||||
* 应用名
|
||||
*/
|
||||
private String appName;
|
||||
/**
|
||||
* 应用描述
|
||||
*/
|
||||
private String appDesc;
|
||||
/**
|
||||
* 认证code
|
||||
*/
|
||||
private String appCode;
|
||||
/**
|
||||
* 密钥ID
|
||||
*/
|
||||
private String appKey;
|
||||
/**
|
||||
* 密钥
|
||||
*/
|
||||
private String appSecret;
|
||||
/**
|
||||
* 策略类型:白名单:white、黑名单black
|
||||
*/
|
||||
private String strategyType;
|
||||
/**
|
||||
* ip地址,分号分割
|
||||
*/
|
||||
private String ips;
|
||||
/**
|
||||
* 状态:1启用,0,禁用
|
||||
*/
|
||||
private Integer enabled;
|
||||
/**
|
||||
* 关联的apiId
|
||||
*/
|
||||
private Long apiId;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package cn.crabc.core.app.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 应用和API关联关系
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class BaseAppApi {
|
||||
|
||||
private Long appId;
|
||||
|
||||
private Long apiId;
|
||||
|
||||
private String createBy;
|
||||
|
||||
private Date createTime;
|
||||
|
||||
private List<Long> apiIds;
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package cn.crabc.core.app.entity;
|
||||
|
||||
import cn.crabc.core.spi.bean.BaseDataSource;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
*
|
||||
* 数据源配置
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@JsonIgnoreProperties(value = {"secretKey"})
|
||||
public class BaseDatasource extends BaseDataSource {
|
||||
|
||||
/**
|
||||
* 租户
|
||||
*/
|
||||
private Integer tenantId;
|
||||
|
||||
private String createBy;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
private String updateBy;
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package cn.crabc.core.app.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 实体类基类
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class BaseEntity implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
private String createBy;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
private String updateBy;
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package cn.crabc.core.app.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* api分组
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class BaseGroup extends BaseEntity{
|
||||
|
||||
private Integer groupId;
|
||||
|
||||
private String groupName;
|
||||
|
||||
private String groupDesc;
|
||||
|
||||
private Integer parentId;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package cn.crabc.core.app.entity;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@JsonIgnoreProperties(value = {"password"})
|
||||
public class BaseUser extends BaseEntity {
|
||||
|
||||
/** 用户ID */
|
||||
private Long userId;
|
||||
|
||||
/** 角色 */
|
||||
private String role;
|
||||
|
||||
/** 用户账号 */
|
||||
private String username;
|
||||
|
||||
/** 用户昵称 */
|
||||
private String nickname;
|
||||
|
||||
/** 用户邮箱 */
|
||||
private String email;
|
||||
|
||||
/** 手机号码 */
|
||||
private String phone;
|
||||
|
||||
/** 用户性别 */
|
||||
private String sex;
|
||||
|
||||
/** 用户头像 */
|
||||
private String picture;
|
||||
|
||||
/** 密码 */
|
||||
private String password;
|
||||
|
||||
/** 帐号状态(0正常 1停用) */
|
||||
private String status;
|
||||
|
||||
private String remark;
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package cn.crabc.core.app.entity.dto;
|
||||
|
||||
import cn.crabc.core.app.entity.BaseApiInfo;
|
||||
import cn.crabc.core.app.entity.BaseApiParam;
|
||||
import cn.crabc.core.app.entity.BaseApp;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* API相关的详情信息
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class ApiInfoDTO extends BaseApiInfo {
|
||||
|
||||
/**
|
||||
* 请求时间
|
||||
*/
|
||||
private Date requestDate;
|
||||
|
||||
private Long requestTime;
|
||||
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* 有权限的应用
|
||||
*/
|
||||
private List<BaseApp> appList = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* API参数
|
||||
*/
|
||||
private List<BaseApiParam> requestParams;
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package cn.crabc.core.app.entity.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 字段信息
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class ColumnDTO implements Serializable {
|
||||
/** 名称 */
|
||||
private String columnName;
|
||||
/** 类型 */
|
||||
private String columnType;
|
||||
/** 别名 */
|
||||
private String alias;
|
||||
/** 操作符 */
|
||||
private String operator;
|
||||
|
||||
private String nullable;
|
||||
|
||||
private String value;
|
||||
|
||||
private String remarks;
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package cn.crabc.core.app.entity.param;
|
||||
|
||||
import cn.crabc.core.app.entity.BaseApiInfo;
|
||||
import cn.crabc.core.app.entity.BaseApiParam;
|
||||
import cn.crabc.core.app.entity.BaseApiSql;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* API请求参数
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class ApiInfoParam {
|
||||
|
||||
/**
|
||||
* 基本信息
|
||||
*/
|
||||
private BaseApiInfo baseInfo;
|
||||
|
||||
/**
|
||||
* sql
|
||||
*/
|
||||
private BaseApiSql sqlInfo;
|
||||
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
private List<BaseApiParam> requestParam;
|
||||
|
||||
/**
|
||||
* 返回参数
|
||||
*/
|
||||
private List<BaseApiParam> responseParam;
|
||||
/**
|
||||
* 查询引擎
|
||||
*/
|
||||
private String queryEngine;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.crabc.core.app.entity.param;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* API日志查询请求参数
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class ApiLogParam {
|
||||
private String result;
|
||||
|
||||
private String keyword;
|
||||
|
||||
private String startTime;
|
||||
|
||||
private String endTime;
|
||||
|
||||
private Integer pageNum;
|
||||
|
||||
private Integer pageSize;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package cn.crabc.core.app.entity.param;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class ApiTestParam {
|
||||
|
||||
private String sqlScript;
|
||||
|
||||
private String datasourceId;
|
||||
|
||||
private String datasourceType;
|
||||
|
||||
private String schemaName;
|
||||
|
||||
private String sqlParams;
|
||||
|
||||
private Integer pageSetup;
|
||||
|
||||
private String resultType;
|
||||
|
||||
private Object requestParams;
|
||||
|
||||
private String bodyData;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.crabc.core.app.entity.param;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 用户请求对象
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class UserParam {
|
||||
|
||||
private Long userId;
|
||||
|
||||
private String username;
|
||||
|
||||
/** 用户昵称 */
|
||||
private String nickname;
|
||||
|
||||
/** 用户邮箱 */
|
||||
private String email;
|
||||
|
||||
/** 手机号码 */
|
||||
private String phone;
|
||||
|
||||
/** 用户性别 */
|
||||
private String sex;
|
||||
|
||||
/** 用户头像 */
|
||||
private String picture;
|
||||
|
||||
/** 密码 */
|
||||
private String password;
|
||||
|
||||
private String newPassword;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.crabc.core.app.entity.vo;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class ApiComboBoxVO {
|
||||
|
||||
private Long apiId;
|
||||
|
||||
private String apiName;
|
||||
|
||||
private String apiType;
|
||||
|
||||
private String apiStatus;
|
||||
|
||||
private Integer groupId;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package cn.crabc.core.app.entity.vo;
|
||||
|
||||
import cn.crabc.core.app.entity.BaseApiInfo;
|
||||
import cn.crabc.core.app.entity.BaseApiParam;
|
||||
import cn.crabc.core.app.entity.BaseApiSql;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* API详情
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class ApiInfoVO {
|
||||
/**
|
||||
* 基本信息
|
||||
*/
|
||||
private BaseApiInfo baseInfo;
|
||||
|
||||
/**
|
||||
* sql
|
||||
*/
|
||||
private BaseApiSql sqlInfo;
|
||||
/**
|
||||
* 查询引擎
|
||||
*/
|
||||
private String queryEngine;
|
||||
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
private List<BaseApiParam> requestParam = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 返回参数
|
||||
*/
|
||||
private List<BaseApiParam> responseParam = new ArrayList<>();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.crabc.core.app.entity.vo;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* api详情参数
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class ApiParamsVO {
|
||||
|
||||
// 请求参数
|
||||
List<RequestParamsVO> reqParams;
|
||||
|
||||
//响应参数
|
||||
List<RequestParamsVO> resParams;
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package cn.crabc.core.app.entity.vo;
|
||||
|
||||
import cn.crabc.core.app.entity.BaseEntity;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* API基本信息
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class BaseApiInfoVO extends BaseEntity {
|
||||
|
||||
/**
|
||||
* api业务唯一ID
|
||||
*/
|
||||
private Long apiId;
|
||||
/**
|
||||
* 接口名称
|
||||
*/
|
||||
private String apiName;
|
||||
/**
|
||||
* 接口路径
|
||||
*/
|
||||
private String apiPath;
|
||||
/**
|
||||
* 请求方式 get、post、put、delete、aptch
|
||||
*/
|
||||
private String apiMethod;
|
||||
/**
|
||||
* API类型:sql、table
|
||||
*/
|
||||
private String apiType;
|
||||
/**
|
||||
* 授权类型:none、code、secret
|
||||
*/
|
||||
private String authType;
|
||||
|
||||
/**
|
||||
* 权限级别:public、default、private
|
||||
*/
|
||||
private String apiLevel;
|
||||
|
||||
/**
|
||||
* 开放启用 1/0
|
||||
*/
|
||||
private Integer enabled;
|
||||
|
||||
/**
|
||||
* API描述
|
||||
*/
|
||||
private String remarks;
|
||||
|
||||
/**
|
||||
* 版本
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* sql类型,select、insert、update、delete
|
||||
*/
|
||||
private String sqlType;
|
||||
|
||||
/**
|
||||
* 分页设置,不分页:0、只分页:page、分页并统计:pageCount
|
||||
*/
|
||||
private Integer pageSetup;
|
||||
|
||||
private String sqlScript;
|
||||
|
||||
private String showSqlScript;
|
||||
/**
|
||||
* 发布时间
|
||||
*/
|
||||
private Date releaseTime;
|
||||
|
||||
private Integer applyed;
|
||||
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,16 @@
|
||||
package cn.crabc.core.app.entity.vo;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class ColumnParseVo {
|
||||
|
||||
private String colName;
|
||||
|
||||
private String colType;
|
||||
|
||||
private Integer itemIndex;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.crabc.core.app.entity.vo;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 分组下的API
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class GroupApiVO implements Serializable {
|
||||
private Integer groupId;
|
||||
private String groupName;
|
||||
private Integer apiId;
|
||||
private String apiName;
|
||||
private Integer parentId;
|
||||
|
||||
private List<GroupApiVO> child = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package cn.crabc.core.app.entity.vo;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class GroupVO {
|
||||
private Integer groupId;
|
||||
private String groupName;
|
||||
private Integer parentId;
|
||||
private List<GroupVO> children;
|
||||
|
||||
}
|
||||
+5
-16
@@ -1,5 +1,8 @@
|
||||
package cn.crabc.core.app.entity.vo;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -10,9 +13,10 @@ import java.util.Set;
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class PreviewVO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 标题字段名
|
||||
*/
|
||||
@@ -23,19 +27,4 @@ public class PreviewVO implements Serializable {
|
||||
*/
|
||||
List<Map<String, Object>> data;
|
||||
|
||||
public Set<String> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setMetadata(Set<String> metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(List<Map<String, Object>> data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package cn.crabc.core.app.entity.vo;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class RequestParamsVO {
|
||||
/**
|
||||
* 参数名
|
||||
*/
|
||||
private String paramName;
|
||||
|
||||
/**
|
||||
* 参数模型,request,response
|
||||
*/
|
||||
private String paramModel;
|
||||
|
||||
/**
|
||||
* 是否必填
|
||||
*/
|
||||
private String required;
|
||||
|
||||
/**
|
||||
* 操作
|
||||
*/
|
||||
private String operation;
|
||||
|
||||
/**
|
||||
* 参数类型
|
||||
*/
|
||||
private String paramType;
|
||||
|
||||
/**
|
||||
* 参数默认值
|
||||
*/
|
||||
private String defaultValue;
|
||||
|
||||
/**
|
||||
* 参数示例值
|
||||
*/
|
||||
private String example;
|
||||
|
||||
/**
|
||||
* 参数备注
|
||||
*/
|
||||
private String paramDesc;
|
||||
|
||||
private List<RequestParamsVO> children;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package cn.crabc.core.app.entity.vo;
|
||||
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class SqlParseVO {
|
||||
|
||||
private Set<String> reqColumns;
|
||||
|
||||
private Set<ColumnParseVo> resColumns;
|
||||
|
||||
private String sqlScript;
|
||||
|
||||
private String datasourceType;
|
||||
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
@@ -79,6 +79,7 @@ public class ExceptionHandler {
|
||||
@org.springframework.web.bind.annotation.ExceptionHandler(value = HttpMessageNotReadableException.class)
|
||||
@ResponseBody
|
||||
public Result exceptionHandler(HttpServletRequest req, HttpMessageNotReadableException e) {
|
||||
e.printStackTrace();
|
||||
return Result.error(50002, "Body参数异常,请检查Body/json是否正确传参");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package cn.crabc.core.app.filter;
|
||||
|
||||
import cn.crabc.core.app.util.ApiThreadLocal;
|
||||
import cn.crabc.core.app.util.UserThreadLocal;
|
||||
import jakarta.servlet.*;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.util.ContentCachingResponseWrapper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ApiFilter implements Filter {
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
Filter.super.init(filterConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||
HttpServletRequest request = (HttpServletRequest)servletRequest;
|
||||
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
ContentCachingResponseWrapper responseWrapper = null;
|
||||
try {
|
||||
// 包装类
|
||||
if (request.getContentType() == null || request.getContentType().contains(MediaType.APPLICATION_JSON_VALUE)) {
|
||||
BaseRequestWrapper requestWrapper = new BaseRequestWrapper(request);
|
||||
responseWrapper = new ContentCachingResponseWrapper(response);
|
||||
filterChain.doFilter(requestWrapper, responseWrapper);
|
||||
} else {
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
}finally {
|
||||
ApiThreadLocal.remove();
|
||||
if (responseWrapper != null) {
|
||||
responseWrapper.copyBodyToResponse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
ApiThreadLocal.remove();
|
||||
Filter.super.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
package cn.crabc.core.app.filter;
|
||||
|
||||
import cn.crabc.core.app.entity.BaseApiLog;
|
||||
import cn.crabc.core.app.entity.BaseApp;
|
||||
import cn.crabc.core.app.entity.dto.ApiInfoDTO;
|
||||
import cn.crabc.core.app.service.system.IBaseApiLogService;
|
||||
import cn.crabc.core.app.util.ApiThreadLocal;
|
||||
import cn.crabc.core.app.util.RequestUtils;
|
||||
import cn.crabc.core.app.util.Result;
|
||||
import cn.crabc.core.app.util.SM3Util;
|
||||
import cn.crabc.core.datasource.enums.ErrorStatusEnum;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.util.ContentCachingResponseWrapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* API开放接口鉴权过滤 拦截器
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
|
||||
public class AuthInterceptor implements HandlerInterceptor {
|
||||
private static final Logger log = LoggerFactory.getLogger(AuthInterceptor.class);
|
||||
|
||||
// API开放接口前缀
|
||||
private static final String API_PRE = "/api/web/";
|
||||
@Autowired
|
||||
private IBaseApiLogService iBaseApiLogService;
|
||||
@Value("${crabc.auth.expiresTime:10}")
|
||||
private Integer expiresTime;
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
@Autowired
|
||||
@Qualifier("apiCache")
|
||||
private Cache<String, Object> apiCache;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
String path = request.getRequestURI();
|
||||
String method = request.getMethod();
|
||||
|
||||
Object apiData = apiCache.getIfPresent(method + "_" + path.replace(API_PRE, ""));
|
||||
if (apiData == null) {
|
||||
setErrorResponse(request, response,ErrorStatusEnum.API_INVALID.getCode(),ErrorStatusEnum.API_INVALID.getMassage());
|
||||
return false;
|
||||
}
|
||||
ApiInfoDTO apiInfo = (ApiInfoDTO) apiData;
|
||||
if (apiInfo.getEnabled() == 0) {
|
||||
setErrorResponse(request, response,ErrorStatusEnum.API_OFFLINE.getCode(),ErrorStatusEnum.API_OFFLINE.getMassage());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 存入当前时间,当作是日志的请求时间
|
||||
apiInfo.setRequestDate(new Date());
|
||||
apiInfo.setRequestTime(System.currentTimeMillis());
|
||||
// 放入上下文
|
||||
ApiThreadLocal.set(apiInfo);
|
||||
try {
|
||||
// 应用列表
|
||||
List<BaseApp> appList = apiInfo.getAppList();
|
||||
|
||||
return switch (apiInfo.getAuthType().toUpperCase()) {
|
||||
case "APP_CODE" -> checkAppCode(request,response, appList);
|
||||
case "APP_KEY" -> checkAppKey(request,response, appList);
|
||||
case "APP_SECRET" -> checkSM3(request,response, appList);
|
||||
default -> true;
|
||||
};
|
||||
}catch (Exception e) {
|
||||
setErrorResponse(request,response,ErrorStatusEnum.API_UN_AUTH.getCode(),ErrorStatusEnum.API_UN_AUTH.getMassage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
|
||||
addLog(request, response, "");
|
||||
// 清除上下文
|
||||
ApiThreadLocal.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* 异常返回
|
||||
* @param response
|
||||
* @param status
|
||||
* @param message
|
||||
* @throws Exception
|
||||
*/
|
||||
private void setErrorResponse(HttpServletRequest request, HttpServletResponse response, int status, String message)
|
||||
throws Exception {
|
||||
// 指定错误码
|
||||
response.setStatus(400);
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
Result result = Result.error(status, message);
|
||||
String json = objectMapper.writeValueAsString(result);
|
||||
// 日记记录
|
||||
addLog(request, response, json);
|
||||
response.getWriter().write(json);
|
||||
}
|
||||
/**
|
||||
* 记录访问日志
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
*/
|
||||
private void addLog(HttpServletRequest request, HttpServletResponse response, String msg) throws Exception {
|
||||
ContentCachingResponseWrapper responseWrapper = null;
|
||||
BaseApiLog apiLog = new BaseApiLog();
|
||||
long endTime = System.currentTimeMillis();
|
||||
ApiInfoDTO apiInfo = ApiThreadLocal.get();
|
||||
if (apiInfo != null) {
|
||||
apiLog.setApiId(apiInfo.getApiId());
|
||||
apiLog.setApiName(apiInfo.getApiName());
|
||||
apiLog.setApiMethod(apiInfo.getApiMethod());
|
||||
apiLog.setAuthType(apiInfo.getAuthType());
|
||||
apiLog.setRequestTime(apiInfo.getRequestDate());
|
||||
apiLog.setCostTime(endTime - apiInfo.getRequestTime());
|
||||
}
|
||||
int status = response.getStatus();
|
||||
apiLog.setAppName(RequestUtils.getAppKey(request));
|
||||
apiLog.setApiPath(request.getRequestURI());
|
||||
apiLog.setRequestIp(RequestUtils.getIp(request));
|
||||
apiLog.setResponseTime(new Date());
|
||||
apiLog.setQueryParam(request.getQueryString());
|
||||
apiLog.setResponseCode(status);
|
||||
apiLog.setRequestStatus(status == 200 ? "success" : "fail");
|
||||
try {
|
||||
if (request instanceof BaseRequestWrapper) {
|
||||
String requestBody = StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8);
|
||||
apiLog.setRequestBody(requestBody);
|
||||
}
|
||||
if (response instanceof ContentCachingResponseWrapper) {
|
||||
responseWrapper = (ContentCachingResponseWrapper) response;
|
||||
byte[] content = responseWrapper.getContentAsByteArray();
|
||||
String responseBody = new String(content, StandardCharsets.UTF_8);
|
||||
apiLog.setResponseBody(responseBody);
|
||||
}
|
||||
if (status == 400) {
|
||||
apiLog.setResponseBody(msg);
|
||||
}
|
||||
iBaseApiLogService.addLog(apiLog);
|
||||
} catch (Exception e) {
|
||||
log.error("响应结果转换异常", e);
|
||||
} finally {
|
||||
if (responseWrapper != null) {
|
||||
responseWrapper.copyBodyToResponse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证接口访问权限APP_CODE
|
||||
*
|
||||
* @param request
|
||||
* @param appList
|
||||
* @return
|
||||
*/
|
||||
private boolean checkAppCode(HttpServletRequest request,HttpServletResponse response, List<BaseApp> appList) throws Exception {
|
||||
String appCode = RequestUtils.getAppCode(request);
|
||||
if (appCode == null || appCode.isEmpty()) {
|
||||
setErrorResponse(request,response,ErrorStatusEnum.API_UN_AUTH.getCode(),ErrorStatusEnum.API_UN_AUTH.getMassage());
|
||||
return false;
|
||||
}
|
||||
boolean check = appList.stream().anyMatch(app -> app.getAppCode().equals(appCode));
|
||||
if (!check) {
|
||||
setErrorResponse(request,response,ErrorStatusEnum.API_UN_AUTH.getCode(),ErrorStatusEnum.API_UN_AUTH.getMassage());
|
||||
}
|
||||
return check;
|
||||
}
|
||||
/**
|
||||
* 验证接口访问权限APP_KEY
|
||||
*
|
||||
* @param request
|
||||
* @param appList
|
||||
* @return
|
||||
*/
|
||||
private boolean checkAppKey(HttpServletRequest request, HttpServletResponse response, List<BaseApp> appList) throws Exception {
|
||||
String appKey = RequestUtils.getAppKey(request);
|
||||
if (appKey == null || appKey.isEmpty()) {
|
||||
setErrorResponse(request,response,ErrorStatusEnum.SHA_APPKEY_NOT_FOUNT.getCode(),ErrorStatusEnum.SHA_APPKEY_NOT_FOUNT.getMassage());
|
||||
return false;
|
||||
}
|
||||
boolean check = appList.stream().anyMatch(app -> app.getAppKey().equals(appKey));
|
||||
if (!check) {
|
||||
setErrorResponse(request,response,ErrorStatusEnum.APP_UN_AUTH.getCode(),ErrorStatusEnum.APP_UN_AUTH.getMassage());
|
||||
}
|
||||
return check;
|
||||
}
|
||||
|
||||
/**
|
||||
* 国密签名认证
|
||||
*
|
||||
* @param request
|
||||
* @param appList
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public boolean checkSM3(HttpServletRequest request, HttpServletResponse response, List<BaseApp> appList) throws Exception {
|
||||
// 认证参数
|
||||
String sign = Optional.ofNullable(request.getHeader("sign")).orElse(request.getParameter("sign"));
|
||||
String timeStamp = Optional.ofNullable(request.getHeader("timestamp")).orElse(request.getParameter("timestamp"));
|
||||
String appKey = Optional.ofNullable(request.getHeader("appkey")).orElse(request.getParameter("appkey"));
|
||||
if (appKey == null || sign == null || timeStamp == null) {
|
||||
setErrorResponse(request,response,ErrorStatusEnum.SHA_PARAM_NOT_FOUNT.getCode(), ErrorStatusEnum.PARAM_NOT_FOUNT.getMassage());
|
||||
return false;
|
||||
}
|
||||
// 校验时间戳,超过10分钟失效
|
||||
long authTime = Long.parseLong(timeStamp);
|
||||
long nowTime = System.currentTimeMillis() - authTime;
|
||||
if (nowTime > expiresTime * 60 * 1000) {
|
||||
setErrorResponse(request,response,ErrorStatusEnum.SHA_TIMESTAMP_EXPIRE.getCode(), ErrorStatusEnum.SHA_TIMESTAMP_EXPIRE.getMassage());
|
||||
return false;
|
||||
}
|
||||
|
||||
String appSecret = appList.stream()
|
||||
.filter(app -> app.getAppKey().equals(appKey))
|
||||
.map(BaseApp::getAppSecret)
|
||||
.findFirst()
|
||||
.orElse("");
|
||||
|
||||
boolean verify = SM3Util.verify(appSecret + timeStamp, sign);
|
||||
if (!verify) {
|
||||
setErrorResponse(request,response,ErrorStatusEnum.API_UN_AUTH.getCode(),ErrorStatusEnum.API_UN_AUTH.getMassage());
|
||||
}
|
||||
return verify;
|
||||
}
|
||||
}
|
||||
File renamed without changes.
+9
-14
@@ -18,30 +18,25 @@ import org.springframework.web.servlet.HandlerInterceptor;
|
||||
*/
|
||||
public class JwtInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Value("${crabc.token.expireTime:36000}")
|
||||
private long expireTime;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
|
||||
if (request.getMethod().toUpperCase().equals("OPTIONS")){
|
||||
return true; // 通过OPTION请求
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||
// 放行OPTIONS请求
|
||||
if ("OPTIONS".equals(request.getMethod().toUpperCase())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 获取并校验token
|
||||
String token = JwtUtil.getToken(request);
|
||||
if (token == null) {
|
||||
throw new CustomException(ErrorStatusEnum.JWT_LOGIN_EXPIRE.getCode(), ErrorStatusEnum.JWT_UN_AUTH.getMassage());
|
||||
}
|
||||
|
||||
// 解析token
|
||||
Claims claims = JwtUtil.parseToken(token);
|
||||
if (claims == null) {
|
||||
throw new CustomException(ErrorStatusEnum.JWT_LOGIN_EXPIRE.getCode(), ErrorStatusEnum.JWT_UN_AUTH.getMassage());
|
||||
}
|
||||
long nowTime = System.currentTimeMillis();
|
||||
Long expire = Long.parseLong(claims.get("expireTime").toString());
|
||||
long time = nowTime - expire;
|
||||
if (time/1000 > expireTime) {
|
||||
throw new CustomException(ErrorStatusEnum.JWT_LOGIN_EXPIRE.getCode(), ErrorStatusEnum.JWT_LOGIN_EXPIRE.getMassage());
|
||||
}else{
|
||||
|
||||
}
|
||||
// 设置用户信息到线程上下文
|
||||
UserThreadLocal.set(claims);
|
||||
return true;
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+25
-25
@@ -23,6 +23,7 @@ public class BaseDataServiceImpl implements IBaseDataService {
|
||||
|
||||
@Autowired
|
||||
private DataSourceManager dataSourceManager;
|
||||
|
||||
@Override
|
||||
public String testConnection(BaseDataSource dataSource) {
|
||||
return dataSourceManager.test(dataSource);
|
||||
@@ -40,21 +41,17 @@ public class BaseDataServiceImpl implements IBaseDataService {
|
||||
Object result = this.execute(datasourceId, datasourceType, schema, sql, params);
|
||||
PreviewVO preview = new PreviewVO();
|
||||
if (result instanceof List) {
|
||||
List<Map<String, Object>> list = (List<Map<String, Object>>)result;
|
||||
List<Map<String, Object>> list = (List<Map<String, Object>>) result;
|
||||
if (!list.isEmpty()) {
|
||||
preview.setData(list);
|
||||
Set<String> fieldName = list.get(0).keySet();
|
||||
preview.setMetadata(fieldName);
|
||||
preview.setMetadata(list.get(0).keySet());
|
||||
}
|
||||
}else{
|
||||
Set<String> fieldName = new HashSet<>();
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
} else {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("执行结果", "执行成功,影响条数:"+result);
|
||||
list.add(data);
|
||||
data.put("执行结果", String.format("执行成功,影响条数:%s", result));
|
||||
List<Map<String, Object>> list = Collections.singletonList(data);
|
||||
preview.setData(list);
|
||||
fieldName.add("执行结果");
|
||||
preview.setMetadata(fieldName);
|
||||
preview.setMetadata(Collections.singleton("执行结果"));
|
||||
}
|
||||
return preview;
|
||||
}
|
||||
@@ -62,25 +59,28 @@ public class BaseDataServiceImpl implements IBaseDataService {
|
||||
@Override
|
||||
public Object execute(String datasourceId, String datasourceType, String schema, String sql, Map<String, Object> params) {
|
||||
StatementMapper statementMapper = dataSourceManager.getStatementMapper(datasourceId);
|
||||
// 数据源类型
|
||||
|
||||
if (datasourceType != null && !params.containsKey(BaseConstant.DATA_SOURCE_TYPE)) {
|
||||
params.put(BaseConstant.DATA_SOURCE_TYPE, datasourceType);
|
||||
}
|
||||
String sqlType = SQLUtil.getOperateType(sql);
|
||||
if ("insert".equalsIgnoreCase(sqlType)) {
|
||||
return statementMapper.insert(datasourceId, schema, sql, params);
|
||||
}else if("update".equalsIgnoreCase(sqlType)){
|
||||
return statementMapper.update(datasourceId, schema, sql, params);
|
||||
}else if("delete".equalsIgnoreCase(sqlType)){
|
||||
return statementMapper.delete(datasourceId, schema, sql, params);
|
||||
} else {
|
||||
Object pageNum = params.get(BaseConstant.PAGE_NUM);
|
||||
Object pageSize = params.get(BaseConstant.PAGE_SIZE);
|
||||
if (pageNum != null && pageSize != null) {
|
||||
return statementMapper.selectPage(datasourceId, schema, sql, params, Integer.parseInt(pageNum.toString()), Integer.parseInt(pageSize.toString()));
|
||||
} else {
|
||||
|
||||
String sqlType = SQLUtil.getOperateType(sql).toLowerCase();
|
||||
switch (sqlType) {
|
||||
case "insert":
|
||||
return statementMapper.insert(datasourceId, schema, sql, params);
|
||||
case "update":
|
||||
return statementMapper.update(datasourceId, schema, sql, params);
|
||||
case "delete":
|
||||
return statementMapper.delete(datasourceId, schema, sql, params);
|
||||
default:
|
||||
Object pageNum = params.get(BaseConstant.PAGE_NUM);
|
||||
Object pageSize = params.get(BaseConstant.PAGE_SIZE);
|
||||
if (pageNum != null && pageSize != null) {
|
||||
return statementMapper.selectPage(datasourceId, schema, sql, params,
|
||||
Integer.parseInt(pageNum.toString()),
|
||||
Integer.parseInt(pageSize.toString()));
|
||||
}
|
||||
return statementMapper.selectList(datasourceId, schema, sql, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -153,4 +153,10 @@ public interface IBaseApiInfoService {
|
||||
*/
|
||||
Integer addChooseApi(BaseAppApi appApi);
|
||||
|
||||
/**
|
||||
* 销毁接口
|
||||
* @param apiId
|
||||
* @return
|
||||
*/
|
||||
Integer destroyApiInfo(Long apiId);
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+17
-7
@@ -50,12 +50,7 @@ public class BaseApiInfoServiceImpl implements IBaseApiInfoService {
|
||||
@Autowired
|
||||
@Qualifier("apiCache")
|
||||
Cache<String, Object> apiInfoCache;
|
||||
|
||||
@Scheduled(cron = "${crabc.corn.api:0 0/1 * * * ?}")
|
||||
public void task() {
|
||||
initApi();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initApi() {
|
||||
updateCache(null);
|
||||
@@ -71,7 +66,7 @@ public class BaseApiInfoServiceImpl implements IBaseApiInfoService {
|
||||
@Override
|
||||
public List<ApiInfoDTO> getApiCache(Long apiId) {
|
||||
List<ApiInfoDTO> apiInfos = apiInfoMapper.selectApiDetail(apiId);
|
||||
if (apiInfos.size() == 0) {
|
||||
if (apiInfos.isEmpty()) {
|
||||
return apiInfos;
|
||||
}
|
||||
// 应用
|
||||
@@ -286,6 +281,21 @@ public class BaseApiInfoServiceImpl implements IBaseApiInfoService {
|
||||
return baseAppApiMapper.insert(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer destroyApiInfo(Long apiId) {
|
||||
String userId = UserThreadLocal.getUserId();
|
||||
|
||||
BaseApiInfo baseApiInfo = new BaseApiInfo();
|
||||
baseApiInfo.setUpdateTime(new Date());
|
||||
baseApiInfo.setUpdateBy(userId);
|
||||
baseApiInfo.setApiStatus(ApiStateEnum.DESTROY.getName());
|
||||
baseApiInfo.setApiId(apiId);
|
||||
apiInfoMapper.updateApiState(baseApiInfo);
|
||||
// 更新缓存
|
||||
this.updateCache(apiId);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* api信息历史发布版本存档
|
||||
*
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package cn.crabc.core.app.service.system.impl;
|
||||
|
||||
import cn.crabc.core.app.entity.vo.ApiParamsVO;
|
||||
import cn.crabc.core.app.entity.vo.RequestParamsVO;
|
||||
import cn.crabc.core.app.mapper.BaseApiParamMapper;
|
||||
import cn.crabc.core.app.service.system.IBaseApiParamService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* API参数 服务实现
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
@Service
|
||||
public class BaseApiParamServiceImpl implements IBaseApiParamService {
|
||||
|
||||
@Autowired
|
||||
private BaseApiParamMapper baseApiParamMapper;
|
||||
@Value("${crabc.result.code:code}")
|
||||
private String resultCode;
|
||||
@Value("${crabc.result.msg:msg}")
|
||||
private String resultMsg;
|
||||
@Value("${crabc.result.data:data}")
|
||||
private String resultData;
|
||||
|
||||
public static final String REQUEST ="request";
|
||||
/**
|
||||
* 响应参数
|
||||
*/
|
||||
public static final String RESPONSE ="response";
|
||||
|
||||
@Override
|
||||
public ApiParamsVO getApiDetailsParams(Long apiId) {
|
||||
ApiParamsVO apiParams = new ApiParamsVO();
|
||||
List<RequestParamsVO> requestParams = baseApiParamMapper.selectApiParams(apiId);
|
||||
Map<String, List<RequestParamsVO>> paramMap = requestParams.stream().collect(Collectors.groupingBy(RequestParamsVO::getParamModel));
|
||||
apiParams.setReqParams(paramMap.get(REQUEST));
|
||||
List<RequestParamsVO> responseParam = paramMap.get(RESPONSE);
|
||||
apiParams.setResParams(this.setResponseParams(responseParam));
|
||||
return apiParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理返回参数
|
||||
* @param responseParams
|
||||
* @return
|
||||
*/
|
||||
public List<RequestParamsVO> setResponseParams(List<RequestParamsVO> responseParams) {
|
||||
List<RequestParamsVO> list = new ArrayList<>();
|
||||
if (responseParams == null || responseParams.isEmpty()) {
|
||||
return list;
|
||||
}
|
||||
RequestParamsVO responseCode = new RequestParamsVO();
|
||||
responseCode.setParamName(resultCode);
|
||||
responseCode.setParamDesc("状态码:0 成功");
|
||||
responseCode.setParamType("Int");
|
||||
responseCode.setExample("0");
|
||||
responseCode.setRequired("Y");
|
||||
list.add(responseCode);
|
||||
|
||||
RequestParamsVO responseMsg = new RequestParamsVO();
|
||||
responseMsg.setParamName(resultMsg);
|
||||
responseMsg.setParamDesc("错误信息");
|
||||
responseMsg.setParamType("String");
|
||||
responseMsg.setExample("");
|
||||
responseMsg.setChildren(null);
|
||||
responseCode.setRequired("Y");
|
||||
list.add(responseMsg);
|
||||
|
||||
RequestParamsVO responseData = new RequestParamsVO();
|
||||
responseData.setParamName(resultData);
|
||||
responseData.setParamDesc("数据");
|
||||
responseData.setParamType("Array");
|
||||
responseData.setExample("");
|
||||
responseCode.setRequired("Y");
|
||||
responseData.setChildren(responseParams);
|
||||
list.add(responseData);
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
File renamed without changes.
+2
-1
@@ -113,6 +113,7 @@ public class BaseDataSourceServiceImpl implements IBaseDataSourceService {
|
||||
dataSource.setClassify("jdbc");
|
||||
dataSource.setCreateBy(UserThreadLocal.getUserId());
|
||||
dataSource.setCreateTime(new Date());
|
||||
dataSource.setUpdateTime(new Date());
|
||||
// 判断是否是自定义
|
||||
if ("custom".equals(dataSource.getDatasourceType())){
|
||||
String dataSourceType = SQLUtil.getDataSourceType(dataSource.getJdbcUrl());
|
||||
@@ -176,7 +177,7 @@ public class BaseDataSourceServiceImpl implements IBaseDataSourceService {
|
||||
byte[] decode = Base64.getDecoder().decode(password);
|
||||
pwd = new String(decode);
|
||||
}else if (dataSource.getDatasourceId() != null){
|
||||
BaseDatasource baseDatasource = dataSourceMapper.selectOne(Integer.parseInt(dataSource.getDatasourceId()));
|
||||
BaseDatasource baseDatasource = dataSourceMapper.selectOne(dataSource.getDatasourceId());
|
||||
byte[] decode = Base64.getDecoder().decode(baseDatasource.getPassword());
|
||||
pwd = new String(decode);
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+6
-1
@@ -1,6 +1,9 @@
|
||||
package cn.crabc.core.app.util;
|
||||
|
||||
import cn.crabc.core.app.entity.dto.ApiInfoDTO;
|
||||
import cn.crabc.core.app.filter.AuthInterceptor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 上下文 当前用户API信息
|
||||
@@ -8,7 +11,7 @@ import cn.crabc.core.app.entity.dto.ApiInfoDTO;
|
||||
* @author yuqf
|
||||
*/
|
||||
public class ApiThreadLocal {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ApiThreadLocal.class);
|
||||
private static ThreadLocal<ApiInfoDTO> apiInfo =new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
@@ -16,6 +19,7 @@ public class ApiThreadLocal {
|
||||
* @param api
|
||||
*/
|
||||
public static void set(ApiInfoDTO api){
|
||||
log.info("--> 设置上下文API信息,{}",api.getApiPath());
|
||||
apiInfo.set(api);
|
||||
}
|
||||
|
||||
@@ -37,6 +41,7 @@ public class ApiThreadLocal {
|
||||
* 清除
|
||||
*/
|
||||
public static void remove(){
|
||||
log.info("<-- 清除上下文API信息");
|
||||
apiInfo.remove();
|
||||
}
|
||||
}
|
||||
+6
-3
@@ -5,6 +5,7 @@ import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
@@ -17,8 +18,9 @@ import java.util.UUID;
|
||||
public class JwtUtil {
|
||||
private static String header = "Authorization";
|
||||
// 令牌秘钥
|
||||
private static String secret = "crabcjfakdjfaldjflkadjlafjaldkjlaflkalk";
|
||||
private static String secret = "KLSDJIWKD27JKZDFJALKJKD82KM90DL1NWMD";
|
||||
public static final String TOKEN_PREFIX = "bearer ";
|
||||
public static long expirationTime = 1000L * 60 * 60 * 8; // 8小时过期
|
||||
|
||||
/**
|
||||
* 创建令牌
|
||||
@@ -27,7 +29,6 @@ public class JwtUtil {
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
claims.put("userId", userId);
|
||||
claims.put("userName", userName);
|
||||
claims.put("expireTime", System.currentTimeMillis());
|
||||
return createToken(claims);
|
||||
}
|
||||
|
||||
@@ -36,6 +37,8 @@ public class JwtUtil {
|
||||
*/
|
||||
public static String createToken(Map<String, Object> claims) {
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
Date now = new Date();
|
||||
Date expiration = new Date(now.getTime() + expirationTime);
|
||||
try {
|
||||
return Jwts.builder()
|
||||
.header()
|
||||
@@ -43,7 +46,7 @@ public class JwtUtil {
|
||||
.add("alg", "HS256")
|
||||
.and()
|
||||
.claims(claims)
|
||||
// 令牌ID
|
||||
.expiration(expiration)
|
||||
.id(uuid)
|
||||
.signWith(Keys.hmacShaKeyFor(secret.getBytes()))
|
||||
.compact();
|
||||
File renamed without changes.
File renamed without changes.
+11
-13
@@ -1,13 +1,11 @@
|
||||
package cn.crabc.core.app.util;
|
||||
|
||||
import org.springframework.util.Base64Utils;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.security.*;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* RSA加/解密工具类
|
||||
@@ -24,13 +22,13 @@ public class RSAUtils {
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String decryptByPubKey(String pubKey, String text) throws Exception {
|
||||
byte[] bytes = Base64Utils.decodeFromString(pubKey);
|
||||
byte[] bytes = Base64.getDecoder().decode(pubKey);
|
||||
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(bytes);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
|
||||
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
|
||||
Cipher cipher = Cipher.getInstance(RSA);
|
||||
cipher.init(Cipher.DECRYPT_MODE, publicKey);
|
||||
byte[] result = Base64Utils.decodeFromString(text);
|
||||
byte[] result = Base64.getDecoder().decode(text);
|
||||
return new String(result);
|
||||
}
|
||||
|
||||
@@ -43,14 +41,14 @@ public class RSAUtils {
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String encryptByPriKey(String priKey, String text) throws Exception {
|
||||
byte[] bytes = Base64Utils.decodeFromString(priKey);
|
||||
byte[] bytes = Base64.getDecoder().decode(priKey);
|
||||
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(bytes);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
|
||||
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
|
||||
Cipher cipher = Cipher.getInstance(RSA);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
|
||||
byte[] result = cipher.doFinal(text.getBytes());
|
||||
return Base64Utils.encodeToString(result);
|
||||
return Base64.getEncoder().encodeToString(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,13 +63,13 @@ public class RSAUtils {
|
||||
if (text == null || priKey == null) {
|
||||
return null;
|
||||
}
|
||||
byte[] bytes = Base64Utils.decodeFromString(priKey);
|
||||
byte[] bytes = Base64.getDecoder().decode(priKey);
|
||||
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(bytes);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
|
||||
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
|
||||
Cipher cipher = Cipher.getInstance(RSA);
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
byte[] result = cipher.doFinal(Base64Utils.decodeFromString(text));
|
||||
byte[] result = cipher.doFinal(Base64.getDecoder().decode(text));
|
||||
return new String(result);
|
||||
}
|
||||
|
||||
@@ -86,7 +84,7 @@ public class RSAUtils {
|
||||
if (text == null || pubKey == null) {
|
||||
return null;
|
||||
}
|
||||
byte[] bytes = Base64Utils.decodeFromString(pubKey);
|
||||
byte[] bytes = Base64.getDecoder().decode(pubKey);
|
||||
|
||||
X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(bytes);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
|
||||
@@ -94,7 +92,7 @@ public class RSAUtils {
|
||||
Cipher cipher = Cipher.getInstance(RSA);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
byte[] result = cipher.doFinal(text.getBytes());
|
||||
return Base64Utils.encodeToString(result);
|
||||
return Base64.getEncoder().encodeToString(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,8 +107,8 @@ public class RSAUtils {
|
||||
KeyPair keyPair = keyPairGenerator.generateKeyPair();
|
||||
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
|
||||
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
|
||||
String pubKey = Base64Utils.encodeToString(rsaPublicKey.getEncoded());
|
||||
String priKey = Base64Utils.encodeToString(rsaPrivateKey.getEncoded());
|
||||
String pubKey = Base64.getEncoder().encodeToString(rsaPublicKey.getEncoded());
|
||||
String priKey = Base64.getEncoder().encodeToString(rsaPrivateKey.getEncoded());
|
||||
RSAKeyPair rsaKeyPair = new RSAKeyPair();
|
||||
rsaKeyPair.setPublicKey(pubKey);
|
||||
rsaKeyPair.setPrivateKey(priKey);
|
||||
+24
-1
@@ -81,7 +81,27 @@ public class RequestUtils {
|
||||
public static String getAppCode(HttpServletRequest req) {
|
||||
String appCode = req.getHeader("appCode");
|
||||
if (appCode == null) {
|
||||
String[] codeNames = new String[]{"appCode","AppCode", "appcode", "app_code"};
|
||||
String[] codeNames = new String[]{"appCode","AppCode", "app_code"};
|
||||
for(String codeName : codeNames) {
|
||||
appCode = req.getParameter(codeName);
|
||||
if (appCode != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return appCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求头和URL参数中的认证AppKey
|
||||
*
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
public static String getAppKey(HttpServletRequest req) {
|
||||
String appCode = req.getHeader("appKey");
|
||||
if (appCode == null) {
|
||||
String[] codeNames = new String[]{"appKey","AppKey", "app_key"};
|
||||
for(String codeName : codeNames) {
|
||||
appCode = req.getParameter(codeName);
|
||||
if (appCode != null) {
|
||||
@@ -123,6 +143,9 @@ public class RequestUtils {
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
}
|
||||
if ("0:0:0:0:0:0:0:1".equals(ip) || "localhost".equals(ip)) {
|
||||
ip ="127.0.0.1";
|
||||
}
|
||||
return ip == null ? "" : ip.trim();
|
||||
}
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,52 @@
|
||||
package cn.crabc.core.app.util;
|
||||
import org.bouncycastle.crypto.digests.SM3Digest;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.Security;
|
||||
import java.util.HexFormat;
|
||||
|
||||
/**
|
||||
* 国密SM3加密工具类
|
||||
*
|
||||
* @author yuqf
|
||||
*/
|
||||
public class SM3Util {
|
||||
|
||||
static {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串的SM3算法哈希值
|
||||
* @param data 输入字符串
|
||||
* @return 十六进制格式的哈希值
|
||||
*/
|
||||
public static String hash(String data) {
|
||||
return hash(data.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* 节数组的SM3算法哈希值
|
||||
* @param bytes 输入字节数组
|
||||
* @return 十六进制格式的哈希值
|
||||
*/
|
||||
public static String hash(byte[] bytes) {
|
||||
SM3Digest digest = new SM3Digest();
|
||||
digest.update(bytes, 0, bytes.length);
|
||||
byte[] result = new byte[digest.getDigestSize()];
|
||||
digest.doFinal(result, 0);
|
||||
return HexFormat.of().formatHex(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证SM3签名哈希值
|
||||
* @param data 待签名字符串
|
||||
* @param sign 预期哈希值
|
||||
* @return 是否验证通过
|
||||
*/
|
||||
public static boolean verify(String data, String sign) {
|
||||
String hash = hash(data.getBytes(StandardCharsets.UTF_8));
|
||||
return hash.equalsIgnoreCase(sign);
|
||||
}
|
||||
}
|
||||
+56
-9
@@ -2,6 +2,7 @@ package cn.crabc.core.app.util;
|
||||
|
||||
|
||||
import cn.crabc.core.app.entity.BaseApiParam;
|
||||
import cn.crabc.core.app.entity.vo.ColumnParseVo;
|
||||
import cn.crabc.core.datasource.exception.CustomException;
|
||||
import com.alibaba.druid.DbType;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
@@ -14,7 +15,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.dialect.clickhouse.visitor.ClickSchemaStatVisitor;
|
||||
import com.alibaba.druid.sql.dialect.clickhouse.visitor.CKStatVisitor;
|
||||
import com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;
|
||||
import com.alibaba.druid.sql.dialect.hive.visitor.HiveSchemaStatVisitor;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
|
||||
@@ -100,19 +101,19 @@ public class SQLUtil {
|
||||
public static Set<String> analyzeSQL(String sql, String dbType) {
|
||||
Set<String> aliasList = new HashSet<>();
|
||||
try {
|
||||
if ("doris".equalsIgnoreCase(dbType) || "starrocks".equalsIgnoreCase(dbType)) {
|
||||
dbType = "mysql";
|
||||
}
|
||||
List<SQLStatement> sqlStatementList = SQLUtils.parseStatements(sql, DbType.valueOf(dbType), false);
|
||||
if (sqlStatementList == null || sqlStatementList.isEmpty()) {
|
||||
//throw new IllegalArgumentException("不是有效语句");
|
||||
return aliasList;
|
||||
} else if (sqlStatementList.size() > 1) {
|
||||
throw new CustomException(55000, "不支持多条SQL语句!请删除多余的SQL");
|
||||
}
|
||||
|
||||
if (!(sqlStatementList.get(0) instanceof SQLSelectStatement)) {
|
||||
if (!(sqlStatementList.get(sqlStatementList.size() -1) instanceof SQLSelectStatement)) {
|
||||
return aliasList;
|
||||
}
|
||||
|
||||
SQLSelectStatement selectStatement = (SQLSelectStatement) sqlStatementList.get(0);
|
||||
SQLSelectStatement selectStatement = (SQLSelectStatement) sqlStatementList.get(sqlStatementList.size() -1);
|
||||
|
||||
SQLSelect sqlSelect = selectStatement.getSelect();
|
||||
|
||||
@@ -195,7 +196,7 @@ public class SQLUtil {
|
||||
visitor = new DB2SchemaStatVisitor();
|
||||
break;
|
||||
case "clickhouse":
|
||||
visitor = new ClickSchemaStatVisitor();
|
||||
visitor = new CKStatVisitor();
|
||||
break;
|
||||
case "hive":
|
||||
visitor = new HiveSchemaStatVisitor();
|
||||
@@ -329,10 +330,10 @@ public class SQLUtil {
|
||||
if (reqParams instanceof Map) {
|
||||
Map<String, Object> paramMap = (Map<String, Object>) reqParams;
|
||||
for (BaseApiParam param : paramsConfig) {
|
||||
if (param.getRequired() && !paramMap.containsKey(param.getParamName())) {
|
||||
if ("Y".equals(param.getRequired()) && !paramMap.containsKey(param.getParamName())) {
|
||||
// 必传参数没有传,则报错提示
|
||||
throw new CustomException(52005, "请求参数缺少!");
|
||||
} else if (!param.getRequired() && !paramMap.containsKey(param.getParamName())) {
|
||||
} else if ("N".equals(param.getRequired()) && !paramMap.containsKey(param.getParamName())) {
|
||||
// 非比传参数,去掉SQL中相应的条件
|
||||
sql = regexSql(sql, param.getParamName());
|
||||
}
|
||||
@@ -416,4 +417,50 @@ public class SQLUtil {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static Set<String> extractForeachParams(String sql) {
|
||||
Set<String> params = new HashSet<>();
|
||||
Pattern pattern = Pattern.compile("collection='(.*?)'");
|
||||
Matcher matcher = pattern.matcher(sql);
|
||||
while (matcher.find()) {
|
||||
params.add(matcher.group(1));
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
public static Set<String> extractIfParams(String sql) {
|
||||
Set<String> params = new HashSet<>();
|
||||
Pattern pattern = Pattern.compile(" test=['\"](\\w+)\\s*(?:!=|>=|<=|==|<|>|<|<=|>|>=)");
|
||||
Matcher matcher = pattern.matcher(sql);
|
||||
while (matcher.find()) {
|
||||
params.add(matcher.group(1));
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
public static String completeSql(String sql) {
|
||||
sql = sql.trim().toLowerCase();
|
||||
if (sql.endsWith("from")) {
|
||||
return sql + " test";
|
||||
} else if (sql.endsWith("where")) {
|
||||
return sql + " 1=1";
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
public static Set<String> parseResultColumns(String sql, String datasourceType) {
|
||||
Set<String> resNames = SQLUtil.analyzeSQL(sql.trim(), datasourceType);
|
||||
if (resNames.isEmpty()) {
|
||||
sql = SQLUtil.checkTable(sql, " test ");
|
||||
resNames = SQLUtil.analyzeSQL(sql.trim(), datasourceType);
|
||||
}
|
||||
return resNames;
|
||||
}
|
||||
|
||||
public static ColumnParseVo buildColumnInfo(String name) {
|
||||
ColumnParseVo column = new ColumnParseVo();
|
||||
column.setColName(name);
|
||||
column.setColType("String");
|
||||
column.setItemIndex(0);
|
||||
return column;
|
||||
}
|
||||
}
|
||||
File renamed without changes.
+10
-9
@@ -24,11 +24,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
i.update_time,
|
||||
i.release_time,
|
||||
i.show_sql_script,
|
||||
d.datasource_name
|
||||
g.group_name
|
||||
FROM
|
||||
base_api_info i
|
||||
left join base_datasource d
|
||||
on i.datasource_id = d.datasource_id
|
||||
left join base_group g
|
||||
on i.group_id = g.group_id
|
||||
<where>
|
||||
<if test="apiName !=null and apiName !=''">
|
||||
(i.api_name like concat('%',#{apiName},'%')
|
||||
@@ -49,7 +49,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
api_status,
|
||||
group_id
|
||||
FROM
|
||||
base_api_info where api_status !='history'
|
||||
base_api_info where api_status in ('edit','release')
|
||||
<if test="groupId !=null">
|
||||
and group_id = #{groupId}
|
||||
</if>
|
||||
@@ -69,8 +69,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
base_app_api aa on
|
||||
ai.api_id = aa.api_id
|
||||
WHERE
|
||||
ai.enabled = 1
|
||||
AND ai.api_status = 'release'
|
||||
ai.api_status = 'release'
|
||||
<if test="appId != null">
|
||||
and aa.app_id = #{appId}
|
||||
</if>
|
||||
@@ -194,7 +193,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="pageSetup != null">page_setup,</if>
|
||||
enabled,
|
||||
create_by,
|
||||
create_time
|
||||
create_time,
|
||||
update_time
|
||||
)values(
|
||||
<if test="apiName != null and apiName != ''">#{apiName},</if>
|
||||
<if test="apiPath != null and apiPath != ''">#{apiPath},</if>
|
||||
@@ -217,7 +217,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="pageSetup != null">#{pageSetup},</if>
|
||||
#{enabled},
|
||||
#{createBy},
|
||||
#{createTime}
|
||||
#{createTime},
|
||||
#{updateTime}
|
||||
)
|
||||
</insert>
|
||||
|
||||
@@ -263,7 +264,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</update>
|
||||
|
||||
<delete id="deleteApiInfo">
|
||||
DELETE FROM base_api_info where api_status ='edit' and api_id =#{apiId} and create_by =#{userId}
|
||||
DELETE FROM base_api_info where api_id =#{apiId} and create_by =#{userId}
|
||||
</delete>
|
||||
|
||||
<select id="countApi" resultType="java.lang.Integer">
|
||||
+2
-2
@@ -33,8 +33,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
and request_status =#{result}
|
||||
</if>
|
||||
<if test="startTime !='' and endTime !=''">
|
||||
and request_time >=#{startTime}
|
||||
and request_time <=#{endTime}
|
||||
and DATE_FORMAT(request_time,'%Y-%m-%d') >=#{startTime}
|
||||
and DATE_FORMAT(request_time,'%Y-%m-%d') <=#{endTime}
|
||||
</if>
|
||||
</where>
|
||||
order by log_id desc
|
||||
+1
@@ -22,6 +22,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
<select id="selectList" resultType="cn.crabc.core.app.entity.BaseApiParam">
|
||||
SELECT
|
||||
param_id,
|
||||
api_id,
|
||||
param_name,
|
||||
column_name,
|
||||
File renamed without changes.
+1
-2
@@ -68,7 +68,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
UPDATE base_app
|
||||
<set>
|
||||
<if test="appName != null and appName != ''">app_name =#{appName},</if>
|
||||
<if test="appDesc != null and appDesc != ''">app_desc =#{appDesc},</if>
|
||||
<if test="appCode != null and appCode != ''">app_code =#{appCode},</if>
|
||||
<if test="appKey != null and appKey != ''">app_key =#{appKey},</if>
|
||||
<if test="appSecret != null and appSecret != ''">app_secret =#{appSecret},</if>
|
||||
@@ -76,7 +75,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="ips != null and ips != ''">ips =#{ips},</if>
|
||||
<if test="enabled != null">enabled =#{enabled},</if>
|
||||
<if test="updateBy != null and updateBy != ''">update_by=#{updateBy},</if>
|
||||
update_time =#{updateTime}
|
||||
update_time =#{updateTime},app_desc =#{appDesc}
|
||||
</set>
|
||||
WHERE app_id = #{appId}
|
||||
</update>
|
||||
+42
-5
@@ -16,7 +16,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
password,
|
||||
remarks,
|
||||
extend,
|
||||
secret_key
|
||||
secret_key,
|
||||
min_idle,
|
||||
max_active,
|
||||
connect_timeout,
|
||||
idle_timeout,
|
||||
max_lifetime,
|
||||
keepalive_time
|
||||
FROM
|
||||
base_datasource ORDER BY datasource_id DESC
|
||||
</select>
|
||||
@@ -33,6 +39,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
'******' as password,
|
||||
remarks,
|
||||
extend,
|
||||
min_idle,
|
||||
max_active,
|
||||
connect_timeout,
|
||||
idle_timeout,
|
||||
max_lifetime,
|
||||
keepalive_time,
|
||||
update_time
|
||||
FROM
|
||||
base_datasource
|
||||
@@ -56,6 +68,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
username,
|
||||
password,
|
||||
extend,
|
||||
min_idle,
|
||||
max_active,
|
||||
connect_timeout,
|
||||
idle_timeout,
|
||||
max_lifetime,
|
||||
keepalive_time,
|
||||
secret_key
|
||||
FROM
|
||||
base_datasource WHERE datasource_id=#{datasourceId}
|
||||
@@ -79,7 +97,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="remarks != null and remarks != ''">remarks,</if>
|
||||
<if test="secretKey != null and secretKey != ''">secret_key,</if>
|
||||
<if test="createBy != null and createBy != ''">create_by,</if>
|
||||
create_time
|
||||
<if test="minIdle != null">min_idle,</if>
|
||||
<if test="maxActive != null">max_active,</if>
|
||||
<if test="connectTimeout != null">connect_timeout,</if>
|
||||
<if test="idleTimeout != null">idle_timeout,</if>
|
||||
<if test="maxLifetime != null">max_lifetime,</if>
|
||||
<if test="keepaliveTime != null">keepalive_time,</if>
|
||||
create_time,
|
||||
update_time
|
||||
)values(
|
||||
<if test="datasourceId != null and datasourceId != ''">#{datasourceId},</if>
|
||||
<if test="datasourceName != null and datasourceName != ''">#{datasourceName},</if>
|
||||
@@ -93,7 +118,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="remarks != null and remarks != ''">#{remarks},</if>
|
||||
<if test="secretKey != null and secretKey != ''">#{secretKey},</if>
|
||||
<if test="createBy != null and createBy != ''">#{createBy},</if>
|
||||
#{createTime}
|
||||
<if test="minIdle != null">#{minIdle},</if>
|
||||
<if test="maxActive != null">#{maxActive},</if>
|
||||
<if test="connectTimeout != null">#{connectTimeout},</if>
|
||||
<if test="idleTimeout != null">#{idleTimeout},</if>
|
||||
<if test="maxLifetime != null">#{maxLifetime},</if>
|
||||
<if test="keepaliveTime != null">#{keepaliveTime},</if>
|
||||
#{createTime},
|
||||
#{updateTime}
|
||||
)
|
||||
</insert>
|
||||
|
||||
@@ -108,10 +140,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="username != null and username != ''">username = #{username},</if>
|
||||
<if test="password != null and password != ''">password = #{password},</if>
|
||||
<if test="classify != null and classify != ''">classify = #{classify},</if>
|
||||
<if test="remarks != null and remarks != ''">remarks = #{remarks},</if>
|
||||
<if test="secretKey != null and secretKey != ''">secret_key = #{secretKey},</if>
|
||||
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
|
||||
update_time =#{updateTime}
|
||||
<if test="minIdle != null">min_idle=#{minIdle},</if>
|
||||
<if test="maxActive != null">max_active=#{maxActive},</if>
|
||||
<if test="connectTimeout != null">connect_timeout=#{connectTimeout},</if>
|
||||
<if test="idleTimeout != null">idle_timeout=#{idleTimeout},</if>
|
||||
<if test="maxLifetime != null">max_lifetime=#{maxLifetime},</if>
|
||||
<if test="keepaliveTime != null">keepalive_time=#{keepaliveTime},</if>
|
||||
update_time =#{updateTime},remarks = #{remarks}
|
||||
</set>
|
||||
WHERE datasource_id = #{datasourceId}
|
||||
</update>
|
||||
Loaded 100 of 286 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user