Files
social-rating/backend/internal/database/mysql.go
2026-04-18 10:58:00 +03:00

110 lines
2.7 KiB
Go

package database
import (
"errors"
"fmt"
"log"
"strings"
"time"
"golang.org/x/crypto/bcrypt"
"social-raiting.nekiiinkognito.ru/internal/config"
"social-raiting.nekiiinkognito.ru/internal/models"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
func Connect(cfg config.Config) *gorm.DB {
dsn := fmt.Sprintf(
"%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
cfg.DBUser,
cfg.DBPassword,
cfg.DBHost,
cfg.DBPort,
cfg.DBName,
)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatalf("failed to connect to mysql: %v", err)
}
sqlDB, err := db.DB()
if err != nil {
log.Fatalf("failed to create sql database handle: %v", err)
}
sqlDB.SetConnMaxLifetime(5 * time.Minute)
sqlDB.SetMaxIdleConns(10)
sqlDB.SetMaxOpenConns(25)
if err := sqlDB.Ping(); err != nil {
log.Fatalf("failed to ping mysql: %v", err)
}
if err := db.AutoMigrate(&models.User{}); err != nil {
log.Fatalf("failed to migrate database: %v", err)
}
if err := db.AutoMigrate(&models.UserSocialRating{}, &models.SocialRatingOperation{}); err != nil {
log.Fatalf("failed to migrate database: %v", err)
}
ensureDefaultAdmin(db, cfg)
return db
}
func ensureDefaultAdmin(db *gorm.DB, cfg config.Config) {
email := strings.ToLower(strings.TrimSpace(cfg.DefaultAdminEmail))
password := strings.TrimSpace(cfg.DefaultAdminPassword)
if email == "" || password == "" {
log.Println("skipping default admin bootstrap because admin credentials are empty")
return
}
var user models.User
err := db.Where("email = ?", email).First(&user).Error
if err == nil {
if !user.IsAdmin {
if updateErr := db.Model(&user).Update("is_admin", true).Error; updateErr != nil {
log.Fatalf("failed to promote default admin user: %v", updateErr)
}
}
return
}
if !errors.Is(err, gorm.ErrRecordNotFound) {
log.Fatalf("failed to check default admin user: %v", err)
}
passwordHash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
log.Fatalf("failed to hash default admin password: %v", err)
}
user = models.User{
Email: email,
PasswordHash: string(passwordHash),
IsAdmin: true,
}
if err := db.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "email"}},
DoNothing: true,
}).Create(&user).Error; err != nil {
log.Fatalf("failed to create default admin user: %v", err)
}
if err := db.Where("email = ?", email).First(&user).Error; err != nil {
log.Fatalf("failed to load default admin user after bootstrap: %v", err)
}
if !user.IsAdmin {
if err := db.Model(&user).Update("is_admin", true).Error; err != nil {
log.Fatalf("failed to ensure default admin privileges: %v", err)
}
}
}