Compare commits
74 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
30cb471629 | ||
![]() |
d70c22dde8 | ||
![]() |
01bb6b7c01 | ||
![]() |
4f4879759e | ||
![]() |
92a410fcea | ||
![]() |
5d1fced8e9 | ||
![]() |
a56e5a8abe | ||
![]() |
28ae7f3a0c | ||
![]() |
8d675c81c5 | ||
![]() |
66a345364f | ||
![]() |
a3cb8be08f | ||
![]() |
0861b30a7b | ||
![]() |
36f2a3eb4b | ||
![]() |
092cbbf8da | ||
![]() |
39e3e8f214 | ||
![]() |
fa983bdcc9 | ||
![]() |
67bb30c10c | ||
![]() |
e85340ca5d | ||
![]() |
a3a1e17849 | ||
![]() |
2601135225 | ||
![]() |
c556affc91 | ||
![]() |
6ee9789a2f | ||
![]() |
68a457ae89 | ||
![]() |
72237596f3 | ||
![]() |
f516333682 | ||
![]() |
873af25684 | ||
![]() |
8b058a873e | ||
![]() |
0c5a5a6454 | ||
![]() |
2096049708 | ||
![]() |
1095aa2b65 | ||
![]() |
13679ff301 | ||
![]() |
89b7a06662 | ||
![]() |
e8582bea75 | ||
![]() |
9af7926eb9 | ||
![]() |
bdcdf7e181 | ||
![]() |
887db0aff7 | ||
![]() |
4a974b7e0a | ||
![]() |
fb286d2def | ||
![]() |
89cb9e6693 | ||
![]() |
927def4472 | ||
![]() |
84fcd31704 | ||
![]() |
005e5cc01f | ||
![]() |
2896409b3a | ||
![]() |
791641f3e1 | ||
![]() |
79f266bbda | ||
![]() |
c9edaf0d1d | ||
![]() |
ac5f73c687 | ||
![]() |
cc0667429a | ||
![]() |
92a5d6faeb | ||
![]() |
1111b6b494 | ||
![]() |
be5a7c99e1 | ||
![]() |
d6a963c087 | ||
![]() |
af753bdffe | ||
![]() |
59b025353f | ||
![]() |
355a6b0205 | ||
![]() |
7de80e9d5a | ||
![]() |
4c6d8cd20c | ||
![]() |
31da89d63a | ||
![]() |
e044ca7d12 | ||
![]() |
7c037b68cd | ||
![]() |
9080824a59 | ||
![]() |
11f4bc2c89 | ||
![]() |
a64ddd1eb8 | ||
![]() |
2fdaecfafe | ||
![]() |
6d1fe20736 | ||
![]() |
f61bc047cd | ||
![]() |
4f52580938 | ||
![]() |
281d0cf880 | ||
![]() |
fdf9215d43 | ||
![]() |
8c182e907d | ||
![]() |
e55af04568 | ||
![]() |
2462ffdbab | ||
![]() |
bfeb57e24f | ||
![]() |
9bb28cda27 |
2
.github/ISSUE_TEMPLATE/bug.yml
vendored
2
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -25,7 +25,7 @@ body:
|
||||
required: true
|
||||
attributes:
|
||||
label: "1Panel 版本"
|
||||
description: "可通过系统右上角下拉菜单中的`关于`选项,或查看安装目录中的 version 文件获取。"
|
||||
description: "登录 1Panel Web 控制台,在页面右下角查看当前版本。"
|
||||
- type: markdown
|
||||
id: details
|
||||
attributes:
|
||||
|
2
.github/ISSUE_TEMPLATE/feature.yml
vendored
2
.github/ISSUE_TEMPLATE/feature.yml
vendored
@@ -14,7 +14,7 @@ body:
|
||||
required: true
|
||||
attributes:
|
||||
label: "1Panel 版本"
|
||||
description: "可通过系统右上角下拉菜单中的`关于`选项,或查看安装目录中的 version 文件获取。"
|
||||
description: "登录 1Panel Web 控制台,在页面右下角查看当前版本。"
|
||||
- type: markdown
|
||||
id: details
|
||||
attributes:
|
||||
|
17
.github/workflows/add-labels-for-pr.yml
vendored
Normal file
17
.github/workflows/add-labels-for-pr.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
on: pull_request
|
||||
|
||||
name: 1Panel 通用 PR 处理
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
generic_handler:
|
||||
name: 为 PR 添加标签
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-ecosystem/action-add-labels@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUBTOKEN }}
|
||||
labels: ${{ github.base_ref }}
|
17
.github/workflows/issue-recent-alert.yml
vendored
Normal file
17
.github/workflows/issue-recent-alert.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 1 * * *"
|
||||
|
||||
name: Check recent handle issues
|
||||
|
||||
jobs:
|
||||
check-recent-issues-not-handle:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check recent issues and send msg
|
||||
uses: jumpserver/action-issues-alert@master
|
||||
with:
|
||||
hook: ${{ secrets.WECHAT_GROUP_WEB_HOOK }}
|
||||
type: recent
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
17
.github/workflows/issue-untimely-alert.yml
vendored
Normal file
17
.github/workflows/issue-untimely-alert.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 9 * * 1-5"
|
||||
|
||||
name: Check untimely handle issues
|
||||
|
||||
jobs:
|
||||
check-untimely-handle-issues:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check untimely issues and send msg
|
||||
uses: jumpserver/action-issues-alert@master
|
||||
with:
|
||||
hook: ${{ secrets.WECHAT_GROUP_WEB_HOOK }}
|
||||
type: untimely
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
16
.github/workflows/sync2gitee.yml
vendored
Normal file
16
.github/workflows/sync2gitee.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
name: sync2gitee
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
repo-sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Mirror the Github organization repos to Gitee.
|
||||
uses: Yikun/hub-mirror-action@master
|
||||
with:
|
||||
src: 'github/1Panel-dev'
|
||||
dst: 'gitee/fit2cloud-xlab'
|
||||
dst_key: ${{ secrets.GITEE_PRIVATE_KEY }}
|
||||
dst_token: ${{ secrets.GITEE_TOKEN }}
|
||||
static_list: "1Panel"
|
||||
force_update: true
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -22,5 +22,4 @@ cmd/server/__debug_bin
|
||||
cmd/server/web/assets
|
||||
cmd/server/web/monacoeditorwork
|
||||
cmd/server/web/index.html
|
||||
cmd/server/web/favicon.png
|
||||
frontend/auto-imports.d.ts
|
||||
|
11
OWNERS
Normal file
11
OWNERS
Normal file
@@ -0,0 +1,11 @@
|
||||
reviewers:
|
||||
- zhengkunwang223
|
||||
- ssongliu
|
||||
- wanghe-fit2cloud
|
||||
- wangdan-fit2cloud
|
||||
|
||||
approvers:
|
||||
- zhengkunwang223
|
||||
- ssongliu
|
||||
- wanghe-fit2cloud
|
||||
- wangdan-fit2cloud
|
23
README.md
23
README.md
@@ -1,3 +1,4 @@
|
||||
[README_EN.md](README_EN.md)
|
||||
<p align="center"><a href="https://1panel.cn"><img src="http://1panel.oss-cn-hangzhou.aliyuncs.com/img/1panel-logo.png" alt="1Panel" width="300" /></a></p>
|
||||
<p align="center"><b>现代化、开源的 Linux 服务器运维管理面板</b></p>
|
||||
<p align="center">
|
||||
@@ -11,14 +12,14 @@
|
||||
|
||||
1Panel 是一个现代化、开源的 Linux 服务器运维管理面板。1Panel 的功能和优势包括:
|
||||
|
||||
- **快速建站**:深度集成 Wordpress 和 Halo,域名绑定、SSL 证书配置等一键搞定;
|
||||
- **高效管理**:通过 Web 端轻松管理 Linux 服务器,包括主机监控、文件管理、数据库管理、容器管理及常用应用软件管理;
|
||||
- **快速建站**:深度集成 Wordpress 和 [Halo](https://github.com/halo-dev/halo/),域名绑定、SSL 证书配置等一键搞定;
|
||||
- **高效管理**:通过 Web 端轻松管理 Linux 服务器,包括应用管理、主机监控、文件管理、数据库管理、容器管理等;
|
||||
- **安全可靠**:最小漏洞暴露面,提供防火墙和安全审计等功能;
|
||||
- **一键备份**:支持一键备份和恢复,备份数据云端存储,永不丢失。
|
||||
|
||||
## UI 展示
|
||||
|
||||

|
||||

|
||||
|
||||
## 快速开始
|
||||
|
||||
@@ -30,16 +31,16 @@
|
||||
|
||||
**一键安装**
|
||||
|
||||
以 root 用户执行如下命令一键安装 1Panel:
|
||||
执行如下命令一键安装 1Panel:
|
||||
|
||||
```sh
|
||||
curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && sh quick_start.sh
|
||||
curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && sudo bash quick_start.sh
|
||||
```
|
||||
|
||||
**学习资料**
|
||||
|
||||
- [在线文档](https://1panel.cn/docs/)
|
||||
- [入门视频](https://1panel.cn/video.html)
|
||||
- [教学视频](https://space.bilibili.com/510493147/channel/collectiondetail?sid=1199760)
|
||||
|
||||
## 社区
|
||||
|
||||
@@ -47,18 +48,22 @@ curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_
|
||||
|
||||
**微信交流群**
|
||||
|
||||
<img src="http://1panel.oss-cn-hangzhou.aliyuncs.com/img/wechat-group.jpg" width="156" height="156"/>
|
||||
<img src="https://1panel.cn/img/wechat-group.jpg" width="156" height="156"/>
|
||||
|
||||
## 安全说明
|
||||
|
||||
如果您在使用过程中发现任何安全问题,请通过以下方式直接联系我们:
|
||||
|
||||
- 邮箱:support@fit2cloud.com
|
||||
- 邮箱:support@fit2cloud.com
|
||||
- 电话:400-052-0755
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#1Panel-dev/1Panel&Date)
|
||||
|
||||
## License
|
||||
|
||||
Copyright (c) 2014-2023 飞致云 FIT2CLOUD, All rights reserved.
|
||||
Copyright (c) 2014-2023 [FIT2CLOUD 飞致云](https://fit2cloud.com/), All rights reserved.
|
||||
|
||||
Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
|
||||
|
||||
|
72
README_EN.md
Normal file
72
README_EN.md
Normal file
@@ -0,0 +1,72 @@
|
||||
[中文 README.md](README.md)
|
||||
<p align="center"><a href="https://1panel.cn"><img src="http://1panel.oss-cn-hangzhou.aliyuncs.com/img/1panel-logo.png" alt="1Panel" width="300" /></a></p>
|
||||
<p align="center"><b>Modern and Open-Source Linux Server Operation and Management Panel</b></p>
|
||||
<p align="center">
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0.html"><img src="https://shields.io/github/license/1Panel-dev/1Panel" alt="License: GPL v3"></a>
|
||||
<a href="https://app.codacy.com/gh/1Panel-dev/1Panel?utm_source=github.com&utm_medium=referral&utm_content=1Panel-dev/1Panel&utm_campaign=Badge_Grade_Dashboard"><img src="https://app.codacy.com/project/badge/Grade/da67574fd82b473992781d1386b937ef" alt="Codacy"></a>
|
||||
<a href="https://github.com/1Panel-dev/1Panel/releases"><img src="https://img.shields.io/github/v/release/1Panel-dev/1Panel" alt="GitHub release"></a>
|
||||
<a href="https://github.com/1Panel-dev/1Panel"><img src="https://img.shields.io/github/stars/1Panel-dev/1Panel?color=%231890FF&style=flat-square" alt="Stars"></a>
|
||||
</p>
|
||||
|
||||
------------------------------
|
||||
|
||||
1Panel is a modern and Open-Source linux server operation and management panel, the functions and advantages of 1Panel include:
|
||||
|
||||
- **Quick website building**: Deeply integrated with Wordpress and [Halo](https://github.com/halo-dev/halo/), with one-click solutions for domain name binding, SSL certificate configuration, and more;
|
||||
- **Efficient management**: Easily manage Linux servers through the web interface, including application management, host monitoring, file management, database management, container management, and more;
|
||||
- **Secure and reliable**: Minimal vulnerability exposure, with firewall and security audit functions provided;
|
||||
- **One-click backup**: Support for one-click backup and restore, with backup data stored in the cloud and never lost.
|
||||
|
||||
## UI Display
|
||||
|
||||

|
||||
|
||||
## Quick Start
|
||||
|
||||
**Online Demo**
|
||||
|
||||
- Address: <https://demo.1panel.cn/>
|
||||
- Username: demo
|
||||
- Password: 1panel
|
||||
|
||||
**One-Click Installation**
|
||||
|
||||
Execute the following command to install 1Panel with one click:
|
||||
|
||||
```sh
|
||||
curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && sudo bash quick_start.sh
|
||||
```
|
||||
|
||||
**Learning Materials**
|
||||
|
||||
- [Online Documentation](https://1panel.cn/docs/)
|
||||
- [Teaching Videos](https://space.bilibili.com/510493147/channel/collectiondetail?sid=1199760)
|
||||
|
||||
## Community
|
||||
|
||||
If you have any questions or suggestions, please submit a GitHub Issue or join our WeChat group for communication.
|
||||
|
||||
**WeChat Group**
|
||||
|
||||
<img src="https://1panel.cn/img/wechat-group.jpg" width="156" height="156"/>
|
||||
|
||||
## Security Information
|
||||
|
||||
If you discover any security issues, please contact us through:
|
||||
|
||||
- Email: support@fit2cloud.com
|
||||
- Phone: 400-052-0755
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#1Panel-dev/1Panel&Date)
|
||||
|
||||
## License
|
||||
|
||||
Copyright (c) 2014-2023 [FIT2CLOUD 飞致云](https://fit2cloud.com/), All rights reserved.
|
||||
|
||||
Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
|
||||
|
||||
<https://www.gnu.org/licenses/gpl-3.0.html>
|
||||
|
||||
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.
|
19
SECURITY.md
Normal file
19
SECURITY.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# 安全说明
|
||||
|
||||
如果您发现安全问题,请直接联系我们:
|
||||
|
||||
- wanghe@fit2cloud.com
|
||||
- support@fit2cloud.com
|
||||
- 400-052-0755
|
||||
|
||||
感谢您的支持!
|
||||
|
||||
# Security Policy
|
||||
|
||||
All security bugs should be reported to the contact as below:
|
||||
|
||||
- wanghe@fit2cloud.com
|
||||
- support@fit2cloud.com
|
||||
- 400-052-0755
|
||||
|
||||
Thanks for your support!
|
@@ -144,7 +144,7 @@ func (b *BaseApi) DeleteCheck(c *gin.Context) {
|
||||
// @Router /apps/installed/sync [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"同步已安装应用列表","formatEN":"Sync the list of installed apps"}
|
||||
func (b *BaseApi) SyncInstalled(c *gin.Context) {
|
||||
if err := appInstallService.SyncAll(); err != nil {
|
||||
if err := appInstallService.SyncAll(false); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
@@ -1,6 +1,8 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
@@ -27,6 +29,23 @@ func (b *BaseApi) CreateBackup(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if len(req.Credential) != 0 {
|
||||
credential, err := base64.StdEncoding.DecodeString(req.Credential)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
req.Credential = string(credential)
|
||||
}
|
||||
if len(req.AccessKey) != 0 {
|
||||
accessKey, err := base64.StdEncoding.DecodeString(req.AccessKey)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
req.AccessKey = string(accessKey)
|
||||
}
|
||||
|
||||
if err := backupService.Create(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
@@ -52,6 +71,23 @@ func (b *BaseApi) ListBuckets(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if len(req.Credential) != 0 {
|
||||
credential, err := base64.StdEncoding.DecodeString(req.Credential)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
req.Credential = string(credential)
|
||||
}
|
||||
if len(req.AccessKey) != 0 {
|
||||
accessKey, err := base64.StdEncoding.DecodeString(req.AccessKey)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
req.AccessKey = string(accessKey)
|
||||
}
|
||||
|
||||
buckets, err := backupService.GetBuckets(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
@@ -139,7 +175,7 @@ func (b *BaseApi) DownloadRecord(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
c.File(filePath)
|
||||
helper.SuccessWithData(c, filePath)
|
||||
}
|
||||
|
||||
// @Tags Backup Account
|
||||
@@ -188,6 +224,23 @@ func (b *BaseApi) UpdateBackup(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if len(req.Credential) != 0 {
|
||||
credential, err := base64.StdEncoding.DecodeString(req.Credential)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
req.Credential = string(credential)
|
||||
}
|
||||
if len(req.AccessKey) != 0 {
|
||||
accessKey, err := base64.StdEncoding.DecodeString(req.AccessKey)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
req.AccessKey = string(accessKey)
|
||||
}
|
||||
|
||||
if err := backupService.Update(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
|
@@ -70,6 +70,34 @@ func (b *BaseApi) SearchCompose(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags Container Compose
|
||||
// @Summary Test compose
|
||||
// @Description 测试 compose 是否可用
|
||||
// @Accept json
|
||||
// @Param request body dto.ComposeCreate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/compose/test [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"检测 compose [name] 格式","formatEN":"check compose [name]"}
|
||||
func (b *BaseApi) TestCompose(c *gin.Context) {
|
||||
var req dto.ComposeCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := global.VALID.Struct(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
|
||||
isOK, err := containerService.TestCompose(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, isOK)
|
||||
}
|
||||
|
||||
// @Tags Container Compose
|
||||
// @Summary Create compose
|
||||
// @Description 创建容器编排
|
||||
@@ -90,11 +118,12 @@ func (b *BaseApi) CreateCompose(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := containerService.CreateCompose(req); err != nil {
|
||||
log, err := containerService.CreateCompose(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
helper.SuccessWithData(c, log)
|
||||
}
|
||||
|
||||
// @Tags Container Compose
|
||||
|
@@ -198,7 +198,7 @@ func (b *BaseApi) TargetDownload(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
c.File(filePath)
|
||||
helper.SuccessWithData(c, filePath)
|
||||
}
|
||||
|
||||
// @Tags Cronjob
|
||||
|
@@ -2,6 +2,7 @@ package v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
@@ -29,6 +30,15 @@ func (b *BaseApi) CreateMysql(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if len(req.Password) != 0 {
|
||||
password, err := base64.StdEncoding.DecodeString(req.Password)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
req.Password = string(password)
|
||||
}
|
||||
|
||||
if _, err := mysqlService.Create(context.Background(), req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
@@ -81,6 +91,15 @@ func (b *BaseApi) ChangeMysqlPassword(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if len(req.Value) != 0 {
|
||||
value, err := base64.StdEncoding.DecodeString(req.Value)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
req.Value = string(value)
|
||||
}
|
||||
|
||||
if err := mysqlService.ChangePassword(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
|
@@ -2,6 +2,7 @@ package v1
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
@@ -106,6 +107,15 @@ func (b *BaseApi) ChangeRedisPassword(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if len(req.Value) != 0 {
|
||||
value, err := base64.StdEncoding.DecodeString(req.Value)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
req.Value = string(value)
|
||||
}
|
||||
|
||||
if err := redisService.ChangePassword(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
|
@@ -35,7 +35,6 @@ var (
|
||||
|
||||
commandService = service.ServiceGroupApp.CommandService
|
||||
|
||||
websiteGroupService = service.ServiceGroupApp.WebsiteGroupService
|
||||
websiteService = service.ServiceGroupApp.WebsiteService
|
||||
websiteDnsAccountService = service.ServiceGroupApp.WebsiteDnsAccountService
|
||||
websiteSSLService = service.ServiceGroupApp.WebsiteSSLService
|
||||
|
@@ -3,6 +3,14 @@ package v1
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||||
@@ -14,13 +22,6 @@ import (
|
||||
websocket2 "github.com/1Panel-dev/1Panel/backend/utils/websocket"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/websocket"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// @Tags File
|
||||
@@ -444,6 +445,28 @@ func (b *BaseApi) Download(c *gin.Context) {
|
||||
c.File(filePath)
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
// @Summary Download file with path
|
||||
// @Description 下载指定文件
|
||||
// @Accept json
|
||||
// @Param request body dto.FilePath true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/download/bypath [post]
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"下载文件 [path]","formatEN":"Download file [path]"}
|
||||
func (b *BaseApi) DownloadFile(c *gin.Context) {
|
||||
var req dto.FilePath
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := global.VALID.Struct(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
c.File(req.Path)
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
// @Summary Load file size
|
||||
// @Description 获取文件夹大小
|
||||
@@ -496,6 +519,12 @@ func (b *BaseApi) LoadFromFile(c *gin.Context) {
|
||||
}
|
||||
|
||||
func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int) error {
|
||||
if _, err := os.Stat(path.Dir(dstDir)); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(path.Dir(dstDir), os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
targetFile, err := os.Create(filepath.Join(dstDir, fileName))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -524,7 +553,6 @@ func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int)
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/chunkupload [post]
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"上传文件 [path]","formatEN":"Upload file [path]"}
|
||||
func (b *BaseApi) UploadChunkFiles(c *gin.Context) {
|
||||
fileForm, err := c.FormFile("chunk")
|
||||
if err != nil {
|
||||
@@ -550,15 +578,18 @@ func (b *BaseApi) UploadChunkFiles(c *gin.Context) {
|
||||
}
|
||||
|
||||
fileOp := files.NewFileOp()
|
||||
if err := fileOp.CreateDir("uploads", 0755); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
tmpDir := path.Join(global.CONF.System.TmpDir, "upload")
|
||||
if !fileOp.Stat(tmpDir) {
|
||||
if err := fileOp.CreateDir(tmpDir, 0755); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
//fileID := uuid.New().String()
|
||||
filename := c.PostForm("filename")
|
||||
fileDir := filepath.Join(global.CONF.System.DataDir, "upload", filename)
|
||||
|
||||
os.MkdirAll(fileDir, 0755)
|
||||
filename := c.PostForm("filename")
|
||||
fileDir := filepath.Join(tmpDir, filename)
|
||||
|
||||
_ = os.MkdirAll(fileDir, 0755)
|
||||
filePath := filepath.Join(fileDir, filename)
|
||||
|
||||
emptyFile, err := os.Create(filePath)
|
||||
@@ -566,26 +597,25 @@ func (b *BaseApi) UploadChunkFiles(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
emptyFile.Close()
|
||||
defer emptyFile.Close()
|
||||
|
||||
chunkData, err := ioutil.ReadAll(uploadFile)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrFileUpload, err)
|
||||
return
|
||||
}
|
||||
|
||||
chunkPath := filepath.Join(fileDir, fmt.Sprintf("%s.%d", filename, chunkIndex))
|
||||
err = ioutil.WriteFile(chunkPath, chunkData, 0644)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrFileUpload, err)
|
||||
return
|
||||
}
|
||||
|
||||
if chunkIndex+1 == chunkCount {
|
||||
err = mergeChunks(filename, fileDir, c.PostForm("path"), chunkCount)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrAppDelete, err)
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrFileUpload, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, true)
|
||||
|
@@ -1,6 +1,8 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
@@ -29,6 +31,23 @@ func (b *BaseApi) CreateHost(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if req.AuthMode == "password" && len(req.Password) != 0 {
|
||||
password, err := base64.StdEncoding.DecodeString(req.Password)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
req.Password = string(password)
|
||||
}
|
||||
if req.AuthMode == "key" && len(req.PrivateKey) != 0 {
|
||||
privateKey, err := base64.StdEncoding.DecodeString(req.PrivateKey)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
req.PrivateKey = string(privateKey)
|
||||
}
|
||||
|
||||
host, err := hostService.Create(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
@@ -55,6 +74,22 @@ func (b *BaseApi) TestByInfo(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if req.AuthMode == "password" && len(req.Password) != 0 {
|
||||
password, err := base64.StdEncoding.DecodeString(req.Password)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
req.Password = string(password)
|
||||
}
|
||||
if req.AuthMode == "key" && len(req.PrivateKey) != 0 {
|
||||
privateKey, err := base64.StdEncoding.DecodeString(req.PrivateKey)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
req.PrivateKey = string(privateKey)
|
||||
}
|
||||
|
||||
var connInfo ssh.ConnInfo
|
||||
_ = copier.Copy(&connInfo, &req)
|
||||
@@ -211,6 +246,22 @@ func (b *BaseApi) UpdateHost(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if req.AuthMode == "password" && len(req.Password) != 0 {
|
||||
password, err := base64.StdEncoding.DecodeString(req.Password)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
req.Password = string(password)
|
||||
}
|
||||
if req.AuthMode == "key" && len(req.PrivateKey) != 0 {
|
||||
privateKey, err := base64.StdEncoding.DecodeString(req.PrivateKey)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
req.PrivateKey = string(privateKey)
|
||||
}
|
||||
|
||||
upMap := make(map[string]interface{})
|
||||
upMap["name"] = req.Name
|
||||
|
@@ -22,6 +22,28 @@ func (b *BaseApi) GetUpgradeInfo(c *gin.Context) {
|
||||
helper.SuccessWithData(c, info)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Load release notes by version
|
||||
// @Description 获取版本 release notes
|
||||
// @Accept json
|
||||
// @Param request body dto.Upgrade true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/upgrade [get]
|
||||
func (b *BaseApi) GetNotesByVersion(c *gin.Context) {
|
||||
var req dto.Upgrade
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
notes, err := upgradeService.LoadNotes(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, notes)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Upgrade
|
||||
// @Description 系统更新
|
||||
|
@@ -1,89 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags Website Group
|
||||
// @Summary List website groups
|
||||
// @Description 获取网站组
|
||||
// @Success 200 {anrry} model.WebsiteGroup
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/groups [get]
|
||||
func (b *BaseApi) GetWebGroups(c *gin.Context) {
|
||||
list, err := websiteGroupService.GetGroups()
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, list)
|
||||
}
|
||||
|
||||
// @Tags Website Group
|
||||
// @Summary Create website group
|
||||
// @Description 创建网站组
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteGroupCreate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/groups [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建网站组 [name]","formatEN":"Create website groups [name]"}
|
||||
func (b *BaseApi) CreateWebGroup(c *gin.Context) {
|
||||
var req request.WebsiteGroupCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := websiteGroupService.CreateGroup(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags Website Group
|
||||
// @Summary Update website group
|
||||
// @Description 更新网站组
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteGroupUpdate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/groups/update [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新网站组 [name]","formatEN":"Update website groups [name]"}
|
||||
func (b *BaseApi) UpdateWebGroup(c *gin.Context) {
|
||||
var req request.WebsiteGroupUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := websiteGroupService.UpdateGroup(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags Website Group
|
||||
// @Summary Delete website group
|
||||
// @Description 删除网站组
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteResourceReq true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/groups/del [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"id","isList":false,"db":"website_groups","output_colume":"name","output_value":"name"}],"formatZH":"删除网站组 [name]","formatEN":"Delete website group [name]"}
|
||||
func (b *BaseApi) DeleteWebGroup(c *gin.Context) {
|
||||
var req request.WebsiteResourceReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := websiteGroupService.DeleteGroup(req.ID); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
@@ -176,3 +176,25 @@ func (b *BaseApi) GetWebsiteSSLById(c *gin.Context) {
|
||||
}
|
||||
helper.SuccessWithData(c, websiteSSL)
|
||||
}
|
||||
|
||||
// @Tags Website SSL
|
||||
// @Summary Update ssl
|
||||
// @Description 更新 ssl
|
||||
// @Accept json
|
||||
// @Param request body request.WebsiteSSLUpdate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/ssl/update [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"id","isList":false,"db":"website_ssls","output_colume":"primary_domain","output_value":"domain"}],"formatZH":"更新证书设置 [domain]","formatEN":"Update ssl config [domain]"}
|
||||
func (b *BaseApi) UpdateWebsiteSSL(c *gin.Context) {
|
||||
var req request.WebsiteSSLUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := websiteSSLService.Update(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
@@ -69,15 +69,21 @@ type AppForm struct {
|
||||
}
|
||||
|
||||
type AppFormFields struct {
|
||||
Type string `json:"type"`
|
||||
LabelZh string `json:"labelZh"`
|
||||
LabelEn string `json:"labelEn"`
|
||||
Required bool `json:"required"`
|
||||
Default interface{} `json:"default"`
|
||||
EnvKey string `json:"envKey"`
|
||||
Disabled bool `json:"disabled"`
|
||||
Edit bool `json:"edit"`
|
||||
Rule string `json:"rule"`
|
||||
Type string `json:"type"`
|
||||
LabelZh string `json:"labelZh"`
|
||||
LabelEn string `json:"labelEn"`
|
||||
Required bool `json:"required"`
|
||||
Default interface{} `json:"default"`
|
||||
EnvKey string `json:"envKey"`
|
||||
Disabled bool `json:"disabled"`
|
||||
Edit bool `json:"edit"`
|
||||
Rule string `json:"rule"`
|
||||
Values []AppFormValue `json:"values"`
|
||||
}
|
||||
|
||||
type AppFormValue struct {
|
||||
Label string `json:"label"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type AppResource struct {
|
||||
|
@@ -9,7 +9,6 @@ type UserLoginInfo struct {
|
||||
Name string `json:"name"`
|
||||
Token string `json:"token"`
|
||||
MfaStatus string `json:"mfaStatus"`
|
||||
MfaSecret string `json:"mfaSecret"`
|
||||
}
|
||||
|
||||
type MfaCredential struct {
|
||||
@@ -28,7 +27,6 @@ type Login struct {
|
||||
type MFALogin struct {
|
||||
Name string `json:"name"`
|
||||
Password string `json:"password"`
|
||||
Secret string `json:"secret"`
|
||||
Code string `json:"code"`
|
||||
AuthMethod string `json:"authMethod"`
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@ type ContainerInfo struct {
|
||||
State string `json:"state"`
|
||||
RunTime string `json:"runTime"`
|
||||
|
||||
IsFromApp bool `json:"isFromApp"`
|
||||
IsFromCompose bool `json:"isFromCompose"`
|
||||
}
|
||||
|
||||
|
@@ -13,6 +13,7 @@ type GroupSearch struct {
|
||||
type GroupUpdate struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
IsDefault bool `json:"isDefault"`
|
||||
}
|
||||
|
||||
|
@@ -44,3 +44,8 @@ type WebsiteDnsAccountUpdate struct {
|
||||
type WebsiteResourceReq struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
}
|
||||
|
||||
type WebsiteSSLUpdate struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
AutoRenew bool `json:"autoRenew" validate:"required"`
|
||||
}
|
||||
|
@@ -61,11 +61,13 @@ type AppService struct {
|
||||
}
|
||||
|
||||
type AppParam struct {
|
||||
Value interface{} `json:"value"`
|
||||
Edit bool `json:"edit"`
|
||||
Key string `json:"key"`
|
||||
Rule string `json:"rule"`
|
||||
LabelZh string `json:"labelZh"`
|
||||
LabelEn string `json:"labelEn"`
|
||||
Type string `json:"type"`
|
||||
Value interface{} `json:"value"`
|
||||
Edit bool `json:"edit"`
|
||||
Key string `json:"key"`
|
||||
Rule string `json:"rule"`
|
||||
LabelZh string `json:"labelZh"`
|
||||
LabelEn string `json:"labelEn"`
|
||||
Type string `json:"type"`
|
||||
Values interface{} `json:"values"`
|
||||
ShowValue string `json:"showValue"`
|
||||
}
|
||||
|
@@ -82,9 +82,11 @@ type SnapshotInfo struct {
|
||||
}
|
||||
|
||||
type UpgradeInfo struct {
|
||||
NewVersion string `json:"newVersion"`
|
||||
ReleaseNote string `json:"releaseNote"`
|
||||
NewVersion string `json:"newVersion"`
|
||||
LatestVersion string `json:"latestVersion"`
|
||||
ReleaseNote string `json:"releaseNote"`
|
||||
}
|
||||
|
||||
type Upgrade struct {
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
@@ -1,11 +0,0 @@
|
||||
package model
|
||||
|
||||
type WebsiteGroup struct {
|
||||
BaseModel
|
||||
Name string `gorm:"type:varchar(64);not null" json:"name"`
|
||||
Default bool `json:"default"`
|
||||
}
|
||||
|
||||
func (w WebsiteGroup) TableName() string {
|
||||
return "website_groups"
|
||||
}
|
@@ -113,6 +113,7 @@ type RootInfo struct {
|
||||
Name string `json:"name"`
|
||||
Port int64 `json:"port"`
|
||||
Password string `json:"password"`
|
||||
UserPassword string `json:"userPassword"`
|
||||
ContainerName string `json:"containerName"`
|
||||
Param string `json:"param"`
|
||||
Env string `json:"env"`
|
||||
@@ -146,6 +147,10 @@ func (a *AppInstallRepo) LoadBaseInfo(key string, name string) (*RootInfo, error
|
||||
if ok {
|
||||
info.Password = password
|
||||
}
|
||||
userPassword, ok := envMap["PANEL_DB_USER_PASSWORD"].(string)
|
||||
if ok {
|
||||
info.UserPassword = userPassword
|
||||
}
|
||||
info.Port = int64(appInstall.HttpPort)
|
||||
info.ID = appInstall.ID
|
||||
info.ContainerName = appInstall.ContainerName
|
||||
|
@@ -24,7 +24,7 @@ type ICronjobRepo interface {
|
||||
Update(id uint, vars map[string]interface{}) error
|
||||
Delete(opts ...DBOption) error
|
||||
DeleteRecord(opts ...DBOption) error
|
||||
StartRecords(cronjobID uint, targetPath string) model.JobRecords
|
||||
StartRecords(cronjobID uint, fromLocal bool, targetPath string) model.JobRecords
|
||||
EndRecords(record model.JobRecords, status, message, records string)
|
||||
}
|
||||
|
||||
@@ -112,10 +112,11 @@ func (c *CronjobRepo) WithByJobID(id int) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (u *CronjobRepo) StartRecords(cronjobID uint, targetPath string) model.JobRecords {
|
||||
func (u *CronjobRepo) StartRecords(cronjobID uint, fromLocal bool, targetPath string) model.JobRecords {
|
||||
var record model.JobRecords
|
||||
record.StartTime = time.Now()
|
||||
record.CronjobID = cronjobID
|
||||
record.FromLocal = fromLocal
|
||||
record.Status = constant.StatusWaiting
|
||||
if err := global.DB.Create(&record).Error; err != nil {
|
||||
global.LOG.Errorf("create record status failed, err: %v", err)
|
||||
|
@@ -19,7 +19,6 @@ type RepoGroup struct {
|
||||
BackupRepo
|
||||
WebsiteRepo
|
||||
WebsiteDomainRepo
|
||||
WebsiteGroupRepo
|
||||
WebsiteDnsAccountRepo
|
||||
WebsiteSSLRepo
|
||||
WebsiteAcmeAccountRepo
|
||||
|
@@ -14,7 +14,7 @@ type IGroupRepo interface {
|
||||
Create(group *model.Group) error
|
||||
Update(id uint, vars map[string]interface{}) error
|
||||
Delete(opts ...DBOption) error
|
||||
CancelDefault() error
|
||||
CancelDefault(groupType string) error
|
||||
WithByIsDefault(isDefault bool) DBOption
|
||||
}
|
||||
|
||||
@@ -64,6 +64,6 @@ func (u *GroupRepo) Delete(opts ...DBOption) error {
|
||||
return db.Delete(&model.Group{}).Error
|
||||
}
|
||||
|
||||
func (w GroupRepo) CancelDefault() error {
|
||||
return global.DB.Model(&model.Group{}).Where("`is_default` = 1").Updates(map[string]interface{}{"is_default": 0}).Error
|
||||
func (u *GroupRepo) CancelDefault(groupType string) error {
|
||||
return global.DB.Model(&model.Group{}).Where("is_default = ? AND type = ?", 1, groupType).Updates(map[string]interface{}{"is_default": 0}).Error
|
||||
}
|
||||
|
@@ -1,44 +0,0 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
type WebsiteGroupRepo struct {
|
||||
}
|
||||
|
||||
func (w WebsiteGroupRepo) Page(page, size int, opts ...DBOption) (int64, []model.WebsiteGroup, error) {
|
||||
var groups []model.WebsiteGroup
|
||||
db := getDb(opts...).Model(&model.WebsiteGroup{})
|
||||
count := int64(0)
|
||||
db = db.Count(&count)
|
||||
err := db.Limit(size).Offset(size * (page - 1)).Order("`default` desc").Find(&groups).Error
|
||||
return count, groups, err
|
||||
}
|
||||
|
||||
func (w WebsiteGroupRepo) GetBy(opts ...DBOption) ([]model.WebsiteGroup, error) {
|
||||
var groups []model.WebsiteGroup
|
||||
db := getDb(opts...).Model(&model.WebsiteGroup{})
|
||||
if err := db.Order("`default` desc").Find(&groups).Error; err != nil {
|
||||
return groups, err
|
||||
}
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
func (w WebsiteGroupRepo) Create(app *model.WebsiteGroup) error {
|
||||
return getDb().Omit(clause.Associations).Create(app).Error
|
||||
}
|
||||
|
||||
func (w WebsiteGroupRepo) Save(app *model.WebsiteGroup) error {
|
||||
return getDb().Omit(clause.Associations).Save(app).Error
|
||||
}
|
||||
|
||||
func (w WebsiteGroupRepo) DeleteBy(opts ...DBOption) error {
|
||||
return getDb(opts...).Delete(&model.WebsiteGroup{}).Error
|
||||
}
|
||||
|
||||
func (w WebsiteGroupRepo) CancelDefault() error {
|
||||
return global.DB.Model(&model.WebsiteGroup{}).Where("`default` = 1").Updates(map[string]interface{}{"default": 0}).Error
|
||||
}
|
@@ -6,6 +6,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -166,6 +167,9 @@ func (a AppService) GetAppDetail(appId uint, version string) (response.AppDetail
|
||||
}
|
||||
|
||||
func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error) {
|
||||
if err := docker.CreateDefaultDockerNetwork(); err != nil {
|
||||
return nil, buserr.WithDetail(constant.Err1PanelNetworkFailed, err.Error(), nil)
|
||||
}
|
||||
if list, _ := appInstallRepo.ListBy(commonRepo.WithByName(req.Name)); len(list) > 0 {
|
||||
return nil, buserr.New(constant.ErrNameIsExist)
|
||||
}
|
||||
|
@@ -3,9 +3,6 @@ package service
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/env"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/nginx"
|
||||
"github.com/joho/godotenv"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
@@ -14,6 +11,10 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/env"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/nginx"
|
||||
"github.com/joho/godotenv"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/response"
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
@@ -33,7 +34,28 @@ import (
|
||||
type AppInstallService struct {
|
||||
}
|
||||
|
||||
func (a AppInstallService) Page(req request.AppInstalledSearch) (int64, []response.AppInstalledDTO, error) {
|
||||
type IAppInstallService interface {
|
||||
Page(req request.AppInstalledSearch) (int64, []response.AppInstalledDTO, error)
|
||||
CheckExist(key string) (*response.AppInstalledCheck, error)
|
||||
LoadPort(key string) (int64, error)
|
||||
LoadPassword(key string) (string, error)
|
||||
SearchForWebsite(req request.AppInstalledSearch) ([]response.AppInstalledDTO, error)
|
||||
Operate(req request.AppInstalledOperate) error
|
||||
Update(req request.AppInstalledUpdate) error
|
||||
SyncAll(systemInit bool) error
|
||||
GetServices(key string) ([]response.AppService, error)
|
||||
GetUpdateVersions(installId uint) ([]dto.AppVersion, error)
|
||||
GetParams(id uint) ([]response.AppParam, error)
|
||||
ChangeAppPort(req request.PortUpdate) error
|
||||
GetDefaultConfigByKey(key string) (string, error)
|
||||
DeleteCheck(installId uint) ([]dto.AppResource, error)
|
||||
}
|
||||
|
||||
func NewIAppInstalledService() IAppInstallService {
|
||||
return &AppInstallService{}
|
||||
}
|
||||
|
||||
func (a *AppInstallService) Page(req request.AppInstalledSearch) (int64, []response.AppInstalledDTO, error) {
|
||||
var opts []repo.DBOption
|
||||
|
||||
if req.Name != "" {
|
||||
@@ -73,7 +95,7 @@ func (a AppInstallService) Page(req request.AppInstalledSearch) (int64, []respon
|
||||
return total, installDTOs, nil
|
||||
}
|
||||
|
||||
func (a AppInstallService) CheckExist(key string) (*response.AppInstalledCheck, error) {
|
||||
func (a *AppInstallService) CheckExist(key string) (*response.AppInstalledCheck, error) {
|
||||
res := &response.AppInstalledCheck{
|
||||
IsExist: false,
|
||||
}
|
||||
@@ -103,7 +125,7 @@ func (a AppInstallService) CheckExist(key string) (*response.AppInstalledCheck,
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (a AppInstallService) LoadPort(key string) (int64, error) {
|
||||
func (a *AppInstallService) LoadPort(key string) (int64, error) {
|
||||
app, err := appInstallRepo.LoadBaseInfo(key, "")
|
||||
if err != nil {
|
||||
return int64(0), nil
|
||||
@@ -111,7 +133,7 @@ func (a AppInstallService) LoadPort(key string) (int64, error) {
|
||||
return app.Port, nil
|
||||
}
|
||||
|
||||
func (a AppInstallService) LoadPassword(key string) (string, error) {
|
||||
func (a *AppInstallService) LoadPassword(key string) (string, error) {
|
||||
app, err := appInstallRepo.LoadBaseInfo(key, "")
|
||||
if err != nil {
|
||||
return "", nil
|
||||
@@ -119,7 +141,7 @@ func (a AppInstallService) LoadPassword(key string) (string, error) {
|
||||
return app.Password, nil
|
||||
}
|
||||
|
||||
func (a AppInstallService) SearchForWebsite(req request.AppInstalledSearch) ([]response.AppInstalledDTO, error) {
|
||||
func (a *AppInstallService) SearchForWebsite(req request.AppInstalledSearch) ([]response.AppInstalledDTO, error) {
|
||||
var (
|
||||
installs []model.AppInstall
|
||||
err error
|
||||
@@ -152,7 +174,7 @@ func (a AppInstallService) SearchForWebsite(req request.AppInstalledSearch) ([]r
|
||||
return handleInstalled(installs, false)
|
||||
}
|
||||
|
||||
func (a AppInstallService) Operate(req request.AppInstalledOperate) error {
|
||||
func (a *AppInstallService) Operate(req request.AppInstalledOperate) error {
|
||||
install, err := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallId))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -196,7 +218,7 @@ func (a AppInstallService) Operate(req request.AppInstalledOperate) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (a AppInstallService) Update(req request.AppInstalledUpdate) error {
|
||||
func (a *AppInstallService) Update(req request.AppInstalledUpdate) error {
|
||||
installed, err := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallId))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -270,13 +292,18 @@ func (a AppInstallService) Update(req request.AppInstalledUpdate) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a AppInstallService) SyncAll() error {
|
||||
func (a *AppInstallService) SyncAll(systemInit bool) error {
|
||||
allList, err := appInstallRepo.ListBy()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, i := range allList {
|
||||
if i.Status == constant.Installing {
|
||||
if systemInit {
|
||||
i.Status = constant.Error
|
||||
i.Message = "System restart causes application exception"
|
||||
_ = appInstallRepo.Save(&i)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err := syncById(i.ID); err != nil {
|
||||
@@ -286,7 +313,7 @@ func (a AppInstallService) SyncAll() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a AppInstallService) GetServices(key string) ([]response.AppService, error) {
|
||||
func (a *AppInstallService) GetServices(key string) ([]response.AppService, error) {
|
||||
app, err := appRepo.GetFirst(appRepo.WithKey(key))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -310,7 +337,7 @@ func (a AppInstallService) GetServices(key string) ([]response.AppService, error
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (a AppInstallService) GetUpdateVersions(installId uint) ([]dto.AppVersion, error) {
|
||||
func (a *AppInstallService) GetUpdateVersions(installId uint) ([]dto.AppVersion, error) {
|
||||
install, err := appInstallRepo.GetFirst(commonRepo.WithByID(installId))
|
||||
var versions []dto.AppVersion
|
||||
if err != nil {
|
||||
@@ -335,7 +362,7 @@ func (a AppInstallService) GetUpdateVersions(installId uint) ([]dto.AppVersion,
|
||||
return versions, nil
|
||||
}
|
||||
|
||||
func (a AppInstallService) ChangeAppPort(req request.PortUpdate) error {
|
||||
func (a *AppInstallService) ChangeAppPort(req request.PortUpdate) error {
|
||||
if common.ScanPort(int(req.Port)) {
|
||||
return buserr.WithDetail(constant.ErrPortInUsed, req.Port, nil)
|
||||
}
|
||||
@@ -363,7 +390,7 @@ func (a AppInstallService) ChangeAppPort(req request.PortUpdate) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a AppInstallService) DeleteCheck(installId uint) ([]dto.AppResource, error) {
|
||||
func (a *AppInstallService) DeleteCheck(installId uint) ([]dto.AppResource, error) {
|
||||
var res []dto.AppResource
|
||||
appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(installId))
|
||||
if err != nil {
|
||||
@@ -404,7 +431,7 @@ func (a AppInstallService) DeleteCheck(installId uint) ([]dto.AppResource, error
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (a AppInstallService) GetDefaultConfigByKey(key string) (string, error) {
|
||||
func (a *AppInstallService) GetDefaultConfigByKey(key string) (string, error) {
|
||||
appInstall, err := getAppInstallByKey(key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -426,7 +453,7 @@ func (a AppInstallService) GetDefaultConfigByKey(key string) (string, error) {
|
||||
return string(contentByte), nil
|
||||
}
|
||||
|
||||
func (a AppInstallService) GetParams(id uint) ([]response.AppParam, error) {
|
||||
func (a *AppInstallService) GetParams(id uint) ([]response.AppParam, error) {
|
||||
var (
|
||||
res []response.AppParam
|
||||
appForm dto.AppForm
|
||||
@@ -459,14 +486,20 @@ func (a AppInstallService) GetParams(id uint) ([]response.AppParam, error) {
|
||||
}
|
||||
appParam.LabelZh = form.LabelZh
|
||||
appParam.LabelEn = form.LabelEn
|
||||
appParam.Value = v
|
||||
if form.Type == "service" {
|
||||
appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithServiceName(v.(string)))
|
||||
appParam.Value = appInstall.Name
|
||||
res = append(res, appParam)
|
||||
} else {
|
||||
appParam.Value = v
|
||||
res = append(res, appParam)
|
||||
appParam.ShowValue = appInstall.Name
|
||||
} else if form.Type == "select" {
|
||||
for _, fv := range form.Values {
|
||||
if fv.Value == v {
|
||||
appParam.ShowValue = fv.Label
|
||||
break
|
||||
}
|
||||
}
|
||||
appParam.Values = form.Values
|
||||
}
|
||||
res = append(res, appParam)
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
@@ -622,7 +655,7 @@ func updateInstallInfoInDB(appKey, appName, param string, isRestart bool, value
|
||||
}, commonRepo.WithByID(appInstall.ID))
|
||||
}
|
||||
if param == "user-password" {
|
||||
oldVal = fmt.Sprintf("\"PANEL_DB_USER_PASSWORD\":\"%v\"", appInstall.Password)
|
||||
oldVal = fmt.Sprintf("\"PANEL_DB_USER_PASSWORD\":\"%v\"", appInstall.UserPassword)
|
||||
newVal = fmt.Sprintf("\"PANEL_DB_USER_PASSWORD\":\"%v\"", value)
|
||||
_ = appInstallRepo.BatchUpdateBy(map[string]interface{}{
|
||||
"param": strings.ReplaceAll(appInstall.Param, oldVal, newVal),
|
||||
|
@@ -86,9 +86,9 @@ func (u *AuthService) MFALogin(c *gin.Context, info dto.MFALogin) (*dto.UserLogi
|
||||
}
|
||||
pass, err := encrypt.StringDecrypt(passwrodSetting.Value)
|
||||
if err != nil {
|
||||
return nil, constant.ErrAuth
|
||||
return nil, err
|
||||
}
|
||||
if info.Password != pass && nameSetting.Value != info.Name {
|
||||
if info.Password != pass || nameSetting.Value != info.Name {
|
||||
return nil, constant.ErrAuth
|
||||
}
|
||||
|
||||
|
@@ -134,7 +134,7 @@ func (u *BackupService) DownloadRecord(info dto.DownloadRecord) (string, error)
|
||||
tempPath := fmt.Sprintf("%sdownload%s", constant.DataDir, info.FileDir)
|
||||
if _, err := os.Stat(tempPath); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(tempPath, os.ModePerm); err != nil {
|
||||
fmt.Println(err)
|
||||
global.LOG.Errorf("mkdir %s failed, err: %v", tempPath, err)
|
||||
}
|
||||
}
|
||||
targetPath := tempPath + info.FileName
|
||||
|
@@ -181,16 +181,19 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback
|
||||
return err
|
||||
}
|
||||
if err := handleMysqlRecover(mysqlInfo, tmpPath, db.Name, fmt.Sprintf("%s.sql.gz", install.Name), true); err != nil {
|
||||
global.LOG.Errorf("handle recover from sql.gz failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := handleUnTar(tmpPath+"/app.tar.gz", fmt.Sprintf("%s/%s", constant.AppInstallDir, install.App.Key)); err != nil {
|
||||
global.LOG.Errorf("handle recover from app.tar.gz failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
oldInstall.Status = constant.Running
|
||||
if err := appInstallRepo.Save(install); err != nil {
|
||||
global.LOG.Errorf("save db app install failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
isOk = true
|
||||
|
@@ -106,8 +106,8 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
|
||||
return fmt.Errorf("backup website %s for rollback before recover failed, err: %v", website.Alias, err)
|
||||
}
|
||||
defer func() {
|
||||
global.LOG.Info("recover failed, start to rollback now")
|
||||
if !isOk {
|
||||
global.LOG.Info("recover failed, start to rollback now")
|
||||
if err := handleWebsiteRecover(website, rollbackFile, true); err != nil {
|
||||
global.LOG.Errorf("rollback website %s from %s failed, err: %v", website.Alias, rollbackFile, err)
|
||||
return
|
||||
@@ -126,6 +126,7 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
|
||||
}
|
||||
nginxConfPath := fmt.Sprintf("%s/openresty/%s/conf/conf.d", constant.AppInstallDir, nginxInfo.Name)
|
||||
if err := fileOp.CopyFile(fmt.Sprintf("%s/%s.conf", tmpPath, website.Alias), nginxConfPath); err != nil {
|
||||
global.LOG.Errorf("handle recover from conf.d failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -135,22 +136,27 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
|
||||
return err
|
||||
}
|
||||
if err := handleAppRecover(&app, fmt.Sprintf("%s/%s.app.tar.gz", tmpPath, website.Alias), true); err != nil {
|
||||
global.LOG.Errorf("handle recover from app.tar.gz failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
if _, err := compose.Restart(fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, app.App.Key, app.Name)); err != nil {
|
||||
global.LOG.Errorf("docker-compose restart failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
siteDir := fmt.Sprintf("%s/openresty/%s/www/sites", constant.AppInstallDir, nginxInfo.Name)
|
||||
if err := handleUnTar(fmt.Sprintf("%s/%s.web.tar.gz", tmpPath, website.Alias), siteDir); err != nil {
|
||||
global.LOG.Errorf("handle recover from web.tar.gz failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
stdout, err := cmd.Execf("docker exec -i %s nginx -s reload", nginxInfo.ContainerName)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("nginx -s reload failed, err: %s", stdout)
|
||||
return errors.New(string(stdout))
|
||||
}
|
||||
|
||||
if err := websiteRepo.SaveWithoutCtx(&oldWebsite); err != nil {
|
||||
global.LOG.Errorf("handle save website data failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
isOk = true
|
||||
|
@@ -3,6 +3,7 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
@@ -33,7 +34,7 @@ type IContainerService interface {
|
||||
PageVolume(req dto.SearchWithPage) (int64, interface{}, error)
|
||||
ListVolume() ([]dto.Options, error)
|
||||
PageCompose(req dto.SearchWithPage) (int64, interface{}, error)
|
||||
CreateCompose(req dto.ComposeCreate) error
|
||||
CreateCompose(req dto.ComposeCreate) (string, error)
|
||||
ComposeOperation(req dto.ComposeOperation) error
|
||||
ContainerCreate(req dto.ContainerCreate) error
|
||||
ContainerOperation(req dto.ContainerOperation) error
|
||||
@@ -98,6 +99,10 @@ func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, erro
|
||||
if _, ok := container.Labels[composeProjectLabel]; ok {
|
||||
IsFromCompose = true
|
||||
}
|
||||
IsFromApp := false
|
||||
if created, ok := container.Labels[composeCreatedBy]; ok && created == "Apps" {
|
||||
IsFromApp = true
|
||||
}
|
||||
backDatas = append(backDatas, dto.ContainerInfo{
|
||||
ContainerID: container.ID,
|
||||
CreateTime: time.Unix(container.Created, 0).Format("2006-01-02 15:04:05"),
|
||||
@@ -106,6 +111,7 @@ func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, erro
|
||||
ImageName: container.Image,
|
||||
State: container.State,
|
||||
RunTime: container.Status,
|
||||
IsFromApp: IsFromApp,
|
||||
IsFromCompose: IsFromCompose,
|
||||
})
|
||||
}
|
||||
@@ -234,7 +240,7 @@ func (u *ContainerService) ContainerLogs(req dto.ContainerLog) (string, error) {
|
||||
}
|
||||
stdout, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", errors.New(string(stdout))
|
||||
}
|
||||
return string(stdout), nil
|
||||
}
|
||||
|
@@ -5,6 +5,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -123,41 +125,49 @@ func (u *ContainerService) PageCompose(req dto.SearchWithPage) (int64, interface
|
||||
return int64(total), BackDatas, nil
|
||||
}
|
||||
|
||||
func (u *ContainerService) CreateCompose(req dto.ComposeCreate) error {
|
||||
if req.From == "template" {
|
||||
template, err := composeRepo.Get(commonRepo.WithByID(req.Template))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.From = "edit"
|
||||
req.File = template.Content
|
||||
func (u *ContainerService) TestCompose(req dto.ComposeCreate) (bool, error) {
|
||||
if err := u.loadPath(&req); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if req.From == "edit" {
|
||||
dir := fmt.Sprintf("%s/docker/compose/%s", constant.DataDir, req.Name)
|
||||
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
cmd := exec.Command("docker-compose", "-f", req.Path, "config")
|
||||
stdout, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return false, errors.New(string(stdout))
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("%s/docker-compose.yml", dir)
|
||||
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
write := bufio.NewWriter(file)
|
||||
_, _ = write.WriteString(string(req.File))
|
||||
write.Flush()
|
||||
req.Path = path
|
||||
func (u *ContainerService) CreateCompose(req dto.ComposeCreate) (string, error) {
|
||||
if err := u.loadPath(&req); err != nil {
|
||||
return "", err
|
||||
}
|
||||
global.LOG.Infof("docker-compose.yml %s create successful, start to docker-compose up", req.Name)
|
||||
if stdout, err := compose.Up(req.Path); err != nil {
|
||||
return errors.New(string(stdout))
|
||||
}
|
||||
|
||||
_ = composeRepo.CreateRecord(&model.Compose{Name: req.Name})
|
||||
return nil
|
||||
if req.From == "path" {
|
||||
req.Name = path.Base(strings.ReplaceAll(req.Path, "/"+path.Base(req.Path), ""))
|
||||
}
|
||||
logName := path.Dir(req.Path) + "/compose.log"
|
||||
file, err := os.OpenFile(logName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
go func() {
|
||||
defer file.Close()
|
||||
cmd := exec.Command("docker-compose", "-f", req.Path, "up", "-d")
|
||||
stdout, err := cmd.CombinedOutput()
|
||||
_, _ = file.Write(stdout)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("docker-compose up %s failed, err: %v", req.Name, err)
|
||||
_, _ = compose.Down(req.Path)
|
||||
_, _ = file.WriteString("docker-compose up failed!")
|
||||
return
|
||||
}
|
||||
global.LOG.Infof("docker-compose up %s successful!", req.Name)
|
||||
_ = composeRepo.CreateRecord(&model.Compose{Name: req.Name})
|
||||
_, _ = file.WriteString("docker-compose up successful!")
|
||||
}()
|
||||
|
||||
return logName, nil
|
||||
}
|
||||
|
||||
func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error {
|
||||
@@ -199,3 +209,34 @@ func (u *ContainerService) ComposeUpdate(req dto.ComposeUpdate) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *ContainerService) loadPath(req *dto.ComposeCreate) error {
|
||||
if req.From == "template" {
|
||||
template, err := composeRepo.Get(commonRepo.WithByID(req.Template))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.From = "edit"
|
||||
req.File = template.Content
|
||||
}
|
||||
if req.From == "edit" {
|
||||
dir := fmt.Sprintf("%s/docker/compose/%s", constant.DataDir, req.Name)
|
||||
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("%s/docker-compose.yml", dir)
|
||||
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
write := bufio.NewWriter(file)
|
||||
_, _ = write.WriteString(string(req.File))
|
||||
write.Flush()
|
||||
req.Path = path
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -7,6 +7,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
@@ -80,6 +82,9 @@ func (u *ContainerService) DeleteNetwork(req dto.BatchDelete) error {
|
||||
}
|
||||
for _, id := range req.Names {
|
||||
if err := client.NetworkRemove(context.TODO(), id); err != nil {
|
||||
if strings.Contains(err.Error(), "has active endpoints") {
|
||||
return buserr.WithDetail(constant.ErrInUsed, id, nil)
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@@ -2,12 +2,12 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
||||
"github.com/docker/docker/api/types"
|
||||
@@ -96,6 +96,9 @@ func (u *ContainerService) DeleteVolume(req dto.BatchDelete) error {
|
||||
}
|
||||
for _, id := range req.Names {
|
||||
if err := client.VolumeRemove(context.TODO(), id, true); err != nil {
|
||||
if strings.Contains(err.Error(), "volume is in use") {
|
||||
return buserr.WithDetail(constant.ErrInUsed, id, nil)
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -122,12 +125,8 @@ func (u *ContainerService) CreateVolume(req dto.VolumeCreat) error {
|
||||
DriverOpts: stringsToMap(req.Options),
|
||||
Labels: stringsToMap(req.Labels),
|
||||
}
|
||||
stat, err := client.VolumeCreate(context.TODO(), options)
|
||||
if err != nil {
|
||||
if _, err := client.VolumeCreate(context.TODO(), options); err != nil {
|
||||
return err
|
||||
}
|
||||
// if len(stat.CreatedAt) != 0 {
|
||||
fmt.Println(stat)
|
||||
// }
|
||||
return nil
|
||||
}
|
||||
|
@@ -2,17 +2,14 @@ package service
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/cloud_storage"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/robfig/cron/v3"
|
||||
@@ -92,69 +89,28 @@ func (u *CronjobService) Download(down dto.CronjobDownload) (string, error) {
|
||||
if cronjob.ID == 0 {
|
||||
return "", constant.ErrRecordNotFound
|
||||
}
|
||||
|
||||
global.LOG.Infof("start to download records %s from %s", cronjob.Type, backup.Type)
|
||||
varMap := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil {
|
||||
if backup.Type == "LOCAL" {
|
||||
if _, err := os.Stat(record.File); err != nil && os.IsNotExist(err) {
|
||||
return "", constant.ErrRecordNotFound
|
||||
}
|
||||
return record.File, nil
|
||||
}
|
||||
if record.FromLocal {
|
||||
local, _ := loadLocalDir()
|
||||
if _, err := os.Stat(local + "/" + record.File); err == nil {
|
||||
return local + "/" + record.File, nil
|
||||
}
|
||||
}
|
||||
client, err := NewIBackupService().NewClient(&backup)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
varMap["type"] = backup.Type
|
||||
if backup.Type != "LOCAL" {
|
||||
varMap["bucket"] = backup.Bucket
|
||||
switch backup.Type {
|
||||
case constant.Sftp:
|
||||
varMap["username"] = backup.AccessKey
|
||||
varMap["password"] = backup.Credential
|
||||
case constant.OSS, constant.S3, constant.MinIo:
|
||||
varMap["accessKey"] = backup.AccessKey
|
||||
varMap["secretKey"] = backup.Credential
|
||||
}
|
||||
backClient, err := cloud_storage.NewCloudStorageClient(varMap)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("new cloud storage client failed, err: %v", err)
|
||||
}
|
||||
global.LOG.Info("new backup client successful")
|
||||
commonDir := fmt.Sprintf("%s/%s/", cronjob.Type, cronjob.Name)
|
||||
name := fmt.Sprintf("%s%s.tar.gz", commonDir, record.StartTime.Format("20060102150405"))
|
||||
if cronjob.Type == "database" {
|
||||
name = fmt.Sprintf("%s%s.gz", commonDir, record.StartTime.Format("20060102150405"))
|
||||
}
|
||||
tempPath := fmt.Sprintf("%s/download/%s", constant.DataDir, commonDir)
|
||||
if _, err := os.Stat(tempPath); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(tempPath, os.ModePerm); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
global.LOG.Infof("download records %s from %s to %s", name, commonDir, tempPath)
|
||||
targetPath := tempPath + strings.ReplaceAll(name, commonDir, "")
|
||||
if _, err = os.Stat(targetPath); err != nil && os.IsNotExist(err) {
|
||||
isOK, err := backClient.Download(name, targetPath)
|
||||
if !isOK {
|
||||
return "", fmt.Errorf("cloud storage download failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
return targetPath, nil
|
||||
}
|
||||
if _, ok := varMap["dir"]; !ok {
|
||||
return "", errors.New("load local backup dir failed")
|
||||
}
|
||||
global.LOG.Infof("record is save in local dir %s", varMap["dir"])
|
||||
|
||||
switch cronjob.Type {
|
||||
case "website":
|
||||
return fmt.Sprintf("%v/website/%s/website_%s_%s.tar.gz", varMap["dir"], cronjob.Website, cronjob.Website, record.StartTime.Format("20060102150405")), nil
|
||||
case "database":
|
||||
mysqlInfo, err := appInstallRepo.LoadBaseInfo("mysql", "")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("load mysqlInfo failed, err: %v", err)
|
||||
}
|
||||
return fmt.Sprintf("%v/database/mysql/%s/%s/db_%s_%s.sql.gz", varMap["dir"], mysqlInfo.Name, cronjob.DBName, cronjob.DBName, record.StartTime.Format("20060102150405")), nil
|
||||
case "directory":
|
||||
return fmt.Sprintf("%v/%s/%s/directory%s_%s.tar.gz", varMap["dir"], cronjob.Type, cronjob.Name, strings.ReplaceAll(cronjob.SourceDir, "/", "_"), record.StartTime.Format("20060102150405")), nil
|
||||
default:
|
||||
return "", fmt.Errorf("not support type %s", cronjob.Type)
|
||||
tempPath := fmt.Sprintf("%s/download/%s", constant.DataDir, record.File)
|
||||
isOK, _ := client.Download(record.File, tempPath)
|
||||
if !isOK || err != nil {
|
||||
return "", constant.ErrRecordNotFound
|
||||
}
|
||||
return tempPath, nil
|
||||
}
|
||||
|
||||
func (u *CronjobService) HandleOnce(id uint) error {
|
||||
|
@@ -22,8 +22,7 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) {
|
||||
message []byte
|
||||
err error
|
||||
)
|
||||
record := cronjobRepo.StartRecords(cronjob.ID, "")
|
||||
record.FromLocal = cronjob.KeepLocal
|
||||
record := cronjobRepo.StartRecords(cronjob.ID, cronjob.KeepLocal, "")
|
||||
go func() {
|
||||
switch cronjob.Type {
|
||||
case "shell":
|
||||
@@ -118,6 +117,8 @@ func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Tim
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
itemFileDir := strings.ReplaceAll(backupDir, localDir+"/", "")
|
||||
if len(record.Name) != 0 {
|
||||
record.FileName = fileName
|
||||
record.FileDir = backupDir
|
||||
@@ -125,7 +126,7 @@ func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Tim
|
||||
record.BackupType = backup.Type
|
||||
if !cronjob.KeepLocal && backup.Type != "LOCAL" {
|
||||
record.Source = backup.Type
|
||||
record.FileDir = strings.ReplaceAll(backupDir, localDir+"/", "")
|
||||
record.FileDir = itemFileDir
|
||||
}
|
||||
if err := backupRepo.CreateRecord(&record); err != nil {
|
||||
global.LOG.Errorf("save backup record failed, err: %v", err)
|
||||
@@ -133,7 +134,10 @@ func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Tim
|
||||
}
|
||||
}
|
||||
|
||||
fullPath := fmt.Sprintf("%s/%s", record.FileDir, fileName)
|
||||
fullPath := fmt.Sprintf("%s/%s", backupDir, fileName)
|
||||
if backup.Type != "LOCAL" {
|
||||
fullPath = fmt.Sprintf("%s/%s", itemFileDir, fileName)
|
||||
}
|
||||
if backup.Type == "LOCAL" {
|
||||
u.HandleRmExpired(backup.Type, backupDir, cronjob, nil)
|
||||
return fullPath, nil
|
||||
@@ -148,10 +152,13 @@ func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Tim
|
||||
if err != nil {
|
||||
return fullPath, err
|
||||
}
|
||||
if _, err = client.Upload(backupDir+"/"+fileName, fullPath); err != nil {
|
||||
if _, err = client.Upload(backupDir+"/"+fileName, itemFileDir+"/"+fileName); err != nil {
|
||||
return fullPath, err
|
||||
}
|
||||
u.HandleRmExpired(backup.Type, backupDir, cronjob, client)
|
||||
u.HandleRmExpired(backup.Type, itemFileDir, cronjob, client)
|
||||
if cronjob.KeepLocal {
|
||||
u.HandleRmExpired("LOCAL", backupDir, cronjob, client)
|
||||
}
|
||||
return fullPath, nil
|
||||
}
|
||||
|
||||
@@ -185,9 +192,7 @@ func (u *CronjobService) HandleRmExpired(backType, backupDir string, cronjob *mo
|
||||
for i := 0; i < len(currentObjs)-int(cronjob.RetainCopies); i++ {
|
||||
_, _ = backClient.Delete(currentObjs[i].(string))
|
||||
}
|
||||
if !cronjob.KeepLocal {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
files, err := ioutil.ReadDir(backupDir)
|
||||
if err != nil {
|
||||
|
@@ -292,7 +292,7 @@ func (u *MysqlService) ChangeAccess(info dto.ChangeDBInfo) error {
|
||||
if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("create user if not exists '%s'@'%s' identified by '%s';", mysql.Username, info.Value, mysql.Password)); err != nil {
|
||||
return err
|
||||
}
|
||||
grantStr := fmt.Sprintf("grant all privileges on %s.* to '%s'@'%s'", mysql.Name, mysql.Username, info.Value)
|
||||
grantStr := fmt.Sprintf("grant all privileges on `%s`.* to '%s'@'%s'", mysql.Name, mysql.Username, info.Value)
|
||||
if app.Version == "5.7.39" {
|
||||
grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, mysql.Password)
|
||||
}
|
||||
|
@@ -28,7 +28,6 @@ type ServiceGroup struct {
|
||||
SettingService
|
||||
BackupService
|
||||
|
||||
WebsiteGroupService
|
||||
WebsiteService
|
||||
WebsiteDnsAccountService
|
||||
WebsiteSSLService
|
||||
@@ -68,7 +67,6 @@ var (
|
||||
backupRepo = repo.RepoGroupApp.BackupRepo
|
||||
|
||||
websiteRepo = repo.NewIWebsiteRepo()
|
||||
websiteGroupRepo = repo.RepoGroupApp.WebsiteGroupRepo
|
||||
websiteDomainRepo = repo.RepoGroupApp.WebsiteDomainRepo
|
||||
websiteDnsRepo = repo.RepoGroupApp.WebsiteDnsAccountRepo
|
||||
websiteSSLRepo = repo.NewISSLRepo()
|
||||
|
@@ -22,7 +22,7 @@ func NewIGroupService() IGroupService {
|
||||
}
|
||||
|
||||
func (u *GroupService) List(req dto.GroupSearch) ([]dto.GroupInfo, error) {
|
||||
groups, err := groupRepo.GetList(commonRepo.WithByType(req.Type))
|
||||
groups, err := groupRepo.GetList(commonRepo.WithByType(req.Type), commonRepo.WithOrderBy("is_default desc"), commonRepo.WithOrderBy("created_at desc"))
|
||||
if err != nil {
|
||||
return nil, constant.ErrRecordNotFound
|
||||
}
|
||||
@@ -38,7 +38,7 @@ func (u *GroupService) List(req dto.GroupSearch) ([]dto.GroupInfo, error) {
|
||||
}
|
||||
|
||||
func (u *GroupService) Create(req dto.GroupCreate) error {
|
||||
group, _ := groupRepo.Get(commonRepo.WithByName(req.Name), commonRepo.WithByName(req.Name))
|
||||
group, _ := groupRepo.Get(commonRepo.WithByName(req.Name), commonRepo.WithByType(req.Type))
|
||||
if group.ID != 0 {
|
||||
return constant.ErrRecordExist
|
||||
}
|
||||
@@ -58,7 +58,7 @@ func (u *GroupService) Delete(id uint) error {
|
||||
}
|
||||
switch group.Type {
|
||||
case "website":
|
||||
websites, _ := websiteRepo.GetBy(commonRepo.WithByGroupID(id))
|
||||
websites, _ := websiteRepo.GetBy(websiteRepo.WithGroupID(id))
|
||||
if len(websites) > 0 {
|
||||
return buserr.New(constant.ErrGroupIsUsed)
|
||||
}
|
||||
@@ -73,7 +73,7 @@ func (u *GroupService) Delete(id uint) error {
|
||||
|
||||
func (u *GroupService) Update(req dto.GroupUpdate) error {
|
||||
if req.IsDefault {
|
||||
if err := groupRepo.CancelDefault(); err != nil {
|
||||
if err := groupRepo.CancelDefault(req.Type); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
||||
@@ -53,8 +54,8 @@ func (u *ImageService) Page(req dto.SearchWithPage) (int64, interface{}, error)
|
||||
return 0, nil, err
|
||||
}
|
||||
if len(req.Info) != 0 {
|
||||
lenth, count := len(list), 0
|
||||
for count < lenth {
|
||||
length, count := len(list), 0
|
||||
for count < length {
|
||||
hasTag := false
|
||||
for _, tag := range list[count].RepoTags {
|
||||
if strings.Contains(tag, req.Info) {
|
||||
@@ -64,7 +65,7 @@ func (u *ImageService) Page(req dto.SearchWithPage) (int64, interface{}, error)
|
||||
}
|
||||
if !hasTag {
|
||||
list = append(list[:count], list[(count+1):]...)
|
||||
lenth--
|
||||
length--
|
||||
} else {
|
||||
count++
|
||||
}
|
||||
@@ -121,6 +122,7 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
fileName := "Dockerfile"
|
||||
if req.From == "edit" {
|
||||
dir := fmt.Sprintf("%s/docker/build/%s", constant.DataDir, strings.ReplaceAll(req.Name, ":", "_"))
|
||||
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
|
||||
@@ -140,7 +142,8 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) (string, error) {
|
||||
write.Flush()
|
||||
req.Dockerfile = dir
|
||||
} else {
|
||||
req.Dockerfile = strings.ReplaceAll(req.Dockerfile, "/Dockerfile", "")
|
||||
fileName = path.Base(req.Dockerfile)
|
||||
req.Dockerfile = path.Dir(req.Dockerfile)
|
||||
}
|
||||
tar, err := archive.TarWithOptions(req.Dockerfile+"/", &archive.TarOptions{})
|
||||
if err != nil {
|
||||
@@ -148,7 +151,7 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) (string, error) {
|
||||
}
|
||||
|
||||
opts := types.ImageBuildOptions{
|
||||
Dockerfile: "Dockerfile",
|
||||
Dockerfile: fileName,
|
||||
Tags: []string{req.Name},
|
||||
Remove: true,
|
||||
Labels: stringsToMap(req.Tags),
|
||||
@@ -178,14 +181,14 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) (string, error) {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.Contains(string(body), "error") && strings.Contains(string(body), "failed:") {
|
||||
if strings.Contains(string(body), "errorDetail") || strings.Contains(string(body), "error:") {
|
||||
global.LOG.Errorf("build image %s failed", req.Name)
|
||||
_, _ = file.Write(body)
|
||||
_, _ = file.WriteString("image build failed!")
|
||||
return
|
||||
}
|
||||
global.LOG.Infof("build image %s successful!", req.Name)
|
||||
_, _ = io.Copy(file, res.Body)
|
||||
_, _ = file.Write(body)
|
||||
_, _ = file.WriteString("image build successful!")
|
||||
}()
|
||||
|
||||
@@ -378,8 +381,14 @@ func (u *ImageService) ImageRemove(req dto.BatchDelete) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, ids := range req.Names {
|
||||
if _, err := client.ImageRemove(context.TODO(), ids, types.ImageRemoveOptions{Force: true, PruneChildren: true}); err != nil {
|
||||
for _, id := range req.Names {
|
||||
if _, err := client.ImageRemove(context.TODO(), id, types.ImageRemoveOptions{Force: true, PruneChildren: true}); err != nil {
|
||||
if strings.Contains(err.Error(), "image is being used") {
|
||||
if strings.Contains(id, "sha256:") {
|
||||
return buserr.New(constant.ErrObjectInUsed)
|
||||
}
|
||||
return buserr.WithDetail(constant.ErrInUsed, id, nil)
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@@ -4,12 +4,15 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type LogService struct{}
|
||||
|
||||
const logs = "https://resource.fit2cloud.com/installation-log.sh"
|
||||
|
||||
type ILogService interface {
|
||||
CreateLoginLog(operation model.LoginLog) error
|
||||
PageLoginLog(search dto.SearchLgLogWithPage) (int64, interface{}, error)
|
||||
@@ -77,3 +80,7 @@ func (u *LogService) CleanLogs(logtype string) error {
|
||||
}
|
||||
return logRepo.CleanLogin()
|
||||
}
|
||||
|
||||
func writeLogs(version string) {
|
||||
_, _ = cmd.Execf("curl -sfL %s | sh -s 1p upgrade %s", logs, version)
|
||||
}
|
||||
|
@@ -66,6 +66,9 @@ func (u *SnapshotService) SnapshotImport(req dto.SnapshotImport) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("incorrect snapshot name format of %s", snap)
|
||||
}
|
||||
if strings.HasSuffix(snap, ".tar.gz") {
|
||||
snap = strings.ReplaceAll(snap, ".tar.gz", "")
|
||||
}
|
||||
itemSnap := model.Snapshot{
|
||||
Name: snap,
|
||||
From: req.From,
|
||||
|
@@ -1,18 +1,20 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
)
|
||||
|
||||
@@ -20,6 +22,7 @@ type UpgradeService struct{}
|
||||
|
||||
type IUpgradeService interface {
|
||||
Upgrade(req dto.Upgrade) error
|
||||
LoadNotes(req dto.Upgrade) (string, error)
|
||||
SearchUpgrade() (*dto.UpgradeInfo, error)
|
||||
}
|
||||
|
||||
@@ -34,36 +37,50 @@ func (u *UpgradeService) SearchUpgrade() (*dto.UpgradeInfo, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
versionRes, err := http.Get(fmt.Sprintf("%s/%s/latest", global.CONF.System.RepoUrl, global.CONF.System.Mode))
|
||||
latestVersion, err := u.loadVersion(true, currentVersion.Value)
|
||||
if err != nil {
|
||||
global.LOG.Infof("load latest version failed, err: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
defer versionRes.Body.Close()
|
||||
version, err := ioutil.ReadAll(versionRes.Body)
|
||||
if err != nil {
|
||||
if !common.CompareVersion(string(latestVersion), currentVersion.Value) {
|
||||
return nil, err
|
||||
}
|
||||
isNew, err := compareVersion(currentVersion.Value, string(version))
|
||||
if !isNew || err != nil {
|
||||
return nil, err
|
||||
upgrade.LatestVersion = latestVersion
|
||||
if latestVersion[0:4] == currentVersion.Value[0:4] {
|
||||
upgrade.NewVersion = ""
|
||||
} else {
|
||||
newerVersion, err := u.loadVersion(false, currentVersion.Value)
|
||||
if err != nil {
|
||||
global.LOG.Infof("load newer version failed, err: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
if newerVersion == currentVersion.Value {
|
||||
upgrade.NewVersion = ""
|
||||
} else {
|
||||
upgrade.NewVersion = newerVersion
|
||||
}
|
||||
}
|
||||
itemVersion := upgrade.LatestVersion
|
||||
if upgrade.NewVersion != "" {
|
||||
itemVersion = upgrade.NewVersion
|
||||
}
|
||||
notes, err := u.loadReleaseNotes(fmt.Sprintf("%s/%s/%s/release/1panel-%s-release-notes", global.CONF.System.RepoUrl, global.CONF.System.Mode, itemVersion, itemVersion))
|
||||
|
||||
upgrade.NewVersion = string(version)
|
||||
|
||||
releaseNotes, err := http.Get(fmt.Sprintf("%s/%s/%s/release/1panel-%s-release-notes", global.CONF.System.RepoUrl, global.CONF.System.Mode, upgrade.NewVersion, upgrade.NewVersion))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("load relase-notes of version %s failed, err: %v", latestVersion, err)
|
||||
}
|
||||
defer releaseNotes.Body.Close()
|
||||
release, err := ioutil.ReadAll(releaseNotes.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
upgrade.ReleaseNote = string(release)
|
||||
|
||||
upgrade.ReleaseNote = notes
|
||||
return &upgrade, nil
|
||||
}
|
||||
|
||||
func (u *UpgradeService) LoadNotes(req dto.Upgrade) (string, error) {
|
||||
notes, err := u.loadReleaseNotes(fmt.Sprintf("%s/%s/%s/release/1panel-%s-release-notes", global.CONF.System.RepoUrl, global.CONF.System.Mode, req.Version, req.Version))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("load relase-notes of version %s failed, err: %v", req.Version, err)
|
||||
}
|
||||
return notes, nil
|
||||
}
|
||||
|
||||
func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
|
||||
global.LOG.Info("start to upgrade now...")
|
||||
fileOp := files.NewFileOp()
|
||||
@@ -128,6 +145,7 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
|
||||
}
|
||||
|
||||
global.LOG.Info("upgrade successful!")
|
||||
go writeLogs(req.Version)
|
||||
_ = settingRepo.Update("SystemVersion", req.Version)
|
||||
_ = settingRepo.Update("SystemStatus", "Free")
|
||||
_, _ = cmd.Exec("systemctl daemon-reload && systemctl restart 1panel.service")
|
||||
@@ -173,45 +191,49 @@ func (u *UpgradeService) handleRollback(fileOp files.FileOp, originalDir string,
|
||||
if err := cpBinary(originalDir+"/1panel.service", "/etc/systemd/system/1panel.service"); err != nil {
|
||||
global.LOG.Errorf("rollback 1panel failed, err: %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func compareVersion(version, newVersion string) (bool, error) {
|
||||
if version == newVersion {
|
||||
return false, nil
|
||||
func (u *UpgradeService) loadVersion(isLatest bool, currentVersion string) (string, error) {
|
||||
path := fmt.Sprintf("%s/%s/latest", global.CONF.System.RepoUrl, global.CONF.System.Mode)
|
||||
if !isLatest {
|
||||
path = fmt.Sprintf("%s/%s/latest.current", global.CONF.System.RepoUrl, global.CONF.System.Mode)
|
||||
}
|
||||
if len(version) == 0 || len(newVersion) == 0 {
|
||||
return false, fmt.Errorf("incorrect version or new version entered %v -- %v", version, newVersion)
|
||||
latestVersionRes, err := http.Get(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
versions := strings.Split(strings.ReplaceAll(version, "v", ""), ".")
|
||||
if len(versions) != 3 {
|
||||
return false, fmt.Errorf("incorrect version input %v", version)
|
||||
defer latestVersionRes.Body.Close()
|
||||
version, err := ioutil.ReadAll(latestVersionRes.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
newVersions := strings.Split(strings.ReplaceAll(newVersion, "v", ""), ".")
|
||||
if len(newVersions) != 3 {
|
||||
return false, fmt.Errorf("incorrect newVersions input %v", version)
|
||||
if isLatest {
|
||||
return string(version), nil
|
||||
}
|
||||
version1, _ := strconv.Atoi(versions[0])
|
||||
newVersion1, _ := strconv.Atoi(newVersions[0])
|
||||
if newVersion1 > version1 {
|
||||
return true, nil
|
||||
} else if newVersion1 == version1 {
|
||||
version2, _ := strconv.Atoi(versions[1])
|
||||
newVersion2, _ := strconv.Atoi(newVersions[1])
|
||||
if newVersion2 > version2 {
|
||||
return true, nil
|
||||
} else if newVersion2 == version2 {
|
||||
version3, _ := strconv.Atoi(versions[2])
|
||||
newVersion3, _ := strconv.Atoi(newVersions[2])
|
||||
if newVersion3 > version3 {
|
||||
return true, nil
|
||||
} else {
|
||||
return false, nil
|
||||
}
|
||||
} else {
|
||||
return false, nil
|
||||
}
|
||||
} else {
|
||||
return false, nil
|
||||
|
||||
versionMap := make(map[string]string)
|
||||
if err := json.Unmarshal(version, &versionMap); err != nil {
|
||||
return "", fmt.Errorf("load version map failed, err: %v", err)
|
||||
}
|
||||
|
||||
if len(currentVersion) < 4 {
|
||||
return "", fmt.Errorf("current version is error format: %s", currentVersion)
|
||||
}
|
||||
if version, ok := versionMap[currentVersion[0:4]]; ok {
|
||||
return version, nil
|
||||
}
|
||||
return "", errors.New("load version failed in latest.current")
|
||||
}
|
||||
|
||||
func (u *UpgradeService) loadReleaseNotes(path string) (string, error) {
|
||||
releaseNotes, err := http.Get(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer releaseNotes.Body.Close()
|
||||
release, err := ioutil.ReadAll(releaseNotes.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(release), nil
|
||||
}
|
||||
|
@@ -1,61 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
)
|
||||
|
||||
type WebsiteGroupService struct {
|
||||
}
|
||||
|
||||
func (w WebsiteGroupService) CreateGroup(create request.WebsiteGroupCreate) error {
|
||||
groups, _ := websiteGroupRepo.GetBy(commonRepo.WithByName(create.Name))
|
||||
if len(groups) > 0 {
|
||||
return buserr.New(constant.ErrNameIsExist)
|
||||
}
|
||||
return websiteGroupRepo.Create(&model.WebsiteGroup{
|
||||
Name: create.Name,
|
||||
})
|
||||
}
|
||||
|
||||
func (w WebsiteGroupService) GetGroups() ([]model.WebsiteGroup, error) {
|
||||
return websiteGroupRepo.GetBy()
|
||||
}
|
||||
|
||||
func (w WebsiteGroupService) UpdateGroup(update request.WebsiteGroupUpdate) error {
|
||||
if update.Default {
|
||||
if err := websiteGroupRepo.CancelDefault(); err != nil {
|
||||
return err
|
||||
}
|
||||
return websiteGroupRepo.Save(&model.WebsiteGroup{
|
||||
BaseModel: model.BaseModel{
|
||||
ID: update.ID,
|
||||
},
|
||||
Name: update.Name,
|
||||
Default: true,
|
||||
})
|
||||
} else {
|
||||
exists, _ := websiteGroupRepo.GetBy(commonRepo.WithByName(update.Name))
|
||||
for _, exist := range exists {
|
||||
if exist.ID != update.ID {
|
||||
return buserr.New(constant.ErrNameIsExist)
|
||||
}
|
||||
}
|
||||
return websiteGroupRepo.Save(&model.WebsiteGroup{
|
||||
BaseModel: model.BaseModel{
|
||||
ID: update.ID,
|
||||
},
|
||||
Name: update.Name,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (w WebsiteGroupService) DeleteGroup(id uint) error {
|
||||
websites, _ := websiteRepo.GetBy(websiteRepo.WithGroupID(id))
|
||||
if len(websites) > 0 {
|
||||
return buserr.New(constant.ErrGroupIsUsed)
|
||||
}
|
||||
return websiteGroupRepo.DeleteBy(commonRepo.WithByID(id))
|
||||
}
|
@@ -27,6 +27,7 @@ type IWebsiteSSLService interface {
|
||||
GetDNSResolve(req request.WebsiteDNSReq) ([]response.WebsiteDNSRes, error)
|
||||
GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO, error)
|
||||
Delete(id uint) error
|
||||
Update(update request.WebsiteSSLUpdate) error
|
||||
}
|
||||
|
||||
func NewIWebsiteSSLService() IWebsiteSSLService {
|
||||
@@ -99,6 +100,10 @@ func (w WebsiteSSLService) Create(create request.WebsiteSSLCreate) (request.Webs
|
||||
if err := client.UseHTTP(path.Join(constant.AppInstallDir, constant.AppOpenresty, appInstall.Name, "root")); err != nil {
|
||||
return res, err
|
||||
}
|
||||
case constant.DnsManual:
|
||||
if err := client.UseManualDns(); err != nil {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
|
||||
domains := []string{create.PrimaryDomain}
|
||||
@@ -128,6 +133,7 @@ func (w WebsiteSSLService) Create(create request.WebsiteSSLCreate) (request.Webs
|
||||
websiteSSL.StartDate = cert.NotBefore
|
||||
websiteSSL.Type = cert.Issuer.CommonName
|
||||
websiteSSL.Organization = cert.Issuer.Organization[0]
|
||||
websiteSSL.AutoRenew = create.AutoRenew
|
||||
|
||||
if err := websiteSSLRepo.Create(context.TODO(), &websiteSSL); err != nil {
|
||||
return res, err
|
||||
@@ -254,3 +260,12 @@ func (w WebsiteSSLService) Delete(id uint) error {
|
||||
}
|
||||
return websiteSSLRepo.DeleteBy(commonRepo.WithByID(id))
|
||||
}
|
||||
|
||||
func (w WebsiteSSLService) Update(update request.WebsiteSSLUpdate) error {
|
||||
websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(update.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
websiteSSL.AutoRenew = update.AutoRenew
|
||||
return websiteSSLRepo.Save(websiteSSL)
|
||||
}
|
||||
|
@@ -50,15 +50,16 @@ var (
|
||||
|
||||
// app
|
||||
var (
|
||||
ErrPortInUsed = "ErrPortInUsed"
|
||||
ErrAppLimit = "ErrAppLimit"
|
||||
ErrAppRequired = "ErrAppRequired"
|
||||
ErrFileCanNotRead = "ErrFileCanNotRead"
|
||||
ErrFileToLarge = "ErrFileToLarge"
|
||||
ErrNotInstall = "ErrNotInstall"
|
||||
ErrPortInOtherApp = "ErrPortInOtherApp"
|
||||
ErrDbUserNotValid = "ErrDbUserNotValid"
|
||||
ErrUpdateBuWebsite = "ErrUpdateBuWebsite"
|
||||
ErrPortInUsed = "ErrPortInUsed"
|
||||
ErrAppLimit = "ErrAppLimit"
|
||||
ErrAppRequired = "ErrAppRequired"
|
||||
ErrFileCanNotRead = "ErrFileCanNotRead"
|
||||
ErrFileToLarge = "ErrFileToLarge"
|
||||
ErrNotInstall = "ErrNotInstall"
|
||||
ErrPortInOtherApp = "ErrPortInOtherApp"
|
||||
ErrDbUserNotValid = "ErrDbUserNotValid"
|
||||
ErrUpdateBuWebsite = "ErrUpdateBuWebsite"
|
||||
Err1PanelNetworkFailed = "Err1PanelNetworkFailed"
|
||||
)
|
||||
|
||||
//website
|
||||
@@ -83,6 +84,7 @@ var (
|
||||
ErrMovePathFailed = "ErrMovePathFailed"
|
||||
ErrLinkPathNotFound = "ErrLinkPathNotFound"
|
||||
ErrFileIsExit = "ErrFileIsExit"
|
||||
ErrFileUpload = "ErrFileUpload"
|
||||
)
|
||||
|
||||
//mysql
|
||||
@@ -95,3 +97,9 @@ var (
|
||||
var (
|
||||
ErrTypeOfRedis = "ErrTypeOfRedis"
|
||||
)
|
||||
|
||||
//container
|
||||
var (
|
||||
ErrInUsed = "ErrInUsed"
|
||||
ErrObjectInUsed = "ErrObjectInUsed"
|
||||
)
|
||||
|
@@ -4,8 +4,9 @@ const (
|
||||
WebRunning = "Running"
|
||||
WebStopped = "Stopped"
|
||||
|
||||
DateLayout = "2006-01-02"
|
||||
DefaultDate = "1970-01-01"
|
||||
DateLayout = "2006-01-02"
|
||||
DateTimeLayout = "2006-01-02 15:04:05"
|
||||
DefaultDate = "1970-01-01"
|
||||
|
||||
ProtocolHTTP = "HTTP"
|
||||
ProtocolHTTPS = "HTTPS"
|
||||
|
@@ -118,6 +118,9 @@ func loadNetIO() {
|
||||
netStatAll2, _ := net.IOCounters(false)
|
||||
for _, net2 := range netStatAll2 {
|
||||
for _, net1 := range netStatAll {
|
||||
if net1.BytesSent == 0 || net1.BytesRecv == 0 {
|
||||
continue
|
||||
}
|
||||
if net2.Name == net1.Name {
|
||||
var itemNet model.MonitorNetwork
|
||||
itemNet.Name = net1.Name
|
||||
|
@@ -3,6 +3,7 @@ package job
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/service"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"time"
|
||||
)
|
||||
@@ -19,18 +20,18 @@ func (ssl *ssl) Run() {
|
||||
sslService := service.NewIWebsiteSSLService()
|
||||
sslList, _ := sslRepo.List()
|
||||
global.LOG.Info("ssl renew cron job start...")
|
||||
now := time.Now()
|
||||
now := time.Now().Add(10 * time.Second)
|
||||
for _, s := range sslList {
|
||||
if !s.AutoRenew || s.Provider == "manual" || s.Provider == "dnsManual" {
|
||||
continue
|
||||
}
|
||||
sum := s.ExpireDate.Sub(now)
|
||||
if sum.Hours() < 168 {
|
||||
expireDate, _ := time.ParseInLocation(constant.DateTimeLayout, s.ExpireDate.String(), time.Now().Location())
|
||||
sum := expireDate.Sub(now)
|
||||
if sum.Hours() < 720 {
|
||||
if err := sslService.Renew(s.ID); err != nil {
|
||||
global.LOG.Errorf("renew doamin [%s] ssl failed err:%s", s.PrimaryDomain, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
global.LOG.Info("ssl renew cron job end...")
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@ func NewWebsiteJob() *website {
|
||||
func (w *website) Run() {
|
||||
websites, _ := repo.NewIWebsiteRepo().List()
|
||||
global.LOG.Info("website cron job start...")
|
||||
now := time.Now()
|
||||
now := time.Now().Add(10 * time.Second)
|
||||
if len(websites) > 0 {
|
||||
neverExpireDate, _ := time.Parse(constant.DateLayout, constant.DefaultDate)
|
||||
var wg sync.WaitGroup
|
||||
@@ -28,7 +28,8 @@ func (w *website) Run() {
|
||||
if site.Status != constant.WebRunning || neverExpireDate.Equal(site.ExpireDate) {
|
||||
continue
|
||||
}
|
||||
if site.ExpireDate.Before(now) {
|
||||
expireDate, _ := time.ParseInLocation(constant.DateTimeLayout, site.ExpireDate.String(), time.Now().Location())
|
||||
if expireDate.Before(now) {
|
||||
wg.Add(1)
|
||||
go func(ws model.Website) {
|
||||
stopWebsite(ws.ID, &wg)
|
||||
|
@@ -11,35 +11,35 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func GetMsgWithMap(msg string, maps map[string]interface{}) string {
|
||||
func GetMsgWithMap(key string, maps map[string]interface{}) string {
|
||||
content := ""
|
||||
if maps == nil {
|
||||
content = ginI18n.MustGetMessage(&i18n.LocalizeConfig{
|
||||
MessageID: msg,
|
||||
MessageID: key,
|
||||
})
|
||||
} else {
|
||||
content = ginI18n.MustGetMessage(&i18n.LocalizeConfig{
|
||||
MessageID: msg,
|
||||
MessageID: key,
|
||||
TemplateData: maps,
|
||||
})
|
||||
}
|
||||
content = strings.ReplaceAll(content, ": <no value>", "")
|
||||
if content == "" {
|
||||
return msg
|
||||
return key
|
||||
} else {
|
||||
return content
|
||||
}
|
||||
}
|
||||
|
||||
func GetErrMsg(msg string, maps map[string]interface{}) string {
|
||||
func GetErrMsg(key string, maps map[string]interface{}) string {
|
||||
content := ""
|
||||
if maps == nil {
|
||||
content = ginI18n.MustGetMessage(&i18n.LocalizeConfig{
|
||||
MessageID: msg,
|
||||
MessageID: key,
|
||||
})
|
||||
} else {
|
||||
content = ginI18n.MustGetMessage(&i18n.LocalizeConfig{
|
||||
MessageID: msg,
|
||||
MessageID: key,
|
||||
TemplateData: maps,
|
||||
})
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@ ErrPortInOtherApp: "{{ .port }} port already in use by {{ .apps }}"
|
||||
ErrDbUserNotValid: "Stock database, username and password do not match!"
|
||||
ErrDockerComposeNotValid: "docker-compose file format error!"
|
||||
ErrUpdateBuWebsite: 'The application was updated successfully, but the modification of the website configuration file failed, please check the configuration!'
|
||||
Err1PanelNetworkFailed: 'Default container network creation failed! {{ .detail }}'
|
||||
|
||||
#file
|
||||
ErrFileCanNotRead: "File can not read"
|
||||
@@ -34,6 +35,7 @@ ErrPathNotFound: "Path is not found"
|
||||
ErrMovePathFailed: "The target path cannot contain the original path!"
|
||||
ErrLinkPathNotFound: "Target path does not exist!"
|
||||
ErrFileIsExit: "File already exists!"
|
||||
ErrFileUpload: "Failed to upload file"
|
||||
|
||||
#website
|
||||
ErrDomainIsExist: "Domain is already exist"
|
||||
@@ -52,4 +54,8 @@ ErrUserIsExist: "The current user already exists. Please enter a new user"
|
||||
ErrDatabaseIsExist: "The current database already exists. Please enter a new database"
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: "The recovery file type does not match the current persistence mode. Modify the file type and try again"
|
||||
ErrTypeOfRedis: "The recovery file type does not match the current persistence mode. Modify the file type and try again"
|
||||
|
||||
#container
|
||||
ErrInUsed: "{{ .detail }} is in use and cannot be deleted"
|
||||
ErrObjectInUsed: "This object is in use and cannot be deleted"
|
@@ -26,6 +26,7 @@ ErrPortInOtherApp: "{{ .port }} 端口已被 {{ .apps }}占用!"
|
||||
ErrDbUserNotValid: "存量数据库,用户名密码不匹配!"
|
||||
ErrDockerComposeNotValid: "docker-compose 文件格式错误"
|
||||
ErrUpdateBuWebsite: '应用更新成功,但是网站配置文件修改失败,请检查配置!'
|
||||
Err1PanelNetworkFailed: '默认容器网络创建失败!{{ .detail }}'
|
||||
|
||||
#file
|
||||
ErrFileCanNotRead: "此文件不支持预览"
|
||||
@@ -34,6 +35,7 @@ ErrPathNotFound: "目录不存在"
|
||||
ErrMovePathFailed: "目标路径不能包含原路径!"
|
||||
ErrLinkPathNotFound: "目标路径不存在!"
|
||||
ErrFileIsExit: "文件已存在!"
|
||||
ErrFileUpload: "上传文件失败"
|
||||
|
||||
#website
|
||||
ErrDomainIsExist: "域名已存在"
|
||||
@@ -52,4 +54,8 @@ ErrUserIsExist: "当前用户已存在,请重新输入"
|
||||
ErrDatabaseIsExist: "当前数据库已存在,请重新输入"
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后重试"
|
||||
ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后重试"
|
||||
|
||||
#container
|
||||
ErrInUsed: "{{ .detail }} 正被使用,无法删除"
|
||||
ErrObjectInUsed: "该对象正被使用,无法删除"
|
@@ -1,12 +1,11 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
||||
"path"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
)
|
||||
|
||||
@@ -23,7 +22,7 @@ func Init() {
|
||||
createDir(fileOp, dir)
|
||||
}
|
||||
|
||||
createDefaultDockerNetwork()
|
||||
_ = docker.CreateDefaultDockerNetwork()
|
||||
}
|
||||
|
||||
func createDir(fileOp files.FileOp, dirPath string) {
|
||||
@@ -31,17 +30,3 @@ func createDir(fileOp files.FileOp, dirPath string) {
|
||||
_ = fileOp.CreateDir(dirPath, 0755)
|
||||
}
|
||||
}
|
||||
|
||||
func createDefaultDockerNetwork() {
|
||||
cli, err := docker.NewClient()
|
||||
if err != nil {
|
||||
fmt.Println("init docker client error", err.Error())
|
||||
return
|
||||
}
|
||||
if !cli.NetworkExist("1panel-network") {
|
||||
if err := cli.CreateNetwork("1panel-network"); err != nil {
|
||||
fmt.Println("init docker client error", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,25 +1,35 @@
|
||||
package business
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/service"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
)
|
||||
|
||||
func Init() {
|
||||
syncApp()
|
||||
syncInstalledApp()
|
||||
}
|
||||
|
||||
func syncApp() {
|
||||
setting, err := service.NewISettingService().GetSettingInfo()
|
||||
if err != nil {
|
||||
global.LOG.Errorf("sync app error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
if setting.AppStoreVersion != "" {
|
||||
fmt.Println(setting.AppStoreVersion)
|
||||
global.LOG.Info("do not sync")
|
||||
global.LOG.Info("no need to sync")
|
||||
return
|
||||
}
|
||||
global.LOG.Info("sync app start...")
|
||||
if err := service.NewIAppService().SyncAppList(); err != nil {
|
||||
global.LOG.Errorf("sync app error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
global.LOG.Info("sync app successful")
|
||||
}
|
||||
|
||||
func syncInstalledApp() {
|
||||
if err := service.NewIAppInstalledService().SyncAll(true); err != nil {
|
||||
global.LOG.Errorf("sync instaled app error: %s", err.Error())
|
||||
}
|
||||
global.LOG.Info("sync app success")
|
||||
}
|
||||
|
@@ -2,9 +2,11 @@ package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"os"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
)
|
||||
@@ -28,6 +30,15 @@ func Init() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_ = db.Exec("PRAGMA journal_mode = WAL;")
|
||||
sqlDB, dbError := db.DB()
|
||||
if dbError != nil {
|
||||
panic(err)
|
||||
}
|
||||
sqlDB.SetConnMaxIdleTime(10)
|
||||
sqlDB.SetMaxOpenConns(100)
|
||||
sqlDB.SetConnMaxLifetime(time.Hour)
|
||||
|
||||
global.DB = db
|
||||
global.LOG.Info("init db successfully")
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@ func Init() {
|
||||
migrations.AddTableWebsite,
|
||||
migrations.AddTableDatabaseMysql,
|
||||
migrations.AddTableSnap,
|
||||
migrations.AddDefaultGroup,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
@@ -140,7 +140,6 @@ var AddTableSetting = &gormigrate.Migration{
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "SystemStatus", Value: "Free"}).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "AppStoreVersion", Value: ""}).Error; err != nil {
|
||||
@@ -211,14 +210,7 @@ var AddTableDatabaseMysql = &gormigrate.Migration{
|
||||
var AddTableWebsite = &gormigrate.Migration{
|
||||
ID: "20201009-add-table-website",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.Website{}, &model.WebsiteDomain{}, &model.WebsiteGroup{}, &model.WebsiteDnsAccount{}, &model.WebsiteSSL{}, &model.WebsiteAcmeAccount{}); err != nil {
|
||||
return err
|
||||
}
|
||||
item := &model.WebsiteGroup{
|
||||
Name: "默认",
|
||||
Default: true,
|
||||
}
|
||||
if err := tx.Create(item).Error; err != nil {
|
||||
if err := tx.AutoMigrate(&model.Website{}, &model.WebsiteDomain{}, &model.WebsiteDnsAccount{}, &model.WebsiteSSL{}, &model.WebsiteAcmeAccount{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -234,3 +226,24 @@ var AddTableSnap = &gormigrate.Migration{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var AddDefaultGroup = &gormigrate.Migration{
|
||||
ID: "2023022-change-default-group",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
defaultGroup := &model.Group{
|
||||
Name: "默认",
|
||||
IsDefault: true,
|
||||
Type: "website",
|
||||
}
|
||||
if err := tx.Create(defaultGroup).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Model(&model.Group{}).Where("name = ? AND type = ?", "default", "host").Update("name", "默认").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Model(&model.Website{}).Where("1 = 1").Update("website_group_id", defaultGroup.ID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Migrator().DropTable("website_groups")
|
||||
},
|
||||
}
|
||||
|
@@ -1,9 +1,6 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
@@ -14,6 +11,9 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
)
|
||||
|
||||
type Writer struct {
|
||||
@@ -261,7 +261,6 @@ func (w *Writer) CompressFile(logFile string) error {
|
||||
comFileName := path.Base(logFile) + ".gz"
|
||||
filePath := path.Dir(logFile)
|
||||
|
||||
fmt.Println(path.Dir(logFile))
|
||||
if err := op.Compress([]string{logFile}, filePath, comFileName, files.Gz); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -96,7 +96,6 @@ func OperationLog() gin.HandlerFunc {
|
||||
var names []string
|
||||
if funcs.IsList {
|
||||
sql := fmt.Sprintf("SELECT %s FROM %s where %s in (?);", funcs.OutputColume, funcs.DB, funcs.InputColume)
|
||||
fmt.Println(value)
|
||||
_ = global.DB.Raw(sql, value).Scan(&names)
|
||||
} else {
|
||||
_ = global.DB.Raw(fmt.Sprintf("select %s from %s where %s = ?;", funcs.OutputColume, funcs.DB, funcs.InputColume), value).Scan(&names)
|
||||
|
@@ -33,6 +33,7 @@ func (s *ContainerRouter) InitContainerRouter(Router *gin.RouterGroup) {
|
||||
|
||||
baRouter.POST("/compose/search", baseApi.SearchCompose)
|
||||
baRouter.POST("/compose", baseApi.CreateCompose)
|
||||
baRouter.POST("/compose/test", baseApi.TestCompose)
|
||||
baRouter.POST("/compose/operate", baseApi.OperatorCompose)
|
||||
baRouter.POST("/compose/update", baseApi.ComposeUpdate)
|
||||
|
||||
|
@@ -32,6 +32,7 @@ func (f *FileRouter) InitFileRouter(Router *gin.RouterGroup) {
|
||||
fileRouter.POST("/wget", baseApi.WgetFile)
|
||||
fileRouter.POST("/move", baseApi.MoveFile)
|
||||
fileRouter.POST("/download", baseApi.Download)
|
||||
fileRouter.POST("/download/bypath", baseApi.DownloadFile)
|
||||
fileRouter.POST("/size", baseApi.Size)
|
||||
fileRouter.GET("/ws", baseApi.Ws)
|
||||
fileRouter.GET("/keys", baseApi.Keys)
|
||||
|
@@ -10,14 +10,14 @@ type WebsiteGroupRouter struct {
|
||||
}
|
||||
|
||||
func (a *WebsiteGroupRouter) InitWebsiteGroupRouter(Router *gin.RouterGroup) {
|
||||
groupRouter := Router.Group("websites/groups")
|
||||
groupRouter := Router.Group("groups")
|
||||
groupRouter.Use(middleware.JwtAuth()).Use(middleware.SessionAuth()).Use(middleware.PasswordExpired())
|
||||
|
||||
baseApi := v1.ApiGroupApp.BaseApi
|
||||
{
|
||||
groupRouter.GET("", baseApi.GetWebGroups)
|
||||
groupRouter.POST("", baseApi.CreateWebGroup)
|
||||
groupRouter.POST("/update", baseApi.UpdateWebGroup)
|
||||
groupRouter.POST("/del", baseApi.DeleteWebGroup)
|
||||
groupRouter.POST("", baseApi.CreateGroup)
|
||||
groupRouter.POST("/del", baseApi.DeleteGroup)
|
||||
groupRouter.POST("/update", baseApi.UpdateGroup)
|
||||
groupRouter.POST("/search", baseApi.ListGroup)
|
||||
}
|
||||
}
|
@@ -26,11 +26,6 @@ func (s *HostRouter) InitHostRouter(Router *gin.RouterGroup) {
|
||||
hostRouter.POST("/test/byid/:id", baseApi.TestByID)
|
||||
hostRouter.GET(":id", baseApi.GetHostInfo)
|
||||
|
||||
hostRouter.POST("/group", baseApi.CreateGroup)
|
||||
hostRouter.POST("/group/del", baseApi.DeleteGroup)
|
||||
hostRouter.POST("/group/update", baseApi.UpdateGroup)
|
||||
hostRouter.POST("/group/search", baseApi.ListGroup)
|
||||
|
||||
hostRouter.GET("/command", baseApi.ListCommand)
|
||||
hostRouter.POST("/command", baseApi.CreateCommand)
|
||||
hostRouter.POST("/command/del", baseApi.DeleteCommand)
|
||||
|
@@ -51,6 +51,7 @@ func (s *SettingRouter) InitSettingRouter(Router *gin.RouterGroup) {
|
||||
settingRouter.POST("/backup/record/del", baseApi.DeleteBackupRecord)
|
||||
|
||||
settingRouter.POST("/upgrade", baseApi.Upgrade)
|
||||
settingRouter.POST("/upgrade/notes", baseApi.GetNotesByVersion)
|
||||
settingRouter.GET("/upgrade", baseApi.GetUpgradeInfo)
|
||||
settingRouter.GET("/basedir", baseApi.LoadBaseDir)
|
||||
}
|
||||
|
@@ -22,5 +22,6 @@ func (a *WebsiteSSLRouter) InitWebsiteSSLRouter(Router *gin.RouterGroup) {
|
||||
groupRouter.POST("/del", baseApi.DeleteWebsiteSSL)
|
||||
groupRouter.GET("/website/:websiteId", baseApi.GetWebsiteSSLByWebsiteId)
|
||||
groupRouter.GET("/:id", baseApi.GetWebsiteSSLById)
|
||||
groupRouter.POST("/update", baseApi.UpdateWebsiteSSL)
|
||||
}
|
||||
}
|
||||
|
@@ -77,7 +77,7 @@ func (oss ossClient) Upload(src, target string) (bool, error) {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = bucket.PutObjectFromFile(target, src)
|
||||
err = bucket.UploadFile(target, src, 200*1024*1024, osssdk.Routines(5), osssdk.Checkpoint(true, ""))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -89,7 +89,7 @@ func (oss ossClient) Download(src, target string) (bool, error) {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = bucket.GetObjectToFile(src, target)
|
||||
err = bucket.DownloadFile(src, target, 200*1024*1024, osssdk.Routines(5), osssdk.Checkpoint(true, ""))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ package docker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
@@ -73,3 +74,18 @@ func (c Client) NetworkExist(name string) bool {
|
||||
}
|
||||
return len(networks) > 0
|
||||
}
|
||||
|
||||
func CreateDefaultDockerNetwork() error {
|
||||
cli, err := NewClient()
|
||||
if err != nil {
|
||||
global.LOG.Errorf("init docker client error %s", err.Error())
|
||||
return err
|
||||
}
|
||||
if !cli.NetworkExist("1panel-network") {
|
||||
if err := cli.CreateNetwork("1panel-network"); err != nil {
|
||||
global.LOG.Errorf("create default docker network error %s", err.Error())
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -1,21 +0,0 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSSH(t *testing.T) {
|
||||
ss := ConnInfo{
|
||||
Addr: "172.16.10.111",
|
||||
Port: 22,
|
||||
User: "root",
|
||||
AuthMode: "password",
|
||||
Password: "Calong@2015",
|
||||
}
|
||||
_, err := ss.NewClient()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(ss.Run("ip a"))
|
||||
}
|
@@ -89,6 +89,7 @@ func NewPrivateKeyClient(email string, privateKey string) (*AcmeClient, error) {
|
||||
func newConfig(user *AcmeUser) *lego.Config {
|
||||
config := lego.NewConfig(user)
|
||||
config.CADirURL = "https://acme-v02.api.letsencrypt.org/directory"
|
||||
//config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
config.UserAgent = "acm_go/0.0.1"
|
||||
config.Certificate.KeyType = certcrypto.RSA2048
|
||||
return config
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/acme/api"
|
||||
"github.com/go-acme/lego/v4/certcrypto"
|
||||
@@ -154,10 +155,10 @@ func TestSSL(t *testing.T) {
|
||||
// panic(err)
|
||||
//}
|
||||
|
||||
// err = client.Challenge.SetDNS01Provider(&plainDnsProvider{}, dns01.AddDNSTimeout(6*time.Minute))
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
err = client.Challenge.SetDNS01Provider(&manualDnsProvider{}, dns01.AddDNSTimeout(6*time.Minute))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
core, err := api.New(config.HTTPClient, config.UserAgent, config.CADirURL, reg.URI, priKey)
|
||||
if err != nil {
|
||||
|
@@ -115,22 +115,12 @@ func (c *AcmeClient) UseDns(dnsType DnsType, params string) error {
|
||||
return c.Client.Challenge.SetDNS01Provider(p, dns01.AddDNSTimeout(3*time.Minute))
|
||||
}
|
||||
|
||||
func (c *AcmeClient) UseManualDns(domains []string) (*Resolve, error) {
|
||||
func (c *AcmeClient) UseManualDns() error {
|
||||
p := &manualDnsProvider{}
|
||||
if err := c.Client.Challenge.SetDNS01Provider(p, dns01.AddDNSTimeout(3*time.Minute)); err != nil {
|
||||
return nil, nil
|
||||
return err
|
||||
}
|
||||
|
||||
request := certificate.ObtainRequest{
|
||||
Domains: domains,
|
||||
Bundle: true,
|
||||
}
|
||||
|
||||
_, err := c.Client.Certificate.Obtain(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p.Resolve, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *AcmeClient) UseHTTP(path string) error {
|
||||
|
@@ -62,6 +62,25 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/apps/checkupdate": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取应用更新版本",
|
||||
"tags": [
|
||||
"App"
|
||||
],
|
||||
"summary": "Get app list update",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/apps/detail/:appId/:version": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -470,6 +489,48 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/apps/installed/params/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "修改应用参数",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"App"
|
||||
],
|
||||
"summary": "Change app params",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.AppInstalledUpdate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [],
|
||||
"bodyKeys": [
|
||||
"installId"
|
||||
],
|
||||
"formatEN": "Application param update [installId]",
|
||||
"formatZH": "应用参数修改 [installId]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/apps/installed/port/change": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -683,6 +744,20 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/auth/demo": {
|
||||
"get": {
|
||||
"description": "判断是否为demo环境",
|
||||
"tags": [
|
||||
"Auth"
|
||||
],
|
||||
"summary": "Check System isDemo",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/auth/init": {
|
||||
"post": {
|
||||
"description": "初始化用户",
|
||||
@@ -970,6 +1045,48 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/containers/compose/test": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "测试 compose 是否可用",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Container Compose"
|
||||
],
|
||||
"summary": "Test compose",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.ComposeCreate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [],
|
||||
"bodyKeys": [
|
||||
"name"
|
||||
],
|
||||
"formatEN": "check compose [name]",
|
||||
"formatZH": "检测 compose [name] 格式",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/containers/compose/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -3899,6 +4016,34 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/chunkupload": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "分片上传文件",
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "ChunkUpload file",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
"description": "request",
|
||||
"name": "file",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/compress": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -4112,6 +4257,48 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/download/bypath": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "下载指定文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "Download file with path",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.FilePath"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [],
|
||||
"bodyKeys": [
|
||||
"path"
|
||||
],
|
||||
"formatEN": "Download file [path]",
|
||||
"formatZH": "下载文件 [path]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/loadfile": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -6706,17 +6893,28 @@ var doc = `{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "系统更新信息",
|
||||
"description": "获取版本 release notes",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"System Setting"
|
||||
],
|
||||
"summary": "Load upgrade info",
|
||||
"summary": "Load release notes by version",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.Upgrade"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.UpgradeInfo"
|
||||
}
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -8256,6 +8454,57 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/ssl/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "更新 ssl",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Website SSL"
|
||||
],
|
||||
"summary": "Update ssl",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.WebsiteSSLUpdate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [
|
||||
{
|
||||
"db": "website_ssls",
|
||||
"input_colume": "id",
|
||||
"input_value": "id",
|
||||
"isList": false,
|
||||
"output_colume": "primary_domain",
|
||||
"output_value": "domain"
|
||||
}
|
||||
],
|
||||
"bodyKeys": [
|
||||
"id"
|
||||
],
|
||||
"formatEN": "Update ssl config [domain]",
|
||||
"formatZH": "更新证书设置 [domain]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/ssl/website/:websiteId": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -8623,8 +8872,7 @@ var doc = `{
|
||||
"dto.ComposeCreate": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"from",
|
||||
"name"
|
||||
"from"
|
||||
],
|
||||
"properties": {
|
||||
"file": {
|
||||
@@ -8860,9 +9108,7 @@ var doc = `{
|
||||
],
|
||||
"properties": {
|
||||
"day": {
|
||||
"type": "integer",
|
||||
"maximum": 31,
|
||||
"minimum": 1
|
||||
"type": "integer"
|
||||
},
|
||||
"dbName": {
|
||||
"type": "string"
|
||||
@@ -8871,17 +9117,13 @@ var doc = `{
|
||||
"type": "string"
|
||||
},
|
||||
"hour": {
|
||||
"type": "integer",
|
||||
"maximum": 23,
|
||||
"minimum": 0
|
||||
"type": "integer"
|
||||
},
|
||||
"keepLocal": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"minute": {
|
||||
"type": "integer",
|
||||
"maximum": 59,
|
||||
"minimum": 0
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
@@ -8942,9 +9184,7 @@ var doc = `{
|
||||
],
|
||||
"properties": {
|
||||
"day": {
|
||||
"type": "integer",
|
||||
"maximum": 31,
|
||||
"minimum": 1
|
||||
"type": "integer"
|
||||
},
|
||||
"dbName": {
|
||||
"type": "string"
|
||||
@@ -8953,9 +9193,7 @@ var doc = `{
|
||||
"type": "string"
|
||||
},
|
||||
"hour": {
|
||||
"type": "integer",
|
||||
"maximum": 23,
|
||||
"minimum": 0
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
@@ -8964,9 +9202,7 @@ var doc = `{
|
||||
"type": "boolean"
|
||||
},
|
||||
"minute": {
|
||||
"type": "integer",
|
||||
"maximum": 59,
|
||||
"minimum": 0
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
@@ -9060,15 +9296,9 @@ var doc = `{
|
||||
},
|
||||
"dto.DaemonJsonUpdateByFile": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"file": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -9254,6 +9484,12 @@ var doc = `{
|
||||
"restart",
|
||||
"stop"
|
||||
]
|
||||
},
|
||||
"stopService": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"stopSocket": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -10511,6 +10747,9 @@ var doc = `{
|
||||
"dto.UpgradeInfo": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"latestVersion": {
|
||||
"type": "string"
|
||||
},
|
||||
"newVersion": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -11042,6 +11281,22 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.AppInstalledUpdate": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"installId",
|
||||
"params"
|
||||
],
|
||||
"properties": {
|
||||
"installId": {
|
||||
"type": "integer"
|
||||
},
|
||||
"params": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.AppSearch": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -11819,6 +12074,21 @@ var doc = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteSSLUpdate": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"autoRenew",
|
||||
"id"
|
||||
],
|
||||
"properties": {
|
||||
"autoRenew": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteSearch": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -12042,10 +12312,29 @@ var doc = `{
|
||||
"response.AppParam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"label": {
|
||||
"edit": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {}
|
||||
"labelEn": {
|
||||
"type": "string"
|
||||
},
|
||||
"labelZh": {
|
||||
"type": "string"
|
||||
},
|
||||
"rule": {
|
||||
"type": "string"
|
||||
},
|
||||
"showValue": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {},
|
||||
"values": {}
|
||||
}
|
||||
},
|
||||
"response.FileInfo": {
|
||||
@@ -12185,6 +12474,9 @@ var doc = `{
|
||||
"appInstallId": {
|
||||
"type": "integer"
|
||||
},
|
||||
"appName": {
|
||||
"type": "string"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@@ -48,6 +48,25 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/apps/checkupdate": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取应用更新版本",
|
||||
"tags": [
|
||||
"App"
|
||||
],
|
||||
"summary": "Get app list update",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/apps/detail/:appId/:version": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -456,6 +475,48 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/apps/installed/params/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "修改应用参数",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"App"
|
||||
],
|
||||
"summary": "Change app params",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.AppInstalledUpdate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [],
|
||||
"bodyKeys": [
|
||||
"installId"
|
||||
],
|
||||
"formatEN": "Application param update [installId]",
|
||||
"formatZH": "应用参数修改 [installId]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/apps/installed/port/change": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -669,6 +730,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/auth/demo": {
|
||||
"get": {
|
||||
"description": "判断是否为demo环境",
|
||||
"tags": [
|
||||
"Auth"
|
||||
],
|
||||
"summary": "Check System isDemo",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/auth/init": {
|
||||
"post": {
|
||||
"description": "初始化用户",
|
||||
@@ -956,6 +1031,48 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/containers/compose/test": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "测试 compose 是否可用",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Container Compose"
|
||||
],
|
||||
"summary": "Test compose",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.ComposeCreate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [],
|
||||
"bodyKeys": [
|
||||
"name"
|
||||
],
|
||||
"formatEN": "check compose [name]",
|
||||
"formatZH": "检测 compose [name] 格式",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/containers/compose/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -3885,6 +4002,34 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/chunkupload": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "分片上传文件",
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "ChunkUpload file",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "file",
|
||||
"description": "request",
|
||||
"name": "file",
|
||||
"in": "formData",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/compress": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -4098,6 +4243,48 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/download/bypath": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "下载指定文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "Download file with path",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.FilePath"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [],
|
||||
"bodyKeys": [
|
||||
"path"
|
||||
],
|
||||
"formatEN": "Download file [path]",
|
||||
"formatZH": "下载文件 [path]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/loadfile": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -6692,17 +6879,28 @@
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "系统更新信息",
|
||||
"description": "获取版本 release notes",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"System Setting"
|
||||
],
|
||||
"summary": "Load upgrade info",
|
||||
"summary": "Load release notes by version",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.Upgrade"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.UpgradeInfo"
|
||||
}
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -8242,6 +8440,57 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/ssl/update": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "更新 ssl",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Website SSL"
|
||||
],
|
||||
"summary": "Update ssl",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/request.WebsiteSSLUpdate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [
|
||||
{
|
||||
"db": "website_ssls",
|
||||
"input_colume": "id",
|
||||
"input_value": "id",
|
||||
"isList": false,
|
||||
"output_colume": "primary_domain",
|
||||
"output_value": "domain"
|
||||
}
|
||||
],
|
||||
"bodyKeys": [
|
||||
"id"
|
||||
],
|
||||
"formatEN": "Update ssl config [domain]",
|
||||
"formatZH": "更新证书设置 [domain]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/websites/ssl/website/:websiteId": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -8609,8 +8858,7 @@
|
||||
"dto.ComposeCreate": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"from",
|
||||
"name"
|
||||
"from"
|
||||
],
|
||||
"properties": {
|
||||
"file": {
|
||||
@@ -8846,9 +9094,7 @@
|
||||
],
|
||||
"properties": {
|
||||
"day": {
|
||||
"type": "integer",
|
||||
"maximum": 31,
|
||||
"minimum": 1
|
||||
"type": "integer"
|
||||
},
|
||||
"dbName": {
|
||||
"type": "string"
|
||||
@@ -8857,17 +9103,13 @@
|
||||
"type": "string"
|
||||
},
|
||||
"hour": {
|
||||
"type": "integer",
|
||||
"maximum": 23,
|
||||
"minimum": 0
|
||||
"type": "integer"
|
||||
},
|
||||
"keepLocal": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"minute": {
|
||||
"type": "integer",
|
||||
"maximum": 59,
|
||||
"minimum": 0
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
@@ -8928,9 +9170,7 @@
|
||||
],
|
||||
"properties": {
|
||||
"day": {
|
||||
"type": "integer",
|
||||
"maximum": 31,
|
||||
"minimum": 1
|
||||
"type": "integer"
|
||||
},
|
||||
"dbName": {
|
||||
"type": "string"
|
||||
@@ -8939,9 +9179,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"hour": {
|
||||
"type": "integer",
|
||||
"maximum": 23,
|
||||
"minimum": 0
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
@@ -8950,9 +9188,7 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"minute": {
|
||||
"type": "integer",
|
||||
"maximum": 59,
|
||||
"minimum": 0
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
@@ -9046,15 +9282,9 @@
|
||||
},
|
||||
"dto.DaemonJsonUpdateByFile": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"file": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -9240,6 +9470,12 @@
|
||||
"restart",
|
||||
"stop"
|
||||
]
|
||||
},
|
||||
"stopService": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"stopSocket": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -10497,6 +10733,9 @@
|
||||
"dto.UpgradeInfo": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"latestVersion": {
|
||||
"type": "string"
|
||||
},
|
||||
"newVersion": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -11028,6 +11267,22 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.AppInstalledUpdate": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"installId",
|
||||
"params"
|
||||
],
|
||||
"properties": {
|
||||
"installId": {
|
||||
"type": "integer"
|
||||
},
|
||||
"params": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.AppSearch": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -11805,6 +12060,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteSSLUpdate": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"autoRenew",
|
||||
"id"
|
||||
],
|
||||
"properties": {
|
||||
"autoRenew": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.WebsiteSearch": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -12028,10 +12298,29 @@
|
||||
"response.AppParam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"label": {
|
||||
"edit": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {}
|
||||
"labelEn": {
|
||||
"type": "string"
|
||||
},
|
||||
"labelZh": {
|
||||
"type": "string"
|
||||
},
|
||||
"rule": {
|
||||
"type": "string"
|
||||
},
|
||||
"showValue": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {},
|
||||
"values": {}
|
||||
}
|
||||
},
|
||||
"response.FileInfo": {
|
||||
@@ -12171,6 +12460,9 @@
|
||||
"appInstallId": {
|
||||
"type": "integer"
|
||||
},
|
||||
"appName": {
|
||||
"type": "string"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@@ -152,7 +152,6 @@ definitions:
|
||||
type: integer
|
||||
required:
|
||||
- from
|
||||
- name
|
||||
type: object
|
||||
dto.ComposeOperation:
|
||||
properties:
|
||||
@@ -294,22 +293,16 @@ definitions:
|
||||
dto.CronjobCreate:
|
||||
properties:
|
||||
day:
|
||||
maximum: 31
|
||||
minimum: 1
|
||||
type: integer
|
||||
dbName:
|
||||
type: string
|
||||
exclusionRules:
|
||||
type: string
|
||||
hour:
|
||||
maximum: 23
|
||||
minimum: 0
|
||||
type: integer
|
||||
keepLocal:
|
||||
type: boolean
|
||||
minute:
|
||||
maximum: 59
|
||||
minimum: 0
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
@@ -352,24 +345,18 @@ definitions:
|
||||
dto.CronjobUpdate:
|
||||
properties:
|
||||
day:
|
||||
maximum: 31
|
||||
minimum: 1
|
||||
type: integer
|
||||
dbName:
|
||||
type: string
|
||||
exclusionRules:
|
||||
type: string
|
||||
hour:
|
||||
maximum: 23
|
||||
minimum: 0
|
||||
type: integer
|
||||
id:
|
||||
type: integer
|
||||
keepLocal:
|
||||
type: boolean
|
||||
minute:
|
||||
maximum: 59
|
||||
minimum: 0
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
@@ -439,10 +426,6 @@ definitions:
|
||||
properties:
|
||||
file:
|
||||
type: string
|
||||
path:
|
||||
type: string
|
||||
required:
|
||||
- path
|
||||
type: object
|
||||
dto.DashboardBase:
|
||||
properties:
|
||||
@@ -564,6 +547,10 @@ definitions:
|
||||
- restart
|
||||
- stop
|
||||
type: string
|
||||
stopService:
|
||||
type: boolean
|
||||
stopSocket:
|
||||
type: boolean
|
||||
required:
|
||||
- operation
|
||||
type: object
|
||||
@@ -1402,6 +1389,8 @@ definitions:
|
||||
type: object
|
||||
dto.UpgradeInfo:
|
||||
properties:
|
||||
latestVersion:
|
||||
type: string
|
||||
newVersion:
|
||||
type: string
|
||||
releaseNote:
|
||||
@@ -1752,6 +1741,17 @@ definitions:
|
||||
- page
|
||||
- pageSize
|
||||
type: object
|
||||
request.AppInstalledUpdate:
|
||||
properties:
|
||||
installId:
|
||||
type: integer
|
||||
params:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
required:
|
||||
- installId
|
||||
- params
|
||||
type: object
|
||||
request.AppSearch:
|
||||
properties:
|
||||
name:
|
||||
@@ -2272,6 +2272,16 @@ definitions:
|
||||
- page
|
||||
- pageSize
|
||||
type: object
|
||||
request.WebsiteSSLUpdate:
|
||||
properties:
|
||||
autoRenew:
|
||||
type: boolean
|
||||
id:
|
||||
type: integer
|
||||
required:
|
||||
- autoRenew
|
||||
- id
|
||||
type: object
|
||||
request.WebsiteSearch:
|
||||
properties:
|
||||
name:
|
||||
@@ -2421,9 +2431,22 @@ definitions:
|
||||
type: object
|
||||
response.AppParam:
|
||||
properties:
|
||||
label:
|
||||
edit:
|
||||
type: boolean
|
||||
key:
|
||||
type: string
|
||||
labelEn:
|
||||
type: string
|
||||
labelZh:
|
||||
type: string
|
||||
rule:
|
||||
type: string
|
||||
showValue:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
value: {}
|
||||
values: {}
|
||||
type: object
|
||||
response.FileInfo:
|
||||
properties:
|
||||
@@ -2515,6 +2538,8 @@ definitions:
|
||||
type: string
|
||||
appInstallId:
|
||||
type: integer
|
||||
appName:
|
||||
type: string
|
||||
createdAt:
|
||||
type: string
|
||||
defaultServer:
|
||||
@@ -2628,6 +2653,17 @@ paths:
|
||||
summary: Search app by key
|
||||
tags:
|
||||
- App
|
||||
/apps/checkupdate:
|
||||
get:
|
||||
description: 获取应用更新版本
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Get app list update
|
||||
tags:
|
||||
- App
|
||||
/apps/detail/:appId/:version:
|
||||
get:
|
||||
consumes:
|
||||
@@ -2887,6 +2923,33 @@ paths:
|
||||
summary: Search params by appInstallId
|
||||
tags:
|
||||
- App
|
||||
/apps/installed/params/update:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 修改应用参数
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/request.AppInstalledUpdate'
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Change app params
|
||||
tags:
|
||||
- App
|
||||
x-panel-log:
|
||||
BeforeFuntions: []
|
||||
bodyKeys:
|
||||
- installId
|
||||
formatEN: Application param update [installId]
|
||||
formatZH: 应用参数修改 [installId]
|
||||
paramKeys: []
|
||||
/apps/installed/port/change:
|
||||
post:
|
||||
consumes:
|
||||
@@ -3022,6 +3085,15 @@ paths:
|
||||
summary: Load captcha
|
||||
tags:
|
||||
- Auth
|
||||
/auth/demo:
|
||||
get:
|
||||
description: 判断是否为demo环境
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
summary: Check System isDemo
|
||||
tags:
|
||||
- Auth
|
||||
/auth/init:
|
||||
post:
|
||||
consumes:
|
||||
@@ -3205,6 +3277,33 @@ paths:
|
||||
summary: Page composes
|
||||
tags:
|
||||
- Container Compose
|
||||
/containers/compose/test:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 测试 compose 是否可用
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/dto.ComposeCreate'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Test compose
|
||||
tags:
|
||||
- Container Compose
|
||||
x-panel-log:
|
||||
BeforeFuntions: []
|
||||
bodyKeys:
|
||||
- name
|
||||
formatEN: check compose [name]
|
||||
formatZH: 检测 compose [name] 格式
|
||||
paramKeys: []
|
||||
/containers/compose/update:
|
||||
post:
|
||||
consumes:
|
||||
@@ -5065,6 +5164,23 @@ paths:
|
||||
formatEN: Check whether file [path] exists
|
||||
formatZH: 检测文件 [path] 是否存在
|
||||
paramKeys: []
|
||||
/files/chunkupload:
|
||||
post:
|
||||
description: 分片上传文件
|
||||
parameters:
|
||||
- description: request
|
||||
in: formData
|
||||
name: file
|
||||
required: true
|
||||
type: file
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: ChunkUpload file
|
||||
tags:
|
||||
- File
|
||||
/files/compress:
|
||||
post:
|
||||
consumes:
|
||||
@@ -5202,6 +5318,33 @@ paths:
|
||||
formatEN: Download file [name]
|
||||
formatZH: 下载文件 [name]
|
||||
paramKeys: []
|
||||
/files/download/bypath:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 下载指定文件
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/dto.FilePath'
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Download file with path
|
||||
tags:
|
||||
- File
|
||||
x-panel-log:
|
||||
BeforeFuntions: []
|
||||
bodyKeys:
|
||||
- path
|
||||
formatEN: Download file [path]
|
||||
formatZH: 下载文件 [path]
|
||||
paramKeys: []
|
||||
/files/loadfile:
|
||||
post:
|
||||
consumes:
|
||||
@@ -6853,15 +6996,22 @@ paths:
|
||||
paramKeys: []
|
||||
/settings/upgrade:
|
||||
get:
|
||||
description: 系统更新信息
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取版本 release notes
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/dto.Upgrade'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/dto.UpgradeInfo'
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Load upgrade info
|
||||
summary: Load release notes by version
|
||||
tags:
|
||||
- System Setting
|
||||
post:
|
||||
@@ -7840,6 +7990,39 @@ paths:
|
||||
summary: Page website ssl
|
||||
tags:
|
||||
- Website SSL
|
||||
/websites/ssl/update:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 更新 ssl
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/request.WebsiteSSLUpdate'
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Update ssl
|
||||
tags:
|
||||
- Website SSL
|
||||
x-panel-log:
|
||||
BeforeFuntions:
|
||||
- db: website_ssls
|
||||
input_colume: id
|
||||
input_value: id
|
||||
isList: false
|
||||
output_colume: primary_domain
|
||||
output_value: domain
|
||||
bodyKeys:
|
||||
- id
|
||||
formatEN: Update ssl config [domain]
|
||||
formatZH: 更新证书设置 [domain]
|
||||
paramKeys: []
|
||||
/websites/ssl/website/:websiteId:
|
||||
get:
|
||||
consumes:
|
||||
|
BIN
cmd/server/web/favicon.png
Normal file
BIN
cmd/server/web/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.1 KiB |
1
frontend/components.d.ts
vendored
1
frontend/components.d.ts
vendored
@@ -87,6 +87,7 @@ declare module 'vue' {
|
||||
SvgIcon: typeof import('./src/components/svg-icon/svg-icon.vue')['default']
|
||||
SystemUpgrade: typeof import('./src/components/system-upgrade/index.vue')['default']
|
||||
TableSetting: typeof import('./src/components/table-setting/index.vue')['default']
|
||||
Tooltip: typeof import('./src/components/tooltip/index.vue')['default']
|
||||
Upload: typeof import('./src/components/upload/index.vue')['default']
|
||||
VCharts: typeof import('./src/components/v-charts/index.vue')['default']
|
||||
}
|
||||
|
27
frontend/package-lock.json
generated
27
frontend/package-lock.json
generated
@@ -30,7 +30,6 @@
|
||||
"sass-loader": "^13.0.2",
|
||||
"screenfull": "^6.0.2",
|
||||
"unplugin-vue-define-options": "^0.7.3",
|
||||
"vite-plugin-monaco-editor": "^1.1.0",
|
||||
"vue": "^3.2.25",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-codemirror": "^6.1.1",
|
||||
@@ -10274,14 +10273,6 @@
|
||||
"entities": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vite-plugin-monaco-editor": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-monaco-editor/-/vite-plugin-monaco-editor-1.1.0.tgz",
|
||||
"integrity": "sha512-IvtUqZotrRoVqwT0PBBDIZPNraya3BxN/bfcNfnxZ5rkJiGcNtO5eAOWWSgT7zullIAEqQwxMU83yL9J5k7gww==",
|
||||
"peerDependencies": {
|
||||
"monaco-editor": ">=0.33.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vite-plugin-vue-setup-extend": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-vue-setup-extend/-/vite-plugin-vue-setup-extend-0.4.0.tgz",
|
||||
@@ -10643,9 +10634,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.75.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz",
|
||||
"integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==",
|
||||
"version": "5.76.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz",
|
||||
"integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/eslint-scope": "^3.7.3",
|
||||
@@ -18367,12 +18358,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"vite-plugin-monaco-editor": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-monaco-editor/-/vite-plugin-monaco-editor-1.1.0.tgz",
|
||||
"integrity": "sha512-IvtUqZotrRoVqwT0PBBDIZPNraya3BxN/bfcNfnxZ5rkJiGcNtO5eAOWWSgT7zullIAEqQwxMU83yL9J5k7gww==",
|
||||
"requires": {}
|
||||
},
|
||||
"vite-plugin-vue-setup-extend": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-vue-setup-extend/-/vite-plugin-vue-setup-extend-0.4.0.tgz",
|
||||
@@ -18679,9 +18664,9 @@
|
||||
}
|
||||
},
|
||||
"webpack": {
|
||||
"version": "5.75.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz",
|
||||
"integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==",
|
||||
"version": "5.76.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz",
|
||||
"integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@types/eslint-scope": "^3.7.3",
|
||||
|
@@ -42,7 +42,6 @@
|
||||
"sass-loader": "^13.0.2",
|
||||
"screenfull": "^6.0.2",
|
||||
"unplugin-vue-define-options": "^0.7.3",
|
||||
"vite-plugin-monaco-editor": "^1.1.0",
|
||||
"vue": "^3.2.25",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-codemirror": "^6.1.1",
|
||||
|
@@ -163,5 +163,7 @@ export namespace App {
|
||||
key: string;
|
||||
rule: string;
|
||||
type: string;
|
||||
values?: any;
|
||||
showValue?: string;
|
||||
}
|
||||
}
|
||||
|
@@ -9,7 +9,6 @@ export namespace Login {
|
||||
export interface MFALoginForm {
|
||||
name: string;
|
||||
password: string;
|
||||
secret: string;
|
||||
code: string;
|
||||
authMethod: string;
|
||||
}
|
||||
@@ -17,7 +16,6 @@ export namespace Login {
|
||||
name: string;
|
||||
token: string;
|
||||
mfaStatus: string;
|
||||
mfaSecret: string;
|
||||
}
|
||||
export interface InitUser {
|
||||
name: string;
|
||||
|
@@ -43,7 +43,8 @@ export namespace Container {
|
||||
state: string;
|
||||
runTime: string;
|
||||
|
||||
isFromCompose: string;
|
||||
isFromApp: boolean;
|
||||
isFromCompose: boolean;
|
||||
}
|
||||
export interface ContainerStats {
|
||||
cpuPercent: number;
|
||||
|
@@ -82,6 +82,7 @@ export namespace Setting {
|
||||
}
|
||||
export interface UpgradeInfo {
|
||||
newVersion: string;
|
||||
latestVersion: string;
|
||||
releaseNote: string;
|
||||
}
|
||||
}
|
||||
|
@@ -79,17 +79,6 @@ export namespace Website {
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface Group extends CommonModel {
|
||||
name: string;
|
||||
default: boolean;
|
||||
}
|
||||
|
||||
export interface GroupOp {
|
||||
name: string;
|
||||
id?: number;
|
||||
default: boolean;
|
||||
}
|
||||
|
||||
export interface Domain {
|
||||
websiteId: number;
|
||||
port: number;
|
||||
@@ -160,6 +149,7 @@ export namespace Website {
|
||||
startDate: string;
|
||||
provider: string;
|
||||
websites?: Website.Website[];
|
||||
autoRenew: boolean;
|
||||
}
|
||||
|
||||
export interface SSLCreate {
|
||||
@@ -179,6 +169,11 @@ export namespace Website {
|
||||
SSLId: number;
|
||||
}
|
||||
|
||||
export interface SSLUpdate {
|
||||
id: number;
|
||||
autoRenew: boolean;
|
||||
}
|
||||
|
||||
export interface AcmeAccount extends CommonModel {
|
||||
email: string;
|
||||
url: string;
|
||||
|
@@ -6,10 +6,10 @@ export const searchContainer = (params: Container.ContainerSearch) => {
|
||||
return http.post<ResPage<Container.ContainerInfo>>(`/containers/search`, params);
|
||||
};
|
||||
export const createContainer = (params: Container.ContainerCreate) => {
|
||||
return http.post(`/containers`, params);
|
||||
return http.post(`/containers`, params, 1200000);
|
||||
};
|
||||
export const logContainer = (params: Container.ContainerLogSearch) => {
|
||||
return http.post<string>(`/containers/search/log`, params);
|
||||
return http.post<string>(`/containers/search/log`, params, 400000);
|
||||
};
|
||||
export const ContainerStats = (id: string) => {
|
||||
return http.get<Container.ContainerStats>(`/containers/stats/${id}`);
|
||||
@@ -38,10 +38,10 @@ export const imagePush = (params: Container.ImagePush) => {
|
||||
return http.post<string>(`/containers/image/push`, params);
|
||||
};
|
||||
export const imageLoad = (params: Container.ImageLoad) => {
|
||||
return http.post(`/containers/image/load`, params);
|
||||
return http.post(`/containers/image/load`, params, 1200000);
|
||||
};
|
||||
export const imageSave = (params: Container.ImageSave) => {
|
||||
return http.post(`/containers/image/save`, params);
|
||||
return http.post(`/containers/image/save`, params, 1200000);
|
||||
};
|
||||
export const imageTag = (params: Container.ImageTag) => {
|
||||
return http.post(`/containers/image/tag`, params);
|
||||
@@ -117,13 +117,16 @@ export const searchCompose = (params: SearchWithPage) => {
|
||||
return http.post<ResPage<Container.ComposeInfo>>(`/containers/compose/search`, params);
|
||||
};
|
||||
export const upCompose = (params: Container.ComposeCreate) => {
|
||||
return http.post(`/containers/compose`, params);
|
||||
return http.post<string>(`/containers/compose`, params);
|
||||
};
|
||||
export const testCompose = (params: Container.ComposeCreate) => {
|
||||
return http.post<boolean>(`/containers/compose/test`, params);
|
||||
};
|
||||
export const composeOperator = (params: Container.ComposeOpration) => {
|
||||
return http.post(`/containers/compose/operate`, params);
|
||||
};
|
||||
export const composeUpdate = (params: Container.ComposeUpdate) => {
|
||||
return http.post(`/containers/compose/update`, params);
|
||||
return http.post(`/containers/compose/update`, params, 600000);
|
||||
};
|
||||
|
||||
// docker
|
||||
|
@@ -31,7 +31,7 @@ export const updateStatus = (params: Cronjob.UpdateStatus) => {
|
||||
};
|
||||
|
||||
export const download = (params: Cronjob.Download) => {
|
||||
return http.download<BlobPart>(`cronjobs/download`, params, { responseType: 'blob' });
|
||||
return http.post<string>(`cronjobs/download`, params);
|
||||
};
|
||||
|
||||
export const handleOnce = (id: number) => {
|
||||
|
@@ -1,4 +1,6 @@
|
||||
import http from '@/api';
|
||||
import { deepCopy } from '@/utils/util';
|
||||
import { Base64 } from 'js-base64';
|
||||
import { SearchWithPage, ResPage, DescriptionUpdate } from '../interface';
|
||||
import { Database } from '../interface/database';
|
||||
|
||||
@@ -7,13 +9,21 @@ export const searchMysqlDBs = (params: SearchWithPage) => {
|
||||
};
|
||||
|
||||
export const addMysqlDB = (params: Database.MysqlDBCreate) => {
|
||||
return http.post(`/databases`, params);
|
||||
let reqest = deepCopy(params) as Database.MysqlDBCreate;
|
||||
if (reqest.password) {
|
||||
reqest.password = Base64.encode(reqest.password);
|
||||
}
|
||||
return http.post(`/databases`, reqest);
|
||||
};
|
||||
export const updateMysqlAccess = (params: Database.ChangeInfo) => {
|
||||
return http.post(`/databases/change/access`, params);
|
||||
};
|
||||
export const updateMysqlPassword = (params: Database.ChangeInfo) => {
|
||||
return http.post(`/databases/change/password`, params);
|
||||
let reqest = deepCopy(params) as Database.ChangeInfo;
|
||||
if (reqest.value) {
|
||||
reqest.value = Base64.encode(reqest.value);
|
||||
}
|
||||
return http.post(`/databases/change/password`, reqest);
|
||||
};
|
||||
export const updateMysqlDescription = (params: DescriptionUpdate) => {
|
||||
return http.post(`/databases/description/update`, params);
|
||||
@@ -58,7 +68,11 @@ export const redisPersistenceConf = () => {
|
||||
return http.get<Database.RedisPersistenceConf>(`/databases/redis/persistence/conf`);
|
||||
};
|
||||
export const changeRedisPassword = (params: Database.ChangeInfo) => {
|
||||
return http.post(`/databases/redis/password`, params);
|
||||
let reqest = deepCopy(params) as Database.ChangeInfo;
|
||||
if (reqest.value) {
|
||||
reqest.value = Base64.encode(reqest.value);
|
||||
}
|
||||
return http.post(`/databases/redis/password`, reqest);
|
||||
};
|
||||
export const updateRedisPersistenceConf = (params: Database.RedisConfPersistenceUpdate) => {
|
||||
return http.post(`/databases/redis/persistence/update`, params);
|
||||
|
@@ -79,6 +79,10 @@ export const DownloadFile = (params: File.FileDownload) => {
|
||||
return http.download<BlobPart>('files/download', params, { responseType: 'blob', timeout: 20000 });
|
||||
};
|
||||
|
||||
export const DownloadByPath = (path: string) => {
|
||||
return http.download<BlobPart>('files/download/bypath', { path: path }, { responseType: 'blob', timeout: 40000 });
|
||||
};
|
||||
|
||||
export const ComputeDirSize = (params: File.DirSizeReq) => {
|
||||
return http.post<File.DirSizeRes>('files/size', params);
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user