1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/*
* Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
*
* This file is licensed under AGPL-3.0-or-later, see NOTICE and LICENSE for
* more information.
*/
package db
import (
"fmt"
"log"
)
var migrationsTable string = "schema_migrations"
func runMigrations() {
log.Print("[felu/db] Running migrations")
var schemaVersion int = 0
schemaVersionQuery := fmt.Sprintf(
`SELECT schema_version
FROM %s
ORDER BY schema_version
DESC LIMIT 1`,
migrationsTable)
err := DBConn.QueryRow(schemaVersionQuery).Scan(&schemaVersion)
if err != nil {
log.Print("[felu/db] No schema version found, running all migrations")
} else {
log.Printf("[felu/db] Currently on schema version %d", schemaVersion)
}
migrations := migrations()
if schemaVersion != len(migrations) {
for i := 0; i < len(migrations); i++ {
if i >= schemaVersion {
log.Printf("[felu/db] Running migration %d", i + 1) // + 1 is just a visual thing
_, err := DBConn.Exec(migrations[i])
if err != nil {
log.Fatalf("[felu/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(schema_version) VALUES(%d)`,
migrationsTable, schemaVersion)
_, err = DBConn.Exec(schemaMigrationInsertQuery)
if err != nil {
log.Fatal("[felu/db] Migrations ran, but was not able to create migration entry")
} else {
log.Print("[felu/db] Migrations ran successfully")
}
} else {
log.Printf("[felu/db] Already on schema version %d, no migrations to run", schemaVersion)
}
}
func migrations() []string {
return []string{
fmt.Sprintf(`CREATE TABLE %s (
schema_version INTEGER
)`, migrationsTable),
fmt.Sprintf(`CREATE TABLE users (
id TEXT NOT NULL PRIMARY KEY UNIQUE,
email TEXT NOT NULL UNIQUE,
pwd TEXT NOT NULL,
is_admin INTEGER DEFAULT FALSE NOT NULL
)`),
fmt.Sprintf(`CREATE TABLE domains (
id TEXT NOT NULL PRIMARY KEY UNIQUE,
apikey TEXT NOT NULL,
owner TEXT NOT NULL,
ddns_domain TEXT NOT NULL UNIQUE,
a_record TEXT,
FOREIGN KEY(owner) REFERENCES users(id)
)`),
}
}