refactor migration

This commit is contained in:
2025-08-17 15:40:26 +02:00
parent dcb490ae31
commit 132a8913aa
3 changed files with 52 additions and 54 deletions

View File

@@ -6,7 +6,7 @@ postgres = "42.7.5"
koin = "4.0.3" koin = "4.0.3"
random = "1.0.0" random = "1.0.0"
otp = "1.1.1" otp = "1.1.1"
kdf = "1.0.1" kdf = "1.0.3"
hash = "1.2.2" hash = "1.2.2"
encoding = "1.1.0" encoding = "1.1.0"
logback = "1.5.18" logback = "1.5.18"

View File

@@ -5,7 +5,6 @@ import com.infendro.account.model.repository.AccountRepository
import com.infendro.account.model.repository.MigrationRepository import com.infendro.account.model.repository.MigrationRepository
import com.infendro.account.util.SecureHasher import com.infendro.account.util.SecureHasher
import io.ktor.server.application.* import io.ktor.server.application.*
import org.intellij.lang.annotations.Language
import org.jetbrains.exposed.sql.SchemaUtils import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.Transaction import org.jetbrains.exposed.sql.Transaction
@@ -17,48 +16,48 @@ fun Application.migrate() {
SchemaUtils.create(MigrationTable) SchemaUtils.create(MigrationTable)
} }
migration( val accounts by inject<AccountRepository>()
"initial",
"""
CREATE TABLE access
(
id BIGSERIAL
PRIMARY KEY,
token_hash TEXT
NOT NULL
);
CREATE TABLE account migration("initial") {
( exec(
id BIGSERIAL """
PRIMARY KEY, CREATE TABLE access
username TEXT (
UNIQUE id BIGSERIAL
NOT NULL, PRIMARY KEY,
password_hash TEXT token_hash TEXT
NOT NULL, NOT NULL
password_salt TEXT );
NOT NULL,
secret TEXT
NOT NULL,
role TEXT
NOT NULL
);
CREATE TABLE session CREATE TABLE account
( (
id BIGSERIAL id BIGSERIAL
PRIMARY KEY, PRIMARY KEY,
token_hash TEXT username TEXT
NOT NULL, UNIQUE
account_id BIGINT NOT NULL,
REFERENCES account (id) ON DELETE CASCADE password_hash TEXT
NOT NULL NOT NULL,
); password_salt TEXT
""".trimIndent() NOT NULL,
) secret TEXT
migration("owner") { NOT NULL,
val accounts by inject<AccountRepository>() role TEXT
NOT NULL
);
CREATE TABLE session
(
id BIGSERIAL
PRIMARY KEY,
token_hash TEXT
NOT NULL,
account_id BIGINT
REFERENCES account (id) ON DELETE CASCADE
NOT NULL
);
""".trimIndent()
)
accounts.insert { accounts.insert {
val salt = SecureHasher.generateSalt() val salt = SecureHasher.generateSalt()
@@ -66,7 +65,7 @@ fun Application.migrate() {
this.username = "infendro" this.username = "infendro"
this.passwordHash = SecureHasher.hash("password", salt) this.passwordHash = SecureHasher.hash("password", salt)
this.passwordSalt = salt this.passwordSalt = salt
this.secret = "deadbeef" this.secret = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA===="
this.role = Role.OWNER this.role = Role.OWNER
} }
} }
@@ -83,17 +82,16 @@ private fun Application.migration(
?.run { return } ?.run { return }
transaction { transaction {
block() try {
block()
log.info("""Migration "$name" successful""")
} catch (e: Exception) {
log.error("""Migration "$name" failed""")
throw e
}
} }
migrations.insert { migrations.insert {
this.name = name this.name = name
} }
} }
private fun Application.migration(
name: String,
@Language("sql") sql: String,
) = migration(name) {
exec(sql)
}

View File

@@ -24,6 +24,6 @@ object OTP {
fun generateSecret(): String { fun generateSecret(): String {
val bytes = SecretGenerator.generate(totp.hotp.function) val bytes = SecretGenerator.generate(totp.hotp.function)
return Base32.encode(bytes).toString() return Base32.encode(bytes).decodeToString()
} }
} }