package db import ( "context" "fmt" "log" "github.com/jackc/pgx/v5/pgtype" ) var migrationsTable string = "schema_migrations" func RunMigrations() { log.Print("[tixe/db] Running migrations") var ranTimestamp pgtype.Timestamptz var schemaVersion int = 0 schemaVersionQuery := fmt.Sprintf( `SELECT ran_timestamp, schema_version FROM %s ORDER BY schema_version DESC LIMIT 1;`, migrationsTable) err := PgPool.QueryRow(context.Background(), schemaVersionQuery).Scan(&ranTimestamp, &schemaVersion) if err != nil { log.Print("[tixe/db] No schema version found, running all migrations") } else { log.Printf("[tixe/db] Last migration ran on %s, with schema version %d", ranTimestamp.Time, schemaVersion) } migrations := migrations() if schemaVersion != len(migrations) { for i := 0; i < len(migrations); i++ { if i <= schemaVersion { log.Printf("[tixe/db] Running migration %d", i) _, err := PgPool.Exec(context.Background(), migrations[i]) if err != nil { log.Fatalf("[tixe/db] Migration %d failed to run!", i) } } } // We are now up to date schemaVersion = len(migrations) // Create a new entry in the migrations table schemaMigrationInsertQuery := fmt.Sprintf( `INSERT INTO %s(ran_timestamp, schema_version) VALUES(CURRENT_TIMESTAMP, %d);`, migrationsTable, schemaVersion) _, err = PgPool.Exec(context.Background(), schemaMigrationInsertQuery) if err != nil { log.Fatal("[tixe/db] Migrations ran, but was not able to create migration entry") } else { log.Print("[tixe/db] Migrations ran successfully") } } else { log.Printf("[tixe/db] Already on schema version %d, no migrations to run", schemaVersion) } } func migrations() []string { return []string{ fmt.Sprintf(`CREATE TABLE %s ( ran_timestamp timestamp, schema_version integer )`,migrationsTable), `CREATE TABLE users ( id UUID NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(), is_internal BOOLEAN NOT NULL DEFAULT FALSE, is_admin BOOLEAN NOT NULL DEFAULT FALSE, display_name TEXT NOT NULL, username TEXT, password TEXT, oidc_subject TEXT )`, `INSERT INTO users(is_internal, is_admin, display_name, username, password) VALUES(TRUE, TRUE, "admin", "admin", "$argon2id$v=19$m=65536,t=3,p=4$UC+I4MhJyVJG+N2OGPecHQ$ISwMkf1LQh0wUgoP7im7yzT1vKUNDTWVbT828m75woY")`, } }