diff --git a/app/src/main/java/com/stevesoltys/seedvault/App.kt b/app/src/main/java/com/stevesoltys/seedvault/App.kt index 6aaeeb26..a443b3bc 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/App.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/App.kt @@ -46,7 +46,7 @@ open class App : Application() { factory { AppListRetriever(this@App, get(), get(), get()) } viewModel { SettingsViewModel(this@App, get(), get(), get(), get(), get(), get()) } - viewModel { RecoveryCodeViewModel(this@App, get(), get(), get()) } + viewModel { RecoveryCodeViewModel(this@App, get(), get(), get(), get(), get()) } viewModel { BackupStorageViewModel(this@App, get(), get(), get(), get()) } viewModel { RestoreStorageViewModel(this@App, get(), get()) } viewModel { RestoreViewModel(this@App, get(), get(), get(), get(), get(), get()) } diff --git a/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsProviderBackupPlugin.kt b/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsProviderBackupPlugin.kt index 9789b434..c71d4509 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsProviderBackupPlugin.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsProviderBackupPlugin.kt @@ -44,11 +44,6 @@ internal class DocumentsProviderBackupPlugin( storage.currentFullBackupDir ?: throw IOException() } - @Throws(IOException::class) - override suspend fun deleteAllBackups() { - storage.rootBackupDir?.deleteContents(context) - } - @Throws(IOException::class) override suspend fun getMetadataOutputStream(): OutputStream { val setDir = storage.getSetDir() ?: throw IOException() diff --git a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupPlugin.kt b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupPlugin.kt index 5a08a63a..f8672503 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupPlugin.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupPlugin.kt @@ -25,12 +25,6 @@ interface BackupPlugin { @Throws(IOException::class) suspend fun initializeDevice() - /** - * Delete all existing [RestoreSet]s from the storage medium. - */ - @Throws(IOException::class) - suspend fun deleteAllBackups() - /** * Returns an [OutputStream] for writing backup metadata. */ diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt index 1bde12c7..4b707b84 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt @@ -192,7 +192,7 @@ class RecoveryCodeInputFragment : Fragment() { private val regenRequest = registerForActivityResult(StartActivityForResult()) { if (it.resultCode == RESULT_OK) { - viewModel.deleteAllBackup() + viewModel.reinitializeBackupLocation() parentFragmentManager.popBackStack() Snackbar.make(requireView(), R.string.recovery_code_recreated, Snackbar.LENGTH_LONG) .show() diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeViewModel.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeViewModel.kt index c3069475..3b8c6173 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeViewModel.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeViewModel.kt @@ -1,11 +1,14 @@ package com.stevesoltys.seedvault.ui.recoverycode +import android.app.backup.IBackupManager +import android.os.UserHandle import android.util.Log import androidx.lifecycle.AndroidViewModel import com.stevesoltys.seedvault.App import com.stevesoltys.seedvault.crypto.Crypto import com.stevesoltys.seedvault.crypto.KeyManager -import com.stevesoltys.seedvault.transport.backup.BackupPlugin +import com.stevesoltys.seedvault.transport.TRANSPORT_ID +import com.stevesoltys.seedvault.transport.backup.BackupCoordinator import com.stevesoltys.seedvault.ui.LiveEvent import com.stevesoltys.seedvault.ui.MutableLiveEvent import io.github.novacrypto.bip39.JavaxPBKDF2WithHmacSHA512 @@ -21,6 +24,7 @@ import io.github.novacrypto.bip39.wordlists.English import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch +import org.calyxos.backup.storage.api.StorageBackup import java.io.IOException import java.security.SecureRandom import java.util.ArrayList @@ -28,11 +32,15 @@ import java.util.ArrayList internal const val WORD_NUM = 12 internal const val WORD_LIST_SIZE = 2048 -class RecoveryCodeViewModel( +private val TAG = RecoveryCodeViewModel::class.java.simpleName + +internal class RecoveryCodeViewModel( app: App, private val crypto: Crypto, private val keyManager: KeyManager, - private val backupPlugin: BackupPlugin + private val backupManager: IBackupManager, + private val backupCoordinator: BackupCoordinator, + private val storageBackup: StorageBackup ) : AndroidViewModel(app) { internal val wordList: List by lazy { @@ -79,12 +87,32 @@ class RecoveryCodeViewModel( } } - fun deleteAllBackup() { + /** + * Deletes all storage backups for current user and clears the storage backup cache. + * Also starts a new app data restore set and initializes it. + * + * The reason is that old backups won't be readable anymore with the new key. + * We can't delete other backups safely, because we can't be sure + * that they don't belong to a different device or user. + */ + fun reinitializeBackupLocation() { + Log.d(TAG, "Re-initializing backup location...") GlobalScope.launch(Dispatchers.IO) { + // remove old storage snapshots and clear cache + storageBackup.deleteAllSnapshots() + storageBackup.clearCache() try { - backupPlugin.deleteAllBackups() + // will also generate a new backup token for the new restore set + backupCoordinator.startNewRestoreSet() + + // initialize the new location + backupManager.initializeTransportsForUser( + UserHandle.myUserId(), + arrayOf(TRANSPORT_ID), + null + ) } catch (e: IOException) { - Log.e("RecoveryCodeViewModel", "Error deleting backups", e) + Log.e(TAG, "Error starting new RestoreSet", e) } } }