From 5d55f5a8d97072e9aa6c502d54a79b06cb6172b3 Mon Sep 17 00:00:00 2001 From: Alex <$(pass /github/email)> Date: Mon, 24 Mar 2025 17:45:55 +0100 Subject: [PATCH] add new db constraints and foreignKey mode --- go-backend/internal/database/db.go | 91 +++++++++++++++++++----------- 1 file changed, 58 insertions(+), 33 deletions(-) diff --git a/go-backend/internal/database/db.go b/go-backend/internal/database/db.go index 4767aee..eb4b987 100644 --- a/go-backend/internal/database/db.go +++ b/go-backend/internal/database/db.go @@ -6,6 +6,8 @@ import ( "GoMembership/pkg/logger" "crypto/rand" "encoding/base64" + "errors" + "fmt" "time" "github.com/alexedwards/argon2id" @@ -15,27 +17,55 @@ import ( var DB *gorm.DB -func Open(dbPath string, adminMail string) (*gorm.DB, error) { +func Open(dbPath string, adminMail string, debug bool) (*gorm.DB, error) { + // Add foreign key support and WAL journal mode to DSN + dsn := fmt.Sprintf("%s?_foreign_keys=1&_journal_mode=WAL", dbPath) - db, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{}) + db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{ + // Enable PrepareStmt for better performance + PrepareStmt: true, + }) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to connect database: %w", err) } + + // Verify foreign key support is enabled + var foreignKeyEnabled int + if err := db.Raw("PRAGMA foreign_keys").Scan(&foreignKeyEnabled).Error; err != nil { + return nil, fmt.Errorf("foreign key check failed: %w", err) + } + if foreignKeyEnabled != 1 { + return nil, errors.New("SQLite foreign key constraints not enabled") + } + + if debug { + db = db.Debug() + } + + // Configure connection pool + sqlDB, err := db.DB() + if err != nil { + return nil, fmt.Errorf("failed to get DB instance: %w", err) + } + sqlDB.SetMaxOpenConns(1) // Required for SQLite in production + sqlDB.SetMaxIdleConns(1) + sqlDB.SetConnMaxLifetime(time.Hour) + if err := db.AutoMigrate( &models.User{}, &models.SubscriptionModel{}, &models.Membership{}, &models.Consent{}, &models.Verification{}, + &models.BankAccount{}, &models.Licence{}, &models.Category{}, - &models.Insurance{}, &models.Car{}, &models.Location{}, &models.Damage{}, - &models.BankAccount{}); err != nil { - logger.Error.Fatalf("Couldn't create database: %v", err) - return nil, err + &models.Insurance{}, + ); err != nil { + return nil, fmt.Errorf("failed to migrate database: %w", err) } logger.Info.Print("Opened DB") @@ -78,14 +108,11 @@ func Open(dbPath string, adminMail string) (*gorm.DB, error) { return nil, err } - admin, err := createAdmin(adminMail, createdModel.ID) + admin, err := createAdmin(adminMail) if err != nil { return nil, err } - result := db.Session(&gorm.Session{FullSaveAssociations: true}).Create(&admin) - if result.Error != nil { - return nil, result.Error - } + admin.Create(db) } return db, nil @@ -125,7 +152,7 @@ func createLicenceCategories() []models.Category { // TODO: Landing page to create an admin -func createAdmin(userMail string, subscriptionModelID uint) (*models.User, error) { +func createAdmin(userMail string) (*models.User, error) { passwordBytes := make([]byte, 12) _, err := rand.Read(passwordBytes) if err != nil { @@ -146,26 +173,24 @@ func createAdmin(userMail string, subscriptionModelID uint) (*models.User, error logger.Error.Print("==============================================================") return &models.User{ - FirstName: "ad", - LastName: "min", - DateOfBirth: time.Now().AddDate(-20, 0, 0), - Password: hash, - Address: "Downhill 4", - ZipCode: "99999", - City: "TechTown", - Phone: "0123455678", - Email: userMail, - Status: constants.ActiveStatus, - RoleID: constants.Roles.Admin, - Membership: models.Membership{ - Status: constants.DisabledStatus, - StartDate: time.Now(), - SubscriptionModelID: subscriptionModelID, - }, - BankAccount: models.BankAccount{}, - Licence: &models.Licence{ - Status: constants.UnverifiedStatus, - }, + FirstName: "Ad", + LastName: "Min", + DateOfBirth: time.Now().AddDate(-20, 0, 0), + Password: hash, + Company: "", + Address: "", + ZipCode: "", + City: "", + Phone: "", + Notes: "", + Email: userMail, + Status: constants.ActiveStatus, + RoleID: constants.Roles.Admin, + Consents: nil, + Verifications: nil, + Membership: nil, + BankAccount: nil, + Licence: nil, }, nil //"DE49700500000008447644", //fake }