Delete all backups (if possible) when user generates a new recovery code

This commit is contained in:
Torsten Grote 2020-11-19 11:20:24 -03:00 committed by Chirayu Desai
parent 395cc4c899
commit 4271fd6005
5 changed files with 31 additions and 3 deletions

View file

@ -44,7 +44,7 @@ class App : Application() {
factory { AppListRetriever(this@App, get(), get(), get()) } factory { AppListRetriever(this@App, get(), get(), get()) }
viewModel { SettingsViewModel(this@App, get(), get(), get(), get(), get()) } viewModel { SettingsViewModel(this@App, get(), get(), get(), get(), get()) }
viewModel { RecoveryCodeViewModel(this@App, get(), get()) } viewModel { RecoveryCodeViewModel(this@App, get(), get(), get()) }
viewModel { BackupStorageViewModel(this@App, get(), get(), get()) } viewModel { BackupStorageViewModel(this@App, get(), get(), get()) }
viewModel { RestoreStorageViewModel(this@App, get(), get()) } viewModel { RestoreStorageViewModel(this@App, get(), get()) }
viewModel { RestoreViewModel(this@App, get(), get(), get(), get(), get()) } viewModel { RestoreViewModel(this@App, get(), get(), get(), get(), get()) }

View file

@ -44,6 +44,11 @@ internal class DocumentsProviderBackupPlugin(
storage.currentFullBackupDir ?: throw IOException() storage.currentFullBackupDir ?: throw IOException()
} }
@Throws(IOException::class)
override suspend fun deleteAllBackups() {
storage.rootBackupDir?.deleteContents(context)
}
@Throws(IOException::class) @Throws(IOException::class)
override suspend fun getMetadataOutputStream(): OutputStream { override suspend fun getMetadataOutputStream(): OutputStream {
val setDir = storage.getSetDir() ?: throw IOException() val setDir = storage.getSetDir() ?: throw IOException()

View file

@ -25,6 +25,12 @@ interface BackupPlugin {
@Throws(IOException::class) @Throws(IOException::class)
suspend fun initializeDevice() 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. * Returns an [OutputStream] for writing backup metadata.
*/ */

View file

@ -190,6 +190,7 @@ class RecoveryCodeInputFragment : Fragment() {
private val regenRequest = registerForActivityResult(StartActivityForResult()) { private val regenRequest = registerForActivityResult(StartActivityForResult()) {
if (it.resultCode == RESULT_OK) { if (it.resultCode == RESULT_OK) {
viewModel.deleteAllBackup()
parentFragmentManager.popBackStack() parentFragmentManager.popBackStack()
Snackbar.make(requireView(), R.string.recovery_code_recreated, Snackbar.LENGTH_LONG) Snackbar.make(requireView(), R.string.recovery_code_recreated, Snackbar.LENGTH_LONG)
.show() .show()
@ -203,7 +204,6 @@ class RecoveryCodeInputFragment : Fragment() {
.setMessage(R.string.recovery_code_verification_new_dialog_message) .setMessage(R.string.recovery_code_verification_new_dialog_message)
.setPositiveButton(R.string.recovery_code_verification_generate_new) { dialog, _ -> .setPositiveButton(R.string.recovery_code_verification_generate_new) { dialog, _ ->
dialog.dismiss() dialog.dismiss()
// TODO try to delete backups
val i = Intent(requireContext(), RecoveryCodeActivity::class.java) val i = Intent(requireContext(), RecoveryCodeActivity::class.java)
regenRequest.launch(i) regenRequest.launch(i)
} }

View file

@ -1,9 +1,11 @@
package com.stevesoltys.seedvault.ui.recoverycode package com.stevesoltys.seedvault.ui.recoverycode
import android.util.Log
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import com.stevesoltys.seedvault.App import com.stevesoltys.seedvault.App
import com.stevesoltys.seedvault.crypto.Crypto import com.stevesoltys.seedvault.crypto.Crypto
import com.stevesoltys.seedvault.crypto.KeyManager import com.stevesoltys.seedvault.crypto.KeyManager
import com.stevesoltys.seedvault.transport.backup.BackupPlugin
import com.stevesoltys.seedvault.ui.LiveEvent import com.stevesoltys.seedvault.ui.LiveEvent
import com.stevesoltys.seedvault.ui.MutableLiveEvent import com.stevesoltys.seedvault.ui.MutableLiveEvent
import io.github.novacrypto.bip39.JavaxPBKDF2WithHmacSHA512 import io.github.novacrypto.bip39.JavaxPBKDF2WithHmacSHA512
@ -16,6 +18,10 @@ import io.github.novacrypto.bip39.Validation.UnexpectedWhiteSpaceException
import io.github.novacrypto.bip39.Validation.WordNotFoundException import io.github.novacrypto.bip39.Validation.WordNotFoundException
import io.github.novacrypto.bip39.Words import io.github.novacrypto.bip39.Words
import io.github.novacrypto.bip39.wordlists.English import io.github.novacrypto.bip39.wordlists.English
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.IOException
import java.security.SecureRandom import java.security.SecureRandom
import java.util.ArrayList import java.util.ArrayList
@ -25,7 +31,8 @@ internal const val WORD_LIST_SIZE = 2048
class RecoveryCodeViewModel( class RecoveryCodeViewModel(
app: App, app: App,
private val crypto: Crypto, private val crypto: Crypto,
private val keyManager: KeyManager private val keyManager: KeyManager,
private val backupPlugin: BackupPlugin
) : AndroidViewModel(app) { ) : AndroidViewModel(app) {
internal val wordList: List<CharSequence> by lazy { internal val wordList: List<CharSequence> by lazy {
@ -69,4 +76,14 @@ class RecoveryCodeViewModel(
} }
} }
fun deleteAllBackup() {
GlobalScope.launch(Dispatchers.IO) {
try {
backupPlugin.deleteAllBackups()
} catch (e: IOException) {
Log.e("RecoveryCodeViewModel", "Error deleting backups", e)
}
}
}
} }