Skip to content

Commit

Permalink
fix: only perform encryption migration if a database file already exists
Browse files Browse the repository at this point in the history
  • Loading branch information
DarkAtra committed Nov 16, 2024
1 parent 97435b2 commit 06f0940
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 35 deletions.
2 changes: 1 addition & 1 deletion docs/self-hosting.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ You can also build it from scratch by cloning the repository and then running `m
```yaml
services:
v-rising-discord-bot:
image: ghcr.io/darkatra/v-rising-discord-bot:2.12.0-native # find the latest version here: https://github.com/DarkAtra/v-rising-discord-bot/releases
image: ghcr.io/darkatra/v-rising-discord-bot:2.12.1-native # find the latest version here: https://github.com/DarkAtra/v-rising-discord-bot/releases
command: -Dagql.nativeTransport=false
mem_reservation: 128M
mem_limit: 256M
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,49 +42,52 @@ class DatabaseConfiguration(
fun buildNitriteDatabase(databaseFile: Path, username: String? = null, password: String? = null): Nitrite {

// version 2.12.0 introduced database encryption at rest. the following code attempts to perform the migration if necessary
val firstFewBytes = databaseFile.inputStream().readNBytes(ENCRYPTED_MARKER.length).toString(StandardCharsets.UTF_8)
if (firstFewBytes != ENCRYPTED_MARKER) {

// if the automated migration was aborted while writing the files to disc, restore the backup
val unencryptedDatabaseBackupFile = Path.of(System.getProperty("java.io.tmpdir")).resolve("v-rising-bot.db.unencrypted")
if (unencryptedDatabaseBackupFile.exists()) {
logger.info("Found an unencrypted backup of the database at: ${unencryptedDatabaseBackupFile.absolutePathString()}")
unencryptedDatabaseBackupFile.copyTo(databaseFile, overwrite = true)
logger.info("Successfully restored the backup. Will re-attempt the migration.")
}
if (databaseFile.exists()) {

logger.info("Attempting to encrypt the bot database with the provided database password.")
val firstFewBytes = databaseFile.inputStream().readNBytes(ENCRYPTED_MARKER.length).toString(StandardCharsets.UTF_8)
if (firstFewBytes != ENCRYPTED_MARKER) {

// retry opening the database without encryption if we encounter an error
val unencryptedDatabase = try {
getNitriteBuilder(getStoreModule(databaseFile, null)).openOrCreate(username, password)
} catch (e: NitriteIOException) {
throw IllegalStateException("Could not encrypt the database.", e)
}
// if the automated migration was aborted while writing the files to disc, restore the backup
val unencryptedDatabaseBackupFile = Path.of(System.getProperty("java.io.tmpdir")).resolve("v-rising-bot.db.unencrypted")
if (unencryptedDatabaseBackupFile.exists()) {
logger.info("Found an unencrypted backup of the database at: ${unencryptedDatabaseBackupFile.absolutePathString()}")
unencryptedDatabaseBackupFile.copyTo(databaseFile, overwrite = true)
logger.info("Successfully restored the backup. Will re-attempt the migration.")
}

unencryptedDatabaseBackupFile.deleteIfExists()
logger.info("Attempting to encrypt the bot database with the provided database password.")

// create an encrypted copy of the existing database
val tempDatabaseFile = Files.createTempFile("v-rising-bot", ".db")
// retry opening the database without encryption if we encounter an error
val unencryptedDatabase = try {
getNitriteBuilder(getStoreModule(databaseFile, null)).openOrCreate(username, password)
} catch (e: NitriteIOException) {
throw IllegalStateException("Could not encrypt the database.", e)
}

val encryptedDatabase = getNitriteBuilder(getStoreModule(tempDatabaseFile, password)).openOrCreate(username, password)
for (collectionName in unencryptedDatabase.listAllCollectionNames()) {
unencryptedDatabaseBackupFile.deleteIfExists()

val oldCollection = unencryptedDatabase.store.openMap<NitriteId, Any>(collectionName, NitriteId::class.java, Document::class.java)
val newCollection = encryptedDatabase.store.openMap<NitriteId, Any>(collectionName, NitriteId::class.java, Document::class.java)
// create an encrypted copy of the existing database
val tempDatabaseFile = Files.createTempFile("v-rising-bot", ".db")

oldCollection.entries().forEach { entry -> newCollection.put(entry.first, entry.second) }
}
unencryptedDatabase.close()
encryptedDatabase.close()
val encryptedDatabase = getNitriteBuilder(getStoreModule(tempDatabaseFile, password)).openOrCreate(username, password)
for (collectionName in unencryptedDatabase.listAllCollectionNames()) {

databaseFile.copyTo(unencryptedDatabaseBackupFile)
tempDatabaseFile.copyTo(databaseFile, overwrite = true)
val oldCollection = unencryptedDatabase.store.openMap<NitriteId, Any>(collectionName, NitriteId::class.java, Document::class.java)
val newCollection = encryptedDatabase.store.openMap<NitriteId, Any>(collectionName, NitriteId::class.java, Document::class.java)

unencryptedDatabaseBackupFile.deleteIfExists()
tempDatabaseFile.deleteIfExists()
oldCollection.entries().forEach { entry -> newCollection.put(entry.first, entry.second) }
}
unencryptedDatabase.close()
encryptedDatabase.close()

logger.info("Successfully encrypted the database.")
databaseFile.copyTo(unencryptedDatabaseBackupFile)
tempDatabaseFile.copyTo(databaseFile, overwrite = true)

unencryptedDatabaseBackupFile.deleteIfExists()
tempDatabaseFile.deleteIfExists()

logger.info("Successfully encrypted the database.")
}
}

return getNitriteBuilder(getStoreModule(databaseFile, password)).openOrCreate(username, password)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import java.nio.file.Files
import java.nio.file.StandardOpenOption.CREATE
import java.nio.file.StandardOpenOption.TRUNCATE_EXISTING
import kotlin.io.path.absolutePathString
import kotlin.io.path.deleteIfExists
import kotlin.io.path.outputStream

object DatabaseConfigurationTestUtils {
Expand All @@ -24,7 +25,7 @@ object DatabaseConfigurationTestUtils {

val databaseFile = Files.createTempFile("v-rising-bot", ".db").also {
logger.info("Test Db location: " + it.absolutePathString())
}
}.also { it.deleteIfExists() }

if (fromTemplate != null) {
logger.info("Loading template from '$fromTemplate'.")
Expand Down

0 comments on commit 06f0940

Please sign in to comment.