2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 03:07:20 +08:00

feat: 添加API和更新渠道的设置字段

This commit is contained in:
2025-05-13 02:42:55 +08:00
parent 69ddca44bf
commit 715b42dfbb
6 changed files with 83 additions and 5 deletions

4
go.mod
View File

@@ -48,9 +48,10 @@ require (
github.com/ncruces/go-sqlite3 v0.25.2
github.com/ncruces/go-sqlite3/gormlite v0.24.0
github.com/orandin/slog-gorm v1.4.0
github.com/pquerna/otp v1.4.1-0.20241231231527-5971b1ef1d66
github.com/robfig/cron/v3 v3.0.1
github.com/samber/lo v1.50.0
github.com/sethvargo/go-limiter v1.0.0
github.com/sethvargo/go-limiter v1.0.1-0.20250412144437-fa26982c7e1a
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/spf13/cast v1.8.0
github.com/stretchr/testify v1.10.0
@@ -66,6 +67,7 @@ require (
require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/G-Core/gcore-dns-sdk-go v0.2.9 // indirect
github.com/boombuler/barcode v1.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect

7
go.sum
View File

@@ -31,6 +31,9 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.2 h1:79yrbttoZrLGkL/oOI8hBrUKucwOL0oOjUgEguGMcJ4=
github.com/boombuler/barcode v1.0.2/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
@@ -279,6 +282,8 @@ github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZ
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/pquerna/otp v1.4.1-0.20241231231527-5971b1ef1d66 h1:7pccJSb6/BRgd5BKejX/dgzinfq0K5HPwj35+saHuCU=
github.com/pquerna/otp v1.4.1-0.20241231231527-5971b1ef1d66/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@@ -301,6 +306,8 @@ github.com/samber/lo v1.50.0/go.mod h1:RjZyNk6WSnUFRKK6EyOhsRJMqft3G+pg7dCWHQCWv
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sethvargo/go-limiter v1.0.0 h1:JqW13eWEMn0VFv86OKn8wiYJY/m250WoXdrjRV0kLe4=
github.com/sethvargo/go-limiter v1.0.0/go.mod h1:01b6tW25Ap+MeLYBuD4aHunMrJoNO5PVUFdS9rac3II=
github.com/sethvargo/go-limiter v1.0.1-0.20250412144437-fa26982c7e1a h1:CdCoDHVynJVAQWN7ZQrAUOp0SV5TmRwNOSkF5KedDko=
github.com/sethvargo/go-limiter v1.0.1-0.20250412144437-fa26982c7e1a/go.mod h1:01b6tW25Ap+MeLYBuD4aHunMrJoNO5PVUFdS9rac3II=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=

View File

@@ -4,6 +4,8 @@ import (
"context"
"time"
"github.com/pquerna/otp"
"github.com/tnb-labs/panel/internal/http/request"
)
@@ -12,6 +14,7 @@ type SettingKey string
const (
SettingKeyName SettingKey = "name"
SettingKeyVersion SettingKey = "version"
SettingKeyChannel SettingKey = "channel"
SettingKeyMonitor SettingKey = "monitor"
SettingKeyMonitorDays SettingKey = "monitor_days"
SettingKeyBackupPath SettingKey = "backup_path"
@@ -20,11 +23,14 @@ const (
SettingKeyOfflineMode SettingKey = "offline_mode"
SettingKeyAutoUpdate SettingKey = "auto_update"
SettingKeyTwoFA SettingKey = "two_fa"
SettingKeyTwoFAToken SettingKey = "two_fa_token"
SettingKeyTwoFASecret SettingKey = "two_fa_secret"
SettingKeyLoginTimeout SettingKey = "login_timeout"
SettingKeyBindDomain SettingKey = "bind_domain"
SettingKeyBindIP SettingKey = "bind_ip"
SettingKeyBindUA SettingKey = "bind_ua"
SettingKeyAPI SettingKey = "api"
SettingKeyAPIKey SettingKey = "api_key"
SettingKeyAPIWhiteList SettingKey = "api_white_list"
)
type Setting struct {
@@ -45,4 +51,6 @@ type SettingRepo interface {
Delete(key SettingKey) error
GetPanelSetting(ctx context.Context) (*request.PanelSetting, error)
UpdatePanelSetting(ctx context.Context, setting *request.PanelSetting) (bool, error)
GenerateTwoFAKey() (*otp.Key, error)
GenerateAPIKey() (string, error)
}

View File

@@ -7,8 +7,11 @@ import (
"path/filepath"
"github.com/go-rat/utils/hash"
"github.com/go-rat/utils/str"
"github.com/knadh/koanf/v2"
"github.com/leonelquinteros/gotext"
"github.com/pquerna/otp"
"github.com/pquerna/otp/totp"
"github.com/spf13/cast"
"gopkg.in/yaml.v3"
"gorm.io/gorm"
@@ -160,6 +163,10 @@ func (r *settingRepo) GetPanelSetting(ctx context.Context) (*request.PanelSettin
if err != nil {
return nil, err
}
channel, err := r.Get(biz.SettingKeyChannel)
if err != nil {
return nil, err
}
offlineMode, err := r.GetBool(biz.SettingKeyOfflineMode)
if err != nil {
return nil, err
@@ -188,7 +195,6 @@ func (r *settingRepo) GetPanelSetting(ctx context.Context) (*request.PanelSettin
if err != nil {
return nil, err
}
websitePath, err := r.Get(biz.SettingKeyWebsitePath)
if err != nil {
return nil, err
@@ -197,6 +203,14 @@ func (r *settingRepo) GetPanelSetting(ctx context.Context) (*request.PanelSettin
if err != nil {
return nil, err
}
api, err := r.GetBool(biz.SettingKeyAPI)
if err != nil {
return nil, err
}
apiWhiteList, err := r.GetSlice(biz.SettingKeyAPIWhiteList)
if err != nil {
return nil, err
}
userID := cast.ToUint(ctx.Value("user_id"))
user := new(biz.User)
@@ -215,6 +229,7 @@ func (r *settingRepo) GetPanelSetting(ctx context.Context) (*request.PanelSettin
return &request.PanelSetting{
Name: name,
Channel: channel,
Locale: r.conf.String("app.locale"),
Entrance: r.conf.String("http.entrance"),
OfflineMode: offlineMode,
@@ -229,6 +244,8 @@ func (r *settingRepo) GetPanelSetting(ctx context.Context) (*request.PanelSettin
Username: user.Username,
Email: user.Email,
Port: uint(r.conf.Int("http.port")),
API: api,
APIWhiteList: apiWhiteList,
HTTPS: r.conf.Bool("http.tls"),
Cert: crt,
Key: key,
@@ -239,6 +256,9 @@ func (r *settingRepo) UpdatePanelSetting(ctx context.Context, setting *request.P
if err := r.Set(biz.SettingKeyName, setting.Name); err != nil {
return false, err
}
if err := r.Set(biz.SettingKeyChannel, setting.Channel); err != nil {
return false, err
}
if err := r.Set(biz.SettingKeyOfflineMode, cast.ToString(setting.OfflineMode)); err != nil {
return false, err
}
@@ -361,3 +381,37 @@ func (r *settingRepo) UpdatePanelSetting(ctx context.Context, setting *request.P
return restartFlag, nil
}
// GenerateTwoFAKey 生成两步验证密钥
func (r *settingRepo) GenerateTwoFAKey() (*otp.Key, error) {
key, err := totp.Generate(totp.GenerateOpts{
Issuer: "RatPanel",
AccountName: "admin",
SecretSize: 32,
Algorithm: otp.AlgorithmSHA256,
})
if err != nil {
return nil, err
}
if err = r.Set(biz.SettingKeyTwoFASecret, key.Secret()); err != nil {
return nil, err
}
return key, nil
}
// GenerateAPIKey 生成API密钥
func (r *settingRepo) GenerateAPIKey() (string, error) {
key := str.Random(32)
hashed, err := hash.NewArgon2id().Make(key)
if err != nil {
return "", err
}
if err = r.Set(biz.SettingKeyAPIKey, hashed); err != nil {
return "", err
}
return key, nil
}

View File

@@ -2,6 +2,7 @@ package request
type PanelSetting struct {
Name string `json:"name" validate:"required"`
Channel string `json:"channel" validate:"required|in:stable,beta"`
Locale string `json:"locale" validate:"required"`
Entrance string `json:"entrance" validate:"required"`
OfflineMode bool `json:"offline_mode"`
@@ -17,6 +18,8 @@ type PanelSetting struct {
Password string `json:"password" validate:"password"`
Email string `json:"email" validate:"required"`
Port uint `json:"port" validate:"required|min:1|max:65535"`
API bool `json:"api"`
APIWhiteList []string `json:"api_white_list"`
HTTPS bool `json:"https"`
Cert string `json:"cert" validate:"required"`
Key string `json:"key" validate:"required"`

View File

@@ -818,19 +818,23 @@ func (s *CliService) Init(ctx context.Context, cmd *cli.Command) error {
settings := []biz.Setting{
{Key: biz.SettingKeyName, Value: "耗子面板"},
{Key: biz.SettingKeyChannel, Value: "stable"},
{Key: biz.SettingKeyVersion, Value: app.Version},
{Key: biz.SettingKeyMonitor, Value: "true"},
{Key: biz.SettingKeyMonitorDays, Value: "30"},
{Key: biz.SettingKeyBackupPath, Value: filepath.Join(app.Root, "backup")},
{Key: biz.SettingKeyWebsitePath, Value: filepath.Join(app.Root, "wwwroot")},
{Key: biz.SettingKeyVersion, Value: app.Version},
{Key: biz.SettingKeyOfflineMode, Value: "false"},
{Key: biz.SettingKeyAutoUpdate, Value: "true"},
{Key: biz.SettingKeyTwoFA, Value: "false"},
{Key: biz.SettingKeyTwoFAToken, Value: ""},
{Key: biz.SettingKeyTwoFASecret, Value: ""},
{Key: biz.SettingKeyLoginTimeout, Value: "720"},
{Key: biz.SettingKeyBindDomain, Value: "[]"},
{Key: biz.SettingKeyBindIP, Value: "[]"},
{Key: biz.SettingKeyBindUA, Value: "[]"},
{Key: biz.SettingKeyAPI, Value: "false"},
{Key: biz.SettingKeyAPIKey, Value: ""},
{Key: biz.SettingKeyAPIWhiteList, Value: "[]"},
}
if err := s.db.Create(&settings).Error; err != nil {
return errors.New(s.t.Get("Initialization failed: %v", err))