mirror of
https://github.com/tnb-labs/panel.git
synced 2026-08-31 01:12:17 +08:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 83f58e0a2e | |||
| e941ab6661 | |||
| 688801eebb | |||
| 8ad42f8c0e | |||
| 02c8809785 | |||
| fd0e43fb26 | |||
| 96ec795096 | |||
| 5ea191b550 | |||
| c37cc3bd2c | |||
| 110f305f16 | |||
| 179b6ff83e | |||
| 0da1b0b565 | |||
| 0da3f7b8e0 | |||
| c6f9a585b0 | |||
| 686bdd9ae2 | |||
| e3a22f924e | |||
| 0c3c47361b | |||
| c3f9f56f11 | |||
| 76e992cc9e | |||
| 73cc5a35ad | |||
| 873520e9f4 | |||
| af3254c11a | |||
| 5575d34ab4 | |||
| a995c56f1b | |||
| 1fbea148e3 | |||
| ca504e1acc | |||
| 18fe84117d | |||
| 9eb9a2c7d6 | |||
| de7d50ce51 | |||
| 6e0d93257f | |||
| 96806d4e94 | |||
| 3de78c95bf |
+2
-2
@@ -59,7 +59,7 @@ fetch:
|
||||
stage: build
|
||||
image: alpine:latest
|
||||
before_script:
|
||||
- sed -i 's/dl-cdn.alpinelinux.org/mirror.sjtu.edu.cn/g' /etc/apk/repositories
|
||||
- sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
|
||||
- apk add --no-cache curl jq unzip zip
|
||||
script:
|
||||
- curl -sSL "https://git.haozi.net/api/v4/projects/opensource%2Fpanel-frontend/releases" | jq -r '.[0].assets.links[] | select(.name | contains("dist")) | .direct_asset_url' | xargs curl -L -o frontend.zip
|
||||
@@ -87,6 +87,6 @@ release:
|
||||
# generate a changelog.
|
||||
GIT_DEPTH: 0
|
||||
script:
|
||||
- sed -i 's/dl-cdn.alpinelinux.org/mirror.sjtu.edu.cn/g' /etc/apk/repositories
|
||||
- sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
|
||||
- apk add --no-cache upx
|
||||
- goreleaser release --clean
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ upx:
|
||||
# Whether to try LZMA (slower).
|
||||
lzma: true
|
||||
# Whether to try all methods and filters (slow).
|
||||
brute: true
|
||||
brute: false
|
||||
|
||||
archives:
|
||||
- id: panel-archive
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
<a href="https://app.fossa.com/projects/git%2Bgithub.com%2FTheTNB%2Fpanel?ref=badge_shield"><img src="https://app.fossa.com/api/projects/git%2Bgithub.com%2FTheTNB%2Fpanel.svg?type=shield" alt="FOSSA Status"></a>
|
||||
</p>
|
||||
|
||||
耗子 Linux 面板是使用 Golang + Vue 开发的轻量 Linux 服务器运维管理面板,以 GNU Affero General Public License v3.0 开源。
|
||||
耗子 Linux 面板是使用 Golang + Vue 开发的开源轻量 Linux 服务器运维管理面板。
|
||||
|
||||
交流QQ群:[12370907](https://jq.qq.com/?_wv=1027&k=I1oJKSTH) | QQ频道:[pd.qq.com/s/fyol46wfy](https://pd.qq.com/s/fyol46wfy)
|
||||
交流QQ群:[12370907](https://jq.qq.com/?_wv=1027&k=I1oJKSTH) | 论坛:[tom.moe](https://tom.moe) | 赞助:[爱发电](https://afdian.net/a/TheTNB)
|
||||
|
||||
## 优势
|
||||
|
||||
@@ -36,9 +36,7 @@
|
||||
|
||||
低配机器建议使用 `Debian`,资源占用较 `RHEL` 系更低。其他机器建议使用 `AlmaLinux` | `RockyLinux`,维护周期更长也更稳定。
|
||||
|
||||
不在下表中的其他 RHEL 9.x 系统,可自行尝试安装,但不保证能够正常运行,且不提供无偿技术支持(理论上不会有大问题)。
|
||||
|
||||
CentOS Stream 可使用迁移脚本迁移至支持的系统: [CentOS 8/9 迁移脚本](https://github.com/TheTNB/byecentos)
|
||||
不在下表中的其他 RHEL 9.x 系统,可自行尝试安装,但不保证能够正常运行,且不提供技术支持(理论上不会有大问题)。
|
||||
|
||||
| 系统 | 版本 |
|
||||
|------------|----|
|
||||
|
||||
+3
-5
@@ -12,9 +12,9 @@
|
||||
<a href="https://app.fossa.com/projects/git%2Bgithub.com%2FTheTNB%2Fpanel?ref=badge_shield"><img src="https://app.fossa.com/api/projects/git%2Bgithub.com%2FTheTNB%2Fpanel.svg?type=shield" alt="FOSSA Status"></a>
|
||||
</p>
|
||||
|
||||
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.
|
||||
The HaoZi Linux Panel is an open source lightweight Linux server operation and maintenance management panel developed using Golang and Vue.
|
||||
|
||||
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)
|
||||
Communication QQ group: [12370907](https://jq.qq.com/?_wv=1027&k=I1oJKSTH) | Forum: [tom.moe](https://tom.moe) | Sponsor: [Open Collective](https://opencollective.com/tnb)
|
||||
|
||||
## Advantages
|
||||
|
||||
@@ -36,9 +36,7 @@ HaoZi Linux Panel only supports the latest version of mainstream systems under t
|
||||
|
||||
Recommended to use `Debian` for low-configuration machines, as its resource usage is lower than that of the `RHEL` system. For other machines, recommended to use `RockyLinux` | `AlmaLinux`, which has a longer maintenance cycle and is more stable.
|
||||
|
||||
For other RHEL 9.x systems not in the table, you can try to install it yourself, but normal operation is not guaranteed, and free technical support is not provided (theoretically there will be no major question).
|
||||
|
||||
CentOS Stream can be migrated to a supported system using the migration script: [CentOS 8/9 Migration Script](https://github.com/TheTNB/byecentos)
|
||||
For other RHEL 9.x systems not in the table, you can try to install it yourself, but normal operation is not guaranteed, and technical support is not provided (theoretically there will be no major question).
|
||||
|
||||
| OS | Version |
|
||||
|------------|---------|
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
// CertRenew 证书续签
|
||||
@@ -39,7 +39,7 @@ func (receiver *CertRenew) Extend() command.Extend {
|
||||
|
||||
// Handle Execute the console command.
|
||||
func (receiver *CertRenew) Handle(console.Context) error {
|
||||
if internal.Status != internal.StatusNormal {
|
||||
if types.Status != types.StatusNormal {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2,19 +2,18 @@ package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/gookit/color"
|
||||
"github.com/goravel/framework/contracts/console"
|
||||
"github.com/goravel/framework/contracts/console/command"
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
"github.com/goravel/framework/support/color"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
// Monitoring 系统监控
|
||||
@@ -41,10 +40,14 @@ func (receiver *Monitoring) Extend() command.Extend {
|
||||
|
||||
// Handle Execute the console command.
|
||||
func (receiver *Monitoring) Handle(console.Context) error {
|
||||
if internal.Status != internal.StatusNormal {
|
||||
if types.Status != types.StatusNormal {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 将等待中的任务分发
|
||||
task := services.NewTaskImpl()
|
||||
_ = task.DispatchWaiting()
|
||||
|
||||
setting := services.NewSettingImpl()
|
||||
monitor := setting.Get(models.SettingKeyMonitor)
|
||||
if !cast.ToBool(monitor) {
|
||||
@@ -52,7 +55,6 @@ func (receiver *Monitoring) Handle(console.Context) error {
|
||||
}
|
||||
|
||||
info := tools.GetMonitoringInfo()
|
||||
|
||||
translate := facades.Lang(context.Background())
|
||||
|
||||
// 去除部分数据以减少数据库存储
|
||||
@@ -66,30 +68,29 @@ func (receiver *Monitoring) Handle(console.Context) error {
|
||||
cpu.Flags = nil
|
||||
}
|
||||
|
||||
if internal.Status != internal.StatusNormal {
|
||||
if types.Status != types.StatusNormal {
|
||||
return nil
|
||||
}
|
||||
err := facades.Orm().Query().Create(&models.Monitor{
|
||||
Info: info,
|
||||
})
|
||||
if err != nil {
|
||||
facades.Log().Infof("[面板] 系统监控保存失败: %s", err.Error())
|
||||
color.Redf(translate.Get("commands.panel:monitoring.fail")+": %s", err.Error())
|
||||
facades.Log().Tags("面板", "系统监控").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Infof("保存失败")
|
||||
color.Red().Printfln(translate.Get("commands.panel:monitoring.fail")+": %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
// 删除过期数据
|
||||
monitorDays := setting.Get(models.SettingKeyMonitorDays)
|
||||
days, err := strconv.Atoi(monitorDays)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if days <= 0 || internal.Status != internal.StatusNormal {
|
||||
days := cast.ToInt(setting.Get(models.SettingKeyMonitorDays))
|
||||
if days <= 0 || types.Status != types.StatusNormal {
|
||||
return nil
|
||||
}
|
||||
if _, err = facades.Orm().Query().Where("created_at < ?", carbon.Now().SubDays(days).ToDateTimeString()).Delete(&models.Monitor{}); err != nil {
|
||||
facades.Log().Infof("[面板] 系统监控删除过期数据失败: %s", err.Error())
|
||||
facades.Log().Tags("面板", "系统监控").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Infof("删除过期数据失败")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+181
-174
@@ -8,17 +8,17 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/gookit/color"
|
||||
"github.com/goravel/framework/contracts/console"
|
||||
"github.com/goravel/framework/contracts/console/command"
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
"github.com/goravel/framework/support/color"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
// Panel 面板命令行
|
||||
@@ -59,69 +59,76 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
var check models.User
|
||||
err := facades.Orm().Query().FirstOrFail(&check)
|
||||
if err == nil {
|
||||
color.Redln(translate.Get("commands.panel.init.exist"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.init.exist"))
|
||||
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.SettingKeyVersion, Value: facades.Config().GetString("panel.version")}}
|
||||
err = facades.Orm().Query().Create(&settings)
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.init.fail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.init.fail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
hash, err := facades.Hash().Make(tools.RandomString(32))
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.init.fail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.init.fail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
user := services.NewUserImpl()
|
||||
_, err = user.Create("admin", hash)
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.init.adminFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.init.adminFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.init.success"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.init.success"))
|
||||
|
||||
case "update":
|
||||
var task models.Task
|
||||
err := facades.Orm().Query().Where("status", models.TaskStatusRunning).OrWhere("status", models.TaskStatusWaiting).FirstOrFail(&task)
|
||||
if err == nil {
|
||||
color.Redln(translate.Get("commands.panel.update.taskCheck"))
|
||||
if err := facades.Orm().Query().Where("status", models.TaskStatusRunning).OrWhere("status", models.TaskStatusWaiting).FirstOrFail(&task); err == nil {
|
||||
color.Red().Printfln(translate.Get("commands.panel.update.taskCheck"))
|
||||
return nil
|
||||
}
|
||||
if _, err := facades.Orm().Query().Exec("PRAGMA wal_checkpoint(TRUNCATE)"); err != nil {
|
||||
types.Status = types.StatusFailed
|
||||
color.Red().Printfln(translate.Get("commands.panel.update.dbFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
panel, err := tools.GetLatestPanelVersion()
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.update.versionFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.update.versionFail"))
|
||||
return err
|
||||
}
|
||||
|
||||
internal.Status = internal.StatusUpgrade
|
||||
// 停止面板服务,因为在shell中运行的和systemd的不同
|
||||
_ = tools.ServiceStop("panel")
|
||||
|
||||
types.Status = types.StatusUpgrade
|
||||
if err = tools.UpdatePanel(panel); err != nil {
|
||||
internal.Status = internal.StatusFailed
|
||||
color.Redln(translate.Get("commands.panel.update.fail") + ": " + err.Error())
|
||||
types.Status = types.StatusFailed
|
||||
color.Red().Printfln(translate.Get("commands.panel.update.fail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
internal.Status = internal.StatusNormal
|
||||
color.Greenln(translate.Get("commands.panel.update.success"))
|
||||
types.Status = types.StatusNormal
|
||||
color.Green().Printfln(translate.Get("commands.panel.update.success"))
|
||||
tools.RestartPanel()
|
||||
|
||||
case "getInfo":
|
||||
var user models.User
|
||||
err := facades.Orm().Query().Where("id", 1).FirstOrFail(&user)
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.getInfo.adminGetFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.getInfo.adminGetFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
password := tools.RandomString(16)
|
||||
hash, err := facades.Hash().Make(password)
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.getInfo.passwordGenerationFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.getInfo.passwordGenerationFail"))
|
||||
return nil
|
||||
}
|
||||
user.Username = tools.RandomString(8)
|
||||
@@ -132,13 +139,13 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
|
||||
err = facades.Orm().Query().Save(&user)
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.getInfo.adminSaveFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.getInfo.adminSaveFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
port, err := tools.Exec(`cat /www/panel/panel.conf | grep APP_PORT | awk -F '=' '{print $2}' | tr -d '\n'`)
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.portFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.portFail"))
|
||||
return nil
|
||||
}
|
||||
ip, err := tools.GetPublicIP()
|
||||
@@ -150,42 +157,42 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
protocol = "https"
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.getInfo.username") + ": " + user.Username)
|
||||
color.Greenln(translate.Get("commands.panel.getInfo.password") + ": " + password)
|
||||
color.Greenln(translate.Get("commands.panel.port") + ": " + port)
|
||||
color.Greenln(translate.Get("commands.panel.entrance") + ": " + facades.Config().GetString("http.entrance"))
|
||||
color.Greenln(translate.Get("commands.panel.getInfo.address") + ": " + protocol + "://" + ip + ":" + port + facades.Config().GetString("http.entrance"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.getInfo.username") + ": " + user.Username)
|
||||
color.Green().Printfln(translate.Get("commands.panel.getInfo.password") + ": " + password)
|
||||
color.Green().Printfln(translate.Get("commands.panel.port") + ": " + port)
|
||||
color.Green().Printfln(translate.Get("commands.panel.entrance") + ": " + facades.Config().GetString("http.entrance"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.getInfo.address") + ": " + protocol + "://" + ip + ":" + port + facades.Config().GetString("http.entrance"))
|
||||
|
||||
case "getPort":
|
||||
port, err := tools.Exec(`cat /www/panel/panel.conf | grep APP_PORT | awk -F '=' '{print $2}' | tr -d '\n'`)
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.portFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.portFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.port") + ": " + port)
|
||||
color.Green().Printfln(translate.Get("commands.panel.port") + ": " + port)
|
||||
|
||||
case "getEntrance":
|
||||
color.Greenln(translate.Get("commands.panel.entrance") + ": " + facades.Config().GetString("http.entrance"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.entrance") + ": " + facades.Config().GetString("http.entrance"))
|
||||
|
||||
case "deleteEntrance":
|
||||
oldEntrance, err := tools.Exec(`cat /www/panel/panel.conf | grep APP_ENTRANCE | awk -F '=' '{print $2}' | tr -d '\n'`)
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.deleteEntrance.fail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.deleteEntrance.fail"))
|
||||
return nil
|
||||
}
|
||||
if _, err = tools.Exec("sed -i 's!APP_ENTRANCE=" + oldEntrance + "!APP_ENTRANCE=/!g' /www/panel/panel.conf"); err != nil {
|
||||
color.Redln(translate.Get("commands.panel.deleteEntrance.fail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.deleteEntrance.fail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.deleteEntrance.success"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.deleteEntrance.success"))
|
||||
|
||||
case "writePlugin":
|
||||
slug := arg1
|
||||
version := arg2
|
||||
if len(slug) == 0 || len(version) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.writePlugin.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.writePlugin.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -197,31 +204,31 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.writePlugin.fail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.writePlugin.fail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.writePlugin.success"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.writePlugin.success"))
|
||||
|
||||
case "deletePlugin":
|
||||
slug := arg1
|
||||
if len(slug) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.deletePlugin.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.deletePlugin.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := facades.Orm().Query().Where("slug", slug).Delete(&models.Plugin{})
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.deletePlugin.fail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.deletePlugin.fail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.deletePlugin.success"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.deletePlugin.success"))
|
||||
|
||||
case "writeMysqlPassword":
|
||||
password := arg1
|
||||
if len(password) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.writeMysqlPassword.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.writeMysqlPassword.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -233,20 +240,20 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.writeMysqlPassword.fail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.writeMysqlPassword.fail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.writeMysqlPassword.success"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.writeMysqlPassword.success"))
|
||||
|
||||
case "cleanTask":
|
||||
_, err := facades.Orm().Query().Model(&models.Task{}).Where("status", models.TaskStatusRunning).OrWhere("status", models.TaskStatusWaiting).Update("status", models.TaskStatusFailed)
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.cleanTask.fail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.cleanTask.fail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.cleanTask.success"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.cleanTask.success"))
|
||||
|
||||
case "backup":
|
||||
backupType := arg1
|
||||
@@ -255,37 +262,37 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
save := arg4
|
||||
hr := `+----------------------------------------------------`
|
||||
if len(backupType) == 0 || len(name) == 0 || len(path) == 0 || len(save) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.backup.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.backup.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(hr)
|
||||
color.Greenln("★ " + translate.Get("commands.panel.backup.start") + " [" + carbon.Now().ToDateTimeString() + "]")
|
||||
color.Greenln(hr)
|
||||
color.Green().Printfln(hr)
|
||||
color.Green().Printfln("★ " + translate.Get("commands.panel.backup.start") + " [" + carbon.Now().ToDateTimeString() + "]")
|
||||
color.Green().Printfln(hr)
|
||||
|
||||
if !tools.Exists(path) {
|
||||
if err := tools.Mkdir(path, 0644); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.backupDirFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.backupDirFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
switch backupType {
|
||||
case "website":
|
||||
color.Yellowln("|-" + translate.Get("commands.panel.backup.targetSite") + ": " + name)
|
||||
color.Yellow().Printfln("|-" + translate.Get("commands.panel.backup.targetSite") + ": " + name)
|
||||
var website models.Website
|
||||
if err := facades.Orm().Query().Where("name", name).FirstOrFail(&website); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.siteNotExist"))
|
||||
color.Greenln(hr)
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.siteNotExist"))
|
||||
color.Green().Printfln(hr)
|
||||
return nil
|
||||
}
|
||||
|
||||
backupFile := path + "/" + website.Name + "_" + carbon.Now().ToShortDateTimeString() + ".zip"
|
||||
if _, err := tools.Exec(`cd '` + website.Path + `' && zip -r '` + backupFile + `' .`); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.backupFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.backupFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.backupSuccess"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.backupSuccess"))
|
||||
|
||||
case "mysql":
|
||||
rootPassword := services.NewSettingImpl().Get(models.SettingKeyMysqlRootPassword)
|
||||
@@ -293,81 +300,81 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
|
||||
err := os.Setenv("MYSQL_PWD", rootPassword)
|
||||
if err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.mysqlBackupFail") + ": " + err.Error())
|
||||
color.Greenln(hr)
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.mysqlBackupFail") + ": " + err.Error())
|
||||
color.Green().Printfln(hr)
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.targetMysql") + ": " + name)
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.startExport"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.targetMysql") + ": " + name)
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.startExport"))
|
||||
if _, err = tools.Exec(`mysqldump -uroot ` + name + ` > /tmp/` + backupFile + ` 2>&1`); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.exportFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.exportFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.exportSuccess"))
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.startCompress"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.exportSuccess"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.startCompress"))
|
||||
if _, err = tools.Exec("cd /tmp && zip -r " + backupFile + ".zip " + backupFile); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.compressFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.compressFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
if err := tools.Remove("/tmp/" + backupFile); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.deleteFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.deleteFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.compressSuccess"))
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.startMove"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.compressSuccess"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.startMove"))
|
||||
if err := tools.Mv("/tmp/"+backupFile+".zip", path+"/"+backupFile+".zip"); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.moveFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.moveFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.moveSuccess"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.moveSuccess"))
|
||||
_ = os.Unsetenv("MYSQL_PWD")
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.success"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.success"))
|
||||
|
||||
case "postgresql":
|
||||
backupFile := name + "_" + carbon.Now().ToShortDateTimeString() + ".sql"
|
||||
check, err := tools.Exec(`su - postgres -c "psql -l" 2>&1`)
|
||||
if err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.databaseGetFail") + ": " + err.Error())
|
||||
color.Greenln(hr)
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.databaseGetFail") + ": " + err.Error())
|
||||
color.Green().Printfln(hr)
|
||||
return nil
|
||||
}
|
||||
if !strings.Contains(check, name) {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.databaseNotExist"))
|
||||
color.Greenln(hr)
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.databaseNotExist"))
|
||||
color.Green().Printfln(hr)
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.targetPostgres") + ": " + name)
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.startExport"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.targetPostgres") + ": " + name)
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.startExport"))
|
||||
if _, err = tools.Exec(`su - postgres -c "pg_dump '` + name + `'" > /tmp/` + backupFile + ` 2>&1`); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.exportFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.exportFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.exportSuccess"))
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.startCompress"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.exportSuccess"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.startCompress"))
|
||||
if _, err = tools.Exec("cd /tmp && zip -r " + backupFile + ".zip " + backupFile); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.compressFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.compressFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
if err := tools.Remove("/tmp/" + backupFile); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.deleteFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.deleteFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.compressSuccess"))
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.startMove"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.compressSuccess"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.startMove"))
|
||||
if err := tools.Mv("/tmp/"+backupFile+".zip", path+"/"+backupFile+".zip"); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.moveFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.moveFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.moveSuccess"))
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.success"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.moveSuccess"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.success"))
|
||||
}
|
||||
|
||||
color.Greenln(hr)
|
||||
color.Green().Printfln(hr)
|
||||
files, err := os.ReadDir(path)
|
||||
if err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.cleanupFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.cleanupFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
var filteredFiles []os.FileInfo
|
||||
@@ -385,60 +392,60 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
})
|
||||
for i := cast.ToInt(save); i < len(filteredFiles); i++ {
|
||||
fileToDelete := filepath.Join(path, filteredFiles[i].Name())
|
||||
color.Yellowln("|-" + translate.Get("commands.panel.backup.cleanBackup") + ": " + fileToDelete)
|
||||
color.Yellow().Printfln("|-" + translate.Get("commands.panel.backup.cleanBackup") + ": " + fileToDelete)
|
||||
if err := tools.Remove(fileToDelete); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.backup.cleanupFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.backup.cleanupFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
}
|
||||
color.Greenln("|-" + translate.Get("commands.panel.backup.cleanupSuccess"))
|
||||
color.Greenln(hr)
|
||||
color.Greenln("☆ " + translate.Get("commands.panel.backup.success") + " [" + carbon.Now().ToDateTimeString() + "]")
|
||||
color.Greenln(hr)
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.backup.cleanupSuccess"))
|
||||
color.Green().Printfln(hr)
|
||||
color.Green().Printfln("☆ " + translate.Get("commands.panel.backup.success") + " [" + carbon.Now().ToDateTimeString() + "]")
|
||||
color.Green().Printfln(hr)
|
||||
|
||||
case "cutoff":
|
||||
name := arg1
|
||||
save := arg2
|
||||
hr := `+----------------------------------------------------`
|
||||
if len(name) == 0 || len(save) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.cutoff.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.cutoff.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(hr)
|
||||
color.Greenln("★ " + translate.Get("commands.panel.cutoff.start") + " [" + carbon.Now().ToDateTimeString() + "]")
|
||||
color.Greenln(hr)
|
||||
color.Green().Printfln(hr)
|
||||
color.Green().Printfln("★ " + translate.Get("commands.panel.cutoff.start") + " [" + carbon.Now().ToDateTimeString() + "]")
|
||||
color.Green().Printfln(hr)
|
||||
|
||||
color.Yellowln("|-" + translate.Get("commands.panel.cutoff.targetSite") + ": " + name)
|
||||
color.Yellow().Printfln("|-" + translate.Get("commands.panel.cutoff.targetSite") + ": " + name)
|
||||
var website models.Website
|
||||
if err := facades.Orm().Query().Where("name", name).FirstOrFail(&website); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.cutoff.siteNotExist"))
|
||||
color.Greenln(hr)
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.cutoff.siteNotExist"))
|
||||
color.Green().Printfln(hr)
|
||||
return nil
|
||||
}
|
||||
|
||||
logPath := "/www/wwwlogs/" + website.Name + ".log"
|
||||
if !tools.Exists(logPath) {
|
||||
color.Redln("|-" + translate.Get("commands.panel.cutoff.logNotExist"))
|
||||
color.Greenln(hr)
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.cutoff.logNotExist"))
|
||||
color.Green().Printfln(hr)
|
||||
return nil
|
||||
}
|
||||
|
||||
backupPath := "/www/wwwlogs/" + website.Name + "_" + carbon.Now().ToShortDateTimeString() + ".log.zip"
|
||||
if _, err := tools.Exec(`cd /www/wwwlogs && zip -r ` + backupPath + ` ` + website.Name + ".log"); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.cutoff.backupFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.cutoff.backupFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
if _, err := tools.Exec(`echo "" > ` + logPath); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.cutoff.clearFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.cutoff.clearFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
color.Greenln("|-" + translate.Get("commands.panel.cutoff.cutSuccess"))
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.cutoff.cutSuccess"))
|
||||
|
||||
color.Greenln(hr)
|
||||
color.Green().Printfln(hr)
|
||||
files, err := os.ReadDir("/www/wwwlogs")
|
||||
if err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.cutoff.cleanupFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.cutoff.cleanupFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
var filteredFiles []os.FileInfo
|
||||
@@ -456,16 +463,16 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
})
|
||||
for i := cast.ToInt(save); i < len(filteredFiles); i++ {
|
||||
fileToDelete := filepath.Join("/www/wwwlogs", filteredFiles[i].Name())
|
||||
color.Yellowln("|-" + translate.Get("commands.panel.cutoff.clearLog") + ": " + fileToDelete)
|
||||
color.Yellow().Printfln("|-" + translate.Get("commands.panel.cutoff.clearLog") + ": " + fileToDelete)
|
||||
if err := tools.Remove(fileToDelete); err != nil {
|
||||
color.Redln("|-" + translate.Get("commands.panel.cutoff.cleanupFail") + ": " + err.Error())
|
||||
color.Red().Printfln("|-" + translate.Get("commands.panel.cutoff.cleanupFail") + ": " + err.Error())
|
||||
return nil
|
||||
}
|
||||
}
|
||||
color.Greenln("|-" + translate.Get("commands.panel.cutoff.cleanupSuccess"))
|
||||
color.Greenln(hr)
|
||||
color.Greenln("☆ " + translate.Get("commands.panel.cutoff.end") + " [" + carbon.Now().ToDateTimeString() + "]")
|
||||
color.Greenln(hr)
|
||||
color.Green().Printfln("|-" + translate.Get("commands.panel.cutoff.cleanupSuccess"))
|
||||
color.Green().Printfln(hr)
|
||||
color.Green().Printfln("☆ " + translate.Get("commands.panel.cutoff.end") + " [" + carbon.Now().ToDateTimeString() + "]")
|
||||
color.Green().Printfln(hr)
|
||||
|
||||
case "writeSite":
|
||||
name := arg1
|
||||
@@ -474,19 +481,19 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
php := cast.ToInt(arg4)
|
||||
ssl := cast.ToBool(ctx.Argument(5))
|
||||
if len(name) == 0 || len(path) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.writeSite.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.writeSite.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
var website models.Website
|
||||
if err := facades.Orm().Query().Where("name", name).FirstOrFail(&website); err == nil {
|
||||
color.Redln(translate.Get("commands.panel.writeSite.siteExist"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.writeSite.siteExist"))
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := os.Stat(path)
|
||||
if os.IsNotExist(err) {
|
||||
color.Redln(translate.Get("commands.panel.writeSite.pathNotExist"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.writeSite.pathNotExist"))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -498,32 +505,32 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
Ssl: ssl,
|
||||
})
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.writeSite.fail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.writeSite.fail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.writeSite.success"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.writeSite.success"))
|
||||
|
||||
case "deleteSite":
|
||||
name := arg1
|
||||
if len(name) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.deleteSite.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.deleteSite.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := facades.Orm().Query().Where("name", name).Delete(&models.Website{})
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.deleteSite.fail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.deleteSite.fail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.deleteSite.success"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.deleteSite.success"))
|
||||
|
||||
case "writeSetting":
|
||||
key := arg1
|
||||
value := arg2
|
||||
if len(key) == 0 || len(value) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.writeSetting.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.writeSetting.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -534,16 +541,16 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
Value: value,
|
||||
})
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.writeSetting.fail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.writeSetting.fail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.writeSetting.success"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.writeSetting.success"))
|
||||
|
||||
case "getSetting":
|
||||
key := arg1
|
||||
if len(key) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.getSetting.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.getSetting.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -557,17 +564,17 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
case "deleteSetting":
|
||||
key := arg1
|
||||
if len(key) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.deleteSetting.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.deleteSetting.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := facades.Orm().Query().Where("key", key).Delete(&models.Setting{})
|
||||
if err != nil {
|
||||
color.Redln(translate.Get("commands.panel.deleteSetting.fail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.deleteSetting.fail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.deleteSetting.success"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.deleteSetting.success"))
|
||||
|
||||
case "addSite":
|
||||
name := arg1
|
||||
@@ -576,14 +583,14 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
path := arg4
|
||||
php := arg5
|
||||
if len(name) == 0 || len(domain) == 0 || len(port) == 0 || len(path) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.addSite.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.addSite.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
domains := strings.Split(domain, ",")
|
||||
ports := strings.Split(port, ",")
|
||||
if len(domains) == 0 || len(ports) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.addSite.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.addSite.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -595,15 +602,15 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
website := services.NewWebsiteImpl()
|
||||
id, err := website.GetIDByName(name)
|
||||
if err != nil {
|
||||
color.Redln(err.Error())
|
||||
color.Red().Printfln(err.Error())
|
||||
return nil
|
||||
}
|
||||
if id != 0 {
|
||||
color.Redln(translate.Get("commands.panel.addSite.siteExist"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.addSite.siteExist"))
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = website.Add(internal.PanelWebsite{
|
||||
_, err = website.Add(types.Website{
|
||||
Name: name,
|
||||
Status: true,
|
||||
Domains: domains,
|
||||
@@ -614,108 +621,108 @@ func (receiver *Panel) Handle(ctx console.Context) error {
|
||||
Db: false,
|
||||
})
|
||||
if err != nil {
|
||||
color.Redln(err.Error())
|
||||
color.Red().Printfln(err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.addSite.success"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.addSite.success"))
|
||||
|
||||
case "removeSite":
|
||||
name := arg1
|
||||
if len(name) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.removeSite.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.removeSite.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
website := services.NewWebsiteImpl()
|
||||
id, err := website.GetIDByName(name)
|
||||
if err != nil {
|
||||
color.Redln(err.Error())
|
||||
color.Red().Printfln(err.Error())
|
||||
return nil
|
||||
}
|
||||
if id == 0 {
|
||||
color.Redln(translate.Get("commands.panel.removeSite.siteNotExist"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.removeSite.siteNotExist"))
|
||||
return nil
|
||||
}
|
||||
|
||||
if err = website.Delete(id); err != nil {
|
||||
color.Redln(err.Error())
|
||||
color.Red().Printfln(err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.removeSite.success"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.removeSite.success"))
|
||||
|
||||
case "installPlugin":
|
||||
slug := arg1
|
||||
if len(slug) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.installPlugin.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.installPlugin.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
plugin := services.NewPluginImpl()
|
||||
if err := plugin.Install(slug); err != nil {
|
||||
color.Redln(err.Error())
|
||||
color.Red().Printfln(err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.installPlugin.success"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.installPlugin.success"))
|
||||
|
||||
case "uninstallPlugin":
|
||||
slug := arg1
|
||||
if len(slug) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.uninstallPlugin.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.uninstallPlugin.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
plugin := services.NewPluginImpl()
|
||||
if err := plugin.Uninstall(slug); err != nil {
|
||||
color.Redln(err.Error())
|
||||
color.Red().Printfln(err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.uninstallPlugin.success"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.uninstallPlugin.success"))
|
||||
|
||||
case "updatePlugin":
|
||||
slug := arg1
|
||||
if len(slug) == 0 {
|
||||
color.Redln(translate.Get("commands.panel.updatePlugin.paramFail"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.updatePlugin.paramFail"))
|
||||
return nil
|
||||
}
|
||||
|
||||
plugin := services.NewPluginImpl()
|
||||
if err := plugin.Update(slug); err != nil {
|
||||
color.Redln(err.Error())
|
||||
color.Red().Printfln(err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
color.Greenln(translate.Get("commands.panel.updatePlugin.success"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.updatePlugin.success"))
|
||||
|
||||
default:
|
||||
color.Yellowln(facades.Config().GetString("panel.name") + " - " + translate.Get("commands.panel.tool") + " - " + facades.Config().GetString("panel.version"))
|
||||
color.Greenln(translate.Get("commands.panel.use") + ":")
|
||||
color.Greenln("panel update " + translate.Get("commands.panel.update.description"))
|
||||
color.Greenln("panel getInfo " + translate.Get("commands.panel.getInfo.description"))
|
||||
color.Greenln("panel getPort " + translate.Get("commands.panel.getPort.description"))
|
||||
color.Greenln("panel getEntrance " + translate.Get("commands.panel.getEntrance.description"))
|
||||
color.Greenln("panel deleteEntrance " + translate.Get("commands.panel.deleteEntrance.description"))
|
||||
color.Greenln("panel cleanTask " + translate.Get("commands.panel.cleanTask.description"))
|
||||
color.Greenln("panel backup {website/mysql/postgresql} {name} {path} {save_copies} " + translate.Get("commands.panel.backup.description"))
|
||||
color.Greenln("panel cutoff {website_name} {save_copies} " + translate.Get("commands.panel.cutoff.description"))
|
||||
color.Greenln("panel installPlugin {slug} " + translate.Get("commands.panel.installPlugin.description"))
|
||||
color.Greenln("panel uninstallPlugin {slug} " + translate.Get("commands.panel.uninstallPlugin.description"))
|
||||
color.Greenln("panel updatePlugin {slug} " + translate.Get("commands.panel.updatePlugin.description"))
|
||||
color.Greenln("panel addSite {name} {domain} {port} {path} {php} " + translate.Get("commands.panel.addSite.description"))
|
||||
color.Greenln("panel removeSite {name} " + translate.Get("commands.panel.removeSite.description"))
|
||||
color.Redln(translate.Get("commands.panel.forDeveloper") + ":")
|
||||
color.Yellowln("panel init " + translate.Get("commands.panel.init.description"))
|
||||
color.Yellowln("panel writePlugin {slug} {version} " + translate.Get("commands.panel.writePlugin.description"))
|
||||
color.Yellowln("panel deletePlugin {slug} " + translate.Get("commands.panel.deletePlugin.description"))
|
||||
color.Yellowln("panel writeMysqlPassword {password} " + translate.Get("commands.panel.writeMysqlPassword.description"))
|
||||
color.Yellowln("panel writeSite {name} {status} {path} {php} {ssl} " + translate.Get("commands.panel.writeSite.description"))
|
||||
color.Yellowln("panel deleteSite {name} " + translate.Get("commands.panel.deleteSite.description"))
|
||||
color.Yellowln("panel getSetting {name} " + translate.Get("commands.panel.getSetting.description"))
|
||||
color.Yellowln("panel writeSetting {name} {value} " + translate.Get("commands.panel.writeSetting.description"))
|
||||
color.Yellowln("panel deleteSetting {name} " + translate.Get("commands.panel.deleteSetting.description"))
|
||||
color.Yellow().Printfln(facades.Config().GetString("panel.name") + " - " + translate.Get("commands.panel.tool") + " - " + facades.Config().GetString("panel.version"))
|
||||
color.Green().Printfln(translate.Get("commands.panel.use") + ":")
|
||||
color.Green().Printfln("panel update " + translate.Get("commands.panel.update.description"))
|
||||
color.Green().Printfln("panel getInfo " + translate.Get("commands.panel.getInfo.description"))
|
||||
color.Green().Printfln("panel getPort " + translate.Get("commands.panel.getPort.description"))
|
||||
color.Green().Printfln("panel getEntrance " + translate.Get("commands.panel.getEntrance.description"))
|
||||
color.Green().Printfln("panel deleteEntrance " + translate.Get("commands.panel.deleteEntrance.description"))
|
||||
color.Green().Printfln("panel cleanTask " + translate.Get("commands.panel.cleanTask.description"))
|
||||
color.Green().Printfln("panel backup {website/mysql/postgresql} {name} {path} {save_copies} " + translate.Get("commands.panel.backup.description"))
|
||||
color.Green().Printfln("panel cutoff {website_name} {save_copies} " + translate.Get("commands.panel.cutoff.description"))
|
||||
color.Green().Printfln("panel installPlugin {slug} " + translate.Get("commands.panel.installPlugin.description"))
|
||||
color.Green().Printfln("panel uninstallPlugin {slug} " + translate.Get("commands.panel.uninstallPlugin.description"))
|
||||
color.Green().Printfln("panel updatePlugin {slug} " + translate.Get("commands.panel.updatePlugin.description"))
|
||||
color.Green().Printfln("panel addSite {name} {domain} {port} {path} {php} " + translate.Get("commands.panel.addSite.description"))
|
||||
color.Green().Printfln("panel removeSite {name} " + translate.Get("commands.panel.removeSite.description"))
|
||||
color.Red().Printfln(translate.Get("commands.panel.forDeveloper") + ":")
|
||||
color.Yellow().Printfln("panel init " + translate.Get("commands.panel.init.description"))
|
||||
color.Yellow().Printfln("panel writePlugin {slug} {version} " + translate.Get("commands.panel.writePlugin.description"))
|
||||
color.Yellow().Printfln("panel deletePlugin {slug} " + translate.Get("commands.panel.deletePlugin.description"))
|
||||
color.Yellow().Printfln("panel writeMysqlPassword {password} " + translate.Get("commands.panel.writeMysqlPassword.description"))
|
||||
color.Yellow().Printfln("panel writeSite {name} {status} {path} {php} {ssl} " + translate.Get("commands.panel.writeSite.description"))
|
||||
color.Yellow().Printfln("panel deleteSite {name} " + translate.Get("commands.panel.deleteSite.description"))
|
||||
color.Yellow().Printfln("panel getSetting {name} " + translate.Get("commands.panel.getSetting.description"))
|
||||
color.Yellow().Printfln("panel writeSetting {name} {value} " + translate.Get("commands.panel.writeSetting.description"))
|
||||
color.Yellow().Printfln("panel deleteSetting {name} " + translate.Get("commands.panel.deleteSetting.description"))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
|
||||
"panel/internal"
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
// PanelTask 面板每日任务
|
||||
@@ -35,11 +35,11 @@ func (receiver *PanelTask) Extend() command.Extend {
|
||||
|
||||
// Handle Execute the console command.
|
||||
func (receiver *PanelTask) Handle(console.Context) error {
|
||||
internal.Status = internal.StatusMaintain
|
||||
types.Status = types.StatusMaintain
|
||||
|
||||
// 优化数据库
|
||||
if _, err := facades.Orm().Query().Exec("VACUUM"); err != nil {
|
||||
internal.Status = internal.StatusFailed
|
||||
types.Status = types.StatusFailed
|
||||
facades.Log().Tags("面板", "每日任务").
|
||||
With(map[string]any{
|
||||
"error": err.Error(),
|
||||
@@ -49,7 +49,7 @@ func (receiver *PanelTask) Handle(console.Context) error {
|
||||
|
||||
// 备份面板
|
||||
if err := tools.Archive([]string{"/www/panel"}, "/www/backup/panel/panel-"+carbon.Now().ToShortDateTimeString()+".zip"); err != nil {
|
||||
internal.Status = internal.StatusFailed
|
||||
types.Status = types.StatusFailed
|
||||
facades.Log().Tags("面板", "每日任务").
|
||||
With(map[string]any{
|
||||
"error": err.Error(),
|
||||
@@ -59,7 +59,7 @@ func (receiver *PanelTask) Handle(console.Context) error {
|
||||
|
||||
// 清理 7 天前的备份
|
||||
if _, err := tools.Exec(`find /www/backup/panel -mtime +7 -name "*.zip" -exec rm -rf {} \;`); err != nil {
|
||||
internal.Status = internal.StatusFailed
|
||||
types.Status = types.StatusFailed
|
||||
facades.Log().Tags("面板", "每日任务").
|
||||
With(map[string]any{
|
||||
"error": err.Error(),
|
||||
@@ -67,6 +67,6 @@ func (receiver *PanelTask) Handle(console.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
internal.Status = internal.StatusNormal
|
||||
types.Status = types.StatusNormal
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"github.com/goravel/framework/contracts/schedule"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/console/commands"
|
||||
"github.com/TheTNB/panel/app/console/commands"
|
||||
)
|
||||
|
||||
type Kernel struct {
|
||||
@@ -15,7 +15,7 @@ func (kernel *Kernel) Schedule() []schedule.Event {
|
||||
return []schedule.Event{
|
||||
facades.Schedule().Command("panel:monitoring").EveryMinute().SkipIfStillRunning(),
|
||||
facades.Schedule().Command("panel:cert-renew").DailyAt("04:00").SkipIfStillRunning(),
|
||||
facades.Schedule().Command("panel:task").Daily().SkipIfStillRunning(),
|
||||
facades.Schedule().Command("panel:task").DailyAt("03:30").SkipIfStillRunning(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type AssetController struct {
|
||||
|
||||
@@ -4,12 +4,12 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
requests "panel/app/http/requests/cert"
|
||||
commonrequests "panel/app/http/requests/common"
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"panel/pkg/acme"
|
||||
requests "github.com/TheTNB/panel/app/http/requests/cert"
|
||||
commonrequests "github.com/TheTNB/panel/app/http/requests/common"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/TheTNB/panel/pkg/acme"
|
||||
)
|
||||
|
||||
type CertController struct {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
@@ -13,11 +14,10 @@ import (
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
"panel/pkg/tools"
|
||||
|
||||
commonrequests "panel/app/http/requests/common"
|
||||
requests "panel/app/http/requests/container"
|
||||
"panel/internal/services"
|
||||
commonrequests "github.com/TheTNB/panel/app/http/requests/common"
|
||||
requests "github.com/TheTNB/panel/app/http/requests/container"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
)
|
||||
|
||||
type ContainerController struct {
|
||||
@@ -63,11 +63,8 @@ func (r *ContainerController) ContainerList(ctx http.Context) http.Response {
|
||||
endIndex = len(containers)
|
||||
}
|
||||
paged := containers[startIndex:endIndex]
|
||||
if paged == nil {
|
||||
paged = []types.Container{}
|
||||
}
|
||||
|
||||
var items []any
|
||||
items := make([]any, 0)
|
||||
for _, item := range paged {
|
||||
var name string
|
||||
if len(item.Names) > 0 {
|
||||
|
||||
@@ -9,10 +9,10 @@ import (
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type CronController struct {
|
||||
|
||||
@@ -8,12 +8,12 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
commonrequests "github.com/TheTNB/panel/app/http/requests/common"
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
commonrequests "panel/app/http/requests/common"
|
||||
|
||||
requests "panel/app/http/requests/file"
|
||||
"panel/pkg/tools"
|
||||
requests "github.com/TheTNB/panel/app/http/requests/file"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type FileController struct {
|
||||
|
||||
@@ -9,10 +9,11 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type MenuItem struct {
|
||||
@@ -34,10 +35,11 @@ func NewInfoController() *InfoController {
|
||||
}
|
||||
}
|
||||
|
||||
// Name 获取面板名称
|
||||
func (r *InfoController) Name(ctx http.Context) http.Response {
|
||||
// Panel 获取面板信息
|
||||
func (r *InfoController) Panel(ctx http.Context) http.Response {
|
||||
return Success(ctx, http.Json{
|
||||
"name": r.setting.Get(models.SettingKeyName),
|
||||
"name": r.setting.Get(models.SettingKeyName),
|
||||
"language": facades.Config().GetString("app.locale"),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -296,10 +298,13 @@ func (r *InfoController) UpdateInfo(ctx http.Context) http.Response {
|
||||
// Update 更新面板
|
||||
func (r *InfoController) Update(ctx http.Context) http.Response {
|
||||
var task models.Task
|
||||
err := facades.Orm().Query().Where("status", models.TaskStatusRunning).OrWhere("status", models.TaskStatusWaiting).FirstOrFail(&task)
|
||||
if err == nil {
|
||||
if err := facades.Orm().Query().Where("status", models.TaskStatusRunning).OrWhere("status", models.TaskStatusWaiting).FirstOrFail(&task); err == nil {
|
||||
return Error(ctx, http.StatusInternalServerError, "当前有任务正在执行,禁止更新")
|
||||
}
|
||||
if _, err := facades.Orm().Query().Exec("PRAGMA wal_checkpoint(TRUNCATE)"); err != nil {
|
||||
types.Status = types.StatusFailed
|
||||
return Error(ctx, http.StatusInternalServerError, fmt.Sprintf("面板数据库异常,已终止操作:%s", err.Error()))
|
||||
}
|
||||
|
||||
panel, err := tools.GetLatestPanelVersion()
|
||||
if err != nil {
|
||||
@@ -309,16 +314,16 @@ func (r *InfoController) Update(ctx http.Context) http.Response {
|
||||
return Error(ctx, http.StatusInternalServerError, "获取最新版本失败")
|
||||
}
|
||||
|
||||
internal.Status = internal.StatusUpgrade
|
||||
types.Status = types.StatusUpgrade
|
||||
if err = tools.UpdatePanel(panel); err != nil {
|
||||
internal.Status = internal.StatusFailed
|
||||
types.Status = types.StatusFailed
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "基础信息").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Info("更新面板失败")
|
||||
return Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
internal.Status = internal.StatusNormal
|
||||
types.Status = types.StatusNormal
|
||||
tools.RestartPanel()
|
||||
return Success(ctx, nil)
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
)
|
||||
|
||||
type MonitorController struct {
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
)
|
||||
|
||||
type PluginController struct {
|
||||
|
||||
@@ -8,12 +8,12 @@ import (
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"panel/app/http/controllers"
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"panel/pkg/tools"
|
||||
"panel/types"
|
||||
"github.com/TheTNB/panel/app/http/controllers"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type Fail2banController struct {
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
|
||||
"github.com/TheTNB/panel/app/http/controllers"
|
||||
requests "github.com/TheTNB/panel/app/http/requests/plugins/frp"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type FrpController struct {
|
||||
}
|
||||
|
||||
func NewFrpController() *FrpController {
|
||||
return &FrpController{}
|
||||
}
|
||||
|
||||
// Status
|
||||
//
|
||||
// @Summary 服务状态
|
||||
// @Description 获取 Frp 服务状态
|
||||
// @Tags 插件-Frp
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Success 200 {object} controllers.SuccessResponse
|
||||
// @Router /plugins/frp/status [get]
|
||||
func (r *FrpController) Status(ctx http.Context) http.Response {
|
||||
frps, err := tools.ServiceStatus("frps")
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取 frps 服务运行状态失败")
|
||||
}
|
||||
frpc, err := tools.ServiceStatus("frpc")
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取 frpc 服务运行状态失败")
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, http.Json{
|
||||
"frps": frps,
|
||||
"frpc": frpc,
|
||||
})
|
||||
}
|
||||
|
||||
// IsEnabled
|
||||
//
|
||||
// @Summary 是否启用服务
|
||||
// @Description 获取是否启用 Frp 服务
|
||||
// @Tags 插件-Frp
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Success 200 {object} controllers.SuccessResponse
|
||||
// @Router /plugins/frp/isEnabled [get]
|
||||
func (r *FrpController) IsEnabled(ctx http.Context) http.Response {
|
||||
frps, err := tools.ServiceIsEnabled("frps")
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取 frps 服务启用状态失败")
|
||||
}
|
||||
frpc, err := tools.ServiceIsEnabled("frpc")
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, "获取 frpc 服务启用状态失败")
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, http.Json{
|
||||
"frps": frps,
|
||||
"frpc": frpc,
|
||||
})
|
||||
}
|
||||
|
||||
// Enable
|
||||
//
|
||||
// @Summary 启用服务
|
||||
// @Description 启用 Frp 服务
|
||||
// @Tags 插件-Frp
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.Service true "request"
|
||||
// @Success 200 {object} controllers.SuccessResponse
|
||||
// @Router /plugins/frp/enable [post]
|
||||
func (r *FrpController) Enable(ctx http.Context) http.Response {
|
||||
var serviceRequest requests.Service
|
||||
sanitize := controllers.Sanitize(ctx, &serviceRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
if err := tools.ServiceEnable(serviceRequest.Service); err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, fmt.Sprintf("启用 %s 服务失败", serviceRequest.Service))
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, nil)
|
||||
}
|
||||
|
||||
// Disable
|
||||
//
|
||||
// @Summary 禁用服务
|
||||
// @Description 禁用 Frp 服务
|
||||
// @Tags 插件-Frp
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.Service true "request"
|
||||
// @Success 200 {object} controllers.SuccessResponse
|
||||
// @Router /plugins/frp/disable [post]
|
||||
func (r *FrpController) Disable(ctx http.Context) http.Response {
|
||||
var serviceRequest requests.Service
|
||||
sanitize := controllers.Sanitize(ctx, &serviceRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
if err := tools.ServiceDisable(serviceRequest.Service); err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, fmt.Sprintf("禁用 %s 服务失败", serviceRequest.Service))
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, nil)
|
||||
}
|
||||
|
||||
// Restart
|
||||
//
|
||||
// @Summary 重启服务
|
||||
// @Description 重启 Frp 服务
|
||||
// @Tags 插件-Frp
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @param data body requests.Service true "request"
|
||||
// @Success 200 {object} controllers.SuccessResponse
|
||||
// @Router /plugins/frp/restart [post]
|
||||
func (r *FrpController) Restart(ctx http.Context) http.Response {
|
||||
var serviceRequest requests.Service
|
||||
sanitize := controllers.Sanitize(ctx, &serviceRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
if err := tools.ServiceRestart(serviceRequest.Service); err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, fmt.Sprintf("重启 %s 服务失败", serviceRequest.Service))
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, nil)
|
||||
}
|
||||
|
||||
// Start
|
||||
//
|
||||
// @Summary 启动服务
|
||||
// @Description 启动 Frp 服务
|
||||
// @Tags 插件-Frp
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.Service true "request"
|
||||
// @Success 200 {object} controllers.SuccessResponse
|
||||
// @Router /plugins/frp/start [post]
|
||||
func (r *FrpController) Start(ctx http.Context) http.Response {
|
||||
var serviceRequest requests.Service
|
||||
sanitize := controllers.Sanitize(ctx, &serviceRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
if err := tools.ServiceStart(serviceRequest.Service); err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, fmt.Sprintf("启动 %s 服务失败", serviceRequest.Service))
|
||||
}
|
||||
|
||||
status, err := tools.ServiceStatus(serviceRequest.Service)
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, fmt.Sprintf("获取 %s 服务运行状态失败", serviceRequest.Service))
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, status)
|
||||
}
|
||||
|
||||
// Stop
|
||||
//
|
||||
// @Summary 停止服务
|
||||
// @Description 停止 Frp 服务
|
||||
// @Tags 插件-Frp
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.Service true "request"
|
||||
// @Success 200 {object} controllers.SuccessResponse
|
||||
// @Router /plugins/frp/stop [post]
|
||||
func (r *FrpController) Stop(ctx http.Context) http.Response {
|
||||
var serviceRequest requests.Service
|
||||
sanitize := controllers.Sanitize(ctx, &serviceRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
if err := tools.ServiceStop(serviceRequest.Service); err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, fmt.Sprintf("停止 %s 服务失败", serviceRequest.Service))
|
||||
}
|
||||
|
||||
status, err := tools.ServiceStatus(serviceRequest.Service)
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, fmt.Sprintf("获取 %s 服务运行状态失败", serviceRequest.Service))
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, !status)
|
||||
}
|
||||
|
||||
// GetConfig
|
||||
//
|
||||
// @Summary 获取配置
|
||||
// @Description 获取 Frp 配置
|
||||
// @Tags 插件-Frp
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param service query string false "服务"
|
||||
// @Success 200 {object} controllers.SuccessResponse
|
||||
// @Router /plugins/frp/config [get]
|
||||
func (r *FrpController) GetConfig(ctx http.Context) http.Response {
|
||||
var serviceRequest requests.Service
|
||||
sanitize := controllers.Sanitize(ctx, &serviceRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
config, err := tools.Read(fmt.Sprintf("/www/server/frp/%s.toml", serviceRequest.Service))
|
||||
if err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, config)
|
||||
}
|
||||
|
||||
// UpdateConfig
|
||||
//
|
||||
// @Summary 更新配置
|
||||
// @Description 更新 Frp 配置
|
||||
// @Tags 插件-Frp
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data body requests.UpdateConfig true "request"
|
||||
// @Success 200 {object} controllers.SuccessResponse
|
||||
// @Router /plugins/frp/config [post]
|
||||
func (r *FrpController) UpdateConfig(ctx http.Context) http.Response {
|
||||
var updateRequest requests.UpdateConfig
|
||||
sanitize := controllers.Sanitize(ctx, &updateRequest)
|
||||
if sanitize != nil {
|
||||
return sanitize
|
||||
}
|
||||
|
||||
if err := tools.Write(fmt.Sprintf("/www/server/frp/%s.toml", updateRequest.Service), updateRequest.Config, 0644); err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
if err := tools.ServiceRestart(updateRequest.Service); err != nil {
|
||||
return controllers.Error(ctx, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, nil)
|
||||
}
|
||||
@@ -8,11 +8,12 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"panel/app/http/controllers"
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/app/http/controllers"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type MySQLController struct {
|
||||
@@ -377,7 +378,7 @@ func (r *MySQLController) BackupList(ctx http.Context) http.Response {
|
||||
if startIndex > len(backupList) {
|
||||
return controllers.Success(ctx, http.Json{
|
||||
"total": 0,
|
||||
"items": []internal.BackupFile{},
|
||||
"items": []types.BackupFile{},
|
||||
})
|
||||
}
|
||||
if endIndex > len(backupList) {
|
||||
@@ -385,7 +386,7 @@ func (r *MySQLController) BackupList(ctx http.Context) http.Response {
|
||||
}
|
||||
pagedBackupList := backupList[startIndex:endIndex]
|
||||
if pagedBackupList == nil {
|
||||
pagedBackupList = []internal.BackupFile{}
|
||||
pagedBackupList = []types.BackupFile{}
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, http.Json{
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"panel/app/http/controllers"
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/app/http/controllers"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type OpenRestyController struct {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"github.com/TheTNB/panel/app/http/controllers"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"panel/app/http/controllers"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
)
|
||||
|
||||
type PHPController struct {
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"panel/app/http/controllers"
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/app/http/controllers"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type PhpMyAdminController struct {
|
||||
|
||||
@@ -6,12 +6,12 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
|
||||
"panel/app/http/controllers"
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"panel/pkg/tools"
|
||||
"panel/types"
|
||||
"github.com/TheTNB/panel/app/http/controllers"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type Postgresql15Controller struct {
|
||||
@@ -321,7 +321,7 @@ func (r *Postgresql15Controller) BackupList(ctx http.Context) http.Response {
|
||||
if startIndex > len(backupList) {
|
||||
return controllers.Success(ctx, http.Json{
|
||||
"total": 0,
|
||||
"items": []internal.BackupFile{},
|
||||
"items": []types.BackupFile{},
|
||||
})
|
||||
}
|
||||
if endIndex > len(backupList) {
|
||||
@@ -329,7 +329,7 @@ func (r *Postgresql15Controller) BackupList(ctx http.Context) http.Response {
|
||||
}
|
||||
pagedBackupList := backupList[startIndex:endIndex]
|
||||
if pagedBackupList == nil {
|
||||
pagedBackupList = []internal.BackupFile{}
|
||||
pagedBackupList = []types.BackupFile{}
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, http.Json{
|
||||
|
||||
@@ -6,12 +6,12 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
|
||||
"panel/app/http/controllers"
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"panel/pkg/tools"
|
||||
"panel/types"
|
||||
"github.com/TheTNB/panel/app/http/controllers"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type Postgresql16Controller struct {
|
||||
@@ -321,7 +321,7 @@ func (r *Postgresql16Controller) BackupList(ctx http.Context) http.Response {
|
||||
if startIndex > len(backupList) {
|
||||
return controllers.Success(ctx, http.Json{
|
||||
"total": 0,
|
||||
"items": []internal.BackupFile{},
|
||||
"items": []types.BackupFile{},
|
||||
})
|
||||
}
|
||||
if endIndex > len(backupList) {
|
||||
@@ -329,7 +329,7 @@ func (r *Postgresql16Controller) BackupList(ctx http.Context) http.Response {
|
||||
}
|
||||
pagedBackupList := backupList[startIndex:endIndex]
|
||||
if pagedBackupList == nil {
|
||||
pagedBackupList = []internal.BackupFile{}
|
||||
pagedBackupList = []types.BackupFile{}
|
||||
}
|
||||
|
||||
return controllers.Success(ctx, http.Json{
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"panel/app/http/controllers"
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/app/http/controllers"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type PureFtpdController struct {
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
|
||||
"panel/app/http/controllers"
|
||||
"panel/pkg/tools"
|
||||
"panel/types"
|
||||
"github.com/TheTNB/panel/app/http/controllers"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type RedisController struct {
|
||||
|
||||
@@ -6,23 +6,18 @@ import (
|
||||
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
|
||||
"panel/app/http/controllers"
|
||||
commonrequests "panel/app/http/requests/common"
|
||||
requests "panel/app/http/requests/plugins/rsync"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"panel/pkg/tools"
|
||||
"panel/types"
|
||||
"github.com/TheTNB/panel/app/http/controllers"
|
||||
commonrequests "github.com/TheTNB/panel/app/http/requests/common"
|
||||
requests "github.com/TheTNB/panel/app/http/requests/plugins/rsync"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type RsyncController struct {
|
||||
setting internal.Setting
|
||||
}
|
||||
|
||||
func NewRsyncController() *RsyncController {
|
||||
return &RsyncController{
|
||||
setting: services.NewSettingImpl(),
|
||||
}
|
||||
return &RsyncController{}
|
||||
}
|
||||
|
||||
// Status
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"github.com/goravel/framework/support/json"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"panel/app/http/controllers"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"panel/pkg/tools"
|
||||
"panel/types"
|
||||
"github.com/TheTNB/panel/app/http/controllers"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type S3fsController struct {
|
||||
|
||||
@@ -4,10 +4,10 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"panel/pkg/tools"
|
||||
|
||||
"panel/app/http/controllers"
|
||||
"github.com/TheTNB/panel/app/http/controllers"
|
||||
)
|
||||
|
||||
type SupervisorController struct {
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"panel/app/http/controllers"
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/app/http/controllers"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type ToolBoxController struct {
|
||||
|
||||
@@ -4,11 +4,11 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
commonrequests "github.com/TheTNB/panel/app/http/requests/common"
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/spf13/cast"
|
||||
commonrequests "panel/app/http/requests/common"
|
||||
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type SafeController struct {
|
||||
@@ -302,7 +302,7 @@ func (r *SafeController) GetSshPort(ctx http.Context) http.Response {
|
||||
return Error(ctx, http.StatusInternalServerError, out)
|
||||
}
|
||||
|
||||
return Success(ctx, out)
|
||||
return Success(ctx, cast.ToInt(out))
|
||||
}
|
||||
|
||||
// SetSshPort 设置 SSH 端口
|
||||
|
||||
@@ -5,11 +5,11 @@ import (
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
requests "panel/app/http/requests/setting"
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"panel/pkg/tools"
|
||||
requests "github.com/TheTNB/panel/app/http/requests/setting"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type SettingController struct {
|
||||
@@ -60,6 +60,7 @@ func (r *SettingController) List(ctx http.Context) http.Response {
|
||||
|
||||
return Success(ctx, http.Json{
|
||||
"name": r.setting.Get(models.SettingKeyName),
|
||||
"language": facades.Config().GetString("app.locale"),
|
||||
"entrance": facades.Config().GetString("http.entrance"),
|
||||
"ssl": facades.Config().GetBool("panel.ssl"),
|
||||
"website_path": r.setting.Get(models.SettingKeyWebsitePath),
|
||||
@@ -189,7 +190,6 @@ func (r *SettingController) Update(ctx http.Context) http.Response {
|
||||
}).Info("获取面板入口失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
|
||||
entrance := cast.ToString(updateRequest.Entrance)
|
||||
if oldEntrance != entrance {
|
||||
if out, err := tools.Exec("sed -i 's!APP_ENTRANCE=" + oldEntrance + "!APP_ENTRANCE=" + entrance + "!g' /www/panel/panel.conf"); err != nil {
|
||||
@@ -197,6 +197,19 @@ func (r *SettingController) Update(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
oldLanguage, err := tools.Exec(`cat /www/panel/panel.conf | grep APP_LOCALE | awk -F '=' '{print $2}' | tr -d '\n'`)
|
||||
if err != nil {
|
||||
facades.Log().Request(ctx.Request()).Tags("面板", "面板设置").With(map[string]any{
|
||||
"error": err.Error(),
|
||||
}).Info("获取面板语言失败")
|
||||
return ErrorSystem(ctx)
|
||||
}
|
||||
if oldLanguage != updateRequest.Language {
|
||||
if out, err := tools.Exec("sed -i 's/APP_LOCALE=" + oldLanguage + "/APP_LOCALE=" + updateRequest.Language + "/g' /www/panel/panel.conf"); err != nil {
|
||||
return Error(ctx, http.StatusInternalServerError, out)
|
||||
}
|
||||
}
|
||||
|
||||
if updateRequest.SSL {
|
||||
if out, err := tools.Exec("sed -i 's/APP_SSL=false/APP_SSL=true/g' /www/panel/panel.conf"); err != nil {
|
||||
return Error(ctx, http.StatusInternalServerError, out)
|
||||
@@ -207,7 +220,7 @@ func (r *SettingController) Update(ctx http.Context) http.Response {
|
||||
}
|
||||
}
|
||||
|
||||
if oldPort != port || oldEntrance != entrance || updateRequest.SSL != facades.Config().GetBool("panel.ssl") {
|
||||
if oldPort != port || oldEntrance != entrance || oldLanguage != updateRequest.Language || updateRequest.SSL != facades.Config().GetBool("panel.ssl") {
|
||||
tools.RestartPanel()
|
||||
}
|
||||
|
||||
|
||||
@@ -12,10 +12,10 @@ import (
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"panel/pkg/ssh"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/TheTNB/panel/pkg/ssh"
|
||||
)
|
||||
|
||||
type SshController struct {
|
||||
@@ -103,7 +103,7 @@ func (r *SshController) Session(ctx http.Context) http.Response {
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
config := ssh.SSHClientConfigPassword(
|
||||
config := ssh.ClientConfigPassword(
|
||||
r.setting.Get(models.SettingKeySshHost)+":"+r.setting.Get(models.SettingKeySshPort),
|
||||
r.setting.Get(models.SettingKeySshUser),
|
||||
r.setting.Get(models.SettingKeySshPassword),
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/swaggo/http-swagger/v2"
|
||||
|
||||
_ "panel/docs"
|
||||
_ "github.com/TheTNB/panel/docs"
|
||||
)
|
||||
|
||||
type SwaggerController struct {
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type TaskController struct {
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/http/requests/user"
|
||||
"panel/app/models"
|
||||
"github.com/TheTNB/panel/app/http/requests/user"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
)
|
||||
|
||||
type UserController struct {
|
||||
|
||||
@@ -8,12 +8,13 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
commonrequests "panel/app/http/requests/common"
|
||||
requests "panel/app/http/requests/website"
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/internal/services"
|
||||
"panel/pkg/tools"
|
||||
commonrequests "github.com/TheTNB/panel/app/http/requests/common"
|
||||
requests "github.com/TheTNB/panel/app/http/requests/website"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type WebsiteController struct {
|
||||
@@ -83,7 +84,7 @@ func (r *WebsiteController) Add(ctx http.Context) http.Response {
|
||||
addRequest.Path = r.setting.Get(models.SettingKeyWebsitePath) + "/" + addRequest.Name
|
||||
}
|
||||
|
||||
website := internal.PanelWebsite{
|
||||
website := types.Website{
|
||||
Name: addRequest.Name,
|
||||
Status: true,
|
||||
Domains: addRequest.Domains,
|
||||
@@ -205,7 +206,7 @@ func (r *WebsiteController) SaveDefaultConfig(ctx http.Context) http.Response {
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param id path int true "网站 ID"
|
||||
// @Success 200 {object} SuccessResponse{data=internal.PanelWebsite}
|
||||
// @Success 200 {object} SuccessResponse{data=types.Website}
|
||||
// @Router /panel/websites/{id}/config [get]
|
||||
func (r *WebsiteController) GetConfig(ctx http.Context) http.Response {
|
||||
var idRequest requests.ID
|
||||
@@ -328,7 +329,7 @@ func (r *WebsiteController) UpdateRemark(ctx http.Context) http.Response {
|
||||
// @Produce json
|
||||
// @Security BearerToken
|
||||
// @Param data query commonrequests.Paginate true "request"
|
||||
// @Success 200 {object} SuccessResponse{data=[]internal.BackupFile}
|
||||
// @Success 200 {object} SuccessResponse{data=[]types.BackupFile}
|
||||
// @Router /panel/website/backupList [get]
|
||||
func (r *WebsiteController) BackupList(ctx http.Context) http.Response {
|
||||
var paginateRequest commonrequests.Paginate
|
||||
@@ -350,7 +351,7 @@ func (r *WebsiteController) BackupList(ctx http.Context) http.Response {
|
||||
if startIndex > len(backupList) {
|
||||
return Success(ctx, http.Json{
|
||||
"total": 0,
|
||||
"items": []internal.BackupFile{},
|
||||
"items": []types.BackupFile{},
|
||||
})
|
||||
}
|
||||
if endIndex > len(backupList) {
|
||||
@@ -358,7 +359,7 @@ func (r *WebsiteController) BackupList(ctx http.Context) http.Response {
|
||||
}
|
||||
pagedBackupList := backupList[startIndex:endIndex]
|
||||
if pagedBackupList == nil {
|
||||
pagedBackupList = []internal.BackupFile{}
|
||||
pagedBackupList = []types.BackupFile{}
|
||||
}
|
||||
|
||||
return Success(ctx, http.Json{
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ package http
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
|
||||
"panel/app/http/middleware"
|
||||
"github.com/TheTNB/panel/app/http/middleware"
|
||||
)
|
||||
|
||||
type Kernel struct {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/goravel/framework/contracts/translation"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/internal/services"
|
||||
"github.com/TheTNB/panel/internal/services"
|
||||
)
|
||||
|
||||
// MustInstall 确保已安装插件
|
||||
|
||||
@@ -4,30 +4,30 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/internal"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
// Status 检查程序状态
|
||||
func Status() http.Middleware {
|
||||
return func(ctx http.Context) {
|
||||
translate := facades.Lang(ctx)
|
||||
switch internal.Status {
|
||||
case internal.StatusUpgrade:
|
||||
switch types.Status {
|
||||
case types.StatusUpgrade:
|
||||
ctx.Request().AbortWithStatusJson(http.StatusServiceUnavailable, http.Json{
|
||||
"message": translate.Get("status.upgrade"),
|
||||
})
|
||||
return
|
||||
case internal.StatusMaintain:
|
||||
case types.StatusMaintain:
|
||||
ctx.Request().AbortWithStatusJson(http.StatusServiceUnavailable, http.Json{
|
||||
"message": translate.Get("status.maintain"),
|
||||
})
|
||||
return
|
||||
case internal.StatusClosed:
|
||||
case types.StatusClosed:
|
||||
ctx.Request().AbortWithStatusJson(http.StatusForbidden, http.Json{
|
||||
"message": translate.Get("status.closed"),
|
||||
})
|
||||
return
|
||||
case internal.StatusFailed:
|
||||
case types.StatusFailed:
|
||||
ctx.Request().AbortWithStatusJson(http.StatusInternalServerError, http.Json{
|
||||
"message": translate.Get("status.failed"),
|
||||
})
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
|
||||
"panel/pkg/acme"
|
||||
"github.com/TheTNB/panel/pkg/acme"
|
||||
)
|
||||
|
||||
type DNSStore struct {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
|
||||
"panel/pkg/acme"
|
||||
"github.com/TheTNB/panel/pkg/acme"
|
||||
)
|
||||
|
||||
type DNSUpdate struct {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
|
||||
"panel/types"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type ContainerCreate struct {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
|
||||
"panel/types"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type ContainerUpdate struct {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
|
||||
"panel/types"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type NetworkCreate struct {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
|
||||
"panel/types"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type VolumeCreate struct {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
Service string `form:"service" json:"service"`
|
||||
}
|
||||
|
||||
func (r *Service) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Service) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"service": "required|string|in:frps,frpc",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Service) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *Service) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *Service) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package requests
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
)
|
||||
|
||||
type UpdateConfig struct {
|
||||
Service string `form:"service" json:"service"`
|
||||
Config string `form:"config" json:"config"`
|
||||
}
|
||||
|
||||
func (r *UpdateConfig) Authorize(ctx http.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *UpdateConfig) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"service": "required|string|in:frps,frpc",
|
||||
"config": "required|string",
|
||||
}
|
||||
}
|
||||
|
||||
func (r *UpdateConfig) Messages(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *UpdateConfig) Attributes(ctx http.Context) map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (r *UpdateConfig) PrepareForValidation(ctx http.Context, data validation.Data) error {
|
||||
return nil
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
type Update struct {
|
||||
Name string `form:"name" json:"name"`
|
||||
Language string `form:"language" json:"language"`
|
||||
Port uint `form:"port" json:"port" filter:"uint"`
|
||||
BackupPath string `form:"backup_path" json:"backup_path"`
|
||||
WebsitePath string `form:"website_path" json:"website_path"`
|
||||
@@ -24,6 +25,7 @@ func (r *Update) Authorize(ctx http.Context) error {
|
||||
func (r *Update) Rules(ctx http.Context) map[string]string {
|
||||
return map[string]string{
|
||||
"name": "required|string:2,20",
|
||||
"language": "required|in:zh_CN,en",
|
||||
"port": "required|int:1000,65535",
|
||||
"backup_path": "required|string:2,255",
|
||||
"website_path": "required|string:2,255",
|
||||
|
||||
+33
-37
@@ -1,12 +1,10 @@
|
||||
package jobs
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/models"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
)
|
||||
|
||||
// ProcessTask 处理面板任务
|
||||
@@ -22,63 +20,61 @@ func (receiver *ProcessTask) Signature() string {
|
||||
func (receiver *ProcessTask) Handle(args ...any) error {
|
||||
taskID, ok := args[0].(uint)
|
||||
if !ok {
|
||||
facades.Log().Info("[面板][ProcessTask] 任务ID参数错误")
|
||||
facades.Log().Tags("面板", "异步任务").With(map[string]any{
|
||||
"args": args,
|
||||
}).Infof("参数错误")
|
||||
return nil
|
||||
}
|
||||
|
||||
for {
|
||||
if !haveRunningTask() {
|
||||
break
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
|
||||
var task models.Task
|
||||
if err := facades.Orm().Query().Where("id = ?", taskID).Get(&task); err != nil {
|
||||
facades.Log().Infof("[面板][ProcessTask] 获取任务%d失败: %s", taskID, err.Error())
|
||||
facades.Log().Tags("面板", "异步任务").With(map[string]any{
|
||||
"task_id": taskID,
|
||||
"error": err.Error(),
|
||||
}).Infof("获取任务失败")
|
||||
return nil
|
||||
}
|
||||
|
||||
task.Status = models.TaskStatusRunning
|
||||
if err := facades.Orm().Query().Save(&task); err != nil {
|
||||
facades.Log().Infof("[面板][ProcessTask] 更新任务%d失败: %s", taskID, err.Error())
|
||||
facades.Log().Tags("面板", "异步任务").With(map[string]any{
|
||||
"task_id": taskID,
|
||||
"error": err.Error(),
|
||||
}).Infof("更新任务失败")
|
||||
return nil
|
||||
}
|
||||
|
||||
facades.Log().Infof("[面板][ProcessTask] 开始执行任务%d", taskID)
|
||||
cmd := exec.Command("bash", "-c", task.Shell)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
facades.Log().Tags("面板", "异步任务").With(map[string]any{
|
||||
"task_id": taskID,
|
||||
}).Infof("开始执行任务")
|
||||
|
||||
if _, err := tools.Exec(task.Shell); err != nil {
|
||||
task.Status = models.TaskStatusFailed
|
||||
if err := facades.Orm().Query().Save(&task); err != nil {
|
||||
facades.Log().Infof("[面板][ProcessTask] 更新任务%d失败: %s", taskID, err.Error())
|
||||
facades.Log().Tags("面板", "异步任务").With(map[string]any{
|
||||
"task_id": taskID,
|
||||
"error": err.Error(),
|
||||
}).Infof("更新任务失败")
|
||||
return nil
|
||||
}
|
||||
facades.Log().Infof("[面板][ProcessTask] 任务%d执行失败: %s", taskID, err.Error())
|
||||
facades.Log().Tags("面板", "异步任务").With(map[string]any{
|
||||
"task_id": taskID,
|
||||
"error": err.Error(),
|
||||
}).Infof("执行任务失败")
|
||||
return nil
|
||||
}
|
||||
|
||||
task.Status = models.TaskStatusSuccess
|
||||
if err := facades.Orm().Query().Save(&task); err != nil {
|
||||
facades.Log().Infof("[面板][ProcessTask] 更新任务%d失败: %s", taskID, err.Error())
|
||||
facades.Log().Tags("面板", "异步任务").With(map[string]any{
|
||||
"task_id": taskID,
|
||||
"error": err.Error(),
|
||||
}).Infof("更新任务失败")
|
||||
return nil
|
||||
}
|
||||
|
||||
facades.Log().Infof("[面板][ProcessTask] 任务%d执行成功", taskID)
|
||||
facades.Log().Tags("面板", "异步任务").With(map[string]any{
|
||||
"task_id": taskID,
|
||||
}).Infof("执行任务成功")
|
||||
return nil
|
||||
}
|
||||
|
||||
// haveRunningTask 是否有任务正在执行
|
||||
func haveRunningTask() bool {
|
||||
var task models.Task
|
||||
if err := facades.Orm().Query().Where("status = ?", models.TaskStatusRunning).Get(&task); err != nil {
|
||||
facades.Log().Info("[面板][ProcessTask] 获取任务失败: " + err.Error())
|
||||
return true
|
||||
}
|
||||
|
||||
if task.ID != 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package models
|
||||
import (
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
|
||||
"panel/pkg/acme"
|
||||
"github.com/TheTNB/panel/pkg/acme"
|
||||
)
|
||||
|
||||
type CertDNS struct {
|
||||
|
||||
@@ -3,7 +3,7 @@ package models
|
||||
import (
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type Monitor struct {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"github.com/goravel/framework/contracts/foundation"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/console"
|
||||
"github.com/TheTNB/panel/app/console"
|
||||
)
|
||||
|
||||
type ConsoleServiceProvider struct {
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"github.com/goravel/framework/contracts/foundation"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/database/seeders"
|
||||
"github.com/TheTNB/panel/database/seeders"
|
||||
)
|
||||
|
||||
type DatabaseServiceProvider struct {
|
||||
|
||||
@@ -5,14 +5,16 @@ import (
|
||||
"github.com/goravel/framework/contracts/queue"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/jobs"
|
||||
"github.com/TheTNB/panel/app/jobs"
|
||||
)
|
||||
|
||||
type QueueServiceProvider struct {
|
||||
}
|
||||
|
||||
func (receiver *QueueServiceProvider) Register(app foundation.Application) {
|
||||
facades.Queue().Register(receiver.Jobs())
|
||||
if err := facades.Queue().Register(receiver.Jobs()); err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (receiver *QueueServiceProvider) Boot(app foundation.Application) {
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"github.com/goravel/framework/contracts/foundation"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/http"
|
||||
"panel/routes"
|
||||
"github.com/TheTNB/panel/app/http"
|
||||
"github.com/TheTNB/panel/routes"
|
||||
)
|
||||
|
||||
type RouteServiceProvider struct {
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/rules"
|
||||
"github.com/TheTNB/panel/app/rules"
|
||||
)
|
||||
|
||||
type ValidationServiceProvider struct {
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
|
||||
"panel/pkg/captcha"
|
||||
"github.com/TheTNB/panel/pkg/captcha"
|
||||
)
|
||||
|
||||
type Captcha struct {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package rules
|
||||
|
||||
import (
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
"github.com/spf13/cast"
|
||||
"panel/pkg/tools"
|
||||
)
|
||||
|
||||
type PathExists struct {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package rules
|
||||
|
||||
import (
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/goravel/framework/contracts/validation"
|
||||
"github.com/spf13/cast"
|
||||
"panel/pkg/tools"
|
||||
)
|
||||
|
||||
type PathNotExists struct {
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import (
|
||||
"github.com/gookit/validate/locales/zhcn"
|
||||
"github.com/goravel/framework/foundation"
|
||||
|
||||
"panel/config"
|
||||
"github.com/TheTNB/panel/config"
|
||||
)
|
||||
|
||||
func Boot() {
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import (
|
||||
"github.com/goravel/framework/validation"
|
||||
"github.com/goravel/gin"
|
||||
|
||||
"panel/app/providers"
|
||||
"github.com/TheTNB/panel/app/providers"
|
||||
)
|
||||
|
||||
// Boot Start all init methods of the current folder to bootstrap all config.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ func init() {
|
||||
config := facades.Config()
|
||||
config.Add("panel", map[string]any{
|
||||
"name": "耗子 Linux 面板",
|
||||
"version": "v2.2.2",
|
||||
"version": "v2.2.4",
|
||||
"ssl": config.Env("APP_SSL", false),
|
||||
})
|
||||
}
|
||||
|
||||
+4
-4
@@ -8,15 +8,15 @@ func init() {
|
||||
config := facades.Config()
|
||||
config.Add("queue", map[string]any{
|
||||
// Default Queue Connection Name
|
||||
"default": "sync",
|
||||
"default": "async",
|
||||
|
||||
// Queue Connections
|
||||
//
|
||||
// Here you may configure the connection information for each server that is used by your application.
|
||||
// Drivers: "sync", "redis"
|
||||
// Drivers: "sync", "async", "custom"
|
||||
"connections": map[string]any{
|
||||
"sync": map[string]any{
|
||||
"driver": "sync",
|
||||
"async": map[string]any{
|
||||
"driver": "async",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
+411
-117
@@ -11,7 +11,7 @@ const docTemplate = `{
|
||||
"title": "{{.Title}}",
|
||||
"contact": {
|
||||
"name": "耗子科技",
|
||||
"email": "i@haozi.net"
|
||||
"email": "admin@haozi.net"
|
||||
},
|
||||
"license": {
|
||||
"name": "GNU Affero General Public License v3"
|
||||
@@ -1122,7 +1122,7 @@ const docTemplate = `{
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1190,7 +1190,7 @@ const docTemplate = `{
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1538,7 +1538,7 @@ const docTemplate = `{
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1599,7 +1599,7 @@ const docTemplate = `{
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1671,7 +1671,7 @@ const docTemplate = `{
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1741,7 +1741,7 @@ const docTemplate = `{
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1809,7 +1809,7 @@ const docTemplate = `{
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1845,7 +1845,7 @@ const docTemplate = `{
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -2046,7 +2046,7 @@ const docTemplate = `{
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -2693,7 +2693,7 @@ const docTemplate = `{
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_setting.Update"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_setting.Update"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -2819,7 +2819,7 @@ const docTemplate = `{
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/internal.BackupFile"
|
||||
"$ref": "#/definitions/types.BackupFile"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3136,7 +3136,7 @@ const docTemplate = `{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/internal.PanelWebsite"
|
||||
"$ref": "#/definitions/types.Website"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3412,6 +3412,278 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/frp/config": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "获取 Frp 配置",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "获取配置",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "服务",
|
||||
"name": "service",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "更新 Frp 配置",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "更新配置",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_plugins_frp.UpdateConfig"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/frp/disable": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "禁用 Frp 服务",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "禁用服务",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/requests.Service"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/frp/enable": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "启用 Frp 服务",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "启用服务",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/requests.Service"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/frp/restart": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "重启 Frp 服务",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "重启服务",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/requests.Service"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/frp/start": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "启动 Frp 服务",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "启动服务",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/requests.Service"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/frp/status": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "获取 Frp 服务状态",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "服务状态",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/frp/stop": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "停止 Frp 服务",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "停止服务",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/requests.Service"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/rsync/config": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -3457,7 +3729,7 @@ const docTemplate = `{
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/requests.UpdateConfig"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_plugins_rsync.UpdateConfig"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -3571,7 +3843,7 @@ const docTemplate = `{
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_plugins_rsync.Update"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_plugins_rsync.Update"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -3784,64 +4056,88 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"internal.BackupFile": {
|
||||
"github_com_TheTNB_panel_app_http_requests_container.ID": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"internal.PanelWebsite": {
|
||||
"github_com_TheTNB_panel_app_http_requests_plugins_frp.UpdateConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"db": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"db_name": {
|
||||
"config": {
|
||||
"type": "string"
|
||||
},
|
||||
"db_password": {
|
||||
"service": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_TheTNB_panel_app_http_requests_plugins_rsync.Update": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"auth_user": {
|
||||
"type": "string"
|
||||
},
|
||||
"db_type": {
|
||||
"comment": {
|
||||
"type": "string"
|
||||
},
|
||||
"db_user": {
|
||||
"hosts_allow": {
|
||||
"type": "string"
|
||||
},
|
||||
"domains": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"php": {
|
||||
"secret": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_TheTNB_panel_app_http_requests_plugins_rsync.UpdateConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"config": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_TheTNB_panel_app_http_requests_setting.Update": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"backup_path": {
|
||||
"type": "string"
|
||||
},
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"remark": {
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"entrance": {
|
||||
"type": "string"
|
||||
},
|
||||
"language": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"port": {
|
||||
"type": "integer"
|
||||
},
|
||||
"ssl": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"status": {
|
||||
"type": "boolean"
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"website_path": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3999,69 +4295,6 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel_app_http_requests_container.ID": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel_app_http_requests_plugins_rsync.Update": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"auth_user": {
|
||||
"type": "string"
|
||||
},
|
||||
"comment": {
|
||||
"type": "string"
|
||||
},
|
||||
"hosts_allow": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"secret": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel_app_http_requests_setting.Update": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"backup_path": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"entrance": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"port": {
|
||||
"type": "integer"
|
||||
},
|
||||
"ssl": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"website_path": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requests.Add": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -4274,10 +4507,10 @@ const docTemplate = `{
|
||||
"requests.Copy": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"new": {
|
||||
"source": {
|
||||
"type": "string"
|
||||
},
|
||||
"old": {
|
||||
"target": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@@ -4562,6 +4795,14 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"requests.Service": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"service": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requests.UnArchive": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -4573,14 +4814,6 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"requests.UpdateConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"config": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requests.UserStore": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -4647,6 +4880,17 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"types.BackupFile": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"types.ContainerNetwork": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -4711,6 +4955,56 @@ const docTemplate = `{
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"types.Website": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"db": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"db_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"db_password": {
|
||||
"type": "string"
|
||||
},
|
||||
"db_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"db_user": {
|
||||
"type": "string"
|
||||
},
|
||||
"domains": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"php": {
|
||||
"type": "string"
|
||||
},
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"remark": {
|
||||
"type": "string"
|
||||
},
|
||||
"ssl": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"status": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
|
||||
+411
-117
@@ -5,7 +5,7 @@
|
||||
"title": "耗子 Linux 面板 API",
|
||||
"contact": {
|
||||
"name": "耗子科技",
|
||||
"email": "i@haozi.net"
|
||||
"email": "admin@haozi.net"
|
||||
},
|
||||
"license": {
|
||||
"name": "GNU Affero General Public License v3"
|
||||
@@ -1115,7 +1115,7 @@
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1183,7 +1183,7 @@
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1531,7 +1531,7 @@
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1592,7 +1592,7 @@
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1664,7 +1664,7 @@
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1734,7 +1734,7 @@
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1802,7 +1802,7 @@
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1838,7 +1838,7 @@
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -2039,7 +2039,7 @@
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_container.ID"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -2686,7 +2686,7 @@
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_setting.Update"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_setting.Update"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -2812,7 +2812,7 @@
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/internal.BackupFile"
|
||||
"$ref": "#/definitions/types.BackupFile"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3129,7 +3129,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/internal.PanelWebsite"
|
||||
"$ref": "#/definitions/types.Website"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3405,6 +3405,278 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/frp/config": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "获取 Frp 配置",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "获取配置",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "服务",
|
||||
"name": "service",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "更新 Frp 配置",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "更新配置",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_plugins_frp.UpdateConfig"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/frp/disable": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "禁用 Frp 服务",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "禁用服务",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/requests.Service"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/frp/enable": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "启用 Frp 服务",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "启用服务",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/requests.Service"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/frp/restart": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "重启 Frp 服务",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "重启服务",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/requests.Service"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/frp/start": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "启动 Frp 服务",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "启动服务",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/requests.Service"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/frp/status": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "获取 Frp 服务状态",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "服务状态",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/frp/stop": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"BearerToken": []
|
||||
}
|
||||
],
|
||||
"description": "停止 Frp 服务",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"插件-Frp"
|
||||
],
|
||||
"summary": "停止服务",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "data",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/requests.Service"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.SuccessResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/plugins/rsync/config": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -3450,7 +3722,7 @@
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/requests.UpdateConfig"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_plugins_rsync.UpdateConfig"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -3564,7 +3836,7 @@
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/panel_app_http_requests_plugins_rsync.Update"
|
||||
"$ref": "#/definitions/github_com_TheTNB_panel_app_http_requests_plugins_rsync.Update"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -3777,64 +4049,88 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"internal.BackupFile": {
|
||||
"github_com_TheTNB_panel_app_http_requests_container.ID": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"internal.PanelWebsite": {
|
||||
"github_com_TheTNB_panel_app_http_requests_plugins_frp.UpdateConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"db": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"db_name": {
|
||||
"config": {
|
||||
"type": "string"
|
||||
},
|
||||
"db_password": {
|
||||
"service": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_TheTNB_panel_app_http_requests_plugins_rsync.Update": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"auth_user": {
|
||||
"type": "string"
|
||||
},
|
||||
"db_type": {
|
||||
"comment": {
|
||||
"type": "string"
|
||||
},
|
||||
"db_user": {
|
||||
"hosts_allow": {
|
||||
"type": "string"
|
||||
},
|
||||
"domains": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"php": {
|
||||
"secret": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_TheTNB_panel_app_http_requests_plugins_rsync.UpdateConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"config": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_TheTNB_panel_app_http_requests_setting.Update": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"backup_path": {
|
||||
"type": "string"
|
||||
},
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"remark": {
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"entrance": {
|
||||
"type": "string"
|
||||
},
|
||||
"language": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"port": {
|
||||
"type": "integer"
|
||||
},
|
||||
"ssl": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"status": {
|
||||
"type": "boolean"
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"website_path": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3992,69 +4288,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel_app_http_requests_container.ID": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel_app_http_requests_plugins_rsync.Update": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"auth_user": {
|
||||
"type": "string"
|
||||
},
|
||||
"comment": {
|
||||
"type": "string"
|
||||
},
|
||||
"hosts_allow": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"secret": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel_app_http_requests_setting.Update": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"backup_path": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"entrance": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"port": {
|
||||
"type": "integer"
|
||||
},
|
||||
"ssl": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"website_path": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requests.Add": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -4267,10 +4500,10 @@
|
||||
"requests.Copy": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"new": {
|
||||
"source": {
|
||||
"type": "string"
|
||||
},
|
||||
"old": {
|
||||
"target": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@@ -4555,6 +4788,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"requests.Service": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"service": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requests.UnArchive": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -4566,14 +4807,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"requests.UpdateConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"config": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requests.UserStore": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -4640,6 +4873,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"types.BackupFile": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"types.ContainerNetwork": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -4704,6 +4948,56 @@
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"types.Website": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"db": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"db_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"db_password": {
|
||||
"type": "string"
|
||||
},
|
||||
"db_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"db_user": {
|
||||
"type": "string"
|
||||
},
|
||||
"domains": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"php": {
|
||||
"type": "string"
|
||||
},
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"remark": {
|
||||
"type": "string"
|
||||
},
|
||||
"ssl": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"status": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
|
||||
+266
-86
@@ -31,45 +31,60 @@ definitions:
|
||||
message:
|
||||
type: string
|
||||
type: object
|
||||
internal.BackupFile:
|
||||
github_com_TheTNB_panel_app_http_requests_container.ID:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
size:
|
||||
id:
|
||||
type: string
|
||||
type: object
|
||||
internal.PanelWebsite:
|
||||
github_com_TheTNB_panel_app_http_requests_plugins_frp.UpdateConfig:
|
||||
properties:
|
||||
db:
|
||||
type: boolean
|
||||
db_name:
|
||||
config:
|
||||
type: string
|
||||
db_password:
|
||||
service:
|
||||
type: string
|
||||
db_type:
|
||||
type: object
|
||||
github_com_TheTNB_panel_app_http_requests_plugins_rsync.Update:
|
||||
properties:
|
||||
auth_user:
|
||||
type: string
|
||||
db_user:
|
||||
comment:
|
||||
type: string
|
||||
hosts_allow:
|
||||
type: string
|
||||
domains:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
type: string
|
||||
path:
|
||||
type: string
|
||||
php:
|
||||
secret:
|
||||
type: string
|
||||
ports:
|
||||
items:
|
||||
type: integer
|
||||
type: array
|
||||
remark:
|
||||
type: object
|
||||
github_com_TheTNB_panel_app_http_requests_plugins_rsync.UpdateConfig:
|
||||
properties:
|
||||
config:
|
||||
type: string
|
||||
type: object
|
||||
github_com_TheTNB_panel_app_http_requests_setting.Update:
|
||||
properties:
|
||||
backup_path:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
entrance:
|
||||
type: string
|
||||
language:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
port:
|
||||
type: integer
|
||||
ssl:
|
||||
type: boolean
|
||||
status:
|
||||
type: boolean
|
||||
username:
|
||||
type: string
|
||||
website_path:
|
||||
type: string
|
||||
type: object
|
||||
models.Cert:
|
||||
properties:
|
||||
@@ -176,47 +191,6 @@ definitions:
|
||||
updated_at:
|
||||
type: string
|
||||
type: object
|
||||
panel_app_http_requests_container.ID:
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
type: object
|
||||
panel_app_http_requests_plugins_rsync.Update:
|
||||
properties:
|
||||
auth_user:
|
||||
type: string
|
||||
comment:
|
||||
type: string
|
||||
hosts_allow:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
path:
|
||||
type: string
|
||||
secret:
|
||||
type: string
|
||||
type: object
|
||||
panel_app_http_requests_setting.Update:
|
||||
properties:
|
||||
backup_path:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
entrance:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
port:
|
||||
type: integer
|
||||
ssl:
|
||||
type: boolean
|
||||
username:
|
||||
type: string
|
||||
website_path:
|
||||
type: string
|
||||
type: object
|
||||
requests.Add:
|
||||
properties:
|
||||
db:
|
||||
@@ -356,9 +330,9 @@ definitions:
|
||||
type: object
|
||||
requests.Copy:
|
||||
properties:
|
||||
new:
|
||||
source:
|
||||
type: string
|
||||
old:
|
||||
target:
|
||||
type: string
|
||||
type: object
|
||||
requests.Create:
|
||||
@@ -542,6 +516,11 @@ definitions:
|
||||
path:
|
||||
type: string
|
||||
type: object
|
||||
requests.Service:
|
||||
properties:
|
||||
service:
|
||||
type: string
|
||||
type: object
|
||||
requests.UnArchive:
|
||||
properties:
|
||||
file:
|
||||
@@ -549,11 +528,6 @@ definitions:
|
||||
path:
|
||||
type: string
|
||||
type: object
|
||||
requests.UpdateConfig:
|
||||
properties:
|
||||
config:
|
||||
type: string
|
||||
type: object
|
||||
requests.UserStore:
|
||||
properties:
|
||||
ca:
|
||||
@@ -597,6 +571,13 @@ definitions:
|
||||
$ref: '#/definitions/types.KV'
|
||||
type: array
|
||||
type: object
|
||||
types.BackupFile:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
size:
|
||||
type: string
|
||||
type: object
|
||||
types.ContainerNetwork:
|
||||
properties:
|
||||
enabled:
|
||||
@@ -639,9 +620,42 @@ definitions:
|
||||
value:
|
||||
type: string
|
||||
type: object
|
||||
types.Website:
|
||||
properties:
|
||||
db:
|
||||
type: boolean
|
||||
db_name:
|
||||
type: string
|
||||
db_password:
|
||||
type: string
|
||||
db_type:
|
||||
type: string
|
||||
db_user:
|
||||
type: string
|
||||
domains:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
name:
|
||||
type: string
|
||||
path:
|
||||
type: string
|
||||
php:
|
||||
type: string
|
||||
ports:
|
||||
items:
|
||||
type: integer
|
||||
type: array
|
||||
remark:
|
||||
type: string
|
||||
ssl:
|
||||
type: boolean
|
||||
status:
|
||||
type: boolean
|
||||
type: object
|
||||
info:
|
||||
contact:
|
||||
email: i@haozi.net
|
||||
email: admin@haozi.net
|
||||
name: 耗子科技
|
||||
description: 耗子 Linux 面板的 API 信息
|
||||
license:
|
||||
@@ -1311,7 +1325,7 @@ paths:
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/panel_app_http_requests_container.ID'
|
||||
$ref: '#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@@ -1352,7 +1366,7 @@ paths:
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/panel_app_http_requests_container.ID'
|
||||
$ref: '#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@@ -1562,7 +1576,7 @@ paths:
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/panel_app_http_requests_container.ID'
|
||||
$ref: '#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@@ -1599,7 +1613,7 @@ paths:
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/panel_app_http_requests_container.ID'
|
||||
$ref: '#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@@ -1643,7 +1657,7 @@ paths:
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/panel_app_http_requests_container.ID'
|
||||
$ref: '#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@@ -1686,7 +1700,7 @@ paths:
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/panel_app_http_requests_container.ID'
|
||||
$ref: '#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@@ -1727,7 +1741,7 @@ paths:
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/panel_app_http_requests_container.ID'
|
||||
$ref: '#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@@ -1749,7 +1763,7 @@ paths:
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/panel_app_http_requests_container.ID'
|
||||
$ref: '#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@@ -1870,7 +1884,7 @@ paths:
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/panel_app_http_requests_container.ID'
|
||||
$ref: '#/definitions/github_com_TheTNB_panel_app_http_requests_container.ID'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@@ -2269,7 +2283,7 @@ paths:
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/panel_app_http_requests_setting.Update'
|
||||
$ref: '#/definitions/github_com_TheTNB_panel_app_http_requests_setting.Update'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@@ -2348,7 +2362,7 @@ paths:
|
||||
- properties:
|
||||
data:
|
||||
items:
|
||||
$ref: '#/definitions/internal.BackupFile'
|
||||
$ref: '#/definitions/types.BackupFile'
|
||||
type: array
|
||||
type: object
|
||||
security:
|
||||
@@ -2539,7 +2553,7 @@ paths:
|
||||
- $ref: '#/definitions/controllers.SuccessResponse'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/internal.PanelWebsite'
|
||||
$ref: '#/definitions/types.Website'
|
||||
type: object
|
||||
security:
|
||||
- BearerToken: []
|
||||
@@ -2712,6 +2726,172 @@ paths:
|
||||
summary: 更新备注
|
||||
tags:
|
||||
- 网站管理
|
||||
/plugins/frp/config:
|
||||
get:
|
||||
description: 获取 Frp 配置
|
||||
parameters:
|
||||
- description: 服务
|
||||
in: query
|
||||
name: service
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 获取配置
|
||||
tags:
|
||||
- 插件-Frp
|
||||
post:
|
||||
description: 更新 Frp 配置
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/github_com_TheTNB_panel_app_http_requests_plugins_frp.UpdateConfig'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 更新配置
|
||||
tags:
|
||||
- 插件-Frp
|
||||
/plugins/frp/disable:
|
||||
post:
|
||||
description: 禁用 Frp 服务
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/requests.Service'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 禁用服务
|
||||
tags:
|
||||
- 插件-Frp
|
||||
/plugins/frp/enable:
|
||||
post:
|
||||
description: 启用 Frp 服务
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/requests.Service'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 启用服务
|
||||
tags:
|
||||
- 插件-Frp
|
||||
/plugins/frp/restart:
|
||||
post:
|
||||
description: 重启 Frp 服务
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/requests.Service'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 重启服务
|
||||
tags:
|
||||
- 插件-Frp
|
||||
/plugins/frp/start:
|
||||
post:
|
||||
description: 启动 Frp 服务
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/requests.Service'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 启动服务
|
||||
tags:
|
||||
- 插件-Frp
|
||||
/plugins/frp/status:
|
||||
get:
|
||||
description: 获取 Frp 服务状态
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 服务状态
|
||||
tags:
|
||||
- 插件-Frp
|
||||
/plugins/frp/stop:
|
||||
post:
|
||||
description: 停止 Frp 服务
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/requests.Service'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.SuccessResponse'
|
||||
security:
|
||||
- BearerToken: []
|
||||
summary: 停止服务
|
||||
tags:
|
||||
- 插件-Frp
|
||||
/plugins/rsync/config:
|
||||
get:
|
||||
description: 获取 Rsync 配置
|
||||
@@ -2735,7 +2915,7 @@ paths:
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/requests.UpdateConfig'
|
||||
$ref: '#/definitions/github_com_TheTNB_panel_app_http_requests_plugins_rsync.UpdateConfig'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@@ -2825,7 +3005,7 @@ paths:
|
||||
name: data
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/panel_app_http_requests_plugins_rsync.Update'
|
||||
$ref: '#/definitions/github_com_TheTNB_panel_app_http_requests_plugins_rsync.Update'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
module panel
|
||||
module github.com/TheTNB/panel
|
||||
|
||||
go 1.22
|
||||
|
||||
require (
|
||||
github.com/docker/docker v26.1.3+incompatible
|
||||
github.com/docker/docker v26.1.4+incompatible
|
||||
github.com/docker/go-connections v0.5.0
|
||||
github.com/go-resty/resty/v2 v2.13.1
|
||||
github.com/gookit/color v1.5.4
|
||||
github.com/gookit/validate v1.5.2
|
||||
github.com/goravel/framework v1.13.1-0.20240430025652-cf76911d0286
|
||||
github.com/goravel/framework v1.13.1-0.20240529174304-bddcb8bcc28a
|
||||
github.com/goravel/gin v1.1.6-0.20240426085159-718e4d6d5f4f
|
||||
github.com/gorilla/websocket v1.5.1
|
||||
github.com/libdns/alidns v1.0.3
|
||||
@@ -24,16 +23,14 @@ require (
|
||||
github.com/swaggo/http-swagger/v2 v2.0.2
|
||||
github.com/swaggo/swag v1.16.3
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/crypto v0.23.0
|
||||
golang.org/x/net v0.25.0
|
||||
golang.org/x/crypto v0.24.0
|
||||
golang.org/x/net v0.26.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.112.0 // indirect
|
||||
cloud.google.com/go/compute v1.24.0 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/iam v1.1.6 // indirect
|
||||
cloud.google.com/go/pubsub v1.36.1 // indirect
|
||||
atomicgo.dev/cursor v0.2.0 // indirect
|
||||
atomicgo.dev/keyboard v0.2.9 // indirect
|
||||
atomicgo.dev/schedule v0.1.0 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.2 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1 // indirect
|
||||
@@ -44,27 +41,37 @@ require (
|
||||
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/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae // indirect
|
||||
github.com/RichardKnop/machinery/v2 v2.0.13 // indirect
|
||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||
github.com/aws/aws-sdk-go v1.49.6 // indirect
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/bytedance/sonic v1.11.6 // indirect
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/catppuccin/go v0.2.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/charmbracelet/bubbles v0.18.0 // indirect
|
||||
github.com/charmbracelet/bubbletea v0.26.3 // indirect
|
||||
github.com/charmbracelet/huh v0.4.2 // indirect
|
||||
github.com/charmbracelet/huh/spinner v0.0.0-20240508140610-13957916abf0 // indirect
|
||||
github.com/charmbracelet/lipgloss v0.11.0 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.1.1 // indirect
|
||||
github.com/charmbracelet/x/exp/strings v0.0.0-20240524151031-ff83003bf67a // indirect
|
||||
github.com/charmbracelet/x/input v0.1.1 // indirect
|
||||
github.com/charmbracelet/x/term v0.1.1 // indirect
|
||||
github.com/charmbracelet/x/windows v0.1.2 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // 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/distribution/reference v0.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.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.22.0 // indirect
|
||||
@@ -79,7 +86,6 @@ require (
|
||||
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.5 // indirect
|
||||
github.com/go-redsync/redsync/v4 v4.8.1 // indirect
|
||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
@@ -90,16 +96,12 @@ require (
|
||||
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
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/gomodule/redigo v2.0.0+incompatible // indirect
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/google/wire v0.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/gookit/color v1.5.4 // indirect
|
||||
github.com/gookit/filter v1.2.1 // indirect
|
||||
github.com/gookit/goutil v0.6.15 // indirect
|
||||
github.com/goravel/file-rotatelogs/v2 v2.4.2 // indirect
|
||||
@@ -113,44 +115,49 @@ require (
|
||||
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // 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.17.7 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/lithammer/fuzzysearch v1.1.8 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/microsoft/go-mssqldb v1.6.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/montanaflynn/stats v0.7.0 // indirect
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/nrdcg/dnspod-go v0.4.0 // indirect
|
||||
github.com/nwaples/rardecode v1.1.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.16 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/rabbitmq/amqp091-go v1.9.0 // indirect
|
||||
github.com/redis/go-redis/v9 v9.5.1 // indirect
|
||||
github.com/pterm/pterm v0.12.79 // 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.7 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
github.com/rotisserie/eris v0.5.4 // indirect
|
||||
github.com/rs/cors v1.11.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/samber/do/v2 v2.0.0-beta.7 // indirect
|
||||
github.com/samber/go-type-to-string v1.7.0 // indirect
|
||||
github.com/savioxavier/termlink v1.3.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
@@ -160,7 +167,6 @@ require (
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/swaggo/files/v2 v2.0.0 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
@@ -168,43 +174,32 @@ require (
|
||||
github.com/ulikunitz/xz v0.5.11 // indirect
|
||||
github.com/unrolled/secure v1.14.0 // indirect
|
||||
github.com/urfave/cli/v2 v2.27.2 // 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
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||
go.mongodb.org/mongo-driver v1.11.3 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect
|
||||
go.opentelemetry.io/otel v1.22.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
|
||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/arch v0.7.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
|
||||
golang.org/x/image v0.13.0 // indirect
|
||||
golang.org/x/mod v0.16.0 // indirect
|
||||
golang.org/x/oauth2 v0.17.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.20.0 // indirect
|
||||
golang.org/x/text v0.15.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.19.0 // indirect
|
||||
google.golang.org/api v0.162.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.21.0 // indirect
|
||||
golang.org/x/term v0.21.0 // indirect
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
google.golang.org/grpc v1.63.2 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
|
||||
google.golang.org/grpc v1.64.0 // indirect
|
||||
google.golang.org/protobuf v1.33.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.6 // indirect
|
||||
gorm.io/driver/postgres v1.5.7 // indirect
|
||||
|
||||
+7
-9
@@ -1,20 +1,18 @@
|
||||
package internal
|
||||
|
||||
import "panel/app/models"
|
||||
import (
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type Backup interface {
|
||||
WebsiteList() ([]BackupFile, error)
|
||||
WebsiteList() ([]types.BackupFile, error)
|
||||
WebSiteBackup(website models.Website) error
|
||||
WebsiteRestore(website models.Website, backupFile string) error
|
||||
MysqlList() ([]BackupFile, error)
|
||||
MysqlList() ([]types.BackupFile, error)
|
||||
MysqlBackup(database string) error
|
||||
MysqlRestore(database string, backupFile string) error
|
||||
PostgresqlList() ([]BackupFile, error)
|
||||
PostgresqlList() ([]types.BackupFile, error)
|
||||
PostgresqlBackup(database string) error
|
||||
PostgresqlRestore(database string, backupFile string) error
|
||||
}
|
||||
|
||||
type BackupFile struct {
|
||||
Name string `json:"name"`
|
||||
Size string `json:"size"`
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
requests "panel/app/http/requests/cert"
|
||||
"panel/app/models"
|
||||
"panel/pkg/acme"
|
||||
requests "github.com/TheTNB/panel/app/http/requests/cert"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/pkg/acme"
|
||||
)
|
||||
|
||||
type Cert interface {
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
|
||||
requests "panel/app/http/requests/container"
|
||||
paneltypes "panel/types"
|
||||
requests "github.com/TheTNB/panel/app/http/requests/container"
|
||||
paneltypes "github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type Container interface {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package internal
|
||||
|
||||
import "panel/app/models"
|
||||
import "github.com/TheTNB/panel/app/models"
|
||||
|
||||
type Cron interface {
|
||||
AddToSystem(cron models.Cron) error
|
||||
|
||||
+2
-9
@@ -1,13 +1,6 @@
|
||||
package internal
|
||||
|
||||
import "panel/types"
|
||||
|
||||
type PHPExtension struct {
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
Description string `json:"description"`
|
||||
Installed bool `json:"installed"`
|
||||
}
|
||||
import "github.com/TheTNB/panel/types"
|
||||
|
||||
type PHP interface {
|
||||
Status() (bool, error)
|
||||
@@ -24,7 +17,7 @@ type PHP interface {
|
||||
GetSlowLog() (string, error)
|
||||
ClearErrorLog() error
|
||||
ClearSlowLog() error
|
||||
GetExtensions() ([]PHPExtension, error)
|
||||
GetExtensions() ([]types.PHPExtension, error)
|
||||
InstallExtension(slug string) error
|
||||
UninstallExtension(slug string) error
|
||||
}
|
||||
|
||||
+6
-16
@@ -1,24 +1,14 @@
|
||||
package internal
|
||||
|
||||
import "panel/app/models"
|
||||
|
||||
// PanelPlugin 插件元数据结构
|
||||
type PanelPlugin struct {
|
||||
Name string
|
||||
Description string
|
||||
Slug string
|
||||
Version string
|
||||
Requires []string
|
||||
Excludes []string
|
||||
Install string
|
||||
Uninstall string
|
||||
Update string
|
||||
}
|
||||
import (
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type Plugin interface {
|
||||
AllInstalled() ([]models.Plugin, error)
|
||||
All() []PanelPlugin
|
||||
GetBySlug(slug string) PanelPlugin
|
||||
All() []types.Plugin
|
||||
GetBySlug(slug string) types.Plugin
|
||||
GetInstalledBySlug(slug string) models.Plugin
|
||||
Install(slug string) error
|
||||
Uninstall(slug string) error
|
||||
|
||||
+22
-21
@@ -9,9 +9,10 @@ import (
|
||||
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type BackupImpl struct {
|
||||
@@ -25,30 +26,30 @@ func NewBackupImpl() *BackupImpl {
|
||||
}
|
||||
|
||||
// WebsiteList 网站备份列表
|
||||
func (s *BackupImpl) WebsiteList() ([]internal.BackupFile, error) {
|
||||
func (s *BackupImpl) WebsiteList() ([]types.BackupFile, error) {
|
||||
backupPath := s.setting.Get(models.SettingKeyBackupPath)
|
||||
if len(backupPath) == 0 {
|
||||
return []internal.BackupFile{}, nil
|
||||
return []types.BackupFile{}, nil
|
||||
}
|
||||
|
||||
backupPath += "/website"
|
||||
if !tools.Exists(backupPath) {
|
||||
if err := tools.Mkdir(backupPath, 0644); err != nil {
|
||||
return []internal.BackupFile{}, err
|
||||
return []types.BackupFile{}, err
|
||||
}
|
||||
}
|
||||
|
||||
files, err := os.ReadDir(backupPath)
|
||||
if err != nil {
|
||||
return []internal.BackupFile{}, err
|
||||
return []types.BackupFile{}, err
|
||||
}
|
||||
var backupList []internal.BackupFile
|
||||
var backupList []types.BackupFile
|
||||
for _, file := range files {
|
||||
info, err := file.Info()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
backupList = append(backupList, internal.BackupFile{
|
||||
backupList = append(backupList, types.BackupFile{
|
||||
Name: file.Name(),
|
||||
Size: tools.FormatBytes(float64(info.Size())),
|
||||
})
|
||||
@@ -115,30 +116,30 @@ func (s *BackupImpl) WebsiteRestore(website models.Website, backupFile string) e
|
||||
}
|
||||
|
||||
// MysqlList MySQL备份列表
|
||||
func (s *BackupImpl) MysqlList() ([]internal.BackupFile, error) {
|
||||
func (s *BackupImpl) MysqlList() ([]types.BackupFile, error) {
|
||||
backupPath := s.setting.Get(models.SettingKeyBackupPath)
|
||||
if len(backupPath) == 0 {
|
||||
return []internal.BackupFile{}, nil
|
||||
return []types.BackupFile{}, nil
|
||||
}
|
||||
|
||||
backupPath += "/mysql"
|
||||
if !tools.Exists(backupPath) {
|
||||
if err := tools.Mkdir(backupPath, 0644); err != nil {
|
||||
return []internal.BackupFile{}, err
|
||||
return []types.BackupFile{}, err
|
||||
}
|
||||
}
|
||||
|
||||
files, err := os.ReadDir(backupPath)
|
||||
if err != nil {
|
||||
return []internal.BackupFile{}, err
|
||||
return []types.BackupFile{}, err
|
||||
}
|
||||
var backupList []internal.BackupFile
|
||||
var backupList []types.BackupFile
|
||||
for _, file := range files {
|
||||
info, err := file.Info()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
backupList = append(backupList, internal.BackupFile{
|
||||
backupList = append(backupList, types.BackupFile{
|
||||
Name: file.Name(),
|
||||
Size: tools.FormatBytes(float64(info.Size())),
|
||||
})
|
||||
@@ -228,30 +229,30 @@ func (s *BackupImpl) MysqlRestore(database string, backupFile string) error {
|
||||
}
|
||||
|
||||
// PostgresqlList PostgreSQL备份列表
|
||||
func (s *BackupImpl) PostgresqlList() ([]internal.BackupFile, error) {
|
||||
func (s *BackupImpl) PostgresqlList() ([]types.BackupFile, error) {
|
||||
backupPath := s.setting.Get(models.SettingKeyBackupPath)
|
||||
if len(backupPath) == 0 {
|
||||
return []internal.BackupFile{}, nil
|
||||
return []types.BackupFile{}, nil
|
||||
}
|
||||
|
||||
backupPath += "/postgresql"
|
||||
if !tools.Exists(backupPath) {
|
||||
if err := tools.Mkdir(backupPath, 0644); err != nil {
|
||||
return []internal.BackupFile{}, err
|
||||
return []types.BackupFile{}, err
|
||||
}
|
||||
}
|
||||
|
||||
files, err := os.ReadDir(backupPath)
|
||||
if err != nil {
|
||||
return []internal.BackupFile{}, err
|
||||
return []types.BackupFile{}, err
|
||||
}
|
||||
var backupList []internal.BackupFile
|
||||
var backupList []types.BackupFile
|
||||
for _, file := range files {
|
||||
info, err := file.Info()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
backupList = append(backupList, internal.BackupFile{
|
||||
backupList = append(backupList, types.BackupFile{
|
||||
Name: file.Name(),
|
||||
Size: tools.FormatBytes(float64(info.Size())),
|
||||
})
|
||||
|
||||
@@ -9,10 +9,10 @@ import (
|
||||
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
requests "panel/app/http/requests/cert"
|
||||
"panel/app/models"
|
||||
"panel/pkg/acme"
|
||||
"panel/pkg/tools"
|
||||
requests "github.com/TheTNB/panel/app/http/requests/cert"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/pkg/acme"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type CertImpl struct {
|
||||
|
||||
@@ -15,8 +15,8 @@ import (
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/goravel/framework/support/json"
|
||||
|
||||
requests "panel/app/http/requests/container"
|
||||
paneltypes "panel/types"
|
||||
requests "github.com/TheTNB/panel/app/http/requests/container"
|
||||
paneltypes "github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type Container struct {
|
||||
|
||||
+21
-23
@@ -1,10 +1,12 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type CronImpl struct {
|
||||
@@ -17,43 +19,39 @@ func NewCronImpl() *CronImpl {
|
||||
// AddToSystem 添加到系统
|
||||
func (r *CronImpl) AddToSystem(cron models.Cron) error {
|
||||
if tools.IsRHEL() {
|
||||
if _, err := tools.Exec("echo \"" + cron.Time + " " + cron.Shell + " >> " + cron.Log + " 2>&1\" >> /var/spool/cron/root"); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tools.Exec("systemctl restart crond"); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if _, err := tools.Exec("echo \"" + cron.Time + " " + cron.Shell + " >> " + cron.Log + " 2>&1\" >> /var/spool/cron/crontabs/root"); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tools.Exec("systemctl restart cron"); err != nil {
|
||||
if _, err := tools.Exec(fmt.Sprintf(`echo "%s %s >> %s 2>&1" >> /var/spool/cron/root`, cron.Time, cron.Shell, cron.Log)); err != nil {
|
||||
return err
|
||||
}
|
||||
return tools.ServiceRestart("crond")
|
||||
}
|
||||
|
||||
return nil
|
||||
if tools.IsDebian() {
|
||||
if _, err := tools.Exec(fmt.Sprintf(`echo "%s %s >> %s 2>&1" >> /var/spool/cron/crontabs/root`, cron.Time, cron.Shell, cron.Log)); err != nil {
|
||||
return err
|
||||
}
|
||||
return tools.ServiceRestart("cron")
|
||||
}
|
||||
|
||||
return errors.New("不支持的系统")
|
||||
}
|
||||
|
||||
// DeleteFromSystem 从系统中删除
|
||||
func (r *CronImpl) DeleteFromSystem(cron models.Cron) error {
|
||||
// 需要转义Shell路径的/为\/
|
||||
// 需要转义 shell 路径的/为\/
|
||||
cron.Shell = strings.ReplaceAll(cron.Shell, "/", "\\/")
|
||||
if tools.IsRHEL() {
|
||||
if _, err := tools.Exec("sed -i '/" + cron.Shell + "/d' /var/spool/cron/root"); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tools.Exec("systemctl restart crond"); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return tools.ServiceRestart("crond")
|
||||
}
|
||||
|
||||
if tools.IsDebian() {
|
||||
if _, err := tools.Exec("sed -i '/" + cron.Shell + "/d' /var/spool/cron/crontabs/root"); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tools.Exec("systemctl restart cron"); err != nil {
|
||||
return err
|
||||
}
|
||||
return tools.ServiceRestart("cron")
|
||||
}
|
||||
|
||||
return nil
|
||||
return errors.New("不支持的系统")
|
||||
}
|
||||
|
||||
+11
-14
@@ -12,10 +12,9 @@ import (
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/pkg/tools"
|
||||
"panel/types"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type PHPImpl struct {
|
||||
@@ -122,8 +121,8 @@ func (r *PHPImpl) ClearSlowLog() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *PHPImpl) GetExtensions() ([]internal.PHPExtension, error) {
|
||||
extensions := []internal.PHPExtension{
|
||||
func (r *PHPImpl) GetExtensions() ([]types.PHPExtension, error) {
|
||||
extensions := []types.PHPExtension{
|
||||
{
|
||||
Name: "fileinfo",
|
||||
Slug: "fileinfo",
|
||||
@@ -264,7 +263,7 @@ func (r *PHPImpl) GetExtensions() ([]internal.PHPExtension, error) {
|
||||
|
||||
// ionCube 只支持 PHP 8.3 以下版本
|
||||
if cast.ToUint(r.version) < 83 {
|
||||
extensions = append(extensions, internal.PHPExtension{
|
||||
extensions = append(extensions, types.PHPExtension{
|
||||
Name: "ionCube",
|
||||
Slug: "ionCube Loader",
|
||||
Description: "ionCube 是一个专业级的 PHP 加密解密工具。",
|
||||
@@ -273,13 +272,13 @@ func (r *PHPImpl) GetExtensions() ([]internal.PHPExtension, error) {
|
||||
}
|
||||
// Swoole 和 Swow 不支持 PHP 8.0 以下版本
|
||||
if cast.ToUint(r.version) >= 80 {
|
||||
extensions = append(extensions, internal.PHPExtension{
|
||||
extensions = append(extensions, types.PHPExtension{
|
||||
Name: "Swoole",
|
||||
Slug: "swoole",
|
||||
Description: "Swoole 是一个用于构建高性能的异步并发服务器的 PHP 扩展。",
|
||||
Installed: false,
|
||||
})
|
||||
extensions = append(extensions, internal.PHPExtension{
|
||||
extensions = append(extensions, types.PHPExtension{
|
||||
Name: "Swow",
|
||||
Slug: "Swow",
|
||||
Description: "Swow 是一个用于构建高性能的异步并发服务器的 PHP 扩展。",
|
||||
@@ -292,7 +291,7 @@ func (r *PHPImpl) GetExtensions() ([]internal.PHPExtension, error) {
|
||||
return extensions, err
|
||||
}
|
||||
|
||||
extensionMap := make(map[string]*internal.PHPExtension)
|
||||
extensionMap := make(map[string]*types.PHPExtension)
|
||||
for i := range extensions {
|
||||
extensionMap[extensions[i].Slug] = &extensions[i]
|
||||
}
|
||||
@@ -328,8 +327,7 @@ func (r *PHPImpl) InstallExtension(slug string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
NewTaskImpl().Process(task.ID)
|
||||
return nil
|
||||
return NewTaskImpl().Process(task.ID)
|
||||
}
|
||||
|
||||
func (r *PHPImpl) UninstallExtension(slug string) error {
|
||||
@@ -353,8 +351,7 @@ func (r *PHPImpl) UninstallExtension(slug string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
NewTaskImpl().Process(task.ID)
|
||||
return nil
|
||||
return NewTaskImpl().Process(task.ID)
|
||||
}
|
||||
|
||||
func (r *PHPImpl) checkExtension(slug string) bool {
|
||||
|
||||
+32
-33
@@ -6,8 +6,9 @@ import (
|
||||
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type PluginImpl struct {
|
||||
@@ -31,44 +32,45 @@ func (r *PluginImpl) AllInstalled() ([]models.Plugin, error) {
|
||||
}
|
||||
|
||||
// All 获取所有插件
|
||||
func (r *PluginImpl) All() []internal.PanelPlugin {
|
||||
var plugins = []internal.PanelPlugin{
|
||||
internal.PluginOpenResty,
|
||||
internal.PluginMySQL57,
|
||||
internal.PluginMySQL80,
|
||||
internal.PluginMySQL84,
|
||||
internal.PluginPostgreSQL15,
|
||||
internal.PluginPostgreSQL16,
|
||||
internal.PluginPHP74,
|
||||
internal.PluginPHP80,
|
||||
internal.PluginPHP81,
|
||||
internal.PluginPHP82,
|
||||
internal.PluginPHP83,
|
||||
internal.PluginPHPMyAdmin,
|
||||
internal.PluginPureFTPd,
|
||||
internal.PluginRedis,
|
||||
internal.PluginS3fs,
|
||||
internal.PluginRsync,
|
||||
internal.PluginSupervisor,
|
||||
internal.PluginFail2ban,
|
||||
internal.PluginToolBox,
|
||||
func (r *PluginImpl) All() []types.Plugin {
|
||||
var plugins = []types.Plugin{
|
||||
types.PluginOpenResty,
|
||||
types.PluginMySQL57,
|
||||
types.PluginMySQL80,
|
||||
types.PluginMySQL84,
|
||||
types.PluginPostgreSQL15,
|
||||
types.PluginPostgreSQL16,
|
||||
types.PluginPHP74,
|
||||
types.PluginPHP80,
|
||||
types.PluginPHP81,
|
||||
types.PluginPHP82,
|
||||
types.PluginPHP83,
|
||||
types.PluginPHPMyAdmin,
|
||||
types.PluginPureFTPd,
|
||||
types.PluginRedis,
|
||||
types.PluginS3fs,
|
||||
types.PluginRsync,
|
||||
types.PluginSupervisor,
|
||||
types.PluginFail2ban,
|
||||
types.PluginFrp,
|
||||
types.PluginToolBox,
|
||||
}
|
||||
|
||||
return plugins
|
||||
}
|
||||
|
||||
// GetBySlug 根据slug获取插件
|
||||
func (r *PluginImpl) GetBySlug(slug string) internal.PanelPlugin {
|
||||
// GetBySlug 根据 slug 获取插件
|
||||
func (r *PluginImpl) GetBySlug(slug string) types.Plugin {
|
||||
for _, item := range r.All() {
|
||||
if item.Slug == slug {
|
||||
return item
|
||||
}
|
||||
}
|
||||
|
||||
return internal.PanelPlugin{}
|
||||
return types.Plugin{}
|
||||
}
|
||||
|
||||
// GetInstalledBySlug 根据slug获取已安装的插件
|
||||
// GetInstalledBySlug 根据 slug 获取已安装的插件
|
||||
func (r *PluginImpl) GetInstalledBySlug(slug string) models.Plugin {
|
||||
var plugin models.Plugin
|
||||
if err := facades.Orm().Query().Where("slug", slug).Get(&plugin); err != nil {
|
||||
@@ -120,8 +122,7 @@ func (r *PluginImpl) Install(slug string) error {
|
||||
return errors.New("创建任务失败")
|
||||
}
|
||||
|
||||
r.task.Process(task.ID)
|
||||
return nil
|
||||
return r.task.Process(task.ID)
|
||||
}
|
||||
|
||||
// Uninstall 卸载插件
|
||||
@@ -166,8 +167,7 @@ func (r *PluginImpl) Uninstall(slug string) error {
|
||||
return errors.New("创建任务失败")
|
||||
}
|
||||
|
||||
r.task.Process(task.ID)
|
||||
return nil
|
||||
return r.task.Process(task.ID)
|
||||
}
|
||||
|
||||
// Update 更新插件
|
||||
@@ -212,6 +212,5 @@ func (r *PluginImpl) Update(slug string) error {
|
||||
return errors.New("创建任务失败")
|
||||
}
|
||||
|
||||
r.task.Process(task.ID)
|
||||
return nil
|
||||
return r.task.Process(task.ID)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ package services
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/facades"
|
||||
"panel/app/models"
|
||||
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type SettingImpl struct {
|
||||
@@ -17,19 +19,11 @@ func NewSettingImpl() *SettingImpl {
|
||||
func (r *SettingImpl) Get(key string, defaultValue ...string) string {
|
||||
var setting models.Setting
|
||||
if err := facades.Orm().Query().Where("key", key).FirstOrFail(&setting); err != nil {
|
||||
if len(defaultValue) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return defaultValue[0]
|
||||
return tools.FirstElement(defaultValue)
|
||||
}
|
||||
|
||||
if len(setting.Value) == 0 {
|
||||
if len(defaultValue) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return defaultValue[0]
|
||||
return tools.FirstElement(defaultValue)
|
||||
}
|
||||
|
||||
return setting.Value
|
||||
|
||||
+19
-12
@@ -1,10 +1,10 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"github.com/goravel/framework/contracts/queue"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/jobs"
|
||||
"github.com/TheTNB/panel/app/jobs"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
)
|
||||
|
||||
type TaskImpl struct {
|
||||
@@ -14,14 +14,21 @@ func NewTaskImpl() *TaskImpl {
|
||||
return &TaskImpl{}
|
||||
}
|
||||
|
||||
func (r *TaskImpl) Process(taskID uint) {
|
||||
go func() {
|
||||
err := facades.Queue().Job(&jobs.ProcessTask{}, []queue.Arg{
|
||||
{Type: "uint", Value: taskID},
|
||||
}).Dispatch()
|
||||
if err != nil {
|
||||
facades.Log().Info("[面板][TaskService] 运行任务失败: " + err.Error())
|
||||
return
|
||||
}
|
||||
}()
|
||||
func (r *TaskImpl) Process(taskID uint) error {
|
||||
return facades.Queue().Job(&jobs.ProcessTask{}, []any{taskID}).Dispatch()
|
||||
}
|
||||
|
||||
func (r *TaskImpl) DispatchWaiting() error {
|
||||
var tasks []models.Task
|
||||
if err := facades.Orm().Query().Where("status = ?", models.TaskStatusWaiting).Find(&tasks); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, task := range tasks {
|
||||
if err := r.Process(task.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package services
|
||||
import (
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/models"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
)
|
||||
|
||||
type UserImpl struct {
|
||||
|
||||
@@ -12,11 +12,12 @@ import (
|
||||
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/spf13/cast"
|
||||
requests "panel/app/http/requests/website"
|
||||
|
||||
"panel/app/models"
|
||||
"panel/internal"
|
||||
"panel/pkg/tools"
|
||||
requests "github.com/TheTNB/panel/app/http/requests/website"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/internal"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type WebsiteImpl struct {
|
||||
@@ -41,7 +42,7 @@ func (r *WebsiteImpl) List(page, limit int) (int64, []models.Website, error) {
|
||||
}
|
||||
|
||||
// Add 添加网站
|
||||
func (r *WebsiteImpl) Add(website internal.PanelWebsite) (models.Website, error) {
|
||||
func (r *WebsiteImpl) Add(website types.Website) (models.Website, error) {
|
||||
w := models.Website{
|
||||
Name: website.Name,
|
||||
Status: website.Status,
|
||||
@@ -459,8 +460,7 @@ func (r *WebsiteImpl) SaveConfig(config requests.SaveConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = tools.Exec("systemctl reload openresty")
|
||||
return err
|
||||
return tools.ServiceReload("openresty")
|
||||
}
|
||||
|
||||
// Delete 删除网站
|
||||
@@ -494,23 +494,22 @@ func (r *WebsiteImpl) Delete(id uint) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := tools.Exec("systemctl reload openresty")
|
||||
return err
|
||||
return tools.ServiceReload("openresty")
|
||||
}
|
||||
|
||||
// GetConfig 获取网站配置
|
||||
func (r *WebsiteImpl) GetConfig(id uint) (internal.WebsiteSetting, error) {
|
||||
func (r *WebsiteImpl) GetConfig(id uint) (types.WebsiteSetting, error) {
|
||||
var website models.Website
|
||||
if err := facades.Orm().Query().Where("id", id).First(&website); err != nil {
|
||||
return internal.WebsiteSetting{}, err
|
||||
return types.WebsiteSetting{}, err
|
||||
}
|
||||
|
||||
config, err := tools.Read("/www/server/vhost/" + website.Name + ".conf")
|
||||
if err != nil {
|
||||
return internal.WebsiteSetting{}, err
|
||||
return types.WebsiteSetting{}, err
|
||||
}
|
||||
|
||||
var setting internal.WebsiteSetting
|
||||
var setting types.WebsiteSetting
|
||||
setting.Name = website.Name
|
||||
setting.Path = website.Path
|
||||
setting.Ssl = website.Ssl
|
||||
@@ -612,10 +611,10 @@ func (r *WebsiteImpl) GetConfig(id uint) (internal.WebsiteSetting, error) {
|
||||
}
|
||||
|
||||
// GetConfigByName 根据网站名称获取网站配置
|
||||
func (r *WebsiteImpl) GetConfigByName(name string) (internal.WebsiteSetting, error) {
|
||||
func (r *WebsiteImpl) GetConfigByName(name string) (types.WebsiteSetting, error) {
|
||||
var website models.Website
|
||||
if err := facades.Orm().Query().Where("name", name).First(&website); err != nil {
|
||||
return internal.WebsiteSetting{}, err
|
||||
return types.WebsiteSetting{}, err
|
||||
}
|
||||
|
||||
return r.GetConfig(website.ID)
|
||||
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
package internal
|
||||
|
||||
type Task interface {
|
||||
Process(taskID uint)
|
||||
Process(taskID uint) error
|
||||
DispatchWaiting() error
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package internal
|
||||
|
||||
import "panel/app/models"
|
||||
import "github.com/TheTNB/panel/app/models"
|
||||
|
||||
type User interface {
|
||||
Create(name, password string) (models.User, error)
|
||||
|
||||
+6
-50
@@ -1,61 +1,17 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
requests "panel/app/http/requests/website"
|
||||
"panel/app/models"
|
||||
requests "github.com/TheTNB/panel/app/http/requests/website"
|
||||
"github.com/TheTNB/panel/app/models"
|
||||
"github.com/TheTNB/panel/types"
|
||||
)
|
||||
|
||||
type Website interface {
|
||||
List(page int, limit int) (int64, []models.Website, error)
|
||||
Add(website PanelWebsite) (models.Website, error)
|
||||
Add(website types.Website) (models.Website, error)
|
||||
SaveConfig(config requests.SaveConfig) error
|
||||
Delete(id uint) error
|
||||
GetConfig(id uint) (WebsiteSetting, error)
|
||||
GetConfigByName(name string) (WebsiteSetting, error)
|
||||
GetConfig(id uint) (types.WebsiteSetting, error)
|
||||
GetConfigByName(name string) (types.WebsiteSetting, error)
|
||||
GetIDByName(name string) (uint, error)
|
||||
}
|
||||
|
||||
type PanelWebsite struct {
|
||||
Name string `json:"name"`
|
||||
Status bool `json:"status"`
|
||||
Domains []string `json:"domains"`
|
||||
Ports []uint `json:"ports"`
|
||||
Path string `json:"path"`
|
||||
Php string `json:"php"`
|
||||
Ssl bool `json:"ssl"`
|
||||
Remark string `json:"remark"`
|
||||
Db bool `json:"db"`
|
||||
DbType string `json:"db_type"`
|
||||
DbName string `json:"db_name"`
|
||||
DbUser string `json:"db_user"`
|
||||
DbPassword string `json:"db_password"`
|
||||
}
|
||||
|
||||
// WebsiteSetting 网站设置
|
||||
type WebsiteSetting struct {
|
||||
Name string `json:"name"`
|
||||
Domains []string `json:"domains"`
|
||||
Ports []uint `json:"ports"`
|
||||
Root string `json:"root"`
|
||||
Path string `json:"path"`
|
||||
Index string `json:"index"`
|
||||
Php string `json:"php"`
|
||||
OpenBasedir bool `json:"open_basedir"`
|
||||
Ssl bool `json:"ssl"`
|
||||
SslCertificate string `json:"ssl_certificate"`
|
||||
SslCertificateKey string `json:"ssl_certificate_key"`
|
||||
SslNotBefore string `json:"ssl_not_before"`
|
||||
SslNotAfter string `json:"ssl_not_after"`
|
||||
SSlDNSNames []string `json:"ssl_dns_names"`
|
||||
SslIssuer string `json:"ssl_issuer"`
|
||||
SslOCSPServer []string `json:"ssl_ocsp_server"`
|
||||
HttpRedirect bool `json:"http_redirect"`
|
||||
Hsts bool `json:"hsts"`
|
||||
Waf bool `json:"waf"`
|
||||
WafMode string `json:"waf_mode"`
|
||||
WafCcDeny string `json:"waf_cc_deny"`
|
||||
WafCache string `json:"waf_cache"`
|
||||
Rewrite string `json:"rewrite"`
|
||||
Raw string `json:"raw"`
|
||||
Log string `json:"log"`
|
||||
}
|
||||
|
||||
+2
-1
@@ -24,6 +24,7 @@
|
||||
"update": {
|
||||
"description": "update/fix panel to latest version",
|
||||
"taskCheck": "There is currently a task being executed and updates are prohibited.",
|
||||
"dbFail": "panel database exception, operation terminated",
|
||||
"versionFail": "failed to get latest version",
|
||||
"fail": "update failed",
|
||||
"success": "update completed"
|
||||
@@ -76,7 +77,7 @@
|
||||
"databaseGetFail": "failed to get database",
|
||||
"databaseNotExist": "database does not exist",
|
||||
"targetPostgres": "target PostgreSQL database",
|
||||
"cleanBackup" : "clean backup",
|
||||
"cleanBackup": "clean backup",
|
||||
"cleanupFail": "cleanup failed",
|
||||
"cleanupSuccess": "cleanup successful",
|
||||
"deleteFail": "failed to delete",
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"update": {
|
||||
"description": "更新 / 修复面板到最新版本",
|
||||
"taskCheck": "当前有任务正在执行,禁止更新",
|
||||
"dbFail": "面板数据库异常,已终止操作",
|
||||
"versionFail": "获取最新版本失败",
|
||||
"fail": "更新失败",
|
||||
"success": "更新成功"
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/bootstrap"
|
||||
"github.com/TheTNB/panel/bootstrap"
|
||||
)
|
||||
|
||||
// @title 耗子 Linux 面板 API
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
// @description 耗子 Linux 面板的 API 信息
|
||||
|
||||
// @contact.name 耗子科技
|
||||
// @contact.email i@haozi.net
|
||||
// @contact.email admin@haozi.net
|
||||
|
||||
// @license.name GNU Affero General Public License v3
|
||||
// @license url https://www.gnu.org/licenses/agpl-3.0.html
|
||||
@@ -59,5 +59,12 @@ func main() {
|
||||
// 启动计划任务
|
||||
go facades.Schedule().Run()
|
||||
|
||||
// 启动队列
|
||||
go func() {
|
||||
if err := facades.Queue().Worker(nil).Run(); err != nil {
|
||||
facades.Log().Errorf("Queue run error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
select {}
|
||||
}
|
||||
|
||||
+3
-8
@@ -26,13 +26,11 @@ func (s httpSolver) Present(_ context.Context, challenge acme.Challenge) error {
|
||||
}
|
||||
|
||||
challengeFilePath := filepath.Join(s.path, challenge.HTTP01ResourcePath())
|
||||
err = os.MkdirAll(filepath.Dir(challengeFilePath), 0o755)
|
||||
if err != nil {
|
||||
if err = os.MkdirAll(filepath.Dir(challengeFilePath), 0o755); err != nil {
|
||||
return fmt.Errorf("无法在网站目录创建 HTTP 挑战所需的目录: %w", err)
|
||||
}
|
||||
|
||||
err = os.WriteFile(challengeFilePath, []byte(challenge.KeyAuthorization), 0o644)
|
||||
if err != nil {
|
||||
if err = os.WriteFile(challengeFilePath, []byte(challenge.KeyAuthorization), 0o644); err != nil {
|
||||
return fmt.Errorf("无法在网站目录创建 HTTP 挑战所需的文件: %w", err)
|
||||
}
|
||||
|
||||
@@ -45,8 +43,7 @@ func (s httpSolver) CleanUp(_ context.Context, challenge acme.Challenge) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := os.Remove(filepath.Join(s.path, challenge.HTTP01ResourcePath()))
|
||||
if err != nil {
|
||||
if err := os.Remove(filepath.Join(s.path, challenge.HTTP01ResourcePath())); err != nil {
|
||||
return fmt.Errorf("无法删除 HTTP 挑战文件: %w", err)
|
||||
}
|
||||
|
||||
@@ -167,7 +164,6 @@ func (s manualDNSSolver) Present(ctx context.Context, challenge acme.Challenge)
|
||||
dnsName := challenge.DNS01TXTRecordName()
|
||||
keyAuth := challenge.DNS01KeyAuthorization()
|
||||
|
||||
// 追加记录到 records 中
|
||||
*s.records = append(*s.records, DNSRecord{
|
||||
Key: dnsName,
|
||||
Value: keyAuth,
|
||||
@@ -177,7 +173,6 @@ func (s manualDNSSolver) Present(ctx context.Context, challenge acme.Challenge)
|
||||
_, cancel := context.WithTimeout(ctx, 2*time.Minute)
|
||||
defer cancel()
|
||||
|
||||
// 等待信号以继续
|
||||
<-s.controlChan
|
||||
return nil
|
||||
}
|
||||
|
||||
+7
-7
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
|
||||
"panel/pkg/tools"
|
||||
"github.com/TheTNB/panel/pkg/tools"
|
||||
)
|
||||
|
||||
type AuthMethod int8
|
||||
@@ -15,7 +15,7 @@ const (
|
||||
PUBLICKEY
|
||||
)
|
||||
|
||||
type SSHClientConfig struct {
|
||||
type ClientConfig struct {
|
||||
AuthMethod AuthMethod
|
||||
HostAddr string
|
||||
User string
|
||||
@@ -24,8 +24,8 @@ type SSHClientConfig struct {
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
func SSHClientConfigPassword(hostAddr, user, Password string) *SSHClientConfig {
|
||||
return &SSHClientConfig{
|
||||
func ClientConfigPassword(hostAddr, user, Password string) *ClientConfig {
|
||||
return &ClientConfig{
|
||||
Timeout: time.Second * 5,
|
||||
AuthMethod: PASSWORD,
|
||||
HostAddr: hostAddr,
|
||||
@@ -34,8 +34,8 @@ func SSHClientConfigPassword(hostAddr, user, Password string) *SSHClientConfig {
|
||||
}
|
||||
}
|
||||
|
||||
func SSHClientConfigPulicKey(hostAddr, user, keyPath string) *SSHClientConfig {
|
||||
return &SSHClientConfig{
|
||||
func ClientConfigPublicKey(hostAddr, user, keyPath string) *ClientConfig {
|
||||
return &ClientConfig{
|
||||
Timeout: time.Second * 5,
|
||||
AuthMethod: PUBLICKEY,
|
||||
HostAddr: hostAddr,
|
||||
@@ -44,7 +44,7 @@ func SSHClientConfigPulicKey(hostAddr, user, keyPath string) *SSHClientConfig {
|
||||
}
|
||||
}
|
||||
|
||||
func NewSSHClient(conf *SSHClientConfig) (*ssh.Client, error) {
|
||||
func NewSSHClient(conf *ClientConfig) (*ssh.Client, error) {
|
||||
config := &ssh.ClientConfig{
|
||||
Timeout: conf.Timeout,
|
||||
User: conf.User,
|
||||
|
||||
+40
-1
@@ -1,6 +1,11 @@
|
||||
package tools
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ServiceStatus 获取服务状态
|
||||
func ServiceStatus(name string) (bool, error) {
|
||||
@@ -8,6 +13,28 @@ func ServiceStatus(name string) (bool, error) {
|
||||
return output == "active", err
|
||||
}
|
||||
|
||||
// ServiceIsEnabled 服务是否启用
|
||||
func ServiceIsEnabled(name string) (bool, error) {
|
||||
cmd := exec.Command("systemctl", "is-enabled", name)
|
||||
output, _ := cmd.CombinedOutput()
|
||||
status := strings.TrimSpace(string(output))
|
||||
|
||||
switch status {
|
||||
case "enabled":
|
||||
return true, nil
|
||||
case "disabled":
|
||||
return false, nil
|
||||
case "masked":
|
||||
return false, errors.New("服务已被屏蔽")
|
||||
case "static":
|
||||
return false, errors.New("服务已被静态启用")
|
||||
case "indirect":
|
||||
return false, errors.New("服务已被间接启用")
|
||||
default:
|
||||
return false, errors.New("无法确定服务状态")
|
||||
}
|
||||
}
|
||||
|
||||
// ServiceStart 启动服务
|
||||
func ServiceStart(name string) error {
|
||||
_, err := Exec(fmt.Sprintf("systemctl start %s", name))
|
||||
@@ -31,3 +58,15 @@ func ServiceReload(name string) error {
|
||||
_, err := Exec(fmt.Sprintf("systemctl reload %s", name))
|
||||
return err
|
||||
}
|
||||
|
||||
// ServiceEnable 启用服务
|
||||
func ServiceEnable(name string) error {
|
||||
_, err := Exec(fmt.Sprintf("systemctl enable %s", name))
|
||||
return err
|
||||
}
|
||||
|
||||
// ServiceDisable 禁用服务
|
||||
func ServiceDisable(name string) error {
|
||||
_, err := Exec(fmt.Sprintf("systemctl disable %s", name))
|
||||
return err
|
||||
}
|
||||
|
||||
+42
-60
@@ -4,14 +4,14 @@ package tools
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/spf13/cast"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/gookit/color"
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
"github.com/goravel/framework/support/color"
|
||||
"github.com/goravel/framework/support/env"
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/disk"
|
||||
@@ -101,30 +101,12 @@ func GenerateVersions(start, end string) ([]string, error) {
|
||||
return nil, fmt.Errorf("版本格式错误")
|
||||
}
|
||||
|
||||
startMajor, err := strconv.Atoi(startParts[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("无效的起始主版本号: %v", err)
|
||||
}
|
||||
startMinor, err := strconv.Atoi(startParts[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("无效的起始次版本号: %v", err)
|
||||
}
|
||||
startPatch, err := strconv.Atoi(startParts[2])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("无效的起始修订号: %v", err)
|
||||
}
|
||||
endMajor, err := strconv.Atoi(endParts[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("无效的结束主版本号: %v", err)
|
||||
}
|
||||
endMinor, err := strconv.Atoi(endParts[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("无效的结束次版本号: %v", err)
|
||||
}
|
||||
endPatch, err := strconv.Atoi(endParts[2])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("无效的结束修订号: %v", err)
|
||||
}
|
||||
startMajor := cast.ToInt(startParts[0])
|
||||
startMinor := cast.ToInt(startParts[1])
|
||||
startPatch := cast.ToInt(startParts[2])
|
||||
endMajor := cast.ToInt(endParts[0])
|
||||
endMinor := cast.ToInt(endParts[1])
|
||||
endPatch := cast.ToInt(endParts[2])
|
||||
|
||||
for major := startMajor; major <= endMajor; major++ {
|
||||
for minor := 0; minor <= 99; minor++ {
|
||||
@@ -402,108 +384,108 @@ func GetPanelVersion(version string) (PanelInfo, error) {
|
||||
|
||||
// UpdatePanel 更新面板
|
||||
func UpdatePanel(panelInfo PanelInfo) error {
|
||||
color.Greenln("目标版本: " + panelInfo.Version)
|
||||
color.Greenln("下载链接: " + panelInfo.DownloadUrl)
|
||||
color.Green().Printfln("目标版本: " + panelInfo.Version)
|
||||
color.Green().Printfln("下载链接: " + panelInfo.DownloadUrl)
|
||||
|
||||
color.Greenln("前置检查...")
|
||||
color.Green().Printfln("前置检查...")
|
||||
if Exists("/tmp/panel-storage.zip") || Exists("/tmp/panel.conf.bak") {
|
||||
return errors.New("检测到 /tmp 存在临时文件,可能是上次更新失败导致的,请谨慎排除后重试")
|
||||
}
|
||||
|
||||
color.Greenln("备份面板数据...")
|
||||
color.Green().Printfln("备份面板数据...")
|
||||
// 备份面板
|
||||
if err := Archive([]string{"/www/panel"}, "/www/backup/panel/panel-"+carbon.Now().ToShortDateTimeString()+".zip"); err != nil {
|
||||
color.Redln("备份面板失败")
|
||||
color.Red().Printfln("备份面板失败")
|
||||
return err
|
||||
}
|
||||
if _, err := Exec("cd /www/panel/storage && zip -r /tmp/panel-storage.zip *"); err != nil {
|
||||
color.Redln("备份面板数据失败")
|
||||
color.Red().Printfln("备份面板数据失败")
|
||||
return err
|
||||
}
|
||||
if _, err := Exec("cp -f /www/panel/panel.conf /tmp/panel.conf.bak"); err != nil {
|
||||
color.Redln("备份面板配置失败")
|
||||
color.Red().Printfln("备份面板配置失败")
|
||||
return err
|
||||
}
|
||||
if !Exists("/tmp/panel-storage.zip") || !Exists("/tmp/panel.conf.bak") {
|
||||
return errors.New("备份面板数据失败")
|
||||
}
|
||||
color.Greenln("备份完成")
|
||||
color.Green().Printfln("备份完成")
|
||||
|
||||
color.Greenln("清理旧版本...")
|
||||
color.Green().Printfln("清理旧版本...")
|
||||
if _, err := Exec("rm -rf /www/panel/*"); err != nil {
|
||||
color.Redln("清理旧版本失败")
|
||||
color.Red().Printfln("清理旧版本失败")
|
||||
return err
|
||||
}
|
||||
color.Greenln("清理完成")
|
||||
color.Green().Printfln("清理完成")
|
||||
|
||||
color.Greenln("正在下载...")
|
||||
color.Green().Printfln("正在下载...")
|
||||
if _, err := Exec("wget -T 120 -t 3 -O /www/panel/" + panelInfo.DownloadName + " " + panelInfo.DownloadUrl); err != nil {
|
||||
color.Redln("下载失败")
|
||||
color.Red().Printfln("下载失败")
|
||||
return err
|
||||
}
|
||||
if _, err := Exec("wget -T 20 -t 3 -O /www/panel/" + panelInfo.Checksums + " " + panelInfo.ChecksumsUrl); err != nil {
|
||||
color.Redln("下载失败")
|
||||
color.Red().Printfln("下载失败")
|
||||
return err
|
||||
}
|
||||
if !Exists("/www/panel/"+panelInfo.DownloadName) || !Exists("/www/panel/"+panelInfo.Checksums) {
|
||||
return errors.New("下载失败")
|
||||
}
|
||||
color.Greenln("下载完成")
|
||||
color.Green().Printfln("下载完成")
|
||||
|
||||
color.Greenln("校验下载文件...")
|
||||
color.Green().Printfln("校验下载文件...")
|
||||
check, err := Exec("cd /www/panel && sha256sum -c " + panelInfo.Checksums + " --ignore-missing")
|
||||
if check != panelInfo.DownloadName+": OK" || err != nil {
|
||||
return errors.New("下载文件校验失败")
|
||||
}
|
||||
if err = Remove("/www/panel/" + panelInfo.Checksums); err != nil {
|
||||
color.Redln("清理临时文件失败")
|
||||
color.Red().Printfln("清理临时文件失败")
|
||||
return err
|
||||
}
|
||||
color.Greenln("文件校验完成")
|
||||
color.Green().Printfln("文件校验完成")
|
||||
|
||||
color.Greenln("更新新版本...")
|
||||
color.Green().Printfln("更新新版本...")
|
||||
if _, err = Exec("cd /www/panel && unzip -o " + panelInfo.DownloadName + " && rm -rf " + panelInfo.DownloadName); err != nil {
|
||||
color.Redln("更新失败")
|
||||
color.Red().Printfln("更新失败")
|
||||
return err
|
||||
}
|
||||
if !Exists("/www/panel/panel") {
|
||||
return errors.New("更新失败,可能是下载过程中出现了问题")
|
||||
}
|
||||
color.Greenln("更新完成")
|
||||
color.Green().Printfln("更新完成")
|
||||
|
||||
color.Greenln("恢复面板数据...")
|
||||
color.Green().Printfln("恢复面板数据...")
|
||||
if _, err = Exec("cp -f /tmp/panel-storage.zip /www/panel/storage/panel-storage.zip && cd /www/panel/storage && unzip -o panel-storage.zip && rm -rf panel-storage.zip"); err != nil {
|
||||
color.Redln("恢复面板数据失败")
|
||||
color.Red().Printfln("恢复面板数据失败")
|
||||
return err
|
||||
}
|
||||
if _, err = Exec("cp -f /tmp/panel.conf.bak /www/panel/panel.conf"); err != nil {
|
||||
color.Redln("恢复面板配置失败")
|
||||
color.Red().Printfln("恢复面板配置失败")
|
||||
return err
|
||||
}
|
||||
if _, err = Exec("cp -f /www/panel/scripts/panel.sh /usr/bin/panel"); err != nil {
|
||||
color.Redln("恢复面板脚本失败")
|
||||
color.Red().Printfln("恢复面板脚本失败")
|
||||
return err
|
||||
}
|
||||
if !Exists("/www/panel/storage/panel.db") || !Exists("/www/panel/panel.conf") {
|
||||
return errors.New("恢复面板数据失败")
|
||||
}
|
||||
color.Greenln("恢复完成")
|
||||
color.Green().Printfln("恢复完成")
|
||||
|
||||
color.Greenln("设置面板文件权限...")
|
||||
color.Green().Printfln("设置面板文件权限...")
|
||||
_, _ = Exec("chmod -R 700 /www/panel")
|
||||
_, _ = Exec("chmod -R 700 /usr/bin/panel")
|
||||
color.Greenln("设置完成")
|
||||
color.Green().Printfln("设置完成")
|
||||
|
||||
if _, err = Exec("/www/panel/panel --env=panel.conf artisan migrate"); err != nil {
|
||||
color.Redln("运行面板数据库迁移失败")
|
||||
color.Red().Printfln("运行面板数据库迁移失败")
|
||||
return err
|
||||
}
|
||||
if _, err = Exec("bash /www/panel/scripts/update_panel.sh"); err != nil {
|
||||
color.Redln("执行面板升级后脚本失败")
|
||||
color.Red().Printfln("执行面板升级后脚本失败")
|
||||
return err
|
||||
}
|
||||
if _, err = Exec("panel writeSetting version " + panelInfo.Version); err != nil {
|
||||
color.Redln("写入面板版本号失败")
|
||||
color.Red().Printfln("写入面板版本号失败")
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -514,14 +496,14 @@ func UpdatePanel(panelInfo PanelInfo) error {
|
||||
}
|
||||
|
||||
func RestartPanel() {
|
||||
color.Greenln("重启面板...")
|
||||
color.Green().Printfln("重启面板...")
|
||||
err := ExecAsync("sleep 2 && systemctl restart panel")
|
||||
if err != nil {
|
||||
color.Redln("重启失败")
|
||||
color.Red().Printfln("重启失败")
|
||||
return
|
||||
}
|
||||
|
||||
color.Greenln("重启完成")
|
||||
color.Green().Printfln("重启完成")
|
||||
}
|
||||
|
||||
// IsChina 是否中国大陆
|
||||
|
||||
@@ -74,14 +74,6 @@ func (s *HelperTestSuite) TestGenerateVersions() {
|
||||
"1.0.91", "1.0.92", "1.0.93", "1.0.94", "1.0.95", "1.0.96", "1.0.97", "1.0.98", "1.0.99", "1.1.0",
|
||||
"1.1.1",
|
||||
}, versions)
|
||||
|
||||
versions, err = GenerateVersions("1..0", "1.0.1")
|
||||
s.Error(err)
|
||||
s.Nil(versions)
|
||||
|
||||
versions, err = GenerateVersions("1.0.0", "1..1")
|
||||
s.Error(err)
|
||||
s.Nil(versions)
|
||||
}
|
||||
|
||||
func (s *HelperTestSuite) TestGetLatestPanelVersion() {
|
||||
|
||||
+3
-3
@@ -4,15 +4,15 @@ import (
|
||||
"github.com/goravel/framework/contracts/route"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/http/controllers"
|
||||
"panel/app/http/middleware"
|
||||
"github.com/TheTNB/panel/app/http/controllers"
|
||||
"github.com/TheTNB/panel/app/http/middleware"
|
||||
)
|
||||
|
||||
func Api() {
|
||||
facades.Route().Prefix("api/panel").Group(func(r route.Router) {
|
||||
r.Prefix("info").Group(func(r route.Router) {
|
||||
infoController := controllers.NewInfoController()
|
||||
r.Get("name", infoController.Name)
|
||||
r.Get("panel", infoController.Panel)
|
||||
r.Middleware(middleware.Jwt()).Get("homePlugins", infoController.HomePlugins)
|
||||
r.Middleware(middleware.Jwt()).Get("nowMonitor", infoController.NowMonitor)
|
||||
r.Middleware(middleware.Jwt()).Get("systemInfo", infoController.SystemInfo)
|
||||
|
||||
+14
-2
@@ -4,8 +4,8 @@ import (
|
||||
"github.com/goravel/framework/contracts/route"
|
||||
"github.com/goravel/framework/facades"
|
||||
|
||||
"panel/app/http/controllers/plugins"
|
||||
"panel/app/http/middleware"
|
||||
"github.com/TheTNB/panel/app/http/controllers/plugins"
|
||||
"github.com/TheTNB/panel/app/http/middleware"
|
||||
)
|
||||
|
||||
// Plugin 加载插件路由
|
||||
@@ -353,6 +353,18 @@ func Plugin() {
|
||||
route.Get("config", rsyncController.GetConfig)
|
||||
route.Post("config", rsyncController.UpdateConfig)
|
||||
})
|
||||
r.Prefix("frp").Group(func(route route.Router) {
|
||||
frpController := plugins.NewFrpController()
|
||||
route.Get("status", frpController.Status)
|
||||
route.Get("isEnabled", frpController.IsEnabled)
|
||||
route.Post("enable", frpController.Enable)
|
||||
route.Post("disable", frpController.Disable)
|
||||
route.Post("start", frpController.Start)
|
||||
route.Post("stop", frpController.Stop)
|
||||
route.Post("restart", frpController.Restart)
|
||||
route.Get("config", frpController.GetConfig)
|
||||
route.Post("config", frpController.UpdateConfig)
|
||||
})
|
||||
r.Prefix("toolbox").Group(func(route route.Router) {
|
||||
toolboxController := plugins.NewToolBoxController()
|
||||
route.Get("dns", toolboxController.GetDNS)
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/www/server/bin:/www/server/sbin:$PATH
|
||||
|
||||
: '
|
||||
Copyright (C) 2022 - now HaoZi Technology Co., Ltd.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
'
|
||||
|
||||
HR="+----------------------------------------------------"
|
||||
ARCH=$(uname -m)
|
||||
downloadUrl="https://dl.cdn.haozi.net/panel/frp"
|
||||
frpPath="/www/server/frp"
|
||||
frpVersion="0.58.0"
|
||||
|
||||
if [ ! -d "${frpPath}" ]; then
|
||||
mkdir -p ${frpPath}
|
||||
fi
|
||||
|
||||
# 架构判断
|
||||
if [ "${ARCH}" == "x86_64" ]; then
|
||||
frpFile="frp_${frpVersion}_linux_amd64.7z"
|
||||
elif [ "${ARCH}" == "aarch64" ]; then
|
||||
frpFile="frp_${frpVersion}_linux_arm64.7z"
|
||||
else
|
||||
echo -e $HR
|
||||
echo "错误:不支持的架构"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 下载frp
|
||||
cd ${frpPath}
|
||||
wget -T 120 -t 3 -O ${frpPath}/${frpFile} ${downloadUrl}/${frpFile}
|
||||
wget -T 20 -t 3 -O ${frpPath}/${frpFile}.checksum.txt ${downloadUrl}/${frpFile}.checksum.txt
|
||||
if ! sha256sum --status -c ${frpPath}/${frpFile}.checksum.txt; then
|
||||
echo -e $HR
|
||||
echo "错误:frp checksum 校验失败,文件可能被篡改或不完整,已终止操作"
|
||||
rm -rf ${frpPath}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 解压frp
|
||||
cd ${frpPath}
|
||||
7z x ${frpFile}
|
||||
chmod -R 700 ${frpPath}
|
||||
rm -f ${frpFile} ${frpFile}.checksum.txt
|
||||
|
||||
# 配置systemd
|
||||
cat >/etc/systemd/system/frps.service <<EOF
|
||||
[Unit]
|
||||
Description=Frp Server Service
|
||||
After=network.target syslog.target
|
||||
Wants=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
ExecStart=/www/server/frp/frps -c /www/server/frp/frps.toml
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
cat >/etc/systemd/system/frpc.service <<EOF
|
||||
[Unit]
|
||||
Description=Frp Client Service
|
||||
After=network.target syslog.target
|
||||
Wants=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
ExecStart=/www/server/frp/frpc -c /www/server/frp/frpc.toml
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable frps
|
||||
systemctl enable frpc
|
||||
systemctl start frps
|
||||
systemctl start frpc
|
||||
|
||||
panel writePlugin frp ${frpVersion}
|
||||
echo -e "${HR}\nfrp 安装完成\n${HR}"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user