init bootstrap
This commit is contained in:
320
local/utl/db/db.go
Normal file
320
local/utl/db/db.go
Normal file
@@ -0,0 +1,320 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"omega-server/local/model"
|
||||
"omega-server/local/utl/logging"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"go.uber.org/dig"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
func Start(di *dig.Container) {
|
||||
dbName := os.Getenv("DB_NAME")
|
||||
if dbName == "" {
|
||||
dbName = "app.db"
|
||||
}
|
||||
|
||||
// Configure GORM logger
|
||||
gormLogger := logger.Default
|
||||
if os.Getenv("LOG_LEVEL") == "DEBUG" {
|
||||
gormLogger = logger.Default.LogMode(logger.Info)
|
||||
} else {
|
||||
gormLogger = logger.Default.LogMode(logger.Silent)
|
||||
}
|
||||
|
||||
db, err := gorm.Open(sqlite.Open(dbName), &gorm.Config{
|
||||
Logger: gormLogger,
|
||||
})
|
||||
if err != nil {
|
||||
logging.Panic("failed to connect database: " + err.Error())
|
||||
}
|
||||
|
||||
// Configure connection pool
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
logging.Panic("failed to get database instance: " + err.Error())
|
||||
}
|
||||
|
||||
// Set connection pool settings
|
||||
sqlDB.SetMaxIdleConns(10)
|
||||
sqlDB.SetMaxOpenConns(100)
|
||||
sqlDB.SetConnMaxLifetime(time.Hour)
|
||||
|
||||
err = di.Provide(func() *gorm.DB {
|
||||
return db
|
||||
})
|
||||
if err != nil {
|
||||
logging.Panic("failed to bind database: " + err.Error())
|
||||
}
|
||||
|
||||
logging.Info("Database connected successfully")
|
||||
Migrate(db)
|
||||
}
|
||||
|
||||
func Migrate(db *gorm.DB) {
|
||||
logging.Info("Starting database migration...")
|
||||
|
||||
err := db.AutoMigrate(
|
||||
&model.User{},
|
||||
&model.Role{},
|
||||
&model.Permission{},
|
||||
&model.SystemConfig{},
|
||||
&model.AuditLog{},
|
||||
&model.SecurityEvent{},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
logging.Panic("failed to migrate database models: " + err.Error())
|
||||
}
|
||||
|
||||
logging.Info("Database migration completed successfully")
|
||||
Seed(db)
|
||||
}
|
||||
|
||||
func Seed(db *gorm.DB) error {
|
||||
logging.Info("Starting database seeding...")
|
||||
|
||||
if err := seedRoles(db); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := seedPermissions(db); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := seedDefaultAdmin(db); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := seedSystemConfigs(db); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logging.Info("Database seeding completed successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
func seedRoles(db *gorm.DB) error {
|
||||
roles := []model.Role{
|
||||
{Name: "admin", Description: "Administrator with full access"},
|
||||
{Name: "user", Description: "Regular user with limited access"},
|
||||
{Name: "viewer", Description: "Read-only access"},
|
||||
}
|
||||
|
||||
for _, role := range roles {
|
||||
var existingRole model.Role
|
||||
err := db.Where("name = ?", role.Name).First(&existingRole).Error
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
role.Init()
|
||||
if err := db.Create(&role).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
logging.Info("Created role: %s", role.Name)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func seedPermissions(db *gorm.DB) error {
|
||||
permissions := []model.Permission{
|
||||
{Name: "user:create", Description: "Create new users"},
|
||||
{Name: "user:read", Description: "Read user information"},
|
||||
{Name: "user:update", Description: "Update user information"},
|
||||
{Name: "user:delete", Description: "Delete users"},
|
||||
{Name: "role:create", Description: "Create new roles"},
|
||||
{Name: "role:read", Description: "Read role information"},
|
||||
{Name: "role:update", Description: "Update role information"},
|
||||
{Name: "role:delete", Description: "Delete roles"},
|
||||
{Name: "system:config", Description: "Access system configuration"},
|
||||
{Name: "system:logs", Description: "Access system logs"},
|
||||
{Name: "system:admin", Description: "Full system administration"},
|
||||
}
|
||||
|
||||
for _, permission := range permissions {
|
||||
var existingPermission model.Permission
|
||||
err := db.Where("name = ?", permission.Name).First(&existingPermission).Error
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
permission.Init()
|
||||
if err := db.Create(&permission).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
logging.Info("Created permission: %s", permission.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// Assign all permissions to admin role
|
||||
var adminRole model.Role
|
||||
if err := db.Where("name = ?", "admin").First(&adminRole).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var allPermissions []model.Permission
|
||||
if err := db.Find(&allPermissions).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := db.Model(&adminRole).Association("Permissions").Replace(allPermissions); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Assign basic permissions to user role
|
||||
var userRole model.Role
|
||||
if err := db.Where("name = ?", "user").First(&userRole).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var userPermissions []model.Permission
|
||||
userPermissionNames := []string{"user:read", "role:read"}
|
||||
if err := db.Where("name IN ?", userPermissionNames).Find(&userPermissions).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := db.Model(&userRole).Association("Permissions").Replace(userPermissions); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Assign read permissions to viewer role
|
||||
var viewerRole model.Role
|
||||
if err := db.Where("name = ?", "viewer").First(&viewerRole).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var viewerPermissions []model.Permission
|
||||
viewerPermissionNames := []string{"user:read", "role:read"}
|
||||
if err := db.Where("name IN ?", viewerPermissionNames).Find(&viewerPermissions).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := db.Model(&viewerRole).Association("Permissions").Replace(viewerPermissions); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func seedDefaultAdmin(db *gorm.DB) error {
|
||||
// Check if admin user already exists
|
||||
var existingAdmin model.User
|
||||
err := db.Where("email = ?", "admin@example.com").First(&existingAdmin).Error
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
return nil // Admin already exists or other error
|
||||
}
|
||||
|
||||
// Get admin role
|
||||
var adminRole model.Role
|
||||
if err := db.Where("name = ?", "admin").First(&adminRole).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create default admin user
|
||||
defaultPassword := os.Getenv("DEFAULT_ADMIN_PASSWORD")
|
||||
if defaultPassword == "" {
|
||||
defaultPassword = "admin123"
|
||||
}
|
||||
|
||||
admin := model.User{
|
||||
Email: "admin@example.com",
|
||||
Username: "admin",
|
||||
Name: "System Administrator",
|
||||
Active: true,
|
||||
}
|
||||
admin.Init()
|
||||
|
||||
if err := admin.SetPassword(defaultPassword); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := db.Create(&admin).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Assign admin role
|
||||
if err := db.Model(&admin).Association("Roles").Append(&adminRole); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logging.Info("Created default admin user with email: %s", admin.Email)
|
||||
logging.Warn("Default admin password is: %s - PLEASE CHANGE THIS IMMEDIATELY!", defaultPassword)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func seedSystemConfigs(db *gorm.DB) error {
|
||||
configs := []model.SystemConfig{
|
||||
{
|
||||
Key: "app.name",
|
||||
Value: "Bootstrap App",
|
||||
DefaultValue: "Bootstrap App",
|
||||
Description: "Application name",
|
||||
Category: "general",
|
||||
DataType: "string",
|
||||
IsEditable: true,
|
||||
DateModified: time.Now().UTC().Format(time.RFC3339),
|
||||
},
|
||||
{
|
||||
Key: "app.version",
|
||||
Value: "1.0.0",
|
||||
DefaultValue: "1.0.0",
|
||||
Description: "Application version",
|
||||
Category: "general",
|
||||
DataType: "string",
|
||||
IsEditable: false,
|
||||
DateModified: time.Now().UTC().Format(time.RFC3339),
|
||||
},
|
||||
{
|
||||
Key: "security.jwt_expiry_hours",
|
||||
Value: "24",
|
||||
DefaultValue: "24",
|
||||
Description: "JWT token expiry time in hours",
|
||||
Category: "security",
|
||||
DataType: "integer",
|
||||
IsEditable: true,
|
||||
DateModified: time.Now().UTC().Format(time.RFC3339),
|
||||
},
|
||||
{
|
||||
Key: "security.password_min_length",
|
||||
Value: "8",
|
||||
DefaultValue: "8",
|
||||
Description: "Minimum password length",
|
||||
Category: "security",
|
||||
DataType: "integer",
|
||||
IsEditable: true,
|
||||
DateModified: time.Now().UTC().Format(time.RFC3339),
|
||||
},
|
||||
{
|
||||
Key: "security.max_login_attempts",
|
||||
Value: "5",
|
||||
DefaultValue: "5",
|
||||
Description: "Maximum login attempts before lockout",
|
||||
Category: "security",
|
||||
DataType: "integer",
|
||||
IsEditable: true,
|
||||
DateModified: time.Now().UTC().Format(time.RFC3339),
|
||||
},
|
||||
{
|
||||
Key: "security.lockout_duration_minutes",
|
||||
Value: "30",
|
||||
DefaultValue: "30",
|
||||
Description: "Account lockout duration in minutes",
|
||||
Category: "security",
|
||||
DataType: "integer",
|
||||
IsEditable: true,
|
||||
DateModified: time.Now().UTC().Format(time.RFC3339),
|
||||
},
|
||||
}
|
||||
|
||||
for _, config := range configs {
|
||||
var existingConfig model.SystemConfig
|
||||
err := db.Where("key = ?", config.Key).First(&existingConfig).Error
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
config.Init()
|
||||
if err := db.Create(&config).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
logging.Info("Created system config: %s", config.Key)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user