Skip to content
Snippets Groups Projects
Commit 053303c9 authored by Matthias Urhahn's avatar Matthias Urhahn
Browse files

Merge branch 'release/1.5.x' into fix/1.5.x-into-1.6.x

# Conflicts:
#	Corona-Warn-App/build.gradle
#	Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainFragment.kt
parents 0f6b440a 75e9312a
No related branches found
No related tags found
No related merge requests found
...@@ -14,17 +14,20 @@ class RecoveryByResetDialogFactory(private val fragment: Fragment) { ...@@ -14,17 +14,20 @@ class RecoveryByResetDialogFactory(private val fragment: Fragment) {
fun showDialog( fun showDialog(
@StringRes detailsLink: Int, @StringRes detailsLink: Int,
onDismiss: () -> Unit onPositive: () -> Unit
) { ) {
AlertDialog.Builder(context) val dialog = AlertDialog.Builder(context)
.setTitle(R.string.errors_generic_headline) .setTitle(R.string.errors_generic_headline)
.setMessage(R.string.errors_generic_text_catastrophic_error_recovery_via_reset) .setMessage(R.string.errors_generic_text_catastrophic_error_recovery_via_reset)
.setCancelable(false) .setCancelable(false)
.setOnDismissListener { onDismiss() } .setNeutralButton(R.string.errors_generic_button_negative, null)
.setNeutralButton(R.string.errors_generic_button_negative) { _, _ -> .setPositiveButton(R.string.errors_generic_button_positive) { _, _ ->
ExternalActionHelper.openUrl(fragment, context.getString(detailsLink)) onPositive()
} }
.setPositiveButton(R.string.errors_generic_button_positive) { _, _ -> } .create()
.show() dialog.show()
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)?.setOnClickListener {
ExternalActionHelper.openUrl(fragment, context.getString(detailsLink))
}
} }
} }
...@@ -74,8 +74,8 @@ class EncryptionErrorResetTool @Inject constructor( ...@@ -74,8 +74,8 @@ class EncryptionErrorResetTool @Inject constructor(
} }
isResetWindowConsumed = true isResetWindowConsumed = true
val keyException = error.causes().singleOrNull { it is GeneralSecurityException } val keyException = error.causes().lastOrNull()
if (keyException == null) { if (keyException == null || keyException !is GeneralSecurityException) {
Timber.v("Error has no GeneralSecurityException as cause -> no reset.") Timber.v("Error has no GeneralSecurityException as cause -> no reset.")
return false return false
} }
......
...@@ -16,7 +16,9 @@ import org.junit.jupiter.api.Test ...@@ -16,7 +16,9 @@ import org.junit.jupiter.api.Test
import testhelpers.BaseIOTest import testhelpers.BaseIOTest
import testhelpers.preferences.MockSharedPreferences import testhelpers.preferences.MockSharedPreferences
import java.io.File import java.io.File
import java.io.IOException
import java.security.GeneralSecurityException import java.security.GeneralSecurityException
import java.security.KeyException
import java.security.KeyStoreException import java.security.KeyStoreException
class EncryptionResetToolTest : BaseIOTest() { class EncryptionResetToolTest : BaseIOTest() {
...@@ -199,6 +201,86 @@ class EncryptionResetToolTest : BaseIOTest() { ...@@ -199,6 +201,86 @@ class EncryptionResetToolTest : BaseIOTest() {
} }
} }
@Test
fun `nested exception may have the same base exception type, ie GeneralSecurityException`() {
// https://github.com/corona-warn-app/cwa-app-android/issues/642#issuecomment-712188157
createMockFiles()
createInstance().tryResetIfNecessary(
KeyException( // subclass of GeneralSecurityException
"Permantly failed to instantiate encrypted preferences",
SecurityException(
"Could not decrypt key. decryption failed",
GeneralSecurityException("decryption failed")
)
)
) shouldBe true
encryptedPrefsFile.exists() shouldBe false
encryptedDatabaseFile.exists() shouldBe false
mockPreferences.dataMapPeek.apply {
this["ea1851.reset.performedAt"] shouldNotBe null
this["ea1851.reset.windowconsumed"] shouldBe true
this["ea1851.reset.shownotice"] shouldBe true
}
}
@Test
fun `exception check does not care about the first exception type`() {
createMockFiles()
createInstance().tryResetIfNecessary(
CwaSecurityException(
KeyException( // subclass of GeneralSecurityException
"Permantly failed to instantiate encrypted preferences",
SecurityException(
"Could not decrypt key. decryption failed",
GeneralSecurityException("decryption failed")
)
)
)
) shouldBe true
encryptedPrefsFile.exists() shouldBe false
encryptedDatabaseFile.exists() shouldBe false
mockPreferences.dataMapPeek.apply {
this["ea1851.reset.performedAt"] shouldNotBe null
this["ea1851.reset.windowconsumed"] shouldBe true
this["ea1851.reset.shownotice"] shouldBe true
}
}
@Test
fun `exception check DOES care about the most nested exception`() {
createMockFiles()
createInstance().tryResetIfNecessary(
CwaSecurityException(
KeyException( // subclass of GeneralSecurityException
"Permantly failed to instantiate encrypted preferences",
SecurityException(
"Could not decrypt key. decryption failed",
GeneralSecurityException(
"decryption failed",
IOException("I am unexpeted")
)
)
)
)
) shouldBe false
encryptedPrefsFile.exists() shouldBe true
encryptedDatabaseFile.exists() shouldBe true
mockPreferences.dataMapPeek.apply {
this["ea1851.reset.performedAt"] shouldBe null
this["ea1851.reset.windowconsumed"] shouldBe true
this["ea1851.reset.shownotice"] shouldBe null
}
}
@Test @Test
fun `we want only a specific type of GeneralSecurityException`() { fun `we want only a specific type of GeneralSecurityException`() {
createMockFiles() createMockFiles()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment