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

feat: 添加2fa,登录超时,绑定域名、IP、UA的设置字段

This commit is contained in:
2025-05-12 22:45:36 +08:00
parent 3fd768a99c
commit 71d9151fa0
4 changed files with 153 additions and 27 deletions

View File

@@ -19,6 +19,12 @@ const (
SettingKeyMySQLRootPassword SettingKey = "mysql_root_password"
SettingKeyOfflineMode SettingKey = "offline_mode"
SettingKeyAutoUpdate SettingKey = "auto_update"
SettingKeyTwoFA SettingKey = "two_fa"
SettingKeyTwoFAToken SettingKey = "two_fa_token"
SettingKeyLoginTimeout SettingKey = "login_timeout"
SettingKeyBindDomain SettingKey = "bind_domain"
SettingKeyBindIP SettingKey = "bind_ip"
SettingKeyBindUA SettingKey = "bind_ua"
)
type Setting struct {
@@ -32,7 +38,10 @@ type Setting struct {
type SettingRepo interface {
Get(key SettingKey, defaultValue ...string) (string, error)
GetBool(key SettingKey, defaultValue ...bool) (bool, error)
GetInt(key SettingKey, defaultValue ...int) (int, error)
GetSlice(key SettingKey, defaultValue ...[]string) ([]string, error)
Set(key SettingKey, value string) error
SetSlice(key SettingKey, value []string) error
Delete(key SettingKey) error
GetPanelSetting(ctx context.Context) (*request.PanelSetting, error)
UpdatePanelSetting(ctx context.Context, setting *request.PanelSetting) (bool, error)

View File

@@ -2,6 +2,7 @@ package data
import (
"context"
"encoding/json"
"errors"
"path/filepath"
@@ -68,6 +69,48 @@ func (r *settingRepo) GetBool(key biz.SettingKey, defaultValue ...bool) (bool, e
return cast.ToBool(setting.Value), nil
}
func (r *settingRepo) GetInt(key biz.SettingKey, defaultValue ...int) (int, error) {
setting := new(biz.Setting)
if err := r.db.Where("key = ?", key).First(setting).Error; err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
return 0, err
}
}
if setting.Value == "" && len(defaultValue) > 0 {
return defaultValue[0], nil
}
return cast.ToInt(setting.Value), nil
}
func (r *settingRepo) GetSlice(key biz.SettingKey, defaultValue ...[]string) ([]string, error) {
setting := new(biz.Setting)
if err := r.db.Where("key = ?", key).First(setting).Error; err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, err
}
}
// 设置值为空时提前返回
slice := make([]string, 0)
if setting.Value == "" {
if len(defaultValue) > 0 {
return defaultValue[0], nil
}
return slice, nil
}
if err := json.Unmarshal([]byte(setting.Value), &slice); err != nil {
return nil, err
}
if len(slice) == 0 && len(defaultValue) > 0 {
return defaultValue[0], nil
}
return slice, nil
}
func (r *settingRepo) Set(key biz.SettingKey, value string) error {
setting := new(biz.Setting)
if err := r.db.Where("key = ?", key).First(setting).Error; err != nil {
@@ -81,6 +124,28 @@ func (r *settingRepo) Set(key biz.SettingKey, value string) error {
return r.db.Save(setting).Error
}
func (r *settingRepo) SetSlice(key biz.SettingKey, value []string) error {
setting := new(biz.Setting)
if err := r.db.Where("key = ?", key).First(setting).Error; err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
}
setting.Key = key
if len(value) == 0 {
setting.Value = "[]"
} else {
b, err := json.Marshal(value)
if err != nil {
return err
}
setting.Value = string(b)
}
return r.db.Save(setting).Error
}
func (r *settingRepo) Delete(key biz.SettingKey) error {
setting := new(biz.Setting)
if err := r.db.Where("key = ?", key).Delete(setting).Error; err != nil {
@@ -103,6 +168,27 @@ func (r *settingRepo) GetPanelSetting(ctx context.Context) (*request.PanelSettin
if err != nil {
return nil, err
}
twoFA, err := r.GetBool(biz.SettingKeyTwoFA)
if err != nil {
return nil, err
}
loginTimeout, err := r.GetInt(biz.SettingKeyLoginTimeout)
if err != nil {
return nil, err
}
bindDomain, err := r.GetSlice(biz.SettingKeyBindDomain)
if err != nil {
return nil, err
}
bindIP, err := r.GetSlice(biz.SettingKeyBindIP)
if err != nil {
return nil, err
}
bindUA, err := r.GetSlice(biz.SettingKeyBindUA)
if err != nil {
return nil, err
}
websitePath, err := r.Get(biz.SettingKeyWebsitePath)
if err != nil {
return nil, err
@@ -128,19 +214,24 @@ func (r *settingRepo) GetPanelSetting(ctx context.Context) (*request.PanelSettin
}
return &request.PanelSetting{
Name: name,
Locale: r.conf.String("app.locale"),
Entrance: r.conf.String("http.entrance"),
OfflineMode: offlineMode,
AutoUpdate: autoUpdate,
WebsitePath: websitePath,
BackupPath: backupPath,
Username: user.Username,
Email: user.Email,
Port: uint(r.conf.Int("http.port")),
HTTPS: r.conf.Bool("http.tls"),
Cert: crt,
Key: key,
Name: name,
Locale: r.conf.String("app.locale"),
Entrance: r.conf.String("http.entrance"),
OfflineMode: offlineMode,
AutoUpdate: autoUpdate,
TwoFA: twoFA,
LoginTimeout: loginTimeout,
BindDomain: bindDomain,
BindIP: bindIP,
BindUA: bindUA,
WebsitePath: websitePath,
BackupPath: backupPath,
Username: user.Username,
Email: user.Email,
Port: uint(r.conf.Int("http.port")),
HTTPS: r.conf.Bool("http.tls"),
Cert: crt,
Key: key,
}, nil
}
@@ -154,6 +245,21 @@ func (r *settingRepo) UpdatePanelSetting(ctx context.Context, setting *request.P
if err := r.Set(biz.SettingKeyAutoUpdate, cast.ToString(setting.AutoUpdate)); err != nil {
return false, err
}
if err := r.Set(biz.SettingKeyLoginTimeout, cast.ToString(setting.LoginTimeout)); err != nil {
return false, err
}
if err := r.Set(biz.SettingKeyTwoFA, cast.ToString(setting.TwoFA)); err != nil {
return false, err
}
if err := r.SetSlice(biz.SettingKeyBindDomain, setting.BindDomain); err != nil {
return false, err
}
if err := r.SetSlice(biz.SettingKeyBindIP, setting.BindIP); err != nil {
return false, err
}
if err := r.SetSlice(biz.SettingKeyBindUA, setting.BindUA); err != nil {
return false, err
}
if err := r.Set(biz.SettingKeyWebsitePath, setting.WebsitePath); err != nil {
return false, err
}

View File

@@ -1,18 +1,23 @@
package request
type PanelSetting struct {
Name string `json:"name" validate:"required"`
Locale string `json:"locale" validate:"required"`
Entrance string `json:"entrance" validate:"required"`
OfflineMode bool `json:"offline_mode"`
AutoUpdate bool `json:"auto_update"`
WebsitePath string `json:"website_path" validate:"required"`
BackupPath string `json:"backup_path" validate:"required"`
Username string `json:"username" validate:"required"`
Password string `json:"password" validate:"password"`
Email string `json:"email" validate:"required"`
Port uint `json:"port" validate:"required|min:1|max:65535"`
HTTPS bool `json:"https"`
Cert string `json:"cert" validate:"required"`
Key string `json:"key" validate:"required"`
Name string `json:"name" validate:"required"`
Locale string `json:"locale" validate:"required"`
Entrance string `json:"entrance" validate:"required"`
OfflineMode bool `json:"offline_mode"`
AutoUpdate bool `json:"auto_update"`
TwoFA bool `json:"two_fa"`
LoginTimeout int `json:"login_timeout" validate:"required|min:10|max:43200"` // 登录超时,单位:分
BindDomain []string `json:"bind_domain"`
BindIP []string `json:"bind_ip"`
BindUA []string `json:"bind_ua"`
WebsitePath string `json:"website_path" validate:"required"`
BackupPath string `json:"backup_path" validate:"required"`
Username string `json:"username" validate:"required"`
Password string `json:"password" validate:"password"`
Email string `json:"email" validate:"required"`
Port uint `json:"port" validate:"required|min:1|max:65535"`
HTTPS bool `json:"https"`
Cert string `json:"cert" validate:"required"`
Key string `json:"key" validate:"required"`
}

View File

@@ -825,6 +825,12 @@ func (s *CliService) Init(ctx context.Context, cmd *cli.Command) error {
{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.SettingKeyLoginTimeout, Value: "720"},
{Key: biz.SettingKeyBindDomain, Value: "[]"},
{Key: biz.SettingKeyBindIP, Value: "[]"},
{Key: biz.SettingKeyBindUA, Value: "[]"},
}
if err := s.db.Create(&settings).Error; err != nil {
return errors.New(s.t.Get("Initialization failed: %v", err))