Test backup: run every configured mechanism, stop misreporting passphrase-only as unconfigured
The user's report: with only a backup passphrase set (no S3), 'Test
backup nå' errored 'ikke konfigurert' even though Google Auto Backup
works on the passphrase alone. New runConfiguredBackups() writes the
Google blob whenever a passphrase exists and uploads to S3 only when
those credentials are present, throwing only when NOTHING is set up.
The toast now names what actually ran ('Kryptert Google-kopi
oppdatert' and/or the bucket key). Two instrumented tests pin both
ends: passphrase-only succeeds, nothing-configured throws.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
c9ee76387f
commit
8e8156488a
3 changed files with 49 additions and 2 deletions
|
|
@ -86,6 +86,26 @@ class CloudBackupRoundTripTest {
|
|||
assertTrue("DB still empty after failed restore", db.inventoryDao().getAll().isEmpty())
|
||||
}
|
||||
|
||||
@Test fun testBackupWithOnlyPassphraseSucceeds() = runBlocking {
|
||||
// The user's report: passphrase set, no S3 → "Test backup" must NOT
|
||||
// error with "not configured"; it writes the Google blob and says so.
|
||||
SettingsStore(context).autoBackupPassphrase = "x"
|
||||
db.inventoryDao().insert(InventoryItem(name = "A", strength = "", unit = "stk", form = MedForm.OTHER))
|
||||
|
||||
val outcome = manager.runConfiguredBackups()
|
||||
assertTrue("cloud blob written", outcome.cloudBlobWritten)
|
||||
assertNull("no S3 attempted when unconfigured", outcome.s3Key)
|
||||
assertTrue(BackupManager.cloudBlobFile(context).exists())
|
||||
}
|
||||
|
||||
@Test fun testBackupWithNothingConfiguredThrows() = runBlocking {
|
||||
SettingsStore(context).autoBackupPassphrase = null
|
||||
try {
|
||||
manager.runConfiguredBackups()
|
||||
org.junit.Assert.fail("must require at least one mechanism")
|
||||
} catch (_: IllegalArgumentException) { /* expected */ }
|
||||
}
|
||||
|
||||
@Test fun noPassphraseRemovesBlob() = runBlocking {
|
||||
SettingsStore(context).autoBackupPassphrase = "x"
|
||||
db.inventoryDao().insert(InventoryItem(name = "A", strength = "", unit = "stk", form = MedForm.OTHER))
|
||||
|
|
|
|||
|
|
@ -104,6 +104,26 @@ class BackupManager(private val context: Context) {
|
|||
return key to s3.get(key)
|
||||
}
|
||||
|
||||
/** What a "test backup now" actually accomplished, for an honest message. */
|
||||
data class BackupOutcome(val cloudBlobWritten: Boolean, val s3Key: String?)
|
||||
|
||||
/**
|
||||
* Run every backup mechanism that's actually set up, and report which ran.
|
||||
* The Google blob needs only a passphrase; S3 needs the full credentials.
|
||||
* Throws only when NOTHING is configured — so a passphrase-only setup no
|
||||
* longer reports the misleading "not configured" error.
|
||||
*/
|
||||
suspend fun runConfiguredBackups(): BackupOutcome {
|
||||
val settings = SettingsStore(context)
|
||||
val hasPassphrase = !settings.autoBackupPassphrase.isNullOrEmpty()
|
||||
require(hasPassphrase || settings.isBackupConfigured) { "Ingen sikkerhetskopi er satt opp" }
|
||||
|
||||
// Google Auto Backup blob: written whenever a passphrase exists.
|
||||
writeCloudBlob()
|
||||
val s3Key = if (settings.isBackupConfigured) runAutoBackup() else null
|
||||
return BackupOutcome(cloudBlobWritten = hasPassphrase, s3Key = s3Key)
|
||||
}
|
||||
|
||||
/**
|
||||
* Unattended backup → S3. Encrypts with the STORED passphrase if one is
|
||||
* configured (protects against bucket compromise only — see SettingsStore),
|
||||
|
|
|
|||
|
|
@ -191,8 +191,15 @@ fun BackupSettingsScreen(nav: Nav) {
|
|||
onClick = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val key = BackupManager(context).runAutoBackup()
|
||||
withContext(Dispatchers.Main) { toast("Lastet opp: $key") }
|
||||
val r = BackupManager(context).runConfiguredBackups()
|
||||
val msg = buildString {
|
||||
if (r.cloudBlobWritten) append("Kryptert Google-kopi oppdatert")
|
||||
if (r.s3Key != null) {
|
||||
if (isNotEmpty()) append("\n")
|
||||
append("Lastet opp til bøtta: ${r.s3Key}")
|
||||
}
|
||||
}
|
||||
withContext(Dispatchers.Main) { toast(msg) }
|
||||
} catch (e: Exception) {
|
||||
withContext(Dispatchers.Main) { toast("Backup feilet: ${e.message}") }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue