Re-initialize backup location when changing recovery code
* delete all storage backups for current user * clears the storage backup cache * start 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 also can't delete other backups safely as we did before, because we can't be sure that they don't belong to a different device or user.
This commit is contained in:
parent
347d2a316f
commit
1ff8e54748
5 changed files with 36 additions and 19 deletions
|
@ -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()) }
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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<CharSequence> 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue