mirror of
https://github.com/acepanel/panel.git
synced 2026-02-07 10:37:14 +08:00
feat: 数据库同步及fail2ban重构
This commit is contained in:
2
go.mod
2
go.mod
@@ -35,6 +35,7 @@ require (
|
||||
github.com/mholt/acmez/v2 v2.0.3
|
||||
github.com/orandin/slog-gorm v1.4.0
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/samber/do/v2 v2.0.0-beta.7
|
||||
github.com/samber/lo v1.47.0
|
||||
github.com/sethvargo/go-limiter v1.0.0
|
||||
github.com/shirou/gopsutil v2.21.11+incompatible
|
||||
@@ -76,6 +77,7 @@ require (
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/samber/go-type-to-string v1.4.0 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1033 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1033 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.14 // indirect
|
||||
|
||||
4
go.sum
4
go.sum
@@ -130,6 +130,10 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/samber/do/v2 v2.0.0-beta.7 h1:tmdLOVSCbTA6uGWLU5poi/nZvMRh5QxXFJ9vHytU+Jk=
|
||||
github.com/samber/do/v2 v2.0.0-beta.7/go.mod h1:+LpV3vu4L81Q1JMZNSkMvSkW9lt4e5eJoXoZHkeBS4c=
|
||||
github.com/samber/go-type-to-string v1.4.0 h1:KXphToZgiFdnJQxryU25brhlh/CqY/cwJVeX2rfmow0=
|
||||
github.com/samber/go-type-to-string v1.4.0/go.mod h1:jpU77vIDoIxkahknKDoEx9C8bQ1ADnh2sotZ8I4QqBU=
|
||||
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
|
||||
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
|
||||
github.com/sethvargo/go-limiter v1.0.0 h1:JqW13eWEMn0VFv86OKn8wiYJY/m250WoXdrjRV0kLe4=
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/TheTNB/panel/internal/data"
|
||||
"github.com/TheTNB/panel/internal/service"
|
||||
"github.com/TheTNB/panel/pkg/io"
|
||||
"github.com/TheTNB/panel/pkg/os"
|
||||
"github.com/TheTNB/panel/pkg/shell"
|
||||
)
|
||||
|
||||
@@ -55,7 +54,6 @@ func (s *Service) List(w http.ResponseWriter, r *http.Request) {
|
||||
continue
|
||||
}
|
||||
jailEnabled := strings.Contains(jailRaw, "enabled = true")
|
||||
jailLogPath := regexp.MustCompile(`logpath = (.*)`).FindStringSubmatch(jailRaw)
|
||||
jailMaxRetry := regexp.MustCompile(`maxretry = (.*)`).FindStringSubmatch(jailRaw)
|
||||
jailFindTime := regexp.MustCompile(`findtime = (.*)`).FindStringSubmatch(jailRaw)
|
||||
jailBanTime := regexp.MustCompile(`bantime = (.*)`).FindStringSubmatch(jailRaw)
|
||||
@@ -63,7 +61,6 @@ func (s *Service) List(w http.ResponseWriter, r *http.Request) {
|
||||
jails = append(jails, Jail{
|
||||
Name: jailName,
|
||||
Enabled: jailEnabled,
|
||||
LogPath: jailLogPath[1],
|
||||
MaxRetry: cast.ToInt(jailMaxRetry[1]),
|
||||
FindTime: cast.ToInt(jailFindTime[1]),
|
||||
BanTime: cast.ToInt(jailBanTime[1]),
|
||||
@@ -128,7 +125,6 @@ port = ` + ports + `
|
||||
maxretry = ` + jailMaxRetry + `
|
||||
findtime = ` + jailFindTime + `
|
||||
bantime = ` + jailBanTime + `
|
||||
action = %(action_mwl)s
|
||||
logpath = ` + app.Root + `/wwwlogs/` + website.Name + `.log
|
||||
# ` + jailWebsiteName + `-` + jailWebsiteMode + `-END
|
||||
`
|
||||
@@ -158,25 +154,17 @@ ignoreregex =
|
||||
}
|
||||
|
||||
case "service":
|
||||
var logPath string
|
||||
var filter string
|
||||
var port string
|
||||
var err error
|
||||
switch jailName {
|
||||
case "ssh":
|
||||
if os.IsDebian() || os.IsUbuntu() {
|
||||
logPath = "/var/log/auth.log"
|
||||
} else {
|
||||
logPath = "/var/log/secure"
|
||||
}
|
||||
filter = "sshd"
|
||||
port, err = shell.Execf("cat /etc/ssh/sshd_config | grep 'Port ' | awk '{print $2}'")
|
||||
case "mysql":
|
||||
logPath = app.Root + "/server/mysql/mysql-error.log"
|
||||
filter = "mysqld-auth"
|
||||
port, err = shell.Execf("cat %s/server/mysql/conf/my.cnf | grep 'port' | head -n 1 | awk '{print $3}'", app.Root)
|
||||
case "pure-ftpd":
|
||||
logPath = "/var/log/messages"
|
||||
filter = "pure-ftpd"
|
||||
port, err = shell.Execf(`cat %s/server/pure-ftpd/etc/pure-ftpd.conf | grep "Bind" | awk '{print $2}' | awk -F "," '{print $2}'`, app.Root)
|
||||
default:
|
||||
@@ -197,8 +185,6 @@ port = ` + port + `
|
||||
maxretry = ` + jailMaxRetry + `
|
||||
findtime = ` + jailFindTime + `
|
||||
bantime = ` + jailBanTime + `
|
||||
action = %(action_mwl)s
|
||||
logpath = ` + logPath + `
|
||||
# ` + jailName + `-END
|
||||
`
|
||||
raw += rule
|
||||
@@ -208,7 +194,7 @@ logpath = ` + logPath + `
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := shell.Execf("fail2ban-client reload"); err != nil {
|
||||
if _, err = shell.Execf("fail2ban-client reload"); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "重载配置失败")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package fail2ban
|
||||
type Jail struct {
|
||||
Name string `json:"name"`
|
||||
Enabled bool `json:"enabled"`
|
||||
LogPath string `json:"log_path"`
|
||||
MaxRetry int `json:"max_retry"`
|
||||
FindTime int `json:"find_time"`
|
||||
BanTime int `json:"ban_time"`
|
||||
|
||||
@@ -15,7 +15,6 @@ func init() {
|
||||
r.Get("/load", service.Load)
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
r.Get("/errorLog", service.ErrorLog)
|
||||
r.Post("/clearErrorLog", service.ClearErrorLog)
|
||||
r.Get("/slowLog", service.SlowLog)
|
||||
r.Post("/clearSlowLog", service.ClearSlowLog)
|
||||
|
||||
@@ -142,14 +142,9 @@ func (s *Service) Load(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, load)
|
||||
}
|
||||
|
||||
// ErrorLog 获取错误日志
|
||||
func (s *Service) ErrorLog(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, fmt.Sprintf("%s/server/mysql/mysql-error.log", app.Root))
|
||||
}
|
||||
|
||||
// ClearErrorLog 清空错误日志
|
||||
func (s *Service) ClearErrorLog(w http.ResponseWriter, r *http.Request) {
|
||||
if _, err := shell.Execf("echo '' > %s/server/mysql/mysql-error.log", app.Root); err != nil {
|
||||
if err := systemctl.LogsClear("mysqld"); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -66,4 +66,5 @@ type DatabaseRepo interface {
|
||||
Create(req *request.DatabaseCreate) error
|
||||
Update(req *request.DatabaseUpdate) error
|
||||
Delete(id uint) error
|
||||
Add(serverID uint, name string) error
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/expr-lang/expr"
|
||||
"github.com/go-rat/utils/collect"
|
||||
"github.com/hashicorp/go-version"
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
@@ -19,21 +20,15 @@ import (
|
||||
)
|
||||
|
||||
type appRepo struct {
|
||||
cacheRepo biz.CacheRepo
|
||||
taskRepo biz.TaskRepo
|
||||
api *api.API
|
||||
api *api.API
|
||||
}
|
||||
|
||||
func NewAppRepo() biz.AppRepo {
|
||||
return &appRepo{
|
||||
cacheRepo: NewCacheRepo(),
|
||||
taskRepo: NewTaskRepo(),
|
||||
api: api.NewAPI(app.Version),
|
||||
}
|
||||
return do.MustInvoke[biz.AppRepo](injector)
|
||||
}
|
||||
|
||||
func (r *appRepo) All() api.Apps {
|
||||
cached, err := r.cacheRepo.Get(biz.CacheKeyApps)
|
||||
cached, err := NewCacheRepo().Get(biz.CacheKeyApps)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -190,7 +185,7 @@ func (r *appRepo) Install(channel, slug string) error {
|
||||
task.Shell = fmt.Sprintf(`curl -fsLm 10 --retry 3 "%s" | bash -s -- "%s" "%s" >> /tmp/%s.log 2>&1`, shellUrl, shellChannel, shellVersion, item.Slug)
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
|
||||
return r.taskRepo.Push(task)
|
||||
return NewTaskRepo().Push(task)
|
||||
}
|
||||
|
||||
func (r *appRepo) UnInstall(slug string) error {
|
||||
@@ -245,7 +240,7 @@ func (r *appRepo) UnInstall(slug string) error {
|
||||
task.Shell = fmt.Sprintf(`curl -fsLm 10 --retry 3 "%s" | bash -s -- "%s" "%s" >> /tmp/%s.log 2>&1`, shellUrl, shellChannel, shellVersion, item.Slug)
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
|
||||
return r.taskRepo.Push(task)
|
||||
return NewTaskRepo().Push(task)
|
||||
}
|
||||
|
||||
func (r *appRepo) Update(slug string) error {
|
||||
@@ -300,7 +295,7 @@ func (r *appRepo) Update(slug string) error {
|
||||
task.Shell = fmt.Sprintf(`curl -fsLm 10 --retry 3 "%s" | bash -s -- "%s" "%s" >> /tmp/%s.log 2>&1`, shellUrl, shellChannel, shellVersion, item.Slug)
|
||||
task.Log = "/tmp/" + item.Slug + ".log"
|
||||
|
||||
return r.taskRepo.Push(task)
|
||||
return NewTaskRepo().Push(task)
|
||||
}
|
||||
|
||||
func (r *appRepo) UpdateShow(slug string, show bool) error {
|
||||
@@ -331,7 +326,7 @@ func (r *appRepo) UpdateCache() error {
|
||||
return err
|
||||
}
|
||||
|
||||
return r.cacheRepo.Set(biz.CacheKeyApps, string(encoded))
|
||||
return NewCacheRepo().Set(biz.CacheKeyApps, string(encoded))
|
||||
}
|
||||
|
||||
func (r *appRepo) preCheck(app *api.App) error {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/shirou/gopsutil/disk"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
@@ -20,16 +21,10 @@ import (
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
type backupRepo struct {
|
||||
setting biz.SettingRepo
|
||||
website biz.WebsiteRepo
|
||||
}
|
||||
type backupRepo struct{}
|
||||
|
||||
func NewBackupRepo() biz.BackupRepo {
|
||||
return &backupRepo{
|
||||
setting: NewSettingRepo(),
|
||||
website: NewWebsiteRepo(),
|
||||
}
|
||||
return do.MustInvoke[biz.BackupRepo](injector)
|
||||
}
|
||||
|
||||
// List 备份列表
|
||||
@@ -197,7 +192,7 @@ func (r *backupRepo) ClearExpired(path, prefix string, save int) error {
|
||||
|
||||
// GetPath 获取备份路径
|
||||
func (r *backupRepo) GetPath(typ biz.BackupType) (string, error) {
|
||||
backupPath, err := r.setting.Get(biz.SettingKeyBackupPath)
|
||||
backupPath, err := NewSettingRepo().Get(biz.SettingKeyBackupPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -217,7 +212,7 @@ func (r *backupRepo) GetPath(typ biz.BackupType) (string, error) {
|
||||
|
||||
// createWebsite 创建网站备份
|
||||
func (r *backupRepo) createWebsite(to string, name string) error {
|
||||
website, err := r.website.GetByName(name)
|
||||
website, err := NewWebsiteRepo().GetByName(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -241,7 +236,7 @@ func (r *backupRepo) createWebsite(to string, name string) error {
|
||||
|
||||
// createMySQL 创建 MySQL 备份
|
||||
func (r *backupRepo) createMySQL(to string, name string) error {
|
||||
rootPassword, err := r.setting.Get(biz.SettingKeyMySQLRootPassword)
|
||||
rootPassword, err := NewSettingRepo().Get(biz.SettingKeyMySQLRootPassword)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -370,7 +365,7 @@ func (r *backupRepo) restoreWebsite(backup, target string) error {
|
||||
return errors.New("备份文件不存在")
|
||||
}
|
||||
|
||||
website, err := r.website.GetByName(target)
|
||||
website, err := NewWebsiteRepo().GetByName(target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -397,7 +392,7 @@ func (r *backupRepo) restoreMySQL(backup, target string) error {
|
||||
return errors.New("备份文件不存在")
|
||||
}
|
||||
|
||||
rootPassword, err := r.setting.Get(biz.SettingKeyMySQLRootPassword)
|
||||
rootPassword, err := NewSettingRepo().Get(biz.SettingKeyMySQLRootPassword)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package data
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/samber/do/v2"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
@@ -12,7 +13,7 @@ import (
|
||||
type cacheRepo struct{}
|
||||
|
||||
func NewCacheRepo() biz.CacheRepo {
|
||||
return &cacheRepo{}
|
||||
return do.MustInvoke[biz.CacheRepo](injector)
|
||||
}
|
||||
|
||||
func (r *cacheRepo) Get(key biz.CacheKey, defaultValue ...string) (string, error) {
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/samber/do/v2"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/internal/http/request"
|
||||
@@ -24,7 +26,7 @@ type certRepo struct {
|
||||
}
|
||||
|
||||
func NewCertRepo() biz.CertRepo {
|
||||
return &certRepo{}
|
||||
return do.MustInvoke[biz.CertRepo](injector)
|
||||
}
|
||||
|
||||
func (r *certRepo) List(page, limit uint) ([]*types.CertList, int64, error) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/samber/do/v2"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
@@ -18,7 +19,7 @@ import (
|
||||
type certAccountRepo struct{}
|
||||
|
||||
func NewCertAccountRepo() biz.CertAccountRepo {
|
||||
return &certAccountRepo{}
|
||||
return do.MustInvoke[biz.CertAccountRepo](injector)
|
||||
}
|
||||
|
||||
func (r certAccountRepo) List(page, limit uint) ([]*biz.CertAccount, int64, error) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"github.com/samber/do/v2"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/internal/http/request"
|
||||
@@ -9,7 +11,7 @@ import (
|
||||
type certDNSRepo struct{}
|
||||
|
||||
func NewCertDNSRepo() biz.CertDNSRepo {
|
||||
return &certDNSRepo{}
|
||||
return do.MustInvoke[biz.CertDNSRepo](injector)
|
||||
}
|
||||
|
||||
func (r certDNSRepo) List(page, limit uint) ([]*biz.CertDNS, int64, error) {
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/samber/do/v2"
|
||||
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/internal/http/request"
|
||||
@@ -22,23 +20,8 @@ type containerRepo struct {
|
||||
client *resty.Client
|
||||
}
|
||||
|
||||
func NewContainerRepo(sock ...string) biz.ContainerRepo {
|
||||
if len(sock) == 0 {
|
||||
sock = append(sock, "/var/run/docker.sock")
|
||||
}
|
||||
client := resty.New()
|
||||
client.SetTimeout(1 * time.Minute)
|
||||
client.SetRetryCount(2)
|
||||
client.SetTransport(&http.Transport{
|
||||
DialContext: func(ctx context.Context, _ string, _ string) (net.Conn, error) {
|
||||
return (&net.Dialer{}).DialContext(ctx, "unix", sock[0])
|
||||
},
|
||||
})
|
||||
client.SetBaseURL("http://d/v1.40")
|
||||
|
||||
return &containerRepo{
|
||||
client: client,
|
||||
}
|
||||
func NewContainerRepo() biz.ContainerRepo {
|
||||
return do.MustInvoke[biz.ContainerRepo](injector)
|
||||
}
|
||||
|
||||
// ListAll 列出所有容器
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/samber/do/v2"
|
||||
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/internal/http/request"
|
||||
@@ -23,23 +21,8 @@ type containerImageRepo struct {
|
||||
client *resty.Client
|
||||
}
|
||||
|
||||
func NewContainerImageRepo(sock ...string) biz.ContainerImageRepo {
|
||||
if len(sock) == 0 {
|
||||
sock = append(sock, "/var/run/docker.sock")
|
||||
}
|
||||
client := resty.New()
|
||||
client.SetTimeout(1 * time.Minute)
|
||||
client.SetRetryCount(2)
|
||||
client.SetTransport(&http.Transport{
|
||||
DialContext: func(ctx context.Context, _ string, _ string) (net.Conn, error) {
|
||||
return (&net.Dialer{}).DialContext(ctx, "unix", sock[0])
|
||||
},
|
||||
})
|
||||
client.SetBaseURL("http://d/v1.40")
|
||||
|
||||
return &containerImageRepo{
|
||||
client: client,
|
||||
}
|
||||
func NewContainerImageRepo() biz.ContainerImageRepo {
|
||||
return do.MustInvoke[biz.ContainerImageRepo](injector)
|
||||
}
|
||||
|
||||
// List 列出镜像
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/samber/do/v2"
|
||||
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/internal/http/request"
|
||||
@@ -22,23 +20,8 @@ type containerNetworkRepo struct {
|
||||
client *resty.Client
|
||||
}
|
||||
|
||||
func NewContainerNetworkRepo(sock ...string) biz.ContainerNetworkRepo {
|
||||
if len(sock) == 0 {
|
||||
sock = append(sock, "/var/run/docker.sock")
|
||||
}
|
||||
client := resty.New()
|
||||
client.SetTimeout(1 * time.Minute)
|
||||
client.SetRetryCount(2)
|
||||
client.SetTransport(&http.Transport{
|
||||
DialContext: func(ctx context.Context, _ string, _ string) (net.Conn, error) {
|
||||
return (&net.Dialer{}).DialContext(ctx, "unix", sock[0])
|
||||
},
|
||||
})
|
||||
client.SetBaseURL("http://d/v1.40")
|
||||
|
||||
return &containerNetworkRepo{
|
||||
client: client,
|
||||
}
|
||||
func NewContainerNetworkRepo() biz.ContainerNetworkRepo {
|
||||
return do.MustInvoke[biz.ContainerNetworkRepo](injector)
|
||||
}
|
||||
|
||||
// List 列出网络
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/samber/do/v2"
|
||||
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/internal/http/request"
|
||||
@@ -23,23 +21,8 @@ type containerVolumeRepo struct {
|
||||
client *resty.Client
|
||||
}
|
||||
|
||||
func NewContainerVolumeRepo(sock ...string) biz.ContainerVolumeRepo {
|
||||
if len(sock) == 0 {
|
||||
sock = append(sock, "/var/run/docker.sock")
|
||||
}
|
||||
client := resty.New()
|
||||
client.SetTimeout(1 * time.Minute)
|
||||
client.SetRetryCount(2)
|
||||
client.SetTransport(&http.Transport{
|
||||
DialContext: func(ctx context.Context, _ string, _ string) (net.Conn, error) {
|
||||
return (&net.Dialer{}).DialContext(ctx, "unix", sock[0])
|
||||
},
|
||||
})
|
||||
client.SetBaseURL("http://d/v1.40")
|
||||
|
||||
return &containerVolumeRepo{
|
||||
client: client,
|
||||
}
|
||||
func NewContainerVolumeRepo() biz.ContainerVolumeRepo {
|
||||
return do.MustInvoke[biz.ContainerVolumeRepo](injector)
|
||||
}
|
||||
|
||||
// List 列出存储卷
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-rat/utils/str"
|
||||
"github.com/samber/do/v2"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
@@ -18,14 +19,10 @@ import (
|
||||
"github.com/TheTNB/panel/pkg/systemctl"
|
||||
)
|
||||
|
||||
type cronRepo struct {
|
||||
settingRepo biz.SettingRepo
|
||||
}
|
||||
type cronRepo struct{}
|
||||
|
||||
func NewCronRepo() biz.CronRepo {
|
||||
return &cronRepo{
|
||||
settingRepo: NewSettingRepo(),
|
||||
}
|
||||
return do.MustInvoke[biz.CronRepo](injector)
|
||||
}
|
||||
|
||||
func (r *cronRepo) Count() (int64, error) {
|
||||
|
||||
@@ -3,20 +3,18 @@ package data
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/samber/do/v2"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/internal/http/request"
|
||||
"github.com/TheTNB/panel/pkg/db"
|
||||
)
|
||||
|
||||
type databaseRepo struct {
|
||||
databaseServer biz.DatabaseServerRepo
|
||||
}
|
||||
type databaseRepo struct{}
|
||||
|
||||
func NewDatabaseRepo() biz.DatabaseRepo {
|
||||
return &databaseRepo{
|
||||
databaseServer: NewDatabaseServerRepo(),
|
||||
}
|
||||
return do.MustInvoke[biz.DatabaseRepo](injector)
|
||||
}
|
||||
|
||||
func (r databaseRepo) Count() (int64, error) {
|
||||
@@ -45,7 +43,7 @@ func (r databaseRepo) Get(id uint) (*biz.Database, error) {
|
||||
}
|
||||
|
||||
func (r databaseRepo) Create(req *request.DatabaseCreate) error {
|
||||
server, err := r.databaseServer.Get(req.ServerID)
|
||||
server, err := NewDatabaseServerRepo().Get(req.ServerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -107,3 +105,15 @@ func (r databaseRepo) Update(req *request.DatabaseUpdate) error {
|
||||
func (r databaseRepo) Delete(id uint) error {
|
||||
return app.Orm.Delete(&biz.Database{}, id).Error
|
||||
}
|
||||
|
||||
func (r databaseRepo) Add(serverID uint, name string) error {
|
||||
database := &biz.Database{
|
||||
Name: name,
|
||||
Username: name,
|
||||
ServerID: serverID,
|
||||
Status: biz.DatabaseStatusNormal,
|
||||
Remark: "sync from server",
|
||||
}
|
||||
|
||||
return app.Orm.Create(database).Error
|
||||
}
|
||||
|
||||
@@ -6,16 +6,20 @@ import (
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/samber/do/v2"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/internal/http/request"
|
||||
"github.com/TheTNB/panel/pkg/db"
|
||||
)
|
||||
|
||||
type databaseServerRepo struct{}
|
||||
type databaseServerRepo struct {
|
||||
database biz.DatabaseRepo
|
||||
}
|
||||
|
||||
func NewDatabaseServerRepo() biz.DatabaseServerRepo {
|
||||
return &databaseServerRepo{}
|
||||
return do.MustInvoke[biz.DatabaseServerRepo](injector)
|
||||
}
|
||||
|
||||
func (r databaseServerRepo) Count() (int64, error) {
|
||||
@@ -115,11 +119,12 @@ func (r databaseServerRepo) Delete(id uint) error {
|
||||
}
|
||||
|
||||
func (r databaseServerRepo) Sync(id uint) error {
|
||||
/*server, err := r.Get(id)
|
||||
server, err := r.Get(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dbRepo := NewDatabaseRepo()
|
||||
switch server.Type {
|
||||
case biz.DatabaseTypeMysql:
|
||||
mysql, err := db.NewMySQL(server.Username, server.Password, fmt.Sprintf("%s:%d", server.Host, server.Port))
|
||||
@@ -131,18 +136,10 @@ func (r databaseServerRepo) Sync(id uint) error {
|
||||
return err
|
||||
}
|
||||
for database := range slices.Values(databases) {
|
||||
db := &biz.Database{
|
||||
Name: database.Name,
|
||||
Username: server.Username,
|
||||
Password: server.Password,
|
||||
ServerID: server.ID,
|
||||
Status: biz.DatabaseStatusInvalid,
|
||||
}
|
||||
if err := app.Orm.Where("name = ? AND server_id = ?", database.Name, server.ID).First(db).Error; err != nil {
|
||||
app.Orm.Create(db)
|
||||
if err = dbRepo.Add(id, database); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
case biz.DatabaseTypePostgresql:
|
||||
postgres, err := db.NewPostgres(server.Username, server.Password, server.Host, server.Port)
|
||||
if err != nil {
|
||||
@@ -152,7 +149,12 @@ func (r databaseServerRepo) Sync(id uint) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}*/
|
||||
for database := range slices.Values(databases) {
|
||||
if err = dbRepo.Add(id, database.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
117
internal/data/init.go
Normal file
117
internal/data/init.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-rat/utils/hash"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/samber/do/v2"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/pkg/api"
|
||||
"github.com/TheTNB/panel/pkg/os"
|
||||
)
|
||||
|
||||
var injector = do.New()
|
||||
|
||||
func init() {
|
||||
do.Provide(injector, func(i do.Injector) (biz.AppRepo, error) {
|
||||
return &appRepo{
|
||||
api: api.NewAPI(app.Version),
|
||||
}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.BackupRepo, error) {
|
||||
return &backupRepo{}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.CacheRepo, error) {
|
||||
return &cacheRepo{}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.CertRepo, error) {
|
||||
return &certRepo{}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.CertAccountRepo, error) {
|
||||
return &certAccountRepo{}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.CertDNSRepo, error) {
|
||||
return &certDNSRepo{}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.ContainerRepo, error) {
|
||||
return &containerRepo{
|
||||
client: getDockerClient("/var/run/docker.sock"),
|
||||
}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.ContainerImageRepo, error) {
|
||||
return &containerImageRepo{
|
||||
client: getDockerClient("/var/run/docker.sock"),
|
||||
}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.ContainerNetworkRepo, error) {
|
||||
return &containerNetworkRepo{
|
||||
client: getDockerClient("/var/run/docker.sock"),
|
||||
}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.ContainerVolumeRepo, error) {
|
||||
return &containerVolumeRepo{
|
||||
client: getDockerClient("/var/run/docker.sock"),
|
||||
}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.CronRepo, error) {
|
||||
return &cronRepo{}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.DatabaseServerRepo, error) {
|
||||
return &databaseServerRepo{}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.DatabaseRepo, error) {
|
||||
return &databaseRepo{}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.MonitorRepo, error) {
|
||||
return &monitorRepo{}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.SafeRepo, error) {
|
||||
var ssh string
|
||||
if os.IsRHEL() {
|
||||
ssh = "sshd"
|
||||
} else {
|
||||
ssh = "ssh"
|
||||
}
|
||||
return &safeRepo{
|
||||
ssh: ssh,
|
||||
}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.SettingRepo, error) {
|
||||
return &settingRepo{}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.SSHRepo, error) {
|
||||
return &sshRepo{}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.TaskRepo, error) {
|
||||
task := &taskRepo{}
|
||||
task.DispatchWaiting()
|
||||
return task, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.UserRepo, error) {
|
||||
return &userRepo{
|
||||
hasher: hash.NewArgon2id(),
|
||||
}, nil
|
||||
})
|
||||
do.Provide(injector, func(i do.Injector) (biz.WebsiteRepo, error) {
|
||||
return &websiteRepo{}, nil
|
||||
})
|
||||
}
|
||||
|
||||
func getDockerClient(sock string) *resty.Client {
|
||||
client := resty.New()
|
||||
client.SetTimeout(1 * time.Minute)
|
||||
client.SetRetryCount(2)
|
||||
client.SetTransport(&http.Transport{
|
||||
DialContext: func(ctx context.Context, _ string, _ string) (net.Conn, error) {
|
||||
return (&net.Dialer{}).DialContext(ctx, "unix", sock)
|
||||
},
|
||||
})
|
||||
client.SetBaseURL("http://d/v1.40")
|
||||
return client
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
@@ -11,22 +12,19 @@ import (
|
||||
"github.com/TheTNB/panel/internal/http/request"
|
||||
)
|
||||
|
||||
type monitorRepo struct {
|
||||
settingRepo biz.SettingRepo
|
||||
}
|
||||
type monitorRepo struct{}
|
||||
|
||||
func NewMonitorRepo() biz.MonitorRepo {
|
||||
return &monitorRepo{
|
||||
settingRepo: NewSettingRepo(),
|
||||
}
|
||||
return do.MustInvoke[biz.MonitorRepo](injector)
|
||||
}
|
||||
|
||||
func (r monitorRepo) GetSetting() (*request.MonitorSetting, error) {
|
||||
monitor, err := r.settingRepo.Get(biz.SettingKeyMonitor)
|
||||
repo := NewSettingRepo()
|
||||
monitor, err := repo.Get(biz.SettingKeyMonitor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
monitorDays, err := r.settingRepo.Get(biz.SettingKeyMonitorDays)
|
||||
monitorDays, err := repo.Get(biz.SettingKeyMonitorDays)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -39,10 +37,11 @@ func (r monitorRepo) GetSetting() (*request.MonitorSetting, error) {
|
||||
}
|
||||
|
||||
func (r monitorRepo) UpdateSetting(setting *request.MonitorSetting) error {
|
||||
if err := r.settingRepo.Set(biz.SettingKeyMonitor, cast.ToString(setting.Enabled)); err != nil {
|
||||
repo := NewSettingRepo()
|
||||
if err := repo.Set(biz.SettingKeyMonitor, cast.ToString(setting.Enabled)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := r.settingRepo.Set(biz.SettingKeyMonitorDays, cast.ToString(setting.Days)); err != nil {
|
||||
if err := repo.Set(biz.SettingKeyMonitorDays, cast.ToString(setting.Days)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/pkg/firewall"
|
||||
"github.com/TheTNB/panel/pkg/os"
|
||||
"github.com/TheTNB/panel/pkg/shell"
|
||||
"github.com/TheTNB/panel/pkg/systemctl"
|
||||
)
|
||||
@@ -18,16 +18,7 @@ type safeRepo struct {
|
||||
}
|
||||
|
||||
func NewSafeRepo() biz.SafeRepo {
|
||||
var ssh string
|
||||
if os.IsRHEL() {
|
||||
ssh = "sshd"
|
||||
} else {
|
||||
ssh = "ssh"
|
||||
}
|
||||
|
||||
return &safeRepo{
|
||||
ssh: ssh,
|
||||
}
|
||||
return do.MustInvoke[biz.SafeRepo](injector)
|
||||
}
|
||||
|
||||
func (r *safeRepo) GetSSH() (uint, bool, error) {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"slices"
|
||||
|
||||
"github.com/go-rat/utils/hash"
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/spf13/cast"
|
||||
"gopkg.in/yaml.v3"
|
||||
"gorm.io/gorm"
|
||||
@@ -24,14 +25,10 @@ import (
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
type settingRepo struct {
|
||||
taskRepo biz.TaskRepo
|
||||
}
|
||||
type settingRepo struct{}
|
||||
|
||||
func NewSettingRepo() biz.SettingRepo {
|
||||
return &settingRepo{
|
||||
taskRepo: NewTaskRepo(),
|
||||
}
|
||||
return do.MustInvoke[biz.SettingRepo](injector)
|
||||
}
|
||||
|
||||
func (r *settingRepo) Get(key biz.SettingKey, defaultValue ...string) (string, error) {
|
||||
@@ -170,12 +167,13 @@ func (r *settingRepo) UpdatePanelSetting(ctx context.Context, setting *request.P
|
||||
}
|
||||
|
||||
// 下面是需要需要重启的设置
|
||||
task := NewTaskRepo()
|
||||
// 面板HTTPS
|
||||
restartFlag := false
|
||||
oldCert, _ := io.Read(filepath.Join(app.Root, "panel/storage/cert.pem"))
|
||||
oldKey, _ := io.Read(filepath.Join(app.Root, "panel/storage/cert.key"))
|
||||
if oldCert != setting.Cert || oldKey != setting.Key {
|
||||
if r.taskRepo.HasRunningTask() {
|
||||
if task.HasRunningTask() {
|
||||
return false, errors.New("后台任务正在运行,禁止修改部分设置,请稍后再试")
|
||||
}
|
||||
restartFlag = true
|
||||
@@ -232,7 +230,7 @@ func (r *settingRepo) UpdatePanelSetting(ctx context.Context, setting *request.P
|
||||
return false, err
|
||||
}
|
||||
if raw != string(encoded) {
|
||||
if r.taskRepo.HasRunningTask() {
|
||||
if task.HasRunningTask() {
|
||||
return false, errors.New("后台任务正在运行,禁止修改部分设置,请稍后再试")
|
||||
}
|
||||
restartFlag = true
|
||||
|
||||
@@ -3,20 +3,18 @@ package data
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/samber/do/v2"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/internal/http/request"
|
||||
pkgssh "github.com/TheTNB/panel/pkg/ssh"
|
||||
)
|
||||
|
||||
type sshRepo struct {
|
||||
settingRepo biz.SettingRepo
|
||||
}
|
||||
type sshRepo struct{}
|
||||
|
||||
func NewSSHRepo() biz.SSHRepo {
|
||||
return &sshRepo{
|
||||
settingRepo: NewSettingRepo(),
|
||||
}
|
||||
return do.MustInvoke[biz.SSHRepo](injector)
|
||||
}
|
||||
|
||||
func (r *sshRepo) List(page, limit uint) ([]*biz.SSH, int64, error) {
|
||||
|
||||
@@ -3,21 +3,18 @@ package data
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"sync"
|
||||
|
||||
"github.com/samber/do/v2"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/internal/queuejob"
|
||||
)
|
||||
|
||||
var taskDispatchOnce sync.Once
|
||||
|
||||
type taskRepo struct{}
|
||||
|
||||
func NewTaskRepo() biz.TaskRepo {
|
||||
task := &taskRepo{}
|
||||
taskDispatchOnce.Do(task.DispatchWaiting)
|
||||
return &taskRepo{}
|
||||
return do.MustInvoke[biz.TaskRepo](injector)
|
||||
}
|
||||
|
||||
func (r *taskRepo) HasRunningTask() bool {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
|
||||
"github.com/go-rat/utils/hash"
|
||||
"github.com/samber/do/v2"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
@@ -15,9 +16,7 @@ type userRepo struct {
|
||||
}
|
||||
|
||||
func NewUserRepo() biz.UserRepo {
|
||||
return &userRepo{
|
||||
hasher: hash.NewArgon2id(),
|
||||
}
|
||||
return do.MustInvoke[biz.UserRepo](injector)
|
||||
}
|
||||
|
||||
func (r *userRepo) Create(username, password string) (*biz.User, error) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/samber/lo"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
@@ -30,7 +31,7 @@ import (
|
||||
type websiteRepo struct{}
|
||||
|
||||
func NewWebsiteRepo() biz.WebsiteRepo {
|
||||
return &websiteRepo{}
|
||||
return do.MustInvoke[biz.WebsiteRepo](injector)
|
||||
}
|
||||
|
||||
func (r *websiteRepo) UpdateDefaultConfig(req *request.WebsiteDefaultConfig) error {
|
||||
|
||||
@@ -76,6 +76,7 @@ func Http(r chi.Router) {
|
||||
r.Post("/", database.Create)
|
||||
r.Put("/{id}", database.Update)
|
||||
r.Delete("/{id}", database.Delete)
|
||||
r.Post("/{id}/sync", database.Sync)
|
||||
})
|
||||
|
||||
r.Route("/backup", func(r chi.Router) {
|
||||
|
||||
@@ -156,14 +156,14 @@ func (m *MySQL) Users() ([]types.MySQLUser, error) {
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (m *MySQL) Databases() ([]types.MySQLDatabase, error) {
|
||||
func (m *MySQL) Databases() ([]string, error) {
|
||||
rows, err := m.Query("SHOW DATABASES")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var databases []types.MySQLDatabase
|
||||
var databases []string
|
||||
for rows.Next() {
|
||||
var database string
|
||||
if err := rows.Scan(&database); err != nil {
|
||||
@@ -172,9 +172,7 @@ func (m *MySQL) Databases() ([]types.MySQLDatabase, error) {
|
||||
if slices.Contains([]string{"information_schema", "performance_schema", "mysql", "sys"}, database) {
|
||||
continue
|
||||
}
|
||||
databases = append(databases, types.MySQLDatabase{
|
||||
Name: database,
|
||||
})
|
||||
databases = append(databases, database)
|
||||
}
|
||||
return databases, nil
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ var (
|
||||
StrategyAccept Strategy = "accept" // 接受
|
||||
StrategyDrop Strategy = "drop" // 丢弃
|
||||
StrategyReject Strategy = "reject" // 拒绝
|
||||
StrategyMark Strategy = "mark" // 标记
|
||||
)
|
||||
|
||||
type Direction string
|
||||
@@ -44,7 +45,7 @@ type FireInfo struct {
|
||||
PortStart uint `json:"port_start"` // 1-65535
|
||||
PortEnd uint `json:"port_end"` // 1-65535
|
||||
Protocol Protocol `json:"protocol"` // tcp udp tcp/udp
|
||||
Strategy Strategy `json:"strategy"` // accept drop reject
|
||||
Strategy Strategy `json:"strategy"` // accept drop reject mark
|
||||
Direction Direction `json:"direction"` // in out 入站或出站
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ type Firewall struct {
|
||||
func NewFirewall() *Firewall {
|
||||
firewall := &Firewall{
|
||||
forwardListRegex: regexp.MustCompile(`^port=(\d{1,5}):proto=(.+?):toport=(\d{1,5}):toaddr=(.*)$`),
|
||||
richRuleRegex: regexp.MustCompile(`^rule family="([^"]+)"(?: .*?(source|destination) address="([^"]+)")?(?: .*?port port="([^"]+)")?(?: .*?protocol(?: value)?="([^"]+)")?.*?(accept|drop|reject)$`),
|
||||
richRuleRegex: regexp.MustCompile(`^rule family="([^"]+)"(?: .*?(source|destination) address="([^"]+)")?(?: .*?port port="([^"]+)")?(?: .*?protocol(?: value)?="([^"]+)")?.*?(accept|drop|reject|mark).*?$`),
|
||||
}
|
||||
|
||||
return firewall
|
||||
|
||||
@@ -71,3 +71,22 @@ func Disable(name string) error {
|
||||
_, err := shell.Execf("systemctl disable %s", name)
|
||||
return err
|
||||
}
|
||||
|
||||
// Logs 获取服务日志
|
||||
func Logs(name string) (string, error) {
|
||||
return shell.Execf("journalctl -u %s", name)
|
||||
}
|
||||
|
||||
// LogsTail 获取服务日志
|
||||
func LogsTail(name string, lines int) (string, error) {
|
||||
return shell.Execf("journalctl -u %s --lines %d", name, lines)
|
||||
}
|
||||
|
||||
// LogsClear 清空服务日志
|
||||
func LogsClear(name string) error {
|
||||
if _, err := shell.Execf("journalctl --rotate -u %s", name); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := shell.Execf("journalctl --vacuum-time=1s -u %s", name)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -5,7 +5,3 @@ type MySQLUser struct {
|
||||
Host string `json:"host"`
|
||||
Grants []string `json:"grants"`
|
||||
}
|
||||
|
||||
type MySQLDatabase struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
@@ -5,7 +5,11 @@ import type { LogInst } from 'naive-ui'
|
||||
const props = defineProps({
|
||||
path: {
|
||||
type: String,
|
||||
required: true
|
||||
required: false
|
||||
},
|
||||
service: {
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
})
|
||||
|
||||
@@ -14,7 +18,15 @@ const logRef = ref<LogInst | null>(null)
|
||||
let logWs: WebSocket | null = null
|
||||
|
||||
const init = async () => {
|
||||
const cmd = `tail -n 100 -f '${props.path}'`
|
||||
let cmd = ''
|
||||
if (props.path) {
|
||||
cmd = `tail -n 100 -f '${props.path}'`
|
||||
} else if (props.service) {
|
||||
cmd = `journalctl -u '${props.service}' -f`
|
||||
} else {
|
||||
window.$message.error('path 或 service 不能为空')
|
||||
return
|
||||
}
|
||||
ws.exec(cmd)
|
||||
.then((ws: WebSocket) => {
|
||||
logWs = ws
|
||||
|
||||
@@ -13,7 +13,6 @@ const currentTab = ref('status')
|
||||
const status = ref(false)
|
||||
const isEnabled = ref(false)
|
||||
const config = ref('')
|
||||
const errorLog = ref('')
|
||||
const slowLog = ref('')
|
||||
const rootPassword = ref('')
|
||||
|
||||
@@ -65,11 +64,6 @@ const getRootPassword = async () => {
|
||||
})
|
||||
}
|
||||
|
||||
const getErrorLog = async () => {
|
||||
const { data } = await mysql.errorLog()
|
||||
return data
|
||||
}
|
||||
|
||||
const getSlowLog = async () => {
|
||||
const { data } = await mysql.slowLog()
|
||||
return data
|
||||
@@ -142,9 +136,6 @@ onMounted(() => {
|
||||
getLoad().then((res) => {
|
||||
load.value = res
|
||||
})
|
||||
getErrorLog().then((res) => {
|
||||
errorLog.value = res
|
||||
})
|
||||
getSlowLog().then((res) => {
|
||||
slowLog.value = res
|
||||
})
|
||||
@@ -266,7 +257,7 @@ onMounted(() => {
|
||||
/>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="error-log" tab="错误日志">
|
||||
<realtime-log :path="errorLog" />
|
||||
<realtime-log service="mysqld" />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="slow-log" tab="慢查询日志">
|
||||
<realtime-log :path="slowLog" />
|
||||
|
||||
@@ -53,7 +53,13 @@ const columns: any = [
|
||||
NTag,
|
||||
{
|
||||
type:
|
||||
row.strategy === 'accept' ? 'success' : row.strategy === 'drop' ? 'warning' : 'error'
|
||||
row.strategy === 'accept'
|
||||
? 'success'
|
||||
: row.strategy === 'drop'
|
||||
? 'warning'
|
||||
: row.strategy === 'reject'
|
||||
? 'error'
|
||||
: 'default'
|
||||
},
|
||||
{
|
||||
default: () => {
|
||||
@@ -64,6 +70,8 @@ const columns: any = [
|
||||
return '丢弃'
|
||||
case 'reject':
|
||||
return '拒绝'
|
||||
case 'mark':
|
||||
return '标记'
|
||||
default:
|
||||
return '未知'
|
||||
}
|
||||
|
||||
@@ -87,7 +87,13 @@ const columns: any = [
|
||||
NTag,
|
||||
{
|
||||
type:
|
||||
row.strategy === 'accept' ? 'success' : row.strategy === 'drop' ? 'warning' : 'error'
|
||||
row.strategy === 'accept'
|
||||
? 'success'
|
||||
: row.strategy === 'drop'
|
||||
? 'warning'
|
||||
: row.strategy === 'reject'
|
||||
? 'error'
|
||||
: 'default'
|
||||
},
|
||||
{
|
||||
default: () => {
|
||||
@@ -98,6 +104,8 @@ const columns: any = [
|
||||
return '丢弃'
|
||||
case 'reject':
|
||||
return '拒绝'
|
||||
case 'mark':
|
||||
return '标记'
|
||||
default:
|
||||
return '未知'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user