mirror of
https://github.com/tnb-labs/panel.git
synced 2026-08-31 01:12:17 +08:00
Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b0c072f78b | |||
| 8559fb9d0c | |||
| 1bbec2b637 | |||
| 1426fb48ff | |||
| 0509397332 | |||
| 57de4cb988 | |||
| d05d3eb2aa | |||
| 876fdc419f | |||
| 3f64d81250 | |||
| c4d304f2c9 | |||
| 33d5d48b59 | |||
| d90423db4a | |||
| e032faeae0 | |||
| 70601dfb00 | |||
| c6263ebe73 | |||
| 485b7b9e8d | |||
| 4c4a605684 | |||
| a347b5470d | |||
| 0a3573bfb7 | |||
| 01620ebd1d | |||
| 57ad59093d | |||
| 4339ad7c50 | |||
| 5916ad98bd | |||
| b8ccfbb4f5 | |||
| 786985341b | |||
| 1cb5a61ff2 | |||
| f6f47785ed | |||
| 3d43a2a08f | |||
| 00ec8d693c | |||
| 1fa96e828e | |||
| c46656ed2d | |||
| 47a9e6728f | |||
| b343071ec2 | |||
| 5383623203 | |||
| 31fff122c3 | |||
| ebc0c31611 | |||
| 52e5bc6277 | |||
| 6892fcde43 | |||
| 7ef2aef377 | |||
| 4b61cad486 | |||
| ad9076162b | |||
| cf82d3c1c1 | |||
| b8f5eccf9c | |||
| 914e4e1b7b | |||
| 2fd37af6ea | |||
| 30b7a8f317 |
@@ -17,6 +17,8 @@ jobs:
|
||||
- name: Set up environment
|
||||
run: |
|
||||
cp panel-example.conf .env
|
||||
echo "DB_FILE=database/panel.db" >> .env
|
||||
go run . artisan key:generate
|
||||
go run . artisan migrate
|
||||
- name: Run tests
|
||||
run: go test ./...
|
||||
|
||||
@@ -44,7 +44,9 @@ unit_test:
|
||||
- apt-get update
|
||||
- apt-get install -y curl jq
|
||||
- cp panel-example.conf .env
|
||||
- echo "DB_FILE=database/panel.db" >> .env
|
||||
- go run . artisan key:generate
|
||||
- go run . artisan migrate
|
||||
- go test -v -coverprofile=coverage.txt -covermode=atomic ./...
|
||||
|
||||
build:
|
||||
|
||||
@@ -25,6 +25,7 @@ archives:
|
||||
strip_parent_binary_folder: true
|
||||
files:
|
||||
- LICENSE
|
||||
- docs/*
|
||||
- public/*
|
||||
- storage/*
|
||||
- database/*
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<p align="right">
|
||||
[简体中文] | [<a href="README_EN.md">English</a>]
|
||||
</p>
|
||||
|
||||
<h1 align="center">耗子 Linux 面板</h1>
|
||||
|
||||
<p align="center">
|
||||
@@ -6,25 +10,24 @@
|
||||
<a href="https://goreportcard.com/report/github.com/haozi-team/panel"><img src="https://goreportcard.com/badge/github.com/haozi-team/panel"></a>
|
||||
<a href="https://codecov.io/gh/haozi-team/panel"><img src="https://codecov.io/gh/haozi-team/panel/branch/main/graph/badge.svg?token=XFT5NGNSRG"></a>
|
||||
<a href="https://img.shields.io/github/license/haozi-team/panel"><img src="https://img.shields.io/github/license/haozi-team/panel"></a>
|
||||
<a href="https://app.fossa.com/projects/git%2Bgithub.com%2Fhaozi-team%2Fpanel?ref=badge_shield"><img src="https://app.fossa.com/api/projects/git%2Bgithub.com%2Fhaozi-team%2Fpanel.svg?type=shield" alt="FOSSA Status"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
[简体中文] | [<a href="README_EN.md">English</a>]
|
||||
</p>
|
||||
|
||||
耗子 Linux 面板是针对我们自身业务需要使用 Golang 开发的轻量 Linux 服务器运维管理面板,以 GNU Affero General Public License v3.0 开源。
|
||||
|
||||
免责声明:严禁使用耗子 Linux 面板从事任何非法活动,非法站点请勿向我们请求任何形式的技术支持,如果在技术支持过程中发现非法内容,我们将立即停止技术支持并留存相关证据。
|
||||
耗子 Linux 面板是使用 Golang + Vue 开发的轻量 Linux 服务器运维管理面板,以 GNU Affero General Public License v3.0 开源。
|
||||
|
||||
交流QQ群:[12370907](https://jq.qq.com/?_wv=1027&k=I1oJKSTH) | QQ频道:[pd.qq.com/s/fyol46wfy](https://pd.qq.com/s/fyol46wfy)
|
||||
|
||||
## 重要说明
|
||||
## 优势
|
||||
|
||||
目前我们正在重构面板前端部分开发 2.1 版本,v2.0.58 将是 2.0 的最后一个版本。
|
||||
1. **极低占用:** 在 Debian 12 下部署面板 + LNMP 环境,内存占用不到 500 MB,遥遥领先于使用容器化的其他面板。
|
||||
2. **高效运维:** 面板 UI 界面简洁,操作简单,无需繁琐的配置,即可快速部署各类环境、调整应用设置。
|
||||
3. **离线运行:** 面板运行可不依赖任何外部服务,你甚至可以在部署完成后停止面板进程,不会对已部署服务造成任何影响。
|
||||
4. **久经考验:** 我们生产环境自 2022 年即开始使用,已稳定运行 1 年无事故。
|
||||
5. **开源开放:** 面板开源,你可以自由修改、审计面板源码,安全性有保障。
|
||||
|
||||
新前端将使用 Vue + Naive UI 开发,预计 10 月底可以完成。
|
||||
## UI 截图
|
||||
|
||||
存量用户请尽快更新至 v2.0.58,以便后续升级到 2.1 版本。
|
||||

|
||||
|
||||
## 运行环境
|
||||
|
||||
@@ -47,7 +50,8 @@ CentOS Stream 可使用迁移脚本迁移至支持的系统: [CentOS 8/9 迁移
|
||||
|
||||
## 安装面板
|
||||
|
||||
安装面板前,你需要了解LNMP环境的基本知识,以及如何处理常见的LNMP环境问题,不建议0基础的用户安装和使用耗子Linux面板([推荐: 宝塔 - 简单好用服务器运维面板](https://www.bt.cn/?invite_code=M190eXRpZWE=))。
|
||||
> **Warning**
|
||||
> 安装面板前,你需要了解LNMP环境的基本知识,以及如何处理常见的LNMP环境问题,不建议0基础的用户安装和使用耗子Linux面板。
|
||||
|
||||
如果你决定继续,请以`root`用户登录服务器,执行以下命令安装面板:
|
||||
|
||||
@@ -104,10 +108,6 @@ panel
|
||||
|
||||
- [盾云CDN](http://cdn.ddunyun.com/)
|
||||
|
||||
### 对象存储
|
||||
|
||||
- [又拍云](https://www.upyun.com/?utm_source=lianmeng&utm_medium=referral)
|
||||
|
||||
### DevOps
|
||||
|
||||
- [极狐 GitLab](https://www.jihulab.com/)
|
||||
@@ -129,3 +129,7 @@ panel
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=haozi-team/panel&type=Date" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
## 免责声明
|
||||
|
||||
严禁使用耗子 Linux 面板从事任何非法活动,非法站点请勿向我们请求任何形式的技术支持,如果在技术支持过程中发现非法内容,我们将立即停止技术支持并留存相关证据。
|
||||
|
||||
+20
-12
@@ -1,3 +1,7 @@
|
||||
<p align="right">
|
||||
[<a href="README.md">简体中文</a>] | [English]
|
||||
</p>
|
||||
|
||||
<h1 align="center">HaoZi Linux Panel</h1>
|
||||
|
||||
<p align="center">
|
||||
@@ -6,18 +10,21 @@
|
||||
<a href="https://goreportcard.com/report/github.com/haozi-team/panel"><img src="https://goreportcard.com/badge/github.com/haozi-team/panel"></a>
|
||||
<a href="https://codecov.io/gh/haozi-team/panel"><img src="https://codecov.io/gh/haozi-team/panel/branch/main/graph/badge.svg?token=XFT5NGNSRG"></a>
|
||||
<a href="https://img.shields.io/github/license/haozi-team/panel"><img src="https://img.shields.io/github/license/haozi-team/panel"></a>
|
||||
<a href="https://app.fossa.com/projects/git%2Bgithub.com%2Fhaozi-team%2Fpanel?ref=badge_shield"><img src="https://app.fossa.com/api/projects/git%2Bgithub.com%2Fhaozi-team%2Fpanel.svg?type=shield" alt="FOSSA Status"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
[<a href="README.md">简体中文</a>] | [English]
|
||||
</p>
|
||||
|
||||
The HaoZi Linux Panel is a lightweight Linux server operation and maintenance management panel developed using Golang for our own business needs. It is open source under the GNU Affero General Public License v3.0 protocol.
|
||||
|
||||
Disclaimer: It is strictly prohibited to use the HaoZi Linux Panel to engage in any illegal activities. Please do not request any form of technical support from us for illegal sites. If illegal content is discovered during the technical support process, we will immediately stop technical support and retain relevant evidence.
|
||||
The HaoZi Linux Panel is a lightweight Linux server operation and maintenance management panel developed using Golang and Vue. It is open source under the GNU Affero General Public License v3.0 protocol.
|
||||
|
||||
Communication QQ group: [12370907](https://jq.qq.com/?_wv=1027&k=I1oJKSTH) | QQ channel: [pd.qq.com/s/fyol46wfy](https://pd.qq.com/s/fyol46wfy)
|
||||
|
||||
## Advantages
|
||||
|
||||
1. **Extremely low usage:** Deploying the panel + LNMP environment under Debian 12, the memory usage is less than 500 MB, far ahead of other panels using containerization.
|
||||
2. **Efficient operation and maintenance:** The panel UI interface is simple and easy to operate, and you can quickly deploy various environments and adjust application settings without complicated configuration.
|
||||
3. **Offline operation:** The panel can run without relying on any external services. You can even stop the panel process after deployment is complete, and it will not affect the deployed services.
|
||||
4. **Tested by time:** We have been using it in production environment since 2022, and it has been running stably for 1 year without any accidents.
|
||||
5. **Open source and open:** The panel is open source, you can freely modify and audit the panel source code, and the security is guaranteed.
|
||||
|
||||
## UI Screenshots
|
||||
|
||||

|
||||
@@ -43,7 +50,8 @@ As system versions are constantly updated, we may also terminate support for som
|
||||
|
||||
## Install Panel
|
||||
|
||||
Before installing the panel, you need to understand the basic knowledge of the LNMP environment and how to deal with common LNMP environment problems. It is not recommended for users with zero basic knowledge to install and use HaoZi Linux Panel ([Recommended: aaPanel - easy-to-use server operation and maintenance panel](https://aapanel.com)).
|
||||
> **Warning**
|
||||
> Before installing the panel, you need to understand the basic knowledge of the LNMP environment and how to deal with common LNMP environment problems. It is not recommended for users with zero basic knowledge to install and use HaoZi Linux Panel.
|
||||
|
||||
If you decide to continue, please log in to the server as `root` user and execute the following command to install the panel:
|
||||
|
||||
@@ -100,10 +108,6 @@ You can find or create an Issue in [Issue List](https://github.com/haozi-team/pa
|
||||
|
||||
- [盾云CDN](http://cdn.ddunyun.com/)
|
||||
|
||||
### Object Storage
|
||||
|
||||
- [又拍云](https://www.upyun.com/?utm_source=lianmeng&utm_medium=referral)
|
||||
|
||||
### DevOps
|
||||
|
||||
- [JiHu GitLab](https://www.jihulab.com/)
|
||||
@@ -125,3 +129,7 @@ This project owes its existence to all those who have contributed. To contribute
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=haozi-team/panel&type=Date" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
## Disclaimer
|
||||
|
||||
It is strictly prohibited to use the HaoZi Linux Panel to engage in any illegal activities. Please do not request any form of technical support from us for illegal sites. If illegal content is discovered during the technical support process, we will immediately stop technical support and retain relevant evidence.
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
|
||||
"github.com/goravel/framework/contracts/console"
|
||||
"github.com/goravel/framework/contracts/console/command"
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/app/services"
|
||||
)
|
||||
|
||||
type CertRenew struct {
|
||||
}
|
||||
|
||||
// Signature The name and signature of the console command.
|
||||
func (receiver *CertRenew) Signature() string {
|
||||
return "panel:cert-renew"
|
||||
}
|
||||
|
||||
// Description The console command description.
|
||||
func (receiver *CertRenew) Description() string {
|
||||
return "[面板] 证书续签"
|
||||
}
|
||||
|
||||
// Extend The console command extend.
|
||||
func (receiver *CertRenew) Extend() command.Extend {
|
||||
return command.Extend{
|
||||
Category: "panel",
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Execute the console command.
|
||||
func (receiver *CertRenew) Handle(ctx console.Context) error {
|
||||
var certs []models.Cert
|
||||
err := facades.Orm().Query().With("Website").With("User").With("DNS").Find(&certs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, cert := range certs {
|
||||
if !cert.AutoRenew {
|
||||
continue
|
||||
}
|
||||
|
||||
block, _ := pem.Decode([]byte(cert.Cert))
|
||||
if block != nil {
|
||||
data, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// 结束时间大于 7 天的证书不续签
|
||||
endTime := carbon.FromStdTime(data.NotAfter)
|
||||
if endTime.Gt(carbon.Now().AddDays(7)) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
certService := services.NewCertImpl()
|
||||
_, err = certService.Renew(cert.ID)
|
||||
if err != nil {
|
||||
facades.Log().Tags("面板", "证书管理").With(map[string]any{
|
||||
"cert_id": cert.ID,
|
||||
"error": err.Error(),
|
||||
}).Errorf("证书续签失败")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -56,7 +56,7 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
settings := []models.Setting{{Key: models.SettingKeyName, Value: "耗子Linux面板"}, {Key: models.SettingKeyMonitor, Value: "1"}, {Key: models.SettingKeyMonitorDays, Value: "30"}, {Key: models.SettingKeyBackupPath, Value: "/www/backup"}, {Key: models.SettingKeyWebsitePath, Value: "/www/wwwroot"}, {Key: models.SettingKeyEntrance, Value: "/"}, {Key: models.SettingKeyVersion, Value: facades.Config().GetString("panel.version")}}
|
||||
settings := []models.Setting{{Key: models.SettingKeyName, Value: "耗子Linux面板"}, {Key: models.SettingKeyMonitor, Value: "1"}, {Key: models.SettingKeyMonitorDays, Value: "30"}, {Key: models.SettingKeyBackupPath, Value: "/www/backup"}, {Key: models.SettingKeyWebsitePath, Value: "/www/wwwroot"}, {Key: models.SettingKeyVersion, Value: facades.Config().GetString("panel.version")}}
|
||||
err = facades.Orm().Query().Create(&settings)
|
||||
if err != nil {
|
||||
color.Redln("初始化失败")
|
||||
@@ -130,21 +130,18 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
color.Greenln("用户名: " + user.Username)
|
||||
color.Greenln("密码: " + password)
|
||||
color.Greenln("面板端口: " + port)
|
||||
color.Greenln("面板入口: " + services.NewSettingImpl().Get(models.SettingKeyEntrance, "/"))
|
||||
color.Greenln("面板入口: " + facades.Config().GetString("http.entrance"))
|
||||
|
||||
case "getPort":
|
||||
port := tools.Exec("cat /www/panel/panel.conf | grep APP_PORT | awk -F '=' '{print $2}'")
|
||||
color.Greenln("面板端口: " + port)
|
||||
|
||||
case "getEntrance":
|
||||
color.Greenln("面板入口: " + services.NewSettingImpl().Get(models.SettingKeyEntrance, "/"))
|
||||
color.Greenln("面板入口: " + facades.Config().GetString("http.entrance"))
|
||||
|
||||
case "deleteEntrance":
|
||||
err := services.NewSettingImpl().Set(models.SettingKeyEntrance, "/")
|
||||
if err != nil {
|
||||
color.Redln("删除面板入口失败")
|
||||
return nil
|
||||
}
|
||||
oldEntrance := tools.Exec(`cat /www/panel/panel.conf | grep APP_ENTRANCE | awk -F '=' '{print $2}' | tr -d '\n'`)
|
||||
tools.Exec("sed -i 's!APP_ENTRANCE=" + oldEntrance + "!APP_ENTRANCE=/!g' /www/panel/panel.conf")
|
||||
|
||||
color.Greenln("删除面板入口成功")
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ type Kernel struct {
|
||||
func (kernel *Kernel) Schedule() []schedule.Event {
|
||||
return []schedule.Event{
|
||||
facades.Schedule().Command("panel:monitoring").EveryMinute().SkipIfStillRunning(),
|
||||
facades.Schedule().Command("panel:cert-renew").Daily().SkipIfStillRunning(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,5 +22,6 @@ func (kernel *Kernel) Commands() []console.Command {
|
||||
return []console.Command{
|
||||
&commands.Panel{},
|
||||
&commands.Monitoring{},
|
||||
&commands.CertRenew{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/services"
|
||||
"panel/pkg/tools"
|
||||
)
|
||||
|
||||
type AssetController struct {
|
||||
setting services.Setting
|
||||
}
|
||||
|
||||
func NewAssetController() *AssetController {
|
||||
return &AssetController{
|
||||
setting: services.NewSettingImpl(),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *AssetController) Index(ctx http.Context) http.Response {
|
||||
entrance := facades.Config().GetString("http.entrance")
|
||||
if entrance == "/" {
|
||||
entrance = ""
|
||||
}
|
||||
|
||||
// 自动纠正 URL 格式
|
||||
if ctx.Request().Path() == entrance && ctx.Request().Path() != "/" {
|
||||
return ctx.Response().Redirect(http.StatusMovedPermanently, ctx.Request().Path()+"/")
|
||||
}
|
||||
// 拒绝访问非入口文件
|
||||
if !strings.HasPrefix(ctx.Request().Path(), entrance) {
|
||||
return ctx.Response().Status(http.StatusNotFound).String(http.StatusText(http.StatusNotFound))
|
||||
}
|
||||
|
||||
path := strings.TrimPrefix(ctx.Request().Path(), entrance)
|
||||
// 设置默认首页
|
||||
if path == "/" || path == "" {
|
||||
path = "/index.html"
|
||||
}
|
||||
|
||||
if !tools.Exists("public" + path) {
|
||||
return ctx.Response().Status(http.StatusNotFound).String(http.StatusText(http.StatusNotFound))
|
||||
}
|
||||
|
||||
file, err := os.Open("public" + path)
|
||||
if err != nil {
|
||||
return ctx.Response().Status(http.StatusInternalServerError).String(http.StatusText(http.StatusInternalServerError))
|
||||
}
|
||||
|
||||
stat, err := file.Stat()
|
||||
if err != nil {
|
||||
return ctx.Response().Status(http.StatusInternalServerError).String(http.StatusText(http.StatusInternalServerError))
|
||||
}
|
||||
|
||||
if stat.IsDir() {
|
||||
return ctx.Response().Status(http.StatusForbidden).String(http.StatusText(http.StatusForbidden))
|
||||
}
|
||||
|
||||
return ctx.Response().Header("Cache-Control", "no-cache").File("public" + path)
|
||||
}
|
||||
|
||||
func (r *AssetController) Favicon(ctx http.Context) http.Response {
|
||||
return ctx.Response().File("public/favicon.png")
|
||||
}
|
||||
|
||||
func (r *AssetController) Robots(ctx http.Context) http.Response {
|
||||
return ctx.Response().File("public/robots.txt")
|
||||
}
|
||||
|
||||
func (r *AssetController) NotFound(ctx http.Context) http.Response {
|
||||
return ctx.Response().Status(http.StatusNotFound).String(http.StatusText(http.StatusNotFound))
|
||||
}
|
||||
@@ -0,0 +1,686 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
requests "panel/app/http/requests/cert"
|
||||
commonrequests "panel/app/http/requests/common"
|
||||
responses "panel/app/http/responses/cert"
|
||||
"panel/app/models"
|
||||
"panel/app/services"
|
||||
"panel/pkg/acme"
|
||||
)
|
||||
|
||||
type CertController struct {
|
||||
cron services.Cron
|
||||
cert services.Cert
|
||||
}
|
||||
|
||||
func NewCertController() *CertController {
|
||||
return &CertController{
|
||||
cron: services.NewCronImpl(),
|
||||
cert: services.NewCertImpl(),
|
||||
}
|
||||
}
|
||||
|
||||
// CAProviders
|
||||
// @Summary 获取 CA 提供商
|
||||
// @Description 获取面板证书管理支持的 CA 提供商
|
||||
// @Tags 证书管理
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Router /panel/cert/caProviders [get]
|
||||
func (r *CertController) CAProviders(ctx http.Context) http.Response {
|
||||
return Success(ctx, []map[string]string{
|
||||
{
|
||||
"name": "Let's Encrypt",
|
||||
"ca": "letsencrypt",
|
||||
},
|
||||
{
|
||||
"name": "ZeroSSL",
|
||||
"ca": "zerossl",
|
||||
},
|
||||
{
|
||||
"name": "SSL.com",
|
||||
"ca": "sslcom",
|
||||
},
|
||||
{
|
||||
"name": "Google",
|
||||
"ca": "google",
|
||||
},
|
||||
{
|
||||
"name": "Buypass",
|
||||
"ca": "buypass",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// DNSProviders
|
||||
// @Summary 获取 DNS 提供商
|
||||
// @Description 获取面板证书管理支持的 DNS 提供商
|
||||
// @Tags 证书管理
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Router /panel/cert/dnsProviders [get]
|
||||
func (r *CertController) DNSProviders(ctx http.Context) http.Response {
|
||||
return Success(ctx, []map[string]any{
|
||||
{
|
||||
"name": "DNSPod",
|
||||
"dns": acme.DnsPod,
|
||||
},
|
||||
{
|
||||
"name": "阿里云",
|
||||
"dns": acme.AliYun,
|
||||
},
|
||||
{
|
||||
"name": "CloudFlare",
|
||||
"dns": acme.CloudFlare,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Algorithms
|
||||
// @Summary 获取算法列表
|
||||
// @Description 获取面板证书管理支持的算法列表
|
||||
// @Tags 证书管理
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Router /panel/cert/algorithms [get]
|
||||
func (r *CertController) Algorithms(ctx http.Context) http.Response {
|
||||
return Success(ctx, []map[string]any{
|
||||
{
|
||||
"name": "EC256",
|
||||
"key": acme.KeyEC256,
|
||||
},
|
||||
{
|
||||
"name": "EC384",
|
||||
"key": acme.KeyEC384,
|
||||
},
|
||||
{
|
||||
"name": "RSA2048",
|
||||
"key": acme.KeyRSA2048,
|
||||
},
|
||||
{
|
||||
"name": "RSA4096",
|
||||
"key": acme.KeyRSA4096,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// UserList
|
||||
// @Summary 获取用户列表
|
||||
// @Description 获取面板证书管理的 ACME 用户列表
|
||||
// @Tags 证书管理
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Success 200 {object} SuccessResponse{data=responses.CertList}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/users [get]
|
||||
func (r *CertController) UserList(ctx http.Context) http.Response {
|
||||
var paginateRequest commonrequests.Paginate
|
||||
sanitize := Sanitize(ctx, &paginateRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
var users []models.CertUser
|
||||
var total int64
|
||||
err := facades.Orm().Query().Paginate(paginateRequest.Page, paginateRequest.Limit, &users, &total)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("获取ACME用户列表失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, &responses.UserList{
|
||||
Total: total,
|
||||
Items: users,
|
||||
})
|
||||
}
|
||||
|
||||
// UserStore
|
||||
// @Summary 添加 ACME 用户
|
||||
// @Description 添加 ACME 用户到面板证书管理
|
||||
// @Tags 证书管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.UserStore true "用户信息"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/users [post]
|
||||
func (r *CertController) UserStore(ctx http.Context) http.Response {
|
||||
var storeRequest requests.UserStore
|
||||
sanitize := Sanitize(ctx, &storeRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
err := r.cert.UserStore(storeRequest)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("添加ACME用户失败")
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// UserUpdate
|
||||
// @Summary 更新 ACME 用户
|
||||
// @Description 更新面板证书管理的 ACME 用户
|
||||
// @Tags 证书管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "用户 ID"
|
||||
// @Param data body requests.UserUpdate true "用户信息"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/users/{id} [put]
|
||||
func (r *CertController) UserUpdate(ctx http.Context) http.Response {
|
||||
var updateRequest requests.UserUpdate
|
||||
sanitize := Sanitize(ctx, &updateRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
err := r.cert.UserUpdate(updateRequest)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"userID": updateRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("更新ACME用户失败")
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// UserShow
|
||||
// @Summary 获取 ACME 用户
|
||||
// @Description 获取面板证书管理的 ACME 用户
|
||||
// @Tags 证书管理
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "用户 ID"
|
||||
// @Success 200 {object} SuccessResponse{data=models.CertUser}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/users/{id} [get]
|
||||
func (r *CertController) UserShow(ctx http.Context) http.Response {
|
||||
var showAndDestroyRequest requests.UserShowAndDestroy
|
||||
sanitize := Sanitize(ctx, &showAndDestroyRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
user, err := r.cert.UserShow(showAndDestroyRequest.ID)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"userID": showAndDestroyRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("获取ACME用户失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, user)
|
||||
}
|
||||
|
||||
// UserDestroy
|
||||
// @Summary 删除 ACME 用户
|
||||
// @Description 删除面板证书管理的 ACME 用户
|
||||
// @Tags 证书管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "用户 ID"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/users/{id} [delete]
|
||||
func (r *CertController) UserDestroy(ctx http.Context) http.Response {
|
||||
var showAndDestroyRequest requests.UserShowAndDestroy
|
||||
sanitize := Sanitize(ctx, &showAndDestroyRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
err := r.cert.UserDestroy(showAndDestroyRequest.ID)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"userID": showAndDestroyRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("删除ACME用户失败")
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// DNSList
|
||||
// @Summary 获取 DNS 接口列表
|
||||
// @Description 获取面板证书管理的 DNS 接口列表
|
||||
// @Tags 证书管理
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Success 200 {object} SuccessResponse{data=responses.DNSList}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/dns [get]
|
||||
func (r *CertController) DNSList(ctx http.Context) http.Response {
|
||||
var paginateRequest commonrequests.Paginate
|
||||
sanitize := Sanitize(ctx, &paginateRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
var dns []models.CertDNS
|
||||
var total int64
|
||||
err := facades.Orm().Query().Paginate(paginateRequest.Page, paginateRequest.Limit, &dns, &total)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("获取DNS接口列表失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, &responses.DNSList{
|
||||
Total: total,
|
||||
Items: dns,
|
||||
})
|
||||
}
|
||||
|
||||
// DNSStore
|
||||
// @Summary 添加 DNS 接口
|
||||
// @Description 添加 DNS 接口到面板证书管理
|
||||
// @Tags 证书管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.DNSStore true "DNS 接口信息"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/dns [post]
|
||||
func (r *CertController) DNSStore(ctx http.Context) http.Response {
|
||||
var storeRequest requests.DNSStore
|
||||
sanitize := Sanitize(ctx, &storeRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
err := r.cert.DNSStore(storeRequest)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("添加DNS接口失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// DNSShow
|
||||
// @Summary 获取 DNS 接口
|
||||
// @Description 获取面板证书管理的 DNS 接口
|
||||
// @Tags 证书管理
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "DNS 接口 ID"
|
||||
// @Success 200 {object} SuccessResponse{data=models.CertDNS}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/dns/{id} [get]
|
||||
func (r *CertController) DNSShow(ctx http.Context) http.Response {
|
||||
var showAndDestroyRequest requests.DNSShowAndDestroy
|
||||
sanitize := Sanitize(ctx, &showAndDestroyRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
dns, err := r.cert.DNSShow(showAndDestroyRequest.ID)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"dnsID": showAndDestroyRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("获取DNS接口失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, dns)
|
||||
}
|
||||
|
||||
// DNSUpdate
|
||||
// @Summary 更新 DNS 接口
|
||||
// @Description 更新面板证书管理的 DNS 接口
|
||||
// @Tags 证书管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "DNS 接口 ID"
|
||||
// @Param data body requests.DNSUpdate true "DNS 接口信息"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/dns/{id} [put]
|
||||
func (r *CertController) DNSUpdate(ctx http.Context) http.Response {
|
||||
var updateRequest requests.DNSUpdate
|
||||
sanitize := Sanitize(ctx, &updateRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
err := r.cert.DNSUpdate(updateRequest)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"dnsID": updateRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("更新DNS接口失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// DNSDestroy
|
||||
// @Summary 删除 DNS 接口
|
||||
// @Description 删除面板证书管理的 DNS 接口
|
||||
// @Tags 证书管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "DNS 接口 ID"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/dns/{id} [delete]
|
||||
func (r *CertController) DNSDestroy(ctx http.Context) http.Response {
|
||||
var showAndDestroyRequest requests.DNSShowAndDestroy
|
||||
sanitize := Sanitize(ctx, &showAndDestroyRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
err := r.cert.DNSDestroy(showAndDestroyRequest.ID)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"dnsID": showAndDestroyRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("删除DNS接口失败")
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// CertList
|
||||
// @Summary 获取证书列表
|
||||
// @Description 获取面板证书管理的证书列表
|
||||
// @Tags 证书管理
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Success 200 {object} SuccessResponse{data=responses.CertList}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/certs [get]
|
||||
func (r *CertController) CertList(ctx http.Context) http.Response {
|
||||
var paginateRequest commonrequests.Paginate
|
||||
sanitize := Sanitize(ctx, &paginateRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
var certs []models.Cert
|
||||
var total int64
|
||||
err := facades.Orm().Query().With("Website").With("User").With("DNS").Paginate(paginateRequest.Page, paginateRequest.Limit, &certs, &total)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("获取证书列表失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, &responses.CertList{
|
||||
Total: total,
|
||||
Items: certs,
|
||||
})
|
||||
}
|
||||
|
||||
// CertStore
|
||||
// @Summary 添加证书
|
||||
// @Description 添加证书到面板证书管理
|
||||
// @Tags 证书管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.CertStore true "证书信息"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/certs [post]
|
||||
func (r *CertController) CertStore(ctx http.Context) http.Response {
|
||||
var storeRequest requests.CertStore
|
||||
sanitize := Sanitize(ctx, &storeRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
err := r.cert.CertStore(storeRequest)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("添加证书失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// CertUpdate
|
||||
// @Summary 更新证书
|
||||
// @Description 更新面板证书管理的证书
|
||||
// @Tags 证书管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "证书 ID"
|
||||
// @Param data body requests.CertUpdate true "证书信息"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/certs/{id} [put]
|
||||
func (r *CertController) CertUpdate(ctx http.Context) http.Response {
|
||||
var updateRequest requests.CertUpdate
|
||||
sanitize := Sanitize(ctx, &updateRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
err := r.cert.CertUpdate(updateRequest)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"certID": updateRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("更新证书失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// CertShow
|
||||
// @Summary 获取证书
|
||||
// @Description 获取面板证书管理的证书
|
||||
// @Tags 证书管理
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "证书 ID"
|
||||
// @Success 200 {object} SuccessResponse{data=models.Cert}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/certs/{id} [get]
|
||||
func (r *CertController) CertShow(ctx http.Context) http.Response {
|
||||
var showAndDestroyRequest requests.CertShowAndDestroy
|
||||
sanitize := Sanitize(ctx, &showAndDestroyRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
cert, err := r.cert.CertShow(showAndDestroyRequest.ID)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"certID": showAndDestroyRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("获取证书失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, cert)
|
||||
}
|
||||
|
||||
// CertDestroy
|
||||
// @Summary 删除证书
|
||||
// @Description 删除面板证书管理的证书
|
||||
// @Tags 证书管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "证书 ID"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/certs/{id} [delete]
|
||||
func (r *CertController) CertDestroy(ctx http.Context) http.Response {
|
||||
var showAndDestroyRequest requests.CertShowAndDestroy
|
||||
sanitize := Sanitize(ctx, &showAndDestroyRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
err := r.cert.CertDestroy(showAndDestroyRequest.ID)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"certID": showAndDestroyRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("删除证书失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// Obtain
|
||||
// @Summary 签发证书
|
||||
// @Description 签发面板证书管理的证书
|
||||
// @Tags 证书管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.Obtain true "证书信息"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/obtain [post]
|
||||
func (r *CertController) Obtain(ctx http.Context) http.Response {
|
||||
var obtainRequest requests.Obtain
|
||||
sanitize := Sanitize(ctx, &obtainRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
cert, err := r.cert.CertShow(obtainRequest.ID)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"certID": obtainRequest.ID,
|
||||
"error": err.Error(),
|
||||
}).Error("获取证书失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
if cert.DNS != nil || cert.Website != nil {
|
||||
_, err = r.cert.ObtainAuto(obtainRequest.ID)
|
||||
} else {
|
||||
_, err = r.cert.ObtainManual(obtainRequest.ID)
|
||||
}
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("签发证书失败")
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// Renew
|
||||
// @Summary 续签证书
|
||||
// @Description 续签面板证书管理的证书
|
||||
// @Tags 证书管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.Renew true "证书信息"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/renew [post]
|
||||
func (r *CertController) Renew(ctx http.Context) http.Response {
|
||||
var renewRequest requests.Renew
|
||||
sanitize := Sanitize(ctx, &renewRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
_, err := r.cert.Renew(renewRequest.ID)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("续签证书失败")
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
// ManualDNS
|
||||
// @Summary 获取手动 DNS 记录
|
||||
// @Description 获取签发证书所需的 DNS 记录
|
||||
// @Tags 证书管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.Obtain true "证书信息"
|
||||
// @Success 200 {object} SuccessResponse{data=map[string]acme.Resolve}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/cert/manualDNS [post]
|
||||
func (r *CertController) ManualDNS(ctx http.Context) http.Response {
|
||||
var obtainRequest requests.Obtain
|
||||
sanitize := Sanitize(ctx, &obtainRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
resolves, err := r.cert.ManualDNS(obtainRequest.ID)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("获取手动DNS记录失败")
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return Success(ctx, resolves)
|
||||
}
|
||||
@@ -9,21 +9,57 @@ import (
|
||||
"panel/app/services"
|
||||
)
|
||||
|
||||
// SuccessResponse 通用成功响应
|
||||
type SuccessResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data any `json:"data"`
|
||||
}
|
||||
|
||||
// ErrorResponse 通用错误响应
|
||||
type ErrorResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// Success 响应成功
|
||||
func Success(ctx http.Context, data any) http.Response {
|
||||
return ctx.Response().Success().Json(http.Json{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": data,
|
||||
return ctx.Response().Success().Json(&SuccessResponse{
|
||||
Code: 0,
|
||||
Message: "success",
|
||||
Data: data,
|
||||
})
|
||||
}
|
||||
|
||||
func Error(ctx http.Context, code int, message any) http.Response {
|
||||
return ctx.Response().Json(http.StatusOK, http.Json{
|
||||
"code": code,
|
||||
"message": message,
|
||||
// Error 响应错误
|
||||
func Error(ctx http.Context, code int, message string) http.Response {
|
||||
return ctx.Response().Json(http.StatusOK, &ErrorResponse{
|
||||
Code: code,
|
||||
Message: message,
|
||||
})
|
||||
}
|
||||
|
||||
// ErrorSystem 响应系统错误
|
||||
func ErrorSystem(ctx http.Context) http.Response {
|
||||
return ctx.Response().Json(http.StatusOK, &ErrorResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
Message: "系统内部错误",
|
||||
})
|
||||
}
|
||||
|
||||
// Sanitize 消毒请求参数
|
||||
func Sanitize(ctx http.Context, request http.FormRequest) http.Response {
|
||||
errors, err := ctx.Request().ValidateRequest(request)
|
||||
if err != nil {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, err.Error())
|
||||
}
|
||||
if errors != nil {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, errors.One())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check 检查插件是否可用
|
||||
func Check(ctx http.Context, slug string) http.Response {
|
||||
plugin := services.NewPluginImpl().GetBySlug(slug)
|
||||
@@ -31,7 +67,7 @@ func Check(ctx http.Context, slug string) http.Response {
|
||||
installedPlugins, err := services.NewPluginImpl().AllInstalled()
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][插件] 获取已安装插件失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
if installedPlugin.Version != plugin.Version || installedPlugin.Slug != plugin.Slug {
|
||||
@@ -35,7 +35,7 @@ func (c *CronController) List(ctx http.Context) http.Response {
|
||||
err := facades.Orm().Query().Paginate(page, limit, &crons, &total)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][CronController] 查询计划任务列表失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, http.Json{
|
||||
@@ -121,7 +121,7 @@ panel cutoff ${name} ${save} 2>&1
|
||||
shellFile := strconv.Itoa(int(carbon.Now().Timestamp())) + tools.RandomString(16)
|
||||
if !tools.Write(shellDir+shellFile+".sh", shell, 0700) {
|
||||
facades.Log().Error("[面板][CronController] 创建计划任务脚本失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
tools.Exec("dos2unix " + shellDir + shellFile + ".sh")
|
||||
|
||||
@@ -136,7 +136,7 @@ panel cutoff ${name} ${save} 2>&1
|
||||
err = facades.Orm().Query().Create(&cron)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][CronController] 创建计划任务失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
c.cron.AddToSystem(cron)
|
||||
@@ -191,12 +191,12 @@ func (c *CronController) Update(ctx http.Context) http.Response {
|
||||
err = facades.Orm().Query().Save(&cron)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][CronController] 更新计划任务失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
if !tools.Write(cron.Shell, ctx.Request().Input("script"), 0644) {
|
||||
facades.Log().Error("[面板][CronController] 更新计划任务脚本失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
tools.Exec("dos2unix " + cron.Shell)
|
||||
|
||||
@@ -222,7 +222,7 @@ func (c *CronController) Delete(ctx http.Context) http.Response {
|
||||
_, err = facades.Orm().Query().Delete(&cron)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][CronController] 删除计划任务失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
@@ -250,7 +250,7 @@ func (c *CronController) Status(ctx http.Context) http.Response {
|
||||
err = facades.Orm().Query().Save(&cron)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][CronController] 更新计划任务状态失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
c.cron.DeleteFromSystem(cron)
|
||||
|
||||
@@ -39,7 +39,7 @@ func (c *InfoController) Name(ctx http.Context) http.Response {
|
||||
err := facades.Orm().Query().Where("key", "name").First(&setting)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][InfoController] 查询面板名称失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, http.Json{
|
||||
@@ -53,7 +53,7 @@ func (c *InfoController) HomePlugins(ctx http.Context) http.Response {
|
||||
err := facades.Orm().Query().Where("show", 1).Find(&plugins)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][InfoController] 查询首页插件失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
type pluginsData struct {
|
||||
@@ -119,7 +119,7 @@ func (c *InfoController) CountInfo(ctx http.Context) http.Response {
|
||||
|
||||
db, err := sql.Open("mysql", "root:"+rootPassword+"@unix(/tmp/mysql.sock)/")
|
||||
if err != nil {
|
||||
facades.Log().With(map[string]any{
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("[面板][InfoController] 获取数据库列表失败")
|
||||
databaseCount = -1
|
||||
@@ -127,7 +127,7 @@ func (c *InfoController) CountInfo(ctx http.Context) http.Response {
|
||||
defer db.Close()
|
||||
rows, err := db.Query("SHOW DATABASES")
|
||||
if err != nil {
|
||||
facades.Log().With(map[string]any{
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("[面板][InfoController] 获取数据库列表失败")
|
||||
databaseCount = -1
|
||||
@@ -199,7 +199,7 @@ func (c *InfoController) InstalledDbAndPhp(ctx http.Context) http.Response {
|
||||
var php []models.Plugin
|
||||
err := facades.Orm().Query().Where("slug like ?", "php%").Find(&php)
|
||||
if err != nil {
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
var mysql models.Plugin
|
||||
@@ -305,7 +305,7 @@ func (c *InfoController) Update(ctx http.Context) http.Response {
|
||||
|
||||
panel, err := tools.GetLatestPanelVersion()
|
||||
if err != nil {
|
||||
facades.Log().With(map[string]any{
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("[面板][InfoController] 获取最新版本失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "获取最新版本失败")
|
||||
@@ -313,7 +313,7 @@ func (c *InfoController) Update(ctx http.Context) http.Response {
|
||||
|
||||
err = tools.UpdatePanel(panel)
|
||||
if err != nil {
|
||||
facades.Log().With(map[string]any{
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("[面板][InfoController] 更新面板失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "更新失败: "+err.Error())
|
||||
|
||||
@@ -27,7 +27,7 @@ func (r *MonitorController) Switch(ctx http.Context) http.Response {
|
||||
err := r.setting.Set(models.SettingKeyMonitor, cast.ToString(value))
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][MonitorController] 更新监控开关失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
@@ -39,7 +39,7 @@ func (r *MonitorController) SaveDays(ctx http.Context) http.Response {
|
||||
err := r.setting.Set(models.SettingKeyMonitorDays, days)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][MonitorController] 更新监控天数失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
@@ -61,7 +61,7 @@ func (r *MonitorController) Clear(ctx http.Context) http.Response {
|
||||
_, err := facades.Orm().Query().Where("1 = 1").Delete(&models.Monitor{})
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][MonitorController] 清空监控数据失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
@@ -78,7 +78,7 @@ func (r *MonitorController) List(ctx http.Context) http.Response {
|
||||
err := facades.Orm().Query().Where("created_at >= ?", startTime.ToDateTimeString()).Where("created_at <= ?", endTime.ToDateTimeString()).Get(&monitors)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][MonitorController] 查询监控数据失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
if len(monitors) == 0 {
|
||||
|
||||
@@ -27,7 +27,7 @@ func (r *PluginController) List(ctx http.Context) http.Response {
|
||||
plugins := r.plugin.All()
|
||||
installedPlugins, err := r.plugin.AllInstalled()
|
||||
if err != nil {
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
var lock sync.RWMutex
|
||||
@@ -101,7 +101,7 @@ func (r *PluginController) Install(ctx http.Context) http.Response {
|
||||
installedPlugins, err := r.plugin.AllInstalled()
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 获取已安装插件失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
if installedPlugin.ID != 0 {
|
||||
@@ -142,7 +142,7 @@ func (r *PluginController) Install(ctx http.Context) http.Response {
|
||||
task.Log = "/tmp/" + plugin.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 创建任务失败: " + err.Error())
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
r.task.Process(task.ID)
|
||||
@@ -157,7 +157,7 @@ func (r *PluginController) Uninstall(ctx http.Context) http.Response {
|
||||
installedPlugins, err := r.plugin.AllInstalled()
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 获取已安装插件失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
if installedPlugin.ID == 0 {
|
||||
@@ -198,7 +198,7 @@ func (r *PluginController) Uninstall(ctx http.Context) http.Response {
|
||||
task.Log = "/tmp/" + plugin.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 创建任务失败: " + err.Error())
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
r.task.Process(task.ID)
|
||||
@@ -213,7 +213,7 @@ func (r *PluginController) Update(ctx http.Context) http.Response {
|
||||
installedPlugins, err := r.plugin.AllInstalled()
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 获取已安装插件失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
if installedPlugin.ID == 0 {
|
||||
@@ -254,7 +254,7 @@ func (r *PluginController) Update(ctx http.Context) http.Response {
|
||||
task.Log = "/tmp/" + plugin.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 创建任务失败: " + err.Error())
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
r.task.Process(task.ID)
|
||||
@@ -269,7 +269,7 @@ func (r *PluginController) UpdateShow(ctx http.Context) http.Response {
|
||||
var plugin models.Plugin
|
||||
if err := facades.Orm().Query().Where("slug", slug).First(&plugin); err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 查询插件失败: " + err.Error())
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
if plugin.ID == 0 {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "插件未安装")
|
||||
@@ -278,7 +278,7 @@ func (r *PluginController) UpdateShow(ctx http.Context) http.Response {
|
||||
plugin.Show = show
|
||||
if err := facades.Orm().Query().Save(&plugin); err != nil {
|
||||
facades.Log().Error("[面板][PluginController] 更新插件失败: " + err.Error())
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, "操作成功")
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package plugins
|
||||
|
||||
type PHPExtension struct {
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
Description string `json:"description"`
|
||||
Installed bool `json:"installed"`
|
||||
}
|
||||
|
||||
type LoadInfo struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type Fail2banJail struct {
|
||||
Name string `json:"name"`
|
||||
Enabled bool `json:"enabled"`
|
||||
LogPath string `json:"log_path"`
|
||||
MaxRetry int `json:"max_retry"`
|
||||
FindTime int `json:"find_time"`
|
||||
BanTime int `json:"ban_time"`
|
||||
}
|
||||
|
||||
type S3fsMount struct {
|
||||
ID int64 `json:"id"`
|
||||
Path string `json:"path"`
|
||||
Bucket string `json:"bucket"`
|
||||
Url string `json:"url"`
|
||||
}
|
||||
+37
-38
@@ -1,4 +1,4 @@
|
||||
package fail2ban
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
@@ -24,17 +24,8 @@ func NewFail2banController() *Fail2banController {
|
||||
}
|
||||
}
|
||||
|
||||
type Jail struct {
|
||||
Name string `json:"name"`
|
||||
Enabled bool `json:"enabled"`
|
||||
LogPath string `json:"log_path"`
|
||||
MaxRetry int `json:"max_retry"`
|
||||
FindTime int `json:"find_time"`
|
||||
BanTime int `json:"ban_time"`
|
||||
}
|
||||
|
||||
// Status 获取运行状态
|
||||
func (c *Fail2banController) Status(ctx http.Context) http.Response {
|
||||
func (r *Fail2banController) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "fail2ban")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -53,7 +44,7 @@ func (c *Fail2banController) Status(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Reload 重载配置
|
||||
func (c *Fail2banController) Reload(ctx http.Context) http.Response {
|
||||
func (r *Fail2banController) Reload(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "fail2ban")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -73,7 +64,7 @@ func (c *Fail2banController) Reload(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Restart 重启服务
|
||||
func (c *Fail2banController) Restart(ctx http.Context) http.Response {
|
||||
func (r *Fail2banController) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "fail2ban")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -93,7 +84,7 @@ func (c *Fail2banController) Restart(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Start 启动服务
|
||||
func (c *Fail2banController) Start(ctx http.Context) http.Response {
|
||||
func (r *Fail2banController) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "fail2ban")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -113,7 +104,7 @@ func (c *Fail2banController) Start(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Stop 停止服务
|
||||
func (c *Fail2banController) Stop(ctx http.Context) http.Response {
|
||||
func (r *Fail2banController) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "fail2ban")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -133,7 +124,7 @@ func (c *Fail2banController) Stop(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// List 所有 Fail2ban 规则
|
||||
func (c *Fail2banController) List(ctx http.Context) http.Response {
|
||||
func (r *Fail2banController) List(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "fail2ban")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -151,7 +142,7 @@ func (c *Fail2banController) List(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "Fail2ban 规则为空")
|
||||
}
|
||||
|
||||
var jails []Jail
|
||||
var jails []Fail2banJail
|
||||
for i, jail := range jailList {
|
||||
if i == 0 {
|
||||
continue
|
||||
@@ -168,7 +159,7 @@ func (c *Fail2banController) List(ctx http.Context) http.Response {
|
||||
jailFindTime := regexp.MustCompile(`findtime = (.*)`).FindStringSubmatch(jailRaw)
|
||||
jailBanTime := regexp.MustCompile(`bantime = (.*)`).FindStringSubmatch(jailRaw)
|
||||
|
||||
jails = append(jails, Jail{
|
||||
jails = append(jails, Fail2banJail{
|
||||
Name: jailName,
|
||||
Enabled: jailEnabled,
|
||||
LogPath: jailLogPath[1],
|
||||
@@ -183,13 +174,16 @@ func (c *Fail2banController) List(ctx http.Context) http.Response {
|
||||
if startIndex > len(jails) {
|
||||
return controllers.Success(ctx, http.Json{
|
||||
"total": 0,
|
||||
"items": []Jail{},
|
||||
"items": []Fail2banJail{},
|
||||
})
|
||||
}
|
||||
if endIndex > len(jails) {
|
||||
endIndex = len(jails)
|
||||
}
|
||||
pagedJails := jails[startIndex:endIndex]
|
||||
if pagedJails == nil {
|
||||
pagedJails = []Fail2banJail{}
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, http.Json{
|
||||
"total": len(jails),
|
||||
@@ -198,7 +192,7 @@ func (c *Fail2banController) List(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Add 添加 Fail2ban 规则
|
||||
func (c *Fail2banController) Add(ctx http.Context) http.Response {
|
||||
func (r *Fail2banController) Add(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "fail2ban")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -210,8 +204,9 @@ func (c *Fail2banController) Add(ctx http.Context) http.Response {
|
||||
"maxretry": "required",
|
||||
"findtime": "required",
|
||||
"bantime": "required",
|
||||
"website_name": "required_if:type,website",
|
||||
"website_mode": "required_if:type,website",
|
||||
"website_path": "required_if:type,website",
|
||||
"website_path": "required_if:website_mode,path",
|
||||
})
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, err.Error())
|
||||
@@ -225,22 +220,23 @@ func (c *Fail2banController) Add(ctx http.Context) http.Response {
|
||||
jailMaxRetry := ctx.Request().Input("maxretry")
|
||||
jailFindTime := ctx.Request().Input("findtime")
|
||||
jailBanTime := ctx.Request().Input("bantime")
|
||||
jailWebsiteName := ctx.Request().Input("website_name")
|
||||
jailWebsiteMode := ctx.Request().Input("website_mode")
|
||||
jailWebsitePath := ctx.Request().Input("website_path")
|
||||
|
||||
raw := tools.Read("/etc/fail2ban/jail.local")
|
||||
if strings.Contains(raw, "["+jailName+"]") || (strings.Contains(raw, "["+jailName+"]"+"-cc") && jailWebsiteMode == "cc") || (strings.Contains(raw, "["+jailName+"]"+"-path") && jailWebsiteMode == "path") {
|
||||
if (strings.Contains(raw, "["+jailName+"]") && jailType == "service") || (strings.Contains(raw, "["+jailWebsiteName+"]"+"-cc") && jailType == "website" && jailWebsiteMode == "cc") || (strings.Contains(raw, "["+jailWebsiteName+"]"+"-path") && jailType == "website" && jailWebsiteMode == "path") {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "规则已存在")
|
||||
}
|
||||
|
||||
switch jailType {
|
||||
case "website":
|
||||
var website models.Website
|
||||
err := facades.Orm().Query().Where("name", jailName).FirstOrFail(&website)
|
||||
err := facades.Orm().Query().Where("name", jailWebsiteName).FirstOrFail(&website)
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "网站不存在")
|
||||
}
|
||||
config, err := c.website.GetConfig(int(website.ID))
|
||||
config, err := r.website.GetConfig(int(website.ID))
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "获取网站配置失败")
|
||||
}
|
||||
@@ -254,17 +250,17 @@ func (c *Fail2banController) Add(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
rule := `
|
||||
# ` + jailName + `-` + jailWebsiteMode + `-START
|
||||
[` + jailName + `-` + jailWebsiteMode + `]
|
||||
# ` + jailWebsiteName + `-` + jailWebsiteMode + `-START
|
||||
[` + jailWebsiteName + `-` + jailWebsiteMode + `]
|
||||
enabled = true
|
||||
filter = haozi-` + jailName + `-` + jailWebsiteMode + `
|
||||
filter = haozi-` + jailWebsiteName + `-` + jailWebsiteMode + `
|
||||
port = ` + ports + `
|
||||
maxretry = ` + jailMaxRetry + `
|
||||
findtime = ` + jailFindTime + `
|
||||
bantime = ` + jailBanTime + `
|
||||
action = %(action_mwl)s
|
||||
logpath = /www/wwwlogs/` + website.Name + `.log
|
||||
# ` + jailName + `-` + jailWebsiteMode + `-END
|
||||
# ` + jailWebsiteName + `-` + jailWebsiteMode + `-END
|
||||
`
|
||||
raw += rule
|
||||
tools.Write("/etc/fail2ban/jail.local", raw, 0644)
|
||||
@@ -283,7 +279,7 @@ failregex = ^<HOST>\s-.*\s` + jailWebsitePath + `.*HTTP/.*$
|
||||
ignoreregex =
|
||||
`
|
||||
}
|
||||
tools.Write("/etc/fail2ban/filter.d/haozi-"+jailName+"-"+jailWebsiteMode+".conf", filter, 0644)
|
||||
tools.Write("/etc/fail2ban/filter.d/haozi-"+jailWebsiteName+"-"+jailWebsiteMode+".conf", filter, 0644)
|
||||
|
||||
case "service":
|
||||
var logPath string
|
||||
@@ -335,7 +331,7 @@ logpath = ` + logPath + `
|
||||
}
|
||||
|
||||
// Delete 删除规则
|
||||
func (c *Fail2banController) Delete(ctx http.Context) http.Response {
|
||||
func (r *Fail2banController) Delete(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "fail2ban")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -357,13 +353,13 @@ func (c *Fail2banController) Delete(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// BanList 获取封禁列表
|
||||
func (c *Fail2banController) BanList(ctx http.Context) http.Response {
|
||||
func (r *Fail2banController) BanList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "fail2ban")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
name := ctx.Request().Query("name")
|
||||
name := ctx.Request().Input("name")
|
||||
if len(name) == 0 {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "缺少参数")
|
||||
}
|
||||
@@ -382,16 +378,19 @@ func (c *Fail2banController) BanList(ctx http.Context) http.Response {
|
||||
})
|
||||
}
|
||||
}
|
||||
if list == nil {
|
||||
list = []map[string]string{}
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, http.Json{
|
||||
"currentlyBan": currentlyBan,
|
||||
"totalBan": totalBan,
|
||||
"bannedIpList": list,
|
||||
"currently_ban": currentlyBan,
|
||||
"total_ban": totalBan,
|
||||
"baned_list": list,
|
||||
})
|
||||
}
|
||||
|
||||
// Unban 解封
|
||||
func (c *Fail2banController) Unban(ctx http.Context) http.Response {
|
||||
func (r *Fail2banController) Unban(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "fail2ban")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -408,7 +407,7 @@ func (c *Fail2banController) Unban(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SetWhiteList 设置白名单
|
||||
func (c *Fail2banController) SetWhiteList(ctx http.Context) http.Response {
|
||||
func (r *Fail2banController) SetWhiteList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "fail2ban")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -434,7 +433,7 @@ func (c *Fail2banController) SetWhiteList(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// GetWhiteList 获取白名单
|
||||
func (c *Fail2banController) GetWhiteList(ctx http.Context) http.Response {
|
||||
func (r *Fail2banController) GetWhiteList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "fail2ban")
|
||||
if check != nil {
|
||||
return check
|
||||
+46
-46
@@ -1,4 +1,4 @@
|
||||
package mysql57
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
@@ -29,7 +29,7 @@ func NewMysql57Controller() *Mysql57Controller {
|
||||
}
|
||||
|
||||
// Status 获取运行状态
|
||||
func (c *Mysql57Controller) Status(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -48,7 +48,7 @@ func (c *Mysql57Controller) Status(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Reload 重载配置
|
||||
func (c *Mysql57Controller) Reload(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) Reload(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -68,7 +68,7 @@ func (c *Mysql57Controller) Reload(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Restart 重启服务
|
||||
func (c *Mysql57Controller) Restart(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -88,7 +88,7 @@ func (c *Mysql57Controller) Restart(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Start 启动服务
|
||||
func (c *Mysql57Controller) Start(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -108,7 +108,7 @@ func (c *Mysql57Controller) Start(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Stop 停止服务
|
||||
func (c *Mysql57Controller) Stop(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -128,7 +128,7 @@ func (c *Mysql57Controller) Stop(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// GetConfig 获取配置
|
||||
func (c *Mysql57Controller) GetConfig(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) GetConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -144,7 +144,7 @@ func (c *Mysql57Controller) GetConfig(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SaveConfig 保存配置
|
||||
func (c *Mysql57Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -159,17 +159,17 @@ func (c *Mysql57Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "写入MySQL配置失败")
|
||||
}
|
||||
|
||||
return c.Restart(ctx)
|
||||
return r.Restart(ctx)
|
||||
}
|
||||
|
||||
// Load 获取负载
|
||||
func (c *Mysql57Controller) Load(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) Load(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
if len(rootPassword) == 0 {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "MySQL root密码为空")
|
||||
}
|
||||
@@ -238,7 +238,7 @@ func (c *Mysql57Controller) Load(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// ErrorLog 获取错误日志
|
||||
func (c *Mysql57Controller) ErrorLog(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) ErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -249,7 +249,7 @@ func (c *Mysql57Controller) ErrorLog(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// ClearErrorLog 清空错误日志
|
||||
func (c *Mysql57Controller) ClearErrorLog(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) ClearErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -260,7 +260,7 @@ func (c *Mysql57Controller) ClearErrorLog(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SlowLog 获取慢查询日志
|
||||
func (c *Mysql57Controller) SlowLog(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) SlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -271,7 +271,7 @@ func (c *Mysql57Controller) SlowLog(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// ClearSlowLog 清空慢查询日志
|
||||
func (c *Mysql57Controller) ClearSlowLog(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) ClearSlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -282,13 +282,13 @@ func (c *Mysql57Controller) ClearSlowLog(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// GetRootPassword 获取root密码
|
||||
func (c *Mysql57Controller) GetRootPassword(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) GetRootPassword(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
if len(rootPassword) == 0 {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "MySQL root密码为空")
|
||||
}
|
||||
@@ -297,7 +297,7 @@ func (c *Mysql57Controller) GetRootPassword(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SetRootPassword 设置root密码
|
||||
func (c *Mysql57Controller) SetRootPassword(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) SetRootPassword(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -316,11 +316,11 @@ func (c *Mysql57Controller) SetRootPassword(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "MySQL root密码不能为空")
|
||||
}
|
||||
|
||||
oldRootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
oldRootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
if oldRootPassword != rootPassword {
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + oldRootPassword + " -e \"ALTER USER 'root'@'localhost' IDENTIFIED BY '" + rootPassword + "';\"")
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + oldRootPassword + " -e \"FLUSH PRIVILEGES;\"")
|
||||
err := c.setting.Set(models.SettingKeyMysqlRootPassword, rootPassword)
|
||||
err := r.setting.Set(models.SettingKeyMysqlRootPassword, rootPassword)
|
||||
if err != nil {
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"ALTER USER 'root'@'localhost' IDENTIFIED BY '" + oldRootPassword + "';\"")
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\"")
|
||||
@@ -332,13 +332,13 @@ func (c *Mysql57Controller) SetRootPassword(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// DatabaseList 获取数据库列表
|
||||
func (c *Mysql57Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
type database struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
@@ -395,7 +395,7 @@ func (c *Mysql57Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// AddDatabase 添加数据库
|
||||
func (c *Mysql57Controller) AddDatabase(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) AddDatabase(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -413,7 +413,7 @@ func (c *Mysql57Controller) AddDatabase(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
database := ctx.Request().Input("database")
|
||||
user := ctx.Request().Input("user")
|
||||
password := ctx.Request().Input("password")
|
||||
@@ -427,7 +427,7 @@ func (c *Mysql57Controller) AddDatabase(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// DeleteDatabase 删除数据库
|
||||
func (c *Mysql57Controller) DeleteDatabase(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) DeleteDatabase(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -443,7 +443,7 @@ func (c *Mysql57Controller) DeleteDatabase(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
database := ctx.Request().Input("database")
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"DROP DATABASE IF EXISTS " + database + ";\"")
|
||||
|
||||
@@ -451,13 +451,13 @@ func (c *Mysql57Controller) DeleteDatabase(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// BackupList 获取备份列表
|
||||
func (c *Mysql57Controller) BackupList(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) BackupList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
backupList, err := c.backup.MysqlList()
|
||||
backupList, err := r.backup.MysqlList()
|
||||
if err != nil {
|
||||
facades.Log().Error("[MySQL57] 获取备份列表失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取备份列表失败")
|
||||
@@ -488,7 +488,7 @@ func (c *Mysql57Controller) BackupList(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// UploadBackup 上传备份
|
||||
func (c *Mysql57Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -499,7 +499,7 @@ func (c *Mysql57Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "上传文件失败")
|
||||
}
|
||||
|
||||
backupPath := c.setting.Get(models.SettingKeyBackupPath) + "/mysql"
|
||||
backupPath := r.setting.Get(models.SettingKeyBackupPath) + "/mysql"
|
||||
if !tools.Exists(backupPath) {
|
||||
tools.Mkdir(backupPath, 0644)
|
||||
}
|
||||
@@ -514,7 +514,7 @@ func (c *Mysql57Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// CreateBackup 创建备份
|
||||
func (c *Mysql57Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -531,7 +531,7 @@ func (c *Mysql57Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
database := ctx.Request().Input("database")
|
||||
err = c.backup.MysqlBackup(database)
|
||||
err = r.backup.MysqlBackup(database)
|
||||
if err != nil {
|
||||
facades.Log().Error("[MYSQL57] 创建备份失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "创建备份失败")
|
||||
@@ -541,7 +541,7 @@ func (c *Mysql57Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// DeleteBackup 删除备份
|
||||
func (c *Mysql57Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -557,7 +557,7 @@ func (c *Mysql57Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
backupPath := c.setting.Get(models.SettingKeyBackupPath) + "/mysql"
|
||||
backupPath := r.setting.Get(models.SettingKeyBackupPath) + "/mysql"
|
||||
fileName := ctx.Request().Input("name")
|
||||
tools.Remove(backupPath + "/" + fileName)
|
||||
|
||||
@@ -565,7 +565,7 @@ func (c *Mysql57Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// RestoreBackup 还原备份
|
||||
func (c *Mysql57Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -582,7 +582,7 @@ func (c *Mysql57Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
err = c.backup.MysqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
|
||||
err = r.backup.MysqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
|
||||
if err != nil {
|
||||
facades.Log().Error("[MYSQL57] 还原失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "还原失败: "+err.Error())
|
||||
@@ -592,7 +592,7 @@ func (c *Mysql57Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// UserList 用户列表
|
||||
func (c *Mysql57Controller) UserList(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) UserList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -604,7 +604,7 @@ func (c *Mysql57Controller) UserList(ctx http.Context) http.Response {
|
||||
Grants []string `json:"grants"`
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
db, err := sql.Open("mysql", "root:"+rootPassword+"@unix(/tmp/mysql.sock)/")
|
||||
if err != nil {
|
||||
facades.Log().Error("[MYSQL57] 连接数据库失败:" + err.Error())
|
||||
@@ -678,7 +678,7 @@ func (c *Mysql57Controller) UserList(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// AddUser 添加用户
|
||||
func (c *Mysql57Controller) AddUser(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) AddUser(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -696,7 +696,7 @@ func (c *Mysql57Controller) AddUser(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
user := ctx.Request().Input("user")
|
||||
password := ctx.Request().Input("password")
|
||||
database := ctx.Request().Input("database")
|
||||
@@ -708,7 +708,7 @@ func (c *Mysql57Controller) AddUser(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// DeleteUser 删除用户
|
||||
func (c *Mysql57Controller) DeleteUser(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) DeleteUser(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -724,7 +724,7 @@ func (c *Mysql57Controller) DeleteUser(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
user := ctx.Request().Input("user")
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"DROP USER '" + user + "'@'localhost';\"")
|
||||
|
||||
@@ -732,7 +732,7 @@ func (c *Mysql57Controller) DeleteUser(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SetUserPassword 设置用户密码
|
||||
func (c *Mysql57Controller) SetUserPassword(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) SetUserPassword(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -749,7 +749,7 @@ func (c *Mysql57Controller) SetUserPassword(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
user := ctx.Request().Input("user")
|
||||
password := ctx.Request().Input("password")
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"ALTER USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + "';\"")
|
||||
@@ -759,7 +759,7 @@ func (c *Mysql57Controller) SetUserPassword(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SetUserPrivileges 设置用户权限
|
||||
func (c *Mysql57Controller) SetUserPrivileges(ctx http.Context) http.Response {
|
||||
func (r *Mysql57Controller) SetUserPrivileges(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql57")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -776,7 +776,7 @@ func (c *Mysql57Controller) SetUserPrivileges(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
user := ctx.Request().Input("user")
|
||||
database := ctx.Request().Input("database")
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"REVOKE ALL PRIVILEGES ON *.* FROM '" + user + "'@'localhost';\"")
|
||||
+46
-46
@@ -1,4 +1,4 @@
|
||||
package mysql80
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
@@ -29,7 +29,7 @@ func NewMysql80Controller() *Mysql80Controller {
|
||||
}
|
||||
|
||||
// Status 获取运行状态
|
||||
func (c *Mysql80Controller) Status(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -48,7 +48,7 @@ func (c *Mysql80Controller) Status(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Reload 重载配置
|
||||
func (c *Mysql80Controller) Reload(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) Reload(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -68,7 +68,7 @@ func (c *Mysql80Controller) Reload(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Restart 重启服务
|
||||
func (c *Mysql80Controller) Restart(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -88,7 +88,7 @@ func (c *Mysql80Controller) Restart(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Start 启动服务
|
||||
func (c *Mysql80Controller) Start(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -108,7 +108,7 @@ func (c *Mysql80Controller) Start(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Stop 停止服务
|
||||
func (c *Mysql80Controller) Stop(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -128,7 +128,7 @@ func (c *Mysql80Controller) Stop(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// GetConfig 获取配置
|
||||
func (c *Mysql80Controller) GetConfig(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) GetConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -144,7 +144,7 @@ func (c *Mysql80Controller) GetConfig(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SaveConfig 保存配置
|
||||
func (c *Mysql80Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -159,17 +159,17 @@ func (c *Mysql80Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "写入MySQL配置失败")
|
||||
}
|
||||
|
||||
return c.Restart(ctx)
|
||||
return r.Restart(ctx)
|
||||
}
|
||||
|
||||
// Load 获取负载
|
||||
func (c *Mysql80Controller) Load(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) Load(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
if len(rootPassword) == 0 {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "MySQL root密码为空")
|
||||
}
|
||||
@@ -238,7 +238,7 @@ func (c *Mysql80Controller) Load(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// ErrorLog 获取错误日志
|
||||
func (c *Mysql80Controller) ErrorLog(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) ErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -249,7 +249,7 @@ func (c *Mysql80Controller) ErrorLog(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// ClearErrorLog 清空错误日志
|
||||
func (c *Mysql80Controller) ClearErrorLog(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) ClearErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -260,7 +260,7 @@ func (c *Mysql80Controller) ClearErrorLog(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SlowLog 获取慢查询日志
|
||||
func (c *Mysql80Controller) SlowLog(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) SlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -271,7 +271,7 @@ func (c *Mysql80Controller) SlowLog(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// ClearSlowLog 清空慢查询日志
|
||||
func (c *Mysql80Controller) ClearSlowLog(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) ClearSlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -282,13 +282,13 @@ func (c *Mysql80Controller) ClearSlowLog(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// GetRootPassword 获取root密码
|
||||
func (c *Mysql80Controller) GetRootPassword(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) GetRootPassword(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
if len(rootPassword) == 0 {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "MySQL root密码为空")
|
||||
}
|
||||
@@ -297,7 +297,7 @@ func (c *Mysql80Controller) GetRootPassword(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SetRootPassword 设置root密码
|
||||
func (c *Mysql80Controller) SetRootPassword(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) SetRootPassword(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -316,11 +316,11 @@ func (c *Mysql80Controller) SetRootPassword(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "MySQL root密码不能为空")
|
||||
}
|
||||
|
||||
oldRootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
oldRootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
if oldRootPassword != rootPassword {
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + oldRootPassword + " -e \"ALTER USER 'root'@'localhost' IDENTIFIED BY '" + rootPassword + "';\"")
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + oldRootPassword + " -e \"FLUSH PRIVILEGES;\"")
|
||||
err := c.setting.Set(models.SettingKeyMysqlRootPassword, rootPassword)
|
||||
err := r.setting.Set(models.SettingKeyMysqlRootPassword, rootPassword)
|
||||
if err != nil {
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"ALTER USER 'root'@'localhost' IDENTIFIED BY '" + oldRootPassword + "';\"")
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"FLUSH PRIVILEGES;\"")
|
||||
@@ -332,13 +332,13 @@ func (c *Mysql80Controller) SetRootPassword(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// DatabaseList 获取数据库列表
|
||||
func (c *Mysql80Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
type database struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
@@ -395,7 +395,7 @@ func (c *Mysql80Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// AddDatabase 添加数据库
|
||||
func (c *Mysql80Controller) AddDatabase(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) AddDatabase(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -413,7 +413,7 @@ func (c *Mysql80Controller) AddDatabase(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
database := ctx.Request().Input("database")
|
||||
user := ctx.Request().Input("user")
|
||||
password := ctx.Request().Input("password")
|
||||
@@ -427,7 +427,7 @@ func (c *Mysql80Controller) AddDatabase(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// DeleteDatabase 删除数据库
|
||||
func (c *Mysql80Controller) DeleteDatabase(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) DeleteDatabase(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -443,7 +443,7 @@ func (c *Mysql80Controller) DeleteDatabase(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
database := ctx.Request().Input("database")
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"DROP DATABASE IF EXISTS " + database + ";\"")
|
||||
|
||||
@@ -451,13 +451,13 @@ func (c *Mysql80Controller) DeleteDatabase(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// BackupList 获取备份列表
|
||||
func (c *Mysql80Controller) BackupList(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) BackupList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
backupList, err := c.backup.MysqlList()
|
||||
backupList, err := r.backup.MysqlList()
|
||||
if err != nil {
|
||||
facades.Log().Error("[MySQL80] 获取备份列表失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取备份列表失败")
|
||||
@@ -488,7 +488,7 @@ func (c *Mysql80Controller) BackupList(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// UploadBackup 上传备份
|
||||
func (c *Mysql80Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -499,7 +499,7 @@ func (c *Mysql80Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "上传文件失败")
|
||||
}
|
||||
|
||||
backupPath := c.setting.Get(models.SettingKeyBackupPath) + "/mysql"
|
||||
backupPath := r.setting.Get(models.SettingKeyBackupPath) + "/mysql"
|
||||
if !tools.Exists(backupPath) {
|
||||
tools.Mkdir(backupPath, 0644)
|
||||
}
|
||||
@@ -514,7 +514,7 @@ func (c *Mysql80Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// CreateBackup 创建备份
|
||||
func (c *Mysql80Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -531,7 +531,7 @@ func (c *Mysql80Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
database := ctx.Request().Input("database")
|
||||
err = c.backup.MysqlBackup(database)
|
||||
err = r.backup.MysqlBackup(database)
|
||||
if err != nil {
|
||||
facades.Log().Error("[MYSQL80] 创建备份失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "创建备份失败")
|
||||
@@ -541,7 +541,7 @@ func (c *Mysql80Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// DeleteBackup 删除备份
|
||||
func (c *Mysql80Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -557,7 +557,7 @@ func (c *Mysql80Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
backupPath := c.setting.Get(models.SettingKeyBackupPath) + "/mysql"
|
||||
backupPath := r.setting.Get(models.SettingKeyBackupPath) + "/mysql"
|
||||
fileName := ctx.Request().Input("name")
|
||||
tools.Remove(backupPath + "/" + fileName)
|
||||
|
||||
@@ -565,7 +565,7 @@ func (c *Mysql80Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// RestoreBackup 还原备份
|
||||
func (c *Mysql80Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -582,7 +582,7 @@ func (c *Mysql80Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
err = c.backup.MysqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
|
||||
err = r.backup.MysqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
|
||||
if err != nil {
|
||||
facades.Log().Error("[MYSQL80] 还原失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "还原失败: "+err.Error())
|
||||
@@ -592,7 +592,7 @@ func (c *Mysql80Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// UserList 用户列表
|
||||
func (c *Mysql80Controller) UserList(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) UserList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -604,7 +604,7 @@ func (c *Mysql80Controller) UserList(ctx http.Context) http.Response {
|
||||
Grants []string `json:"grants"`
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
db, err := sql.Open("mysql", "root:"+rootPassword+"@unix(/tmp/mysql.sock)/")
|
||||
if err != nil {
|
||||
facades.Log().Error("[MYSQL80] 连接数据库失败:" + err.Error())
|
||||
@@ -678,7 +678,7 @@ func (c *Mysql80Controller) UserList(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// AddUser 添加用户
|
||||
func (c *Mysql80Controller) AddUser(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) AddUser(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -696,7 +696,7 @@ func (c *Mysql80Controller) AddUser(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
user := ctx.Request().Input("user")
|
||||
password := ctx.Request().Input("password")
|
||||
database := ctx.Request().Input("database")
|
||||
@@ -708,7 +708,7 @@ func (c *Mysql80Controller) AddUser(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// DeleteUser 删除用户
|
||||
func (c *Mysql80Controller) DeleteUser(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) DeleteUser(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -724,7 +724,7 @@ func (c *Mysql80Controller) DeleteUser(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
user := ctx.Request().Input("user")
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"DROP USER '" + user + "'@'localhost';\"")
|
||||
|
||||
@@ -732,7 +732,7 @@ func (c *Mysql80Controller) DeleteUser(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SetUserPassword 设置用户密码
|
||||
func (c *Mysql80Controller) SetUserPassword(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) SetUserPassword(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -749,7 +749,7 @@ func (c *Mysql80Controller) SetUserPassword(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
user := ctx.Request().Input("user")
|
||||
password := ctx.Request().Input("password")
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"ALTER USER '" + user + "'@'localhost' IDENTIFIED BY '" + password + "';\"")
|
||||
@@ -759,7 +759,7 @@ func (c *Mysql80Controller) SetUserPassword(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SetUserPrivileges 设置用户权限
|
||||
func (c *Mysql80Controller) SetUserPrivileges(ctx http.Context) http.Response {
|
||||
func (r *Mysql80Controller) SetUserPrivileges(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "mysql80")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -776,7 +776,7 @@ func (c *Mysql80Controller) SetUserPrivileges(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
rootPassword := c.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
rootPassword := r.setting.Get(models.SettingKeyMysqlRootPassword)
|
||||
user := ctx.Request().Input("user")
|
||||
database := ctx.Request().Input("database")
|
||||
tools.Exec("/www/server/mysql/bin/mysql -uroot -p" + rootPassword + " -e \"REVOKE ALL PRIVILEGES ON *.* FROM '" + user + "'@'localhost';\"")
|
||||
+12
-12
@@ -1,4 +1,4 @@
|
||||
package openresty
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
@@ -24,7 +24,7 @@ func NewOpenrestyController() *OpenRestyController {
|
||||
}
|
||||
|
||||
// Status 获取运行状态
|
||||
func (c *OpenRestyController) Status(ctx http.Context) http.Response {
|
||||
func (r *OpenRestyController) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -43,7 +43,7 @@ func (c *OpenRestyController) Status(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Reload 重载配置
|
||||
func (c *OpenRestyController) Reload(ctx http.Context) http.Response {
|
||||
func (r *OpenRestyController) Reload(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -63,7 +63,7 @@ func (c *OpenRestyController) Reload(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Start 启动OpenResty
|
||||
func (c *OpenRestyController) Start(ctx http.Context) http.Response {
|
||||
func (r *OpenRestyController) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -83,7 +83,7 @@ func (c *OpenRestyController) Start(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Stop 停止OpenResty
|
||||
func (c *OpenRestyController) Stop(ctx http.Context) http.Response {
|
||||
func (r *OpenRestyController) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -103,7 +103,7 @@ func (c *OpenRestyController) Stop(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Restart 重启OpenResty
|
||||
func (c *OpenRestyController) Restart(ctx http.Context) http.Response {
|
||||
func (r *OpenRestyController) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -123,7 +123,7 @@ func (c *OpenRestyController) Restart(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// GetConfig 获取配置
|
||||
func (c *OpenRestyController) GetConfig(ctx http.Context) http.Response {
|
||||
func (r *OpenRestyController) GetConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -138,7 +138,7 @@ func (c *OpenRestyController) GetConfig(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SaveConfig 保存配置
|
||||
func (c *OpenRestyController) SaveConfig(ctx http.Context) http.Response {
|
||||
func (r *OpenRestyController) SaveConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -153,11 +153,11 @@ func (c *OpenRestyController) SaveConfig(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "保存OpenResty配置失败")
|
||||
}
|
||||
|
||||
return c.Reload(ctx)
|
||||
return r.Reload(ctx)
|
||||
}
|
||||
|
||||
// ErrorLog 获取错误日志
|
||||
func (c *OpenRestyController) ErrorLog(ctx http.Context) http.Response {
|
||||
func (r *OpenRestyController) ErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -172,7 +172,7 @@ func (c *OpenRestyController) ErrorLog(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// ClearErrorLog 清空错误日志
|
||||
func (c *OpenRestyController) ClearErrorLog(ctx http.Context) http.Response {
|
||||
func (r *OpenRestyController) ClearErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -183,7 +183,7 @@ func (c *OpenRestyController) ClearErrorLog(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Load 获取负载
|
||||
func (c *OpenRestyController) Load(ctx http.Context) http.Response {
|
||||
func (r *OpenRestyController) Load(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "openresty")
|
||||
if check != nil {
|
||||
return check
|
||||
+77
-84
@@ -1,4 +1,4 @@
|
||||
package php74
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -30,15 +30,15 @@ func NewPhp74Controller() *Php74Controller {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php74Controller) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php74Controller) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
status := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -48,17 +48,17 @@ func (c *Php74Controller) Status(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php74Controller) Reload(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php74Controller) Reload(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl reload php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl reload php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -68,17 +68,17 @@ func (c *Php74Controller) Reload(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php74Controller) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php74Controller) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl start php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl start php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -88,17 +88,17 @@ func (c *Php74Controller) Start(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php74Controller) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php74Controller) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl stop php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl stop php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status != "active" {
|
||||
@@ -108,17 +108,17 @@ func (c *Php74Controller) Stop(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php74Controller) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php74Controller) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl restart php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl restart php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -128,38 +128,38 @@ func (c *Php74Controller) Restart(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php74Controller) GetConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php74Controller) GetConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
config := tools.Read("/www/server/php/" + c.version + "/etc/php.ini")
|
||||
config := tools.Read("/www/server/php/" + r.version + "/etc/php.ini")
|
||||
return controllers.Success(ctx, config)
|
||||
}
|
||||
|
||||
func (c *Php74Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php74Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
config := ctx.Request().Input("config")
|
||||
tools.Write("/www/server/php/"+c.version+"/etc/php.ini", config, 0644)
|
||||
return c.Reload(ctx)
|
||||
tools.Write("/www/server/php/"+r.version+"/etc/php.ini", config, 0644)
|
||||
return r.Reload(ctx)
|
||||
}
|
||||
|
||||
func (c *Php74Controller) Load(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php74Controller) Load(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
client := req.C().SetTimeout(10 * time.Second)
|
||||
resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + c.version)
|
||||
resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + r.version)
|
||||
if err != nil || !resp.IsSuccessState() {
|
||||
facades.Log().Error("获取PHP-" + c.version + "运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+c.version+"] 获取运行状态失败")
|
||||
facades.Log().Error("获取PHP-" + r.version + "运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+r.version+"] 获取运行状态失败")
|
||||
}
|
||||
|
||||
raw := resp.String()
|
||||
@@ -185,65 +185,58 @@ func (c *Php74Controller) Load(ctx http.Context) http.Response {
|
||||
return controllers.Success(ctx, data)
|
||||
}
|
||||
|
||||
func (c *Php74Controller) ErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php74Controller) ErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + c.version + "/var/log/php-fpm.log"))
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log"))
|
||||
return controllers.Success(ctx, log)
|
||||
}
|
||||
|
||||
func (c *Php74Controller) SlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php74Controller) SlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + c.version + "/var/log/slow.log"))
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log"))
|
||||
return controllers.Success(ctx, log)
|
||||
}
|
||||
|
||||
func (c *Php74Controller) ClearErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php74Controller) ClearErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("echo '' > /www/server/php/" + c.version + "/var/log/php-fpm.log")
|
||||
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log")
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
|
||||
func (c *Php74Controller) ClearSlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php74Controller) ClearSlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("echo '' > /www/server/php/" + c.version + "/var/log/slow.log")
|
||||
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log")
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
|
||||
type Extension struct {
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
Description string `json:"description"`
|
||||
Installed bool `json:"installed"`
|
||||
}
|
||||
|
||||
func (c *Php74Controller) GetExtensionList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php74Controller) GetExtensionList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
extensions := c.GetExtensions()
|
||||
extensions := r.GetExtensions()
|
||||
return controllers.Success(ctx, extensions)
|
||||
}
|
||||
|
||||
func (c *Php74Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php74Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
@@ -253,7 +246,7 @@ func (c *Php74Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
}
|
||||
|
||||
extensions := c.GetExtensions()
|
||||
extensions := r.GetExtensions()
|
||||
for _, item := range extensions {
|
||||
if item.Slug == slug {
|
||||
if item.Installed {
|
||||
@@ -261,16 +254,16 @@ func (c *Php74Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
var task models.Task
|
||||
task.Name = "安装PHP-" + c.version + "扩展-" + item.Name
|
||||
task.Name = "安装PHP-" + r.version + "扩展-" + item.Name
|
||||
task.Status = models.TaskStatusWaiting
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + c.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + c.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
c.task.Process(task.ID)
|
||||
r.task.Process(task.ID)
|
||||
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
@@ -279,8 +272,8 @@ func (c *Php74Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在")
|
||||
}
|
||||
|
||||
func (c *Php74Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php74Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
@@ -290,7 +283,7 @@ func (c *Php74Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
}
|
||||
|
||||
extensions := c.GetExtensions()
|
||||
extensions := r.GetExtensions()
|
||||
for _, item := range extensions {
|
||||
if item.Slug == slug {
|
||||
if !item.Installed {
|
||||
@@ -298,16 +291,16 @@ func (c *Php74Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
var task models.Task
|
||||
task.Name = "卸载PHP-" + c.version + "扩展-" + item.Name
|
||||
task.Name = "卸载PHP-" + r.version + "扩展-" + item.Name
|
||||
task.Status = models.TaskStatusWaiting
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + c.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + c.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
c.task.Process(task.ID)
|
||||
r.task.Process(task.ID)
|
||||
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
@@ -316,46 +309,46 @@ func (c *Php74Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在")
|
||||
}
|
||||
|
||||
func (c *Php74Controller) GetExtensions() []Extension {
|
||||
var extensions []Extension
|
||||
extensions = append(extensions, Extension{
|
||||
func (r *Php74Controller) GetExtensions() []PHPExtension {
|
||||
var extensions []PHPExtension
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "OPcache",
|
||||
Slug: "Zend OPcache",
|
||||
Description: "OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能,存储预编译字节码可以省去每次加载和解析 PHP 脚本的开销。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "PhpRedis",
|
||||
Slug: "redis",
|
||||
Description: "PhpRedis 是一个用C语言编写的PHP模块,用来连接并操作 Redis 数据库上的数据。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "ImageMagick",
|
||||
Slug: "imagick",
|
||||
Description: "ImageMagick 是一个免费的创建、编辑、合成图片的软件。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "Exif",
|
||||
Slug: "exif",
|
||||
Description: "通过 exif 扩展,你可以操作图像元数据。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "pdo_pgsql",
|
||||
Slug: "pdo_pgsql",
|
||||
Description: "(需先安装PostgreSQL)pdo_pgsql 是一个驱动程序,它实现了 PHP 数据对象(PDO)接口以启用从 PHP 到 PostgreSQL 数据库的访问。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "ionCube",
|
||||
Slug: "ionCube Loader",
|
||||
Description: "ionCube 是一个专业级的PHP加密解密工具。",
|
||||
Installed: false,
|
||||
})
|
||||
|
||||
raw := tools.Exec("/www/server/php/" + c.version + "/bin/php -m")
|
||||
raw := tools.Exec("/www/server/php/" + r.version + "/bin/php -m")
|
||||
rawExtensionList := strings.Split(raw, "\n")
|
||||
|
||||
for _, item := range rawExtensionList {
|
||||
+77
-84
@@ -1,4 +1,4 @@
|
||||
package php80
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -30,15 +30,15 @@ func NewPhp80Controller() *Php80Controller {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php80Controller) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php80Controller) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
status := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -48,17 +48,17 @@ func (c *Php80Controller) Status(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php80Controller) Reload(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php80Controller) Reload(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl reload php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl reload php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -68,17 +68,17 @@ func (c *Php80Controller) Reload(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php80Controller) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php80Controller) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl start php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl start php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -88,17 +88,17 @@ func (c *Php80Controller) Start(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php80Controller) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php80Controller) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl stop php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl stop php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status != "active" {
|
||||
@@ -108,17 +108,17 @@ func (c *Php80Controller) Stop(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php80Controller) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php80Controller) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl restart php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl restart php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -128,38 +128,38 @@ func (c *Php80Controller) Restart(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php80Controller) GetConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php80Controller) GetConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
config := tools.Read("/www/server/php/" + c.version + "/etc/php.ini")
|
||||
config := tools.Read("/www/server/php/" + r.version + "/etc/php.ini")
|
||||
return controllers.Success(ctx, config)
|
||||
}
|
||||
|
||||
func (c *Php80Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php80Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
config := ctx.Request().Input("config")
|
||||
tools.Write("/www/server/php/"+c.version+"/etc/php.ini", config, 0644)
|
||||
return c.Reload(ctx)
|
||||
tools.Write("/www/server/php/"+r.version+"/etc/php.ini", config, 0644)
|
||||
return r.Reload(ctx)
|
||||
}
|
||||
|
||||
func (c *Php80Controller) Load(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php80Controller) Load(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
client := req.C().SetTimeout(10 * time.Second)
|
||||
resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + c.version)
|
||||
resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + r.version)
|
||||
if err != nil || !resp.IsSuccessState() {
|
||||
facades.Log().Error("获取PHP-" + c.version + "运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+c.version+"] 获取运行状态失败")
|
||||
facades.Log().Error("获取PHP-" + r.version + "运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+r.version+"] 获取运行状态失败")
|
||||
}
|
||||
|
||||
raw := resp.String()
|
||||
@@ -185,65 +185,58 @@ func (c *Php80Controller) Load(ctx http.Context) http.Response {
|
||||
return controllers.Success(ctx, data)
|
||||
}
|
||||
|
||||
func (c *Php80Controller) ErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php80Controller) ErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + c.version + "/var/log/php-fpm.log"))
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log"))
|
||||
return controllers.Success(ctx, log)
|
||||
}
|
||||
|
||||
func (c *Php80Controller) SlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php80Controller) SlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + c.version + "/var/log/slow.log"))
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log"))
|
||||
return controllers.Success(ctx, log)
|
||||
}
|
||||
|
||||
func (c *Php80Controller) ClearErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php80Controller) ClearErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("echo '' > /www/server/php/" + c.version + "/var/log/php-fpm.log")
|
||||
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log")
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
|
||||
func (c *Php80Controller) ClearSlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php80Controller) ClearSlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("echo '' > /www/server/php/" + c.version + "/var/log/slow.log")
|
||||
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log")
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
|
||||
type Extension struct {
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
Description string `json:"description"`
|
||||
Installed bool `json:"installed"`
|
||||
}
|
||||
|
||||
func (c *Php80Controller) GetExtensionList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php80Controller) GetExtensionList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
extensions := c.GetExtensions()
|
||||
extensions := r.GetExtensions()
|
||||
return controllers.Success(ctx, extensions)
|
||||
}
|
||||
|
||||
func (c *Php80Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php80Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
@@ -253,7 +246,7 @@ func (c *Php80Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
}
|
||||
|
||||
extensions := c.GetExtensions()
|
||||
extensions := r.GetExtensions()
|
||||
for _, item := range extensions {
|
||||
if item.Slug == slug {
|
||||
if item.Installed {
|
||||
@@ -261,16 +254,16 @@ func (c *Php80Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
var task models.Task
|
||||
task.Name = "安装PHP-" + c.version + "扩展-" + item.Name
|
||||
task.Name = "安装PHP-" + r.version + "扩展-" + item.Name
|
||||
task.Status = models.TaskStatusWaiting
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + c.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + c.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
c.task.Process(task.ID)
|
||||
r.task.Process(task.ID)
|
||||
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
@@ -279,8 +272,8 @@ func (c *Php80Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在")
|
||||
}
|
||||
|
||||
func (c *Php80Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php80Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
@@ -290,7 +283,7 @@ func (c *Php80Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
}
|
||||
|
||||
extensions := c.GetExtensions()
|
||||
extensions := r.GetExtensions()
|
||||
for _, item := range extensions {
|
||||
if item.Slug == slug {
|
||||
if !item.Installed {
|
||||
@@ -298,16 +291,16 @@ func (c *Php80Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
var task models.Task
|
||||
task.Name = "卸载PHP-" + c.version + "扩展-" + item.Name
|
||||
task.Name = "卸载PHP-" + r.version + "扩展-" + item.Name
|
||||
task.Status = models.TaskStatusWaiting
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + c.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + c.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
c.task.Process(task.ID)
|
||||
r.task.Process(task.ID)
|
||||
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
@@ -316,46 +309,46 @@ func (c *Php80Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在")
|
||||
}
|
||||
|
||||
func (c *Php80Controller) GetExtensions() []Extension {
|
||||
var extensions []Extension
|
||||
extensions = append(extensions, Extension{
|
||||
func (r *Php80Controller) GetExtensions() []PHPExtension {
|
||||
var extensions []PHPExtension
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "OPcache",
|
||||
Slug: "Zend OPcache",
|
||||
Description: "OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能,存储预编译字节码可以省去每次加载和解析 PHP 脚本的开销。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "PhpRedis",
|
||||
Slug: "redis",
|
||||
Description: "PhpRedis 是一个用C语言编写的PHP模块,用来连接并操作 Redis 数据库上的数据。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "ImageMagick",
|
||||
Slug: "imagick",
|
||||
Description: "ImageMagick 是一个免费的创建、编辑、合成图片的软件。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "Exif",
|
||||
Slug: "exif",
|
||||
Description: "通过 exif 扩展,你可以操作图像元数据。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "pdo_pgsql",
|
||||
Slug: "pdo_pgsql",
|
||||
Description: "(需先安装PostgreSQL)pdo_pgsql 是一个驱动程序,它实现了 PHP 数据对象(PDO)接口以启用从 PHP 到 PostgreSQL 数据库的访问。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "ionCube",
|
||||
Slug: "ionCube Loader",
|
||||
Description: "ionCube 是一个专业级的PHP加密解密工具。",
|
||||
Installed: false,
|
||||
})
|
||||
|
||||
raw := tools.Exec("/www/server/php/" + c.version + "/bin/php -m")
|
||||
raw := tools.Exec("/www/server/php/" + r.version + "/bin/php -m")
|
||||
rawExtensionList := strings.Split(raw, "\n")
|
||||
|
||||
for _, item := range rawExtensionList {
|
||||
+77
-84
@@ -1,4 +1,4 @@
|
||||
package php81
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -30,15 +30,15 @@ func NewPhp81Controller() *Php81Controller {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php81Controller) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php81Controller) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
status := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -48,17 +48,17 @@ func (c *Php81Controller) Status(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php81Controller) Reload(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php81Controller) Reload(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl reload php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl reload php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -68,17 +68,17 @@ func (c *Php81Controller) Reload(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php81Controller) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php81Controller) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl start php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl start php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -88,17 +88,17 @@ func (c *Php81Controller) Start(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php81Controller) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php81Controller) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl stop php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl stop php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status != "active" {
|
||||
@@ -108,17 +108,17 @@ func (c *Php81Controller) Stop(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php81Controller) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php81Controller) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl restart php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl restart php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -128,38 +128,38 @@ func (c *Php81Controller) Restart(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php81Controller) GetConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php81Controller) GetConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
config := tools.Read("/www/server/php/" + c.version + "/etc/php.ini")
|
||||
config := tools.Read("/www/server/php/" + r.version + "/etc/php.ini")
|
||||
return controllers.Success(ctx, config)
|
||||
}
|
||||
|
||||
func (c *Php81Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php81Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
config := ctx.Request().Input("config")
|
||||
tools.Write("/www/server/php/"+c.version+"/etc/php.ini", config, 0644)
|
||||
return c.Reload(ctx)
|
||||
tools.Write("/www/server/php/"+r.version+"/etc/php.ini", config, 0644)
|
||||
return r.Reload(ctx)
|
||||
}
|
||||
|
||||
func (c *Php81Controller) Load(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php81Controller) Load(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
client := req.C().SetTimeout(10 * time.Second)
|
||||
resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + c.version)
|
||||
resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + r.version)
|
||||
if err != nil || !resp.IsSuccessState() {
|
||||
facades.Log().Error("获取PHP-" + c.version + "运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+c.version+"] 获取运行状态失败")
|
||||
facades.Log().Error("获取PHP-" + r.version + "运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+r.version+"] 获取运行状态失败")
|
||||
}
|
||||
|
||||
raw := resp.String()
|
||||
@@ -185,65 +185,58 @@ func (c *Php81Controller) Load(ctx http.Context) http.Response {
|
||||
return controllers.Success(ctx, data)
|
||||
}
|
||||
|
||||
func (c *Php81Controller) ErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php81Controller) ErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + c.version + "/var/log/php-fpm.log"))
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log"))
|
||||
return controllers.Success(ctx, log)
|
||||
}
|
||||
|
||||
func (c *Php81Controller) SlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php81Controller) SlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + c.version + "/var/log/slow.log"))
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log"))
|
||||
return controllers.Success(ctx, log)
|
||||
}
|
||||
|
||||
func (c *Php81Controller) ClearErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php81Controller) ClearErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("echo '' > /www/server/php/" + c.version + "/var/log/php-fpm.log")
|
||||
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log")
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
|
||||
func (c *Php81Controller) ClearSlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php81Controller) ClearSlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("echo '' > /www/server/php/" + c.version + "/var/log/slow.log")
|
||||
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log")
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
|
||||
type Extension struct {
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
Description string `json:"description"`
|
||||
Installed bool `json:"installed"`
|
||||
}
|
||||
|
||||
func (c *Php81Controller) GetExtensionList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php81Controller) GetExtensionList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
extensions := c.GetExtensions()
|
||||
extensions := r.GetExtensions()
|
||||
return controllers.Success(ctx, extensions)
|
||||
}
|
||||
|
||||
func (c *Php81Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php81Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
@@ -253,7 +246,7 @@ func (c *Php81Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
}
|
||||
|
||||
extensions := c.GetExtensions()
|
||||
extensions := r.GetExtensions()
|
||||
for _, item := range extensions {
|
||||
if item.Slug == slug {
|
||||
if item.Installed {
|
||||
@@ -261,16 +254,16 @@ func (c *Php81Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
var task models.Task
|
||||
task.Name = "安装PHP-" + c.version + "扩展-" + item.Name
|
||||
task.Name = "安装PHP-" + r.version + "扩展-" + item.Name
|
||||
task.Status = models.TaskStatusWaiting
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + c.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + c.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
c.task.Process(task.ID)
|
||||
r.task.Process(task.ID)
|
||||
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
@@ -279,8 +272,8 @@ func (c *Php81Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在")
|
||||
}
|
||||
|
||||
func (c *Php81Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php81Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
@@ -290,7 +283,7 @@ func (c *Php81Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
}
|
||||
|
||||
extensions := c.GetExtensions()
|
||||
extensions := r.GetExtensions()
|
||||
for _, item := range extensions {
|
||||
if item.Slug == slug {
|
||||
if !item.Installed {
|
||||
@@ -298,16 +291,16 @@ func (c *Php81Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
var task models.Task
|
||||
task.Name = "卸载PHP-" + c.version + "扩展-" + item.Name
|
||||
task.Name = "卸载PHP-" + r.version + "扩展-" + item.Name
|
||||
task.Status = models.TaskStatusWaiting
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + c.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + c.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
c.task.Process(task.ID)
|
||||
r.task.Process(task.ID)
|
||||
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
@@ -316,46 +309,46 @@ func (c *Php81Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在")
|
||||
}
|
||||
|
||||
func (c *Php81Controller) GetExtensions() []Extension {
|
||||
var extensions []Extension
|
||||
extensions = append(extensions, Extension{
|
||||
func (r *Php81Controller) GetExtensions() []PHPExtension {
|
||||
var extensions []PHPExtension
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "OPcache",
|
||||
Slug: "Zend OPcache",
|
||||
Description: "OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能,存储预编译字节码可以省去每次加载和解析 PHP 脚本的开销。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "PhpRedis",
|
||||
Slug: "redis",
|
||||
Description: "PhpRedis 是一个用C语言编写的PHP模块,用来连接并操作 Redis 数据库上的数据。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "ImageMagick",
|
||||
Slug: "imagick",
|
||||
Description: "ImageMagick 是一个免费的创建、编辑、合成图片的软件。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "Exif",
|
||||
Slug: "exif",
|
||||
Description: "通过 exif 扩展,你可以操作图像元数据。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "pdo_pgsql",
|
||||
Slug: "pdo_pgsql",
|
||||
Description: "(需先安装PostgreSQL)pdo_pgsql 是一个驱动程序,它实现了 PHP 数据对象(PDO)接口以启用从 PHP 到 PostgreSQL 数据库的访问。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "ionCube",
|
||||
Slug: "ionCube Loader",
|
||||
Description: "ionCube 是一个专业级的PHP加密解密工具。",
|
||||
Installed: false,
|
||||
})
|
||||
|
||||
raw := tools.Exec("/www/server/php/" + c.version + "/bin/php -m")
|
||||
raw := tools.Exec("/www/server/php/" + r.version + "/bin/php -m")
|
||||
rawExtensionList := strings.Split(raw, "\n")
|
||||
|
||||
for _, item := range rawExtensionList {
|
||||
+76
-83
@@ -1,4 +1,4 @@
|
||||
package php82
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -30,15 +30,15 @@ func NewPhp82Controller() *Php82Controller {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php82Controller) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php82Controller) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
status := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -48,17 +48,17 @@ func (c *Php82Controller) Status(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php82Controller) Reload(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php82Controller) Reload(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl reload php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl reload php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -68,17 +68,17 @@ func (c *Php82Controller) Reload(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php82Controller) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php82Controller) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl start php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl start php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -88,17 +88,17 @@ func (c *Php82Controller) Start(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php82Controller) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php82Controller) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl stop php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl stop php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status != "active" {
|
||||
@@ -108,17 +108,17 @@ func (c *Php82Controller) Stop(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php82Controller) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php82Controller) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("systemctl restart php-fpm-" + c.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + c.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
tools.Exec("systemctl restart php-fpm-" + r.version)
|
||||
out := tools.Exec("systemctl status php-fpm-" + r.version + " | grep Active | grep -v grep | awk '{print $2}'")
|
||||
status := strings.TrimSpace(out)
|
||||
if len(status) == 0 {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+c.version+"运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取PHP-"+r.version+"运行状态失败")
|
||||
}
|
||||
|
||||
if status == "active" {
|
||||
@@ -128,38 +128,38 @@ func (c *Php82Controller) Restart(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Php82Controller) GetConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php82Controller) GetConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
config := tools.Read("/www/server/php/" + c.version + "/etc/php.ini")
|
||||
config := tools.Read("/www/server/php/" + r.version + "/etc/php.ini")
|
||||
return controllers.Success(ctx, config)
|
||||
}
|
||||
|
||||
func (c *Php82Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php82Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
config := ctx.Request().Input("config")
|
||||
tools.Write("/www/server/php/"+c.version+"/etc/php.ini", config, 0644)
|
||||
return c.Reload(ctx)
|
||||
tools.Write("/www/server/php/"+r.version+"/etc/php.ini", config, 0644)
|
||||
return r.Reload(ctx)
|
||||
}
|
||||
|
||||
func (c *Php82Controller) Load(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php82Controller) Load(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
client := req.C().SetTimeout(10 * time.Second)
|
||||
resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + c.version)
|
||||
resp, err := client.R().Get("http://127.0.0.1/phpfpm_status/" + r.version)
|
||||
if err != nil || !resp.IsSuccessState() {
|
||||
facades.Log().Error("获取PHP-" + c.version + "运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+c.version+"] 获取运行状态失败")
|
||||
facades.Log().Error("获取PHP-" + r.version + "运行状态失败")
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "[PHP-"+r.version+"] 获取运行状态失败")
|
||||
}
|
||||
|
||||
raw := resp.String()
|
||||
@@ -185,65 +185,58 @@ func (c *Php82Controller) Load(ctx http.Context) http.Response {
|
||||
return controllers.Success(ctx, data)
|
||||
}
|
||||
|
||||
func (c *Php82Controller) ErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php82Controller) ErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + c.version + "/var/log/php-fpm.log"))
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/php-fpm.log"))
|
||||
return controllers.Success(ctx, log)
|
||||
}
|
||||
|
||||
func (c *Php82Controller) SlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php82Controller) SlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + c.version + "/var/log/slow.log"))
|
||||
log := tools.Escape(tools.Exec("tail -n 100 /www/server/php/" + r.version + "/var/log/slow.log"))
|
||||
return controllers.Success(ctx, log)
|
||||
}
|
||||
|
||||
func (c *Php82Controller) ClearErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php82Controller) ClearErrorLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("echo '' > /www/server/php/" + c.version + "/var/log/php-fpm.log")
|
||||
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/php-fpm.log")
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
|
||||
func (c *Php82Controller) ClearSlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php82Controller) ClearSlowLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec("echo '' > /www/server/php/" + c.version + "/var/log/slow.log")
|
||||
tools.Exec("echo '' > /www/server/php/" + r.version + "/var/log/slow.log")
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
|
||||
type Extension struct {
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
Description string `json:"description"`
|
||||
Installed bool `json:"installed"`
|
||||
}
|
||||
|
||||
func (c *Php82Controller) GetExtensionList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php82Controller) GetExtensionList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
extensions := c.GetExtensions()
|
||||
extensions := r.GetExtensions()
|
||||
return controllers.Success(ctx, extensions)
|
||||
}
|
||||
|
||||
func (c *Php82Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php82Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
@@ -253,7 +246,7 @@ func (c *Php82Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
}
|
||||
|
||||
extensions := c.GetExtensions()
|
||||
extensions := r.GetExtensions()
|
||||
for _, item := range extensions {
|
||||
if item.Slug == slug {
|
||||
if item.Installed {
|
||||
@@ -261,16 +254,16 @@ func (c *Php82Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
var task models.Task
|
||||
task.Name = "安装PHP-" + c.version + "扩展-" + item.Name
|
||||
task.Name = "安装PHP-" + r.version + "扩展-" + item.Name
|
||||
task.Status = models.TaskStatusWaiting
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + c.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' install ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + c.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建安装拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
c.task.Process(task.ID)
|
||||
r.task.Process(task.ID)
|
||||
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
@@ -279,8 +272,8 @@ func (c *Php82Controller) InstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在")
|
||||
}
|
||||
|
||||
func (c *Php82Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+c.version)
|
||||
func (r *Php82Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "php"+r.version)
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
@@ -290,7 +283,7 @@ func (c *Php82Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "参数错误")
|
||||
}
|
||||
|
||||
extensions := c.GetExtensions()
|
||||
extensions := r.GetExtensions()
|
||||
for _, item := range extensions {
|
||||
if item.Slug == slug {
|
||||
if !item.Installed {
|
||||
@@ -298,16 +291,16 @@ func (c *Php82Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
var task models.Task
|
||||
task.Name = "卸载PHP-" + c.version + "扩展-" + item.Name
|
||||
task.Name = "卸载PHP-" + r.version + "扩展-" + item.Name
|
||||
task.Status = models.TaskStatusWaiting
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + c.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Shell = `bash '/www/panel/scripts/php_extensions/` + item.Slug + `.sh' uninstall ` + r.version + ` >> /tmp/` + item.Slug + `.log 2>&1`
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
if err := facades.Orm().Query().Create(&task); err != nil {
|
||||
facades.Log().Error("[PHP-" + c.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
facades.Log().Error("[PHP-" + r.version + "] 创建卸载拓展任务失败:" + err.Error())
|
||||
return controllers.ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
c.task.Process(task.ID)
|
||||
r.task.Process(task.ID)
|
||||
|
||||
return controllers.Success(ctx, true)
|
||||
}
|
||||
@@ -316,40 +309,40 @@ func (c *Php82Controller) UninstallExtension(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "扩展不存在")
|
||||
}
|
||||
|
||||
func (c *Php82Controller) GetExtensions() []Extension {
|
||||
var extensions []Extension
|
||||
extensions = append(extensions, Extension{
|
||||
func (r *Php82Controller) GetExtensions() []PHPExtension {
|
||||
var extensions []PHPExtension
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "OPcache",
|
||||
Slug: "Zend OPcache",
|
||||
Description: "OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能,存储预编译字节码可以省去每次加载和解析 PHP 脚本的开销。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "PhpRedis",
|
||||
Slug: "redis",
|
||||
Description: "PhpRedis 是一个用C语言编写的PHP模块,用来连接并操作 Redis 数据库上的数据。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "ImageMagick",
|
||||
Slug: "imagick",
|
||||
Description: "ImageMagick 是一个免费的创建、编辑、合成图片的软件。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "Exif",
|
||||
Slug: "exif",
|
||||
Description: "通过 exif 扩展,你可以操作图像元数据。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, Extension{
|
||||
extensions = append(extensions, PHPExtension{
|
||||
Name: "pdo_pgsql",
|
||||
Slug: "pdo_pgsql",
|
||||
Description: "(需先安装PostgreSQL)pdo_pgsql 是一个驱动程序,它实现了 PHP 数据对象(PDO)接口以启用从 PHP 到 PostgreSQL 数据库的访问。",
|
||||
Installed: false,
|
||||
})
|
||||
|
||||
raw := tools.Exec("/www/server/php/" + c.version + "/bin/php -m")
|
||||
raw := tools.Exec("/www/server/php/" + r.version + "/bin/php -m")
|
||||
rawExtensionList := strings.Split(raw, "\n")
|
||||
|
||||
for _, item := range rawExtensionList {
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package phpmyadmin
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"os"
|
||||
@@ -19,7 +19,7 @@ func NewPhpMyAdminController() *PhpMyAdminController {
|
||||
return &PhpMyAdminController{}
|
||||
}
|
||||
|
||||
func (c *PhpMyAdminController) Info(ctx http.Context) http.Response {
|
||||
func (r *PhpMyAdminController) Info(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "phpmyadmin")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -52,7 +52,7 @@ func (c *PhpMyAdminController) Info(ctx http.Context) http.Response {
|
||||
})
|
||||
}
|
||||
|
||||
func (c *PhpMyAdminController) SetPort(ctx http.Context) http.Response {
|
||||
func (r *PhpMyAdminController) SetPort(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "phpmyadmin")
|
||||
if check != nil {
|
||||
return check
|
||||
+36
-41
@@ -1,4 +1,4 @@
|
||||
package postgresql15
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"strings"
|
||||
@@ -18,11 +18,6 @@ type Postgresql15Controller struct {
|
||||
backup services.Backup
|
||||
}
|
||||
|
||||
type Info struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
func NewPostgresql15Controller() *Postgresql15Controller {
|
||||
return &Postgresql15Controller{
|
||||
setting: services.NewSettingImpl(),
|
||||
@@ -31,7 +26,7 @@ func NewPostgresql15Controller() *Postgresql15Controller {
|
||||
}
|
||||
|
||||
// Status 获取运行状态
|
||||
func (c *Postgresql15Controller) Status(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -50,7 +45,7 @@ func (c *Postgresql15Controller) Status(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Reload 重载配置
|
||||
func (c *Postgresql15Controller) Reload(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) Reload(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -70,7 +65,7 @@ func (c *Postgresql15Controller) Reload(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Restart 重启服务
|
||||
func (c *Postgresql15Controller) Restart(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -90,7 +85,7 @@ func (c *Postgresql15Controller) Restart(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Start 启动服务
|
||||
func (c *Postgresql15Controller) Start(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -110,7 +105,7 @@ func (c *Postgresql15Controller) Start(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Stop 停止服务
|
||||
func (c *Postgresql15Controller) Stop(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -130,7 +125,7 @@ func (c *Postgresql15Controller) Stop(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// GetConfig 获取配置
|
||||
func (c *Postgresql15Controller) GetConfig(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) GetConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -146,7 +141,7 @@ func (c *Postgresql15Controller) GetConfig(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// GetUserConfig 获取用户配置
|
||||
func (c *Postgresql15Controller) GetUserConfig(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) GetUserConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -162,7 +157,7 @@ func (c *Postgresql15Controller) GetUserConfig(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SaveConfig 保存配置
|
||||
func (c *Postgresql15Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -177,11 +172,11 @@ func (c *Postgresql15Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "写入PostgreSQL配置失败")
|
||||
}
|
||||
|
||||
return c.Restart(ctx)
|
||||
return r.Restart(ctx)
|
||||
}
|
||||
|
||||
// SaveUserConfig 保存用户配置
|
||||
func (c *Postgresql15Controller) SaveUserConfig(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) SaveUserConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -196,11 +191,11 @@ func (c *Postgresql15Controller) SaveUserConfig(ctx http.Context) http.Response
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "写入PostgreSQL配置失败")
|
||||
}
|
||||
|
||||
return c.Restart(ctx)
|
||||
return r.Restart(ctx)
|
||||
}
|
||||
|
||||
// Load 获取负载
|
||||
func (c *Postgresql15Controller) Load(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) Load(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -211,7 +206,7 @@ func (c *Postgresql15Controller) Load(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "PostgreSQL 已停止运行")
|
||||
}
|
||||
|
||||
data := []Info{
|
||||
data := []LoadInfo{
|
||||
{"启动时间", carbon.Parse(tools.Exec(`echo "select pg_postmaster_start_time();" | su - postgres -c "psql" | sed -n 3p | cut -d'.' -f1`)).ToDateTimeString()},
|
||||
{"进程 PID", tools.Exec(`echo "select pg_backend_pid();" | su - postgres -c "psql" | sed -n 3p`)},
|
||||
{"进程数", tools.Exec(`ps aux | grep postgres | grep -v grep | wc -l`)},
|
||||
@@ -223,7 +218,7 @@ func (c *Postgresql15Controller) Load(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Log 获取日志
|
||||
func (c *Postgresql15Controller) Log(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) Log(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -234,7 +229,7 @@ func (c *Postgresql15Controller) Log(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// ClearLog 清空日志
|
||||
func (c *Postgresql15Controller) ClearLog(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) ClearLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -245,7 +240,7 @@ func (c *Postgresql15Controller) ClearLog(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// DatabaseList 获取数据库列表
|
||||
func (c *Postgresql15Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -309,7 +304,7 @@ func (c *Postgresql15Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// AddDatabase 添加数据库
|
||||
func (c *Postgresql15Controller) AddDatabase(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) AddDatabase(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -339,11 +334,11 @@ func (c *Postgresql15Controller) AddDatabase(ctx http.Context) http.Response {
|
||||
userConfig := "host " + database + " " + user + " 127.0.0.1/32 scram-sha-256"
|
||||
tools.Exec(`echo "` + userConfig + `" >> /www/server/postgresql/data/pg_hba.conf`)
|
||||
|
||||
return c.Reload(ctx)
|
||||
return r.Reload(ctx)
|
||||
}
|
||||
|
||||
// DeleteDatabase 删除数据库
|
||||
func (c *Postgresql15Controller) DeleteDatabase(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) DeleteDatabase(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -366,13 +361,13 @@ func (c *Postgresql15Controller) DeleteDatabase(ctx http.Context) http.Response
|
||||
}
|
||||
|
||||
// BackupList 获取备份列表
|
||||
func (c *Postgresql15Controller) BackupList(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) BackupList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
backupList, err := c.backup.PostgresqlList()
|
||||
backupList, err := r.backup.PostgresqlList()
|
||||
if err != nil {
|
||||
facades.Log().Error("[PostgreSQL] 获取备份列表失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取备份列表失败")
|
||||
@@ -403,7 +398,7 @@ func (c *Postgresql15Controller) BackupList(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// UploadBackup 上传备份
|
||||
func (c *Postgresql15Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -414,7 +409,7 @@ func (c *Postgresql15Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "上传文件失败")
|
||||
}
|
||||
|
||||
backupPath := c.setting.Get(models.SettingKeyBackupPath) + "/postgresql"
|
||||
backupPath := r.setting.Get(models.SettingKeyBackupPath) + "/postgresql"
|
||||
if !tools.Exists(backupPath) {
|
||||
tools.Mkdir(backupPath, 0644)
|
||||
}
|
||||
@@ -429,7 +424,7 @@ func (c *Postgresql15Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// CreateBackup 创建备份
|
||||
func (c *Postgresql15Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -446,7 +441,7 @@ func (c *Postgresql15Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
database := ctx.Request().Input("database")
|
||||
err = c.backup.PostgresqlBackup(database)
|
||||
err = r.backup.PostgresqlBackup(database)
|
||||
if err != nil {
|
||||
facades.Log().Error("[PostgreSQL] 创建备份失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "创建备份失败")
|
||||
@@ -456,7 +451,7 @@ func (c *Postgresql15Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// DeleteBackup 删除备份
|
||||
func (c *Postgresql15Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -472,7 +467,7 @@ func (c *Postgresql15Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
backupPath := c.setting.Get(models.SettingKeyBackupPath) + "/postgresql"
|
||||
backupPath := r.setting.Get(models.SettingKeyBackupPath) + "/postgresql"
|
||||
fileName := ctx.Request().Input("name")
|
||||
tools.Remove(backupPath + "/" + fileName)
|
||||
|
||||
@@ -480,7 +475,7 @@ func (c *Postgresql15Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// RestoreBackup 还原备份
|
||||
func (c *Postgresql15Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -497,7 +492,7 @@ func (c *Postgresql15Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
err = c.backup.PostgresqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
|
||||
err = r.backup.PostgresqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
|
||||
if err != nil {
|
||||
facades.Log().Error("[PostgreSQL] 还原失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "还原失败: "+err.Error())
|
||||
@@ -507,7 +502,7 @@ func (c *Postgresql15Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// UserList 用户列表
|
||||
func (c *Postgresql15Controller) UserList(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) UserList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -560,7 +555,7 @@ func (c *Postgresql15Controller) UserList(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// AddUser 添加用户
|
||||
func (c *Postgresql15Controller) AddUser(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) AddUser(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -587,11 +582,11 @@ func (c *Postgresql15Controller) AddUser(ctx http.Context) http.Response {
|
||||
userConfig := "host " + database + " " + user + " 127.0.0.1/32 scram-sha-256"
|
||||
tools.Exec(`echo "` + userConfig + `" >> /www/server/postgresql/data/pg_hba.conf`)
|
||||
|
||||
return c.Reload(ctx)
|
||||
return r.Reload(ctx)
|
||||
}
|
||||
|
||||
// DeleteUser 删除用户
|
||||
func (c *Postgresql15Controller) DeleteUser(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) DeleteUser(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -611,11 +606,11 @@ func (c *Postgresql15Controller) DeleteUser(ctx http.Context) http.Response {
|
||||
tools.Exec(`echo "DROP USER ` + user + `;" | su - postgres -c "psql"`)
|
||||
tools.Exec(`sed -i '/` + user + `/d' /www/server/postgresql/data/pg_hba.conf`)
|
||||
|
||||
return c.Reload(ctx)
|
||||
return r.Reload(ctx)
|
||||
}
|
||||
|
||||
// SetUserPassword 设置用户密码
|
||||
func (c *Postgresql15Controller) SetUserPassword(ctx http.Context) http.Response {
|
||||
func (r *Postgresql15Controller) SetUserPassword(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql15")
|
||||
if check != nil {
|
||||
return check
|
||||
+36
-41
@@ -1,4 +1,4 @@
|
||||
package postgresql16
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"strings"
|
||||
@@ -18,11 +18,6 @@ type Postgresql16Controller struct {
|
||||
backup services.Backup
|
||||
}
|
||||
|
||||
type Info struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
func NewPostgresql16Controller() *Postgresql16Controller {
|
||||
return &Postgresql16Controller{
|
||||
setting: services.NewSettingImpl(),
|
||||
@@ -31,7 +26,7 @@ func NewPostgresql16Controller() *Postgresql16Controller {
|
||||
}
|
||||
|
||||
// Status 获取运行状态
|
||||
func (c *Postgresql16Controller) Status(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -50,7 +45,7 @@ func (c *Postgresql16Controller) Status(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Reload 重载配置
|
||||
func (c *Postgresql16Controller) Reload(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) Reload(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -70,7 +65,7 @@ func (c *Postgresql16Controller) Reload(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Restart 重启服务
|
||||
func (c *Postgresql16Controller) Restart(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -90,7 +85,7 @@ func (c *Postgresql16Controller) Restart(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Start 启动服务
|
||||
func (c *Postgresql16Controller) Start(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -110,7 +105,7 @@ func (c *Postgresql16Controller) Start(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Stop 停止服务
|
||||
func (c *Postgresql16Controller) Stop(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -130,7 +125,7 @@ func (c *Postgresql16Controller) Stop(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// GetConfig 获取配置
|
||||
func (c *Postgresql16Controller) GetConfig(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) GetConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -146,7 +141,7 @@ func (c *Postgresql16Controller) GetConfig(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// GetUserConfig 获取用户配置
|
||||
func (c *Postgresql16Controller) GetUserConfig(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) GetUserConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -162,7 +157,7 @@ func (c *Postgresql16Controller) GetUserConfig(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SaveConfig 保存配置
|
||||
func (c *Postgresql16Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -177,11 +172,11 @@ func (c *Postgresql16Controller) SaveConfig(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "写入PostgreSQL配置失败")
|
||||
}
|
||||
|
||||
return c.Restart(ctx)
|
||||
return r.Restart(ctx)
|
||||
}
|
||||
|
||||
// SaveUserConfig 保存用户配置
|
||||
func (c *Postgresql16Controller) SaveUserConfig(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) SaveUserConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -196,11 +191,11 @@ func (c *Postgresql16Controller) SaveUserConfig(ctx http.Context) http.Response
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "写入PostgreSQL配置失败")
|
||||
}
|
||||
|
||||
return c.Restart(ctx)
|
||||
return r.Restart(ctx)
|
||||
}
|
||||
|
||||
// Load 获取负载
|
||||
func (c *Postgresql16Controller) Load(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) Load(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -211,7 +206,7 @@ func (c *Postgresql16Controller) Load(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "PostgreSQL 已停止运行")
|
||||
}
|
||||
|
||||
data := []Info{
|
||||
data := []LoadInfo{
|
||||
{"启动时间", carbon.Parse(tools.Exec(`echo "select pg_postmaster_start_time();" | su - postgres -c "psql" | sed -n 3p | cut -d'.' -f1`)).ToDateTimeString()},
|
||||
{"进程 PID", tools.Exec(`echo "select pg_backend_pid();" | su - postgres -c "psql" | sed -n 3p`)},
|
||||
{"进程数", tools.Exec(`ps aux | grep postgres | grep -v grep | wc -l`)},
|
||||
@@ -223,7 +218,7 @@ func (c *Postgresql16Controller) Load(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Log 获取日志
|
||||
func (c *Postgresql16Controller) Log(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) Log(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -234,7 +229,7 @@ func (c *Postgresql16Controller) Log(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// ClearLog 清空日志
|
||||
func (c *Postgresql16Controller) ClearLog(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) ClearLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -245,7 +240,7 @@ func (c *Postgresql16Controller) ClearLog(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// DatabaseList 获取数据库列表
|
||||
func (c *Postgresql16Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -309,7 +304,7 @@ func (c *Postgresql16Controller) DatabaseList(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// AddDatabase 添加数据库
|
||||
func (c *Postgresql16Controller) AddDatabase(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) AddDatabase(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -339,11 +334,11 @@ func (c *Postgresql16Controller) AddDatabase(ctx http.Context) http.Response {
|
||||
userConfig := "host " + database + " " + user + " 127.0.0.1/32 scram-sha-256"
|
||||
tools.Exec(`echo "` + userConfig + `" >> /www/server/postgresql/data/pg_hba.conf`)
|
||||
|
||||
return c.Reload(ctx)
|
||||
return r.Reload(ctx)
|
||||
}
|
||||
|
||||
// DeleteDatabase 删除数据库
|
||||
func (c *Postgresql16Controller) DeleteDatabase(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) DeleteDatabase(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -366,13 +361,13 @@ func (c *Postgresql16Controller) DeleteDatabase(ctx http.Context) http.Response
|
||||
}
|
||||
|
||||
// BackupList 获取备份列表
|
||||
func (c *Postgresql16Controller) BackupList(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) BackupList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
backupList, err := c.backup.PostgresqlList()
|
||||
backupList, err := r.backup.PostgresqlList()
|
||||
if err != nil {
|
||||
facades.Log().Error("[PostgreSQL] 获取备份列表失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取备份列表失败")
|
||||
@@ -403,7 +398,7 @@ func (c *Postgresql16Controller) BackupList(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// UploadBackup 上传备份
|
||||
func (c *Postgresql16Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -414,7 +409,7 @@ func (c *Postgresql16Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "上传文件失败")
|
||||
}
|
||||
|
||||
backupPath := c.setting.Get(models.SettingKeyBackupPath) + "/postgresql"
|
||||
backupPath := r.setting.Get(models.SettingKeyBackupPath) + "/postgresql"
|
||||
if !tools.Exists(backupPath) {
|
||||
tools.Mkdir(backupPath, 0644)
|
||||
}
|
||||
@@ -429,7 +424,7 @@ func (c *Postgresql16Controller) UploadBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// CreateBackup 创建备份
|
||||
func (c *Postgresql16Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -446,7 +441,7 @@ func (c *Postgresql16Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
database := ctx.Request().Input("database")
|
||||
err = c.backup.PostgresqlBackup(database)
|
||||
err = r.backup.PostgresqlBackup(database)
|
||||
if err != nil {
|
||||
facades.Log().Error("[PostgreSQL] 创建备份失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "创建备份失败")
|
||||
@@ -456,7 +451,7 @@ func (c *Postgresql16Controller) CreateBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// DeleteBackup 删除备份
|
||||
func (c *Postgresql16Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -472,7 +467,7 @@ func (c *Postgresql16Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
backupPath := c.setting.Get(models.SettingKeyBackupPath) + "/postgresql"
|
||||
backupPath := r.setting.Get(models.SettingKeyBackupPath) + "/postgresql"
|
||||
fileName := ctx.Request().Input("name")
|
||||
tools.Remove(backupPath + "/" + fileName)
|
||||
|
||||
@@ -480,7 +475,7 @@ func (c *Postgresql16Controller) DeleteBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// RestoreBackup 还原备份
|
||||
func (c *Postgresql16Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -497,7 +492,7 @@ func (c *Postgresql16Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, validator.Errors().One())
|
||||
}
|
||||
|
||||
err = c.backup.PostgresqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
|
||||
err = r.backup.PostgresqlRestore(ctx.Request().Input("database"), ctx.Request().Input("backup"))
|
||||
if err != nil {
|
||||
facades.Log().Error("[PostgreSQL] 还原失败:" + err.Error())
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "还原失败: "+err.Error())
|
||||
@@ -507,7 +502,7 @@ func (c *Postgresql16Controller) RestoreBackup(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// UserList 用户列表
|
||||
func (c *Postgresql16Controller) UserList(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) UserList(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -560,7 +555,7 @@ func (c *Postgresql16Controller) UserList(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// AddUser 添加用户
|
||||
func (c *Postgresql16Controller) AddUser(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) AddUser(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -587,11 +582,11 @@ func (c *Postgresql16Controller) AddUser(ctx http.Context) http.Response {
|
||||
userConfig := "host " + database + " " + user + " 127.0.0.1/32 scram-sha-256"
|
||||
tools.Exec(`echo "` + userConfig + `" >> /www/server/postgresql/data/pg_hba.conf`)
|
||||
|
||||
return c.Reload(ctx)
|
||||
return r.Reload(ctx)
|
||||
}
|
||||
|
||||
// DeleteUser 删除用户
|
||||
func (c *Postgresql16Controller) DeleteUser(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) DeleteUser(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -611,11 +606,11 @@ func (c *Postgresql16Controller) DeleteUser(ctx http.Context) http.Response {
|
||||
tools.Exec(`echo "DROP USER ` + user + `;" | su - postgres -c "psql"`)
|
||||
tools.Exec(`sed -i '/` + user + `/d' /www/server/postgresql/data/pg_hba.conf`)
|
||||
|
||||
return c.Reload(ctx)
|
||||
return r.Reload(ctx)
|
||||
}
|
||||
|
||||
// SetUserPassword 设置用户密码
|
||||
func (c *Postgresql16Controller) SetUserPassword(ctx http.Context) http.Response {
|
||||
func (r *Postgresql16Controller) SetUserPassword(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "postgresql16")
|
||||
if check != nil {
|
||||
return check
|
||||
+11
-11
@@ -1,4 +1,4 @@
|
||||
package pureftpd
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
@@ -24,7 +24,7 @@ func NewPureFtpdController() *PureFtpdController {
|
||||
}
|
||||
|
||||
// Status 获取运行状态
|
||||
func (c *PureFtpdController) Status(ctx http.Context) http.Response {
|
||||
func (r *PureFtpdController) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "pureftpd")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -43,7 +43,7 @@ func (c *PureFtpdController) Status(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Restart 重启服务
|
||||
func (c *PureFtpdController) Restart(ctx http.Context) http.Response {
|
||||
func (r *PureFtpdController) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "pureftpd")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -63,7 +63,7 @@ func (c *PureFtpdController) Restart(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Start 启动服务
|
||||
func (c *PureFtpdController) Start(ctx http.Context) http.Response {
|
||||
func (r *PureFtpdController) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "pureftpd")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -83,7 +83,7 @@ func (c *PureFtpdController) Start(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Stop 停止服务
|
||||
func (c *PureFtpdController) Stop(ctx http.Context) http.Response {
|
||||
func (r *PureFtpdController) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "pureftpd")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -103,7 +103,7 @@ func (c *PureFtpdController) Stop(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// List 获取用户列表
|
||||
func (c *PureFtpdController) List(ctx http.Context) http.Response {
|
||||
func (r *PureFtpdController) List(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "pureftpd")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -153,7 +153,7 @@ func (c *PureFtpdController) List(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Add 添加用户
|
||||
func (c *PureFtpdController) Add(ctx http.Context) http.Response {
|
||||
func (r *PureFtpdController) Add(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "pureftpd")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -191,7 +191,7 @@ func (c *PureFtpdController) Add(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Delete 删除用户
|
||||
func (c *PureFtpdController) Delete(ctx http.Context) http.Response {
|
||||
func (r *PureFtpdController) Delete(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "pureftpd")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -216,7 +216,7 @@ func (c *PureFtpdController) Delete(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// ChangePassword 修改密码
|
||||
func (c *PureFtpdController) ChangePassword(ctx http.Context) http.Response {
|
||||
func (r *PureFtpdController) ChangePassword(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "pureftpd")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -243,7 +243,7 @@ func (c *PureFtpdController) ChangePassword(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// GetPort 获取端口
|
||||
func (c *PureFtpdController) GetPort(ctx http.Context) http.Response {
|
||||
func (r *PureFtpdController) GetPort(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "pureftpd")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -258,7 +258,7 @@ func (c *PureFtpdController) GetPort(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SetPort 设置端口
|
||||
func (c *PureFtpdController) SetPort(ctx http.Context) http.Response {
|
||||
func (r *PureFtpdController) SetPort(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "pureftpd")
|
||||
if check != nil {
|
||||
return check
|
||||
+10
-15
@@ -1,4 +1,4 @@
|
||||
package redis
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"strings"
|
||||
@@ -12,17 +12,12 @@ import (
|
||||
type RedisController struct {
|
||||
}
|
||||
|
||||
type Info struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
func NewRedisController() *RedisController {
|
||||
return &RedisController{}
|
||||
}
|
||||
|
||||
// Status 获取运行状态
|
||||
func (c *RedisController) Status(ctx http.Context) http.Response {
|
||||
func (r *RedisController) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "redis")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -41,7 +36,7 @@ func (c *RedisController) Status(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Restart 重启服务
|
||||
func (c *RedisController) Restart(ctx http.Context) http.Response {
|
||||
func (r *RedisController) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "redis")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -61,7 +56,7 @@ func (c *RedisController) Restart(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Start 启动服务
|
||||
func (c *RedisController) Start(ctx http.Context) http.Response {
|
||||
func (r *RedisController) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "redis")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -81,7 +76,7 @@ func (c *RedisController) Start(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Stop 停止服务
|
||||
func (c *RedisController) Stop(ctx http.Context) http.Response {
|
||||
func (r *RedisController) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "redis")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -101,7 +96,7 @@ func (c *RedisController) Stop(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// GetConfig 获取配置
|
||||
func (c *RedisController) GetConfig(ctx http.Context) http.Response {
|
||||
func (r *RedisController) GetConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "redis")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -117,7 +112,7 @@ func (c *RedisController) GetConfig(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SaveConfig 保存配置
|
||||
func (c *RedisController) SaveConfig(ctx http.Context) http.Response {
|
||||
func (r *RedisController) SaveConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "redis")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -132,11 +127,11 @@ func (c *RedisController) SaveConfig(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "写入Redis配置失败")
|
||||
}
|
||||
|
||||
return c.Restart(ctx)
|
||||
return r.Restart(ctx)
|
||||
}
|
||||
|
||||
// Load 获取负载
|
||||
func (c *RedisController) Load(ctx http.Context) http.Response {
|
||||
func (r *RedisController) Load(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "redis")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -162,7 +157,7 @@ func (c *RedisController) Load(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
data := []Info{
|
||||
data := []LoadInfo{
|
||||
{"TCP 端口", dataRaw["tcp_port"]},
|
||||
{"已运行天数", dataRaw["uptime_in_days"]},
|
||||
{"连接的客户端数", dataRaw["connected_clients"]},
|
||||
+20
-27
@@ -1,11 +1,11 @@
|
||||
package s3fs
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
"github.com/goravel/framework/support/json"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"panel/app/http/controllers"
|
||||
@@ -17,13 +17,6 @@ type S3fsController struct {
|
||||
setting services.Setting
|
||||
}
|
||||
|
||||
type s3fs struct {
|
||||
ID int64 `json:"id"`
|
||||
Path string `json:"path"`
|
||||
Bucket string `json:"bucket"`
|
||||
Url string `json:"url"`
|
||||
}
|
||||
|
||||
func NewS3fsController() *S3fsController {
|
||||
return &S3fsController{
|
||||
setting: services.NewSettingImpl(),
|
||||
@@ -31,7 +24,7 @@ func NewS3fsController() *S3fsController {
|
||||
}
|
||||
|
||||
// List 所有 S3fs 挂载
|
||||
func (c *S3fsController) List(ctx http.Context) http.Response {
|
||||
func (r *S3fsController) List(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "s3fs")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -40,8 +33,8 @@ func (c *S3fsController) List(ctx http.Context) http.Response {
|
||||
page := ctx.Request().QueryInt("page", 1)
|
||||
limit := ctx.Request().QueryInt("limit", 10)
|
||||
|
||||
var s3fsList []s3fs
|
||||
err := sonic.UnmarshalString(c.setting.Get("s3fs", "[]"), &s3fsList)
|
||||
var s3fsList []S3fsMount
|
||||
err := json.UnmarshalString(r.setting.Get("s3fs", "[]"), &s3fsList)
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "获取 S3fs 挂载失败")
|
||||
}
|
||||
@@ -51,7 +44,7 @@ func (c *S3fsController) List(ctx http.Context) http.Response {
|
||||
if startIndex > len(s3fsList) {
|
||||
return controllers.Success(ctx, http.Json{
|
||||
"total": 0,
|
||||
"items": []s3fs{},
|
||||
"items": []S3fsMount{},
|
||||
})
|
||||
}
|
||||
if endIndex > len(s3fsList) {
|
||||
@@ -59,7 +52,7 @@ func (c *S3fsController) List(ctx http.Context) http.Response {
|
||||
}
|
||||
pagedS3fsList := s3fsList[startIndex:endIndex]
|
||||
if pagedS3fsList == nil {
|
||||
pagedS3fsList = []s3fs{}
|
||||
pagedS3fsList = []S3fsMount{}
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, http.Json{
|
||||
@@ -69,7 +62,7 @@ func (c *S3fsController) List(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Add 添加 S3fs 挂载
|
||||
func (c *S3fsController) Add(ctx http.Context) http.Response {
|
||||
func (r *S3fsController) Add(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "s3fs")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -108,8 +101,8 @@ func (c *S3fsController) Add(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "挂载目录必须为空")
|
||||
}
|
||||
|
||||
var s3fsList []s3fs
|
||||
err = sonic.UnmarshalString(c.setting.Get("s3fs", "[]"), &s3fsList)
|
||||
var s3fsList []S3fsMount
|
||||
err = json.UnmarshalString(r.setting.Get("s3fs", "[]"), &s3fsList)
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取 S3fs 挂载失败")
|
||||
}
|
||||
@@ -135,17 +128,17 @@ func (c *S3fsController) Add(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "挂载失败,请检查配置是否正确")
|
||||
}
|
||||
|
||||
s3fsList = append(s3fsList, s3fs{
|
||||
s3fsList = append(s3fsList, S3fsMount{
|
||||
ID: id,
|
||||
Path: path,
|
||||
Bucket: bucket,
|
||||
Url: url,
|
||||
})
|
||||
json, err := sonic.MarshalString(s3fsList)
|
||||
encoded, err := json.MarshalString(s3fsList)
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "添加 S3fs 挂载失败")
|
||||
}
|
||||
err = c.setting.Set("s3fs", json)
|
||||
err = r.setting.Set("s3fs", encoded)
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "添加 S3fs 挂载失败")
|
||||
}
|
||||
@@ -154,7 +147,7 @@ func (c *S3fsController) Add(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Delete 删除 S3fs 挂载
|
||||
func (c *S3fsController) Delete(ctx http.Context) http.Response {
|
||||
func (r *S3fsController) Delete(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "s3fs")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -165,13 +158,13 @@ func (c *S3fsController) Delete(ctx http.Context) http.Response {
|
||||
return controllers.Error(ctx, http.StatusUnprocessableEntity, "挂载ID不能为空")
|
||||
}
|
||||
|
||||
var s3fsList []s3fs
|
||||
err := sonic.UnmarshalString(c.setting.Get("s3fs", "[]"), &s3fsList)
|
||||
var s3fsList []S3fsMount
|
||||
err := json.UnmarshalString(r.setting.Get("s3fs", "[]"), &s3fsList)
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取 S3fs 挂载失败")
|
||||
}
|
||||
|
||||
var mount s3fs
|
||||
var mount S3fsMount
|
||||
for _, s := range s3fsList {
|
||||
if cast.ToString(s.ID) == id {
|
||||
mount = s
|
||||
@@ -191,17 +184,17 @@ func (c *S3fsController) Delete(ctx http.Context) http.Response {
|
||||
}
|
||||
tools.Remove("/etc/passwd-s3fs-" + cast.ToString(mount.ID))
|
||||
|
||||
var newS3fsList []s3fs
|
||||
var newS3fsList []S3fsMount
|
||||
for _, s := range s3fsList {
|
||||
if s.ID != mount.ID {
|
||||
newS3fsList = append(newS3fsList, s)
|
||||
}
|
||||
}
|
||||
json, err := sonic.MarshalString(newS3fsList)
|
||||
encoded, err := json.MarshalString(newS3fsList)
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "删除 S3fs 挂载失败")
|
||||
}
|
||||
err = c.setting.Set("s3fs", json)
|
||||
err = r.setting.Set("s3fs", encoded)
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "删除 S3fs 挂载失败")
|
||||
}
|
||||
+33
-30
@@ -1,4 +1,4 @@
|
||||
package supervisor
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
@@ -28,13 +28,13 @@ func NewSupervisorController() *SupervisorController {
|
||||
}
|
||||
|
||||
// Status 状态
|
||||
func (c *SupervisorController) Status(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) Status(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
status := tools.Exec(`systemctl status ` + c.ServiceName + ` | grep Active | grep -v grep | awk '{print $2}'`)
|
||||
status := tools.Exec(`systemctl status ` + r.ServiceName + ` | grep Active | grep -v grep | awk '{print $2}'`)
|
||||
if status == "active" {
|
||||
return controllers.Success(ctx, true)
|
||||
} else {
|
||||
@@ -43,14 +43,14 @@ func (c *SupervisorController) Status(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Start 启动
|
||||
func (c *SupervisorController) Start(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) Start(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec(`systemctl start ` + c.ServiceName)
|
||||
status := tools.Exec(`systemctl status ` + c.ServiceName + ` | grep Active | grep -v grep | awk '{print $2}'`)
|
||||
tools.Exec(`systemctl start ` + r.ServiceName)
|
||||
status := tools.Exec(`systemctl status ` + r.ServiceName + ` | grep Active | grep -v grep | awk '{print $2}'`)
|
||||
if status == "active" {
|
||||
return controllers.Success(ctx, true)
|
||||
} else {
|
||||
@@ -59,14 +59,14 @@ func (c *SupervisorController) Start(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Stop 停止
|
||||
func (c *SupervisorController) Stop(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) Stop(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec(`systemctl stop ` + c.ServiceName)
|
||||
status := tools.Exec(`systemctl status ` + c.ServiceName + ` | grep Active | grep -v grep | awk '{print $2}'`)
|
||||
tools.Exec(`systemctl stop ` + r.ServiceName)
|
||||
status := tools.Exec(`systemctl status ` + r.ServiceName + ` | grep Active | grep -v grep | awk '{print $2}'`)
|
||||
if status != "active" {
|
||||
return controllers.Success(ctx, true)
|
||||
} else {
|
||||
@@ -75,14 +75,14 @@ func (c *SupervisorController) Stop(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Restart 重启
|
||||
func (c *SupervisorController) Restart(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) Restart(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec(`systemctl restart ` + c.ServiceName)
|
||||
status := tools.Exec(`systemctl status ` + c.ServiceName + ` | grep Active | grep -v grep | awk '{print $2}'`)
|
||||
tools.Exec(`systemctl restart ` + r.ServiceName)
|
||||
status := tools.Exec(`systemctl status ` + r.ServiceName + ` | grep Active | grep -v grep | awk '{print $2}'`)
|
||||
if status == "active" {
|
||||
return controllers.Success(ctx, true)
|
||||
} else {
|
||||
@@ -91,14 +91,14 @@ func (c *SupervisorController) Restart(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Reload 重载
|
||||
func (c *SupervisorController) Reload(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) Reload(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
}
|
||||
|
||||
tools.Exec(`systemctl reload ` + c.ServiceName)
|
||||
status := tools.Exec(`systemctl status ` + c.ServiceName + ` | grep Active | grep -v grep | awk '{print $2}'`)
|
||||
tools.Exec(`systemctl reload ` + r.ServiceName)
|
||||
status := tools.Exec(`systemctl status ` + r.ServiceName + ` | grep Active | grep -v grep | awk '{print $2}'`)
|
||||
if status == "active" {
|
||||
return controllers.Success(ctx, true)
|
||||
} else {
|
||||
@@ -107,7 +107,7 @@ func (c *SupervisorController) Reload(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Log 日志
|
||||
func (c *SupervisorController) Log(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) Log(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -118,7 +118,7 @@ func (c *SupervisorController) Log(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// ClearLog 清空日志
|
||||
func (c *SupervisorController) ClearLog(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) ClearLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -129,7 +129,7 @@ func (c *SupervisorController) ClearLog(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// Config 获取配置
|
||||
func (c *SupervisorController) Config(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) Config(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -145,7 +145,7 @@ func (c *SupervisorController) Config(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SaveConfig 保存配置
|
||||
func (c *SupervisorController) SaveConfig(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) SaveConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -158,11 +158,11 @@ func (c *SupervisorController) SaveConfig(ctx http.Context) http.Response {
|
||||
tools.Write(`/etc/supervisor/supervisord.conf`, config, 0644)
|
||||
}
|
||||
|
||||
return c.Restart(ctx)
|
||||
return r.Restart(ctx)
|
||||
}
|
||||
|
||||
// Processes 进程列表
|
||||
func (c *SupervisorController) Processes(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) Processes(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -210,6 +210,9 @@ func (c *SupervisorController) Processes(ctx http.Context) http.Response {
|
||||
endIndex = len(processList)
|
||||
}
|
||||
pagedProcessList := processList[startIndex:endIndex]
|
||||
if pagedProcessList == nil {
|
||||
pagedProcessList = []process{}
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, http.Json{
|
||||
"total": len(processList),
|
||||
@@ -218,7 +221,7 @@ func (c *SupervisorController) Processes(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// StartProcess 启动进程
|
||||
func (c *SupervisorController) StartProcess(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) StartProcess(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -230,7 +233,7 @@ func (c *SupervisorController) StartProcess(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// StopProcess 停止进程
|
||||
func (c *SupervisorController) StopProcess(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) StopProcess(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -242,7 +245,7 @@ func (c *SupervisorController) StopProcess(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// RestartProcess 重启进程
|
||||
func (c *SupervisorController) RestartProcess(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) RestartProcess(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -254,7 +257,7 @@ func (c *SupervisorController) RestartProcess(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// ProcessLog 进程日志
|
||||
func (c *SupervisorController) ProcessLog(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) ProcessLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -273,7 +276,7 @@ func (c *SupervisorController) ProcessLog(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// ClearProcessLog 清空进程日志
|
||||
func (c *SupervisorController) ClearProcessLog(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) ClearProcessLog(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -292,7 +295,7 @@ func (c *SupervisorController) ClearProcessLog(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// ProcessConfig 获取进程配置
|
||||
func (c *SupervisorController) ProcessConfig(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) ProcessConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -310,7 +313,7 @@ func (c *SupervisorController) ProcessConfig(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SaveProcessConfig 保存进程配置
|
||||
func (c *SupervisorController) SaveProcessConfig(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) SaveProcessConfig(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -331,7 +334,7 @@ func (c *SupervisorController) SaveProcessConfig(ctx http.Context) http.Response
|
||||
}
|
||||
|
||||
// AddProcess 添加进程
|
||||
func (c *SupervisorController) AddProcess(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) AddProcess(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -381,7 +384,7 @@ stdout_logfile_maxbytes=2MB
|
||||
}
|
||||
|
||||
// DeleteProcess 删除进程
|
||||
func (c *SupervisorController) DeleteProcess(ctx http.Context) http.Response {
|
||||
func (r *SupervisorController) DeleteProcess(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "supervisor")
|
||||
if check != nil {
|
||||
return check
|
||||
+10
-10
@@ -1,4 +1,4 @@
|
||||
package toolbox
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
@@ -19,7 +19,7 @@ func NewToolBoxController() *ToolBoxController {
|
||||
}
|
||||
|
||||
// GetDNS 获取 DNS 信息
|
||||
func (c *ToolBoxController) GetDNS(ctx http.Context) http.Response {
|
||||
func (r *ToolBoxController) GetDNS(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "toolbox")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -40,7 +40,7 @@ func (c *ToolBoxController) GetDNS(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SetDNS 设置 DNS 信息
|
||||
func (c *ToolBoxController) SetDNS(ctx http.Context) http.Response {
|
||||
func (r *ToolBoxController) SetDNS(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "toolbox")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -62,7 +62,7 @@ func (c *ToolBoxController) SetDNS(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// GetSWAP 获取 SWAP 信息
|
||||
func (c *ToolBoxController) GetSWAP(ctx http.Context) http.Response {
|
||||
func (r *ToolBoxController) GetSWAP(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "toolbox")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -95,7 +95,7 @@ func (c *ToolBoxController) GetSWAP(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SetSWAP 设置 SWAP 信息
|
||||
func (c *ToolBoxController) SetSWAP(ctx http.Context) http.Response {
|
||||
func (r *ToolBoxController) SetSWAP(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "toolbox")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -130,7 +130,7 @@ func (c *ToolBoxController) SetSWAP(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// GetTimezone 获取时区
|
||||
func (c *ToolBoxController) GetTimezone(ctx http.Context) http.Response {
|
||||
func (r *ToolBoxController) GetTimezone(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "toolbox")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -165,7 +165,7 @@ func (c *ToolBoxController) GetTimezone(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SetTimezone 设置时区
|
||||
func (c *ToolBoxController) SetTimezone(ctx http.Context) http.Response {
|
||||
func (r *ToolBoxController) SetTimezone(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "toolbox")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -182,7 +182,7 @@ func (c *ToolBoxController) SetTimezone(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// GetHosts 获取 hosts 信息
|
||||
func (c *ToolBoxController) GetHosts(ctx http.Context) http.Response {
|
||||
func (r *ToolBoxController) GetHosts(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "toolbox")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -192,7 +192,7 @@ func (c *ToolBoxController) GetHosts(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SetHosts 设置 hosts 信息
|
||||
func (c *ToolBoxController) SetHosts(ctx http.Context) http.Response {
|
||||
func (r *ToolBoxController) SetHosts(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "toolbox")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -209,7 +209,7 @@ func (c *ToolBoxController) SetHosts(ctx http.Context) http.Response {
|
||||
}
|
||||
|
||||
// SetRootPassword 设置 root 密码
|
||||
func (c *ToolBoxController) SetRootPassword(ctx http.Context) http.Response {
|
||||
func (r *ToolBoxController) SetRootPassword(ctx http.Context) http.Response {
|
||||
check := controllers.Check(ctx, "toolbox")
|
||||
if check != nil {
|
||||
return check
|
||||
@@ -1,14 +1,15 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
"panel/pkg/tools"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
requests "panel/app/http/requests/setting"
|
||||
responses "panel/app/http/responses/setting"
|
||||
"panel/app/models"
|
||||
"panel/app/services"
|
||||
"panel/pkg/tools"
|
||||
)
|
||||
|
||||
type SettingController struct {
|
||||
@@ -21,29 +22,27 @@ func NewSettingController() *SettingController {
|
||||
}
|
||||
}
|
||||
|
||||
// List 获取设置列表
|
||||
// List
|
||||
// @Summary 设置列表
|
||||
// @Description 获取面板设置列表
|
||||
// @Tags 面板设置
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Success 200 {object} SuccessResponse{data=responses.Settings}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/setting/list [get]
|
||||
func (r *SettingController) List(ctx http.Context) http.Response {
|
||||
var settings []models.Setting
|
||||
err := facades.Orm().Query().Get(&settings)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SettingController] 查询设置列表失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
type data struct {
|
||||
Name string `json:"name"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Email string `json:"email"`
|
||||
Port string `json:"port"`
|
||||
Entrance string `json:"entrance"`
|
||||
WebsitePath string `json:"website_path"`
|
||||
BackupPath string `json:"backup_path"`
|
||||
}
|
||||
|
||||
var result data
|
||||
var result responses.Settings
|
||||
result.Name = r.setting.Get(models.SettingKeyName)
|
||||
result.Entrance = r.setting.Get(models.SettingKeyEntrance)
|
||||
result.Entrance = facades.Config().GetString("http.entrance")
|
||||
result.WebsitePath = r.setting.Get(models.SettingKeyWebsitePath)
|
||||
result.BackupPath = r.setting.Get(models.SettingKeyBackupPath)
|
||||
|
||||
@@ -51,7 +50,7 @@ func (r *SettingController) List(ctx http.Context) http.Response {
|
||||
err = facades.Auth().User(ctx, &user)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SettingController] 获取用户失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
result.Username = user.Username
|
||||
result.Email = user.Email
|
||||
@@ -61,78 +60,89 @@ func (r *SettingController) List(ctx http.Context) http.Response {
|
||||
return Success(ctx, result)
|
||||
}
|
||||
|
||||
// Save 保存设置
|
||||
func (r *SettingController) Save(ctx http.Context) http.Response {
|
||||
name := ctx.Request().Input("name")
|
||||
port := ctx.Request().Input("port")
|
||||
backupPath := ctx.Request().Input("backup_path")
|
||||
websitePath := ctx.Request().Input("website_path")
|
||||
entrance := ctx.Request().Input("entrance")
|
||||
username := ctx.Request().Input("username")
|
||||
email := ctx.Request().Input("email")
|
||||
password := ctx.Request().Input("password")
|
||||
|
||||
if !regexp.MustCompile(`^/[^/]*[^/]$`).MatchString(entrance) || entrance == "/api" {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, "入口格式错误")
|
||||
// Update
|
||||
// @Summary 更新设置
|
||||
// @Description 更新面板设置
|
||||
// @Tags 面板设置
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.Update true "更新设置"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/setting/update [post]
|
||||
func (r *SettingController) Update(ctx http.Context) http.Response {
|
||||
var updateRequest requests.Update
|
||||
sanitize := Sanitize(ctx, &updateRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
err := r.setting.Set(models.SettingKeyName, name)
|
||||
err := r.setting.Set(models.SettingKeyName, updateRequest.Name)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SettingController] 保存设置失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "面板设置").Error("保存面板名称失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
oldPort := tools.Exec(`cat /www/panel/panel.conf | grep APP_PORT | awk -F '=' '{print $2}' | tr -d '\n'`)
|
||||
if oldPort != port {
|
||||
tools.Exec("sed -i 's/APP_PORT=" + oldPort + "/APP_PORT=" + port + "/g' /www/panel/panel.conf")
|
||||
|
||||
if !tools.Exists(updateRequest.BackupPath) {
|
||||
tools.Mkdir(updateRequest.BackupPath, 0644)
|
||||
}
|
||||
if !tools.Exists(backupPath) {
|
||||
tools.Mkdir(backupPath, 0644)
|
||||
}
|
||||
err = r.setting.Set(models.SettingKeyBackupPath, backupPath)
|
||||
err = r.setting.Set(models.SettingKeyBackupPath, updateRequest.BackupPath)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SettingController] 保存设置失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "面板设置").Error("保存备份目录失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
if !tools.Exists(websitePath) {
|
||||
tools.Mkdir(websitePath, 0755)
|
||||
tools.Chown(websitePath, "www", "www")
|
||||
if !tools.Exists(updateRequest.WebsitePath) {
|
||||
tools.Mkdir(updateRequest.WebsitePath, 0755)
|
||||
tools.Chown(updateRequest.WebsitePath, "www", "www")
|
||||
}
|
||||
err = r.setting.Set(models.SettingKeyWebsitePath, websitePath)
|
||||
err = r.setting.Set(models.SettingKeyWebsitePath, updateRequest.WebsitePath)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SettingController] 保存设置失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
}
|
||||
err = r.setting.Set(models.SettingKeyEntrance, entrance)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SettingController] 保存设置失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "面板设置").Error("保存建站目录失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
var user models.User
|
||||
err = facades.Auth().User(ctx, &user)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SettingController] 获取用户失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
if len(username) > 0 {
|
||||
user.Username = username
|
||||
}
|
||||
if len(email) > 0 {
|
||||
user.Email = email
|
||||
}
|
||||
if len(password) > 0 {
|
||||
hash, err := facades.Hash().Make(password)
|
||||
user.Username = updateRequest.UserName
|
||||
user.Email = updateRequest.Email
|
||||
if len(updateRequest.Password) > 0 {
|
||||
hash, err := facades.Hash().Make(updateRequest.Password)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SettingController] 保存设置失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
user.Password = hash
|
||||
}
|
||||
|
||||
if err = facades.Orm().Query().Save(&user); err != nil {
|
||||
facades.Log().Error("[面板][SettingController] 保存设置失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "面板设置").Error("保存用户信息失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
oldPort := tools.Exec(`cat /www/panel/panel.conf | grep APP_PORT | awk -F '=' '{print $2}' | tr -d '\n'`)
|
||||
port := cast.ToString(updateRequest.Port)
|
||||
if oldPort != port {
|
||||
tools.Exec("sed -i 's/APP_PORT=" + oldPort + "/APP_PORT=" + port + "/g' /www/panel/panel.conf")
|
||||
}
|
||||
oldEntrance := tools.Exec(`cat /www/panel/panel.conf | grep APP_ENTRANCE | awk -F '=' '{print $2}' | tr -d '\n'`)
|
||||
entrance := cast.ToString(updateRequest.Entrance)
|
||||
if oldEntrance != entrance {
|
||||
tools.Exec("sed -i 's/APP_ENTRANCE=" + oldEntrance + "/APP_ENTRANCE=" + entrance + "/g' /www/panel/panel.conf")
|
||||
}
|
||||
|
||||
if oldPort != port || oldEntrance != entrance {
|
||||
tools.RestartPanel()
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
|
||||
@@ -3,14 +3,15 @@ package controllers
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
nethttp "net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fasthttp/websocket"
|
||||
"github.com/goravel/fiber"
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/spf13/cast"
|
||||
"github.com/valyala/fasthttp"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/app/services"
|
||||
@@ -69,22 +70,22 @@ func (r *SshController) UpdateInfo(ctx http.Context) http.Response {
|
||||
err = r.setting.Set(models.SettingKeySshHost, host)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 更新配置失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
err = r.setting.Set(models.SettingKeySshPort, port)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 更新配置失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
err = r.setting.Set(models.SettingKeySshUser, user)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 更新配置失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
err = r.setting.Set(models.SettingKeySshPassword, password)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 更新配置失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
@@ -92,71 +93,72 @@ func (r *SshController) UpdateInfo(ctx http.Context) http.Response {
|
||||
|
||||
// Session SSH 会话
|
||||
func (r *SshController) Session(ctx http.Context) http.Response {
|
||||
upGrader := websocket.Upgrader{
|
||||
upGrader := websocket.FastHTTPUpgrader{
|
||||
ReadBufferSize: 4096,
|
||||
WriteBufferSize: 4096,
|
||||
CheckOrigin: func(r *nethttp.Request) bool {
|
||||
CheckOrigin: func(ctx *fasthttp.RequestCtx) bool {
|
||||
return true
|
||||
},
|
||||
Subprotocols: []string{ctx.Request().Header("Sec-WebSocket-Protocol")},
|
||||
}
|
||||
|
||||
ws, err := upGrader.Upgrade(ctx.Response().Writer(), ctx.Request().Origin(), nil)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 建立连接失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
config := ssh.SSHClientConfigPassword(
|
||||
r.setting.Get(models.SettingKeySshHost)+":"+r.setting.Get(models.SettingKeySshPort),
|
||||
r.setting.Get(models.SettingKeySshUser),
|
||||
r.setting.Get(models.SettingKeySshPassword),
|
||||
)
|
||||
client, err := ssh.NewSSHClient(config)
|
||||
if err != nil {
|
||||
_ = ws.WriteControl(websocket.CloseMessage,
|
||||
[]byte(err.Error()), time.Now().Add(time.Second))
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
turn, err := ssh.NewTurn(ws, client)
|
||||
if err != nil {
|
||||
_ = ws.WriteControl(websocket.CloseMessage,
|
||||
[]byte(err.Error()), time.Now().Add(time.Second))
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
}
|
||||
defer turn.Close()
|
||||
|
||||
var bufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(bytes.Buffer)
|
||||
},
|
||||
}
|
||||
var logBuff = bufPool.Get().(*bytes.Buffer)
|
||||
logBuff.Reset()
|
||||
defer bufPool.Put(logBuff)
|
||||
|
||||
ctx2, cancel := context.WithCancel(context.Background())
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := turn.LoopRead(logBuff, ctx2)
|
||||
err = upGrader.Upgrade(ctx.(*fiber.Context).Instance().Context(), func(conn *websocket.Conn) {
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 读取数据失败 ", err.Error())
|
||||
_ = conn.WriteControl(websocket.CloseMessage,
|
||||
[]byte(err.Error()), time.Now().Add(time.Second))
|
||||
return
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := turn.SessionWait()
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 会话失败 ", err.Error())
|
||||
}
|
||||
cancel()
|
||||
}()
|
||||
wg.Wait()
|
||||
|
||||
return Success(ctx, logBuff.String())
|
||||
defer client.Close()
|
||||
|
||||
turn, err := ssh.NewTurn(conn, client)
|
||||
if err != nil {
|
||||
_ = conn.WriteControl(websocket.CloseMessage,
|
||||
[]byte(err.Error()), time.Now().Add(time.Second))
|
||||
return
|
||||
}
|
||||
defer turn.Close()
|
||||
|
||||
var bufPool = sync.Pool{
|
||||
New: func() any {
|
||||
return new(bytes.Buffer)
|
||||
},
|
||||
}
|
||||
var logBuff = bufPool.Get().(*bytes.Buffer)
|
||||
logBuff.Reset()
|
||||
defer bufPool.Put(logBuff)
|
||||
|
||||
ctx2, cancel := context.WithCancel(context.Background())
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := turn.LoopRead(logBuff, ctx2)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 读取数据失败 ", err.Error())
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := turn.SessionWait()
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 会话失败 ", err.Error())
|
||||
}
|
||||
cancel()
|
||||
}()
|
||||
wg.Wait()
|
||||
})
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][SSH] 建立连接失败 ", err)
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
swaggerFiles "github.com/swaggo/files/v2"
|
||||
"github.com/swaggo/swag"
|
||||
)
|
||||
|
||||
type SwaggerController struct {
|
||||
// Dependent services
|
||||
}
|
||||
|
||||
// Config stores fiberSwagger configuration variables.
|
||||
type Config struct {
|
||||
URL string
|
||||
InstanceName string
|
||||
DocExpansion string
|
||||
DomID string
|
||||
DeepLinking bool
|
||||
PersistAuthorization bool
|
||||
}
|
||||
|
||||
func NewSwaggerController() *SwaggerController {
|
||||
return &SwaggerController{
|
||||
// Inject services
|
||||
}
|
||||
}
|
||||
|
||||
// Index
|
||||
// @Summary Swagger UI
|
||||
// @Description Swagger UI
|
||||
// @Tags Swagger
|
||||
// @Success 200
|
||||
// @Failure 500
|
||||
// @Router /swagger [get]
|
||||
func (r *SwaggerController) Index(ctx http.Context) http.Response {
|
||||
config := Config{
|
||||
URL: "swagger.json",
|
||||
DocExpansion: "list",
|
||||
DomID: "swagger-ui",
|
||||
InstanceName: swag.Name,
|
||||
DeepLinking: true,
|
||||
}
|
||||
|
||||
// create a template with name
|
||||
index, _ := template.New("swagger_index.html").Parse(indexTemplate)
|
||||
|
||||
var re = regexp.MustCompile(`^(.*/)([^?].*)?[?|.]*$`)
|
||||
|
||||
matches := re.FindStringSubmatch(ctx.Request().Path())
|
||||
path := matches[2]
|
||||
|
||||
fileExt := filepath.Ext(path)
|
||||
|
||||
switch path {
|
||||
case "":
|
||||
return ctx.Response().Redirect(http.StatusMovedPermanently, filepath.Join(matches[1], "index.html"))
|
||||
|
||||
case "index.html":
|
||||
var builder strings.Builder
|
||||
err := index.Execute(&builder, config)
|
||||
if err != nil {
|
||||
return ctx.Response().Status(http.StatusInternalServerError).String(http.StatusText(http.StatusInternalServerError))
|
||||
}
|
||||
|
||||
return ctx.Response().Success().String("html", builder.String())
|
||||
case "swagger.json":
|
||||
return ctx.Response().File("docs/swagger.json")
|
||||
}
|
||||
|
||||
file, err := swaggerFiles.FS.Open(path)
|
||||
if err != nil {
|
||||
return ctx.Response().Status(http.StatusInternalServerError).String(http.StatusText(http.StatusInternalServerError))
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
content, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return ctx.Response().Status(http.StatusInternalServerError).String(http.StatusText(http.StatusInternalServerError))
|
||||
}
|
||||
|
||||
return ctx.Response().Success().String(fileExt[0:], string(content))
|
||||
}
|
||||
|
||||
const indexTemplate = `<!-- HTML for static distribution bundle build -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Swagger UI</title>
|
||||
<link href="https://gfont.cdn.haozi.net/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
|
||||
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
||||
<style>
|
||||
html
|
||||
{
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
*,
|
||||
*:before,
|
||||
*:after
|
||||
{
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body {
|
||||
margin:0;
|
||||
background: #fafafa;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0">
|
||||
<defs>
|
||||
<symbol viewBox="0 0 20 20" id="unlocked">
|
||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="locked">
|
||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="close">
|
||||
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="large-arrow">
|
||||
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="large-arrow-down">
|
||||
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/>
|
||||
</symbol>
|
||||
|
||||
|
||||
<symbol viewBox="0 0 24 24" id="jump-to">
|
||||
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 24 24" id="expand">
|
||||
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>
|
||||
</symbol>
|
||||
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<script src="./swagger-ui-bundle.js"> </script>
|
||||
<script src="./swagger-ui-standalone-preset.js"> </script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
// Build a system
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "{{.URL}}",
|
||||
deepLinking: {{.DeepLinking}},
|
||||
docExpansion: "{{.DocExpansion}}",
|
||||
dom_id: "#{{.DomID}}",
|
||||
persistAuthorization: {{.PersistAuthorization}},
|
||||
validatorUrl: null,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "StandaloneLayout"
|
||||
})
|
||||
window.ui = ui
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
`
|
||||
@@ -36,12 +36,12 @@ func (r *TaskController) Status(ctx http.Context) http.Response {
|
||||
func (r *TaskController) List(ctx http.Context) http.Response {
|
||||
var tasks []models.Task
|
||||
var total int64
|
||||
err := facades.Orm().Query().Paginate(ctx.Request().QueryInt("page", 1), ctx.Request().QueryInt("limit", 10), &tasks, &total)
|
||||
err := facades.Orm().Query().Order("id desc").Paginate(ctx.Request().QueryInt("page", 1), ctx.Request().QueryInt("limit", 10), &tasks, &total)
|
||||
if err != nil {
|
||||
facades.Log().With(map[string]any{
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("[面板][TaskController] 查询任务列表失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, http.Json{
|
||||
@@ -55,11 +55,11 @@ func (r *TaskController) Log(ctx http.Context) http.Response {
|
||||
var task models.Task
|
||||
err := facades.Orm().Query().Where("id", ctx.Request().QueryInt("id")).FirstOrFail(&task)
|
||||
if err != nil {
|
||||
facades.Log().With(map[string]any{
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"id": ctx.Request().QueryInt("id"),
|
||||
"error": err.Error(),
|
||||
}).Error("[面板][TaskController] 查询任务失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
log := tools.Exec("tail -n 1000 " + task.Log)
|
||||
@@ -76,7 +76,7 @@ func (r *TaskController) Delete(ctx http.Context) http.Response {
|
||||
"id": ctx.Request().QueryInt("id"),
|
||||
"error": err.Error(),
|
||||
}).Error("[面板][TaskController] 删除任务失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
|
||||
@@ -4,7 +4,8 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/http/requests"
|
||||
"panel/app/http/requests/user"
|
||||
responses "panel/app/http/responses/user"
|
||||
"panel/app/models"
|
||||
)
|
||||
|
||||
@@ -18,22 +19,31 @@ func NewUserController() *UserController {
|
||||
}
|
||||
}
|
||||
|
||||
// Login 用户登录
|
||||
// Login
|
||||
// @Summary 登录
|
||||
// @Description 通过用户名和密码获取访问令牌
|
||||
// @Tags 用户鉴权
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body requests.Login true "登录信息"
|
||||
// @Success 200 {object} SuccessResponse
|
||||
// @Failure 403 {object} ErrorResponse "用户名或密码错误"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误
|
||||
// @Router /panel/user/login [post]
|
||||
func (r *UserController) Login(ctx http.Context) http.Response {
|
||||
var loginRequest requests.LoginRequest
|
||||
errors, err := ctx.Request().ValidateRequest(&loginRequest)
|
||||
if err != nil {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, err.Error())
|
||||
}
|
||||
if errors != nil {
|
||||
return Error(ctx, http.StatusUnprocessableEntity, errors.One())
|
||||
var loginRequest requests.Login
|
||||
sanitize := Sanitize(ctx, &loginRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
var user models.User
|
||||
err = facades.Orm().Query().Where("username", loginRequest.Username).First(&user)
|
||||
err := facades.Orm().Query().Where("username", loginRequest.Username).First(&user)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][UserController] 查询用户失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "用户").Error("查询用户失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
if user.ID == 0 || !facades.Hash().Check(loginRequest.Password, user.Password) {
|
||||
@@ -43,15 +53,19 @@ func (r *UserController) Login(ctx http.Context) http.Response {
|
||||
if facades.Hash().NeedsRehash(user.Password) {
|
||||
user.Password, err = facades.Hash().Make(loginRequest.Password)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][UserController] 更新密码失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "用户").Error("更新密码失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
token, loginErr := facades.Auth().LoginUsingID(ctx, user.ID)
|
||||
if loginErr != nil {
|
||||
facades.Log().Error("[面板][UserController] 登录失败 ", loginErr)
|
||||
return Error(ctx, http.StatusInternalServerError, loginErr.Error())
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "用户").Error("登录失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, http.Json{
|
||||
@@ -59,21 +73,30 @@ func (r *UserController) Login(ctx http.Context) http.Response {
|
||||
})
|
||||
}
|
||||
|
||||
// Info 用户信息
|
||||
// Info
|
||||
// @Summary 用户信息
|
||||
// @Description 获取当前登录用户信息
|
||||
// @Tags 用户鉴权
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Success 200 {object} SuccessResponse{data=responses.Info}
|
||||
// @Failure 401 {object} ErrorResponse "登录已过期"
|
||||
// @Failure 500 {object} ErrorResponse "系统内部错误"
|
||||
// @Router /panel/user/info [get]
|
||||
func (r *UserController) Info(ctx http.Context) http.Response {
|
||||
var user models.User
|
||||
err := facades.Auth().User(ctx, &user)
|
||||
if err != nil {
|
||||
facades.Log().With(map[string]any{
|
||||
facades.Log().Request(ctx.Request()).With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Error("[面板][UserController] 查询用户信息失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
}).Tags("面板", "用户").Error("获取用户信息失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, http.Json{
|
||||
"id": user.ID,
|
||||
"role": []string{"admin"},
|
||||
"username": user.Username,
|
||||
"email": user.Email,
|
||||
return Success(ctx, responses.Info{
|
||||
ID: user.ID,
|
||||
Role: []string{"admin"},
|
||||
Username: user.Username,
|
||||
Email: user.Email,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func (c *WebsiteController) List(ctx http.Context) http.Response {
|
||||
total, websites, err := c.website.List(page, limit)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站列表失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, http.Json{
|
||||
@@ -83,7 +83,7 @@ func (c *WebsiteController) Add(ctx http.Context) http.Response {
|
||||
newSite, err := c.website.Add(website)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 添加网站失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, newSite)
|
||||
@@ -131,12 +131,12 @@ func (c *WebsiteController) SaveDefaultConfig(ctx http.Context) http.Response {
|
||||
|
||||
if !tools.Write("/www/server/openresty/html/index.html", index, 0644) {
|
||||
facades.Log().Error("[面板][WebsiteController] 保存默认配置失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
if !tools.Write("/www/server/openresty/html/stop.html", stop, 0644) {
|
||||
facades.Log().Error("[面板][WebsiteController] 保存默认配置失败")
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
@@ -156,7 +156,7 @@ func (c *WebsiteController) GetConfig(ctx http.Context) http.Response {
|
||||
config, err := c.website.GetConfig(id)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站配置失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, config)
|
||||
@@ -378,7 +378,7 @@ func (c *WebsiteController) SaveConfig(ctx http.Context) http.Response {
|
||||
err = facades.Orm().Query().Save(&website)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 保存网站配置失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
tools.Write("/www/server/vhost/"+website.Name+".conf", raw, 0644)
|
||||
@@ -403,7 +403,7 @@ func (c *WebsiteController) ClearLog(ctx http.Context) http.Response {
|
||||
err := facades.Orm().Query().Where("id", id).Get(&website)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
tools.Remove("/www/wwwlogs/" + website.Name + ".log")
|
||||
@@ -422,14 +422,14 @@ func (c *WebsiteController) UpdateRemark(ctx http.Context) http.Response {
|
||||
err := facades.Orm().Query().Where("id", id).Get(&website)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
website.Remark = ctx.Request().Input("remark")
|
||||
err = facades.Orm().Query().Save(&website)
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 保存网站备注失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, nil)
|
||||
@@ -440,7 +440,7 @@ func (c *WebsiteController) BackupList(ctx http.Context) http.Response {
|
||||
backupList, err := c.backup.WebsiteList()
|
||||
if err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站备份列表失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
return Success(ctx, backupList)
|
||||
@@ -550,14 +550,14 @@ func (c *WebsiteController) ResetConfig(ctx http.Context) http.Response {
|
||||
website := models.Website{}
|
||||
if err := facades.Orm().Query().Where("id", id).Get(&website); err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
website.Status = true
|
||||
website.Ssl = false
|
||||
if err := facades.Orm().Query().Save(&website); err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 保存网站配置失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
raw := fmt.Sprintf(`
|
||||
@@ -640,13 +640,13 @@ func (c *WebsiteController) Status(ctx http.Context) http.Response {
|
||||
website := models.Website{}
|
||||
if err := facades.Orm().Query().Where("id", id).Get(&website); err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 获取网站信息失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
website.Status = ctx.Request().InputBool("status")
|
||||
if err := facades.Orm().Query().Save(&website); err != nil {
|
||||
facades.Log().Error("[面板][WebsiteController] 保存网站配置失败 ", err)
|
||||
return Error(ctx, http.StatusInternalServerError, "系统内部错误")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
raw := tools.Read("/www/server/vhost/" + website.Name + ".conf")
|
||||
|
||||
+1
-5
@@ -2,8 +2,6 @@ package http
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
|
||||
"panel/app/http/middleware"
|
||||
)
|
||||
|
||||
type Kernel struct {
|
||||
@@ -12,7 +10,5 @@ type Kernel struct {
|
||||
// The application's global HTTP middleware stack.
|
||||
// These middleware are run during every request to your application.
|
||||
func (kernel Kernel) Middleware() []http.Middleware {
|
||||
return []http.Middleware{
|
||||
middleware.Static(),
|
||||
}
|
||||
return []http.Middleware{}
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-contrib/static"
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/gin"
|
||||
|
||||
"panel/app/services"
|
||||
)
|
||||
|
||||
func Static() http.Middleware {
|
||||
return func(ctx http.Context) {
|
||||
// 自动纠正 URL 格式
|
||||
if ctx.Request().Path() == services.NewSettingImpl().Get("entrance", "/") && ctx.Request().Path() != "/" {
|
||||
// ctx.Response().Redirect(http.StatusFound, ctx.Request().Path()+"/")
|
||||
ctx.Response().Writer().WriteHeader(http.StatusFound)
|
||||
_, err := ctx.Response().Writer().Write([]byte(fmt.Sprintf(`<html><head><meta http-equiv="refresh" content="0;url=%s/"></head></html>`, ctx.Request().Path())))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ctx.Response().Flush()
|
||||
return
|
||||
}
|
||||
|
||||
static.Serve(services.NewSettingImpl().Get("entrance", "/"), static.LocalFile("public", false))(ctx.(*gin.Context).Instance())
|
||||
ctx.Request().Next()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type CertDeploy struct {
|
||||
ID uint `form:"id" json:"id"`
|
||||
WebsiteID uint `form:"website_id" json:"website_id"`
|
||||
}
|
||||
|
||||
func (r *CertDeploy) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *CertDeploy) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"id": "required|uint|min:1|exists:certs,id",
|
||||
"website_id": "required|uint|min:1|exists:websites,id",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *CertDeploy) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *CertDeploy) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *CertDeploy) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type CertShowAndDestroy struct {
|
||||
ID uint `form:"id" json:"id"`
|
||||
}
|
||||
|
||||
func (r *CertShowAndDestroy) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *CertShowAndDestroy) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"id": "required|uint|min:1|exists:certs,id",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *CertShowAndDestroy) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *CertShowAndDestroy) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *CertShowAndDestroy) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type CertStore struct {
|
||||
Type string `form:"type" json:"type"`
|
||||
Domains []string `form:"domains" json:"domains"`
|
||||
AutoRenew bool `form:"auto_renew" json:"auto_renew"`
|
||||
UserID uint `form:"user_id" json:"user_id"`
|
||||
DNSID *uint `form:"dns_id" json:"dns_id"`
|
||||
WebsiteID *uint `form:"website_id" json:"website_id"`
|
||||
}
|
||||
|
||||
func (r *CertStore) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *CertStore) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"type": "required|in:P256,P384,2048,4096",
|
||||
"domains": "required|slice",
|
||||
"auto_renew": "required|bool",
|
||||
"user_id": "required|uint|exists:cert_users,id",
|
||||
"dns_id": "uint",
|
||||
"website_id": "uint",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *CertStore) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *CertStore) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *CertStore) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
// TODO 由于验证器 filter 标签的问题,暂时这里这样处理
|
||||
userID, exist := data.Get("user_id")
|
||||
if exist {
|
||||
err := data.Set("user_id", cast.ToUint(userID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
dnsID, exist := data.Get("dns_id")
|
||||
if exist {
|
||||
err := data.Set("dns_id", cast.ToUint(dnsID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
websiteID, exist := data.Get("website_id")
|
||||
if exist {
|
||||
err := data.Set("website_id", cast.ToUint(websiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type CertUpdate struct {
|
||||
ID uint `form:"id" json:"id"`
|
||||
Type string `form:"type" json:"type"`
|
||||
Domains []string `form:"domains" json:"domains"`
|
||||
AutoRenew bool `form:"auto_renew" json:"auto_renew"`
|
||||
UserID uint `form:"user_id" json:"user_id"`
|
||||
DNSID *uint `form:"dns_id" json:"dns_id"`
|
||||
WebsiteID *uint `form:"website_id" json:"website_id"`
|
||||
}
|
||||
|
||||
func (r *CertUpdate) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *CertUpdate) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"id": "required|uint|min:1|exists:certs,id",
|
||||
"type": "required|in:P256,P384,2048,4096",
|
||||
"domains": "required|slice",
|
||||
"auto_renew": "required|bool",
|
||||
"user_id": "required|uint|exists:cert_users,id",
|
||||
"dns_id": "uint",
|
||||
"website_id": "uint",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *CertUpdate) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *CertUpdate) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *CertUpdate) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
// TODO 由于验证器 filter 标签的问题,暂时这里这样处理
|
||||
userID, exist := data.Get("user_id")
|
||||
if exist {
|
||||
err := data.Set("user_id", cast.ToUint(userID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
dnsID, exist := data.Get("dns_id")
|
||||
if exist {
|
||||
err := data.Set("dns_id", cast.ToUint(dnsID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
websiteID, exist := data.Get("website_id")
|
||||
if exist {
|
||||
err := data.Set("website_id", cast.ToUint(websiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type DNSShowAndDestroy struct {
|
||||
ID uint `form:"id" json:"id"`
|
||||
}
|
||||
|
||||
func (r *DNSShowAndDestroy) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *DNSShowAndDestroy) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"id": "required|uint|min:1|exists:cert_dns,id",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *DNSShowAndDestroy) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *DNSShowAndDestroy) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *DNSShowAndDestroy) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
|
||||
"panel/pkg/acme"
|
||||
)
|
||||
|
||||
type DNSStore struct {
|
||||
Type string `form:"type" json:"type"`
|
||||
Name string `form:"name" json:"name"`
|
||||
Data acme.DNSParam `form:"data" json:"data"`
|
||||
}
|
||||
|
||||
func (r *DNSStore) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *DNSStore) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"type": "required|in:dnspod,aliyun,cloudflare",
|
||||
"name": "required",
|
||||
"data": "required",
|
||||
"data.id": "required_if:type,dnspod",
|
||||
"data.token": "required_if:type,dnspod",
|
||||
"data.access_key": "required_if:type,aliyun",
|
||||
"data.secret_key": "required_if:type,aliyun",
|
||||
"data.email": "required_if:type,cloudflare",
|
||||
"data.api_key": "required_if:type,cloudflare",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *DNSStore) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *DNSStore) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *DNSStore) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
|
||||
"panel/pkg/acme"
|
||||
)
|
||||
|
||||
type DNSUpdate struct {
|
||||
ID uint `form:"id" json:"id"`
|
||||
Type string `form:"type" json:"type"`
|
||||
Name string `form:"name" json:"name"`
|
||||
Data acme.DNSParam `form:"data" json:"data"`
|
||||
}
|
||||
|
||||
func (r *DNSUpdate) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *DNSUpdate) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"id": "required|uint|min:1|exists:cert_dns,id",
|
||||
"type": "required|in:dnspod,aliyun,cloudflare",
|
||||
"name": "required",
|
||||
"data": "required",
|
||||
"data.id": "required_if:type,dnspod",
|
||||
"data.token": "required_if:type,dnspod",
|
||||
"data.access_key": "required_if:type,aliyun",
|
||||
"data.secret_key": "required_if:type,aliyun",
|
||||
"data.email": "required_if:type,cloudflare",
|
||||
"data.api_key": "required_if:type,cloudflare",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *DNSUpdate) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *DNSUpdate) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *DNSUpdate) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type Obtain struct {
|
||||
ID uint `form:"id" json:"id"`
|
||||
}
|
||||
|
||||
func (r *Obtain) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Obtain) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"id": "required|exists:certs,id",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Obtain) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *Obtain) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *Obtain) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type Renew struct {
|
||||
ID uint `form:"id" json:"id"`
|
||||
}
|
||||
|
||||
func (r *Renew) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Renew) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"id": "required|exists:certs,id",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Renew) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *Renew) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *Renew) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type UserShowAndDestroy struct {
|
||||
ID uint `form:"id" json:"id"`
|
||||
}
|
||||
|
||||
func (r *UserShowAndDestroy) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *UserShowAndDestroy) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"id": "required|uint|min:1|exists:cert_users,id",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *UserShowAndDestroy) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *UserShowAndDestroy) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *UserShowAndDestroy) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type UserStore struct {
|
||||
CA string `form:"ca" json:"ca"`
|
||||
Email string `form:"email" json:"email"`
|
||||
Kid string `form:"kid" json:"kid"`
|
||||
HmacEncoded string `form:"hmac_encoded" json:"hmac_encoded"`
|
||||
KeyType string `form:"key_type" json:"key_type"`
|
||||
}
|
||||
|
||||
func (r *UserStore) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *UserStore) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"ca": "required|in:letsencrypt,zerossl,sslcom,google,buypass",
|
||||
"email": "required|email",
|
||||
"kid": "required_unless:ca,letsencrypt,buypass",
|
||||
"hmac_encoded": "required_unless:ca,letsencrypt,buypass",
|
||||
"key_type": "required|in:P256,P384,2048,4096",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *UserStore) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *UserStore) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *UserStore) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type UserUpdate struct {
|
||||
ID uint `form:"id" json:"id"`
|
||||
CA string `form:"ca" json:"ca"`
|
||||
Email string `form:"email" json:"email"`
|
||||
Kid string `form:"kid" json:"kid"`
|
||||
HmacEncoded string `form:"hmac_encoded" json:"hmac_encoded"`
|
||||
KeyType string `form:"key_type" json:"key_type"`
|
||||
}
|
||||
|
||||
func (r *UserUpdate) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *UserUpdate) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"id": "required|uint|min:1|exists:cert_users,id",
|
||||
"ca": "required|in:letsencrypt,zerossl,sslcom,google,buypass",
|
||||
"email": "required|email",
|
||||
"kid": "required_unless:ca,letsencrypt,buypass",
|
||||
"hmac_encoded": "required_unless:ca,letsencrypt,buypass",
|
||||
"key_type": "required|in:P256,P384,2048,4096",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *UserUpdate) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *UserUpdate) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *UserUpdate) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package commonrequests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type Paginate struct {
|
||||
Page int `form:"page" json:"page"`
|
||||
Limit int `form:"limit" json:"limit"`
|
||||
}
|
||||
|
||||
func (r *Paginate) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Paginate) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"page": "required|uint|min:1",
|
||||
"limit": "required|uint|min:1",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Paginate) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"page.required": "分页参数 page 不能为空",
|
||||
"page.uint": "分页参数 page 必须是一个整数",
|
||||
"page.min": "分页参数 page 必须大于等于 1",
|
||||
"limit.required": "分页参数 limit 不能为空",
|
||||
"limit.uint": "分页参数 limit 必须是一个整数",
|
||||
"limit.min": "分页参数 limit 必须大于等于 1",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Paginate) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *Paginate) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type Update struct {
|
||||
Name string `form:"name" json:"name"`
|
||||
Port uint `form:"port" json:"port" filter:"uint"`
|
||||
BackupPath string `form:"backup_path" json:"backup_path"`
|
||||
WebsitePath string `form:"website_path" json:"website_path"`
|
||||
Entrance string `form:"entrance" json:"entrance"`
|
||||
UserName string `form:"username" json:"username"`
|
||||
Email string `form:"email" json:"email"`
|
||||
Password string `form:"password" json:"password"`
|
||||
}
|
||||
|
||||
func (r *Update) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Update) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"name": "required|string:2,20",
|
||||
"port": "required|int:1000,65535",
|
||||
"backup_path": "required|string:2,255",
|
||||
"website_path": "required|string:2,255",
|
||||
"entrance": `required|regex:^/(\w+)?$|not_in:/api`,
|
||||
"username": "required|string:2,20",
|
||||
"email": "required|email",
|
||||
"password": "string:8,255",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Update) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"port.int": "port 值必须是一个整数且在 1000 - 65535 之间",
|
||||
"password.string": "password 必须是一个字符串且长度在 8 - 255 之间",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Update) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *Update) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
@@ -5,39 +5,34 @@ import (
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type LoginRequest struct {
|
||||
type Login struct {
|
||||
Username string `json:"username" form:"username"`
|
||||
Password string `json:"password" form:"password"`
|
||||
|
||||
CaptchaID string `json:"captcha_id" form:"captcha_id"`
|
||||
Captcha string `json:"captcha" form:"captcha"`
|
||||
}
|
||||
|
||||
func (r *LoginRequest) Authorize(ctx http.Context) error {
|
||||
func (r *Login) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *LoginRequest) Rules(ctx http.Context) map[string]string {
|
||||
func (r *Login) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"username": "required",
|
||||
"password": "required|min_len:8",
|
||||
"captcha": "captcha:true",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *LoginRequest) Messages(ctx http.Context) map[string]string {
|
||||
func (r *Login) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"username.required": "登录名不能为空",
|
||||
"password.required": "密码不能为空",
|
||||
"password.min_len": "密码长度不能小于 8 位",
|
||||
"captcha.captcha": "验证码错误",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *LoginRequest) Attributes(ctx http.Context) map[string]string {
|
||||
func (r *Login) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *LoginRequest) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
func (r *Login) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package responses
|
||||
|
||||
import "panel/app/models"
|
||||
|
||||
type CertList struct {
|
||||
Total int64 `json:"total"`
|
||||
Items []models.Cert `json:"items"`
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package responses
|
||||
|
||||
import "panel/app/models"
|
||||
|
||||
type DNSList struct {
|
||||
Total int64 `json:"total"`
|
||||
Items []models.CertDNS `json:"items"`
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package responses
|
||||
|
||||
import "panel/app/models"
|
||||
|
||||
type UserList struct {
|
||||
Total int64 `json:"total"`
|
||||
Items []models.CertUser `json:"items"`
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package responses
|
||||
|
||||
type Settings struct {
|
||||
Name string `json:"name"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Email string `json:"email"`
|
||||
Port string `json:"port"`
|
||||
Entrance string `json:"entrance"`
|
||||
WebsitePath string `json:"website_path"`
|
||||
BackupPath string `json:"backup_path"`
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package responses
|
||||
|
||||
type Info struct {
|
||||
ID uint `json:"id"`
|
||||
Role []string `json:"role"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
)
|
||||
|
||||
type Cert struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
UserID uint `gorm:"default:null" json:"user_id"` // 关联的 ACME 用户 ID
|
||||
WebsiteID *uint `gorm:"default:null" json:"website_id"` // 关联的网站 ID
|
||||
DNSID *uint `gorm:"column:dns_id;default:null" json:"dns_id"` // 关联的 DNS ID
|
||||
Type string `gorm:"not null" json:"type"` // 证书类型 (P256, P384, 2048, 4096)
|
||||
Domains []string `gorm:"type:json;serializer:json" json:"domains"`
|
||||
AutoRenew bool `gorm:"default:true" json:"auto_renew"` // 自动续签
|
||||
CertURL *string `gorm:"default:null" json:"cert_url"` // 证书 URL (续签时使用)
|
||||
Cert string `gorm:"default:null" json:"cert"` // 证书内容
|
||||
Key string `gorm:"default:null" json:"key"` // 私钥内容
|
||||
CreatedAt carbon.DateTime `gorm:"autoCreateTime;column:created_at" json:"created_at"`
|
||||
UpdatedAt carbon.DateTime `gorm:"autoUpdateTime;column:updated_at" json:"updated_at"`
|
||||
|
||||
Website *Website `gorm:"foreignKey:WebsiteID" json:"website"`
|
||||
User *CertUser `gorm:"foreignKey:UserID" json:"user"`
|
||||
DNS *CertDNS `gorm:"foreignKey:DNSID" json:"dns"`
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
|
||||
"panel/pkg/acme"
|
||||
)
|
||||
|
||||
type CertDNS struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Name string `gorm:"not null" json:"name"` // 备注名称
|
||||
Type string `gorm:"not null" json:"type"` // DNS 提供商 (dnspod, aliyun, cloudflare)
|
||||
Data acme.DNSParam `gorm:"type:json;serializer:json" json:"dns_param"`
|
||||
CreatedAt carbon.DateTime `gorm:"autoCreateTime;column:created_at" json:"created_at"`
|
||||
UpdatedAt carbon.DateTime `gorm:"autoUpdateTime;column:updated_at" json:"updated_at"`
|
||||
|
||||
Certs []*Cert `gorm:"foreignKey:DNSID" json:"-"`
|
||||
}
|
||||
|
||||
func (CertDNS) TableName() string {
|
||||
return "cert_dns"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
)
|
||||
|
||||
type CertUser struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Email string `gorm:"not null" json:"email"`
|
||||
CA string `gorm:"not null" json:"ca"` // CA 提供商 (letsencrypt, zerossl, sslcom, google, buypass)
|
||||
Kid *string `gorm:"default:null" json:"kid"`
|
||||
HmacEncoded *string `gorm:"default:null" json:"hmac_encoded"`
|
||||
PrivateKey string `gorm:"not null" json:"private_key"`
|
||||
KeyType string `gorm:"not null" json:"key_type"`
|
||||
CreatedAt carbon.DateTime `gorm:"autoCreateTime;column:created_at" json:"created_at"`
|
||||
UpdatedAt carbon.DateTime `gorm:"autoUpdateTime;column:updated_at" json:"updated_at"`
|
||||
|
||||
Certs []*Cert `gorm:"foreignKey:UserID" json:"-"`
|
||||
}
|
||||
@@ -9,7 +9,6 @@ const (
|
||||
SettingKeyMonitorDays = "monitor_days"
|
||||
SettingKeyBackupPath = "backup_path"
|
||||
SettingKeyWebsitePath = "website_path"
|
||||
SettingKeyEntrance = "entrance"
|
||||
SettingKeyMysqlRootPassword = "mysql_root_password"
|
||||
SettingKeySshHost = "ssh_host"
|
||||
SettingKeySshPort = "ssh_port"
|
||||
|
||||
@@ -14,4 +14,6 @@ type Website struct {
|
||||
Remark string `gorm:"default:''" json:"remark"`
|
||||
CreatedAt carbon.DateTime `gorm:"autoCreateTime;column:created_at" json:"created_at"`
|
||||
UpdatedAt carbon.DateTime `gorm:"autoUpdateTime;column:updated_at" json:"updated_at"`
|
||||
|
||||
Cert *Cert `gorm:"foreignKey:WebsiteID" json:"cert"`
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ func (receiver *RouteServiceProvider) Boot(app foundation.Application) {
|
||||
|
||||
receiver.configureRateLimiting()
|
||||
|
||||
routes.Api()
|
||||
routes.Plugin()
|
||||
routes.Api()
|
||||
}
|
||||
|
||||
func (receiver *RouteServiceProvider) configureRateLimiting() {
|
||||
|
||||
+4
-3
@@ -3,6 +3,7 @@ package rules
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type Exists struct {
|
||||
@@ -21,8 +22,8 @@ func (receiver *Exists) Passes(_ validation.Data, val any, options ...any) bool
|
||||
// 第二个参数,字段名称,如 id
|
||||
fieldName := options[1].(string)
|
||||
// 用户请求过来的数据
|
||||
requestValue, ok := val.(string)
|
||||
if !ok {
|
||||
requestValue, err := cast.ToStringE(val)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -40,7 +41,7 @@ func (receiver *Exists) Passes(_ validation.Data, val any, options ...any) bool
|
||||
query = query.OrWhere(options[i].(string), requestValue)
|
||||
}
|
||||
}
|
||||
err := query.Count(&count)
|
||||
err = query.Count(&count)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package rules
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type NotExists struct {
|
||||
@@ -21,8 +22,8 @@ func (receiver *NotExists) Passes(_ validation.Data, val any, options ...any) bo
|
||||
// 第二个参数,字段名称,如 id
|
||||
fieldName := options[1].(string)
|
||||
// 用户请求过来的数据
|
||||
requestValue, ok := val.(string)
|
||||
if !ok {
|
||||
requestValue, err := cast.ToStringE(val)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -40,7 +41,7 @@ func (receiver *NotExists) Passes(_ validation.Data, val any, options ...any) bo
|
||||
query = query.OrWhere(options[i].(string), requestValue)
|
||||
}
|
||||
}
|
||||
err := query.Count(&count)
|
||||
err = query.Count(&count)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -0,0 +1,474 @@
|
||||
// Package services 证书服务
|
||||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/go-acme/lego/v4/certcrypto"
|
||||
"github.com/go-acme/lego/v4/certificate"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
requests "panel/app/http/requests/cert"
|
||||
"panel/app/models"
|
||||
"panel/pkg/acme"
|
||||
"panel/pkg/tools"
|
||||
)
|
||||
|
||||
type Cert interface {
|
||||
UserStore(request requests.UserStore) error
|
||||
UserUpdate(request requests.UserUpdate) error
|
||||
UserShow(ID uint) (models.CertUser, error)
|
||||
UserDestroy(ID uint) error
|
||||
DNSStore(request requests.DNSStore) error
|
||||
DNSUpdate(request requests.DNSUpdate) error
|
||||
DNSShow(ID uint) (models.CertDNS, error)
|
||||
DNSDestroy(ID uint) error
|
||||
CertStore(request requests.CertStore) error
|
||||
CertUpdate(request requests.CertUpdate) error
|
||||
CertShow(ID uint) (models.Cert, error)
|
||||
CertDestroy(ID uint) error
|
||||
ObtainAuto(ID uint) (certificate.Resource, error)
|
||||
ObtainManual(ID uint) (certificate.Resource, error)
|
||||
ManualDNS(ID uint) (map[string]acme.Resolve, error)
|
||||
Renew(ID uint) (certificate.Resource, error)
|
||||
}
|
||||
|
||||
type CertImpl struct {
|
||||
}
|
||||
|
||||
func NewCertImpl() *CertImpl {
|
||||
return &CertImpl{}
|
||||
}
|
||||
|
||||
// UserStore 添加用户
|
||||
func (s *CertImpl) UserStore(request requests.UserStore) error {
|
||||
var user models.CertUser
|
||||
user.CA = request.CA
|
||||
user.Email = request.Email
|
||||
user.Kid = &request.Kid
|
||||
user.HmacEncoded = &request.HmacEncoded
|
||||
user.KeyType = request.KeyType
|
||||
|
||||
var err error
|
||||
var client *acme.Client
|
||||
switch user.CA {
|
||||
case "letsencrypt":
|
||||
client, err = acme.NewRegisterClient(user.Email, acme.CALetEncrypt, certcrypto.KeyType(user.KeyType))
|
||||
case "buypass":
|
||||
client, err = acme.NewRegisterClient(user.Email, acme.CABuypass, certcrypto.KeyType(user.KeyType))
|
||||
case "zerossl":
|
||||
client, err = acme.NewRegisterWithExternalAccountBindingClient(user.Email, *user.Kid, *user.HmacEncoded, acme.CAZeroSSL, certcrypto.KeyType(user.KeyType))
|
||||
case "sslcom":
|
||||
client, err = acme.NewRegisterWithExternalAccountBindingClient(user.Email, *user.Kid, *user.HmacEncoded, acme.CASSLcom, certcrypto.KeyType(user.KeyType))
|
||||
case "google":
|
||||
client, err = acme.NewRegisterWithExternalAccountBindingClient(user.Email, *user.Kid, *user.HmacEncoded, acme.CAGoogle, certcrypto.KeyType(user.KeyType))
|
||||
default:
|
||||
return errors.New("CA 提供商不支持")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return errors.New("向 CA 注册账号失败,请检查参数是否正确")
|
||||
}
|
||||
|
||||
privateKey, err := acme.GetPrivateKey(client.User.GetPrivateKey(), acme.KeyType(user.KeyType))
|
||||
if err != nil {
|
||||
return errors.New("获取私钥失败")
|
||||
}
|
||||
user.PrivateKey = string(privateKey)
|
||||
|
||||
return facades.Orm().Query().Create(&user)
|
||||
}
|
||||
|
||||
// UserUpdate 更新用户
|
||||
func (s *CertImpl) UserUpdate(request requests.UserUpdate) error {
|
||||
var user models.CertUser
|
||||
err := facades.Orm().Query().Where("id = ?", request.ID).First(&user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user.CA = request.CA
|
||||
user.Email = request.Email
|
||||
user.Kid = &request.Kid
|
||||
user.HmacEncoded = &request.HmacEncoded
|
||||
user.KeyType = request.KeyType
|
||||
|
||||
var client *acme.Client
|
||||
switch user.CA {
|
||||
case "letsencrypt":
|
||||
client, err = acme.NewRegisterClient(user.Email, acme.CALetEncrypt, certcrypto.KeyType(user.KeyType))
|
||||
case "buypass":
|
||||
client, err = acme.NewRegisterClient(user.Email, acme.CABuypass, certcrypto.KeyType(user.KeyType))
|
||||
case "zerossl":
|
||||
client, err = acme.NewRegisterWithExternalAccountBindingClient(user.Email, *user.Kid, *user.HmacEncoded, acme.CAZeroSSL, certcrypto.KeyType(user.KeyType))
|
||||
case "sslcom":
|
||||
client, err = acme.NewRegisterWithExternalAccountBindingClient(user.Email, *user.Kid, *user.HmacEncoded, acme.CASSLcom, certcrypto.KeyType(user.KeyType))
|
||||
case "google":
|
||||
client, err = acme.NewRegisterWithExternalAccountBindingClient(user.Email, *user.Kid, *user.HmacEncoded, acme.CAGoogle, certcrypto.KeyType(user.KeyType))
|
||||
default:
|
||||
return errors.New("CA 提供商不支持")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return errors.New("向 CA 注册账号失败,请检查参数是否正确")
|
||||
}
|
||||
|
||||
privateKey, err := acme.GetPrivateKey(client.User.GetPrivateKey(), acme.KeyType(user.KeyType))
|
||||
if err != nil {
|
||||
return errors.New("获取私钥失败")
|
||||
}
|
||||
user.PrivateKey = string(privateKey)
|
||||
|
||||
return facades.Orm().Query().Save(&user)
|
||||
}
|
||||
|
||||
// UserShow 根据 ID 获取用户
|
||||
func (s *CertImpl) UserShow(ID uint) (models.CertUser, error) {
|
||||
var user models.CertUser
|
||||
err := facades.Orm().Query().With("Certs").Where("id = ?", ID).First(&user)
|
||||
|
||||
return user, err
|
||||
}
|
||||
|
||||
// UserDestroy 删除用户
|
||||
func (s *CertImpl) UserDestroy(ID uint) error {
|
||||
var cert models.Cert
|
||||
err := facades.Orm().Query().Where("user_id = ?", ID).First(&cert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cert.ID != 0 {
|
||||
return errors.New("该用户下存在证书,无法删除")
|
||||
}
|
||||
|
||||
_, err = facades.Orm().Query().Delete(&models.CertUser{}, ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// DNSStore 添加 DNS
|
||||
func (s *CertImpl) DNSStore(request requests.DNSStore) error {
|
||||
var dns models.CertDNS
|
||||
dns.Type = request.Type
|
||||
dns.Name = request.Name
|
||||
dns.Data = request.Data
|
||||
|
||||
return facades.Orm().Query().Create(&dns)
|
||||
}
|
||||
|
||||
// DNSUpdate 更新 DNS
|
||||
func (s *CertImpl) DNSUpdate(request requests.DNSUpdate) error {
|
||||
var dns models.CertDNS
|
||||
err := facades.Orm().Query().Where("id = ?", request.ID).First(&dns)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dns.Type = request.Type
|
||||
dns.Name = request.Name
|
||||
dns.Data = request.Data
|
||||
|
||||
return facades.Orm().Query().Save(&dns)
|
||||
}
|
||||
|
||||
// DNSShow 根据 ID 获取 DNS
|
||||
func (s *CertImpl) DNSShow(ID uint) (models.CertDNS, error) {
|
||||
var dns models.CertDNS
|
||||
err := facades.Orm().Query().With("Certs").Where("id = ?", ID).First(&dns)
|
||||
|
||||
return dns, err
|
||||
}
|
||||
|
||||
// DNSDestroy 删除 DNS
|
||||
func (s *CertImpl) DNSDestroy(ID uint) error {
|
||||
var cert models.Cert
|
||||
err := facades.Orm().Query().Where("dns_id = ?", ID).First(&cert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cert.ID != 0 {
|
||||
return errors.New("该 DNS 接口下存在证书,无法删除")
|
||||
}
|
||||
|
||||
_, err = facades.Orm().Query().Delete(&models.CertDNS{}, ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// CertStore 添加证书
|
||||
func (s *CertImpl) CertStore(request requests.CertStore) error {
|
||||
var cert models.Cert
|
||||
cert.Type = request.Type
|
||||
cert.Domains = request.Domains
|
||||
cert.AutoRenew = request.AutoRenew
|
||||
cert.UserID = request.UserID
|
||||
|
||||
if request.DNSID != nil {
|
||||
cert.DNSID = request.DNSID
|
||||
}
|
||||
if request.WebsiteID != nil {
|
||||
cert.WebsiteID = request.WebsiteID
|
||||
}
|
||||
|
||||
return facades.Orm().Query().Create(&cert)
|
||||
}
|
||||
|
||||
// CertUpdate 更新证书
|
||||
func (s *CertImpl) CertUpdate(request requests.CertUpdate) error {
|
||||
var cert models.Cert
|
||||
err := facades.Orm().Query().Where("id = ?", request.ID).First(&cert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cert.Type = request.Type
|
||||
cert.Domains = request.Domains
|
||||
cert.AutoRenew = request.AutoRenew
|
||||
cert.UserID = request.UserID
|
||||
|
||||
if request.DNSID != nil {
|
||||
cert.DNSID = request.DNSID
|
||||
}
|
||||
if request.WebsiteID != nil {
|
||||
cert.WebsiteID = request.WebsiteID
|
||||
}
|
||||
|
||||
return facades.Orm().Query().Save(&cert)
|
||||
}
|
||||
|
||||
// CertShow 根据 ID 获取证书
|
||||
func (s *CertImpl) CertShow(ID uint) (models.Cert, error) {
|
||||
var cert models.Cert
|
||||
err := facades.Orm().Query().With("User").With("DNS").With("Website").Where("id = ?", ID).First(&cert)
|
||||
|
||||
return cert, err
|
||||
}
|
||||
|
||||
// CertDestroy 删除证书
|
||||
func (s *CertImpl) CertDestroy(ID uint) error {
|
||||
var cert models.Cert
|
||||
err := facades.Orm().Query().Where("id = ?", ID).First(&cert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = facades.Orm().Query().Delete(&models.Cert{}, ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// ObtainAuto 自动签发证书
|
||||
func (s *CertImpl) ObtainAuto(ID uint) (certificate.Resource, error) {
|
||||
var cert models.Cert
|
||||
err := facades.Orm().Query().With("Website").With("User").With("DNS").Where("id = ?", ID).First(&cert)
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
var ca string
|
||||
switch cert.User.CA {
|
||||
case "letsencrypt":
|
||||
ca = acme.CALetEncrypt
|
||||
case "buypass":
|
||||
ca = acme.CABuypass
|
||||
case "zerossl":
|
||||
ca = acme.CAZeroSSL
|
||||
case "sslcom":
|
||||
ca = acme.CASSLcom
|
||||
case "google":
|
||||
ca = acme.CAGoogle
|
||||
}
|
||||
|
||||
client, err := acme.NewPrivateKeyClient(cert.User.Email, cert.User.PrivateKey, ca, certcrypto.KeyType(cert.User.KeyType))
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
if cert.DNS != nil {
|
||||
err = client.UseDns(acme.DnsType(cert.DNS.Type), cert.DNS.Data)
|
||||
} else {
|
||||
if cert.Website == nil {
|
||||
return certificate.Resource{}, errors.New("该证书没有关联网站,无法自动签发")
|
||||
} else {
|
||||
err = client.UseHTTP(cert.Website.Path)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
ssl, err := client.ObtainSSL(cert.Domains)
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
cert.CertURL = &ssl.CertURL
|
||||
cert.Cert = string(ssl.Certificate)
|
||||
cert.Key = string(ssl.PrivateKey)
|
||||
err = facades.Orm().Query().Save(&cert)
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
if cert.Website != nil {
|
||||
tools.Write("/www/server/vhost/ssl/"+cert.Website.Name+".pem", string(ssl.Certificate), 0644)
|
||||
tools.Write("/www/server/vhost/ssl/"+cert.Website.Name+".key", string(ssl.PrivateKey), 0644)
|
||||
tools.Exec("systemctl reload openresty")
|
||||
}
|
||||
|
||||
return ssl, nil
|
||||
}
|
||||
|
||||
// ObtainManual 手动签发证书
|
||||
func (s *CertImpl) ObtainManual(ID uint) (certificate.Resource, error) {
|
||||
var cert models.Cert
|
||||
err := facades.Orm().Query().With("User").Where("id = ?", ID).First(&cert)
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
var ca string
|
||||
switch cert.User.CA {
|
||||
case "letsencrypt":
|
||||
ca = acme.CALetEncrypt
|
||||
case "buypass":
|
||||
ca = acme.CABuypass
|
||||
case "zerossl":
|
||||
ca = acme.CAZeroSSL
|
||||
case "sslcom":
|
||||
ca = acme.CASSLcom
|
||||
case "google":
|
||||
ca = acme.CAGoogle
|
||||
}
|
||||
|
||||
client, err := acme.NewPrivateKeyClient(cert.User.Email, cert.User.PrivateKey, ca, certcrypto.KeyType(cert.User.KeyType))
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
err = client.UseManualDns()
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
ssl, err := client.ObtainSSL(cert.Domains)
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
cert.CertURL = &ssl.CertURL
|
||||
cert.Cert = string(ssl.Certificate)
|
||||
cert.Key = string(ssl.PrivateKey)
|
||||
err = facades.Orm().Query().Save(&cert)
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
if cert.Website != nil {
|
||||
tools.Write("/www/server/vhost/ssl/"+cert.Website.Name+".pem", string(ssl.Certificate), 0644)
|
||||
tools.Write("/www/server/vhost/ssl/"+cert.Website.Name+".key", string(ssl.PrivateKey), 0644)
|
||||
tools.Exec("systemctl reload openresty")
|
||||
}
|
||||
|
||||
return ssl, nil
|
||||
}
|
||||
|
||||
// ManualDNS 获取手动 DNS 解析信息
|
||||
func (s *CertImpl) ManualDNS(ID uint) (map[string]acme.Resolve, error) {
|
||||
var cert models.Cert
|
||||
err := facades.Orm().Query().With("User").Where("id = ?", ID).First(&cert)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ca string
|
||||
switch cert.User.CA {
|
||||
case "letsencrypt":
|
||||
ca = acme.CALetEncrypt
|
||||
case "buypass":
|
||||
ca = acme.CABuypass
|
||||
case "zerossl":
|
||||
ca = acme.CAZeroSSL
|
||||
case "sslcom":
|
||||
ca = acme.CASSLcom
|
||||
case "google":
|
||||
ca = acme.CAGoogle
|
||||
}
|
||||
|
||||
client, err := acme.NewPrivateKeyClient(cert.User.Email, cert.User.PrivateKey, ca, certcrypto.KeyType(cert.User.KeyType))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = client.UseManualDns()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client.GetDNSResolve(cert.Domains)
|
||||
}
|
||||
|
||||
// Renew 续签证书
|
||||
func (s *CertImpl) Renew(ID uint) (certificate.Resource, error) {
|
||||
var cert models.Cert
|
||||
err := facades.Orm().Query().With("Website").With("User").With("DNS").Where("id = ?", ID).First(&cert)
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
var ca string
|
||||
switch cert.User.CA {
|
||||
case "letsencrypt":
|
||||
ca = acme.CALetEncrypt
|
||||
case "buypass":
|
||||
ca = acme.CABuypass
|
||||
case "zerossl":
|
||||
ca = acme.CAZeroSSL
|
||||
case "sslcom":
|
||||
ca = acme.CASSLcom
|
||||
case "google":
|
||||
ca = acme.CAGoogle
|
||||
}
|
||||
|
||||
client, err := acme.NewPrivateKeyClient(cert.User.Email, cert.User.PrivateKey, ca, certcrypto.KeyType(cert.User.KeyType))
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
if cert.CertURL == nil {
|
||||
return certificate.Resource{}, errors.New("该证书没有签发成功,无法续签")
|
||||
}
|
||||
|
||||
if cert.DNS != nil {
|
||||
err = client.UseDns(acme.DnsType(cert.DNS.Type), cert.DNS.Data)
|
||||
} else {
|
||||
if cert.Website == nil {
|
||||
return certificate.Resource{}, errors.New("该证书没有关联网站,无法续签,可以尝试手动签发")
|
||||
} else {
|
||||
err = client.UseHTTP(cert.Website.Path)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
ssl, err := client.RenewSSL(*cert.CertURL)
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
cert.CertURL = &ssl.CertURL
|
||||
cert.Cert = string(ssl.Certificate)
|
||||
cert.Key = string(ssl.PrivateKey)
|
||||
err = facades.Orm().Query().Save(&cert)
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
if cert.Website != nil {
|
||||
tools.Write("/www/server/vhost/ssl/"+cert.Website.Name+".pem", string(ssl.Certificate), 0644)
|
||||
tools.Write("/www/server/vhost/ssl/"+cert.Website.Name+".key", string(ssl.PrivateKey), 0644)
|
||||
tools.Exec("systemctl reload openresty")
|
||||
}
|
||||
|
||||
return ssl, nil
|
||||
}
|
||||
@@ -295,10 +295,14 @@ server
|
||||
// Delete 删除网站
|
||||
func (r *WebsiteImpl) Delete(id int) error {
|
||||
var website models.Website
|
||||
if err := facades.Orm().Query().Where("id", id).FirstOrFail(&website); err != nil {
|
||||
if err := facades.Orm().Query().With("Cert").Where("id", id).FirstOrFail(&website); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if website.Cert != nil {
|
||||
return errors.New("网站" + website.Name + "已绑定SSL证书,请先删除证书")
|
||||
}
|
||||
|
||||
if _, err := facades.Orm().Query().Delete(&website); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"github.com/gookit/validate/locales/zhcn"
|
||||
"github.com/goravel/framework/foundation"
|
||||
|
||||
"panel/config"
|
||||
)
|
||||
|
||||
func Boot() {
|
||||
zhcn.RegisterGlobal()
|
||||
|
||||
app := foundation.NewApplication()
|
||||
|
||||
// Bootstrap the application
|
||||
|
||||
+2
-2
@@ -1,6 +1,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/goravel/fiber"
|
||||
"github.com/goravel/framework/auth"
|
||||
"github.com/goravel/framework/cache"
|
||||
"github.com/goravel/framework/console"
|
||||
@@ -20,7 +21,6 @@ import (
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
"github.com/goravel/framework/testing"
|
||||
"github.com/goravel/framework/validation"
|
||||
"github.com/goravel/gin"
|
||||
|
||||
"panel/app/providers"
|
||||
)
|
||||
@@ -91,7 +91,7 @@ func init() {
|
||||
&providers.EventServiceProvider{},
|
||||
&providers.ValidationServiceProvider{},
|
||||
&providers.DatabaseServiceProvider{},
|
||||
&gin.ServiceProvider{},
|
||||
&fiber.ServiceProvider{},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ func init() {
|
||||
// Here you may define all the cache "stores" for your application as
|
||||
// well as their drivers. You may even define multiple stores for the
|
||||
// same cache driver to group types of items stored in your caches.
|
||||
// Available Drivers: "memory", "redis", "custom"
|
||||
// Available Drivers: "memory", "custom"
|
||||
"stores": map[string]any{
|
||||
"memory": map[string]any{
|
||||
"driver": "memory",
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ func init() {
|
||||
"connections": map[string]any{
|
||||
"panel": map[string]any{
|
||||
"driver": "sqlite",
|
||||
"database": "/www/panel/database/panel.db",
|
||||
"database": config.Env("DB_FILE", "/www/panel/database/panel.db"),
|
||||
"prefix": "",
|
||||
"singular": false, // Table name is singular
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@ package config
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/goravel/framework/support/path"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -27,6 +28,11 @@ func init() {
|
||||
"root": "/",
|
||||
"url": "http://localhost/",
|
||||
},
|
||||
"public": map[string]any{
|
||||
"driver": "local",
|
||||
"root": path.Storage("app/public"),
|
||||
"url": config.Env("APP_URL", "").(string) + "/storage",
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ func init() {
|
||||
// factor by 1 doubles the necessary time. After a certain point, the returns on
|
||||
// hashing time versus attacker time are diminishing, so choose your cost factor wisely.
|
||||
"bcrypt": map[string]any{
|
||||
"rounds": 10,
|
||||
"rounds": 12,
|
||||
},
|
||||
|
||||
// Argon2id Hashing Options
|
||||
|
||||
+8
-4
@@ -1,21 +1,23 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
fiberfacades "github.com/goravel/fiber/facades"
|
||||
"github.com/goravel/framework/contracts/route"
|
||||
"github.com/goravel/framework/facades"
|
||||
ginfacades "github.com/goravel/gin/facades"
|
||||
)
|
||||
|
||||
func init() {
|
||||
config := facades.Config()
|
||||
config.Add("http", map[string]any{
|
||||
// HTTP Driver
|
||||
"default": "gin",
|
||||
"default": "fiber",
|
||||
// HTTP Drivers
|
||||
"drivers": map[string]any{
|
||||
"gin": map[string]any{
|
||||
"fiber": map[string]any{
|
||||
// prefork mode, see https://docs.gofiber.io/api/fiber/#config
|
||||
"prefork": false,
|
||||
"route": func() (route.Route, error) {
|
||||
return ginfacades.Route("gin"), nil
|
||||
return fiberfacades.Route("fiber"), nil
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -25,6 +27,8 @@ func init() {
|
||||
"host": config.Env("APP_HOST", "0.0.0.0"),
|
||||
// HTTP Port
|
||||
"port": config.Env("APP_PORT", "8888"),
|
||||
// HTTP Entrance
|
||||
"entrance": config.Env("APP_ENTRANCE", "/"),
|
||||
// HTTPS Configuration
|
||||
"tls": map[string]any{
|
||||
// HTTPS Host
|
||||
|
||||
+1
-1
@@ -8,6 +8,6 @@ func init() {
|
||||
config := facades.Config()
|
||||
config.Add("panel", map[string]any{
|
||||
"name": "耗子Linux面板",
|
||||
"version": "v2.1.3",
|
||||
"version": "v2.1.10",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
DROP TABLE IF EXISTS cert_users;
|
||||
@@ -0,0 +1,14 @@
|
||||
CREATE TABLE cert_users
|
||||
(
|
||||
id integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
email varchar(255) NOT NULL,
|
||||
ca varchar(255) NOT NULL,
|
||||
kid varchar(255) DEFAULT NULL,
|
||||
hmac_encoded varchar(255) DEFAULT NULL,
|
||||
private_key text NOT NULL,
|
||||
key_type varchar(255) NOT NULL,
|
||||
created_at datetime NOT NULL,
|
||||
updated_at datetime NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX idx_cert_users_email ON cert_users (email);
|
||||
@@ -0,0 +1 @@
|
||||
DROP TABLE IF EXISTS cert_dns;
|
||||
@@ -0,0 +1,9 @@
|
||||
CREATE TABLE cert_dns
|
||||
(
|
||||
id integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
name varchar(255) NOT NULL,
|
||||
type varchar(255) NOT NULL,
|
||||
data text NOT NULL,
|
||||
created_at datetime NOT NULL,
|
||||
updated_at datetime NOT NULL
|
||||
);
|
||||
@@ -0,0 +1 @@
|
||||
DROP TABLE IF EXISTS certs;
|
||||
@@ -0,0 +1,15 @@
|
||||
CREATE TABLE certs
|
||||
(
|
||||
id integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
user_id integer NOT NULL,
|
||||
website_id integer DEFAULT NULL,
|
||||
dns_id integer DEFAULT NULL,
|
||||
type varchar(255) NOT NULL,
|
||||
domains text NOT NULL,
|
||||
auto_renew integer DEFAULT 1,
|
||||
cert_url varchar(255) DEFAULT NULL,
|
||||
cert text DEFAULT NULL,
|
||||
key text DEFAULT NULL,
|
||||
created_at datetime NOT NULL,
|
||||
updated_at datetime NOT NULL
|
||||
);
|
||||
+1775
File diff suppressed because it is too large
Load Diff
+1750
File diff suppressed because it is too large
Load Diff
+1096
File diff suppressed because it is too large
Load Diff
@@ -1,79 +1,89 @@
|
||||
module panel
|
||||
|
||||
go 1.18
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/bytedance/sonic v1.10.2
|
||||
github.com/fasthttp/websocket v1.5.6
|
||||
github.com/gertd/go-pluralize v0.2.1
|
||||
github.com/gin-contrib/static v0.0.1
|
||||
github.com/go-acme/lego/v4 v4.14.2
|
||||
github.com/gookit/color v1.5.4
|
||||
github.com/goravel/framework v1.13.2
|
||||
github.com/goravel/gin v1.1.5
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/gookit/validate v1.5.1
|
||||
github.com/goravel/fiber v1.1.11-0.20231108081345-36e967f101d0
|
||||
github.com/goravel/framework v1.13.1-0.20231109083801-f2c86a7c0796
|
||||
github.com/iancoleman/strcase v0.3.0
|
||||
github.com/imroc/req/v3 v3.42.1
|
||||
github.com/mojocn/base64Captcha v1.3.5
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||
github.com/spf13/cast v1.5.1
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/swaggo/files/v2 v2.0.0
|
||||
github.com/swaggo/swag v1.16.2
|
||||
github.com/valyala/fasthttp v1.50.0
|
||||
golang.org/x/crypto v0.14.0
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.110.6 // indirect
|
||||
cloud.google.com/go/compute v1.23.0 // indirect
|
||||
cloud.google.com/go v0.110.9 // indirect
|
||||
cloud.google.com/go/compute v1.23.2 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/iam v1.1.1 // indirect
|
||||
cloud.google.com/go/iam v1.1.4 // indirect
|
||||
cloud.google.com/go/pubsub v1.33.0 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.16 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
|
||||
github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae // indirect
|
||||
github.com/RichardKnop/machinery/v2 v2.0.11 // indirect
|
||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 // indirect
|
||||
github.com/andybalholm/brotli v1.0.6 // indirect
|
||||
github.com/aws/aws-sdk-go v1.37.16 // indirect
|
||||
github.com/bytedance/sonic v1.10.2 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
||||
github.com/chenzhuoyu/iasm v0.9.0 // indirect
|
||||
github.com/chenzhuoyu/iasm v0.9.1 // indirect
|
||||
github.com/cloudflare/circl v1.3.3 // indirect
|
||||
github.com/containerd/continuity v0.4.2 // indirect
|
||||
github.com/cloudflare/cloudflare-go v0.70.0 // indirect
|
||||
github.com/containerd/continuity v0.4.3 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/docker/cli v24.0.6+incompatible // indirect
|
||||
github.com/docker/docker v24.0.6+incompatible // indirect
|
||||
github.com/docker/cli v24.0.7+incompatible // indirect
|
||||
github.com/docker/docker v24.0.7+incompatible // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gaukas/godicttls v0.0.4 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/gin-gonic/gin v1.9.1 // indirect
|
||||
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
||||
github.com/glebarez/sqlite v1.9.0 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.15.3 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/spec v0.20.9 // indirect
|
||||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
||||
github.com/go-redsync/redsync/v4 v4.0.4 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
||||
github.com/go-stack/stack v1.8.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gofiber/fiber/v2 v2.50.0 // indirect
|
||||
github.com/gofiber/template v1.8.2 // indirect
|
||||
github.com/gofiber/template/html/v2 v2.0.5 // indirect
|
||||
github.com/gofiber/utils v1.1.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
|
||||
github.com/golang-migrate/migrate/v4 v4.16.2 // indirect
|
||||
github.com/golang-module/carbon/v2 v2.2.8 // indirect
|
||||
github.com/golang-module/carbon/v2 v2.2.12 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
@@ -82,22 +92,23 @@ require (
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/gomodule/redigo v2.0.0+incompatible // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20230907193218-d3ddc7976beb // indirect
|
||||
github.com/google/s2a-go v0.1.4 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/google/uuid v1.3.1 // indirect
|
||||
github.com/google/uuid v1.4.0 // indirect
|
||||
github.com/google/wire v0.5.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.11.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/gookit/filter v1.2.0 // indirect
|
||||
github.com/gookit/goutil v0.6.12 // indirect
|
||||
github.com/gookit/validate v1.5.1 // indirect
|
||||
github.com/gookit/goutil v0.6.14 // indirect
|
||||
github.com/goravel/file-rotatelogs v0.0.0-20211215053220-2ab31dd9575c // indirect
|
||||
github.com/goravel/file-rotatelogs/v2 v2.4.1 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
@@ -107,54 +118,63 @@ require (
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kelseyhightower/envconfig v1.4.0 // indirect
|
||||
github.com/klauspost/compress v1.16.7 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/klauspost/compress v1.17.2 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
||||
github.com/lestrrat-go/strftime v1.0.5 // indirect
|
||||
github.com/lib/pq v1.10.2 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/microsoft/go-mssqldb v1.1.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/microsoft/go-mssqldb v1.6.0 // indirect
|
||||
github.com/miekg/dns v1.1.55 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/nrdcg/dnspod-go v0.4.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.12.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||
github.com/opencontainers/runc v1.1.9 // indirect
|
||||
github.com/opencontainers/runc v1.1.10 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/ory/dockertest/v3 v3.10.0 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
|
||||
github.com/quic-go/quic-go v0.38.1 // indirect
|
||||
github.com/refraction-networking/utls v1.5.3 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
github.com/rotisserie/eris v0.5.4 // indirect
|
||||
github.com/rs/cors v1.10.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/savioxavier/termlink v1.3.0 // indirect
|
||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/spf13/afero v1.9.5 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.10.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.16.0 // indirect
|
||||
github.com/spf13/viper v1.17.0 // indirect
|
||||
github.com/streadway/amqp v1.0.0 // indirect
|
||||
github.com/stretchr/objx v0.5.0 // indirect
|
||||
github.com/subosito/gotenv v1.4.2 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
||||
github.com/tklauser/numcpus v0.6.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
github.com/unrolled/secure v1.13.0 // indirect
|
||||
github.com/urfave/cli/v2 v2.25.7 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.1 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.3 // indirect
|
||||
@@ -168,29 +188,31 @@ require (
|
||||
go.mongodb.org/mongo-driver v1.7.5 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
golang.org/x/arch v0.5.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
golang.org/x/arch v0.6.0 // indirect
|
||||
golang.org/x/image v0.11.0 // indirect
|
||||
golang.org/x/mod v0.13.0 // indirect
|
||||
golang.org/x/net v0.16.0 // indirect
|
||||
golang.org/x/oauth2 v0.10.0 // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/oauth2 v0.12.0 // indirect
|
||||
golang.org/x/sync v0.4.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/sys v0.14.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.14.0 // indirect
|
||||
google.golang.org/api v0.126.0 // indirect
|
||||
google.golang.org/api v0.143.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||
google.golang.org/grpc v1.58.2 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect
|
||||
google.golang.org/grpc v1.59.0 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/driver/mysql v1.5.1 // indirect
|
||||
gorm.io/driver/mysql v1.5.2 // indirect
|
||||
gorm.io/driver/postgres v1.5.2 // indirect
|
||||
gorm.io/driver/sqlserver v1.5.1 // indirect
|
||||
gorm.io/gorm v1.25.4 // indirect
|
||||
gorm.io/driver/sqlserver v1.5.2 // indirect
|
||||
gorm.io/gorm v1.25.5 // indirect
|
||||
gorm.io/plugin/dbresolver v1.4.7 // indirect
|
||||
modernc.org/libc v1.22.5 // indirect
|
||||
modernc.org/mathutil v1.5.0 // indirect
|
||||
|
||||
@@ -17,23 +17,23 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb
|
||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||
cloud.google.com/go v0.110.6 h1:8uYAkj3YHTP/1iwReuHPxLSbdcyc+dSBbzFMrVwDR6Q=
|
||||
cloud.google.com/go v0.110.6/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
|
||||
cloud.google.com/go v0.110.9 h1:e7ITSqGFFk4rbz/JFIqZh3G4VEHguhAL4BQcFlWtU68=
|
||||
cloud.google.com/go v0.110.9/go.mod h1:rpxevX/0Lqvlbc88b7Sc1SPNdyK1riNBTUU6JXhYNpM=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY=
|
||||
cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
|
||||
cloud.google.com/go/compute v1.23.2 h1:nWEMDhgbBkBJjfpVySqU4jgWdc22PLR0o4vEexZHers=
|
||||
cloud.google.com/go/compute v1.23.2/go.mod h1:JJ0atRC0J/oWYiiVBmsSsrRnh92DhZPG4hFDcR04Rns=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y=
|
||||
cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU=
|
||||
cloud.google.com/go/kms v1.15.0 h1:xYl5WEaSekKYN5gGRyhjvZKM22GVBBCzegGNVPy+aIs=
|
||||
cloud.google.com/go/iam v1.1.4 h1:K6n/GZHFTtEoKT5aUG3l9diPi0VduZNQ1PfdnpkkIFk=
|
||||
cloud.google.com/go/iam v1.1.4/go.mod h1:l/rg8l1AaA+VFMho/HYx2Vv6xinPSLMF8qfhRPIZ0L8=
|
||||
cloud.google.com/go/kms v1.15.4 h1:gEZzC54ZBI+aeW8/jg9tgz9KR4Aa+WEDPbdGIV3iJ7A=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
@@ -48,15 +48,29 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1 h1:/iHxaJhsFr0+xVFfbMr5vxz848jyiWuIEDhYq3y5odY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0 h1:yfJe15aSwEQ6Oo6J+gdfdulPNoZ3TEhmbhLIoxZcA+U=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0/go.mod h1:Q28U+75mpCaSCDowNEmhIo/rmgdkqmkmzI7N6TGR4UY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.16 h1:P8An8Z9rH1ldbOLdFpxYorgOt2sywL9V24dAwWHPuGc=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.16/go.mod h1:tGMin8I49Yij6AQ+rvV+Xa/zwxYQB5hmsd6DkfAx2+A=
|
||||
github.com/Azure/go-autorest/autorest v0.11.24 h1:1fIGgHKqVm54KIPT+q8Zmd1QlVsmHqeUGso5qm2BqqE=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=
|
||||
@@ -66,8 +80,12 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0 h1:HCc0+LpPfpCKs6LGGLAhwBARt9632unrVcI6i8s/8os=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
|
||||
@@ -76,15 +94,16 @@ github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae h1:DcFpTQBYQ9C
|
||||
github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae/go.mod h1:rJJ84PyA/Wlmw1hO+xTzV2wsSUon6J5ktg0g8BF2PuU=
|
||||
github.com/RichardKnop/machinery/v2 v2.0.11 h1:BTfLGOmOju3W/OtlZmLX26OjYNZsU4PJo04pQReycdc=
|
||||
github.com/RichardKnop/machinery/v2 v2.0.11/go.mod h1:b5Q6cT/w7YLlIl4Vi+jpdEoyYiqhTgx+0USoKb1wzqU=
|
||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 h1:J45/QHgrzUdqe/Vco/Vxk0wRvdS2nKUxmf/zLgvfass=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU=
|
||||
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
|
||||
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
|
||||
github.com/aws/aws-sdk-go v1.37.16 h1:Q4YOP2s00NpB9wfmTDZArdcLRuG9ijbnoAwTW3ivleI=
|
||||
github.com/aws/aws-sdk-go v1.37.16/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
||||
github.com/brianvoe/gofakeit/v6 v6.23.2 h1:lVde18uhad5wII/f5RMVFLtdQNE0HaGFuBUXmYKk8i8=
|
||||
github.com/brianvoe/gofakeit/v6 v6.24.0 h1:74yq7RRz/noddscZHRS2T84oHZisW9muwbb8sRnU52A=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
|
||||
github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE=
|
||||
@@ -99,40 +118,41 @@ github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
|
||||
github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
|
||||
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
|
||||
github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0=
|
||||
github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cloudflare/cloudflare-go v0.70.0 h1:4opGbUygM8DjirUuaz23jn3akuAcnOCEx+0nQtQEcFo=
|
||||
github.com/cloudflare/cloudflare-go v0.70.0/go.mod h1:VW6GuazkaZ4xEDkFt24lkXQUsE8q7BiGqDniC2s8WEM=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM=
|
||||
github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
|
||||
github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8=
|
||||
github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/dhui/dktest v0.3.16 h1:i6gq2YQEtcrjKbeJpBkWjE8MmLZPYllcjOFbTZuPDnw=
|
||||
github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
|
||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||
github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY=
|
||||
github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg=
|
||||
github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
|
||||
github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE=
|
||||
github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
|
||||
github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
@@ -144,51 +164,53 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fasthttp/websocket v1.5.6 h1:4WtWgRJ0Gzj1Ou+xGKy66Ji+a0mUfgAj9ZdPqHiUwQE=
|
||||
github.com/fasthttp/websocket v1.5.6/go.mod h1:yiKhNx2zFOv65YYtCJNhtl5VjdCFew3W+gt8U/9aFkI=
|
||||
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw=
|
||||
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
|
||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
|
||||
github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
|
||||
github.com/gertd/go-pluralize v0.2.1 h1:M3uASbVjMnTsPb0PNqg+E/24Vwigyo/tvyMTtAlLgiA=
|
||||
github.com/gertd/go-pluralize v0.2.1/go.mod h1:rbYaKDbsXxmRfr8uygAEKhOWsjyrrqrkHVpZvoOp8zk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-contrib/static v0.0.1 h1:JVxuvHPuUfkoul12N7dtQw7KRn/pSMq7Ue1Va9Swm1U=
|
||||
github.com/gin-contrib/static v0.0.1/go.mod h1:CSxeF+wep05e0kCOsqWdAWbSszmc31zTIbD8TvWl7Hs=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
|
||||
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
|
||||
github.com/glebarez/sqlite v1.9.0 h1:Aj6bPA12ZEx5GbSF6XADmCkYXlljPNUY+Zf1EQxynXs=
|
||||
github.com/glebarez/sqlite v1.9.0/go.mod h1:YBYCoyupOao60lzp1MVBLEjZfgkq0tdB1voAQ09K9zw=
|
||||
github.com/go-acme/lego/v4 v4.14.2 h1:/D/jqRgLi8Cbk33sLGtu2pX2jEg3bGJWHyV8kFuUHGM=
|
||||
github.com/go-acme/lego/v4 v4.14.2/go.mod h1:kBXxbeTg0x9AgaOYjPSwIeJy3Y33zTz+tMD16O4MO6c=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo=
|
||||
github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/go-playground/validator/v10 v10.15.3 h1:S+sSpunYjNPDuXkWbK+x+bA7iXiW296KG4dL3X7xUZo=
|
||||
github.com/go-playground/validator/v10 v10.15.3/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||
github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
|
||||
github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
|
||||
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
|
||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8=
|
||||
github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
|
||||
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1x4=
|
||||
@@ -232,10 +254,17 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe
|
||||
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
|
||||
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
|
||||
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/gofiber/fiber/v2 v2.50.0 h1:ia0JaB+uw3GpNSCR5nvC5dsaxXjRU5OEu36aytx+zGw=
|
||||
github.com/gofiber/fiber/v2 v2.50.0/go.mod h1:21eytvay9Is7S6z+OgPi7c7n4++tnClWmhpimVHMimw=
|
||||
github.com/gofiber/template v1.8.2 h1:PIv9s/7Uq6m+Fm2MDNd20pAFFKt5wWs7ZBd8iV9pWwk=
|
||||
github.com/gofiber/template v1.8.2/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8=
|
||||
github.com/gofiber/template/html/v2 v2.0.5 h1:BKLJ6Qr940NjntbGmpO3zVa4nFNGDCi/IfUiDB9OC20=
|
||||
github.com/gofiber/template/html/v2 v2.0.5/go.mod h1:RCF14eLeQDCSUPp0IGc2wbSSDv6yt+V54XB/+Unz+LM=
|
||||
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
|
||||
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||
@@ -244,8 +273,8 @@ github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJ
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-migrate/migrate/v4 v4.16.2 h1:8coYbMKUyInrFk1lfGfRovTLAW7PhWp8qQDT2iKfuoA=
|
||||
github.com/golang-migrate/migrate/v4 v4.16.2/go.mod h1:pfcJX4nPHaVdc5nmdCikFBWtm+UBpiZjRNNsyBbp0/o=
|
||||
github.com/golang-module/carbon/v2 v2.2.8 h1:a1VxHHKAR7fc1ho7sYXhS1s5S4x7+oqAf2EY5p8C46A=
|
||||
github.com/golang-module/carbon/v2 v2.2.8/go.mod h1:XDALX7KgqmHk95xyLeaqX9/LJGbfLATyruTziq68SZ8=
|
||||
github.com/golang-module/carbon/v2 v2.2.12 h1:qydcu64b5+29dOnMNVS27V3JaphyA2eLrUvKv8CNPMI=
|
||||
github.com/golang-module/carbon/v2 v2.2.12/go.mod h1:XDALX7KgqmHk95xyLeaqX9/LJGbfLATyruTziq68SZ8=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
@@ -282,7 +311,6 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
@@ -305,7 +333,8 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
@@ -323,54 +352,57 @@ github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/pprof v0.0.0-20230907193218-d3ddc7976beb h1:LCMfzVg3sflxTs4UvuP4D8CkoZnfHLe2qzqgDn/4OHs=
|
||||
github.com/google/pprof v0.0.0-20230907193218-d3ddc7976beb/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc=
|
||||
github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
|
||||
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
|
||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
|
||||
github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4=
|
||||
github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
|
||||
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
|
||||
github.com/gookit/filter v1.2.0 h1:r7E01dHVkysb5WgzooiGsfblHGShEZCeGcyYM+5IpYU=
|
||||
github.com/gookit/filter v1.2.0/go.mod h1:bXs9RcB4Blxwny970opiwABeIEqQ/gzOMmHBhKwBdms=
|
||||
github.com/gookit/goutil v0.6.12 h1:73vPUcTtVGXbhSzBOFcnSB1aJl7Jq9np3RAE50yIDZc=
|
||||
github.com/gookit/goutil v0.6.12/go.mod h1:g6krlFib8xSe3G1h02IETowOtrUGpAmetT8IevDpvpM=
|
||||
github.com/gookit/goutil v0.6.14 h1:96elyOG4BvVoDaiT7vx1vHPrVyEtFfYlPPBODR0/FGQ=
|
||||
github.com/gookit/goutil v0.6.14/go.mod h1:YyDBddefmjS+mU2PDPgCcjVzTDM5WgExiDv5ZA/b8I8=
|
||||
github.com/gookit/validate v1.5.1 h1:rPp64QZQJM+fysGFAhKpvekQAav4Ok6sjfTs9ZtxcpA=
|
||||
github.com/gookit/validate v1.5.1/go.mod h1:SskOHUQokzMNt6T3r7N+N/4me/6fxDx+tmoXf/3ZQog=
|
||||
github.com/goravel/fiber v1.1.11-0.20231108081345-36e967f101d0 h1:mEuJdUWmNXIrg5njcbOS+GucmOM2QrqAHL+ODTgDHPo=
|
||||
github.com/goravel/fiber v1.1.11-0.20231108081345-36e967f101d0/go.mod h1:IOvZ0G1bojUU/Kv9DZl+/8cwGhcNr0YRhwElz0hpjTg=
|
||||
github.com/goravel/file-rotatelogs v0.0.0-20211215053220-2ab31dd9575c h1:obhFK91JAhcf7s6h5sggZishm1VyGW/gBCreo+7/SwQ=
|
||||
github.com/goravel/file-rotatelogs v0.0.0-20211215053220-2ab31dd9575c/go.mod h1:YSWsLXlG16u5CWFaXNZHhEQD10+NwF3xfgDV816OwLE=
|
||||
github.com/goravel/file-rotatelogs/v2 v2.4.1 h1:ogkeIFcTHSBRUBpZYiyJbpul8hkVXxHPuDbOaP78O1M=
|
||||
github.com/goravel/file-rotatelogs/v2 v2.4.1/go.mod h1:euk9qr52WrzM8ICs1hecFcR4CZ/ZZOPdacHfvHgbOf0=
|
||||
github.com/goravel/framework v1.13.2 h1:7BRNihQ/ZNeA384941yg8zRytXRXkkStksXNyyUEgQI=
|
||||
github.com/goravel/framework v1.13.2/go.mod h1:BOUTIwzhOMyKNXaxSYbVB74NkmbS2xv1W1fPRv9eDws=
|
||||
github.com/goravel/gin v1.1.5 h1:HWVBxSDHsfpq2lWvuagQVMJlCwznf6ifc71IYEo3sCE=
|
||||
github.com/goravel/gin v1.1.5/go.mod h1:FxnhnqcMJk/Sk6jA/xcXn6tHtFzayNXeFuw7GnLORMY=
|
||||
github.com/goravel/framework v1.13.1-0.20231109083801-f2c86a7c0796 h1:4ZqUXMfPP8M10joipSdP9PGgDoVD51vZIcCPds/EyGk=
|
||||
github.com/goravel/framework v1.13.1-0.20231109083801-f2c86a7c0796/go.mod h1:5jKFbJzfqhaQTP3HCgbyrpnrCyoJjxN5JWSXO96H0iQ=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c=
|
||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
@@ -405,6 +437,7 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr
|
||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
@@ -414,7 +447,9 @@ github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA=
|
||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
@@ -427,24 +462,24 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
|
||||
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
|
||||
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
|
||||
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
|
||||
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
|
||||
github.com/lestrrat-go/strftime v0.0.0-20180821113735-8b31f9c59b0f/go.mod h1:RMlXygAD3c48Psmr06d2G75L4E4xxzxkIe/+ppX9eAU=
|
||||
@@ -454,13 +489,24 @@ github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
|
||||
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
|
||||
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/microsoft/go-mssqldb v1.1.0 h1:jsV+tpvcPTbNNKW0o3kiCD69kOHICsfjZ2VcVu2lKYc=
|
||||
github.com/microsoft/go-mssqldb v1.1.0/go.mod h1:LzkFdl4z2Ck+Hi+ycGOTbL56VEfgoyA2DvYejrNGbRk=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/microsoft/go-mssqldb v1.6.0 h1:mM3gYdVwEPFrlg/Dvr2DNVEgYFG7L42l+dGc67NNNpc=
|
||||
github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU=
|
||||
github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
|
||||
github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
@@ -468,7 +514,7 @@ github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
||||
@@ -477,6 +523,9 @@ github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nrdcg/dnspod-go v0.4.0 h1:c/jn1mLZNKF3/osJ6mz3QPxTudvPArXTjpkmYj0uK6U=
|
||||
github.com/nrdcg/dnspod-go v0.4.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgPTGKr6KQ=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
@@ -497,8 +546,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
|
||||
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v1.1.9 h1:XR0VIHTGce5eWPkaPesqTBrhW2yAcaraWfsEalNwQLM=
|
||||
github.com/opencontainers/runc v1.1.9/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50=
|
||||
github.com/opencontainers/runc v1.1.10 h1:EaL5WeO9lv9wmS6SASjszOeQdSctvpbu0DdBQBizE40=
|
||||
github.com/opencontainers/runc v1.1.10/go.mod h1:+/R6+KmDlh+hOO8NkjmgkG9Qzvypzk0yXxAPYYR65+M=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
|
||||
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
|
||||
@@ -509,14 +558,16 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK
|
||||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
@@ -531,20 +582,28 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnHyvtYjDeq0zlVHn9K/ZXoy17ylucdo=
|
||||
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rotisserie/eris v0.5.4 h1:Il6IvLdAapsMhvuOahHWiBnl1G++Q0/L5UIkI5mARSk=
|
||||
github.com/rotisserie/eris v0.5.4/go.mod h1:Z/kgYTJiJtocxCbFfvRmO+QejApzG6zpyky9G1A4g9s=
|
||||
github.com/rs/cors v1.10.0 h1:62NOS1h+r8p1mW6FM0FSB0exioXLhd/sh15KpjWBZ+8=
|
||||
github.com/rs/cors v1.10.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
|
||||
github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/savioxavier/termlink v1.3.0 h1:3Gl4FzQjUyiHzmoEDfmWEhgIwDiJY4poOQHP+k8ReA4=
|
||||
github.com/savioxavier/termlink v1.3.0/go.mod h1:5T5ePUlWbxCHIwyF8/Ez1qufOoGM89RCg9NvG+3G3gc=
|
||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk=
|
||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
@@ -553,18 +612,18 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
|
||||
github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
|
||||
github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
|
||||
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
|
||||
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc=
|
||||
github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg=
|
||||
github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI=
|
||||
github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI=
|
||||
github.com/streadway/amqp v1.0.0 h1:kuuDrUJFZL1QYL9hUNuCxNObNzB0bV/ZG5jV3RWAQgo=
|
||||
github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@@ -586,8 +645,12 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM=
|
||||
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8=
|
||||
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
|
||||
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw=
|
||||
github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM=
|
||||
github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04=
|
||||
github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E=
|
||||
github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ=
|
||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
@@ -597,15 +660,15 @@ github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYm
|
||||
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/unrolled/secure v1.13.0 h1:sdr3Phw2+f8Px8HE5sd1EHdj1aV3yUwed/uZXChLFsk=
|
||||
github.com/unrolled/secure v1.13.0/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40=
|
||||
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
|
||||
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.50.0 h1:H7fweIlBm0rXLs2q0XbalvJ6r0CUPFWK3/bB4N13e9M=
|
||||
github.com/valyala/fasthttp v1.50.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
|
||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
||||
@@ -653,33 +716,34 @@ go.opentelemetry.io/otel v0.17.0/go.mod h1:Oqtdxmf7UtEvL037ohlgnaYa1h7GtMh0NcSd9
|
||||
go.opentelemetry.io/otel/metric v0.17.0/go.mod h1:hUz9lH1rNXyEwWAhIWCMFWKhYtpASgSnObJFnU26dJ0=
|
||||
go.opentelemetry.io/otel/oteltest v0.17.0/go.mod h1:JT/LGFxPwpN+nlsTiinSYjdIx3hZIGqHCpChcIZmdoE=
|
||||
go.opentelemetry.io/otel/trace v0.17.0/go.mod h1:bIujpqg6ZL6xUTubIUgziI1jSaUPthmabA/ygf/6Cfg=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
||||
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
|
||||
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.5.0 h1:jpGode6huXQxcskEIpOCvrU+tzo81b6+oFLUYXWtH/Y=
|
||||
golang.org/x/arch v0.5.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc=
|
||||
golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -723,8 +787,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
|
||||
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -754,6 +818,7 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
@@ -768,8 +833,9 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos=
|
||||
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -780,8 +846,8 @@ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210113205817-d3ed898aa8a3/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
||||
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
||||
golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
|
||||
golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -822,7 +888,6 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -857,18 +922,21 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -879,17 +947,18 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
@@ -975,8 +1044,8 @@ google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ
|
||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||
google.golang.org/api v0.39.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/api v0.126.0 h1:q4GJq+cAdMAC7XP7njvQ4tvohGLiSlytuL4BQxbIZ+o=
|
||||
google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw=
|
||||
google.golang.org/api v0.143.0 h1:o8cekTkqhywkbZT6p1UHJPZ9+9uuCAJs/KYomxZB8fA=
|
||||
google.golang.org/api v0.143.0/go.mod h1:FoX9DO9hT7DLNn97OuoZAGSDuNAXdJRuGK98rSUgurk=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
@@ -1009,7 +1078,6 @@ google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfG
|
||||
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
@@ -1024,12 +1092,12 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D
|
||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWofoFcihmDEMYeDR9KN/ThbPWGrh++g=
|
||||
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e h1:z3vDksarJxsAKM5dmEGv0GHwE2hKJ096wZra71Vs4sw=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
|
||||
google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 h1:I6WNifs6pF9tNdSob2W24JtyxIYjzFB9qDlpUC76q+U=
|
||||
google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405/go.mod h1:3WDQMjmJk36UQhjQ89emUzb1mdaHcPeeAh4SCBKznB4=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b h1:CIC2YMXmIhYw6evmhPxBKJ4fmLbOFtXQN/GV3XOZR8k=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:IBQ646DjkDkvUIsVq/cc03FUFQ9wbZu7yE396YcL870=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 h1:Jyp0Hsi0bmHXG6k9eATXoYtjd6e2UzZ1SCn/wIupY14=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@@ -1043,14 +1111,11 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||
google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I=
|
||||
google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
|
||||
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
||||
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -1068,39 +1133,41 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
|
||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c=
|
||||
gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw=
|
||||
gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o=
|
||||
gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs=
|
||||
gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8=
|
||||
gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0=
|
||||
gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8=
|
||||
gorm.io/driver/sqlserver v1.5.1 h1:wpyW/pR26U94uaujltiFGXY7fd2Jw5hC9PB1ZF/Y5s4=
|
||||
gorm.io/driver/sqlserver v1.5.1/go.mod h1:AYHzzte2msKTmYBYsSIq8ZUsznLJwBdkB2wpI+kt0nM=
|
||||
gorm.io/driver/sqlserver v1.5.2 h1:+o4RQ8w1ohPbADhFqDxeeZnSWjwOcBnxBckjTbcP4wk=
|
||||
gorm.io/driver/sqlserver v1.5.2/go.mod h1:gaKF0MO0cfTq9Q3/XhkowSw4g6nIwHPGAs4hzKCmvBo=
|
||||
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
||||
gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.2-0.20230610234218-206613868439/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw=
|
||||
gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
|
||||
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/plugin/dbresolver v1.4.7 h1:ZwtwmJQxTx9us7o6zEHFvH1q4OeEo1pooU7efmnunJA=
|
||||
gorm.io/plugin/dbresolver v1.4.7/go.mod h1:l4Cn87EHLEYuqUncpEeTC2tTJQkjngPSD+lo8hIvcT0=
|
||||
gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo=
|
||||
|
||||
@@ -22,6 +22,18 @@ import (
|
||||
"panel/bootstrap"
|
||||
)
|
||||
|
||||
// @title 耗子 Linux 面板 API
|
||||
// @version 2
|
||||
// @description 耗子 Linux 面板的 API 信息
|
||||
|
||||
// @contact.name 耗子科技
|
||||
// @contact.email i@haozi.net
|
||||
|
||||
// @securityDefinitions.apikey BearerToken
|
||||
// @in header
|
||||
// @name Authorization
|
||||
|
||||
// @BasePath /api
|
||||
func main() {
|
||||
// 启动框架
|
||||
bootstrap.Boot()
|
||||
|
||||
@@ -3,5 +3,6 @@ APP_KEY=
|
||||
APP_DEBUG=false
|
||||
APP_HOST=0.0.0.0
|
||||
APP_PORT=8888
|
||||
APP_ENTRANCE=/
|
||||
|
||||
JWT_SECRET=
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
package acme
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
|
||||
"github.com/go-acme/lego/v4/certcrypto"
|
||||
"github.com/go-acme/lego/v4/lego"
|
||||
"github.com/go-acme/lego/v4/registration"
|
||||
)
|
||||
|
||||
const (
|
||||
CALetEncrypt = "https://acme-v02.api.letsencrypt.org/directory"
|
||||
CAZeroSSL = "https://acme.zerossl.com/v2/DV90"
|
||||
CAGoogle = "https://dv.acme-v02.api.pki.goog/directory"
|
||||
CABuypass = "https://api.buypass.com/acme/directory"
|
||||
CASSLcom = "https://acme.ssl.com/sslcom-dv-rsa"
|
||||
)
|
||||
|
||||
type KeyType = certcrypto.KeyType
|
||||
|
||||
const (
|
||||
KeyEC256 = certcrypto.EC256
|
||||
KeyEC384 = certcrypto.EC384
|
||||
KeyRSA2048 = certcrypto.RSA2048
|
||||
KeyRSA3072 = certcrypto.RSA3072
|
||||
KeyRSA4096 = certcrypto.RSA4096
|
||||
)
|
||||
|
||||
type domainError struct {
|
||||
Domain string
|
||||
Error error
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Email string
|
||||
Registration *registration.Resource
|
||||
Key crypto.PrivateKey
|
||||
}
|
||||
|
||||
func (u *User) GetEmail() string {
|
||||
return u.Email
|
||||
}
|
||||
|
||||
func (u *User) GetRegistration() *registration.Resource {
|
||||
return u.Registration
|
||||
}
|
||||
func (u *User) GetPrivateKey() crypto.PrivateKey {
|
||||
return u.Key
|
||||
}
|
||||
|
||||
func GetPrivateKey(priKey crypto.PrivateKey, keyType KeyType) ([]byte, error) {
|
||||
var marshal []byte
|
||||
var block *pem.Block
|
||||
var err error
|
||||
|
||||
switch keyType {
|
||||
case KeyEC256, KeyEC384:
|
||||
key := priKey.(*ecdsa.PrivateKey)
|
||||
marshal, err = x509.MarshalECPrivateKey(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
block = &pem.Block{
|
||||
Type: "PRIVATE KEY",
|
||||
Bytes: marshal,
|
||||
}
|
||||
case KeyRSA2048, KeyRSA3072, KeyRSA4096:
|
||||
key := priKey.(*rsa.PrivateKey)
|
||||
marshal = x509.MarshalPKCS1PrivateKey(key)
|
||||
block = &pem.Block{
|
||||
Type: "privateKey",
|
||||
Bytes: marshal,
|
||||
}
|
||||
}
|
||||
|
||||
return pem.EncodeToMemory(block), nil
|
||||
}
|
||||
|
||||
func NewRegisterClient(email string, CA string, keyType certcrypto.KeyType) (*Client, error) {
|
||||
privateKey, err := certcrypto.GeneratePrivateKey(keyType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user := &User{
|
||||
Email: email,
|
||||
Key: privateKey,
|
||||
}
|
||||
config := lego.NewConfig(user)
|
||||
config.CADirURL = CA
|
||||
config.Certificate.KeyType = keyType
|
||||
client, err := lego.NewClient(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user.Registration = reg
|
||||
|
||||
acmeClient := &Client{
|
||||
User: user,
|
||||
Client: client,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
return acmeClient, nil
|
||||
}
|
||||
|
||||
func NewRegisterWithExternalAccountBindingClient(email, kid, hmac, CA string, keyType certcrypto.KeyType) (*Client, error) {
|
||||
privateKey, err := certcrypto.GeneratePrivateKey(keyType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user := &User{
|
||||
Email: email,
|
||||
Key: privateKey,
|
||||
}
|
||||
config := lego.NewConfig(user)
|
||||
config.CADirURL = CA
|
||||
config.Certificate.KeyType = keyType
|
||||
client, err := lego.NewClient(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reg, err := client.Registration.RegisterWithExternalAccountBinding(registration.RegisterEABOptions{TermsOfServiceAgreed: true, Kid: kid, HmacEncoded: hmac})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user.Registration = reg
|
||||
|
||||
acmeClient := &Client{
|
||||
User: user,
|
||||
Client: client,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
return acmeClient, nil
|
||||
}
|
||||
|
||||
func NewPrivateKeyClient(email string, privateKey string, CA string, keyType certcrypto.KeyType) (*Client, error) {
|
||||
key, err := certcrypto.ParsePEMPrivateKey([]byte(privateKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user := &User{
|
||||
Email: email,
|
||||
Key: key,
|
||||
}
|
||||
config := lego.NewConfig(user)
|
||||
config.CADirURL = CA
|
||||
config.Certificate.KeyType = keyType
|
||||
client, err := lego.NewClient(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reg, err := client.Registration.ResolveAccountByKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user.Registration = reg
|
||||
|
||||
acmeClient := &Client{
|
||||
User: user,
|
||||
Client: client,
|
||||
Config: config,
|
||||
}
|
||||
|
||||
return acmeClient, nil
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
package acme
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/acme"
|
||||
"github.com/go-acme/lego/v4/acme/api"
|
||||
"github.com/go-acme/lego/v4/certificate"
|
||||
"github.com/go-acme/lego/v4/challenge"
|
||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||
"github.com/go-acme/lego/v4/lego"
|
||||
"github.com/go-acme/lego/v4/providers/dns/alidns"
|
||||
"github.com/go-acme/lego/v4/providers/dns/cloudflare"
|
||||
"github.com/go-acme/lego/v4/providers/dns/dnspod"
|
||||
"github.com/go-acme/lego/v4/providers/http/webroot"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
Config *lego.Config
|
||||
Client *lego.Client
|
||||
User *User
|
||||
}
|
||||
|
||||
type DnsType string
|
||||
|
||||
const (
|
||||
DnsPod DnsType = "dnspod"
|
||||
AliYun DnsType = "aliyun"
|
||||
CloudFlare DnsType = "cloudflare"
|
||||
)
|
||||
|
||||
type DNSParam struct {
|
||||
ID string `form:"id" json:"id"`
|
||||
Token string `form:"token" json:"token"`
|
||||
AccessKey string `form:"access_key" json:"access_key"`
|
||||
SecretKey string `form:"secret_key" json:"secret_key"`
|
||||
Email string `form:"email" json:"email"`
|
||||
APIkey string `form:"api_key" json:"api_key"`
|
||||
}
|
||||
|
||||
// UseDns 使用 DNS 接口验证
|
||||
func (c *Client) UseDns(dnsType DnsType, param DNSParam) error {
|
||||
var p challenge.Provider
|
||||
var err error
|
||||
if dnsType == DnsPod {
|
||||
dnsPodConfig := dnspod.NewDefaultConfig()
|
||||
dnsPodConfig.LoginToken = param.ID + "," + param.Token
|
||||
p, err = dnspod.NewDNSProviderConfig(dnsPodConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if dnsType == AliYun {
|
||||
aliyunConfig := alidns.NewDefaultConfig()
|
||||
aliyunConfig.SecretKey = param.SecretKey
|
||||
aliyunConfig.APIKey = param.AccessKey
|
||||
p, err = alidns.NewDNSProviderConfig(aliyunConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if dnsType == CloudFlare {
|
||||
cloudflareConfig := cloudflare.NewDefaultConfig()
|
||||
cloudflareConfig.AuthEmail = param.Email
|
||||
cloudflareConfig.AuthKey = param.APIkey
|
||||
p, err = cloudflare.NewDNSProviderConfig(cloudflareConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return c.Client.Challenge.SetDNS01Provider(p, dns01.AddDNSTimeout(3*time.Minute))
|
||||
}
|
||||
|
||||
// UseManualDns 使用手动 DNS 验证
|
||||
func (c *Client) UseManualDns(checkDns ...bool) error {
|
||||
p := &manualDnsProvider{}
|
||||
var err error
|
||||
|
||||
if len(checkDns) > 0 && !checkDns[0] {
|
||||
err = c.Client.Challenge.SetDNS01Provider(p, dns01.DisableCompletePropagationRequirement())
|
||||
} else {
|
||||
err = c.Client.Challenge.SetDNS01Provider(p, dns01.AddDNSTimeout(3*time.Minute))
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// UseHTTP 使用 HTTP 验证
|
||||
func (c *Client) UseHTTP(path string) error {
|
||||
httpProvider, err := webroot.NewHTTPProvider(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.Client.Challenge.SetHTTP01Provider(httpProvider)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ObtainSSL 签发 SSL 证书
|
||||
func (c *Client) ObtainSSL(domains []string) (certificate.Resource, error) {
|
||||
request := certificate.ObtainRequest{
|
||||
Domains: domains,
|
||||
Bundle: true,
|
||||
}
|
||||
|
||||
certificates, err := c.Client.Certificate.Obtain(request)
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
return *certificates, nil
|
||||
}
|
||||
|
||||
// RenewSSL 续签 SSL 证书
|
||||
func (c *Client) RenewSSL(certUrl string) (certificate.Resource, error) {
|
||||
certificates, err := c.Client.Certificate.Get(certUrl, true)
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
certificates, err = c.Client.Certificate.RenewWithOptions(*certificates, &certificate.RenewOptions{
|
||||
Bundle: true,
|
||||
MustStaple: true,
|
||||
})
|
||||
if err != nil {
|
||||
return certificate.Resource{}, err
|
||||
}
|
||||
|
||||
return *certificates, nil
|
||||
}
|
||||
|
||||
// GetDNSResolve 获取 DNS 解析(手动设置)
|
||||
func (c *Client) GetDNSResolve(domains []string) (map[string]Resolve, error) {
|
||||
core, err := api.New(c.Config.HTTPClient, c.Config.UserAgent, c.Config.CADirURL, c.User.Registration.URI, c.User.Key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
order, err := core.Orders.New(domains)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resolves := make(map[string]Resolve)
|
||||
resChan, errChan := make(chan acme.Authorization), make(chan domainError)
|
||||
for _, authzURL := range order.Authorizations {
|
||||
go func(authzURL string) {
|
||||
authz, err := core.Authorizations.Get(authzURL)
|
||||
if err != nil {
|
||||
errChan <- domainError{Domain: authz.Identifier.Value, Error: err}
|
||||
return
|
||||
}
|
||||
resChan <- authz
|
||||
}(authzURL)
|
||||
}
|
||||
|
||||
var responses []acme.Authorization
|
||||
for i := 0; i < len(order.Authorizations); i++ {
|
||||
select {
|
||||
case res := <-resChan:
|
||||
responses = append(responses, res)
|
||||
case err := <-errChan:
|
||||
resolves[err.Domain] = Resolve{Err: err.Error.Error()}
|
||||
}
|
||||
}
|
||||
close(resChan)
|
||||
close(errChan)
|
||||
|
||||
for _, auth := range responses {
|
||||
domain := challenge.GetTargetedDomain(auth)
|
||||
acmeChallenge, err := challenge.FindChallenge(challenge.DNS01, auth)
|
||||
if err != nil {
|
||||
resolves[domain] = Resolve{Err: err.Error()}
|
||||
continue
|
||||
}
|
||||
keyAuth, err := core.GetKeyAuthorization(acmeChallenge.Token)
|
||||
if err != nil {
|
||||
resolves[domain] = Resolve{Err: err.Error()}
|
||||
continue
|
||||
}
|
||||
challengeInfo := dns01.GetChallengeInfo(domain, keyAuth)
|
||||
resolves[domain] = Resolve{
|
||||
Key: challengeInfo.FQDN,
|
||||
Value: challengeInfo.Value,
|
||||
}
|
||||
}
|
||||
|
||||
return resolves, nil
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package acme
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type ClientTestSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func TestClientTestSuite(t *testing.T) {
|
||||
suite.Run(t, &ClientTestSuite{})
|
||||
}
|
||||
|
||||
func (s *ClientTestSuite) TestObtainSSL() {
|
||||
client, err := NewRegisterClient("ci@haozi.net", "https://acme-staging-v02.api.letsencrypt.org/directory", KeyEC256)
|
||||
s.Nil(err)
|
||||
|
||||
err = client.UseDns(DnsPod, DNSParam{
|
||||
ID: "xxx",
|
||||
Token: "xxx",
|
||||
})
|
||||
s.Nil(err)
|
||||
|
||||
err = client.UseManualDns(false)
|
||||
s.Nil(err)
|
||||
|
||||
resolves, err := client.GetDNSResolve([]string{"haozi.dev"})
|
||||
s.Nil(err)
|
||||
s.NotNil(resolves)
|
||||
|
||||
ssl, err := client.ObtainSSL([]string{"haozi.dev"})
|
||||
fmt.Println(err.Error())
|
||||
s.Error(err)
|
||||
s.NotNil(ssl)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package acme
|
||||
|
||||
type Resolve struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
Err string `json:"err"`
|
||||
}
|
||||
|
||||
type manualDnsProvider struct {
|
||||
Resolve *Resolve
|
||||
}
|
||||
|
||||
func (p *manualDnsProvider) Present(domain, token, keyAuth string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *manualDnsProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package acme
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"math/big"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// GenerateSelfSignedSSL 生成自签名证书
|
||||
func GenerateSelfSignedSSL(domains []string) ([]byte, []byte, error) {
|
||||
rootPrivateKey, _ := rsa.GenerateKey(rand.Reader, 4096)
|
||||
var ip []net.IP
|
||||
isIP := false
|
||||
for _, item := range domains {
|
||||
ipItem := net.ParseIP(item)
|
||||
if len(ipItem) != 0 {
|
||||
isIP = true
|
||||
ip = append(ip, ipItem)
|
||||
}
|
||||
}
|
||||
|
||||
rootTemplate := x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{CommonName: "HaoZi Panel Root CA"},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().AddDate(20, 0, 0),
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
KeyUsage: x509.KeyUsageCertSign,
|
||||
}
|
||||
if isIP {
|
||||
rootTemplate.IPAddresses = ip
|
||||
} else {
|
||||
rootTemplate.DNSNames = domains
|
||||
}
|
||||
|
||||
rootCertBytes, _ := x509.CreateCertificate(rand.Reader, &rootTemplate, &rootTemplate, &rootPrivateKey.PublicKey, rootPrivateKey)
|
||||
rootCertBlock := &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: rootCertBytes,
|
||||
}
|
||||
|
||||
interPrivateKey, _ := rsa.GenerateKey(rand.Reader, 4096)
|
||||
interTemplate := x509.Certificate{
|
||||
SerialNumber: big.NewInt(2),
|
||||
Subject: pkix.Name{CommonName: "HaoZi Panel Intermediate CA"},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().AddDate(20, 0, 0),
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
KeyUsage: x509.KeyUsageCertSign,
|
||||
}
|
||||
if isIP {
|
||||
interTemplate.IPAddresses = ip
|
||||
} else {
|
||||
interTemplate.DNSNames = domains
|
||||
}
|
||||
|
||||
interCertBytes, _ := x509.CreateCertificate(rand.Reader, &interTemplate, &rootTemplate, &interPrivateKey.PublicKey, rootPrivateKey)
|
||||
interCertBlock := &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: interCertBytes,
|
||||
}
|
||||
|
||||
clientPrivateKey, _ := rsa.GenerateKey(rand.Reader, 4096)
|
||||
clientTemplate := x509.Certificate{
|
||||
SerialNumber: big.NewInt(3),
|
||||
Subject: pkix.Name{CommonName: "HaoZi Panel Client"},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().AddDate(20, 0, 0),
|
||||
KeyUsage: x509.KeyUsageDigitalSignature,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
if isIP {
|
||||
clientTemplate.IPAddresses = ip
|
||||
} else {
|
||||
clientTemplate.DNSNames = domains
|
||||
}
|
||||
|
||||
clientCertBytes, _ := x509.CreateCertificate(rand.Reader, &clientTemplate, &interTemplate, &clientPrivateKey.PublicKey, interPrivateKey)
|
||||
clientCertBlock := &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: clientCertBytes,
|
||||
}
|
||||
|
||||
pemBytes := []byte{}
|
||||
pemBytes = append(pemBytes, pem.EncodeToMemory(clientCertBlock)...)
|
||||
pemBytes = append(pemBytes, pem.EncodeToMemory(interCertBlock)...)
|
||||
pemBytes = append(pemBytes, pem.EncodeToMemory(rootCertBlock)...)
|
||||
keyBytes := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(clientPrivateKey)})
|
||||
|
||||
return pemBytes, keyBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package acme
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type SSLTestSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func TestSSLTestSuite(t *testing.T) {
|
||||
suite.Run(t, &SSLTestSuite{})
|
||||
}
|
||||
|
||||
func (s *SSLTestSuite) TestGenerateSelfSignedSSL() {
|
||||
pem, key, err := GenerateSelfSignedSSL([]string{"haozi.dev"})
|
||||
s.Nil(err)
|
||||
s.NotNil(pem)
|
||||
s.NotNil(key)
|
||||
}
|
||||
+1
-1
@@ -9,7 +9,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/fasthttp/websocket"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
|
||||
+51
-24
@@ -14,13 +14,21 @@ import (
|
||||
// Write 写入文件
|
||||
func Write(path string, data string, permission os.FileMode) bool {
|
||||
if err := os.MkdirAll(filepath.Dir(path), permission); err != nil {
|
||||
facades.Log().Errorf("[面板][Helpers] 创建目录失败: %s", err.Error())
|
||||
facades.Log().With(map[string]any{
|
||||
"path": filepath.Dir(path),
|
||||
"permission": permission,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("创建目录失败")
|
||||
return false
|
||||
}
|
||||
|
||||
err := os.WriteFile(path, []byte(data), permission)
|
||||
if err != nil {
|
||||
facades.Log().Errorf("[面板][Helpers] 写入文件 %s 失败: %s", path, err.Error())
|
||||
facades.Log().With(map[string]any{
|
||||
"path": path,
|
||||
"permission": permission,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("写入文件失败")
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -31,17 +39,23 @@ func Write(path string, data string, permission os.FileMode) bool {
|
||||
func Read(path string) string {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
facades.Log().Errorf("[面板][Helpers] 读取文件 %s 失败: %s", path, err.Error())
|
||||
facades.Log().With(map[string]any{
|
||||
"path": path,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("读取文件失败")
|
||||
return ""
|
||||
}
|
||||
|
||||
return string(data)
|
||||
}
|
||||
|
||||
// Remove 删除文件
|
||||
// Remove 删除文件/目录
|
||||
func Remove(path string) bool {
|
||||
if err := os.Remove(path); err != nil {
|
||||
facades.Log().Errorf("[面板][Helpers] 删除文件 %s 失败: %s", path, err.Error())
|
||||
if err := os.RemoveAll(path); err != nil {
|
||||
facades.Log().With(map[string]any{
|
||||
"path": path,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("删除文件/目录失败")
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -59,7 +73,10 @@ func Exec(shell string) string {
|
||||
fmt.Println(err.Error())
|
||||
panic(err)
|
||||
} else {
|
||||
facades.Log().Errorf("[面板][Helpers] 执行命令 %s 失败: %s", shell, err.Error())
|
||||
facades.Log().With(map[string]any{
|
||||
"shell": shell,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("执行命令失败")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -68,17 +85,11 @@ func Exec(shell string) string {
|
||||
}
|
||||
|
||||
// ExecAsync 异步执行 shell 命令
|
||||
func ExecAsync(shell string) {
|
||||
func ExecAsync(shell string) error {
|
||||
cmd := exec.Command("bash", "-c", shell)
|
||||
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
if support.Env == support.EnvTest {
|
||||
fmt.Println(err.Error())
|
||||
panic(err)
|
||||
} else {
|
||||
facades.Log().Errorf("[面板][Helpers] 执行命令 %s 失败: %s", shell, err.Error())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
@@ -88,39 +99,56 @@ func ExecAsync(shell string) {
|
||||
fmt.Println(err.Error())
|
||||
panic(err)
|
||||
} else {
|
||||
facades.Log().Errorf("[面板][Helpers] 执行命令 %s 失败: %s", shell, err.Error())
|
||||
facades.Log().With(map[string]any{
|
||||
"shell": shell,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("异步执行命令失败")
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Mkdir 创建目录
|
||||
func Mkdir(path string, permission os.FileMode) bool {
|
||||
if err := os.MkdirAll(path, permission); err != nil {
|
||||
facades.Log().Errorf("[面板][Helpers] 创建目录 %s 失败: %s", path, err.Error())
|
||||
facades.Log().With(map[string]any{
|
||||
"path": path,
|
||||
"permission": permission,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("创建目录失败")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Chmod 修改文件权限
|
||||
// Chmod 修改文件/目录权限
|
||||
func Chmod(path string, permission os.FileMode) bool {
|
||||
if err := os.Chmod(path, permission); err != nil {
|
||||
facades.Log().Errorf("[面板][Helpers] 修改文件 %s 权限失败: %s", path, err.Error())
|
||||
facades.Log().With(map[string]any{
|
||||
"path": path,
|
||||
"permission": permission,
|
||||
}).Tags("面板", "工具函数").Error("修改文件/目录权限失败")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Chown 修改路径所有者
|
||||
// Chown 修改文件/目录所有者
|
||||
func Chown(path, user, group string) bool {
|
||||
cmd := exec.Command("chown", "-R", user+":"+group, path)
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
facades.Log().Errorf("[面板][Helpers] 修改路径 %s 所有者失败: %s", path, err.Error())
|
||||
facades.Log().With(map[string]any{
|
||||
"path": path,
|
||||
"user": user,
|
||||
"group": group,
|
||||
"error": err.Error(),
|
||||
}).Tags("面板", "工具函数").Error("修改文件/目录所有者失败")
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -143,20 +171,19 @@ func Empty(path string) bool {
|
||||
return len(files) == 0
|
||||
}
|
||||
|
||||
// Mv 移动路径
|
||||
// Mv 移动文件/目录
|
||||
func Mv(src, dst string) (bool, error) {
|
||||
cmd := exec.Command("mv", src, dst)
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
facades.Log().Errorf("[面板][Helpers] 移动 %s 到 %s 失败: %s", src, dst, err.Error())
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Cp 复制路径
|
||||
// Cp 复制文件/目录
|
||||
func Cp(src, dst string) (bool, error) {
|
||||
cmd := exec.Command("cp", "-r", src, dst)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user