mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 03:07:20 +08:00
feat: 添加API和更新渠道的设置字段
This commit is contained in:
4
go.mod
4
go.mod
@@ -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
7
go.sum
@@ -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=
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user