You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
OneAuth/models/setting.go

206 lines
8.3 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

//
// Copyright (C) 2024 veypi <i@veypi.com>
// 2025-03-04 16:08:06
// Distributed under terms of the MIT license.
//
package models
import (
"encoding/json"
"fmt"
"strconv"
"github.com/veypi/vbase/cfg"
"github.com/veypi/vigo"
)
// Setting 系统配置表(线上配置,存储在数据库)
type Setting struct {
vigo.Model
Key string `gorm:"uniqueIndex;size:100;not null" json:"key"`
Value string `gorm:"type:text" json:"value"`
Type string `gorm:"size:20;default:'string'" json:"type"` // string/int/bool/json
Category string `gorm:"index;size:50" json:"category"`
Desc string `gorm:"size:200" json:"desc"`
UpdatedBy string `gorm:"size:36" json:"updated_by"`
}
// TableName 表名
func (Setting) TableName() string {
return "settings"
}
// 配置分类常量
const (
SettingCategoryAuth = "auth"
SettingCategoryEmail = "email"
SettingCategorySMS = "sms"
SettingCategorySecurity = "security"
SettingCategoryOAuth = "oauth"
SettingCategoryApp = "app"
)
// 配置键常量
const (
// 应用配置
SettingAppName = "app.name"
SettingAppID = "app.id"
// JWT 配置
SettingJWTSecret = "jwt.secret"
SettingJWTAccessExpiry = "jwt.access_expiry" // 单位:秒
SettingJWTRefreshExpiry = "jwt.refresh_expiry" // 单位:秒
SettingJWTIssuer = "jwt.issuer"
// 登录注册
SettingAuthRegRequireEmail = "auth.reg.require_email"
SettingAuthRegRequirePhone = "auth.reg.require_phone"
SettingAuthLoginMethods = "auth.login.methods" // json: ["password", "email_code", "phone_code"]
SettingAuthPasswordFields = "auth.login.password_fields" // json: ["username", "email", "phone"]
// 安全/验证码
SettingSecurityBcryptCost = "security.bcrypt_cost"
SettingSecurityMaxLoginAttempts = "security.max_login_attempts"
SettingSecurityCaptchaEnabled = "security.captcha_enabled"
SettingCodeExpiry = "code.expiry" // 分钟
SettingCodeLength = "code.length"
SettingCodeMaxAttempt = "code.max_attempt"
SettingCodeSendInterval = "code.send_interval" // 秒
SettingCodeMaxDailyCount = "code.max_daily_count"
// 邮件配置
SettingEmailEnabled = "email.enabled"
SettingEmailProvider = "email.provider" // smtp/sendgrid
SettingEmailSMTPHost = "email.smtp.host"
SettingEmailSMTPPort = "email.smtp.port"
SettingEmailSMTPUser = "email.smtp.user"
SettingEmailSMTPPass = "email.smtp.pass"
SettingEmailFrom = "email.from"
SettingEmailFromName = "email.from_name"
// 短信配置
SettingSMSEnabled = "sms.enabled"
SettingSMSProvider = "sms.provider" // aliyun/tencent
SettingSMSAccessKey = "sms.access_key"
SettingSMSAccessSecret = "sms.access_secret"
SettingSMSSignName = "sms.sign_name"
SettingSMSTemplateCode = "sms.template_code"
SettingSMSEndpoint = "sms.endpoint"
)
// 默认配置值
var defaultSettings = []Setting{
// 应用
{Key: SettingAppName, Value: "VBase IAM", Type: "string", Category: SettingCategoryApp, Desc: "应用名称"},
{Key: SettingAppID, Value: "vbase", Type: "string", Category: SettingCategoryApp, Desc: "应用标识"},
// JWT
{Key: SettingJWTSecret, Value: "", Type: "string", Category: SettingCategorySecurity, Desc: "JWT密钥为空则使用本地key配置"},
{Key: SettingJWTAccessExpiry, Value: "3600", Type: "int", Category: SettingCategorySecurity, Desc: "Access Token有效期(秒)"},
{Key: SettingJWTRefreshExpiry, Value: "2592000", Type: "int", Category: SettingCategorySecurity, Desc: "Refresh Token有效期(秒)"},
{Key: SettingJWTIssuer, Value: "vbase", Type: "string", Category: SettingCategorySecurity, Desc: "JWT签发者"},
// 登录注册
{Key: SettingAuthRegRequireEmail, Value: "false", Type: "bool", Category: SettingCategoryAuth, Desc: "注册是否要求邮箱"},
{Key: SettingAuthRegRequirePhone, Value: "false", Type: "bool", Category: SettingCategoryAuth, Desc: "注册是否要求手机号"},
{Key: SettingAuthLoginMethods, Value: `["password"]`, Type: "json", Category: SettingCategoryAuth, Desc: "启用的登录方式"},
{Key: SettingAuthPasswordFields, Value: `["username"]`, Type: "json", Category: SettingCategoryAuth, Desc: "密码登录支持的身份标识"},
// 安全
{Key: SettingSecurityBcryptCost, Value: "12", Type: "int", Category: SettingCategorySecurity, Desc: "bcrypt加密强度"},
{Key: SettingSecurityMaxLoginAttempts, Value: "5", Type: "int", Category: SettingCategorySecurity, Desc: "最大登录尝试次数"},
{Key: SettingSecurityCaptchaEnabled, Value: "true", Type: "bool", Category: SettingCategorySecurity, Desc: "是否启用验证码"},
// 验证码
{Key: SettingCodeExpiry, Value: "5", Type: "int", Category: SettingCategorySecurity, Desc: "验证码有效期(分钟)"},
{Key: SettingCodeLength, Value: "6", Type: "int", Category: SettingCategorySecurity, Desc: "验证码长度"},
{Key: SettingCodeMaxAttempt, Value: "3", Type: "int", Category: SettingCategorySecurity, Desc: "验证码最大尝试次数"},
{Key: SettingCodeSendInterval, Value: "60", Type: "int", Category: SettingCategorySecurity, Desc: "发送间隔(秒)"},
{Key: SettingCodeMaxDailyCount, Value: "100", Type: "int", Category: SettingCategorySecurity, Desc: "单日最大发送次数(0禁用,-1不限制)"},
// 邮件(默认关闭)
{Key: SettingEmailEnabled, Value: "false", Type: "bool", Category: SettingCategoryEmail, Desc: "是否启用邮件服务"},
{Key: SettingEmailProvider, Value: "smtp", Type: "string", Category: SettingCategoryEmail, Desc: "邮件服务商"},
{Key: SettingEmailSMTPHost, Value: "", Type: "string", Category: SettingCategoryEmail, Desc: "SMTP服务器"},
{Key: SettingEmailSMTPPort, Value: "587", Type: "int", Category: SettingCategoryEmail, Desc: "SMTP端口"},
{Key: SettingEmailSMTPUser, Value: "", Type: "string", Category: SettingCategoryEmail, Desc: "SMTP用户名"},
{Key: SettingEmailSMTPPass, Value: "", Type: "string", Category: SettingCategoryEmail, Desc: "SMTP密码"},
{Key: SettingEmailFrom, Value: "", Type: "string", Category: SettingCategoryEmail, Desc: "发件人邮箱"},
{Key: SettingEmailFromName, Value: "VBase", Type: "string", Category: SettingCategoryEmail, Desc: "发件人显示名"},
// 短信(默认关闭)
{Key: SettingSMSEnabled, Value: "false", Type: "bool", Category: SettingCategorySMS, Desc: "是否启用短信服务"},
{Key: SettingSMSProvider, Value: "aliyun", Type: "string", Category: SettingCategorySMS, Desc: "短信服务商"},
{Key: SettingSMSAccessKey, Value: "", Type: "string", Category: SettingCategorySMS, Desc: "AccessKey ID"},
{Key: SettingSMSAccessSecret, Value: "", Type: "string", Category: SettingCategorySMS, Desc: "AccessKey Secret"},
{Key: SettingSMSSignName, Value: "", Type: "string", Category: SettingCategorySMS, Desc: "短信签名"},
{Key: SettingSMSTemplateCode, Value: "", Type: "string", Category: SettingCategorySMS, Desc: "验证码模板CODE"},
{Key: SettingSMSEndpoint, Value: "", Type: "string", Category: SettingCategorySMS, Desc: "自定义接入点"},
}
// InitSettings 初始化默认配置
func InitSettings() error {
db := cfg.DB()
for _, s := range defaultSettings {
var count int64
if err := db.Model(&Setting{}).Where("`key` = ?", s.Key).Count(&count).Error; err != nil {
return err
}
if count == 0 {
if err := db.Create(&s).Error; err != nil {
return fmt.Errorf("init setting %s failed: %w", s.Key, err)
}
}
}
return nil
}
// GetSetting 获取配置值
func GetSetting(key string) (string, error) {
var s Setting
if err := cfg.DB().Where("`key` = ?", key).First(&s).Error; err != nil {
return "", err
}
return s.Value, nil
}
// GetSettingBool 获取布尔配置
func GetSettingBool(key string) (bool, error) {
val, err := GetSetting(key)
if err != nil {
return false, err
}
return strconv.ParseBool(val)
}
// GetSettingInt 获取整数配置
func GetSettingInt(key string) (int, error) {
val, err := GetSetting(key)
if err != nil {
return 0, err
}
return strconv.Atoi(val)
}
// GetSettingJSON 获取 JSON 配置
func GetSettingJSON(key string, v interface{}) error {
val, err := GetSetting(key)
if err != nil {
return err
}
return json.Unmarshal([]byte(val), v)
}
// SetSetting 设置配置值
func SetSetting(key, value, updatedBy string) error {
var s Setting
db := cfg.DB()
if err := db.Where("`key` = ?", key).First(&s).Error; err != nil {
return err
}
s.Value = value
s.UpdatedBy = updatedBy
return db.Save(&s).Error
}