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

142 lines
3.2 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"
)
var AllModels = &vigo.ModelList{}
func init() {
// 注册所有模型
AllModels.Add(&User{})
AllModels.Add(&Identity{})
AllModels.Add(&Session{})
AllModels.Add(&Org{})
AllModels.Add(&OrgMember{})
// Auth 模块模型
AllModels.Add(&Permission{})
AllModels.Add(&Role{})
AllModels.Add(&RolePermission{})
AllModels.Add(&UserRole{})
AllModels.Add(&UserPermission{})
// OAuth 模型
AllModels.Add(&OAuthClient{})
AllModels.Add(&OAuthAuthorizationCode{})
AllModels.Add(&OAuthToken{})
// 配置 & 验证码 & 邮件
AllModels.Add(&Setting{})
AllModels.Add(&VerificationCode{})
AllModels.Add(&EmailLog{})
AllModels.Add(&OAuthProvider{})
}
func Migrate() error {
return AllModels.AutoMigrate(cfg.DB())
}
func Drop() error {
return AllModels.AutoDrop(cfg.DB())
}
func InitDB() error {
// 1. 初始化系统配置
if err := InitSettings(); err != nil {
return fmt.Errorf("init settings failed: %w", err)
}
// 2. 初始化 OAuth 提供商
if err := InitOAuthProviders(); err != nil {
return fmt.Errorf("init oauth providers failed: %w", err)
}
// 3. 检查是否需要创建初始管理员
if err := initAdminUser(); err != nil {
return fmt.Errorf("init admin user failed: %w", err)
}
return nil
}
// 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.Config.InitAdmin
if adminCfg.Username == "" || adminCfg.Password == "" {
// 未配置初始管理员,跳过
return nil
}
// 查找 admin 角色
var adminRole Role
if err := db.Where("code = ? AND org_id IS NULL", 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,
OrgID: nil, // 系统级 admin
}
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
}