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/init.go

123 lines
2.8 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>
// 2024-09-20 16:10:16
// Distributed under terms of the MIT license.
//
package models
import (
"fmt"
"time"
"github.com/veypi/vbase/cfg"
"github.com/veypi/vbase/libs/crypto"
"github.com/veypi/vigo"
"github.com/veypi/vigo/contrib/event"
)
var AllModels = &vigo.ModelList{}
func init() {
// 注册所有模型
AllModels.Add(&User{})
AllModels.Add(&Identity{})
AllModels.Add(&Session{})
// Auth 模块模型
AllModels.Add(&Permission{})
AllModels.Add(&Role{})
AllModels.Add(&UserRole{})
// OAuth 模型
AllModels.Add(&OAuthClient{})
AllModels.Add(&OAuthAuthorizationCode{})
AllModels.Add(&OAuthToken{})
// 配置 & 验证码 & 邮件
AllModels.Add(&Setting{})
AllModels.Add(&VerificationCode{})
AllModels.Add(&EmailLog{})
AllModels.Add(&OAuthProvider{})
event.Add("vb.init.settings", InitSettings)
event.Add("vb.init.oauth", InitOAuthProviders)
event.Add("vb.init.admin", initAdminUser, event.After("vb.init.auth"))
}
func Migrate() error {
return AllModels.AutoMigrate(cfg.DB())
}
func Drop() error {
return AllModels.AutoDrop(cfg.DB())
}
// initAdminUser 如果用户表为空且配置了 init_admin则自动创建管理员
func initAdminUser() error {
db := cfg.DB()
// 检查用户表是否为空
var userCount int64
if err := db.Model(&User{}).Count(&userCount).Error; err != nil {
return err
}
// 已有用户,跳过
if userCount > 0 {
return nil
}
// 检查 init_admin 配置
adminCfg := cfg.Global.InitAdmin
if adminCfg.Username == "" || adminCfg.Password == "" {
// 未配置初始管理员,跳过
return nil
}
// 查找 admin 角色
var adminRole Role
if err := db.Where("code = ?", RoleCodeAdmin).First(&adminRole).Error; err != nil {
return fmt.Errorf("admin role not found, please ensure roles are initialized: %w", err)
}
// 哈希密码(使用默认 bcrypt cost = 12
hashedPassword, err := crypto.HashPassword(adminCfg.Password, 12)
if err != nil {
return fmt.Errorf("hash password failed: %w", err)
}
// 创建用户
var email *string
if adminCfg.Email != "" {
email = &adminCfg.Email
}
now := time.Now()
user := &User{
Username: adminCfg.Username,
Password: hashedPassword,
Email: email,
Nickname: adminCfg.Username,
Status: UserStatusActive,
EmailVerified: email != nil,
LastLoginAt: &now,
}
if err := db.Create(user).Error; err != nil {
return fmt.Errorf("create admin user failed: %w", err)
}
// 授予 admin 角色
userRole := &UserRole{
UserID: user.ID,
RoleID: adminRole.ID,
}
if err := db.Create(userRole).Error; err != nil {
return fmt.Errorf("grant admin role failed: %w", err)
}
fmt.Printf("[vbase] Initial admin user '%s' created successfully\n", adminCfg.Username)
return nil
}