diff options
8 files changed, 72 insertions, 102 deletions
diff --git a/app/src/main/java/app/passwordstore/data/crypto/CryptoRepository.kt b/app/src/main/java/app/passwordstore/data/crypto/CryptoRepository.kt index 0ce4b3e3..50d7a841 100644 --- a/app/src/main/java/app/passwordstore/data/crypto/CryptoRepository.kt +++ b/app/src/main/java/app/passwordstore/data/crypto/CryptoRepository.kt @@ -16,7 +16,7 @@ import app.passwordstore.injection.prefs.SettingsPreferences import app.passwordstore.util.coroutines.DispatcherProvider import app.passwordstore.util.settings.PreferenceKeys import com.github.michaelbull.result.Result -import com.github.michaelbull.result.getAll +import com.github.michaelbull.result.filterValues import com.github.michaelbull.result.mapBoth import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream @@ -57,7 +57,7 @@ constructor( message: ByteArrayInputStream, out: ByteArrayOutputStream, ): Result<Unit, CryptoHandlerException> { - val keys = identities.map { id -> pgpKeyManager.getKeyById(id) }.getAll() + val keys = identities.map { id -> pgpKeyManager.getKeyById(id) }.filterValues() val decryptionOptions = PGPDecryptOptions.Builder().build() return pgpCryptoHandler.decrypt(keys, password, message, out, decryptionOptions) } @@ -71,7 +71,7 @@ constructor( PGPEncryptOptions.Builder() .withAsciiArmor(settings.getBoolean(PreferenceKeys.ASCII_ARMOR, false)) .build() - val keys = identities.map { id -> pgpKeyManager.getKeyById(id) }.getAll() + val keys = identities.map { id -> pgpKeyManager.getKeyById(id) }.filterValues() return pgpCryptoHandler.encrypt( keys, content, diff --git a/app/src/main/java/app/passwordstore/ui/crypto/DecryptActivity.kt b/app/src/main/java/app/passwordstore/ui/crypto/DecryptActivity.kt index 31934d26..895ac50d 100644 --- a/app/src/main/java/app/passwordstore/ui/crypto/DecryptActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/crypto/DecryptActivity.kt @@ -27,8 +27,6 @@ import app.passwordstore.util.features.Feature.EnablePGPPassphraseCache import app.passwordstore.util.features.Features import app.passwordstore.util.settings.Constants import app.passwordstore.util.settings.PreferenceKeys -import com.github.michaelbull.result.Err -import com.github.michaelbull.result.Ok import com.github.michaelbull.result.runCatching import dagger.hilt.android.AndroidEntryPoint import java.io.ByteArrayOutputStream @@ -214,18 +212,16 @@ class DecryptActivity : BasePGPActivity() { authResult: BiometricResult, onSuccess: suspend () -> Unit = {}, ) { - when (val result = decryptPGPStream(passphrase, identifiers)) { - is Ok -> { - val entry = passwordEntryFactory.create(result.value.toByteArray()) - passwordEntry = entry - createPasswordUI(entry) - startAutoDismissTimer() - onSuccess() - } - is Err -> { - logcat(ERROR) { result.error.stackTraceToString() } - decrypt(isError = true, authResult = authResult) - } + val result = decryptPGPStream(passphrase, identifiers) + if (result.isOk) { + val entry = passwordEntryFactory.create(result.value.toByteArray()) + passwordEntry = entry + createPasswordUI(entry) + startAutoDismissTimer() + onSuccess() + } else { + logcat(ERROR) { result.error.stackTraceToString() } + decrypt(isError = true, authResult = authResult) } } @@ -242,10 +238,7 @@ class DecryptActivity : BasePGPActivity() { message, outputStream, ) - when (result) { - is Ok -> outputStream - is Err -> throw result.error - } + if (result.isOk) outputStream else throw result.error } private suspend fun createPasswordUI(entry: PasswordEntry) = diff --git a/app/src/main/java/app/passwordstore/ui/pgp/PGPKeyImportActivity.kt b/app/src/main/java/app/passwordstore/ui/pgp/PGPKeyImportActivity.kt index 0b3fdd4e..03a8f95c 100644 --- a/app/src/main/java/app/passwordstore/ui/pgp/PGPKeyImportActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/pgp/PGPKeyImportActivity.kt @@ -14,8 +14,6 @@ import app.passwordstore.crypto.KeyUtils.tryGetId import app.passwordstore.crypto.PGPKey import app.passwordstore.crypto.PGPKeyManager import app.passwordstore.crypto.errors.KeyAlreadyExistsException -import com.github.michaelbull.result.Err -import com.github.michaelbull.result.Ok import com.github.michaelbull.result.Result import com.github.michaelbull.result.runCatching import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -69,45 +67,42 @@ class PGPKeyImportActivity : AppCompatActivity() { } private fun handleImportResult(result: Result<PGPKey?, Throwable>) { - when (result) { - is Ok<PGPKey?> -> { - val key = result.value - if (key == null) { - setResult(RESULT_CANCELED) + if (result.isOk) { + val key = result.value + if (key == null) { + setResult(RESULT_CANCELED) + finish() + // This return convinces Kotlin that the control flow for `key == null` definitely + // terminates here and allows for a smart cast below. + return + } + MaterialAlertDialogBuilder(this) + .setTitle(getString(R.string.pgp_key_import_succeeded)) + .setMessage(getString(R.string.pgp_key_import_succeeded_message, tryGetId(key))) + .setPositiveButton(android.R.string.ok) { _, _ -> + setResult(RESULT_OK) finish() - // This return convinces Kotlin that the control flow for `key == null` definitely - // terminates here and allows for a smart cast below. - return } + .setCancelable(false) + .show() + } else { + if (result.error is KeyAlreadyExistsException && lastBytes != null) { MaterialAlertDialogBuilder(this) - .setTitle(getString(R.string.pgp_key_import_succeeded)) - .setMessage(getString(R.string.pgp_key_import_succeeded_message, tryGetId(key))) - .setPositiveButton(android.R.string.ok) { _, _ -> - setResult(RESULT_OK) - finish() + .setTitle(getString(R.string.pgp_key_import_failed)) + .setMessage(getString(R.string.pgp_key_import_failed_replace_message)) + .setPositiveButton(R.string.dialog_yes) { _, _ -> + handleImportResult(runCatching { importKey(lastBytes!!, replace = true) }) } + .setNegativeButton(R.string.dialog_no) { _, _ -> finish() } + .setCancelable(false) + .show() + } else { + MaterialAlertDialogBuilder(this) + .setTitle(getString(R.string.pgp_key_import_failed)) + .setMessage(result.error.message) + .setPositiveButton(android.R.string.ok) { _, _ -> finish() } .setCancelable(false) .show() - } - is Err<Throwable> -> { - if (result.error is KeyAlreadyExistsException && lastBytes != null) { - MaterialAlertDialogBuilder(this) - .setTitle(getString(R.string.pgp_key_import_failed)) - .setMessage(getString(R.string.pgp_key_import_failed_replace_message)) - .setPositiveButton(R.string.dialog_yes) { _, _ -> - handleImportResult(runCatching { importKey(lastBytes!!, replace = true) }) - } - .setNegativeButton(R.string.dialog_no) { _, _ -> finish() } - .setCancelable(false) - .show() - } else { - MaterialAlertDialogBuilder(this) - .setTitle(getString(R.string.pgp_key_import_failed)) - .setMessage(result.error.message) - .setPositiveButton(android.R.string.ok) { _, _ -> finish() } - .setCancelable(false) - .show() - } } } } diff --git a/app/src/main/java/app/passwordstore/util/extensions/Extensions.kt b/app/src/main/java/app/passwordstore/util/extensions/Extensions.kt index c6fd9ceb..a921f8d6 100644 --- a/app/src/main/java/app/passwordstore/util/extensions/Extensions.kt +++ b/app/src/main/java/app/passwordstore/util/extensions/Extensions.kt @@ -5,8 +5,6 @@ package app.passwordstore.util.extensions import app.passwordstore.data.repo.PasswordRepository -import com.github.michaelbull.result.Err -import com.github.michaelbull.result.Result import com.github.michaelbull.result.getOrElse import com.github.michaelbull.result.runCatching import java.io.File @@ -68,8 +66,3 @@ fun <T> unsafeLazy(initializer: () -> T) = lazy(LazyThreadSafetyMode.NONE) { ini /** A convenience extension to turn a [Throwable] with a message into a loggable string. */ fun Throwable.asLog(message: String): String = "$message\n${asLog()}" - -/** Extension on [Result] that returns if the type is [Err] */ -fun <V, E> Result<V, E>.isErr(): Boolean { - return this is Err<E> -} diff --git a/app/src/main/java/app/passwordstore/util/viewmodel/PGPKeyListViewModel.kt b/app/src/main/java/app/passwordstore/util/viewmodel/PGPKeyListViewModel.kt index 6711cae1..c5099ace 100644 --- a/app/src/main/java/app/passwordstore/util/viewmodel/PGPKeyListViewModel.kt +++ b/app/src/main/java/app/passwordstore/util/viewmodel/PGPKeyListViewModel.kt @@ -8,9 +8,8 @@ import androidx.lifecycle.viewModelScope import app.passwordstore.crypto.KeyUtils import app.passwordstore.crypto.PGPIdentifier import app.passwordstore.crypto.PGPKeyManager -import com.github.michaelbull.result.Err -import com.github.michaelbull.result.Ok import com.github.michaelbull.result.map +import com.github.michaelbull.result.onSuccess import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject import kotlinx.collections.immutable.ImmutableList @@ -28,15 +27,10 @@ class PGPKeyListViewModel @Inject constructor(private val keyManager: PGPKeyMana fun updateKeySet() { viewModelScope.launch { - when ( - val result = - keyManager.getAllKeys().map { keys -> - keys.mapNotNull { key -> KeyUtils.tryGetEmail(key) } - } - ) { - is Ok -> keys = result.value.toPersistentList() - is Err -> TODO() - } + keyManager + .getAllKeys() + .map { keys -> keys.mapNotNull { key -> KeyUtils.tryGetEmail(key) } } + .onSuccess { keys = it.toPersistentList() } } } diff --git a/crypto/pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPKeyManagerTest.kt b/crypto/pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPKeyManagerTest.kt index 85cf8e1b..d0cc693e 100644 --- a/crypto/pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPKeyManagerTest.kt +++ b/crypto/pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPKeyManagerTest.kt @@ -7,8 +7,6 @@ import app.passwordstore.crypto.errors.KeyAlreadyExistsException import app.passwordstore.crypto.errors.KeyNotFoundException import app.passwordstore.crypto.errors.NoKeysAvailableException import app.passwordstore.crypto.errors.UnusableKeyException -import com.github.michaelbull.result.Err -import com.github.michaelbull.result.Ok import com.github.michaelbull.result.unwrap import com.github.michaelbull.result.unwrapError import java.io.File @@ -18,8 +16,8 @@ import kotlin.test.assertEquals import kotlin.test.assertIs import kotlin.test.assertNotEquals import kotlin.test.assertNotNull +import kotlin.test.assertTrue import kotlinx.coroutines.test.StandardTestDispatcher -import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.rules.TemporaryFolder @@ -28,7 +26,6 @@ class PGPKeyManagerTest { @get:Rule val temporaryFolder: TemporaryFolder = TemporaryFolder() private val dispatcher = StandardTestDispatcher() - private val scope = TestScope(dispatcher) private val filesDir by unsafeLazy { temporaryFolder.root } private val keysDir by unsafeLazy { File(filesDir, PGPKeyManager.KEY_DIR_NAME) } private val keyManager by unsafeLazy { PGPKeyManager(filesDir.absolutePath, dispatcher) } @@ -170,24 +167,24 @@ class PGPKeyManagerTest { @Test fun replaceSecretKeyWithPublicKey() = runTest(dispatcher) { - assertIs<Ok<PGPKey>>(keyManager.addKey(secretKey)) - assertIs<Err<KeyAlreadyExistsException>>(keyManager.addKey(publicKey)) + assertTrue(keyManager.addKey(secretKey).isOk) + assertTrue(keyManager.addKey(publicKey).isErr) } @Test fun replacePublicKeyWithSecretKey() = runTest(dispatcher) { - assertIs<Ok<PGPKey>>(keyManager.addKey(publicKey)) - assertIs<Ok<PGPKey>>(keyManager.addKey(secretKey)) + assertTrue(keyManager.addKey(publicKey).isOk) + assertTrue(keyManager.addKey(secretKey).isOk) } @Test fun replacePublicKeyWithPublicKey() = runTest(dispatcher) { - assertIs<Ok<PGPKey>>(keyManager.addKey(publicKey)) - assertIs<Ok<PGPKey>>(keyManager.addKey(publicKey)) + assertTrue(keyManager.addKey(publicKey).isOk) + assertTrue(keyManager.addKey(publicKey).isOk) val allKeys = keyManager.getAllKeys() - assertIs<Ok<List<PGPKey>>>(allKeys) + assertTrue(allKeys.isOk) assertEquals(1, allKeys.value.size) val key = allKeys.value[0] assertContentEquals(publicKey.contents, key.contents) @@ -196,8 +193,8 @@ class PGPKeyManagerTest { @Test fun replaceSecretKeyWithSecretKey() = runTest(dispatcher) { - assertIs<Ok<PGPKey>>(keyManager.addKey(secretKey)) - assertIs<Err<KeyAlreadyExistsException>>(keyManager.addKey(secretKey)) + assertTrue(keyManager.addKey(secretKey).isOk) + assertTrue(keyManager.addKey(secretKey).isErr) } @Test @@ -207,11 +204,11 @@ class PGPKeyManagerTest { PGPKey(this::class.java.classLoader.getResource("alice_owner@example_com")!!.readBytes()) val bobby = PGPKey(this::class.java.classLoader.getResource("bobby_owner@example_com")!!.readBytes()) - assertIs<Ok<PGPKey>>(keyManager.addKey(alice)) - assertIs<Ok<PGPKey>>(keyManager.addKey(bobby)) + assertTrue(keyManager.addKey(alice).isOk) + assertTrue(keyManager.addKey(bobby).isOk) keyManager.getAllKeys().apply { - assertIs<Ok<List<PGPKey>>>(this) + assertTrue(this.isOk) assertEquals(2, this.value.size) } val longKeyIds = @@ -228,8 +225,8 @@ class PGPKeyManagerTest { for (idCollection in arrayOf(longKeyIds, userIds)) { val alice1 = keyManager.getKeyById(idCollection[0]) val bobby1 = keyManager.getKeyById(idCollection[1]) - assertIs<Ok<PGPKey>>(alice1) - assertIs<Ok<PGPKey>>(bobby1) + assertTrue(alice1.isOk) + assertTrue(bobby1.isOk) assertNotEquals(alice1.value.contents, bobby1.value.contents) } } diff --git a/crypto/pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandlerTest.kt b/crypto/pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandlerTest.kt index 8bf6ba1e..4ec4b7fa 100644 --- a/crypto/pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandlerTest.kt +++ b/crypto/pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPainlessCryptoHandlerTest.kt @@ -9,8 +9,6 @@ package app.passwordstore.crypto import app.passwordstore.crypto.CryptoConstants.KEY_PASSPHRASE import app.passwordstore.crypto.CryptoConstants.PLAIN_TEXT import app.passwordstore.crypto.errors.IncorrectPassphraseException -import com.github.michaelbull.result.Err -import com.github.michaelbull.result.Ok import com.github.michaelbull.result.getError import com.google.testing.junit.testparameterinjector.TestParameter import com.google.testing.junit.testparameterinjector.TestParameterInjector @@ -48,7 +46,7 @@ class PGPainlessCryptoHandlerTest { ciphertextStream, PGPEncryptOptions.Builder().build(), ) - assertIs<Ok<Unit>>(encryptRes) + assertTrue(encryptRes.isOk) val plaintextStream = ByteArrayOutputStream() val decryptRes = cryptoHandler.decrypt( @@ -58,7 +56,7 @@ class PGPainlessCryptoHandlerTest { plaintextStream, PGPDecryptOptions.Builder().build(), ) - assertIs<Ok<Unit>>(decryptRes) + assertTrue(decryptRes.isOk) assertEquals(PLAIN_TEXT, plaintextStream.toString(Charsets.UTF_8)) } @@ -72,7 +70,7 @@ class PGPainlessCryptoHandlerTest { ciphertextStream, PGPEncryptOptions.Builder().build(), ) - assertIs<Ok<Unit>>(encryptRes) + assertTrue(encryptRes.isOk) val plaintextStream = ByteArrayOutputStream() val result = cryptoHandler.decrypt( @@ -82,7 +80,7 @@ class PGPainlessCryptoHandlerTest { plaintextStream, PGPDecryptOptions.Builder().build(), ) - assertIs<Err<Throwable>>(result) + assertTrue(result.isErr) assertIs<IncorrectPassphraseException>(result.getError()) } @@ -96,7 +94,7 @@ class PGPainlessCryptoHandlerTest { ciphertextStream, PGPEncryptOptions.Builder().withAsciiArmor(true).build(), ) - assertIs<Ok<Unit>>(encryptRes) + assertTrue(encryptRes.isOk) val ciphertext = ciphertextStream.toString(Charsets.UTF_8) assertContains(ciphertext, "Version: PGPainless") assertContains(ciphertext, "-----BEGIN PGP MESSAGE-----") @@ -118,7 +116,7 @@ class PGPainlessCryptoHandlerTest { ciphertextStream, PGPEncryptOptions.Builder().withAsciiArmor(true).build(), ) - assertIs<Ok<Unit>>(encryptRes) + assertTrue(encryptRes.isOk) val message = ciphertextStream.toByteArray().decodeToString() val info = MessageInspector.determineEncryptionInfoForMessage(message) assertTrue(info.isEncrypted) @@ -135,7 +133,7 @@ class PGPainlessCryptoHandlerTest { plaintextStream, PGPDecryptOptions.Builder().build(), ) - assertIs<Ok<Unit>>(res) + assertTrue(res.isOk) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c7b4b3e4..617aad76 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ coroutines = "1.8.0" flowbinding = "1.2.0" hilt = "2.51" kotlin = "1.9.23" -kotlinResult = "1.1.20" +kotlinResult = "1.1.21" lifecycle = "2.7.0" moshi = "1.15.1" |