From 5bc16977744ce5bafe3d589a665a8362872613c0 Mon Sep 17 00:00:00 2001 From: Thomas Miceli Date: Tue, 18 Apr 2023 02:33:19 +0200 Subject: [PATCH] Migration system & fix ssh key table constraint --- internal/models/db.go | 2 + internal/models/migration.go | 96 ++++++++++++++++++++++++++++++++++++ internal/models/user.go | 2 +- 3 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 internal/models/migration.go diff --git a/internal/models/db.go b/internal/models/db.go index 4b54b5a..fc4890b 100644 --- a/internal/models/db.go +++ b/internal/models/db.go @@ -23,6 +23,8 @@ func Setup(dbpath string) error { return err } + ApplyMigrations(db) + // Default admin setting values return initAdminSettings(map[string]string{ SettingDisableSignup: "0", diff --git a/internal/models/migration.go b/internal/models/migration.go new file mode 100644 index 0000000..d4d7629 --- /dev/null +++ b/internal/models/migration.go @@ -0,0 +1,96 @@ +package models + +import ( + "fmt" + "github.com/rs/zerolog/log" + "gorm.io/gorm" +) + +type MigrationVersion struct { + ID uint `gorm:"primaryKey"` + Version uint +} + +func ApplyMigrations(db *gorm.DB) error { + // Create migration table if it doesn't exist + if err := db.AutoMigrate(&MigrationVersion{}); err != nil { + log.Fatal().Err(err).Msg("Error creating migration version table") + return err + } + + // Get the current migration version + var currentVersion MigrationVersion + db.First(¤tVersion) + + // Define migrations + migrations := []struct { + Version uint + Func func(*gorm.DB) error + }{ + {1, v1_modifyConstraintToSSHKeys}, + // Add more migrations here as needed + } + + // Apply migrations + for _, m := range migrations { + if m.Version > currentVersion.Version { + tx := db.Begin() + if err := tx.Error; err != nil { + log.Fatal().Err(err).Msg("Error starting transaction") + return err + } + + if err := m.Func(db); err != nil { + log.Fatal().Err(err).Msg(fmt.Sprintf("Error applying migration %d:", m.Version)) + tx.Rollback() + return err + } else { + if err = tx.Commit().Error; err != nil { + log.Fatal().Err(err).Msg(fmt.Sprintf("Error committing migration %d:", m.Version)) + return err + } + currentVersion.Version = m.Version + db.Save(¤tVersion) + log.Info().Msg(fmt.Sprintf("Migration %d applied successfully", m.Version)) + } + } + } + + return nil +} + +// Modify the constraint on the ssh_keys table to use ON DELETE CASCADE +func v1_modifyConstraintToSSHKeys(db *gorm.DB) error { + createSQL := ` + CREATE TABLE ssh_keys_temp ( + id integer primary key, + title text, + content text, + sha text, + created_at integer, + last_used_at integer, + user_id integer + constraint fk_users_ssh_keys references users(id) on update cascade on delete cascade + ); + ` + + if err := db.Exec(createSQL).Error; err != nil { + return err + } + + // Copy data from the old table to the new table + copySQL := `INSERT INTO ssh_keys_temp SELECT * FROM ssh_keys;` + if err := db.Exec(copySQL).Error; err != nil { + return err + } + + // Drop the old table + dropSQL := `DROP TABLE ssh_keys;` + if err := db.Exec(dropSQL).Error; err != nil { + return err + } + + // Rename the new table to the original table name + renameSQL := `ALTER TABLE ssh_keys_temp RENAME TO ssh_keys;` + return db.Exec(renameSQL).Error +} diff --git a/internal/models/user.go b/internal/models/user.go index 961e54b..9b0cabe 100644 --- a/internal/models/user.go +++ b/internal/models/user.go @@ -16,7 +16,7 @@ type User struct { GiteaID string Gists []Gist `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;foreignKey:UserID"` - SSHKeys []SSHKey `gorm:"foreignKey:UserID"` + SSHKeys []SSHKey `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;foreignKey:UserID"` Liked []Gist `gorm:"many2many:likes;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` }