refactor: Rename Config to Global and simplify app initialization

- Rename cfg.Config to cfg.Global for consistency
    - Simplify cli/main.go to use vbase.App.Run() pattern
    - Update init.go to create app with vigo.New and Init function
    - Update all references from cfg.Config to cfg.Global across api, libs, models, and tests
    - Fix VBase constructor parameter order in ui/vbase.js
    - Update ui/env.js to use new VBase('vb', '/') initialization
master
veypi 5 days ago
parent 0b22d2c2c8
commit df0f7f047a

@ -228,7 +228,7 @@ func login(x *vigo.X, req *LoginRequest) (*AuthResponse, error) {
Type: "access",
DeviceInfo: x.Request.UserAgent(),
IP: x.GetRemoteIP(),
ExpiresAt: time.Now().Add(cfg.Config.JWT.AccessExpiry),
ExpiresAt: time.Now().Add(cfg.Global.JWT.AccessExpiry),
}
cfg.DB().Create(session)
@ -323,7 +323,7 @@ func refresh(x *vigo.X, req *RefreshRequest) (*AuthResponse, error) {
Type: "access",
DeviceInfo: x.Request.UserAgent(),
IP: x.GetRemoteIP(),
ExpiresAt: time.Now().Add(cfg.Config.JWT.AccessExpiry),
ExpiresAt: time.Now().Add(cfg.Global.JWT.AccessExpiry),
}
cfg.DB().Create(session)

@ -452,7 +452,7 @@ func exchangeGeneric(provider models.OAuthProvider, code string) (*ThirdPartyUse
// 解密 ClientSecret
clientSecret := provider.ClientSecret
if clientSecret != "" {
decrypted, err := cfg.Config.Key.Decrypt(clientSecret)
decrypted, err := cfg.Global.Key.Decrypt(clientSecret)
if err == nil {
clientSecret = decrypted
}

@ -30,7 +30,7 @@ func create(x *vigo.X, req *models.OAuthProvider) (*models.OAuthProvider, error)
// 加密 ClientSecret
if req.ClientSecret != "" {
encrypted, err := cfg.Config.Key.Encrypt(req.ClientSecret)
encrypted, err := cfg.Global.Key.Encrypt(req.ClientSecret)
if err != nil {
return nil, vigo.ErrInternalServer.WithString("failed to encrypt client secret")
}

@ -39,7 +39,7 @@ func update(x *vigo.X, req *UpdateRequest) (*models.OAuthProvider, error) {
// 如果提供了新的 ClientSecret则加密否则保留原值
if req.OAuthProvider.ClientSecret != "" {
encrypted, err := cfg.Config.Key.Encrypt(req.OAuthProvider.ClientSecret)
encrypted, err := cfg.Global.Key.Encrypt(req.OAuthProvider.ClientSecret)
if err != nil {
return nil, vigo.ErrInternalServer.WithString("failed to encrypt client secret")
}

@ -50,8 +50,8 @@ type InitAdminConfig struct {
Email string `json:"email" usage:"管理员邮箱"`
}
// Config 全局配置实例
var Config = &Options{
// Global全局配置实例
var Global = &Options{
DB: config.Database{
Type: "mysql",
DSN: "root:123456@tcp(127.0.0.1:3306)/vbase?charset=utf8&parseTime=True&loc=Local",
@ -74,4 +74,4 @@ var Config = &Options{
},
}
var DB = Config.DB.Client
var DB = Global.DB.Client

@ -9,50 +9,8 @@ package main
import (
"github.com/veypi/vbase"
"github.com/veypi/vbase/cfg"
"github.com/veypi/vbase/models"
"github.com/veypi/vigo"
"github.com/veypi/vigo/contrib/event"
"github.com/veypi/vigo/flags"
"github.com/veypi/vigo/logv"
)
var cliOpts = &struct {
Host string `json:"host"`
Port int `json:"port" short:"p"`
*cfg.Options
}{
Host: "0.0.0.0",
Port: 4000,
Options: cfg.Config,
}
var (
cmdMain = flags.New("app", "the backend server of app", cliOpts)
cmdDB = cmdMain.SubCommand("db", "database operations")
)
func init() {
cmdMain.Command = runWeb
cmdDB.SubCommand("migrate", "migrate database").Command = models.Migrate
cmdDB.SubCommand("drop", "drop database").Command = models.Drop
}
func main() {
cmdMain.Parse()
err := cmdMain.Run()
if err != nil {
logv.Warn().Msg(err.Error())
}
}
func runWeb() error {
models.Migrate()
event.Start()
server, err := vigo.New(vigo.WithHost(cliOpts.Host), vigo.WithPort(cliOpts.Port))
if err != nil {
return err
}
server.SetRouter(vbase.Router)
return server.Run()
panic(vbase.App.Run())
}

@ -12,6 +12,7 @@ import (
"github.com/veypi/vbase/api"
"github.com/veypi/vbase/auth"
"github.com/veypi/vbase/cfg"
"github.com/veypi/vbase/models"
"github.com/veypi/vhtml"
vhtmlui "github.com/veypi/vhtml-ui"
"github.com/veypi/vigo"
@ -21,7 +22,6 @@ var Router = vigo.NewRouter()
var (
Auth = auth.Factory
Config = cfg.Config
AuthMiddleware = auth.AuthMiddleware
)
@ -34,3 +34,9 @@ func init() {
Router.Extend("vhtml", vhtml.Router)
vhtml.WrapUI(Router, uifs)
}
var App = vigo.New("vbase", Router, cfg.Global, Init)
func Init() error {
return models.Migrate()
}

@ -23,14 +23,14 @@ var (
// Init 初始化Redis连接
func Init() error {
if cfg.Config.Redis.Addr == "" || cfg.Config.Redis.Addr == "memory" {
if cfg.Global.Redis.Addr == "" || cfg.Global.Redis.Addr == "memory" {
return nil
}
Client = redis.NewClient(&redis.Options{
Addr: cfg.Config.Redis.Addr,
Password: cfg.Config.Redis.Password,
DB: cfg.Config.Redis.DB,
Addr: cfg.Global.Redis.Addr,
Password: cfg.Global.Redis.Password,
DB: cfg.Global.Redis.DB,
})
if err := Client.Ping(Ctx).Err(); err != nil {
@ -42,7 +42,7 @@ func Init() error {
// IsEnabled 是否启用缓存
func IsEnabled() bool {
return cfg.Config.Redis.Addr != "" && cfg.Config.Redis.Addr != "memory" && Client != nil
return cfg.Global.Redis.Addr != "" && cfg.Global.Redis.Addr != "memory" && Client != nil
}
// Get 获取字符串值

@ -68,7 +68,7 @@ func GenerateTokenPair(userID, username, nickname, avatar, email string, orgs []
AccessToken: accessToken,
RefreshToken: refreshToken,
TokenType: "Bearer",
ExpiresIn: int(cfg.Config.JWT.AccessExpiry.Seconds()),
ExpiresIn: int(cfg.Global.JWT.AccessExpiry.Seconds()),
}, nil
}
@ -78,12 +78,12 @@ func GenerateAccessToken(userID, username, nickname, avatar, email string, orgs
claims := Claims{
RegisteredClaims: jwt.RegisteredClaims{
ID: uuid.New().String(), // jti
Issuer: cfg.Config.JWT.Issuer,
Issuer: cfg.Global.JWT.Issuer,
Subject: userID,
Audience: jwt.ClaimStrings{"vbase"},
IssuedAt: jwt.NewNumericDate(now),
NotBefore: jwt.NewNumericDate(now),
ExpiresAt: jwt.NewNumericDate(now.Add(cfg.Config.JWT.AccessExpiry)),
ExpiresAt: jwt.NewNumericDate(now.Add(cfg.Global.JWT.AccessExpiry)),
},
UserID: userID,
Username: username,
@ -95,7 +95,7 @@ func GenerateAccessToken(userID, username, nickname, avatar, email string, orgs
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(cfg.Config.JWT.Secret))
return token.SignedString([]byte(cfg.Global.JWT.Secret))
}
// GenerateRefreshToken 生成刷新令牌
@ -104,17 +104,17 @@ func GenerateRefreshToken(userID string) (string, error) {
claims := Claims{
RegisteredClaims: jwt.RegisteredClaims{
ID: uuid.New().String(),
Issuer: cfg.Config.JWT.Issuer,
Issuer: cfg.Global.JWT.Issuer,
Subject: userID,
IssuedAt: jwt.NewNumericDate(now),
ExpiresAt: jwt.NewNumericDate(now.Add(cfg.Config.JWT.RefreshExpiry)),
ExpiresAt: jwt.NewNumericDate(now.Add(cfg.Global.JWT.RefreshExpiry)),
},
UserID: userID,
Type: "refresh",
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(cfg.Config.JWT.Secret))
return token.SignedString([]byte(cfg.Global.JWT.Secret))
}
// ParseToken 解析Token
@ -123,9 +123,8 @@ func ParseToken(tokenString string) (*Claims, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return []byte(cfg.Config.JWT.Secret), nil
return []byte(cfg.Global.JWT.Secret), nil
})
if err != nil {
if errors.Is(err, jwt.ErrTokenExpired) {
return nil, ErrExpiredToken

@ -72,7 +72,7 @@ func initAdminUser() error {
}
// 检查 init_admin 配置
adminCfg := cfg.Config.InitAdmin
adminCfg := cfg.Global.InitAdmin
if adminCfg.Username == "" || adminCfg.Password == "" {
// 未配置初始管理员,跳过
return nil

@ -44,12 +44,12 @@ func TestMain(m *testing.M) {
func setup() {
// Configure for testing
// Use in-memory SQLite database
cfg.Config.DB = config.Database{
cfg.Global.DB = config.Database{
Type: "sqlite",
DSN: TestDBFile,
}
// Use mock/memory Redis
cfg.Config.Redis = config.Redis{
cfg.Global.Redis = config.Redis{
Addr: "memory",
}
// Initialize DB connection and run migrations

@ -11,7 +11,8 @@ export default async ($env) => {
}
// Initialize VBase Service
const vbase = new VBase(''); // Relative path
const vbase = new VBase('vb', '/'); // Relative path
console.log(vbase)
$env.$vbase = vbase;
// Wrap Axios

@ -41,7 +41,7 @@
<form @submit.prevent="handleLogin" style="display: grid; gap: 16px;">
<v-input label="Username" v:value="username" required placeholder="Enter username"></v-input>
<v-input label="Password" type="password" v:value="password" required placeholder="Enter password"></v-input>
<v-btn type="submit" color="primary" block style="margin-top: 8px;">{{ $t('auth.login') }}</v-btn>
</form>

@ -1,8 +1,14 @@
class VBase {
constructor(baseURL, scope) {
if (!baseURL) throw new Error('VBase: baseURL is required');
constructor(scope, baseURL) {
if (!scope) throw new Error('VBase: scope is required');
if (!baseURL) throw new Error('VBase: baseURL is required');
if (!baseURL) {
baseURL = ''
}
if (baseURL === '' || baseURL === '/') {
baseURL = window.location.origin
}
this.baseURL = baseURL;
this.scope = scope;

Loading…
Cancel
Save