@@ -0,0 +1,211 @@ | |||
Apache License | |||
Version 2.0, January 2004 | |||
http://www.apache.org/licenses/ | |||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |||
1. Definitions. | |||
"License" shall mean the terms and conditions for use, reproduction, | |||
and distribution as defined by Sections 1 through 9 of this document. | |||
"Licensor" shall mean the copyright owner or entity authorized by | |||
the copyright owner that is granting the License. | |||
"Legal Entity" shall mean the union of the acting entity and all | |||
other entities that control, are controlled by, or are under common | |||
control with that entity. For the purposes of this definition, | |||
"control" means (i) the power, direct or indirect, to cause the | |||
direction or management of such entity, whether by contract or | |||
otherwise, or (ii) ownership of fifty percent (50%) or more of the | |||
outstanding shares, or (iii) beneficial ownership of such entity. | |||
"You" (or "Your") shall mean an individual or Legal Entity | |||
exercising permissions granted by this License. | |||
"Source" form shall mean the preferred form for making modifications, | |||
including but not limited to software source code, documentation | |||
source, and configuration files. | |||
"Object" form shall mean any form resulting from mechanical | |||
transformation or translation of a Source form, including but | |||
not limited to compiled object code, generated documentation, | |||
and conversions to other media types. | |||
"Work" shall mean the work of authorship, whether in Source or | |||
Object form, made available under the License, as indicated by a | |||
copyright notice that is included in or attached to the work | |||
(an example is provided in the Appendix below). | |||
"Derivative Works" shall mean any work, whether in Source or Object | |||
form, that is based on (or derived from) the Work and for which the | |||
editorial revisions, annotations, elaborations, or other modifications | |||
represent, as a whole, an original work of authorship. For the purposes | |||
of this License, Derivative Works shall not include works that remain | |||
separable from, or merely link (or bind by name) to the interfaces of, | |||
the Work and Derivative Works thereof. | |||
"Contribution" shall mean any work of authorship, including | |||
the original version of the Work and any modifications or additions | |||
to that Work or Derivative Works thereof, that is intentionally | |||
submitted to Licensor for inclusion in the Work by the copyright owner | |||
or by an individual or Legal Entity authorized to submit on behalf of | |||
the copyright owner. For the purposes of this definition, "submitted" | |||
means any form of electronic, verbal, or written communication sent | |||
to the Licensor or its representatives, including but not limited to | |||
communication on electronic mailing lists, source code control systems, | |||
and issue tracking systems that are managed by, or on behalf of, the | |||
Licensor for the purpose of discussing and improving the Work, but | |||
excluding communication that is conspicuously marked or otherwise | |||
designated in writing by the copyright owner as "Not a Contribution." | |||
"Contributor" shall mean Licensor and any individual or Legal Entity | |||
on behalf of whom a Contribution has been received by Licensor and | |||
subsequently incorporated within the Work. | |||
2. Grant of Copyright License. Subject to the terms and conditions of | |||
this License, each Contributor hereby grants to You a perpetual, | |||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||
copyright license to reproduce, prepare Derivative Works of, | |||
publicly display, publicly perform, sublicense, and distribute the | |||
Work and such Derivative Works in Source or Object form. | |||
3. Grant of Patent License. Subject to the terms and conditions of | |||
this License, each Contributor hereby grants to You a perpetual, | |||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||
(except as stated in this section) patent license to make, have made, | |||
use, offer to sell, sell, import, and otherwise transfer the Work, | |||
where such license applies only to those patent claims licensable | |||
by such Contributor that are necessarily infringed by their | |||
Contribution(s) alone or by combination of their Contribution(s) | |||
with the Work to which such Contribution(s) was submitted. If You | |||
institute patent litigation against any entity (including a | |||
cross-claim or counterclaim in a lawsuit) alleging that the Work | |||
or a Contribution incorporated within the Work constitutes direct | |||
or contributory patent infringement, then any patent licenses | |||
granted to You under this License for that Work shall terminate | |||
as of the date such litigation is filed. | |||
4. Redistribution. You may reproduce and distribute copies of the | |||
Work or Derivative Works thereof in any medium, with or without | |||
modifications, and in Source or Object form, provided that You | |||
meet the following conditions: | |||
(a) You must give any other recipients of the Work or | |||
Derivative Works a copy of this License; and | |||
(b) You must cause any modified files to carry prominent notices | |||
stating that You changed the files; and | |||
(c) You must retain, in the Source form of any Derivative Works | |||
that You distribute, all copyright, patent, trademark, and | |||
attribution notices from the Source form of the Work, | |||
excluding those notices that do not pertain to any part of | |||
the Derivative Works; and | |||
(d) If the Work includes a "NOTICE" text file as part of its | |||
distribution, then any Derivative Works that You distribute must | |||
include a readable copy of the attribution notices contained | |||
within such NOTICE file, excluding those notices that do not | |||
pertain to any part of the Derivative Works, in at least one | |||
of the following places: within a NOTICE text file distributed | |||
as part of the Derivative Works; within the Source form or | |||
documentation, if provided along with the Derivative Works; or, | |||
within a display generated by the Derivative Works, if and | |||
wherever such third-party notices normally appear. The contents | |||
of the NOTICE file are for informational purposes only and | |||
do not modify the License. You may add Your own attribution | |||
notices within Derivative Works that You distribute, alongside | |||
or as an addendum to the NOTICE text from the Work, provided | |||
that such additional attribution notices cannot be construed | |||
as modifying the License. | |||
You may add Your own copyright statement to Your modifications and | |||
may provide additional or different license terms and conditions | |||
for use, reproduction, or distribution of Your modifications, or | |||
for any such Derivative Works as a whole, provided Your use, | |||
reproduction, and distribution of the Work otherwise complies with | |||
the conditions stated in this License. | |||
5. Submission of Contributions. Unless You explicitly state otherwise, | |||
any Contribution intentionally submitted for inclusion in the Work | |||
by You to the Licensor shall be under the terms and conditions of | |||
this License, without any additional terms or conditions. | |||
Notwithstanding the above, nothing herein shall supersede or modify | |||
the terms of any separate license agreement you may have executed | |||
with Licensor regarding such Contributions. | |||
6. Trademarks. This License does not grant permission to use the trade | |||
names, trademarks, service marks, or product names of the Licensor, | |||
except as required for reasonable and customary use in describing the | |||
origin of the Work and reproducing the content of the NOTICE file. | |||
7. Disclaimer of Warranty. Unless required by applicable law or | |||
agreed to in writing, Licensor provides the Work (and each | |||
Contributor provides its Contributions) on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |||
implied, including, without limitation, any warranties or conditions | |||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | |||
PARTICULAR PURPOSE. You are solely responsible for determining the | |||
appropriateness of using or redistributing the Work and assume any | |||
risks associated with Your exercise of permissions under this License. | |||
8. Limitation of Liability. In no event and under no legal theory, | |||
whether in tort (including negligence), contract, or otherwise, | |||
unless required by applicable law (such as deliberate and grossly | |||
negligent acts) or agreed to in writing, shall any Contributor be | |||
liable to You for damages, including any direct, indirect, special, | |||
incidental, or consequential damages of any character arising as a | |||
result of this License or out of the use or inability to use the | |||
Work (including but not limited to damages for loss of goodwill, | |||
work stoppage, computer failure or malfunction, or any and all | |||
other commercial damages or losses), even if such Contributor | |||
has been advised of the possibility of such damages. | |||
9. Accepting Warranty or Additional Liability. While redistributing | |||
the Work or Derivative Works thereof, You may choose to offer, | |||
and charge a fee for, acceptance of support, warranty, indemnity, | |||
or other liability obligations and/or rights consistent with this | |||
License. However, in accepting such obligations, You may act only | |||
on Your own behalf and on Your sole responsibility, not on behalf | |||
of any other Contributor, and only if You agree to indemnify, | |||
defend, and hold each Contributor harmless for any liability | |||
incurred by, or claims asserted against, such Contributor by reason | |||
of your accepting any such warranty or additional liability. | |||
END OF TERMS AND CONDITIONS | |||
APPENDIX: How to apply the Apache License to your work. | |||
To apply the Apache License to your work, attach the following | |||
boilerplate notice, with the fields enclosed by brackets "[]" | |||
replaced with your own identifying information. (Don't include | |||
the brackets!) The text should be enclosed in the appropriate | |||
comment syntax for the file format. We also recommend that a | |||
file or class name and description of purpose be included on the | |||
same "printed page" as the copyright notice for easier | |||
identification within third-party archives. | |||
Copyright [yyyy] [name of copyright owner] | |||
Licensed under the Apache License, Version 2.0 (the "License"); | |||
you may not use this file except in compliance with the License. | |||
You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
Other dependencies and licenses: | |||
---------------------------------------------------------------------------------------- | |||
Open Source Software Licensed Under the Apache License, Version 2.0: | |||
The below software in this distribution may have been modified. | |||
---------------------------------------------------------------------------------------- | |||
1. EL-ADMIN | |||
Copyright 2019-2020 Zheng Jie |
@@ -0,0 +1,103 @@ | |||
<p align="center"> | |||
<a href="http://tianshu.org.cn"> | |||
<img width="200" src="http://tianshu.org.cn/template/default/assets/img/logo4.png"> | |||
</a> | |||
</p> | |||
<h1 align="center">天枢一站式AI模型开发平台</h1> | |||
**天枢人工智能开源开放平台**(简称:**天枢平台**)是天枢平台由之江实验室牵头,联合北京一流科技、中国信通院和浙江大学共同自研的人工智能开源平台。整个平台由一站式AI模型开发平台、高性能深度学习框架和模型炼知框架三大子系统组成。 | |||
其中, **一站式AI模型开发平台面**(简称:**一站式开发平台**)面向AI模型生产的生命周期,提供了包括数据处理、模型开发、模型训练和模型管理等功能,方便用户一站式构建AI算法。 | |||
## 平台优势 | |||
* **一站式开发**:为用户提供一站式深度学习开发功能,通过智能数据处理、便利的模型开发和模型训练,打通深度学习全链路; | |||
* **集成先进算法**:除了囊括常规AI算法外,之江天枢还集成了多领域的独家算法,提供业界领先性能。 | |||
* **灵活易用**:除了一站式深度学习开发平台,亦提供可视化和动静结合编码方式,调试灵活,小白亦可快速上手。 | |||
* **性能优越**:集成自主研发的分布式训练平台,提供高性能的分布式计算体验,节省训练成本和训练时间。 | |||
## 页面预览 | |||
![概览](/docs/images/dubhe_dashboard.png "概览") | |||
## 功能列表 | |||
<table> | |||
<tbody> | |||
<tr> | |||
<td rowspan="12">一站式开发平台</td> | |||
</tr> | |||
<tr> | |||
<td>数据管理</td> | |||
<td>数据集管理</td> | |||
</tr> | |||
<tr> | |||
<td rowspan="2">模型开发</td> | |||
<td>Notebook</td> | |||
</tr> | |||
<tr> | |||
<td>算法管理</td> | |||
</tr> | |||
<tr> | |||
<td rowspan="2">训练管理</td> | |||
<td>镜像管理</td> | |||
</tr> | |||
<tr> | |||
<td>训练任务</td> | |||
</tr> | |||
<tr> | |||
<td>模型管理</td> | |||
<td>模型列表</td> | |||
</tr> | |||
<tr> | |||
<td rowspan="5">控制台</td> | |||
<td>用户管理</td> | |||
</tr> | |||
<tr> | |||
<td>角色管理</td> | |||
</tr> | |||
<tr> | |||
<td>菜单管理</td> | |||
</tr> | |||
<tr> | |||
<td>字典管理</td> | |||
</tr> | |||
<tr> | |||
<td>集群状态</td> | |||
</tr> | |||
</tbody> | |||
</table> | |||
## 技术架构 | |||
![技术架构](./docs/images/tech-arc.jpg "技术架构") | |||
## 技术栈 | |||
- 后端: [Spring Boot](https://spring.io/projects/spring-boot) | |||
- 前端: [Vue.js](https://vuejs.org/), [Element](https://element.eleme.cn/) | |||
- 数据处理 [Yolo](https://pjreddie.com/darknet/yolo/) ... | |||
- 可视化: [Django](https://www.djangoproject.com/) ... | |||
- 中间件: [MySQL](https://www.mysql.com/), [MyBatis-Plus](https://mp.baomidou.com/), [Redis](https://redis.io/) | |||
- 基础设施: [Docker](https://www.docker.com/), [Kubernetes](https://kubernetes.io/) | |||
## 目录结构 | |||
``` | |||
├── dubhe_data_process 数据处理服务 | |||
├── dubhe-server 后端服务 | |||
├── dubhe-visual-server 可视化服务 | |||
├── webapp 前端服务 | |||
``` | |||
## 反馈问题 | |||
- [在线社区](http://www.aiiaos.cn/index.php?s=/forum/index/forum/id/45.html) | |||
- 钉钉交流群 | |||
<a href="./docs/images/dingtalk.jpg"><img src="http://cdn.qjycloud.com/dingtalk.jpg" width="320" /></a> | |||
## 许可证书 | |||
本项目的发布受[Apache 2.0 license](./LICENSE)许可认证。 |
@@ -0,0 +1,53 @@ | |||
/target/ | |||
.mvn* | |||
mvnw | |||
mvnw.cmd | |||
kubeconfig | |||
### STS ### | |||
.apt_generated | |||
.classpath | |||
.factorypath | |||
.project | |||
.settings | |||
.springBeans | |||
.sts4-cache | |||
### IntelliJ IDEA ### | |||
.idea | |||
*.iws | |||
*.iml | |||
*.ipr | |||
### NetBeans ### | |||
/nbproject/private/ | |||
/build/ | |||
/nbbuild/ | |||
/dist/ | |||
/nbdist/ | |||
/.nb-gradle/ | |||
# system ignore | |||
.DS_Store | |||
Thumbs.db | |||
*.orig | |||
# maven ignore | |||
target/ | |||
output/ | |||
*.jar | |||
!.mvn/wrapper/* | |||
*.war | |||
*.zip | |||
*.tar | |||
#*.tar.gz | |||
# eclipse ignore | |||
.settings/ | |||
.project | |||
.classpath | |||
logs/ | |||
/dubhe-k8s/src/main/resources/kubeconfig | |||
/dubhe-k8s/src/main/resources | |||
*.log | |||
/dubhe-admin/kubeconfig |
@@ -0,0 +1,10 @@ | |||
# type: subject | |||
# type:feat增加新功能;fix修复错误;docs修改文档;style修改样式;refactor代码重构;test增加测试模块,不涉及生产环境的代码;chore更新核心模块,包配置文件,不涉及生产环境的代码 | |||
# subject: 一两句话简述提交原因,与下方详细描述间隔一行 | |||
# body:提交详细原因,与下方脚注间隔一行 | |||
# footer(可选):1.提供链接关联issue、2.关闭issue |
@@ -0,0 +1,98 @@ | |||
# 之江天枢-服务端 | |||
**之江天枢一站式人工智能开源平台**(简称:**之江天枢**),包括海量数据处理、交互式模型构建(包含Notebook和模型可视化)、AI模型高效训练。多维度产品形态满足从开发者到大型企业的不同需求,将提升人工智能技术的研发效率、扩大算法模型的应用范围,进一步构建人工智能生态“朋友圈”。 | |||
## 源码部署 | |||
### 准备环境 | |||
安装如下软件环境。 | |||
- OpenJDK:1.8+ | |||
- Redis: 3.0+ | |||
- Maven: 3.0+ | |||
- MYSQL: 5.5.0+ | |||
### 下载源码 | |||
``` bash | |||
git clone https://codeup.teambition.com/zhejianglab/dubhe-server.git | |||
# 进入项目根目录 | |||
cd dubhe-server | |||
``` | |||
### 创建DB | |||
在MySQL中依次执行如下sql文件 | |||
``` | |||
sql/v1/00-Dubhe-DB.sql | |||
sql/v1/01-Dubhe-DDL.sql | |||
sql/v1/02-Dubhe-DML.sql | |||
``` | |||
### 配置 | |||
根据实际情况修改如下配置文件。 | |||
``` | |||
dubhe-admin/src/main/resources/config/application-prod.yml | |||
``` | |||
### 构建 | |||
``` bash | |||
# 构建,生成的 jar 包位于 ./dubhe-admin/target/dubhe-admin-1.0.jar | |||
mvn clean compile package | |||
``` | |||
### 启动 | |||
``` bash | |||
# 指定启动环境为 prod | |||
java -jar ./dubhe-admin/target/dubhe-admin-1.0.jar --spring.profiles.active=prod | |||
``` | |||
## 本地开发 | |||
### 必要条件: | |||
导入maven项目,下载所需的依赖包 | |||
mysql下创建数据库dubhe,初始化数据脚本 | |||
安装redis | |||
### 启动: | |||
mvn spring-boot:run | |||
## 代码结构: | |||
``` | |||
├── common 公共模块 | |||
├── dubhe-admin 开发与训练模块 | |||
│ ├── src | |||
│ │ └── main | |||
│ │ ├── java | |||
│ │ │ └── org | |||
│ │ │ └── dubhe | |||
│ │ │ ├── AppRun.java | |||
│ │ │ ├── domain 实体对象 | |||
│ │ │ ├── repository 数据库层 | |||
│ │ │ ├── rest 控制层 | |||
│ │ │ └── service 服务层 | |||
│ │ │ ├── dto 数据传输对象 | |||
│ │ │ ├── impl 服务实现 | |||
│ │ │ └── mapper 对象转化 | |||
│ │ └── resources 配置文件 | |||
├── dubhe-data 数据处理模块 | |||
├── dubhe-model 模型管理模块 | |||
├── dubhe-system 系统管理 | |||
``` | |||
## docker服务器 | |||
上传镜像功能依赖docker服务,harbor与dokcer的信任配置如下: | |||
### 1、对外开放端口 | |||
vi /lib/systemd/system/docker.service | |||
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock | |||
### 2、信任harbor地址 | |||
vi /etc/docker/daemon.json | |||
{ | |||
"exec-opts": ["native.cgroupdriver=systemd"], | |||
"log-driver": "json-file", | |||
"insecure-registries":[harbor地址], | |||
"log-opts": { | |||
"max-size": "100m" | |||
} | |||
} | |||
### 3、重新启动 | |||
systemctl daemon-reload | |||
service docker restart | |||
systemctl status docker |
@@ -0,0 +1,121 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xmlns="http://maven.apache.org/POM/4.0.0" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<parent> | |||
<artifactId>dubheplatform</artifactId> | |||
<groupId>zhejianglab</groupId> | |||
<version>1.0</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
<properties> | |||
<hutool.version>5.0.6</hutool.version> | |||
<minio.version>7.0.2</minio.version> | |||
<aspectjweaver.version>1.8.9</aspectjweaver.version> | |||
</properties> | |||
<artifactId>common</artifactId> | |||
<name>公共模块</name> | |||
<dependencies> | |||
<!--工具包--> | |||
<dependency> | |||
<groupId>cn.hutool</groupId> | |||
<artifactId>hutool-all</artifactId> | |||
<version>${hutool.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.google.guava</groupId> | |||
<artifactId>guava</artifactId> | |||
<version>21.0</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.github.penggle</groupId> | |||
<artifactId>kaptcha</artifactId> | |||
<version>${kaptcha.version}</version> | |||
</dependency> | |||
<!-- shiro --> | |||
<dependency> | |||
<groupId>org.apache.shiro</groupId> | |||
<artifactId>shiro-spring</artifactId> | |||
<version>${shiro.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.auth0</groupId> | |||
<artifactId>java-jwt</artifactId> | |||
<version>${jwt.version}</version> | |||
<exclusions> | |||
<exclusion> | |||
<groupId>*</groupId> | |||
<artifactId>*</artifactId> | |||
</exclusion> | |||
</exclusions> | |||
</dependency> | |||
<dependency> | |||
<groupId>io.minio</groupId> | |||
<artifactId>minio</artifactId> | |||
<version>${minio.version}</version> | |||
</dependency> | |||
<!-- aspect --> | |||
<dependency> | |||
<groupId>org.aspectj</groupId> | |||
<artifactId>aspectjweaver</artifactId> | |||
<version>${aspectjweaver.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>javax.xml.bind</groupId> | |||
<artifactId>jaxb-api</artifactId> | |||
<version>2.3.0</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.sun.xml.bind</groupId> | |||
<artifactId>jaxb-impl</artifactId> | |||
<version>2.3.0</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.sun.xml.bind</groupId> | |||
<artifactId>jaxb-core</artifactId> | |||
<version>2.3.0</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>commons-io</groupId> | |||
<artifactId>commons-io</artifactId> | |||
<version>1.3.2</version> | |||
<scope>compile</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>net.lingala.zip4j</groupId> | |||
<artifactId>zip4j</artifactId> | |||
<version>1.3.2</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.apache.commons</groupId> | |||
<artifactId>commons-compress</artifactId> | |||
<version>1.20</version> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-maven-plugin</artifactId> | |||
</plugin> | |||
<!-- 跳过单元测试 --> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-surefire-plugin</artifactId> | |||
<configuration> | |||
<skipTests>true</skipTests> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
<resources> | |||
<resource> | |||
<filtering>true</filtering> | |||
<directory>src/main/resources</directory> | |||
</resource> | |||
</resources> | |||
</build> | |||
</project> |
@@ -0,0 +1,32 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.annotation; | |||
import java.lang.annotation.*; | |||
/** | |||
* @description API版本控制注解 | |||
* @date 2020-04-06 | |||
*/ | |||
@Target({ElementType.METHOD, ElementType.TYPE}) | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@Documented | |||
public @interface ApiVersion { | |||
//标识版本号 | |||
int value() default 1; | |||
} |
@@ -0,0 +1,44 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.annotation; | |||
import java.lang.annotation.*; | |||
/** | |||
* 数据权限过滤Mapper拦截 | |||
* | |||
* @date 2020-06-22 | |||
*/ | |||
@Target({ElementType.METHOD, ElementType.TYPE}) | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@Documented | |||
public @interface DataPermission { | |||
/** | |||
* 不需要数据权限的方法名 | |||
*/ | |||
String[] ignores() default {}; | |||
/** | |||
* 只在方法的注解上使用,代表方法的数据权限类型,如果不加注解,只会识别带"select"方法名的方法 | |||
* | |||
* @return | |||
*/ | |||
String[] permission() default {}; | |||
} |
@@ -0,0 +1,87 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.annotation; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
import java.lang.reflect.InvocationTargetException; | |||
import java.lang.reflect.Method; | |||
import javax.validation.Constraint; | |||
import javax.validation.ConstraintValidator; | |||
import javax.validation.ConstraintValidatorContext; | |||
import javax.validation.Payload; | |||
/** | |||
* @date: 2020-05-21 | |||
*/ | |||
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE }) | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@Constraint(validatedBy = EnumValue.Validator.class) | |||
public @interface EnumValue { | |||
String message() default "custom.value.invalid"; | |||
Class<?>[] groups() default {}; | |||
Class<? extends Payload>[] payload() default {}; | |||
Class<? extends Enum<?>> enumClass(); | |||
String enumMethod(); | |||
class Validator implements ConstraintValidator<EnumValue, Object> { | |||
private Class<? extends Enum<?>> enumClass; | |||
private String enumMethod; | |||
@Override | |||
public void initialize(EnumValue enumValue) { | |||
enumMethod = enumValue.enumMethod(); | |||
enumClass = enumValue.enumClass(); | |||
} | |||
@Override | |||
public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) { | |||
if (value == null) { | |||
return Boolean.TRUE; | |||
} | |||
if (enumClass == null || enumMethod == null) { | |||
return Boolean.TRUE; | |||
} | |||
Class<?> valueClass = value.getClass(); | |||
try { | |||
Method method = enumClass.getMethod(enumMethod, valueClass); | |||
if (!Boolean.TYPE.equals(method.getReturnType()) && !Boolean.class.equals(method.getReturnType())) { | |||
throw new RuntimeException(String.format("%s method return is not boolean type in the %s class", enumMethod, enumClass)); | |||
} | |||
Boolean result = (Boolean)method.invoke(null, value); | |||
return result == null ? false : result; | |||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { | |||
throw new RuntimeException(e); | |||
} catch (NoSuchMethodException | SecurityException e) { | |||
throw new RuntimeException(String.format("This %s(%s) method does not exist in the %s", enumMethod, valueClass, enumClass), e); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,23 @@ | |||
/** | |||
* Copyright 2019-2020 Zheng Jie | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package org.dubhe.annotation; | |||
/** | |||
* @description 日志 | |||
* @date 2020-03-15 | |||
*/ | |||
public @interface Log { | |||
} |
@@ -0,0 +1,68 @@ | |||
/** | |||
* Copyright 2019-2020 Zheng Jie | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package org.dubhe.annotation; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
/** | |||
* @description 构建Wrapper的注解 | |||
* @date 2020-03-26 | |||
*/ | |||
@Target(ElementType.FIELD) | |||
@Retention(RetentionPolicy.RUNTIME) | |||
public @interface Query { | |||
String propName() default ""; | |||
Type type() default Type.EQ; | |||
String blurry() default ""; | |||
enum Type { | |||
// 相等 | |||
EQ | |||
// 不等于 | |||
, NE | |||
// 大于 | |||
, GT | |||
// 大于等于 | |||
, GE | |||
// 小于 | |||
, LT | |||
// 小于等于 | |||
, LE, | |||
BETWEEN, | |||
NOT_BETWEEN, | |||
LIKE, | |||
NOT_LIKE, | |||
LIkE_LEFT, | |||
LIKE_RIGHT, | |||
IS_NULL, | |||
IS_NOT_NULL, | |||
IN, | |||
NOT_IN, | |||
INSQL, | |||
NOT_INSQL, | |||
ORDER_BY | |||
} | |||
} | |||
@@ -0,0 +1,33 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.annotation; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
/** | |||
* @description 限流 | |||
* @date 2020-03-15 | |||
*/ | |||
@Target(ElementType.METHOD) | |||
@Retention(RetentionPolicy.RUNTIME) | |||
public @interface RateLimit { | |||
double limitNum() default 20; | |||
} |
@@ -0,0 +1,87 @@ | |||
/** | |||
* Copyright 2019-2020 Zheng Jie | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package org.dubhe.aspect; | |||
import java.util.UUID; | |||
import org.aspectj.lang.JoinPoint; | |||
import org.aspectj.lang.ProceedingJoinPoint; | |||
import org.aspectj.lang.annotation.Around; | |||
import org.aspectj.lang.annotation.Aspect; | |||
import org.aspectj.lang.annotation.Pointcut; | |||
import org.dubhe.enums.LogEnum; | |||
import org.dubhe.utils.LogUtil; | |||
import org.slf4j.MDC; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.util.StringUtils; | |||
import lombok.extern.slf4j.Slf4j; | |||
/** | |||
* @date 2020/04/10 | |||
*/ | |||
@Component | |||
@Aspect | |||
@Slf4j | |||
public class LogAspect { | |||
public static final String TRACE_ID = "traceId"; | |||
@Pointcut("execution(* org.dubhe..service..*.*(..))) " | |||
+ "and execution(* org.dubhe..schedule..*.*(..))) " | |||
+ "and execution(* org.dubhe..util*..*.*(..)))") | |||
public void serviceAspect() { | |||
} | |||
@Pointcut("execution(* org.dubhe..rest..*.*(..))) ") | |||
public void restAspect() { | |||
} | |||
@Pointcut(" execution(* org.dubhe..task..*.*(..))) ") | |||
public void taskAspect() { | |||
} | |||
@Pointcut(" serviceAspect() || taskAspect() ") | |||
public void aroundAspect() { | |||
} | |||
@Around("aroundAspect()") | |||
public Object around(JoinPoint joinPoint) throws Throwable { | |||
if (StringUtils.isEmpty(MDC.get(TRACE_ID))) { | |||
MDC.put(TRACE_ID, UUID.randomUUID().toString()); | |||
} | |||
return combineLogInfo(joinPoint); | |||
} | |||
@Around("restAspect()") | |||
public Object aroundRest(JoinPoint joinPoint) throws Throwable { | |||
MDC.clear(); | |||
MDC.put(TRACE_ID, UUID.randomUUID().toString()); | |||
return combineLogInfo(joinPoint); | |||
} | |||
private Object combineLogInfo(JoinPoint joinPoint) throws Throwable { | |||
Object[] param = joinPoint.getArgs(); | |||
LogUtil.info(LogEnum.REST_REQ, "uri:{},input:{},==>begin", joinPoint.getSignature(), param); | |||
long start = System.currentTimeMillis(); | |||
Object result = ((ProceedingJoinPoint) joinPoint).proceed(); | |||
long end = System.currentTimeMillis(); | |||
LogUtil.info(LogEnum.REST_REQ, "uri:{},output:{},proc_time:{},<==end", joinPoint.getSignature().toString(), | |||
result, end - start); | |||
return result; | |||
} | |||
} |
@@ -0,0 +1,58 @@ | |||
/** | |||
* Copyright 2019-2020 Zheng Jie | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package org.dubhe.base; | |||
import java.util.List; | |||
/** | |||
* @description DTO Entity 转换 | |||
* @date 2020-03-15 | |||
*/ | |||
public interface BaseConvert<D, E> { | |||
/** | |||
* DTO转Entity | |||
* | |||
* @param dto / | |||
* @return / | |||
*/ | |||
E toEntity(D dto); | |||
/** | |||
* Entity转DTO | |||
* | |||
* @param entity / | |||
* @return / | |||
*/ | |||
D toDto(E entity); | |||
/** | |||
* DTO集合转Entity集合 | |||
* | |||
* @param dtoList / | |||
* @return / | |||
*/ | |||
List<E> toEntity(List<D> dtoList); | |||
/** | |||
* Entity集合转DTO集合 | |||
* | |||
* @param entityList / | |||
* @return / | |||
*/ | |||
List<D> toDto(List<E> entityList); | |||
} |
@@ -0,0 +1,48 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.base; | |||
import lombok.Getter; | |||
import lombok.Setter; | |||
import java.io.Serializable; | |||
import java.sql.Timestamp; | |||
/** | |||
* @description DTO基础类 | |||
* @date 2020-03-15 | |||
*/ | |||
@Getter | |||
@Setter | |||
public class BaseDTO implements Serializable { | |||
private Boolean deleted; | |||
private Timestamp createTime; | |||
private Timestamp updateTime; | |||
@Override | |||
public String toString() { | |||
return "BaseDTO{" + | |||
"deleted=" + deleted + | |||
", createTime=" + createTime + | |||
", updateTime=" + updateTime + | |||
'}'; | |||
} | |||
} |
@@ -0,0 +1,76 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.base; | |||
import com.baomidou.mybatisplus.annotation.FieldFill; | |||
import com.baomidou.mybatisplus.annotation.TableField; | |||
import com.baomidou.mybatisplus.annotation.TableLogic; | |||
import lombok.Data; | |||
import org.apache.commons.lang3.builder.ToStringBuilder; | |||
import java.io.Serializable; | |||
import java.lang.reflect.Field; | |||
import java.sql.Timestamp; | |||
/** | |||
* @description Entity基础类 | |||
* @date 2020-03-15 | |||
*/ | |||
@Data | |||
public class BaseEntity implements Serializable { | |||
private static final long serialVersionUID = 4936056317364745513L; | |||
/** | |||
* 删除标识 | |||
**/ | |||
@TableField(value = "deleted",fill = FieldFill.INSERT) | |||
@TableLogic | |||
private Boolean deleted = false; | |||
@TableField(value = "create_user_id",fill = FieldFill.INSERT) | |||
private Long createUserId; | |||
@TableField(value = "update_user_id",fill = FieldFill.INSERT_UPDATE) | |||
private Long updateUserId; | |||
@TableField(value = "create_time",fill = FieldFill.INSERT) | |||
private Timestamp createTime; | |||
@TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE) | |||
private Timestamp updateTime; | |||
@Override | |||
public String toString() { | |||
ToStringBuilder builder = new ToStringBuilder(this); | |||
Field[] fields = this.getClass().getDeclaredFields(); | |||
try { | |||
for (Field f : fields) { | |||
f.setAccessible(true); | |||
builder.append(f.getName(), f.get(this)).append("\n"); | |||
} | |||
} catch (Exception e) { | |||
builder.append("toString builder encounter an error"); | |||
} | |||
return builder.toString(); | |||
} | |||
public @interface Update { | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.base; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import lombok.experimental.Accessors; | |||
import javax.validation.constraints.NotBlank; | |||
import java.io.Serializable; | |||
/** | |||
* @description 镜像基础类DTO | |||
* @date: 2020-07-14 | |||
*/ | |||
@Data | |||
@Accessors(chain = true) | |||
public class BaseImageDTO implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
@ApiModelProperty(value = "镜像版本", required = true) | |||
@NotBlank(message = "镜像版本不能为空") | |||
private String imageTag; | |||
@ApiModelProperty(value = "镜像名称", required = true) | |||
@NotBlank(message = "镜像名称不能为空") | |||
private String imageName; | |||
} |
@@ -0,0 +1,46 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.base; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import java.io.Serializable; | |||
import java.sql.Timestamp; | |||
/** | |||
* @description: VO基础类 | |||
* @date: 2020-05-22 | |||
*/ | |||
@Data | |||
public class BaseVO implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
@ApiModelProperty("创建人") | |||
private Long createUserId; | |||
@ApiModelProperty("创建时间") | |||
private Timestamp createTime; | |||
@ApiModelProperty("修改人") | |||
private Long updateUserId; | |||
@ApiModelProperty("修改时间") | |||
private Timestamp updateTime; | |||
} |
@@ -0,0 +1,76 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.base; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import org.slf4j.MDC; | |||
import java.io.Serializable; | |||
/** | |||
* @description 统一的公共响应体 | |||
* @date 2020-03-16 | |||
*/ | |||
@Data | |||
@ApiModel(description = "统一的公共响应体") | |||
public class DataResponseBody<T> implements Serializable { | |||
/** | |||
* 返回状态码 | |||
*/ | |||
@ApiModelProperty("返回状态码") | |||
private Integer code; | |||
/** | |||
* 返回信息 | |||
*/ | |||
@ApiModelProperty("返回信息") | |||
private String msg; | |||
/** | |||
* 泛型数据 | |||
*/ | |||
@ApiModelProperty("泛型数据") | |||
private T data; | |||
/** | |||
* 链路追踪ID | |||
*/ | |||
@ApiModelProperty("链路追踪ID") | |||
private String traceId; | |||
public DataResponseBody() { | |||
this(ResponseCode.SUCCESS, null); | |||
} | |||
public DataResponseBody(T data) { | |||
this(ResponseCode.SUCCESS, null, data); | |||
} | |||
public DataResponseBody(Integer code, String msg) { | |||
this(code, msg, null); | |||
} | |||
public DataResponseBody(Integer code, String msg, T data) { | |||
this.code = code; | |||
this.msg = msg; | |||
this.data = data; | |||
this.traceId = MDC.get("traceId"); | |||
} | |||
} |
@@ -0,0 +1,99 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.base; | |||
/** | |||
* @date: 2020-05-14 | |||
*/ | |||
public final class MagicNumConstant { | |||
public static final int NEGATIVE_ONE = -1; | |||
public static final int ZERO = 0; | |||
public static final int ONE = 1; | |||
public static final int TWO = 2; | |||
public static final int THREE = 3; | |||
public static final int FOUR = 4; | |||
public static final int FIVE = 5; | |||
public static final int SIX = 6; | |||
public static final int SEVEN = 7; | |||
public static final int EIGHT = 8; | |||
public static final int NINE = 9; | |||
public static final int TEN = 10; | |||
public static final int ELEVEN = 11; | |||
public static final int SIXTEEN = 16; | |||
public static final int TWENTY = 20; | |||
public static final int FIFTY = 50; | |||
public static final int SIXTY = 60; | |||
public static final int SIXTY_TWO = 62; | |||
public static final int SIXTY_FOUR = 64; | |||
public static final int INTEGER_TWO_HUNDRED_AND_FIFTY_FIVE = 255; | |||
public static final int ONE_HUNDRED = 100; | |||
public static final int ONE_HUNDRED_TWENTY_EIGHT = 128; | |||
public static final int TWO_HUNDRED = 200; | |||
public static final int FIVE_HUNDRED = 500; | |||
public static final int FIVE_HUNDRED_AND_SIXTEEN = 516; | |||
public static final int ONE_THOUSAND = 1000; | |||
public static final int BINARY_TEN_EXP = 1024; | |||
public static final int ONE_THOUSAND_ONE_HUNDRED = 1100; | |||
public static final int ONE_THOUSAND_ONE_HUNDRED_ONE = 1101; | |||
public static final int ONE_THOUSAND_TWO_HUNDRED = 1200; | |||
public static final int ONE_THOUSAND_TWO_HUNDRED_ONE = 1201; | |||
public static final int ONE_THOUSAND_TWENTY_FOUR = 1024; | |||
public static final int ONE_THOUSAND_THREE_HUNDRED = 1300; | |||
public static final int ONE_THOUSAND_THREE_HUNDRED_ONE = 1301; | |||
public static final int ONE_THOUSAND_THREE_HUNDRED_NINE = 1309; | |||
public static final int ONE_THOUSAND_FIVE_HUNDRED = 1500; | |||
public static final int TWO_THOUSAND = 2000; | |||
public static final int TWO_THOUSAND_TWENTY_EIGHT = 2048; | |||
public static final int THREE_THOUSAND = 3000; | |||
public static final int FOUR_THOUSAND = 4000; | |||
public static final int NINE_THOUSAND = 9000; | |||
public static final int NINE_THOUSAND_NINE_HUNDRED_NINTY_NINE = 9999; | |||
public static final int TEN_THOUSAND = 10000; | |||
public static final int FIFTEEN_THOUSAND = 15000; | |||
public static final int HUNDRED_THOUSAND = 100000; | |||
public static final int MILLION = 1000000; | |||
public static final int ONE_MINUTE = 60000; | |||
public static final long NEGATIVE_ONE__LONG = -1L; | |||
public static final long ZERO_LONG = 0L; | |||
public static final long ONE_LONG = 1L; | |||
public static final long TWO_LONG = 2L; | |||
public static final long THREE_LONG = 3L; | |||
public static final long FOUR_LONG = 4L; | |||
public static final long FIVE_LONG = 5L; | |||
public static final long SIX_LONG = 6L; | |||
public static final long SEVEN_LONG = 7L; | |||
public static final long EIGHT_LONG = 8L; | |||
public static final long NINE_LONG = 9L; | |||
public static final long TEN_LONG = 10L; | |||
public static final long TWELVE_LONG = 12L; | |||
public static final long SIXTY_LONG = 60L; | |||
public static final long TEN_THOUSAND_LONG = 10000L; | |||
public static final long ONE_ZERO_ONE_ZERO_ONE_ZERO_LONG = 101010L; | |||
public static final long NINE_ZERO_NINE_ZERO_NINE_ZERO_LONG = 909090L; | |||
public static final long ONE_YEAR_BEFORE_LONG = 1552579200000L; | |||
public static final int SIXITY_0XFF = 0xFF; | |||
private MagicNumConstant() { | |||
} | |||
} |
@@ -0,0 +1,62 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.base; | |||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import lombok.experimental.Accessors; | |||
import org.dubhe.constant.NumberConstant; | |||
import javax.validation.constraints.Min; | |||
/** | |||
* @description: 分页基类 | |||
* @date: 2020-05-8 | |||
*/ | |||
@Data | |||
@Accessors(chain = true) | |||
public class PageQueryBase<T> { | |||
@ApiModelProperty(value = "分页-当前页数") | |||
@Min(value = 1, message = "current不能小于1") | |||
private Integer current; | |||
@ApiModelProperty(value = "分页-每页展示数") | |||
@Min(value = 1, message = "size不能小于1") | |||
private Integer size; | |||
@ApiModelProperty(value = "排序字段") | |||
private String sort; | |||
@ApiModelProperty(value = "排序方式,asc | desc") | |||
private String order; | |||
public Page<T> toPage() { | |||
Page<T> page = new Page(); | |||
if (this.current != null) { | |||
page.setCurrent(this.current); | |||
} | |||
if (this.size != null && this.size < NumberConstant.MAX_PAGE_SIZE) { | |||
page.setSize(this.size); | |||
} | |||
return page; | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.base; | |||
/** | |||
* @description 返回状态码 | |||
* @date 2020-02-23 | |||
*/ | |||
public class ResponseCode { | |||
public static Integer SUCCESS = 200; | |||
public static Integer UNAUTHORIZED = 401; | |||
public static Integer ERROR = 10000; | |||
public static Integer ENTITY_NOT_EXIST = 10001; | |||
public static Integer BADREQUEST = 10002; | |||
public static Integer SERVICE_ERROR = 10003; | |||
public static Integer DOCKER_ERROR = 10004; | |||
} |
@@ -0,0 +1,56 @@ | |||
/** | |||
* Copyright 2019-2020 Zheng Jie | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package org.dubhe.config; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
import org.springframework.web.cors.CorsConfiguration; | |||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | |||
import org.springframework.web.filter.CorsFilter; | |||
/** | |||
* @description 允许跨域 | |||
* @date 2020-02-23 | |||
*/ | |||
@Configuration | |||
public class GlobalCorsConfig { | |||
@Bean | |||
public CorsFilter corsFilter() { | |||
//1.添加CORS配置信息 | |||
CorsConfiguration config = new CorsConfiguration(); | |||
//放行哪些原始域 | |||
config.addAllowedOrigin("*"); | |||
//是否发送Cookie信息 | |||
config.setAllowCredentials(true); | |||
//放行哪些原始域(请求方式) | |||
config.addAllowedMethod("OPTIONS"); | |||
config.addAllowedMethod("HEAD"); | |||
config.addAllowedMethod("GET"); | |||
config.addAllowedMethod("PUT"); | |||
config.addAllowedMethod("POST"); | |||
config.addAllowedMethod("DELETE"); | |||
config.addAllowedMethod("PATCH"); | |||
config.addAllowedHeader("*"); | |||
//2.添加映射路径 | |||
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); | |||
configSource.registerCorsConfiguration("/**", config); | |||
//3.返回新的CorsFilter. | |||
return new CorsFilter(configSource); | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.config; | |||
import lombok.Getter; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.context.annotation.Configuration; | |||
/** | |||
* @description k8s命名相关配置 | |||
* | |||
* @date 2020-05-13 | |||
*/ | |||
@Getter | |||
@Configuration | |||
public class K8sNameConfig { | |||
@Value("${k8s.nfs-root-path}") | |||
private String nfsRootPath; | |||
@Value("${k8s.namespace}") | |||
private String namespace; | |||
@Value("${minio.bucketName}") | |||
private String fileBucket; | |||
@Value("${train-job.docker-dataset-path}") | |||
private String datasetPath; | |||
} |
@@ -0,0 +1,65 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.config; | |||
import com.google.code.kaptcha.impl.DefaultKaptcha; | |||
import com.google.code.kaptcha.util.Config; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.stereotype.Component; | |||
import java.util.Properties; | |||
/** | |||
* @description 验证码配置 | |||
* @date 2020-02-23 | |||
*/ | |||
@Component | |||
public class KaptchaConfig { | |||
private final static String CODE_LENGTH = "4"; | |||
private final static String SESSION_KEY = "verification_session_key"; | |||
@Bean | |||
public DefaultKaptcha defaultKaptcha() { | |||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); | |||
Properties properties = new Properties(); | |||
// 设置边框 | |||
properties.setProperty("kaptcha.border", "yes"); | |||
// 设置边框颜色 | |||
properties.setProperty("kaptcha.border.color", "105,179,90"); | |||
// 设置字体颜色 | |||
properties.setProperty("kaptcha.textproducer.font.color", "blue"); | |||
// 设置图片宽度 | |||
properties.setProperty("kaptcha.image.width", "108"); | |||
// 设置图片高度 | |||
properties.setProperty("kaptcha.image.height", "28"); | |||
// 设置字体尺寸 | |||
properties.setProperty("kaptcha.textproducer.font.size", "26"); | |||
// 设置session key | |||
properties.setProperty("kaptcha.session.key", SESSION_KEY); | |||
// 设置验证码长度 | |||
properties.setProperty("kaptcha.textproducer.char.length", CODE_LENGTH); | |||
// 设置字体 | |||
properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,黑体"); | |||
//去噪点 | |||
properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise"); | |||
Config config = new Config(properties); | |||
defaultKaptcha.setConfig(config); | |||
return defaultKaptcha; | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.config; | |||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
import java.time.LocalDateTime; | |||
import java.time.format.DateTimeFormatter; | |||
@Configuration | |||
public class LocalDateTimeSerializerConfig { | |||
@Value("${spring.jackson.date-format}") | |||
private String pattern; | |||
@Bean | |||
public LocalDateTimeSerializer localDateTimeDeserializer() { | |||
return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern)); | |||
} | |||
@Bean | |||
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { | |||
return builder -> builder.serializerByType(LocalDateTime.class, localDateTimeDeserializer()); | |||
} | |||
} |
@@ -0,0 +1,95 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.config; | |||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; | |||
import org.apache.ibatis.reflection.MetaObject; | |||
import org.dubhe.constant.StringConstant; | |||
import org.dubhe.domain.dto.UserDTO; | |||
import org.dubhe.enums.SwitchEnum; | |||
import org.dubhe.utils.DateUtil; | |||
import org.dubhe.utils.JwtUtils; | |||
import org.springframework.stereotype.Component; | |||
import java.util.Objects; | |||
/** | |||
* @description 处理新增和更新的基础数据填充,配合BaseEntity和MyBatisPlusConfig使用 | |||
* @date 2020-6-10 | |||
*/ | |||
@Component | |||
public class MetaHandlerConfig implements MetaObjectHandler { | |||
private final String LOCK_USER_ID = "LOCK_USER_ID"; | |||
/** | |||
* 新增数据执行 | |||
* | |||
* @param metaObject | |||
*/ | |||
@Override | |||
public void insertFill(MetaObject metaObject) { | |||
if (Objects.isNull(getFieldValByName(StringConstant.CREATE_TIME, metaObject))) { | |||
this.setFieldValByName(StringConstant.CREATE_TIME, DateUtil.getCurrentTimestamp(), metaObject); | |||
} | |||
if (Objects.isNull(getFieldValByName(StringConstant.UPDATE_TIME, metaObject))) { | |||
this.setFieldValByName(StringConstant.UPDATE_TIME, DateUtil.getCurrentTimestamp(), metaObject); | |||
} | |||
synchronized (LOCK_USER_ID){ | |||
if (Objects.isNull(getFieldValByName(StringConstant.UPDATE_USER_ID, metaObject))) { | |||
this.setFieldValByName(StringConstant.UPDATE_USER_ID, getUserId(), metaObject); | |||
} | |||
if (Objects.isNull(getFieldValByName(StringConstant.CREATE_USER_ID, metaObject))) { | |||
this.setFieldValByName(StringConstant.CREATE_USER_ID, getUserId(), metaObject); | |||
} | |||
} | |||
if (Objects.isNull(getFieldValByName(StringConstant.DELETED, metaObject))) { | |||
this.setFieldValByName(StringConstant.DELETED, SwitchEnum.getBooleanValue(SwitchEnum.OFF.getValue()), metaObject); | |||
} | |||
} | |||
/** | |||
* 更新数据执行 | |||
* | |||
* @param metaObject | |||
*/ | |||
@Override | |||
public void updateFill(MetaObject metaObject) { | |||
if (Objects.isNull(getFieldValByName(StringConstant.UPDATE_TIME, metaObject))) { | |||
this.setFieldValByName(StringConstant.UPDATE_TIME, DateUtil.getCurrentTimestamp(), metaObject); | |||
} | |||
if (Objects.isNull(getFieldValByName(StringConstant.UPDATE_USER_ID, metaObject))) { | |||
this.setFieldValByName(StringConstant.UPDATE_USER_ID, getUserId(), metaObject); | |||
} | |||
} | |||
/** | |||
* 获取用户ID | |||
* | |||
* @return | |||
*/ | |||
private Long getUserId() { | |||
UserDTO userDTO = JwtUtils.getCurrentUserDto(); | |||
return Objects.isNull(userDTO) ? null : userDTO.getId(); | |||
} | |||
} |
@@ -0,0 +1,310 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.config; | |||
import com.baomidou.mybatisplus.core.override.MybatisMapperProxy; | |||
import com.baomidou.mybatisplus.core.parser.ISqlParser; | |||
import com.baomidou.mybatisplus.core.parser.SqlParserHelper; | |||
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; | |||
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler; | |||
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser; | |||
import com.google.common.collect.Sets; | |||
import net.sf.jsqlparser.expression.Expression; | |||
import net.sf.jsqlparser.expression.LongValue; | |||
import net.sf.jsqlparser.expression.operators.relational.ExpressionList; | |||
import net.sf.jsqlparser.expression.operators.relational.InExpression; | |||
import net.sf.jsqlparser.schema.Column; | |||
import org.apache.ibatis.mapping.MappedStatement; | |||
import org.apache.shiro.UnavailableSecurityManagerException; | |||
import org.dubhe.annotation.DataPermission; | |||
import org.dubhe.base.MagicNumConstant; | |||
import org.dubhe.constant.PermissionConstant; | |||
import org.dubhe.domain.dto.UserDTO; | |||
import org.dubhe.domain.entity.Role; | |||
import org.dubhe.enums.LogEnum; | |||
import org.dubhe.utils.JwtUtils; | |||
import org.dubhe.utils.LogUtil; | |||
import org.springframework.beans.BeansException; | |||
import org.springframework.context.ApplicationContext; | |||
import org.springframework.context.ApplicationContextAware; | |||
import org.springframework.context.ApplicationListener; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
import org.springframework.context.event.ContextRefreshedEvent; | |||
import org.springframework.core.annotation.AnnotationUtils; | |||
import org.springframework.transaction.annotation.EnableTransactionManagement; | |||
import org.springframework.util.CollectionUtils; | |||
import java.lang.annotation.Annotation; | |||
import java.lang.reflect.Field; | |||
import java.lang.reflect.Method; | |||
import java.lang.reflect.Proxy; | |||
import java.util.*; | |||
import java.util.stream.Collectors; | |||
/** | |||
* @description MybatisPlus配置类 | |||
* @date 2020-06-24 | |||
*/ | |||
@EnableTransactionManagement | |||
@Configuration | |||
public class MybatisPlusConfig implements ApplicationListener<ContextRefreshedEvent>, ApplicationContextAware { | |||
/** | |||
* 以此字段作为租户实现数据隔离 | |||
*/ | |||
private static final String TENANT_ID_COLUMN = "create_user_id"; | |||
/** | |||
* 以0作为公共数据的标识 | |||
*/ | |||
private static final long PUBLIC_TENANT_ID = MagicNumConstant.ZERO; | |||
private static final Set<Long> PUBLIC_TENANT_ID_SET = new HashSet<Long>() {{ | |||
add(PUBLIC_TENANT_ID); | |||
}}; | |||
private static final String PACKAGE_SEPARATOR = "."; | |||
private static final Set<String> SELECT_PERMISSION = new HashSet<String>() {{ | |||
add(PermissionConstant.SELECT); | |||
}}; | |||
private static final Set<String> UPDATE_DELETE_PERMISSION = new HashSet<String>() {{ | |||
add(PermissionConstant.UPDATE); | |||
add(PermissionConstant.DELETE); | |||
}}; | |||
private static final String SELECT_STR = "select"; | |||
/** | |||
* 优先级高于dataFilters,如果ignore,则不进行sql注入 | |||
*/ | |||
private Map<String, Set<String>> dataFilters = new HashMap<>(); | |||
private ApplicationContext applicationContext; | |||
public Set<Long> tenantId; | |||
/** | |||
* mybatis plus 分页插件 | |||
* 其中增加了通过多租户实现了数据权限功能 | |||
* | |||
* @return | |||
*/ | |||
@Bean | |||
public PaginationInterceptor paginationInterceptor() { | |||
PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); | |||
List<ISqlParser> sqlParserList = new ArrayList<>(); | |||
TenantSqlParser tenantSqlParser = new TenantSqlParser(); | |||
tenantSqlParser.setTenantHandler(new TenantHandler() { | |||
@Override | |||
public Expression getTenantId(boolean where) { | |||
Set<Long> tenants = tenantId; | |||
final boolean multipleTenantIds = tenants.size() > MagicNumConstant.ONE; | |||
if (multipleTenantIds) { | |||
return multipleTenantIdCondition(tenants); | |||
} else { | |||
return singleTenantIdCondition(tenants); | |||
} | |||
} | |||
private Expression singleTenantIdCondition(Set<Long> tenants) { | |||
return new LongValue((Long) tenants.toArray()[0]); | |||
} | |||
private Expression multipleTenantIdCondition(Set<Long> tenants) { | |||
final InExpression inExpression = new InExpression(); | |||
inExpression.setLeftExpression(new Column(getTenantIdColumn())); | |||
final ExpressionList itemsList = new ExpressionList(); | |||
final List<Expression> inValues = new ArrayList<>(tenants.size()); | |||
tenants.forEach(i -> | |||
inValues.add(new LongValue(i)) | |||
); | |||
itemsList.setExpressions(inValues); | |||
inExpression.setRightItemsList(itemsList); | |||
return inExpression; | |||
} | |||
@Override | |||
public String getTenantIdColumn() { | |||
return TENANT_ID_COLUMN; | |||
} | |||
@Override | |||
public boolean doTableFilter(String tableName) { | |||
return false; | |||
} | |||
}); | |||
sqlParserList.add(tenantSqlParser); | |||
paginationInterceptor.setSqlParserList(sqlParserList); | |||
paginationInterceptor.setSqlParserFilter(metaObject -> { | |||
MappedStatement ms = SqlParserHelper.getMappedStatement(metaObject); | |||
String method = ms.getId(); | |||
if (!dataFilters.containsKey(method) || isAdmin()) { | |||
return true; | |||
} | |||
Set<String> permission = dataFilters.get(method); | |||
tenantId = getTenantId(permission); | |||
return false; | |||
}); | |||
return paginationInterceptor; | |||
} | |||
/** | |||
* 判断用户是否是管理员 | |||
* 如果未登录,无法请求任何接口,所以不会到该层,因此匿名认为是定时任务,给予admin权限。 | |||
* | |||
* @return 判断用户是否是管理员 | |||
*/ | |||
private boolean isAdmin() { | |||
UserDTO user; | |||
try { | |||
user = JwtUtils.getCurrentUserDto(); | |||
} catch (UnavailableSecurityManagerException e) { | |||
return true; | |||
} | |||
if (Objects.isNull(user)) { | |||
return true; | |||
} | |||
List<Role> roles; | |||
if ((roles = user.getRoles()) == null) { | |||
return false; | |||
} | |||
Set<String> permissions = roles.stream().map(Role::getPermission).collect(Collectors.toSet()); | |||
if (CollectionUtils.isEmpty(permissions)) { | |||
return false; | |||
} | |||
return user.getId() == PermissionConstant.ANONYMOUS_USER || user.getId() == PermissionConstant.ADMIN_USER_ID; | |||
} | |||
/** | |||
* 如果是管理员,在前一步isAdmin已过滤; | |||
* 如果是匿名用户,在shiro层被过滤; | |||
* 因此只会是无角色、权限用户或普通用户 | |||
* | |||
* @return Set<Long> 租户ID集合 | |||
*/ | |||
private Set<Long> getTenantId(Set<String> permission) { | |||
UserDTO user = JwtUtils.getCurrentUserDto(); | |||
List<Role> roles; | |||
if (Objects.isNull(user) || (roles = user.getRoles()) == null) { | |||
if (permission.contains(PermissionConstant.SELECT)) { | |||
return PUBLIC_TENANT_ID_SET; | |||
} | |||
return Collections.EMPTY_SET; | |||
} | |||
Set<String> permissions = roles.stream().map(Role::getPermission).collect(Collectors.toSet()); | |||
if (CollectionUtils.isEmpty(permissions)) { | |||
if (permission.contains(PermissionConstant.SELECT)) { | |||
return PUBLIC_TENANT_ID_SET; | |||
} | |||
return Collections.EMPTY_SET; | |||
} | |||
if (permission.contains(PermissionConstant.SELECT)) { | |||
return new HashSet<Long>() {{ | |||
add(PUBLIC_TENANT_ID); | |||
add(user.getId()); | |||
}}; | |||
} | |||
return new HashSet<Long>() {{ | |||
add(user.getId()); | |||
}}; | |||
} | |||
/** | |||
* 设置上下文 | |||
* #需要通过上下文 获取SpringBean | |||
* | |||
* @param applicationContext spring上下文 | |||
* @throws BeansException 找不到bean异常 | |||
*/ | |||
@Override | |||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { | |||
this.applicationContext = applicationContext; | |||
} | |||
@Override | |||
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { | |||
Class<? extends Annotation> annotationClass = DataPermission.class; | |||
Map<String, Object> beanWithAnnotation = applicationContext.getBeansWithAnnotation(annotationClass); | |||
Set<Map.Entry<String, Object>> entitySet = beanWithAnnotation.entrySet(); | |||
for (Map.Entry<String, Object> entry : entitySet) { | |||
Proxy proxy = (Proxy) entry.getValue(); | |||
Class clazz = getMapperClass(proxy); | |||
populateDataFilters(clazz); | |||
} | |||
} | |||
/** | |||
* 根据mapper对应代理对象获取Class | |||
* | |||
* @param proxy mapper对应代理对象 | |||
* @return | |||
*/ | |||
private Class getMapperClass(Proxy proxy) { | |||
try { | |||
Field field = proxy.getClass().getSuperclass().getDeclaredField("h"); | |||
field.setAccessible(true); | |||
MybatisMapperProxy mapperProxy = (MybatisMapperProxy) field.get(proxy); | |||
field = mapperProxy.getClass().getDeclaredField("mapperInterface"); | |||
field.setAccessible(true); | |||
return (Class) field.get(mapperProxy); | |||
} catch (NoSuchFieldException | IllegalAccessException e) { | |||
LogUtil.error(LogEnum.BIZ_DATASET, "reflect error", e); | |||
} | |||
return null; | |||
} | |||
/** | |||
* 填充数据权限过滤,处理那些需要排除的方法 | |||
* | |||
* @param clazz 需要处理的类(mapper) | |||
*/ | |||
private void populateDataFilters(Class clazz) { | |||
if (clazz == null) { | |||
return; | |||
} | |||
Method[] methods = clazz.getMethods(); | |||
DataPermission dataPermission = AnnotationUtils.findAnnotation((Class<?>) clazz, DataPermission.class); | |||
Set<String> ignores = Sets.newHashSet(dataPermission.ignores()); | |||
for (Method method : methods) { | |||
if (ignores.contains(method.getName())) { | |||
continue; | |||
} | |||
Set<String> permission = getDataPermission(method); | |||
dataFilters.put(clazz.getName() + PACKAGE_SEPARATOR + method.getName(), permission); | |||
} | |||
} | |||
/** | |||
* 获取方法上权限注解 | |||
* 权限注解包含 | |||
* 1.用户拥有指定权限才可以执行该方法:比如 PermissionConstant.SELECT 表示用户必须拥有select权限,才可以使用该方法 | |||
* 2.方法权限校验排除:比如 ignores = {"insert"} 表示insert方法不做权限处理 | |||
* | |||
* @param method 方法对象 | |||
* @return | |||
*/ | |||
private Set<String> getDataPermission(Method method) { | |||
DataPermission dataPermission = AnnotationUtils.findAnnotation(method, DataPermission.class); | |||
// 无注解时以方法名判断 | |||
if (dataPermission == null) { | |||
if (method.getName().contains(SELECT_STR)) { | |||
return SELECT_PERMISSION; | |||
} | |||
return UPDATE_DELETE_PERMISSION; | |||
} | |||
return Sets.newHashSet(dataPermission.permission()); | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.config; | |||
import lombok.Data; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* @description NFS config | |||
* @create 2020/5/13 | |||
*/ | |||
@Data | |||
@Component | |||
public class NfsConfig { | |||
@Value("${k8s.nfs}") | |||
private String nfsIp; | |||
@Value("${k8s.nfs-root-path}") | |||
private String rootDir; | |||
@Value("/${minio.bucketName}/") | |||
private String bucket; | |||
} |
@@ -0,0 +1,214 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.config; | |||
import cn.hutool.core.lang.Assert; | |||
import com.alibaba.fastjson.JSON; | |||
import com.alibaba.fastjson.parser.ParserConfig; | |||
import com.alibaba.fastjson.serializer.SerializerFeature; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.codec.digest.DigestUtils; | |||
import org.dubhe.utils.StringUtils; | |||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | |||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | |||
import org.springframework.boot.autoconfigure.data.redis.RedisProperties; | |||
import org.springframework.boot.context.properties.EnableConfigurationProperties; | |||
import org.springframework.cache.Cache; | |||
import org.springframework.cache.annotation.CachingConfigurerSupport; | |||
import org.springframework.cache.annotation.EnableCaching; | |||
import org.springframework.cache.interceptor.CacheErrorHandler; | |||
import org.springframework.cache.interceptor.KeyGenerator; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
import org.springframework.data.redis.cache.RedisCacheConfiguration; | |||
import org.springframework.data.redis.connection.RedisConnectionFactory; | |||
import org.springframework.data.redis.core.RedisOperations; | |||
import org.springframework.data.redis.core.RedisTemplate; | |||
import org.springframework.data.redis.serializer.RedisSerializationContext; | |||
import org.springframework.data.redis.serializer.RedisSerializer; | |||
import java.nio.charset.Charset; | |||
import java.nio.charset.StandardCharsets; | |||
import java.time.Duration; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
/** | |||
* @description redis配置类 | |||
* @date 2020-03-25 | |||
*/ | |||
@Slf4j | |||
@Configuration | |||
@EnableCaching | |||
@ConditionalOnClass(RedisOperations.class) | |||
@EnableConfigurationProperties(RedisProperties.class) | |||
public class RedisConfig extends CachingConfigurerSupport { | |||
/** | |||
* 设置 redis 数据默认过期时间,默认2小时 | |||
* 设置@cacheable 序列化方式 | |||
*/ | |||
@Bean | |||
public RedisCacheConfiguration redisCacheConfiguration() { | |||
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); | |||
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig(); | |||
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofHours(2)); | |||
return configuration; | |||
} | |||
@SuppressWarnings("all") | |||
@Bean(name = "redisTemplate") | |||
@ConditionalOnMissingBean(name = "redisTemplate") | |||
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { | |||
RedisTemplate<Object, Object> template = new RedisTemplate<>(); | |||
//序列化 | |||
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); | |||
// value值的序列化采用fastJsonRedisSerializer | |||
template.setValueSerializer(fastJsonRedisSerializer); | |||
template.setHashValueSerializer(fastJsonRedisSerializer); | |||
// 全局开启AutoType,这里方便开发,使用全局的方式 | |||
ParserConfig.getGlobalInstance().setAutoTypeSupport(true); | |||
// 建议使用这种方式,小范围指定白名单 | |||
// ParserConfig.getGlobalInstance().addAccept("org.dubhe.domain"); | |||
// key的序列化采用StringRedisSerializer | |||
template.setKeySerializer(new StringRedisSerializer()); | |||
template.setHashKeySerializer(new StringRedisSerializer()); | |||
template.setConnectionFactory(redisConnectionFactory); | |||
return template; | |||
} | |||
/** | |||
* 自定义缓存key生成策略,默认将使用该策略 | |||
*/ | |||
@Bean | |||
@Override | |||
public KeyGenerator keyGenerator() { | |||
return (target, method, params) -> { | |||
Map<String, Object> container = new HashMap<>(3); | |||
Class<?> targetClassClass = target.getClass(); | |||
// 类地址 | |||
container.put("class", targetClassClass.toGenericString()); | |||
// 方法名称 | |||
container.put("methodName", method.getName()); | |||
// 包名称 | |||
container.put("package", targetClassClass.getPackage()); | |||
// 参数列表 | |||
for (int i = 0; i < params.length; i++) { | |||
container.put(String.valueOf(i), params[i]); | |||
} | |||
// 转为JSON字符串 | |||
String jsonString = JSON.toJSONString(container); | |||
// 做SHA256 Hash计算,得到一个SHA256摘要作为Key | |||
return DigestUtils.sha256Hex(jsonString); | |||
}; | |||
} | |||
@Bean | |||
@Override | |||
public CacheErrorHandler errorHandler() { | |||
// 异常处理,当Redis发生异常时,打印日志,但是程序正常走 | |||
log.info("初始化 -> [{}]", "Redis CacheErrorHandler"); | |||
return new CacheErrorHandler() { | |||
@Override | |||
public void handleCacheGetError(RuntimeException e, Cache cache, Object key) { | |||
log.error("Redis occur handleCacheGetError:key -> [{}]", key, e); | |||
} | |||
@Override | |||
public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) { | |||
log.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e); | |||
} | |||
@Override | |||
public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) { | |||
log.error("Redis occur handleCacheEvictError:key -> [{}]", key, e); | |||
} | |||
@Override | |||
public void handleCacheClearError(RuntimeException e, Cache cache) { | |||
log.error("Redis occur handleCacheClearError:", e); | |||
} | |||
}; | |||
} | |||
} | |||
/** | |||
* Value 序列化 | |||
* | |||
* @param <T> | |||
*/ | |||
class FastJsonRedisSerializer<T> implements RedisSerializer<T> { | |||
private Class<T> clazz; | |||
FastJsonRedisSerializer(Class<T> clazz) { | |||
super(); | |||
this.clazz = clazz; | |||
} | |||
@Override | |||
public byte[] serialize(T t) { | |||
if (t == null) { | |||
return new byte[0]; | |||
} | |||
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8); | |||
} | |||
@Override | |||
public T deserialize(byte[] bytes) { | |||
if (bytes == null || bytes.length <= 0) { | |||
return null; | |||
} | |||
String str = new String(bytes, StandardCharsets.UTF_8); | |||
return JSON.parseObject(str, clazz); | |||
} | |||
} | |||
/** | |||
* 重写序列化器 | |||
* | |||
*/ | |||
class StringRedisSerializer implements RedisSerializer<Object> { | |||
private final Charset charset; | |||
StringRedisSerializer() { | |||
this(StandardCharsets.UTF_8); | |||
} | |||
private StringRedisSerializer(Charset charset) { | |||
Assert.notNull(charset, "Charset must not be null!"); | |||
this.charset = charset; | |||
} | |||
@Override | |||
public String deserialize(byte[] bytes) { | |||
return (bytes == null ? null : new String(bytes, charset)); | |||
} | |||
@Override | |||
public byte[] serialize(Object object) { | |||
String string = JSON.toJSONString(object); | |||
if (StringUtils.isBlank(string)) { | |||
return null; | |||
} | |||
string = string.replace("\"", ""); | |||
return string.getBytes(charset); | |||
} | |||
} |
@@ -0,0 +1,70 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.config; | |||
import org.springframework.context.annotation.PropertySource; | |||
import org.springframework.context.i18n.LocaleContextHolder; | |||
import java.util.HashMap; | |||
import java.util.Locale; | |||
import java.util.Map; | |||
import java.util.ResourceBundle; | |||
/** | |||
* @description 加载配置 | |||
* @date 2020-03-15 | |||
*/ | |||
@PropertySource(value = {"classpath:config/thirdParty.properties", "classpath:i18n/messages*.properties"}) | |||
public final class Resources { | |||
/** | |||
* 第三方登录配置 | |||
*/ | |||
public static final ResourceBundle THIRDPARTY = ResourceBundle.getBundle("config/thirdParty"); | |||
/** | |||
* 国际化信息 | |||
*/ | |||
private static final Map<String, ResourceBundle> MESSAGES = new HashMap<String, ResourceBundle>(); | |||
/** | |||
* 国际化信息 | |||
*/ | |||
public static String getMessage(String key, Object... params) { | |||
Locale locale = LocaleContextHolder.getLocale(); | |||
ResourceBundle message = MESSAGES.get(locale.getLanguage()); | |||
if (message == null) { | |||
synchronized (MESSAGES) { | |||
message = MESSAGES.get(locale.getLanguage()); | |||
if (message == null) { | |||
message = ResourceBundle.getBundle("i18n/messages", locale); | |||
MESSAGES.put(locale.getLanguage(), message); | |||
} | |||
} | |||
} | |||
if (params != null && params.length > 0) { | |||
return String.format(message.getString(key), params); | |||
} | |||
return message.getString(key); | |||
} | |||
/** | |||
* 清除国际化信息 | |||
*/ | |||
public static void flushMessage() { | |||
MESSAGES.clear(); | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.config; | |||
import org.springframework.context.annotation.Configuration; | |||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | |||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; | |||
/** | |||
* @description 关闭Security | |||
* @date 2020-03-25 | |||
*/ | |||
@Configuration | |||
public class SecurityConfig extends WebSecurityConfigurerAdapter { | |||
@Override | |||
protected void configure(HttpSecurity http) throws Exception { | |||
http.authorizeRequests().antMatchers("/**").permitAll().and().csrf().disable(); | |||
} | |||
} |
@@ -0,0 +1,138 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.config; | |||
import com.fasterxml.classmate.TypeResolver; | |||
import com.google.common.base.Predicates; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
import org.springframework.core.Ordered; | |||
import org.springframework.data.domain.Pageable; | |||
import springfox.documentation.builders.ApiInfoBuilder; | |||
import springfox.documentation.builders.ParameterBuilder; | |||
import springfox.documentation.builders.PathSelectors; | |||
import springfox.documentation.schema.AlternateTypeRule; | |||
import springfox.documentation.schema.AlternateTypeRuleConvention; | |||
import springfox.documentation.schema.ModelRef; | |||
import springfox.documentation.service.ApiInfo; | |||
import springfox.documentation.service.Parameter; | |||
import springfox.documentation.spi.DocumentationType; | |||
import springfox.documentation.spring.web.plugins.Docket; | |||
import springfox.documentation.swagger2.annotations.EnableSwagger2; | |||
import java.sql.Timestamp; | |||
import java.util.ArrayList; | |||
import java.util.Date; | |||
import java.util.List; | |||
import static com.google.common.collect.Lists.newArrayList; | |||
import static springfox.documentation.schema.AlternateTypeRules.newRule; | |||
/** | |||
* @description api页面 /swagger-ui.html | |||
* @date 2020-03-25 | |||
*/ | |||
@Configuration | |||
@EnableSwagger2 | |||
public class SwaggerConfig { | |||
@Value("${jwt.header}") | |||
private String tokenHeader; | |||
@Value("${jwt.token-start-with}") | |||
private String tokenStartWith; | |||
@Value("${swagger.enabled}") | |||
private Boolean enabled; | |||
@Value("${server.rest-version}") | |||
private String restVersion; | |||
@Bean | |||
@SuppressWarnings("all") | |||
public Docket createRestApi() { | |||
List<Parameter> pars = new ArrayList<>(); | |||
pars.add(new ParameterBuilder().name(tokenHeader).description("token") | |||
.modelRef(new ModelRef("string")) | |||
.parameterType("header") | |||
.defaultValue(tokenStartWith + " ") | |||
.required(true) | |||
.build()); | |||
pars.add(new ParameterBuilder().name("version").description("版本") | |||
.modelRef(new ModelRef("string")) | |||
.parameterType("path") | |||
.defaultValue(restVersion) | |||
.required(false) | |||
.build()); | |||
return new Docket(DocumentationType.SWAGGER_2) | |||
.enable(enabled) | |||
.apiInfo(apiInfo()) | |||
.select() | |||
.paths(Predicates.not(PathSelectors.regex("/error.*"))) | |||
.build().directModelSubstitute(Timestamp.class, Date.class) | |||
.globalOperationParameters(pars); | |||
} | |||
private ApiInfo apiInfo() { | |||
return new ApiInfoBuilder() | |||
.title("之江天枢一站式人工智能开源平台") | |||
.version("1.0") | |||
.build(); | |||
} | |||
} | |||
/** | |||
* 将Pageable转换展示在swagger中 | |||
*/ | |||
@Configuration | |||
class SwaggerDataConfig { | |||
@Bean | |||
public AlternateTypeRuleConvention pageableConvention(final TypeResolver resolver) { | |||
return new AlternateTypeRuleConvention() { | |||
@Override | |||
public int getOrder() { | |||
return Ordered.HIGHEST_PRECEDENCE; | |||
} | |||
@Override | |||
public List<AlternateTypeRule> rules() { | |||
return newArrayList(newRule(resolver.resolve(Pageable.class), resolver.resolve(Page.class))); | |||
} | |||
}; | |||
} | |||
@ApiModel | |||
@Data | |||
private static class Page { | |||
@ApiModelProperty("页码 (0..N)") | |||
private Integer page; | |||
@ApiModelProperty("每页显示的数目") | |||
private Integer size; | |||
@ApiModelProperty("以下列格式排序标准:property[,asc | desc]。 默认排序顺序为升序。 支持多种排序条件:如:id,asc") | |||
private List<String> sort; | |||
} | |||
} |
@@ -0,0 +1,39 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.config; | |||
import lombok.Data; | |||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* @description harbor相关配置 | |||
* @date 2020-07-17 | |||
*/ | |||
@Data | |||
@Component | |||
@ConfigurationProperties(prefix = "harbor") | |||
public class TrainHarborConfig { | |||
private String address; | |||
private String username; | |||
private String password; | |||
private String modelName; | |||
} |
@@ -0,0 +1,50 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.config; | |||
import org.dubhe.interceptor.K8sCallBackPodInterceptor; | |||
import org.dubhe.utils.K8sCallBackTool; | |||
import org.springframework.context.annotation.Configuration; | |||
import org.springframework.web.servlet.config.annotation.InterceptorRegistration; | |||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; | |||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | |||
import javax.annotation.Resource; | |||
/** | |||
* @description Web Mvc Config | |||
* | |||
* @date 2020-05-28 | |||
*/ | |||
@Configuration | |||
public class WebMvcConfig implements WebMvcConfigurer { | |||
@Resource | |||
private K8sCallBackPodInterceptor k8sCallBackPodInterceptor; | |||
@Override | |||
public void addInterceptors(InterceptorRegistry registry) { | |||
InterceptorRegistration registration = registry.addInterceptor(k8sCallBackPodInterceptor); | |||
// 拦截配置 | |||
registration.addPathPatterns(K8sCallBackTool.getK8sCallbackPaths()); | |||
} | |||
} |
@@ -0,0 +1,35 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.config; | |||
import org.dubhe.handle.CustomRequestMappingHandlerMapping; | |||
import org.springframework.boot.SpringBootConfiguration; | |||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations; | |||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; | |||
/** | |||
* @description API版本控制 | |||
* @date 2020-04-06 | |||
*/ | |||
@SpringBootConfiguration | |||
public class WebMvcRegistrationsConfig implements WebMvcRegistrations { | |||
@Override | |||
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() { | |||
return new CustomRequestMappingHandlerMapping(); | |||
} | |||
} |
@@ -0,0 +1,46 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.constant; | |||
import lombok.Getter; | |||
/** | |||
* @description 算法枚举类 | |||
* @date 2020-05-12 | |||
*/ | |||
@Getter | |||
public enum AlgorithmSourceEnum { | |||
/** | |||
* MINE 算法来源 我的算法 | |||
*/ | |||
MINE(1, "MINE"), | |||
/** | |||
* PRE 算法来源 预置算法 | |||
*/ | |||
PRE(2,"PRE"); | |||
private Integer status; | |||
private String message; | |||
AlgorithmSourceEnum(Integer status, String message) { | |||
this.status = status; | |||
this.message = message; | |||
} | |||
} |
@@ -0,0 +1,39 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.constant; | |||
/** | |||
* @Description 数字常量 | |||
* @Date 2020-6-9 | |||
*/ | |||
public class NumberConstant { | |||
public final static int NUMBER_0 = 0; | |||
public final static int NUMBER_1 = 1; | |||
public final static int NUMBER_2 = 2; | |||
public final static int NUMBER_3 = 3; | |||
public final static int NUMBER_5 = 5; | |||
public final static int NUMBER_10 = 10; | |||
public final static int NUMBER_30 = 30; | |||
public final static int NUMBER_50 = 50; | |||
public final static int NUMBER_60 = 60; | |||
public final static int HOUR_SECOND = 60 * 60; | |||
public final static int DAY_SECOND = 60 * 60 * 24; | |||
public final static int WEEK_SECOND = 60 * 60 * 24 * 7; | |||
public final static int MAX_PAGE_SIZE = 2000; | |||
} |
@@ -0,0 +1,40 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.constant; | |||
import lombok.Data; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* @description: 权限常量 | |||
* @since: 2020-05-25 14:39 | |||
*/ | |||
@Component | |||
@Data | |||
public class PermissionConstant { | |||
/** | |||
* 超级用户 | |||
*/ | |||
public static final long ADMIN_USER_ID = 1L; | |||
public static final long ANONYMOUS_USER = -1L; | |||
public static final String SELECT = "select"; | |||
public static final String UPDATE = "update"; | |||
public static final String DELETE = "delete"; | |||
} |
@@ -0,0 +1,66 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.constant; | |||
/** | |||
* @description 权限标识,对应 menu 表中的 permission 字段 | |||
* @date 2020-05-14 | |||
*/ | |||
public final class Permissions { | |||
/** | |||
* 数据管理 | |||
*/ | |||
public static final String DATA = "data"; | |||
public static final String DATA_DATASET = "data:dataset"; | |||
/** | |||
* 模型开发 | |||
*/ | |||
public static final String DEVELOPMENT = "development"; | |||
public static final String DEVELOPMENT_NOTEBOOK = "development:notebook"; | |||
public static final String DEVELOPMENT_ALGORITHM = "development:algorithm"; | |||
/** | |||
* 训练管理 | |||
*/ | |||
public static final String TRAINING = "training"; | |||
public static final String TRAINING_IMAGE = "training:image"; | |||
public static final String TRAINING_JOB = "training:job"; | |||
/** | |||
* 模型管理 | |||
*/ | |||
public static final String MODEL = "model"; | |||
public static final String MODEL_MODEL = "model:model"; | |||
/** | |||
* 控制台 | |||
*/ | |||
public static final String SYSTEM = "system"; | |||
public static final String SYSTEM_USER = "system:user"; | |||
public static final String SYSTEM_ROLE = "system:role"; | |||
public static final String SYSTEM_MENU = "system:menu"; | |||
public static final String SYSTEM_DICT = "system:dict"; | |||
public static final String SYSTEM_NODE = "system:node"; | |||
public static final String SYSTEM_LOG = "system:log"; | |||
public static final String SYSTEM_TEAM = "system:team"; | |||
private Permissions() { | |||
} | |||
} |
@@ -0,0 +1,46 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.constant; | |||
/** | |||
* @description 字符串constant | |||
* @date 2020-05-14 | |||
*/ | |||
public final class StringConstant { | |||
public static final String MSIE = "MSIE"; | |||
public static final String MOZILLA = "Mozilla"; | |||
/** | |||
* 公共字段 | |||
*/ | |||
public static final String CREATE_TIME = "createTime"; | |||
public static final String UPDATE_TIME = "updateTime"; | |||
public static final String UPDATE_USER_ID = "updateUserId"; | |||
public static final String CREATE_USER_ID = "createUserId"; | |||
public static final String DELETED = "deleted"; | |||
public static final String UTF8 = "utf-8"; | |||
/** | |||
* 测试环境 | |||
*/ | |||
public static final String PROFILE_ACTIVE_TEST = "test"; | |||
private StringConstant() { | |||
} | |||
} |
@@ -0,0 +1,46 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.constant; | |||
/** | |||
* @description 符号常量 | |||
* @Date 2020-5-29 | |||
*/ | |||
public class SymbolConstant { | |||
public static final String SLASH = "/"; | |||
public static final String COMMA = ","; | |||
public static final String COLON = ":"; | |||
public static final String LINEBREAK = "\n"; | |||
public static final String BLANK = ""; | |||
public static final String QUESTION = "?"; | |||
public static final String ZERO = "0"; | |||
public static final String DOT = "."; | |||
public static final String TOKEN = "token"; | |||
public static final String GET = "get"; | |||
public static final String SET = "set"; | |||
public static final String BRACKETS = "{}"; | |||
public static final String BACKSLASH = "\\"; | |||
public static final String BACKSLASH_MARK= "\\\""; | |||
public static final String DOUBLE_MARK= "\"\""; | |||
public static final String MARK= "\""; | |||
private SymbolConstant() { | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.constant; | |||
import lombok.Data; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* @description 算法常量 | |||
* @date 2020-06-02 | |||
*/ | |||
@Data | |||
@Component | |||
public class TrainAlgorithmConstant { | |||
@Value("${train-algorithm.is-train-out}") | |||
private Boolean isTrainOut; | |||
@Value("${train-algorithm.is-train-log}") | |||
private Boolean isTrainLog; | |||
@Value("${train-algorithm.is-visualized-log}") | |||
private Boolean isVisualizedLog; | |||
@Value("${train-algorithm.algorithm-source}") | |||
private Integer algorithmSource; | |||
@Value("${train-algorithm.fork}") | |||
private Boolean fork; | |||
} |
@@ -0,0 +1,100 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.constant; | |||
import lombok.Data; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* @description 训练常量 | |||
* @create: 2020-05-12 | |||
*/ | |||
@Component | |||
@Data | |||
public class TrainJobConstant { | |||
@Value("${train-job.namespace}") | |||
private String namespace; | |||
@Value("${train-job.version-label}") | |||
private String versionLabel; | |||
@Value("${train-job.separator}") | |||
private String separator; | |||
@Value("${train-job.pod-name}") | |||
private String podName; | |||
@Value("${train-job.python-format}") | |||
private String pythonFormat; | |||
@Value("${train-job.manage}") | |||
private String manage; | |||
@Value("${train-job.out-path}") | |||
private String outPath; | |||
@Value("${train-job.log-path}") | |||
private String logPath; | |||
@Value("${train-job.visualized-log-path}") | |||
private String visualizedLogPath; | |||
@Value("${train-job.docker-dataset-path}") | |||
private String dockerDatasetPath; | |||
@Value("${train-job.docker-train-path}") | |||
private String dockerTrainPath; | |||
@Value("${train-job.docker-out-path}") | |||
private String dockerOutPath; | |||
@Value("${train-job.docker-log-path}") | |||
private String dockerLogPath; | |||
@Value("${train-job.docker-dataset}") | |||
private String dockerDataset; | |||
@Value("${train-job.docker-visualized-log-path}") | |||
private String dockerVisualizedLogPath; | |||
@Value("${train-job.load-path}") | |||
private String loadPath; | |||
@Value("${train-job.load-key}") | |||
private String loadKey; | |||
@Value("${train-job.eight}") | |||
private String eight; | |||
@Value("${train-job.plus-eight}") | |||
private String plusEight; | |||
public static final String TRAIN_ID = "trainId"; | |||
public static final String TRAIN_VERSION = "trainVersion"; | |||
public static final String RUN_TIME = "runtime"; | |||
public static final String TRAIN_STATUS = "trainStatus"; | |||
public static final String CREATE_TIME = "createTime"; | |||
public static final String ALGORITHM_NAME = "algorithmName"; | |||
} |
@@ -0,0 +1,36 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.constant; | |||
import org.springframework.stereotype.Component; | |||
import lombok.Data; | |||
/** | |||
* @description 算法用途 | |||
* @date: 2020-06-23 | |||
*/ | |||
@Component | |||
@Data | |||
public class UserAuxiliaryInfoConstant { | |||
public static final String ALGORITHM_USAGE ="algorithem_usage"; | |||
} |
@@ -0,0 +1,65 @@ | |||
/** | |||
* Copyright 2019-2020 Zheng Jie | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package org.dubhe.domain.dto; | |||
import com.fasterxml.jackson.annotation.JsonIgnore; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import org.dubhe.domain.entity.Role; | |||
import org.dubhe.domain.entity.UserAvatar; | |||
import java.io.Serializable; | |||
import java.sql.Timestamp; | |||
import java.util.Date; | |||
import java.util.List; | |||
/** | |||
* @description 用户信息 | |||
* @date 2020-06-29 | |||
*/ | |||
@Data | |||
public class UserDTO implements Serializable { | |||
@ApiModelProperty(hidden = true) | |||
private Long id; | |||
private String username; | |||
private String nickName; | |||
private String sex; | |||
private String email; | |||
private String phone; | |||
private Boolean enabled; | |||
private String remark; | |||
@JsonIgnore | |||
private String password; | |||
private Date lastPasswordResetTime; | |||
private Timestamp createTime; | |||
private List<Role> roles; | |||
private UserAvatar userAvatar; | |||
} |
@@ -0,0 +1,64 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.domain.entity; | |||
import java.io.Serializable; | |||
import org.dubhe.base.MagicNumConstant; | |||
import com.alibaba.fastjson.annotation.JSONField; | |||
import cn.hutool.core.date.DateUtil; | |||
import lombok.Data; | |||
import lombok.experimental.Accessors; | |||
/** | |||
* @description 日志对象封装类 | |||
* @date 2020-06-29 | |||
*/ | |||
@Data | |||
@Accessors(chain = true) | |||
public class LogInfo implements Serializable { | |||
@JSONField(ordinal = MagicNumConstant.ONE) | |||
private String traceId; | |||
@JSONField(ordinal = MagicNumConstant.TWO) | |||
private String type; | |||
@JSONField(ordinal = MagicNumConstant.THREE) | |||
private String level; | |||
@JSONField(ordinal = MagicNumConstant.FOUR) | |||
private String cName; | |||
@JSONField(ordinal = MagicNumConstant.FIVE) | |||
private String mName; | |||
@JSONField(ordinal = MagicNumConstant.SIX) | |||
private String line; | |||
@JSONField(ordinal = MagicNumConstant.SEVEN) | |||
private String time = DateUtil.now(); | |||
@JSONField(ordinal = MagicNumConstant.EIGHT) | |||
private Object info; | |||
public void setInfo(Object info) { | |||
this.info = info; | |||
} | |||
} |
@@ -0,0 +1,120 @@ | |||
/** | |||
* Copyright 2019-2020 Zheng Jie | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package org.dubhe.domain.entity; | |||
import com.baomidou.mybatisplus.annotation.*; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import org.dubhe.base.BaseEntity; | |||
import org.hibernate.validator.constraints.Length; | |||
import javax.validation.constraints.NotBlank; | |||
import javax.validation.constraints.NotNull; | |||
import java.io.Serializable; | |||
import java.sql.Timestamp; | |||
import java.util.Objects; | |||
/** | |||
* @description 菜单实体 | |||
* @date 2020-06-29 | |||
*/ | |||
@Data | |||
@Builder | |||
@AllArgsConstructor | |||
@NoArgsConstructor | |||
@TableName("menu") | |||
public class Menu extends BaseEntity implements Serializable { | |||
private static final long serialVersionUID = 3100515433018008777L; | |||
@TableId(value = "id", type = IdType.AUTO) | |||
private Long id; | |||
@NotBlank | |||
private String name; | |||
@TableField(value = "sort") | |||
private Long sort = 999L; | |||
@TableField(value = "path") | |||
private String path; | |||
@TableField(value = "component") | |||
private String component; | |||
/** | |||
* 类型,目录、菜单、按钮 | |||
*/ | |||
@TableField(value = "type") | |||
private Integer type; | |||
/** | |||
* 权限 | |||
*/ | |||
@TableField(value = "permission") | |||
private String permission; | |||
@TableField(value = "component_name") | |||
private String componentName; | |||
@TableField(value = "icon") | |||
private String icon; | |||
/** | |||
* 布局类型 | |||
*/ | |||
@TableField(value = "layout") | |||
private String layout; | |||
@TableField(value = "cache") | |||
private Boolean cache; | |||
@TableField(value = "hidden") | |||
private Boolean hidden; | |||
/** | |||
* 上级菜单ID | |||
*/ | |||
@TableField(value = "pid") | |||
private Long pid; | |||
@TableField(value = "deleted",fill = FieldFill.INSERT) | |||
private Boolean deleted; | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
Menu menu = (Menu) o; | |||
return Objects.equals(id, menu.id); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(id); | |||
} | |||
public @interface Update { | |||
} | |||
} |
@@ -0,0 +1,87 @@ | |||
/** | |||
* Copyright 2019-2020 Zheng Jie | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package org.dubhe.domain.entity; | |||
import com.baomidou.mybatisplus.annotation.*; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import org.dubhe.base.BaseEntity; | |||
import org.hibernate.validator.constraints.Length; | |||
import javax.validation.constraints.NotBlank; | |||
import javax.validation.constraints.NotEmpty; | |||
import java.io.Serializable; | |||
import java.sql.Timestamp; | |||
import java.util.Objects; | |||
import java.util.Set; | |||
/** | |||
* @description 角色实体 | |||
* @date 2020-06-29 | |||
*/ | |||
@Data | |||
@Builder | |||
@AllArgsConstructor | |||
@NoArgsConstructor | |||
@TableName("role") | |||
public class Role extends BaseEntity implements Serializable { | |||
private static final long serialVersionUID = -812009584744832371L; | |||
@TableId(value = "id", type = IdType.AUTO) | |||
private Long id; | |||
@TableField(value = "name") | |||
private String name; | |||
/** | |||
* 权限 | |||
*/ | |||
@TableField(value = "permission") | |||
private String permission; | |||
@TableField(value = "remark") | |||
private String remark; | |||
@TableField(exist = false) | |||
private Set<Menu> menus; | |||
@TableField(value = "deleted",fill = FieldFill.INSERT) | |||
private Boolean deleted = false; | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
Role role = (Role) o; | |||
return Objects.equals(id, role.id); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(id); | |||
} | |||
public @interface Update { | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
/** | |||
* Copyright 2019-2020 Zheng Jie | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package org.dubhe.domain.entity; | |||
import com.baomidou.mybatisplus.annotation.TableField; | |||
import com.baomidou.mybatisplus.annotation.TableName; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
/** | |||
* @description 角色菜单关系实体 | |||
* @date 2020-06-29 | |||
*/ | |||
@Data | |||
@Builder | |||
@AllArgsConstructor | |||
@NoArgsConstructor | |||
@TableName("roles_menus") | |||
public class RoleMenu implements Serializable { | |||
private static final long serialVersionUID = -6296866205797727963L; | |||
@TableField(value = "menu_id") | |||
private Long menuId; | |||
@TableField(value = "role_id") | |||
private Long roleId; | |||
} |
@@ -0,0 +1,85 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.domain.entity; | |||
import com.baomidou.mybatisplus.annotation.IdType; | |||
import com.baomidou.mybatisplus.annotation.TableField; | |||
import com.baomidou.mybatisplus.annotation.TableId; | |||
import com.baomidou.mybatisplus.annotation.TableName; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import javax.validation.constraints.NotBlank; | |||
import javax.validation.constraints.NotNull; | |||
import java.sql.Timestamp; | |||
import java.util.List; | |||
import java.util.Objects; | |||
/** | |||
* @description 团队实体 | |||
* @date 2020-06-29 | |||
*/ | |||
@TableName("team") | |||
@Data | |||
@Builder | |||
@NoArgsConstructor | |||
@AllArgsConstructor | |||
public class Team { | |||
@TableId(value = "id", type = IdType.AUTO) | |||
@NotNull(groups = Update.class) | |||
private Long id; | |||
@TableField(value = "name") | |||
@NotBlank | |||
private String name; | |||
@TableField(value = "enabled") | |||
@NotNull | |||
private Boolean enabled; | |||
/** | |||
* 团队成员 | |||
*/ | |||
@TableField(exist = false) | |||
private List<User> teamUserList; | |||
@TableField(value = "create_time") | |||
private Timestamp createTime; | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
Team dept = (Team) o; | |||
return Objects.equals(id, dept.id) && | |||
Objects.equals(name, dept.name); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(id, name); | |||
} | |||
public @interface Update { | |||
} | |||
} |
@@ -0,0 +1,58 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.domain.entity; | |||
import com.baomidou.mybatisplus.annotation.IdType; | |||
import com.baomidou.mybatisplus.annotation.TableField; | |||
import com.baomidou.mybatisplus.annotation.TableId; | |||
import com.baomidou.mybatisplus.annotation.TableName; | |||
import lombok.Data; | |||
import javax.validation.constraints.NotNull; | |||
import java.io.Serializable; | |||
/** | |||
* @description 团队用户关系实体 | |||
* @date 2020-06-29 | |||
*/ | |||
@Data | |||
@TableName("teams_users_roles") | |||
public class TeamUserRole implements Serializable { | |||
@TableId(value = "id", type = IdType.AUTO) | |||
@NotNull() | |||
private Long id; | |||
/** | |||
* 团队 | |||
*/ | |||
@TableField(exist = false) | |||
private Team team; | |||
/** | |||
* 用户 | |||
*/ | |||
@TableField(exist = false) | |||
private User user; | |||
/** | |||
* 角色 | |||
*/ | |||
@TableField(exist = false) | |||
private Role role; | |||
} |
@@ -0,0 +1,126 @@ | |||
/** | |||
* Copyright 2019-2020 Zheng Jie | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package org.dubhe.domain.entity; | |||
import com.baomidou.mybatisplus.annotation.*; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import org.dubhe.base.BaseEntity; | |||
import javax.validation.constraints.NotBlank; | |||
import javax.validation.constraints.NotEmpty; | |||
import javax.validation.constraints.NotNull; | |||
import java.io.Serializable; | |||
import java.util.Date; | |||
import java.util.List; | |||
import java.util.Objects; | |||
/** | |||
* @description 用户实体 | |||
* @date 2020-06-29 | |||
*/ | |||
@Data | |||
@TableName("user") | |||
@Builder | |||
@NoArgsConstructor | |||
@AllArgsConstructor | |||
public class User extends BaseEntity implements Serializable { | |||
private static final long serialVersionUID = -3836401769559845765L; | |||
@TableId(value = "id", type = IdType.AUTO) | |||
@NotNull(groups = Update.class) | |||
private Long id; | |||
@NotBlank | |||
@TableField(value = "username") | |||
private String username; | |||
/** | |||
* 用户昵称 | |||
*/ | |||
@TableField(value = "nick_name") | |||
@NotBlank | |||
private String nickName; | |||
/** | |||
* 性别 | |||
*/ | |||
@TableField(value = "sex") | |||
private String sex; | |||
@NotBlank | |||
@TableField(value = "email") | |||
private String email; | |||
@NotBlank | |||
@TableField(value = "phone") | |||
private String phone; | |||
@NotNull | |||
@TableField(value = "enabled") | |||
private Boolean enabled; | |||
@TableField(value = "password") | |||
private String password; | |||
@TableField(value = "last_password_reset_time") | |||
private Date lastPasswordResetTime; | |||
@TableField(value = "remark") | |||
private String remark; | |||
@TableField(value = "avatar_id") | |||
private Long avatarId; | |||
@TableField(exist = false) | |||
private UserAvatar userAvatar; | |||
@NotEmpty | |||
@TableField(exist = false) | |||
private List<Role> roles; | |||
@TableField(value = "deleted",fill = FieldFill.INSERT) | |||
private Boolean deleted = false; | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
User user = (User) o; | |||
return Objects.equals(id, user.id) && | |||
Objects.equals(username, user.username); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(id, username); | |||
} | |||
public @interface Update { | |||
} | |||
} |
@@ -0,0 +1,58 @@ | |||
/** | |||
* Copyright 2019-2020 Zheng Jie | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package org.dubhe.domain.entity; | |||
import cn.hutool.core.util.ObjectUtil; | |||
import com.baomidou.mybatisplus.annotation.IdType; | |||
import com.baomidou.mybatisplus.annotation.TableField; | |||
import com.baomidou.mybatisplus.annotation.TableId; | |||
import com.baomidou.mybatisplus.annotation.TableName; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import org.dubhe.base.BaseEntity; | |||
import java.io.Serializable; | |||
/** | |||
* @description 用户头像实体 | |||
* @date 2020-06-29 | |||
*/ | |||
@Data | |||
@NoArgsConstructor | |||
@TableName("user_avatar") | |||
public class UserAvatar extends BaseEntity implements Serializable { | |||
@TableId(value = "id", type = IdType.AUTO) | |||
private Long id; | |||
@TableField(value = "real_name") | |||
private String realName; | |||
@TableField(value = "path") | |||
private String path; | |||
@TableField(value = "size") | |||
private String size; | |||
public UserAvatar(UserAvatar userAvatar, String realName, String path, String size) { | |||
this.id = ObjectUtil.isNotEmpty(userAvatar) ? userAvatar.getId() : null; | |||
this.realName = realName; | |||
this.path = path; | |||
this.size = size; | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
/** | |||
* Copyright 2019-2020 Zheng Jie | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package org.dubhe.domain.entity; | |||
import com.baomidou.mybatisplus.annotation.TableField; | |||
import com.baomidou.mybatisplus.annotation.TableName; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
/** | |||
* @description 用户角色关系实体 | |||
* @date 2020-06-29 | |||
*/ | |||
@Data | |||
@Builder | |||
@AllArgsConstructor | |||
@NoArgsConstructor | |||
@TableName("users_roles") | |||
public class UserRole implements Serializable { | |||
private static final long serialVersionUID = -6296866205797727963L; | |||
@TableField(value = "user_id") | |||
private Long userId; | |||
@TableField(value = "role_id") | |||
private Long roleId; | |||
} |
@@ -0,0 +1,35 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.dto.callback; | |||
import io.swagger.annotations.ApiModel; | |||
import lombok.Data; | |||
/** | |||
* @descripton 个性化参数实现 与 个性化参数个性化校验 | |||
* | |||
* @date 2020-05-28 | |||
*/ | |||
@ApiModel(description = "k8s pod异步回调Algorithm") | |||
@Data | |||
public class AlgorithmK8sPodCallbackCreateDTO extends BaseK8sPodCallbackCreateDTO { | |||
@Override | |||
public String toString() { | |||
return super.toString(); | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.dto.callback; | |||
import io.swagger.annotations.ApiModel; | |||
import lombok.Data; | |||
/** | |||
* @descripton k8s方异步回调统一汇总类,即不管什么业务所有请求参数都放在这个类中 | |||
* | |||
* @date 2020-05-28 | |||
*/ | |||
@ApiModel(description = "k8s方 pod异步回调汇总类") | |||
@Data | |||
public class AllK8sPodCallbackCreateDTO extends BaseK8sPodCallbackCreateDTO{ | |||
} |
@@ -0,0 +1,76 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.dto.callback; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import javax.validation.constraints.NotEmpty; | |||
/** | |||
* @descripton 统一通用参数实现与校验 | |||
* | |||
* @date 2020-05-28 | |||
*/ | |||
@ApiModel(description = "k8s pod异步回调基类") | |||
@Data | |||
public class BaseK8sPodCallbackCreateDTO { | |||
@ApiModelProperty(required = true,value = "k8s namespace") | |||
@NotEmpty(message = "namespace 不能为空!") | |||
private String namespace; | |||
@ApiModelProperty(required = true,value = "k8s resource name") | |||
@NotEmpty(message = "resourceName 不能为空!") | |||
private String resourceName; | |||
@ApiModelProperty(required = true,value = "k8s pod name") | |||
@NotEmpty(message = "podName 不能为空!") | |||
private String podName; | |||
@ApiModelProperty(value = "k8s pod phase",notes = "对应PodPhaseEnum") | |||
@NotEmpty(message = "phase 不能为空!") | |||
private String phase; | |||
@ApiModelProperty(value = "k8s pod containerStatuses state") | |||
private String messages; | |||
public BaseK8sPodCallbackCreateDTO(){ | |||
} | |||
public BaseK8sPodCallbackCreateDTO(String namespace,String resourceName,String podName,String phase,String messages){ | |||
this.namespace = namespace; | |||
this.resourceName = resourceName; | |||
this.podName = podName; | |||
this.phase = phase; | |||
this.messages = messages; | |||
} | |||
@Override | |||
public String toString() { | |||
return "BaseK8sPodCallbackReq{" + | |||
"namespace='" + namespace + '\'' + | |||
", resourceName='" + resourceName + '\'' + | |||
", podName='" + podName + '\'' + | |||
", phase='" + phase + '\'' + | |||
", messages=" + messages + | |||
'}'; | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.dto.callback; | |||
import io.swagger.annotations.ApiModel; | |||
import lombok.Data; | |||
/** | |||
* @descripton k8s pod异步回调Notebook | |||
* | |||
* @date 2020-05-28 | |||
*/ | |||
@ApiModel(description = "k8s pod异步回调Notebook") | |||
@Data | |||
public class NotebookK8sPodCallbackCreateDTO extends BaseK8sPodCallbackCreateDTO { | |||
@Override | |||
public String toString() { | |||
return super.toString(); | |||
} | |||
} |
@@ -0,0 +1,80 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.enums; | |||
import lombok.Getter; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
/** | |||
* @desc: 业务模块 | |||
* | |||
* @date 2020.05.25 | |||
*/ | |||
@Getter | |||
public enum BizEnum { | |||
/** | |||
* 模型开发 | |||
*/ | |||
NOTEBOOK("模型开发","notebook",0), | |||
/** | |||
* 算法管理 | |||
*/ | |||
ALGORITHM("算法管理","algorithm",1), | |||
; | |||
/** | |||
* 业务模块名称 | |||
*/ | |||
private String bizName; | |||
/** | |||
* 业务模块名称 | |||
*/ | |||
private String bizCode; | |||
/** | |||
* 业务源代号 | |||
*/ | |||
private Integer createResource; | |||
BizEnum(String bizName,String bizCode, Integer createResource) { | |||
this.createResource = createResource; | |||
this.bizName = bizName; | |||
this.bizCode = bizCode; | |||
} | |||
private static final Map<Integer,BizEnum> RESOURCE_ENUM_MAP = new HashMap<Integer,BizEnum>(){ | |||
{ | |||
for (BizEnum enums:BizEnum.values()){ | |||
put(enums.getCreateResource(),enums); | |||
} | |||
} | |||
}; | |||
/** | |||
* 根据createResource获取BizEnum | |||
* @param createResource | |||
* @return | |||
*/ | |||
public static BizEnum getByCreateResource(int createResource){ | |||
return RESOURCE_ENUM_MAP.get(createResource); | |||
} | |||
} |
@@ -0,0 +1,91 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.enums; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
/** | |||
* @desc: 业务NFS路径枚举 | |||
* @date 2020.05.13 | |||
*/ | |||
public enum BizNfsEnum { | |||
/** | |||
* 模型开发 NFS 路径命名 | |||
*/ | |||
NOTEBOOK(BizEnum.NOTEBOOK, "notebook"), | |||
/** | |||
* 算法管理 NFS 路径命名 | |||
*/ | |||
ALGORITHM(BizEnum.ALGORITHM, "algorithm-manage"), | |||
; | |||
BizNfsEnum(BizEnum bizEnum, String bizNfsPath) { | |||
this.bizEnum = bizEnum; | |||
this.bizNfsPath = bizNfsPath; | |||
} | |||
/** | |||
* 业务模块 | |||
*/ | |||
private BizEnum bizEnum; | |||
/** | |||
* 业务模块nfs路径 | |||
*/ | |||
private String bizNfsPath; | |||
private static final Map<Integer, BizNfsEnum> RESOURCE_ENUM_MAP = new HashMap<Integer, BizNfsEnum>() { | |||
{ | |||
for (BizNfsEnum enums : BizNfsEnum.values()) { | |||
put(enums.getCreateResource(), enums); | |||
} | |||
} | |||
}; | |||
/** | |||
* 根据createResource获取BizNfsEnum | |||
* | |||
* @param createResource | |||
* @return | |||
*/ | |||
public static BizNfsEnum getByCreateResource(int createResource) { | |||
return RESOURCE_ENUM_MAP.get(createResource); | |||
} | |||
public String getBizName() { | |||
return bizEnum == null ? null : bizEnum.getBizName(); | |||
} | |||
public Integer getCreateResource() { | |||
return bizEnum == null ? null : bizEnum.getCreateResource(); | |||
} | |||
public String getBizNfsPath() { | |||
return bizNfsPath; | |||
} | |||
public BizEnum getBizEnum(){ | |||
return bizEnum; | |||
} | |||
public String getBizCode() { | |||
return bizEnum == null ? null :bizEnum.getBizCode(); | |||
} | |||
} |
@@ -0,0 +1,61 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.enums; | |||
import lombok.Getter; | |||
/** | |||
* @description 日志类型枚举类 | |||
* @date 2020-06-23 | |||
*/ | |||
@Getter | |||
public enum LogEnum { | |||
// 系统报错日志 | |||
SYS_ERR, | |||
// 用户请求日志 | |||
REST_REQ, | |||
// 训练模块 | |||
BIZ_TRAIN, | |||
// 系统模块 | |||
BIZ_SYS, | |||
// 模型模块 | |||
BIZ_MODEL, | |||
// 数据集模块 | |||
BIZ_DATASET, | |||
// k8s模块 | |||
BIZ_K8S, | |||
//note book | |||
NOTE_BOOK, | |||
//NFS UTILS | |||
NFS_UTIL; | |||
/** | |||
* 判断日志类型不能为空 | |||
* | |||
* @param logType 日志类型 | |||
* @return boolean 返回类型 | |||
*/ | |||
public static boolean isLogType(LogEnum logType) { | |||
if (logType != null) { | |||
return true; | |||
} | |||
return false; | |||
} | |||
} |
@@ -0,0 +1,95 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.enums; | |||
/** | |||
* @Description 是否开关枚举 | |||
* @Date 2020-06-01 | |||
*/ | |||
public enum SwitchEnum { | |||
/** | |||
* OFF 否 | |||
*/ | |||
OFF(0, "否"), | |||
/** | |||
* ON 否 | |||
*/ | |||
ON(1, "是"), | |||
; | |||
private Integer value; | |||
private String desc; | |||
SwitchEnum(Integer value, String desc) { | |||
this.value = value; | |||
this.desc = desc; | |||
} | |||
public Integer getValue() { | |||
return this.value; | |||
} | |||
public String getDesc() { | |||
return desc; | |||
} | |||
public void setDesc(String desc) { | |||
this.desc = desc; | |||
} | |||
public static SwitchEnum getEnumValue(Integer value) { | |||
switch (value) { | |||
case 0: | |||
return OFF; | |||
case 1: | |||
return ON; | |||
default: | |||
return OFF; | |||
} | |||
} | |||
public static Boolean getBooleanValue(Integer value) { | |||
switch (value) { | |||
case 1: | |||
return true; | |||
case 0: | |||
return false; | |||
default: | |||
return false; | |||
} | |||
} | |||
public static boolean isExist(Integer value) { | |||
for (SwitchEnum itm : SwitchEnum.values()) { | |||
if (value.compareTo(itm.getValue()) == 0) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
@Override | |||
public String toString() { | |||
return "[" + this.value + "]" + this.desc; | |||
} | |||
} |
@@ -0,0 +1,101 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.enums; | |||
import lombok.Getter; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
/** | |||
* @description 训练任务枚举类 | |||
* @date 2020-04-27 | |||
*/ | |||
@Getter | |||
public enum TrainJobStatusEnum { | |||
/** | |||
* PENDING | |||
*/ | |||
PENDING(0, "PENDING"), | |||
/** | |||
* RUNNING | |||
*/ | |||
RUNNING(1, "RUNNING"), | |||
/** | |||
* SUCCEEDED | |||
*/ | |||
SUCCEEDED(2, "SUCCEEDED"), | |||
/** | |||
* FAILED | |||
*/ | |||
FAILED(3, "FAILED"), | |||
/** | |||
* STOP | |||
*/ | |||
STOP(4, "STOP"), | |||
/** | |||
* UNKNOWN | |||
*/ | |||
UNKNOWN(5, "UNKNOWN"), | |||
/** | |||
* DELETED | |||
*/ | |||
DELETED(6, "DELETED"), | |||
/** | |||
* CREATE_FAILED | |||
*/ | |||
CREATE_FAILED(7, "CREATE_FAILED"); | |||
private Integer status; | |||
private String message; | |||
TrainJobStatusEnum(Integer status, String message) { | |||
this.status = status; | |||
this.message = message; | |||
} | |||
public static TrainJobStatusEnum get(String msg) { | |||
for (TrainJobStatusEnum statusEnum : values()) { | |||
if (statusEnum.message.equalsIgnoreCase(msg)) { | |||
return statusEnum; | |||
} | |||
} | |||
return UNKNOWN; | |||
} | |||
public static boolean isEnd(String msg) { | |||
List<String> endList = Arrays.asList("SUCCEEDED", "FAILED", "STOP", "CREATE_FAILED"); | |||
return endList.stream().anyMatch(s -> s.equalsIgnoreCase(msg)); | |||
} | |||
public static boolean isEnd(Integer num) { | |||
List<Integer> endList = Arrays.asList(2, 3, 4, 7); | |||
return endList.stream().anyMatch(s -> s.equals(num)); | |||
} | |||
public static boolean checkStopStatus(Integer num) { | |||
return SUCCEEDED.getStatus().equals(num) || | |||
FAILED.getStatus().equals(num) || | |||
STOP.getStatus().equals(num) || | |||
CREATE_FAILED.getStatus().equals(num) || | |||
DELETED.getStatus().equals(num); | |||
} | |||
} |
@@ -0,0 +1,69 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.exception; | |||
import lombok.Getter; | |||
/** | |||
* @description 通用异常code | |||
* @date 2020-03-26 | |||
*/ | |||
@Getter | |||
public enum BaseErrorCode implements ErrorCode { | |||
/** | |||
* undefined error | |||
*/ | |||
UNDEFINED(10000, "操作成功!"), | |||
ERROR(10001, "操作失败!"), | |||
ERROR_SYSTEM(10002, "系统繁忙!"), | |||
UNAUTHORIZED(401, "无权访问!"), | |||
/** | |||
* system 模块异常码 | |||
*/ | |||
SYSTEM_USERNAME_ALREADY_EXISTS(20000, "账号已存在!"), | |||
SYSTEM_CODE_ALREADY_EXISTS(20001, "Code already exists!"), | |||
SYSTEM_USER_IS_NOT_EXISTS(20002, "用户不存在!"), | |||
SYSTEM_USER_ALREADY_REGISTER(20003, "账号已注册!"), | |||
SYSTEM_USER_REGISTER_EMAIL_INFO_EXPIRED(20004, "邮箱验证码已过期!"), | |||
SYSTEM_USER_EMAIL_ALREADY_EXISTS(20004, "该邮箱已被注册!"), | |||
SYSTEM_USER_EMAIL_PASSWORD_ERROR(20005, "邮件密码错误!"), | |||
SYSTEM_USER_EMAIL_CODE_CANNOT_EXCEED_TIMES(20006, "邮件发送不能超过三次!"), | |||
SYSTEM_USER_EMAIL_OR_CODE_ERROR(20007, "邮箱地址或验证码错误、请重新输入!"), | |||
SYSTEM_USER_IS_LOCKED(20008, "用户已锁定!"), | |||
SYSTEM_USER_USERNAME_OR_PASSWORD_ERROR(20009, "账号或密码不正确!"), | |||
SYSTEM_USER_USERNAME_IS_LOCKED(20010, "账号已锁定,6小时后解锁!"), | |||
SYSTEM_USER_CANNOT_UPDATE_ADMIN(20011, "仅超级管理员可操作!"), | |||
SYSTEM_USER_TOKEN_INFO_IS_NULL(20012, "登录信息不存在!"), | |||
SYSTEM_USER_EMAIL_NOT_EXISTS(20013, "该邮箱未注册!"), | |||
SYSTEM_USER_CANNOT_DELETE(20014, "系统默认用户不可删除!"), | |||
SYSTEM_ROLE_CANNOT_DELETE(20015, "系统默认角色不可删除!"), | |||
; | |||
Integer code; | |||
String msg; | |||
BaseErrorCode(Integer code, String msg) { | |||
this.code = code; | |||
this.msg = msg; | |||
} | |||
} |
@@ -0,0 +1,72 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.exception; | |||
import lombok.Getter; | |||
import org.dubhe.base.DataResponseBody; | |||
import org.dubhe.base.ResponseCode; | |||
/** | |||
* @description 业务异常 | |||
* @date 2020-03-13 | |||
*/ | |||
@Getter | |||
public class BusinessException extends RuntimeException { | |||
private DataResponseBody responseBody; | |||
public BusinessException(String msg) { | |||
super(msg); | |||
this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST, msg); | |||
} | |||
public BusinessException(String msg, Throwable cause) { | |||
super(msg,cause); | |||
this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST, msg); | |||
} | |||
public BusinessException(Throwable cause) { | |||
super(cause); | |||
this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST); | |||
} | |||
public BusinessException(Integer code, String msg, String info, Throwable cause) { | |||
super(msg,cause); | |||
if (info == null) { | |||
this.responseBody = new DataResponseBody(code, msg); | |||
} else { | |||
this.responseBody = new DataResponseBody(code, msg + ":" + info); | |||
} | |||
} | |||
public BusinessException(ErrorCode errorCode, Throwable cause) { | |||
this(errorCode.getCode(), errorCode.getMsg(), null, cause); | |||
} | |||
public BusinessException(ErrorCode errorCode, String info, Throwable cause) { | |||
this(errorCode.getCode(), errorCode.getMsg(), info, cause); | |||
} | |||
public BusinessException(ErrorCode errorCode) { | |||
this(errorCode, null); | |||
} | |||
public BusinessException(Integer code,String msg) { | |||
this.responseBody = new DataResponseBody(code, msg); | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.exception; | |||
import lombok.Getter; | |||
import org.dubhe.base.DataResponseBody; | |||
import org.dubhe.base.ResponseCode; | |||
/** | |||
* @description 验证码异常 | |||
* @date 2020-02-23 | |||
*/ | |||
@Getter | |||
public class CaptchaException extends RuntimeException { | |||
private static final long serialVersionUID = 1L; | |||
private DataResponseBody responseBody; | |||
private Throwable cause; | |||
public CaptchaException(String msg) { | |||
this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST, msg); | |||
} | |||
public CaptchaException(String msg, Throwable cause) { | |||
this.cause = cause; | |||
this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST, msg); | |||
} | |||
public CaptchaException(Throwable cause) { | |||
this.cause = cause; | |||
this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST); | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.exception; | |||
import lombok.Getter; | |||
import org.dubhe.base.DataResponseBody; | |||
import org.dubhe.base.ResponseCode; | |||
/** | |||
* @Description docker 异常 | |||
* @Date 2020-6-6 | |||
**/ | |||
@Getter | |||
public class DockerBizException extends RuntimeException { | |||
private static final long serialVersionUID = 1L; | |||
private DataResponseBody responseBody; | |||
private Throwable cause; | |||
public DockerBizException(String msg) { | |||
this.responseBody = new DataResponseBody(ResponseCode.DOCKER_ERROR, msg); | |||
} | |||
public DockerBizException(String msg, Throwable cause) { | |||
this.cause = cause; | |||
this.responseBody = new DataResponseBody(ResponseCode.DOCKER_ERROR, msg); | |||
} | |||
public DockerBizException(Throwable cause) { | |||
this.cause = cause; | |||
this.responseBody = new DataResponseBody(ResponseCode.DOCKER_ERROR); | |||
} | |||
} |
@@ -0,0 +1,39 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.exception; | |||
/** | |||
* @description 异常code | |||
* @date 2020-03-26 | |||
*/ | |||
public interface ErrorCode { | |||
/** | |||
* 错误码 | |||
* @return code | |||
*/ | |||
Integer getCode(); | |||
/** | |||
* error info | |||
* @return | |||
*/ | |||
String getMsg(); | |||
} |
@@ -0,0 +1,44 @@ | |||
/** | |||
* Copyright 2019-2020 Zheng Jie | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package org.dubhe.exception; | |||
import lombok.Getter; | |||
import org.dubhe.base.DataResponseBody; | |||
import org.dubhe.base.ResponseCode; | |||
/** | |||
* @description 登录异常 | |||
* @date 2020-02-23 | |||
*/ | |||
@Getter | |||
public class LoginException extends RuntimeException { | |||
private DataResponseBody responseBody; | |||
private Throwable cause; | |||
public LoginException(String msg) { | |||
this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST, msg); | |||
} | |||
public LoginException(String msg, Throwable cause) { | |||
this.cause = cause; | |||
this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST, msg); | |||
} | |||
public LoginException(Throwable cause) { | |||
this.cause = cause; | |||
this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST); | |||
} | |||
} |
@@ -0,0 +1,42 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.exception; | |||
import lombok.Getter; | |||
/** | |||
* Description : NFS utils 工具异常 | |||
* | |||
* @date 15.06.2020 | |||
*/ | |||
@Getter | |||
public class NfsBizException extends BusinessException { | |||
private static final long serialVersionUID = 1L; | |||
public NfsBizException(Throwable cause){ | |||
super(cause); | |||
} | |||
public NfsBizException(String msg){ | |||
super(msg); | |||
} | |||
} |
@@ -0,0 +1,45 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.exception; | |||
import lombok.Getter; | |||
/** | |||
* @description: Notebook 业务处理异常 | |||
* | |||
* @date 2020.04.27 | |||
*/ | |||
@Getter | |||
public class NotebookBizException extends BusinessException{ | |||
private static final long serialVersionUID = 1L; | |||
public NotebookBizException(String msg) { | |||
super(msg); | |||
} | |||
public NotebookBizException(String msg, Throwable cause) { | |||
super(msg,cause); | |||
} | |||
public NotebookBizException(Throwable cause) { | |||
super(cause); | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.exception; | |||
import lombok.Getter; | |||
import org.dubhe.base.DataResponseBody; | |||
import org.dubhe.base.ResponseCode; | |||
/** | |||
* @description 权限异常 | |||
* @date 2020-02-23 | |||
*/ | |||
@Getter | |||
public class UnauthorizedException extends RuntimeException { | |||
private DataResponseBody responseBody; | |||
private Throwable cause; | |||
public UnauthorizedException(String msg) { | |||
this.responseBody = new DataResponseBody(ResponseCode.UNAUTHORIZED, msg); | |||
} | |||
public UnauthorizedException(String msg, Throwable cause) { | |||
this.cause = cause; | |||
this.responseBody = new DataResponseBody(ResponseCode.UNAUTHORIZED, msg); | |||
} | |||
public UnauthorizedException(Throwable cause) { | |||
this.cause = cause; | |||
this.responseBody = new DataResponseBody(ResponseCode.UNAUTHORIZED); | |||
} | |||
} |
@@ -0,0 +1,190 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.exception.handler; | |||
import java.util.Objects; | |||
import org.apache.shiro.ShiroException; | |||
import org.apache.shiro.authc.AuthenticationException; | |||
import org.apache.shiro.authc.IncorrectCredentialsException; | |||
import org.apache.shiro.authc.LockedAccountException; | |||
import org.apache.shiro.authc.UnknownAccountException; | |||
import org.dubhe.base.DataResponseBody; | |||
import org.dubhe.base.ResponseCode; | |||
import org.dubhe.enums.LogEnum; | |||
import org.dubhe.exception.BusinessException; | |||
import org.dubhe.exception.CaptchaException; | |||
import org.dubhe.exception.LoginException; | |||
import org.dubhe.exception.NotebookBizException; | |||
import org.dubhe.exception.UnauthorizedException; | |||
import org.dubhe.utils.LogUtil; | |||
import org.springframework.http.HttpStatus; | |||
import org.springframework.http.ResponseEntity; | |||
import org.springframework.validation.BindException; | |||
import org.springframework.validation.ObjectError; | |||
import org.springframework.web.bind.MethodArgumentNotValidException; | |||
import org.springframework.web.bind.annotation.ExceptionHandler; | |||
import org.springframework.web.bind.annotation.RestControllerAdvice; | |||
import lombok.extern.slf4j.Slf4j; | |||
/** | |||
* @description 处理异常 | |||
* @date 2020-02-23 | |||
*/ | |||
@Slf4j | |||
@RestControllerAdvice | |||
public class GlobalExceptionHandler { | |||
/** | |||
* 处理所有不可知的异常 | |||
*/ | |||
@ExceptionHandler(Throwable.class) | |||
public ResponseEntity<DataResponseBody> handleException(Throwable e) { | |||
// 打印堆栈信息 | |||
LogUtil.error(LogEnum.SYS_ERR, e); | |||
return buildResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR, | |||
new DataResponseBody(ResponseCode.ERROR, e.getMessage())); | |||
} | |||
/** | |||
* UnauthorizedException | |||
*/ | |||
@ExceptionHandler(UnauthorizedException.class) | |||
public ResponseEntity<DataResponseBody> badCredentialsException(UnauthorizedException e) { | |||
// 打印堆栈信息 | |||
LogUtil.error(LogEnum.SYS_ERR, e); | |||
String message = "坏的凭证".equals(e.getMessage()) ? "用户名或密码不正确" : e.getMessage(); | |||
return buildResponseEntity(HttpStatus.UNAUTHORIZED, new DataResponseBody(ResponseCode.ERROR, message)); | |||
} | |||
/** | |||
* 处理自定义异常 | |||
*/ | |||
@ExceptionHandler(value = BusinessException.class) | |||
public ResponseEntity<DataResponseBody> badRequestException(BusinessException e) { | |||
// 打印堆栈信息 | |||
LogUtil.error(LogEnum.SYS_ERR, e); | |||
return buildResponseEntity(HttpStatus.OK, e.getResponseBody()); | |||
} | |||
/** | |||
* 处理自定义异常 | |||
*/ | |||
@ExceptionHandler(value = AuthenticationException.class) | |||
public ResponseEntity<DataResponseBody> badRequestException(AuthenticationException e) { | |||
// 打印堆栈信息 | |||
LogUtil.error(LogEnum.SYS_ERR, e); | |||
return buildResponseEntity(HttpStatus.OK, new DataResponseBody(ResponseCode.UNAUTHORIZED, "无权访问")); | |||
} | |||
/** | |||
* shiro 异常捕捉 | |||
*/ | |||
@ExceptionHandler(value = ShiroException.class) | |||
public ResponseEntity<DataResponseBody> accountException(ShiroException e) { | |||
// 打印堆栈信息 | |||
LogUtil.error(LogEnum.SYS_ERR, e); | |||
ResponseEntity<DataResponseBody> responseEntity; | |||
if (e instanceof IncorrectCredentialsException) { | |||
responseEntity = buildResponseEntity(HttpStatus.OK, new DataResponseBody(ResponseCode.ERROR, "密码不正确")); | |||
} else if (e instanceof UnknownAccountException) { | |||
responseEntity = buildResponseEntity(HttpStatus.OK, new DataResponseBody(ResponseCode.ERROR, "此账户不存在")); | |||
} | |||
else if (e instanceof LockedAccountException) { | |||
responseEntity = buildResponseEntity(HttpStatus.OK, new DataResponseBody(ResponseCode.ERROR, "未知的账号")); | |||
} | |||
else if (e instanceof UnknownAccountException) { | |||
responseEntity = buildResponseEntity(HttpStatus.OK, new DataResponseBody(ResponseCode.ERROR, "账户已被禁用")); | |||
} | |||
else { | |||
responseEntity = buildResponseEntity(HttpStatus.OK, | |||
new DataResponseBody(ResponseCode.UNAUTHORIZED, "无权访问")); | |||
} | |||
return responseEntity; | |||
} | |||
/** | |||
* 处理自定义异常 | |||
*/ | |||
@ExceptionHandler(value = LoginException.class) | |||
public ResponseEntity<DataResponseBody> loginException(LoginException e) { | |||
// 打印堆栈信息 | |||
LogUtil.error(LogEnum.SYS_ERR, e); | |||
return buildResponseEntity(HttpStatus.UNAUTHORIZED, e.getResponseBody()); | |||
} | |||
/** | |||
* 处理自定义异常 | |||
*/ | |||
@ExceptionHandler(value = CaptchaException.class) | |||
public ResponseEntity<DataResponseBody> captchaException(CaptchaException e) { | |||
// 打印堆栈信息 | |||
LogUtil.error(LogEnum.SYS_ERR, e); | |||
return buildResponseEntity(HttpStatus.OK, e.getResponseBody()); | |||
} | |||
/** | |||
* 处理自定义异常 | |||
*/ | |||
@ExceptionHandler(value = NotebookBizException.class) | |||
public ResponseEntity<DataResponseBody> captchaException(NotebookBizException e) { | |||
// 打印堆栈信息 | |||
LogUtil.error(LogEnum.SYS_ERR, e); | |||
return buildResponseEntity(HttpStatus.OK, e.getResponseBody()); | |||
} | |||
/** | |||
* 处理所有接口数据验证异常 | |||
*/ | |||
@ExceptionHandler(MethodArgumentNotValidException.class) | |||
public ResponseEntity<DataResponseBody> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { | |||
// 打印堆栈信息 | |||
LogUtil.error(LogEnum.SYS_ERR, e); | |||
String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\."); | |||
String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage(); | |||
String msg = "不能为空"; | |||
if (msg.equals(message)) { | |||
message = str[1] + ":" + message; | |||
} | |||
return buildResponseEntity(HttpStatus.BAD_REQUEST, new DataResponseBody(ResponseCode.ERROR, message)); | |||
} | |||
@ExceptionHandler(BindException.class) | |||
public ResponseEntity<DataResponseBody> bindException(BindException e) { | |||
// 打印堆栈信息 | |||
LogUtil.error(LogEnum.SYS_ERR, e); | |||
ObjectError error = e.getAllErrors().get(0); | |||
return buildResponseEntity(HttpStatus.BAD_REQUEST, | |||
new DataResponseBody(ResponseCode.ERROR, error.getDefaultMessage())); | |||
} | |||
/** | |||
* 统一返回 | |||
* | |||
* @param httpStatus | |||
* @param responseBody | |||
* @return | |||
*/ | |||
private ResponseEntity<DataResponseBody> buildResponseEntity(HttpStatus httpStatus, DataResponseBody responseBody) { | |||
return new ResponseEntity<>(responseBody, httpStatus); | |||
} | |||
} |
@@ -0,0 +1,121 @@ | |||
/** | |||
* Copyright 2019-2020 Zheng Jie | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package org.dubhe.factory; | |||
import org.dubhe.base.DataResponseBody; | |||
import org.dubhe.base.ResponseCode; | |||
/** | |||
* @desc DataResponseBody 工厂类 | |||
* | |||
* @date 2020.05.28 | |||
*/ | |||
public class DataResponseFactory { | |||
private DataResponseFactory(){ | |||
} | |||
/** | |||
* 成功响应 | |||
* | |||
* @param <T> | |||
* @return | |||
*/ | |||
public static <T> DataResponseBody success(){ | |||
return success(null,null); | |||
} | |||
/** | |||
* 成功响应 | |||
* | |||
* @param data | |||
* @param <T> | |||
* @return | |||
*/ | |||
public static <T> DataResponseBody success(T data){ | |||
return success(null,data); | |||
} | |||
/** | |||
* 成功响应 | |||
* | |||
* @param msg | |||
* @return | |||
*/ | |||
public static DataResponseBody successWithMsg(String msg){ | |||
return success(msg,null); | |||
} | |||
/** | |||
* 成功响应 | |||
* | |||
* @param msg | |||
* @param data | |||
* @param <T> | |||
* @return | |||
*/ | |||
public static <T> DataResponseBody success(String msg, T data){ | |||
return new DataResponseBody(ResponseCode.SUCCESS,msg,data); | |||
} | |||
/** | |||
* 失败响应 msg | |||
* | |||
* @param msg | |||
* @return | |||
*/ | |||
public static DataResponseBody failed(String msg){ | |||
return failed(ResponseCode.ERROR,msg,null); | |||
} | |||
/** | |||
* 失败响应 | |||
* | |||
* @param failedCode | |||
* @param msg | |||
* @return | |||
*/ | |||
public static DataResponseBody failed(Integer failedCode,String msg){ | |||
return failed(failedCode,msg,null); | |||
} | |||
/** | |||
* 失败响应 | |||
* | |||
* @param failedCode | |||
* @return | |||
*/ | |||
public static DataResponseBody failed(Integer failedCode){ | |||
return failed(failedCode,null,null); | |||
} | |||
/** | |||
* 失败响应 | |||
* | |||
* @param failedCode | |||
* @param msg | |||
* @param data | |||
* @param <T> | |||
* @return | |||
*/ | |||
public static <T> DataResponseBody failed(Integer failedCode, String msg, T data){ | |||
return new DataResponseBody(failedCode,msg,data); | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
/** | |||
* Copyright 2019-2020 Zheng Jie | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package org.dubhe.filter; | |||
import ch.qos.logback.classic.Level; | |||
import ch.qos.logback.classic.spi.ILoggingEvent; | |||
import ch.qos.logback.core.filter.AbstractMatcherFilter; | |||
import ch.qos.logback.core.spi.FilterReply; | |||
/** | |||
* @description 自定义日志过滤器 | |||
* @date 2020-07-21 | |||
*/ | |||
public class FileLogFilter extends AbstractMatcherFilter<ILoggingEvent> { | |||
Level level; | |||
/** | |||
* 重写decide方法 | |||
* | |||
* @param iLoggingEvent event to decide upon. | |||
* @return FilterReply | |||
*/ | |||
@Override | |||
public FilterReply decide(ILoggingEvent iLoggingEvent) { | |||
if (!isStarted()) { | |||
return FilterReply.NEUTRAL; | |||
} | |||
if (iLoggingEvent.getLevel().equals(level) && iLoggingEvent.getMessage() != null | |||
&& iLoggingEvent.getMessage().startsWith("{") && iLoggingEvent.getMessage().endsWith("}")) { | |||
return onMatch; | |||
} | |||
return onMismatch; | |||
} | |||
public void setLevel(Level level) { | |||
this.level = level; | |||
} | |||
@Override | |||
public void start() { | |||
if (this.level != null) { | |||
super.start(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,68 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.handle; | |||
import org.springframework.web.servlet.mvc.condition.RequestCondition; | |||
import javax.servlet.http.HttpServletRequest; | |||
import java.util.regex.Matcher; | |||
import java.util.regex.Pattern; | |||
/** | |||
* @description API版本控制 | |||
* @date 2020-04-06 | |||
*/ | |||
public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> { | |||
/** | |||
* 路径中版本的前缀, 这里用 /v[1-9]/的形式 | |||
*/ | |||
private final static Pattern VERSION_PREFIX_PATTERN = Pattern.compile("v(\\d+)/"); | |||
private int apiVersion; | |||
public ApiVersionCondition(int apiVersion) { | |||
this.apiVersion = apiVersion; | |||
} | |||
@Override | |||
public ApiVersionCondition combine(ApiVersionCondition other) { | |||
// 采用最后定义优先原则,则方法上的定义覆盖类上面的定义 | |||
return new ApiVersionCondition(other.getApiVersion()); | |||
} | |||
@Override | |||
public ApiVersionCondition getMatchingCondition(HttpServletRequest request) { | |||
Matcher m = VERSION_PREFIX_PATTERN.matcher(request.getRequestURI()); | |||
if (m.find()) { | |||
Integer version = Integer.valueOf(m.group(1)); | |||
if (version >= this.apiVersion) { | |||
return this; | |||
} | |||
} | |||
return null; | |||
} | |||
@Override | |||
public int compareTo(ApiVersionCondition other, HttpServletRequest request) { | |||
// 优先匹配最新的版本号 | |||
return other.getApiVersion() - this.apiVersion; | |||
} | |||
public int getApiVersion() { | |||
return apiVersion; | |||
} | |||
} |
@@ -0,0 +1,64 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.handle; | |||
import lombok.Data; | |||
import org.apache.shiro.authz.annotation.RequiresPermissions; | |||
import org.dubhe.annotation.ApiVersion; | |||
import org.springframework.core.annotation.AnnotationUtils; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.web.servlet.mvc.condition.RequestCondition; | |||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; | |||
import java.lang.reflect.Method; | |||
import java.util.HashSet; | |||
import java.util.Set; | |||
/** | |||
* @description 权限注解收集 | |||
* @date 2020-04-06 | |||
*/ | |||
@Component | |||
@Data | |||
public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping { | |||
Set<String> permissionsSet =new HashSet<String>(); | |||
@Override | |||
protected RequestCondition<ApiVersionCondition> getCustomTypeCondition(Class<?> handlerType) { | |||
ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class); | |||
return createCondition(apiVersion); | |||
} | |||
@Override | |||
protected RequestCondition<ApiVersionCondition> getCustomMethodCondition(Method method) { | |||
RequiresPermissions requiresPermissions = AnnotationUtils.findAnnotation(method, RequiresPermissions.class); | |||
if(requiresPermissions != null){ | |||
if(requiresPermissions.value()!=null){ | |||
for(int i=0;i<requiresPermissions.value().length;i++){ | |||
permissionsSet.add(requiresPermissions.value()[i]); | |||
} | |||
} | |||
} | |||
ApiVersion apiVersion = AnnotationUtils.findAnnotation(method, ApiVersion.class); | |||
return createCondition(apiVersion); | |||
} | |||
private RequestCondition<ApiVersionCondition> createCondition(ApiVersion apiVersion) { | |||
return apiVersion == null ? null : new ApiVersionCondition(apiVersion.value()); | |||
} | |||
} |
@@ -0,0 +1,58 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.interceptor; | |||
import org.dubhe.enums.LogEnum; | |||
import org.dubhe.utils.K8sCallBackTool; | |||
import org.dubhe.utils.LogUtil; | |||
import org.dubhe.utils.StringUtils; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; | |||
import javax.servlet.http.HttpServletRequest; | |||
import javax.servlet.http.HttpServletResponse; | |||
/** | |||
* @description k8s pod 异步回调拦截器 | |||
* | |||
* @date 2020-05-28 | |||
*/ | |||
@Component | |||
public class K8sCallBackPodInterceptor extends HandlerInterceptorAdapter { | |||
@Autowired | |||
private K8sCallBackTool k8sCallBackTool; | |||
@Override | |||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { | |||
String uri = request.getRequestURI(); | |||
LogUtil.debug(LogEnum.BIZ_K8S,"接收到k8s异步请求,URI:{}",uri); | |||
String k8sCallbackToken = request.getHeader(K8sCallBackTool.K8S_CALLBACK_TOKEN); | |||
if (StringUtils.isBlank(k8sCallbackToken)){ | |||
LogUtil.warn(LogEnum.BIZ_K8S,"k8s异步回调没有配置【{}】,URI:{}",K8sCallBackTool.K8S_CALLBACK_TOKEN,uri); | |||
return false; | |||
} | |||
boolean pass = k8sCallBackTool.validateToken(k8sCallbackToken); | |||
if (!pass){ | |||
LogUtil.warn(LogEnum.BIZ_K8S,"k8s异步回调token:【{}】 验证不通过,URI:{}",k8sCallbackToken,uri); | |||
} | |||
return pass; | |||
} | |||
} |
@@ -0,0 +1,97 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import cn.hutool.core.util.HexUtil; | |||
import org.dubhe.enums.LogEnum; | |||
import javax.crypto.Cipher; | |||
import javax.crypto.NoSuchPaddingException; | |||
import javax.crypto.spec.SecretKeySpec; | |||
import java.nio.charset.StandardCharsets; | |||
import java.security.InvalidKeyException; | |||
import java.security.MessageDigest; | |||
import java.security.NoSuchAlgorithmException; | |||
/** | |||
* @description AES加解密工具 | |||
* @date 2020-06-01 | |||
*/ | |||
public class AesUtil { | |||
private static final String AES = "AES"; | |||
private AesUtil(){ | |||
} | |||
/** | |||
* | |||
* @param mode Cipher mode | |||
* @param key 秘钥 | |||
* @return Cipher | |||
* @throws NoSuchAlgorithmException | |||
* @throws NoSuchPaddingException | |||
* @throws InvalidKeyException | |||
*/ | |||
private static Cipher getCipher(int mode,String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException { | |||
MessageDigest md5Digest = MessageDigest.getInstance("MD5"); | |||
SecretKeySpec secretKeySpec = new SecretKeySpec(md5Digest.digest(key.getBytes(StandardCharsets.UTF_8)), AES); | |||
Cipher cipher = Cipher.getInstance(AES); | |||
cipher.init(mode, secretKeySpec); | |||
return cipher; | |||
} | |||
/** | |||
* 加密 | |||
* | |||
* @param data 原文 | |||
* @param key 秘钥 | |||
* @return String 密文 | |||
*/ | |||
public static String encrypt(String data, String key) { | |||
try { | |||
Cipher cipher = getCipher(Cipher.ENCRYPT_MODE,key); | |||
byte[] content = data.getBytes(StandardCharsets.UTF_8); | |||
return new String(HexUtil.encodeHex(cipher.doFinal(content), false)); | |||
} catch (Exception e) { | |||
LogUtil.error(LogEnum.BIZ_SYS,"Md5Util 加密失败 ",e); | |||
return null; | |||
} | |||
} | |||
/** | |||
* 解密 | |||
* @param hexData 十六进制密文 | |||
* @param key 秘钥 | |||
* @return String 密文 | |||
*/ | |||
public static String decrypt(String hexData, String key) { | |||
try { | |||
Cipher cipher = getCipher(Cipher.DECRYPT_MODE,key); | |||
byte[] content = HexUtil.decodeHex(hexData); | |||
return new String(cipher.doFinal(content), StandardCharsets.UTF_8); | |||
} catch (Exception e) { | |||
LogUtil.error(LogEnum.BIZ_SYS,"Md5Util 解密失败 ",e); | |||
return null; | |||
} | |||
} | |||
} |
@@ -0,0 +1,80 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import java.sql.Timestamp; | |||
import java.time.Instant; | |||
import java.time.LocalDate; | |||
import java.time.LocalDateTime; | |||
import java.time.ZoneId; | |||
/** | |||
* @description 日期工具类 | |||
* @date 2020-6-10 | |||
*/ | |||
public class DateUtil { | |||
/** | |||
* 获取当前时间戳 | |||
* | |||
* @return | |||
*/ | |||
public static Timestamp getCurrentTimestamp() { | |||
return Timestamp.valueOf(LocalDateTime.now()); | |||
} | |||
/** | |||
* 获取六小时后时间 | |||
* @return | |||
*/ | |||
public static long getAfterSixHourTime(){ | |||
long l1 = getTimestampOfDateTime(LocalDateTime.now()); | |||
long milli = getTimestampOfDateTime(LocalDateTime.now().plusHours(6)); | |||
return (milli-l1); | |||
} | |||
/** | |||
* LocalDateTime -> long | |||
* @param localDateTime | |||
* @return | |||
*/ | |||
public static long getTimestampOfDateTime(LocalDateTime localDateTime) { | |||
ZoneId zone = ZoneId.systemDefault(); | |||
Instant instant = localDateTime.atZone(zone).toInstant(); | |||
return instant.toEpochMilli(); | |||
} | |||
/** | |||
* 获取第二天凌晨时间 | |||
* @return | |||
*/ | |||
public static long getSecondTime(){ | |||
LocalDateTime localDateTime = LocalDateTime.now(); | |||
long l1 = localDateTime.atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli(); | |||
LocalDate localDate = LocalDate.now(); | |||
LocalDate localDate1 = localDate.plusDays(1); | |||
LocalDateTime localDateTime1 = localDate1.atStartOfDay(); | |||
long milli = localDateTime1.atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli(); | |||
System.out.println("当前时间到第二天凌晨的毫秒数"+(milli-l1)); | |||
return (milli-l1); | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
/** | |||
* @description 日期工具类 | |||
* @date 2020-5-29 | |||
**/ | |||
public class DubheDateUtil { | |||
private static final int SIXTY = 60; | |||
/** | |||
* 将时间 秒 转为 小时 | |||
* | |||
* @param second 秒数 | |||
* @return | |||
*/ | |||
public static String convert2Str(Long second) { | |||
if (null == second || second < 1) { | |||
return ""; | |||
} | |||
Long hh = second / (SIXTY * SIXTY); | |||
second = second % (SIXTY * SIXTY); | |||
Long mm = second / SIXTY; | |||
Long ss = second % SIXTY; | |||
StringBuilder sb = new StringBuilder(); | |||
sb.append(String.format("%02d", hh)).append(":").append(String.format("%02d", mm)).append(":").append(String.format("%02d", ss)); | |||
return sb.toString(); | |||
} | |||
} |
@@ -0,0 +1,100 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import javax.crypto.Cipher; | |||
import javax.crypto.SecretKey; | |||
import javax.crypto.SecretKeyFactory; | |||
import javax.crypto.spec.DESKeySpec; | |||
import javax.crypto.spec.IvParameterSpec; | |||
import java.nio.charset.StandardCharsets; | |||
/** | |||
* @description 加密 | |||
* @date 2020-03-13 | |||
*/ | |||
public class EncryptUtils { | |||
private static String strParam = "Passw0rd"; | |||
private static Cipher cipher; | |||
private static IvParameterSpec iv = new IvParameterSpec(strParam.getBytes(StandardCharsets.UTF_8)); | |||
private static DESKeySpec getDesKeySpec(String source) throws Exception { | |||
if (source == null || source.length() == 0) { | |||
return null; | |||
} | |||
cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); | |||
String strKey = "Passw0rd"; | |||
return new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8)); | |||
} | |||
/** | |||
* 对称加密 | |||
*/ | |||
public static String desEncrypt(String source) throws Exception { | |||
DESKeySpec desKeySpec = getDesKeySpec(source); | |||
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); | |||
SecretKey secretKey = keyFactory.generateSecret(desKeySpec); | |||
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv); | |||
return byte2hex( | |||
cipher.doFinal(source.getBytes(StandardCharsets.UTF_8))).toUpperCase(); | |||
} | |||
/** | |||
* 对称解密 | |||
*/ | |||
public static String desDecrypt(String source) throws Exception { | |||
byte[] src = hex2byte(source.getBytes()); | |||
DESKeySpec desKeySpec = getDesKeySpec(source); | |||
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); | |||
SecretKey secretKey = keyFactory.generateSecret(desKeySpec); | |||
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv); | |||
byte[] retByte = cipher.doFinal(src); | |||
return new String(retByte); | |||
} | |||
private static String byte2hex(byte[] inStr) { | |||
String stmp; | |||
StringBuilder out = new StringBuilder(inStr.length * 2); | |||
for (byte b : inStr) { | |||
stmp = Integer.toHexString(b & 0xFF); | |||
if (stmp.length() == 1) { | |||
// 如果是0至F的单位字符串,则添加0 | |||
out.append("0").append(stmp); | |||
} else { | |||
out.append(stmp); | |||
} | |||
} | |||
return out.toString(); | |||
} | |||
private static byte[] hex2byte(byte[] b) { | |||
int size = 2; | |||
if ((b.length % size) != 0) { | |||
throw new IllegalArgumentException("长度不是偶数"); | |||
} | |||
byte[] b2 = new byte[b.length / 2]; | |||
for (int n = 0; n < b.length; n += size) { | |||
String item = new String(b, n, 2); | |||
b2[n / 2] = (byte) Integer.parseInt(item, 16); | |||
} | |||
return b2; | |||
} | |||
} |
@@ -0,0 +1,355 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import cn.hutool.core.codec.Base64; | |||
import cn.hutool.core.io.IoUtil; | |||
import cn.hutool.core.util.IdUtil; | |||
import cn.hutool.poi.excel.BigExcelWriter; | |||
import cn.hutool.poi.excel.ExcelUtil; | |||
import org.apache.poi.util.IOUtils; | |||
import org.dubhe.exception.BusinessException; | |||
import org.springframework.web.multipart.MultipartFile; | |||
import javax.servlet.ServletOutputStream; | |||
import javax.servlet.http.HttpServletRequest; | |||
import javax.servlet.http.HttpServletResponse; | |||
import java.io.*; | |||
import java.security.MessageDigest; | |||
import java.text.DecimalFormat; | |||
import java.text.SimpleDateFormat; | |||
import java.util.Date; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* @description File工具类,扩展 hutool 工具包 | |||
* @date 2020-03-14 | |||
*/ | |||
public class FileUtil extends cn.hutool.core.io.FileUtil { | |||
/** | |||
* 定义GB的计算常量 | |||
*/ | |||
private static final int GB = 1024 * 1024 * 1024; | |||
/** | |||
* 定义MB的计算常量 | |||
*/ | |||
private static final int MB = 1024 * 1024; | |||
/** | |||
* 定义KB的计算常量 | |||
*/ | |||
private static final int KB = 1024; | |||
/** | |||
* 格式化小数 | |||
*/ | |||
private static final DecimalFormat DF = new DecimalFormat("0.00"); | |||
/** | |||
* MultipartFile转File | |||
*/ | |||
public static File toFile(MultipartFile multipartFile) { | |||
// 获取文件名 | |||
String fileName = multipartFile.getOriginalFilename(); | |||
// 获取文件后缀 | |||
String prefix = "." + getExtensionName(fileName); | |||
File file = null; | |||
try { | |||
// 用uuid作为文件名,防止生成的临时文件重复 | |||
file = File.createTempFile(IdUtil.simpleUUID(), prefix); | |||
// MultipartFile to File | |||
multipartFile.transferTo(file); | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} | |||
return file; | |||
} | |||
/** | |||
* 获取文件扩展名,不带 . | |||
*/ | |||
public static String getExtensionName(String filename) { | |||
if ((filename != null) && (filename.length() > 0)) { | |||
int dot = filename.lastIndexOf('.'); | |||
if ((dot > -1) && (dot < (filename.length() - 1))) { | |||
return filename.substring(dot + 1); | |||
} | |||
} | |||
return filename; | |||
} | |||
/** | |||
* Java文件操作 获取不带扩展名的文件名 | |||
*/ | |||
public static String getFileNameNoEx(String filename) { | |||
if ((filename != null) && (filename.length() > 0)) { | |||
int dot = filename.lastIndexOf('.'); | |||
if ((dot > -1) && (dot < (filename.length()))) { | |||
return filename.substring(0, dot); | |||
} | |||
} | |||
return filename; | |||
} | |||
/** | |||
* 文件大小转换 | |||
*/ | |||
public static String getSize(long size) { | |||
String resultSize; | |||
if (size / GB >= 1) { | |||
//如果当前Byte的值大于等于1GB | |||
resultSize = DF.format(size / (float) GB) + "GB "; | |||
} else if (size / MB >= 1) { | |||
//如果当前Byte的值大于等于1MB | |||
resultSize = DF.format(size / (float) MB) + "MB "; | |||
} else if (size / KB >= 1) { | |||
//如果当前Byte的值大于等于1KB | |||
resultSize = DF.format(size / (float) KB) + "KB "; | |||
} else { | |||
resultSize = size + "B "; | |||
} | |||
return resultSize; | |||
} | |||
/** | |||
* inputStream 转 File | |||
*/ | |||
static File inputStreamToFile(InputStream ins, String name) throws Exception { | |||
File file = new File(System.getProperty("java.io.tmpdir") + File.separator + name); | |||
if (file.exists()) { | |||
return file; | |||
} | |||
OutputStream os = new FileOutputStream(file); | |||
int bytesRead; | |||
int len = 8192; | |||
byte[] buffer = new byte[len]; | |||
while ((bytesRead = ins.read(buffer, 0, len)) != -1) { | |||
os.write(buffer, 0, bytesRead); | |||
} | |||
os.close(); | |||
ins.close(); | |||
return file; | |||
} | |||
/** | |||
* 将文件名解析成文件的上传路径 | |||
*/ | |||
public static File upload(MultipartFile file, String filePath) { | |||
Date date = new Date(); | |||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS"); | |||
String name = getFileNameNoEx(file.getOriginalFilename()); | |||
String suffix = getExtensionName(file.getOriginalFilename()); | |||
String nowStr = "-" + format.format(date); | |||
try { | |||
String fileName = name + nowStr + "." + suffix; | |||
String path = filePath + fileName; | |||
// getCanonicalFile 可解析正确各种路径 | |||
File dest = new File(path).getCanonicalFile(); | |||
// 检测是否存在目录 | |||
if (!dest.getParentFile().exists()) { | |||
dest.getParentFile().mkdirs(); | |||
} | |||
// 文件写入 | |||
file.transferTo(dest); | |||
return dest; | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
return null; | |||
} | |||
public static String fileToBase64(File file) throws Exception { | |||
FileInputStream inputFile = new FileInputStream(file); | |||
String base64; | |||
byte[] buffer = new byte[(int) file.length()]; | |||
inputFile.read(buffer); | |||
inputFile.close(); | |||
base64 = Base64.encode(buffer); | |||
return base64.replaceAll("[\\s*\t\n\r]", ""); | |||
} | |||
/** | |||
* 导出excel | |||
*/ | |||
public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException { | |||
String tempPath = System.getProperty("java.io.tmpdir") + IdUtil.fastSimpleUUID() + ".xlsx"; | |||
File file = new File(tempPath); | |||
BigExcelWriter writer = ExcelUtil.getBigWriter(file); | |||
// 一次性写出内容,使用默认样式,强制输出标题 | |||
writer.write(list, true); | |||
//response为HttpServletResponse对象 | |||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"); | |||
//test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码 | |||
response.setHeader("Content-Disposition", "attachment;filename=file.xlsx"); | |||
ServletOutputStream out = response.getOutputStream(); | |||
// 终止后删除临时文件 | |||
file.deleteOnExit(); | |||
writer.flush(out, true); | |||
//此处记得关闭输出Servlet流 | |||
IoUtil.close(out); | |||
} | |||
/** | |||
* 下载文件 | |||
*/ | |||
public static void download(String path, HttpServletResponse response) { | |||
if (path == null) { | |||
return; | |||
} | |||
FileInputStream fis = null; | |||
ServletOutputStream out = null; | |||
try { | |||
File file = new File(path); | |||
fis = new FileInputStream(file); | |||
out = response.getOutputStream(); | |||
IOUtils.copy(fis, out); | |||
response.flushBuffer(); | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} finally { | |||
if (fis != null) { | |||
try { | |||
fis.close(); | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} | |||
} | |||
//此处记得关闭输出Servlet流 | |||
IoUtil.close(out); | |||
} | |||
} | |||
public static String getFileType(String type) { | |||
String documents = "txt doc pdf ppt pps xlsx xls docx"; | |||
String music = "mp3 wav wma mpa ram ra aac aif m4a"; | |||
String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg"; | |||
String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg"; | |||
if (image.contains(type)) { | |||
return "图片"; | |||
} else if (documents.contains(type)) { | |||
return "文档"; | |||
} else if (music.contains(type)) { | |||
return "音乐"; | |||
} else if (video.contains(type)) { | |||
return "视频"; | |||
} else { | |||
return "其他"; | |||
} | |||
} | |||
public static void checkSize(long maxSize, long size) { | |||
// 1M | |||
int len = 1024 * 1024; | |||
if (size > (maxSize * len)) { | |||
throw new BusinessException("文件超出规定大小"); | |||
} | |||
} | |||
/** | |||
* 判断两个文件是否相同 | |||
*/ | |||
public static boolean check(File file1, File file2) { | |||
String img1Md5 = getMd5(file1); | |||
String img2Md5 = getMd5(file2); | |||
return img1Md5.equals(img2Md5); | |||
} | |||
/** | |||
* 判断两个文件是否相同 | |||
*/ | |||
public static boolean check(String file1Md5, String file2Md5) { | |||
return file1Md5.equals(file2Md5); | |||
} | |||
private static byte[] getByte(File file) { | |||
// 得到文件长度 | |||
byte[] b = new byte[(int) file.length()]; | |||
try { | |||
InputStream in = new FileInputStream(file); | |||
try { | |||
in.read(b); | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} | |||
} catch (FileNotFoundException e) { | |||
e.printStackTrace(); | |||
return null; | |||
} | |||
return b; | |||
} | |||
private static String getMd5(byte[] bytes) { | |||
// 16进制字符 | |||
char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; | |||
try { | |||
MessageDigest mdTemp = MessageDigest.getInstance("MD5"); | |||
mdTemp.update(bytes); | |||
byte[] md = mdTemp.digest(); | |||
int j = md.length; | |||
char[] str = new char[j * 2]; | |||
int k = 0; | |||
// 移位 输出字符串 | |||
for (byte byte0 : md) { | |||
str[k++] = hexDigits[byte0 >>> 4 & 0xf]; | |||
str[k++] = hexDigits[byte0 & 0xf]; | |||
} | |||
return new String(str); | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
return null; | |||
} | |||
/** | |||
* 下载文件 | |||
* | |||
* @param request / | |||
* @param response / | |||
* @param file / | |||
*/ | |||
public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) { | |||
response.setCharacterEncoding(request.getCharacterEncoding()); | |||
response.setContentType("application/octet-stream"); | |||
FileInputStream fis = null; | |||
try { | |||
fis = new FileInputStream(file); | |||
response.setHeader("Content-Disposition", "attachment; filename=" + file.getName()); | |||
IOUtils.copy(fis, response.getOutputStream()); | |||
response.flushBuffer(); | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} finally { | |||
if (fis != null) { | |||
try { | |||
fis.close(); | |||
if (deleteOnExit) { | |||
file.deleteOnExit(); | |||
} | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} | |||
} | |||
} | |||
} | |||
public static String getMd5(File file) { | |||
return getMd5(getByte(file)); | |||
} | |||
} |
@@ -0,0 +1,131 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import org.apache.commons.io.IOUtils; | |||
import org.dubhe.enums.LogEnum; | |||
import javax.net.ssl.HttpsURLConnection; | |||
import javax.net.ssl.SSLContext; | |||
import javax.net.ssl.SSLSocketFactory; | |||
import javax.net.ssl.TrustManager; | |||
import javax.net.ssl.X509TrustManager; | |||
import java.io.BufferedReader; | |||
import java.io.InputStream; | |||
import java.io.InputStreamReader; | |||
import java.net.URL; | |||
import java.security.cert.CertificateException; | |||
import java.security.cert.X509Certificate; | |||
import static org.dubhe.constant.StringConstant.UTF8; | |||
import static org.dubhe.constant.SymbolConstant.BLANK; | |||
/** | |||
* @description: httpClient工具类,不校验SSL证书 | |||
* @date: 2020-5-21 | |||
*/ | |||
public class HttpClientUtils { | |||
public static String sendHttps(String path) { | |||
InputStream inputStream = null; | |||
BufferedReader bufferedReader = null; | |||
InputStreamReader inputStreamReader = null; | |||
StringBuilder stringBuider = new StringBuilder(); | |||
String result = BLANK; | |||
HttpsURLConnection con = null; | |||
try { | |||
con = getConnection(path); | |||
con.connect(); | |||
/**将返回的输入流转换成字符串**/ | |||
inputStream = con.getInputStream(); | |||
inputStreamReader = new InputStreamReader(inputStream, UTF8); | |||
bufferedReader = new BufferedReader(inputStreamReader); | |||
String str = null; | |||
while ((str = bufferedReader.readLine()) != null) { | |||
stringBuider.append(str); | |||
} | |||
result = stringBuider.toString(); | |||
LogUtil.info(LogEnum.BIZ_SYS,"Request path:{}, SUCCESS, result:{}", path, result); | |||
} catch (Exception e) { | |||
LogUtil.error(LogEnum.BIZ_SYS,"Request path:{}, ERROR, exception:{}", path, e); | |||
return result; | |||
} finally { | |||
closeResource(bufferedReader,inputStreamReader,inputStream,con); | |||
} | |||
return result; | |||
} | |||
private static void closeResource(BufferedReader bufferedReader,InputStreamReader inputStreamReader,InputStream inputStream,HttpsURLConnection con) { | |||
IOUtils.closeQuietly(bufferedReader); | |||
if (inputStreamReader != null) { | |||
IOUtils.closeQuietly(inputStreamReader); | |||
} | |||
if (inputStream != null) { | |||
IOUtils.closeQuietly(inputStream); | |||
} | |||
if (con != null) { | |||
con.disconnect(); | |||
} | |||
} | |||
private static HttpsURLConnection getConnection(String path){ | |||
HttpsURLConnection con = null; | |||
try { | |||
/**创建并初始化SSLContext对象**/ | |||
TrustManager[] trustManagers = {new X509TrustManager() { | |||
@Override | |||
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { | |||
} | |||
@Override | |||
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { | |||
} | |||
@Override | |||
public X509Certificate[] getAcceptedIssuers() { | |||
return null; | |||
} | |||
}}; | |||
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); | |||
sslContext.init(null, trustManagers, new java.security.SecureRandom()); | |||
/**得到SSLSocketFactory对象**/ | |||
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); | |||
URL url = new URL(path); | |||
con = (HttpsURLConnection) url.openConnection(); | |||
con.setSSLSocketFactory(sslSocketFactory); | |||
con.setUseCaches(false); | |||
}catch (Exception e){ | |||
LogUtil.error(LogEnum.BIZ_SYS,"Request path:{}, error, exception:{}", path, e); | |||
} | |||
return con; | |||
} | |||
} | |||
@@ -0,0 +1,66 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import lombok.extern.slf4j.Slf4j; | |||
/** | |||
* @description: HttpUtil | |||
* @date 2020.04.30 | |||
*/ | |||
@Slf4j | |||
public class HttpUtils { | |||
private HttpUtils() { | |||
} | |||
/** | |||
* 判断http请求是否成功 | |||
* | |||
* @param httpCode | |||
* 1XX Informational(信息性状态码) | |||
* 2XX Success(成功状态码) | |||
* 3XX Redirection(重定向状态码) | |||
* 4XX Client Error(客户端错误状态码) | |||
* 5XX Server Error(服务器错误状态码) | |||
* @return | |||
*/ | |||
public static boolean isSuccess(String httpCode){ | |||
if (StringUtils.isBlank(httpCode)){ | |||
return false; | |||
} | |||
return httpCode.length() == 3 && httpCode.startsWith("2"); | |||
} | |||
/** | |||
* 判断http请求是否成功 | |||
* | |||
* @param httpCode | |||
* 1XX Informational(信息性状态码) | |||
* 2XX Success(成功状态码) | |||
* 3XX Redirection(重定向状态码) | |||
* 4XX Client Error(客户端错误状态码) | |||
* 5XX Server Error(服务器错误状态码) | |||
* @return | |||
*/ | |||
public static boolean isSuccess(int httpCode) { | |||
return isSuccess(String.valueOf(httpCode)); | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.context.annotation.Configuration; | |||
/** | |||
* @description JWT配置类 | |||
* @date 2020-04-15 | |||
*/ | |||
@Configuration | |||
public class JwcConfig { | |||
@Value("${jwt.online-key}") | |||
public String onlineKey; | |||
@Autowired | |||
public RedisUtils redisUtils; | |||
@Value("${jwt.token-validity-in-seconds}") | |||
public Long jwtExpiration; | |||
@Value("${jwt.base64-secret}") | |||
public String secret; | |||
} |
@@ -0,0 +1,203 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import com.auth0.jwt.JWT; | |||
import com.auth0.jwt.JWTCreator.Builder; | |||
import com.auth0.jwt.JWTVerifier; | |||
import com.auth0.jwt.algorithms.Algorithm; | |||
import com.auth0.jwt.exceptions.JWTDecodeException; | |||
import com.auth0.jwt.interfaces.Claim; | |||
import com.auth0.jwt.interfaces.DecodedJWT; | |||
import org.apache.shiro.SecurityUtils; | |||
import org.apache.shiro.crypto.SecureRandomNumberGenerator; | |||
import org.apache.shiro.mgt.SecurityManager; | |||
import org.apache.shiro.util.ThreadContext; | |||
import org.dubhe.domain.dto.UserDTO; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.stereotype.Component; | |||
import java.io.UnsupportedEncodingException; | |||
import java.util.Calendar; | |||
import java.util.Date; | |||
import java.util.Map; | |||
import java.util.Map.Entry; | |||
import java.util.Objects; | |||
import java.util.concurrent.TimeUnit; | |||
/** | |||
* @description JWT | |||
* @date 2020-03-14 | |||
*/ | |||
@Component | |||
public class JwtUtils { | |||
/** | |||
* 请求头 | |||
*/ | |||
public static final String AUTH_HEADER = "Authorization"; | |||
/** | |||
* 过期时间20分钟 | |||
*/ | |||
private static final long EXPIRE_TIME = 20 * 60 * 1000; | |||
private static final String FIELD_NAME = "USER_NAME"; | |||
private static JwcConfig jwcConfig; | |||
private static RedisUtils redisUtils; | |||
@Autowired | |||
public void setJwcConfig(JwcConfig mtJwcConfig) { | |||
jwcConfig = mtJwcConfig; | |||
} | |||
@Autowired | |||
public void setRedisUtils(RedisUtils myredisUtils) { | |||
redisUtils = myredisUtils; | |||
} | |||
/** | |||
* 验证token是否正确 | |||
*/ | |||
public static boolean verify(String token, String username) { | |||
try { | |||
Algorithm algorithm = null; | |||
algorithm = Algorithm.HMAC256(jwcConfig.secret); | |||
JWTVerifier verifier = JWT.require(algorithm).withClaim(FIELD_NAME, username).build(); | |||
verifier.verify(token); | |||
return true; | |||
} catch (UnsupportedEncodingException exception) { | |||
return false; | |||
} | |||
} | |||
/** | |||
* 获得token中的自定义信息,无需secret解密也能获得 | |||
*/ | |||
public static String getClaimFiled(String token, String filed) { | |||
try { | |||
DecodedJWT jwt = JWT.decode(token); | |||
return jwt.getClaim(filed).asString(); | |||
} catch (JWTDecodeException e) { | |||
return null; | |||
} | |||
} | |||
/** | |||
* 生成签名 | |||
*/ | |||
public static String sign(String userName) { | |||
try { | |||
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME); | |||
Algorithm algorithm = Algorithm.HMAC256(jwcConfig.secret); | |||
// 附带username, | |||
String token = JWT.create().withClaim(FIELD_NAME, userName).withExpiresAt(date).sign(algorithm); | |||
saveToken(userName, token); | |||
return token; | |||
} catch (UnsupportedEncodingException e) { | |||
return null; | |||
} | |||
} | |||
/** | |||
* 获取用户名 | |||
*/ | |||
public static String getUserName(String token) { | |||
return getClaimFiled(token, FIELD_NAME); | |||
} | |||
/** | |||
* 获取 token的签发时间 | |||
*/ | |||
public static Date getIssuedAt(String token) { | |||
try { | |||
DecodedJWT jwt = JWT.decode(token); | |||
return jwt.getIssuedAt(); | |||
} catch (JWTDecodeException e) { | |||
return null; | |||
} | |||
} | |||
/** | |||
* 验证 token是否过期 | |||
*/ | |||
public static boolean isTokenExpired(String token) { | |||
Date now = Calendar.getInstance().getTime(); | |||
DecodedJWT jwt = JWT.decode(token); | |||
return jwt.getExpiresAt().before(now); | |||
} | |||
/** | |||
* 刷新 token的过期时间 | |||
*/ | |||
public static String refreshTokenExpired(String token) { | |||
DecodedJWT jwt = JWT.decode(token); | |||
Map<String, Claim> claims = jwt.getClaims(); | |||
try { | |||
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME); | |||
Algorithm algorithm = Algorithm.HMAC256(jwcConfig.secret); | |||
Builder builer = JWT.create().withExpiresAt(date); | |||
for (Entry<String, Claim> entry : claims.entrySet()) { | |||
builer.withClaim(entry.getKey(), entry.getValue().asString()); | |||
} | |||
String newToken = builer.sign(algorithm); | |||
String userName = claims.get(FIELD_NAME).asString(); | |||
String tokenKey = getUserTokenKey(userName); | |||
if (redisUtils.get(tokenKey) == null) { | |||
return null; | |||
} | |||
saveToken(userName, newToken); | |||
return newToken; | |||
} catch (UnsupportedEncodingException e) { | |||
return null; | |||
} | |||
} | |||
/** | |||
* 生成16位随机盐 | |||
*/ | |||
public static String generateSalt() { | |||
SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator(); | |||
String hex = secureRandom.nextBytes(16).toHex(); | |||
return hex; | |||
} | |||
/** | |||
* 获取当前用户 | |||
*/ | |||
public static UserDTO getCurrentUserDto() { | |||
Object principal = null; | |||
SecurityManager manager = ThreadContext.getSecurityManager(); | |||
if (!Objects.isNull(manager)) { | |||
principal = SecurityUtils.getSubject().getPrincipal(); | |||
} | |||
return Objects.isNull(principal) ? null : (UserDTO) principal; | |||
} | |||
/** | |||
* 获取用户token key | |||
*/ | |||
private static String getUserTokenKey(String userName) { | |||
return jwcConfig.onlineKey + userName; | |||
} | |||
private static void saveToken(String userName, String token) { | |||
String tokenKey = getUserTokenKey(userName); | |||
redisUtils.set(tokenKey, token, jwcConfig.jwtExpiration, TimeUnit.MINUTES); | |||
} | |||
} |
@@ -0,0 +1,168 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import cn.hutool.core.date.DateField; | |||
import cn.hutool.core.date.DatePattern; | |||
import cn.hutool.core.date.DateUtil; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.stereotype.Component; | |||
import java.util.ArrayList; | |||
import java.util.Date; | |||
import java.util.List; | |||
/** | |||
* @description k8s命名相关工具类 token使用MD5加密,并设置超时时间 | |||
* @date 2020-05-28 | |||
*/ | |||
@Component | |||
public class K8sCallBackTool { | |||
/** | |||
* k8s 回调 token秘钥 | |||
*/ | |||
@Value("${k8s.callback.token.secret-key}") | |||
private String secretKey; | |||
/** | |||
* k8s 回调token超时时间 | |||
*/ | |||
@Value("${k8s.callback.token.expire-seconds}") | |||
private Integer expireSeconds; | |||
/** | |||
* k8s 回调域名或IP:Port | |||
*/ | |||
@Value("${k8s.callback.url}") | |||
private String url; | |||
/** | |||
* k8s 回调token key | |||
*/ | |||
public static final String K8S_CALLBACK_TOKEN = "k8sCallbackToken"; | |||
/** | |||
* 失败重试次数 | |||
*/ | |||
private static final int RETRY_COUNT = 3; | |||
/** | |||
* k8s 回调匹配地址 | |||
*/ | |||
private static final List<String> K8S_CALLBACK_PATH; | |||
/** | |||
* k8s 回调路径 | |||
*/ | |||
private static final String K8S_CALLBACK_PATH_POD = "/api/k8s/callback/pod/"; | |||
static { | |||
K8S_CALLBACK_PATH = new ArrayList<>(); | |||
// 添加需要token权限校验的地址(Shiro匿名访问的地址) | |||
K8S_CALLBACK_PATH.add(K8S_CALLBACK_PATH_POD + "**"); | |||
} | |||
/** | |||
* 获取 k8s 回调匹配地址 | |||
* | |||
* @return List<String> | |||
*/ | |||
public static List<String> getK8sCallbackPaths() { | |||
return new ArrayList<>(K8S_CALLBACK_PATH); | |||
} | |||
/** | |||
* 生成k8s回调 | |||
* | |||
* @return String | |||
*/ | |||
public String generateToken() { | |||
String expireTime = DateUtil.format( | |||
DateUtil.offset(new Date(), DateField.SECOND, expireSeconds), | |||
DatePattern.PURE_DATETIME_PATTERN | |||
); | |||
return AesUtil.encrypt(expireTime, secretKey); | |||
} | |||
/** | |||
* 验证token | |||
* | |||
* @param token | |||
* @return boolean | |||
*/ | |||
public boolean validateToken(String token) { | |||
String expireTime = AesUtil.decrypt(token, secretKey); | |||
String nowTime = DateUtil.format( | |||
new Date(), | |||
DatePattern.PURE_DATETIME_PATTERN | |||
); | |||
return expireTime.compareTo(nowTime) > 0; | |||
} | |||
/** | |||
* 判断当前是否可以再次重试 | |||
* | |||
* @param retryTimes 第n次试图重试 | |||
* @return boolean | |||
*/ | |||
public boolean continueRetry(int retryTimes) { | |||
return retryTimes <= RETRY_COUNT; | |||
} | |||
/** | |||
* 获取回调地址 | |||
* | |||
* @param podLabel | |||
* @return String | |||
*/ | |||
public String getPodCallbackUrl(String podLabel) { | |||
return url + K8S_CALLBACK_PATH_POD + podLabel; | |||
} | |||
/** | |||
* 获取超时时间秒 | |||
* | |||
* @param timeoutSecond 超时秒数 | |||
* @return Long | |||
*/ | |||
public static Long getTimeoutSecondLong(int timeoutSecond) { | |||
return Long.valueOf( | |||
DateUtil.format( | |||
DateUtil.offset( | |||
new Date(), DateField.SECOND, timeoutSecond | |||
), | |||
DatePattern.PURE_DATETIME_PATTERN | |||
) | |||
); | |||
} | |||
/** | |||
* 获取当前秒数 | |||
* | |||
* @return Long | |||
*/ | |||
public static Long getCurrentSecondLong() { | |||
return Long.valueOf( | |||
DateUtil.format( | |||
new Date(), | |||
DatePattern.PURE_DATETIME_PATTERN | |||
) | |||
); | |||
} | |||
} |
@@ -0,0 +1,255 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import cn.hutool.core.date.DatePattern; | |||
import cn.hutool.core.date.DateUtil; | |||
import cn.hutool.core.util.RandomUtil; | |||
import org.dubhe.config.K8sNameConfig; | |||
import org.dubhe.constant.SymbolConstant; | |||
import org.dubhe.enums.BizEnum; | |||
import org.dubhe.enums.BizNfsEnum; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.stereotype.Component; | |||
import org.apache.commons.lang3.StringUtils; | |||
import java.util.Date; | |||
/** | |||
* @description k8s命名相关工具类 | |||
* @date 2020-05-13 | |||
*/ | |||
@Component | |||
public class K8sNameTool { | |||
@Autowired | |||
private K8sNameConfig k8sNameConfig; | |||
/** | |||
* 命名分隔符 | |||
*/ | |||
private static final char SEPARATOR = '-'; | |||
/** | |||
* 文件分隔符 | |||
*/ | |||
private static final String K8S_FILE_SEPARATOR = "/"; | |||
/** | |||
* 资源名称前缀 | |||
*/ | |||
private static final String RESOURCE_NAME = "rn"; | |||
/** | |||
* 随机长度值 | |||
*/ | |||
private static final int RANDOM_LENGTH = 4; | |||
/** | |||
* 生成 ResourceName | |||
* | |||
* @param bizEnum 业务枚举 | |||
* @param resourceInfo 资源备注信息(保证同业务下唯一并且命名规范) | |||
* @return String | |||
*/ | |||
public String generateResourceName(BizEnum bizEnum, String resourceInfo) { | |||
return bizEnum.getBizCode() + SEPARATOR + RESOURCE_NAME + SEPARATOR + resourceInfo; | |||
} | |||
/** | |||
* 生成 Notebook的NameSpace | |||
* | |||
* @param userId | |||
* @return namespace | |||
*/ | |||
public String generateNameSpace(long userId) { | |||
return this.k8sNameConfig.getNamespace() + SEPARATOR + userId; | |||
} | |||
/** | |||
* 从resourceName中获取资源信息 | |||
* | |||
* @param bizEnum 业务枚举 | |||
* @param resourceName | |||
* @return resourceInfo | |||
*/ | |||
public String getResourceInfoFromResourceName(BizEnum bizEnum, String resourceName) { | |||
if (StringUtils.isEmpty(resourceName) || !resourceName.contains(bizEnum.getBizCode() + SEPARATOR)) { | |||
return null; | |||
} | |||
return resourceName.replace(bizEnum.getBizCode() + SEPARATOR + RESOURCE_NAME + SEPARATOR, SymbolConstant.BLANK); | |||
} | |||
/** | |||
* 从namespace 获取使用者ID | |||
* | |||
* @param namespace | |||
* @return Long | |||
*/ | |||
public Long getUserIdFromNameSpace(String namespace) { | |||
if (StringUtils.isEmpty(namespace) || !namespace.contains(this.k8sNameConfig.getNamespace() + SEPARATOR)) { | |||
return null; | |||
} | |||
return Long.valueOf(namespace.replace(this.k8sNameConfig.getNamespace() + SEPARATOR, "")); | |||
} | |||
/** | |||
* 生成业务模块相对路径 | |||
* | |||
* @param bizNfsEnum 业务NFS路径枚举 | |||
* @return String 例如: /{biz}/{userId}/{YYYYMMDDhhmmssSSS+四位随机数}/ | |||
*/ | |||
public String getNfsPath(BizNfsEnum bizNfsEnum, long userId) { | |||
if (bizNfsEnum == null) { | |||
return null; | |||
} | |||
return optimizationPath(K8S_FILE_SEPARATOR | |||
+ bizNfsEnum.getBizNfsPath() | |||
+ K8S_FILE_SEPARATOR | |||
+ userId | |||
+ K8S_FILE_SEPARATOR | |||
+ DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_FORMAT) + RandomUtil.randomString(RANDOM_LENGTH) | |||
+ K8S_FILE_SEPARATOR); | |||
} | |||
/** | |||
* 去除NFS根路径 | |||
* | |||
* @param nfsPath | |||
* @return String | |||
*/ | |||
public String removeNfsRootPath(String nfsPath) { | |||
if (StringUtils.isBlank(nfsPath) || !nfsPath.startsWith(k8sNameConfig.getNfsRootPath())) { | |||
return nfsPath; | |||
} | |||
return optimizationPath(K8S_FILE_SEPARATOR + nfsPath.replace(k8sNameConfig.getNfsRootPath(), "")); | |||
} | |||
/** | |||
* 路径添加bucket | |||
* | |||
* @param nfsPath | |||
* @return String | |||
*/ | |||
public String appendBucket(String nfsPath) { | |||
return optimizationPath(K8S_FILE_SEPARATOR | |||
+ k8sNameConfig.getFileBucket() | |||
+ K8S_FILE_SEPARATOR | |||
+ nfsPath); | |||
} | |||
/** | |||
* 路径添加时间戳随机数 | |||
* | |||
* @param nfsPath | |||
* @return String | |||
*/ | |||
public String appendTimeStampAndRandomNum(String nfsPath) { | |||
return optimizationPath(nfsPath | |||
+ DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_FORMAT) + RandomUtil.randomString(RANDOM_LENGTH) | |||
+ K8S_FILE_SEPARATOR); | |||
} | |||
/** | |||
* nfs路径根据业务转换 | |||
* | |||
* @param nfsPath | |||
* @param sourceBizNfsEnum 源业务 NFS Path | |||
* @param targetBizNfsEnum 目标业务 NFS Path | |||
* @return String | |||
*/ | |||
public String convertNfsPath(String nfsPath, BizNfsEnum sourceBizNfsEnum, BizNfsEnum targetBizNfsEnum) { | |||
if (!validateBizNfsPath(nfsPath, sourceBizNfsEnum) || targetBizNfsEnum == null) { | |||
return nfsPath; | |||
} | |||
return optimizationPath(nfsPath.replace(K8S_FILE_SEPARATOR + sourceBizNfsEnum.getBizNfsPath() + K8S_FILE_SEPARATOR | |||
, K8S_FILE_SEPARATOR + targetBizNfsEnum.getBizNfsPath() + K8S_FILE_SEPARATOR)); | |||
} | |||
/** | |||
* 获取NFS绝对路径 | |||
* | |||
* @param nfsPath | |||
* @return String | |||
*/ | |||
public String getAbsoluteNfsPath(String nfsPath) { | |||
if (StringUtils.isBlank(nfsPath)) { | |||
return nfsPath; | |||
} | |||
return optimizationPath(k8sNameConfig.getNfsRootPath() | |||
+ K8S_FILE_SEPARATOR | |||
+ k8sNameConfig.getFileBucket() | |||
+ K8S_FILE_SEPARATOR | |||
+ nfsPath); | |||
} | |||
/** | |||
* 验证 nfsPath 是否是所属业务路径 | |||
* | |||
* @param nfsPath | |||
* @param bizNfsEnum | |||
* @return boolean | |||
*/ | |||
public boolean validateBizNfsPath(String nfsPath, BizNfsEnum bizNfsEnum) { | |||
return org.apache.commons.lang3.StringUtils.isNotBlank(nfsPath) | |||
&& bizNfsEnum != null | |||
&& nfsPath.contains(bizNfsEnum.getBizNfsPath()) | |||
&& !nfsPath.contains(K8S_FILE_SEPARATOR + k8sNameConfig.getFileBucket() + K8S_FILE_SEPARATOR) | |||
&& !nfsPath.contains(K8S_FILE_SEPARATOR + k8sNameConfig.getNfsRootPath() + K8S_FILE_SEPARATOR); | |||
} | |||
/** | |||
* 路径优化 | |||
* | |||
* @param path | |||
* @return String | |||
*/ | |||
private String optimizationPath(String path) { | |||
if (StringUtils.isBlank(path)) { | |||
return path; | |||
} | |||
return path.replaceAll("///*", K8S_FILE_SEPARATOR); | |||
} | |||
/** | |||
* 获取k8s pod标签 | |||
* | |||
* @param bizEnum | |||
* @return String | |||
*/ | |||
public String getPodLabel(BizEnum bizEnum) { | |||
return bizEnum == null ? null : bizEnum.getBizCode(); | |||
} | |||
/** | |||
* 获取数据集在镜像中路径 | |||
* | |||
* @return String | |||
*/ | |||
public String getDatasetPath() { | |||
return k8sNameConfig.getDatasetPath(); | |||
} | |||
/** | |||
* 自送生成K8S名称,供K8S使用 | |||
* | |||
* @return String | |||
*/ | |||
public String getK8sName() { | |||
return DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_FORMAT) | |||
+ RandomUtil.randomString(RANDOM_LENGTH); | |||
} | |||
} |
@@ -0,0 +1,39 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import java.text.SimpleDateFormat; | |||
import java.util.Calendar; | |||
/** | |||
* @description Key生成工具类 | |||
* @date 2020-06-08 | |||
*/ | |||
public class KeyUtil { | |||
/** | |||
* 生成训练任务的key,目前规则为:train-{user_id}-{time} | |||
* @param userId 用户id | |||
* @return 训练任务的key | |||
*/ | |||
public static String generateTrainKey(long userId) { | |||
Calendar calendar = Calendar.getInstance(); | |||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); | |||
return "train-" + userId + '-' + dateFormat.format(calendar.getTime()); | |||
} | |||
} |
@@ -0,0 +1,255 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import ch.qos.logback.classic.Level; | |||
import com.alibaba.fastjson.JSON; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.lang3.exception.ExceptionUtils; | |||
import org.dubhe.aspect.LogAspect; | |||
import org.dubhe.base.MagicNumConstant; | |||
import org.dubhe.constant.SymbolConstant; | |||
import org.dubhe.domain.entity.LogInfo; | |||
import org.dubhe.enums.LogEnum; | |||
import org.slf4j.MDC; | |||
import org.slf4j.helpers.MessageFormatter; | |||
import java.util.Arrays; | |||
import java.util.UUID; | |||
/** | |||
* @description 日志工具类 | |||
* @date 2020-06-29 | |||
*/ | |||
@Slf4j | |||
public class LogUtil { | |||
/** | |||
* info级别的日志 | |||
* | |||
* @param logType 日志类型 | |||
* @param object 打印的日志参数 | |||
*/ | |||
public static void info(LogEnum logType, Object... object) { | |||
logHandle(logType, Level.INFO, object); | |||
} | |||
/** | |||
* debug级别的日志 | |||
* | |||
* @param logType 日志类型 | |||
* @param object 打印的日志参数 | |||
*/ | |||
public static void debug(LogEnum logType, Object... object) { | |||
logHandle(logType, Level.DEBUG, object); | |||
} | |||
/** | |||
* error级别的日志 | |||
* | |||
* @param logType 日志类型 | |||
* @param object 打印的日志参数 | |||
*/ | |||
public static void error(LogEnum logType, Object... object) { | |||
errorObjectHandle(object); | |||
logHandle(logType, Level.ERROR, object); | |||
} | |||
/** | |||
* warn级别的日志 | |||
* | |||
* @param logType 日志类型 | |||
* @param object 打印的日志参数 | |||
*/ | |||
public static void warn(LogEnum logType, Object... object) { | |||
logHandle(logType, Level.WARN, object); | |||
} | |||
/** | |||
* trace级别的日志 | |||
* | |||
* @param logType 日志类型 | |||
* @param object 打印的日志参数 | |||
*/ | |||
public static void trace(LogEnum logType, Object... object) { | |||
logHandle(logType, Level.TRACE, object); | |||
} | |||
/** | |||
* 日志处理 | |||
* | |||
* @param logType 日志类型 | |||
* @param level 日志级别 | |||
* @param object 打印的日志参数 | |||
*/ | |||
private static void logHandle(LogEnum logType, Level level, Object[] object) { | |||
LogInfo logInfo = generateLogInfo(logType, level, object); | |||
String logInfoJsonStr = logJsonStringLengthLimit(logInfo); | |||
switch (Level.toLevel(logInfo.getLevel()).levelInt) { | |||
case Level.TRACE_INT: | |||
log.trace(logInfoJsonStr); | |||
break; | |||
case Level.DEBUG_INT: | |||
log.debug(logInfoJsonStr); | |||
break; | |||
case Level.INFO_INT: | |||
log.info(logInfoJsonStr); | |||
break; | |||
case Level.WARN_INT: | |||
log.warn(logInfoJsonStr); | |||
break; | |||
case Level.ERROR_INT: | |||
log.error(logInfoJsonStr); | |||
break; | |||
default: | |||
} | |||
} | |||
/** | |||
* 日志信息组装的内部方法 | |||
* | |||
* @param logType 日志类型 | |||
* @param level 日志级别 | |||
* @param object 打印的日志参数 | |||
* @return LogInfo日志对象信息 | |||
*/ | |||
private static LogInfo generateLogInfo(LogEnum logType, Level level, Object[] object) { | |||
LogInfo logInfo = new LogInfo(); | |||
// 日志类型检测 | |||
if (!LogEnum.isLogType(logType)) { | |||
level = Level.ERROR; | |||
object = new Object[MagicNumConstant.ONE]; | |||
object[MagicNumConstant.ZERO] = String.valueOf("logType【").concat(String.valueOf(logType)) | |||
.concat("】is error !"); | |||
logType = LogEnum.SYS_ERR; | |||
} | |||
// 获取trace_id | |||
if (StringUtils.isEmpty(MDC.get(LogAspect.TRACE_ID))) { | |||
MDC.put(LogAspect.TRACE_ID, UUID.randomUUID().toString()); | |||
} | |||
// 设置logInfo的level,type,traceId属性 | |||
logInfo.setLevel(level.levelStr).setType(logType.toString()).setTraceId(MDC.get(LogAspect.TRACE_ID)); | |||
// 设置logInfo的堆栈信息 | |||
setLogStackInfo(logInfo); | |||
// 设置logInfo的info信息 | |||
setLogInfo(logInfo, object); | |||
// 截取loginfo的长度并转换成json字符串 | |||
return logInfo; | |||
} | |||
/** | |||
* 设置loginfo的堆栈信息 | |||
* | |||
* @param logInfo 日志对象 | |||
*/ | |||
private static void setLogStackInfo(LogInfo logInfo) { | |||
StackTraceElement[] elements = Thread.currentThread().getStackTrace(); | |||
if (elements.length >= MagicNumConstant.SIX) { | |||
logInfo.setCName(elements[MagicNumConstant.FIVE].getClassName()) | |||
.setMName(elements[MagicNumConstant.FIVE].getMethodName()) | |||
.setLine(String.valueOf(elements[MagicNumConstant.FIVE].getLineNumber())); | |||
} | |||
} | |||
/** | |||
* 限制log日志的长度并转换成json | |||
* | |||
* @param logInfo 日志对象 | |||
* @return String 日志对象Json字符串 | |||
*/ | |||
private static String logJsonStringLengthLimit(LogInfo logInfo) { | |||
try { | |||
String jsonString = JSON.toJSONString(logInfo.getInfo()); | |||
if (jsonString.length() > MagicNumConstant.TEN_THOUSAND) { | |||
jsonString = jsonString.substring(MagicNumConstant.ZERO, MagicNumConstant.TEN_THOUSAND); | |||
} | |||
logInfo.setInfo(jsonString); | |||
jsonString = JSON.toJSONString(logInfo); | |||
jsonString = jsonString.replace(SymbolConstant.BACKSLASH_MARK, SymbolConstant.MARK) | |||
.replace(SymbolConstant.DOUBLE_MARK, SymbolConstant.MARK) | |||
.replace(SymbolConstant.BRACKETS, SymbolConstant.BLANK); | |||
return jsonString; | |||
} catch (Exception e) { | |||
logInfo.setLevel(Level.ERROR.levelStr).setType(LogEnum.SYS_ERR.toString()) | |||
.setInfo("cannot serialize exception: " + ExceptionUtils.getStackTrace(e)); | |||
return JSON.toJSONString(logInfo); | |||
} | |||
} | |||
/** | |||
* 设置日志对象的info信息 | |||
* | |||
* @param logInfo 日志对象 | |||
* @param object 打印的日志参数 | |||
*/ | |||
private static void setLogInfo(LogInfo logInfo, Object[] object) { | |||
for (Object obj : object) { | |||
if (obj instanceof Exception) { | |||
log.error((ExceptionUtils.getStackTrace((Throwable) obj))); | |||
} | |||
} | |||
if (object.length > MagicNumConstant.ONE) { | |||
logInfo.setInfo(MessageFormatter.arrayFormat(object[MagicNumConstant.ZERO].toString(), | |||
Arrays.copyOfRange(object, MagicNumConstant.ONE, object.length)).getMessage()); | |||
} else if (object.length == MagicNumConstant.ONE && object[MagicNumConstant.ZERO] instanceof Exception) { | |||
logInfo.setInfo((ExceptionUtils.getStackTrace((Exception) object[MagicNumConstant.ZERO]))); | |||
} else if (object.length == MagicNumConstant.ONE) { | |||
logInfo.setInfo( | |||
object[MagicNumConstant.ZERO] == null ? SymbolConstant.BLANK : object[MagicNumConstant.ZERO]); | |||
} else { | |||
logInfo.setInfo(SymbolConstant.BLANK); | |||
} | |||
} | |||
/** | |||
* 处理Exception的情况 | |||
* | |||
* @param object 打印的日志参数 | |||
*/ | |||
private static void errorObjectHandle(Object[] object) { | |||
if (object.length >= MagicNumConstant.TWO) { | |||
object[MagicNumConstant.ZERO] = String.valueOf(object[MagicNumConstant.ZERO]) | |||
.concat(SymbolConstant.BRACKETS); | |||
} | |||
if (object.length == MagicNumConstant.TWO && object[MagicNumConstant.ONE] instanceof Exception) { | |||
log.error((ExceptionUtils.getStackTrace((Throwable) object[MagicNumConstant.ONE]))); | |||
object[MagicNumConstant.ONE] = ExceptionUtils.getStackTrace((Exception) object[MagicNumConstant.ONE]); | |||
} else if (object.length >= MagicNumConstant.THREE) { | |||
for (int i = 0; i < object.length; i++) { | |||
if (object[i] instanceof Exception) { | |||
log.error((ExceptionUtils.getStackTrace((Throwable) object[i]))); | |||
object[i] = ExceptionUtils.getStackTrace((Exception) object[i]); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import org.dubhe.base.MagicNumConstant; | |||
/** | |||
* @description: 计算工具类 | |||
* @create: 2020/6/4 14:53 | |||
*/ | |||
public class MathUtils { | |||
/** | |||
* 字符串整数加法 | |||
* num1+num2 | |||
* @param num1 | |||
* @param num2 | |||
* @return | |||
*/ | |||
public static String add(String num1,String num2){ | |||
return String.valueOf((!RegexUtil.isDigits(num1) ? MagicNumConstant.ZERO:Integer.valueOf(num1)) + (!RegexUtil.isDigits(num2)?MagicNumConstant.ZERO:Integer.valueOf(num2))); | |||
} | |||
/** | |||
* 字符串整数减法 | |||
* num1 - num2 | |||
* @param num1 | |||
* @param num2 | |||
* @return | |||
*/ | |||
public static String reduce(String num1,String num2){ | |||
return String.valueOf((!RegexUtil.isDigits(num1) ? MagicNumConstant.ZERO:Integer.valueOf(num1)) - (!RegexUtil.isDigits(num2)?MagicNumConstant.ZERO:Integer.valueOf(num2))); | |||
} | |||
} |
@@ -0,0 +1,286 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import cn.hutool.core.io.IoUtil; | |||
import cn.hutool.http.HttpRequest; | |||
import com.alibaba.fastjson.JSONObject; | |||
import io.minio.MinioClient; | |||
import io.minio.PutObjectOptions; | |||
import io.minio.Result; | |||
import io.minio.errors.*; | |||
import io.minio.messages.DeleteError; | |||
import io.minio.messages.Item; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.dubhe.base.MagicNumConstant; | |||
import org.dubhe.enums.LogEnum; | |||
import org.dubhe.exception.BusinessException; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.stereotype.Service; | |||
import javax.annotation.PostConstruct; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.nio.charset.Charset; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.HashSet; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
/** | |||
* @description Minio工具类 | |||
* @date 2020-05-09 | |||
*/ | |||
@Service | |||
public class MinioUtil { | |||
@Value("${minio.url}") | |||
private String url; | |||
@Value("${minio.accessKey}") | |||
private String accessKey; | |||
@Value("${minio.secretKey}") | |||
private String secretKey; | |||
private MinioClient client; | |||
@PostConstruct | |||
public void init() { | |||
try { | |||
client = new MinioClient(url, accessKey, secretKey); | |||
} catch (InvalidEndpointException e) { | |||
LogUtil.warn(LogEnum.BIZ_DATASET, "MinIO endpoint invalid. e:", e); | |||
} catch (InvalidPortException e) { | |||
LogUtil.warn(LogEnum.BIZ_DATASET, "MinIO endpoint port invalid. e:", e); | |||
} | |||
} | |||
/** | |||
* 写文件 | |||
* | |||
* @param bucket 桶名称 | |||
* @param fullFilePath 文件存储的全路径,包括文件名,非'/'开头. e.g. dataset/12/annotation/test.txt | |||
* @param content file content. can not be null | |||
*/ | |||
public void writeString(String bucket, String fullFilePath, String content) throws Exception { | |||
boolean isExist = client.bucketExists(bucket); | |||
if (!isExist) { | |||
client.makeBucket(bucket); | |||
} | |||
InputStream inputStream = IoUtil.toUtf8Stream(content); | |||
PutObjectOptions options = new PutObjectOptions(inputStream.available(), MagicNumConstant.NEGATIVE_ONE); | |||
client.putObject(bucket, fullFilePath, inputStream, options); | |||
} | |||
/** | |||
* 读取文件 | |||
* | |||
* @param bucket | |||
* @param fullFilePath 文件存储的全路径,包括文件名,非'/'开头. e.g. dataset/12/annotation/test.txt | |||
* @return String | |||
*/ | |||
public String readString(String bucket, String fullFilePath) throws Exception { | |||
try (InputStream is = client.getObject(bucket, fullFilePath)) { | |||
return IoUtil.read(is, Charset.defaultCharset()); | |||
} | |||
} | |||
/** | |||
* 文件删除 | |||
* | |||
* @param bucket | |||
* @param fullFilePath 文件存储的全路径,包括文件名,非'/'开头. e.g. dataset/12/annotation/test.txt | |||
*/ | |||
public void del(String bucket, String fullFilePath) throws Exception { | |||
Iterable<Result<Item>> items = client.listObjects(bucket, fullFilePath); | |||
Set<String> files = new HashSet<>(); | |||
for (Result<Item> item : items) { | |||
files.add(item.get().objectName()); | |||
} | |||
Iterable<Result<DeleteError>> results = client.removeObjects(bucket, files); | |||
for (Result<DeleteError> result : results) { | |||
result.get(); | |||
} | |||
} | |||
/** | |||
* 批量删除文件 | |||
* | |||
* @param bucket | |||
* @param objectNames | |||
*/ | |||
public void delFiles(String bucket,List<String> objectNames) throws Exception{ | |||
Iterable<Result<DeleteError>> results = client.removeObjects(bucket, objectNames); | |||
for (Result<DeleteError> result : results) { | |||
result.get(); | |||
} | |||
} | |||
/** | |||
* 获取对象名称 | |||
* | |||
*/ | |||
public List<String> getObjects(String bucketName, String prefix)throws Exception{ | |||
List<String> fileNames = new ArrayList<>(); | |||
Iterable<Result<Item>> results = client.listObjects(bucketName, prefix); | |||
for(Result<Item> result:results){ | |||
Item item = result.get(); | |||
fileNames.add(item.objectName()); | |||
} | |||
return fileNames; | |||
} | |||
/** | |||
* 获取文件流 | |||
* | |||
*/ | |||
public InputStream getObjectInputStream(String bucket,String objectName)throws Exception{ | |||
return client.getObject(bucket, objectName); | |||
} | |||
/** | |||
* 文件夹复制 | |||
* | |||
* @param bucket | |||
* @param sourceFiles 源文件 | |||
* @param targetDir 目标文件夹 | |||
*/ | |||
public void copyDir(String bucket, List<String> sourceFiles, String targetDir) { | |||
sourceFiles.forEach(sourceFile -> { | |||
InputStream inputStream = null; | |||
try { | |||
String sourceObjectName = sourceFile; | |||
String targetObjectName = targetDir + "/" + StringUtils.substringAfterLast(sourceObjectName, "/"); | |||
inputStream = client.getObject(bucket, sourceObjectName); | |||
byte[] buf = new byte[512]; | |||
int bytesRead; | |||
int count = MagicNumConstant.ZERO; | |||
while ((bytesRead = inputStream.read(buf, MagicNumConstant.ZERO, buf.length)) >= MagicNumConstant.ZERO) { | |||
count += bytesRead; | |||
} | |||
PutObjectOptions options = new PutObjectOptions(count, MagicNumConstant.ZERO); | |||
client.putObject(bucket, targetObjectName, client.getObject(bucket, sourceObjectName), options); | |||
} catch (Exception e) { | |||
LogUtil.error(LogEnum.BIZ_DATASET, "MinIO file copy exception, {}", e); | |||
} finally { | |||
try { | |||
if (inputStream != null) { | |||
inputStream.close(); | |||
} | |||
} catch (IOException e) { | |||
LogUtil.error(LogEnum.BIZ_DATASET, "MinIO file read stream closed failed, {}", e); | |||
} | |||
} | |||
}); | |||
} | |||
@Data | |||
@Service | |||
public class MinioWebTokenBody { | |||
@Value("${minioweb.GetToken.url}") | |||
private String tokenUrl; | |||
@Value("${minioweb.GetToken.param.id}") | |||
private int id; | |||
@Value("${minioweb.GetToken.param.jsonrpc}") | |||
private String jsonrpc; | |||
@Value("${minioweb.GetToken.param.method}") | |||
private String method; | |||
@Value("${minioweb.zip.url}") | |||
private String zipUrl; | |||
/** | |||
* 生成文件下载请求参数方法 | |||
* | |||
* @param bucketName | |||
* @param prefix | |||
* @param objects | |||
* @return MinioDownloadDto | |||
*/ | |||
public MinioDownloadDto getDownloadParam(String bucketName, String prefix, List<String> objects, String zipName) { | |||
String paramTemplate = "{\"id\":%d,\"jsonrpc\":\"%s\",\"params\":{\"username\":\"%s\",\"password\":\"%s\"},\"method\":\"%s\"}"; | |||
String downloadBodyTemplate = "{\"bucketName\":\"%s\",\"prefix\":\"%s\",\"objects\":[%s]}"; | |||
String param = String.format(paramTemplate, id, jsonrpc, accessKey, secretKey, method); | |||
String result = HttpRequest.post(url + tokenUrl).contentType("application/json").body(param).execute().body(); | |||
String token = JSONObject.parseObject(result).getJSONObject("result").getString("token"); | |||
return new MinioDownloadDto(token, String.format(downloadBodyTemplate, bucketName, prefix, getStrFromList(objects)), zipName); | |||
} | |||
public String getStrFromList(List<String> objects) { | |||
List<String> result = new ArrayList<>(); | |||
objects.stream().forEach(s -> { | |||
result.add("\"" + s + "\""); | |||
}); | |||
return StringUtils.join(result, ","); | |||
} | |||
} | |||
@ApiModel | |||
@Data | |||
public class MinioDownloadDto { | |||
@ApiModelProperty("下载压缩包请求token") | |||
private String token; | |||
@ApiModelProperty("下载压缩包请求参数") | |||
private String body; | |||
@ApiModelProperty("下载压缩包请求需要的header") | |||
private Map<String, Object> headers; | |||
@ApiModelProperty("下载压缩包文件名称") | |||
private String zipName; | |||
public MinioDownloadDto() { | |||
} | |||
public MinioDownloadDto(String token, String body, String zipName) { | |||
this.token = token; | |||
this.body = body; | |||
this.zipName = zipName; | |||
Map<String, Object> headers = new HashMap<>(); | |||
headers.put("Content-Type", "text/plain;charset=UTF-8"); | |||
this.headers = headers; | |||
} | |||
} | |||
/** | |||
* 生成一个给HTTP PUT请求用的presigned URL。浏览器/移动端的客户端可以用这个URL进行上传, | |||
* 即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天 | |||
* | |||
* @param bucketName 存储桶名称 | |||
* @param objectName 存储桶里的对象名称 | |||
* @param expires 失效时间(以秒为单位),默认是7天,不得大于七天 | |||
* @return String | |||
*/ | |||
public String getEncryptedPutUrl(String bucketName, String objectName, Integer expires) { | |||
if (StringUtils.isEmpty(objectName)) { | |||
throw new BusinessException("object name cannot be empty"); | |||
} | |||
try { | |||
return client.presignedPutObject(bucketName, objectName, expires); | |||
} catch (Exception e) { | |||
LogUtil.error(LogEnum.BIZ_DATASET, e.getMessage()); | |||
throw new BusinessException("MinIO an error occurred, please contact the administrator"); | |||
} | |||
} | |||
} |
@@ -0,0 +1,76 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import com.emc.ecs.nfsclient.nfs.nfs3.Nfs3; | |||
import com.emc.ecs.nfsclient.rpc.CredentialUnix; | |||
import org.apache.commons.pool2.PooledObject; | |||
import org.apache.commons.pool2.PooledObjectFactory; | |||
import org.apache.commons.pool2.impl.DefaultPooledObject; | |||
import org.dubhe.config.NfsConfig; | |||
import org.dubhe.enums.LogEnum; | |||
import org.springframework.stereotype.Component; | |||
import java.io.IOException; | |||
/** | |||
* @description NFS工厂类 | |||
* @date 2020-05-13 | |||
*/ | |||
@Component | |||
public class NfsFactory implements PooledObjectFactory<Nfs3> { | |||
private final NfsConfig nfsConfig; | |||
public NfsFactory(NfsConfig nfsConfig) { | |||
this.nfsConfig = nfsConfig; | |||
} | |||
@Override | |||
public PooledObject<Nfs3> makeObject() { | |||
Nfs3 nfs3 = null; | |||
try { | |||
nfs3 = new Nfs3(nfsConfig.getNfsIp(), nfsConfig.getRootDir(), new CredentialUnix(0, 0, null), 3); | |||
} catch (IOException e) { | |||
LogUtil.error(LogEnum.NFS_UTIL, "创建NFS对象失败: ", e); | |||
} | |||
return new DefaultPooledObject<>(nfs3); | |||
} | |||
@Override | |||
public void destroyObject(PooledObject<Nfs3> pooledObject) { | |||
LogUtil.info(LogEnum.NFS_UTIL, "销毁NFS对象: ", pooledObject.getObject()); | |||
} | |||
@Override | |||
public boolean validateObject(PooledObject<Nfs3> pooledObject) { | |||
LogUtil.info(LogEnum.NFS_UTIL, "验证NFS对象: ", pooledObject.getObject()); | |||
return true; | |||
} | |||
@Override | |||
public void activateObject(PooledObject<Nfs3> pooledObject) { | |||
LogUtil.info(LogEnum.NFS_UTIL, "激活NFS对象: ", pooledObject.getObject()); | |||
} | |||
@Override | |||
public void passivateObject(PooledObject<Nfs3> pooledObject) { | |||
LogUtil.info(LogEnum.NFS_UTIL, "钝化NFS对象: ", pooledObject.getObject()); | |||
} | |||
} |
@@ -0,0 +1,114 @@ | |||
/** | |||
* Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
* ============================================================= | |||
*/ | |||
package org.dubhe.utils; | |||
import com.emc.ecs.nfsclient.nfs.nfs3.Nfs3; | |||
import org.apache.commons.pool2.impl.GenericObjectPool; | |||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig; | |||
import org.dubhe.enums.LogEnum; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* @description NFS3 连接池 | |||
* @date 2020-05-18 | |||
*/ | |||
@Component | |||
public class NfsPool { | |||
/** | |||
* NFS工厂对象 | |||
*/ | |||
private NfsFactory nfsFactory; | |||
/** | |||
* GenericObjectPool对象 | |||
*/ | |||
private final GenericObjectPool<Nfs3> genericObjectPool; | |||
/** | |||
* 最大总共连接数 | |||
*/ | |||
public static final int MAX_TOTAL = 300; | |||
/** | |||
* 最小连接数 | |||
*/ | |||
public static final int MIN = 20; | |||
/** | |||
* 最大连接数 | |||
*/ | |||
public static final int MAX = 300; | |||
/** | |||
* 最大等待时间 单位毫秒 | |||
*/ | |||
public static final int MAX_WAIT_TIME = 3000; | |||
/** | |||
* 初始化连接池 | |||
* | |||
* @param nfsFactory | |||
*/ | |||
public NfsPool(NfsFactory nfsFactory) { | |||
this.nfsFactory = nfsFactory; | |||
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); | |||
poolConfig.setMaxTotal(MAX_TOTAL); | |||
poolConfig.setMinIdle(MIN); | |||
poolConfig.setMaxIdle(MAX); | |||
poolConfig.setMaxWaitMillis(MAX_WAIT_TIME); | |||
this.genericObjectPool = new GenericObjectPool<>(nfsFactory, poolConfig); | |||
} | |||
/** | |||
* 从连接池中取连接 | |||
* | |||
* @return nfs3 | |||
*/ | |||
public Nfs3 getNfs() { | |||
try { | |||
LogUtil.info(LogEnum.NFS_UTIL,"NFS线程 活跃数量:{} ,空闲数量: {} , 等待队列数量 : {}",genericObjectPool.getNumActive(),genericObjectPool.getNumIdle(),genericObjectPool.getNumWaiters()); | |||
return genericObjectPool.borrowObject(); | |||
} catch (Exception e) { | |||
LogUtil.error(LogEnum.NFS_UTIL, "获取NFS连接失败: {} ", e); | |||
return null; | |||
} | |||
} | |||
/** | |||
* 释放连接到连接池 | |||
* | |||
* @param nfs3 | |||
*/ | |||
public void revertNfs(Nfs3 nfs3) { | |||
try { | |||
if(nfs3 != null){ | |||
LogUtil.info(LogEnum.NFS_UTIL,"成功释放对象 : {} ", nfs3); | |||
genericObjectPool.returnObject(nfs3); | |||
} | |||
} catch (Exception e) { | |||
LogUtil.error(LogEnum.NFS_UTIL, " 释放NFS连接失败: ", e); | |||
} | |||
} | |||
/** | |||
* 销毁公共池 | |||
*/ | |||
public void destroyPool() { | |||
try { | |||
genericObjectPool.close(); | |||
} catch (Exception e) { | |||
LogUtil.error(LogEnum.NFS_UTIL, "销毁NFS连接失败: ", e); | |||
} | |||
} | |||
} |