From e8e2e95e022c7ab995feb892f69f0f29734b6416 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Dec 2023 17:40:47 +0100 Subject: [PATCH 1/2] Follow SDK method renaming: fix_recovery_issues() got renamed to recover() --- .../enter/SecureBackupEnterRecoveryKeyPresenter.kt | 2 +- .../enter/SecureBackupEnterRecoveryKeyPresenterTest.kt | 4 ++-- .../matrix/api/encryption/EncryptionService.kt | 4 ++-- .../matrix/impl/encryption/RustEncryptionService.kt | 2 +- .../matrix/test/encryption/FakeEncryptionService.kt | 10 +++++----- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenter.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenter.kt index bec4dd9217..9207dbef79 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenter.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenter.kt @@ -89,7 +89,7 @@ class SecureBackupEnterRecoveryKeyPresenter @Inject constructor( action: MutableState> ) = launch { suspend { - encryptionService.fixRecoveryIssues(recoveryKey).getOrThrow() + encryptionService.recover(recoveryKey).getOrThrow() }.runCatchingUpdatingState(action) } } diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenterTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenterTest.kt index d34f869f6e..862cbbde72 100644 --- a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenterTest.kt +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/enter/SecureBackupEnterRecoveryKeyPresenterTest.kt @@ -73,7 +73,7 @@ class SecureBackupEnterRecoveryKeyPresenterTest { inProgress = false, ) ) - encryptionService.givenFixRecoveryIssuesFailure(AN_EXCEPTION) + encryptionService.givenRecoverFailure(AN_EXCEPTION) withRecoveryKeyState.eventSink(SecureBackupEnterRecoveryKeyEvents.Submit) val loadingState = awaitItem() assertThat(loadingState.submitAction).isEqualTo(Async.Loading()) @@ -85,7 +85,7 @@ class SecureBackupEnterRecoveryKeyPresenterTest { val clearedState = awaitItem() assertThat(clearedState.submitAction).isEqualTo(Async.Uninitialized) assertThat(clearedState.isSubmitEnabled).isTrue() - encryptionService.givenFixRecoveryIssuesFailure(null) + encryptionService.givenRecoverFailure(null) clearedState.eventSink(SecureBackupEnterRecoveryKeyEvents.Submit) val loadingState2 = awaitItem() assertThat(loadingState2.submitAction).isEqualTo(Async.Loading()) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt index 534f5b68e2..522445b6c2 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EncryptionService.kt @@ -43,9 +43,9 @@ interface EncryptionService { suspend fun doesBackupExistOnServer(): Result /** - * Note: accept bot recoveryKey and passphrase. + * Note: accept both recoveryKey and passphrase. */ - suspend fun fixRecoveryIssues(recoveryKey: String): Result + suspend fun recover(recoveryKey: String): Result /** * Wait for backup upload steady state. diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt index 10929f0494..c3f1f8e52e 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt @@ -179,7 +179,7 @@ internal class RustEncryptionService( } } - override suspend fun fixRecoveryIssues(recoveryKey: String): Result = withContext(dispatchers.io) { + override suspend fun recover(recoveryKey: String): Result = withContext(dispatchers.io) { runCatching { service.recover(recoveryKey) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt index f8a2d411fe..44b9d734a5 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt @@ -33,7 +33,7 @@ class FakeEncryptionService : EncryptionService { override val enableRecoveryProgressStateFlow: MutableStateFlow = MutableStateFlow(EnableRecoveryProgress.Starting) private var waitForBackupUploadSteadyStateFlow: Flow = flowOf() - private var fixRecoveryIssuesFailure: Exception? = null + private var recoverFailure: Exception? = null private var doesBackupExistOnServerResult: Result = Result.success(true) override suspend fun enableBackups(): Result = simulateLongTask { @@ -44,8 +44,8 @@ class FakeEncryptionService : EncryptionService { disableRecoveryFailure = exception } - fun givenFixRecoveryIssuesFailure(exception: Exception?) { - fixRecoveryIssuesFailure = exception + fun givenRecoverFailure(exception: Exception?) { + recoverFailure = exception } override suspend fun disableRecovery(): Result = simulateLongTask { @@ -61,8 +61,8 @@ class FakeEncryptionService : EncryptionService { return doesBackupExistOnServerResult } - override suspend fun fixRecoveryIssues(recoveryKey: String): Result = simulateLongTask { - fixRecoveryIssuesFailure?.let { return Result.failure(it) } + override suspend fun recover(recoveryKey: String): Result = simulateLongTask { + recoverFailure?.let { return Result.failure(it) } return Result.success(Unit) } From 9ee339aafbaaf5beb4f61784df321f5b69f4bb92 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Dec 2023 18:11:33 +0100 Subject: [PATCH 2/2] Map RecoveryException --- .../api/encryption/RecoveryException.kt | 25 +++++++++++++ .../encryption/RecoveryExceptionMapper.kt | 37 +++++++++++++++++++ .../impl/encryption/RustEncryptionService.kt | 13 +++++++ 3 files changed, 75 insertions(+) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/RecoveryException.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/RecoveryException.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/RecoveryException.kt new file mode 100644 index 0000000000..fae2dad083 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/RecoveryException.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.encryption + +import io.element.android.libraries.matrix.api.exception.ClientException + +sealed class RecoveryException(message: String) : Exception(message) { + class SecretStorage(message: String) : RecoveryException(message) + data object BackupExistsOnServer : RecoveryException("BackupExistsOnServer") + data class Client(val exception: ClientException) : RecoveryException(exception.message ?: "Unknown error") +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt new file mode 100644 index 0000000000..b21e035602 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.impl.encryption + +import io.element.android.libraries.matrix.api.encryption.RecoveryException +import io.element.android.libraries.matrix.api.exception.ClientException +import io.element.android.libraries.matrix.impl.exception.mapClientException +import org.matrix.rustcomponents.sdk.RecoveryException as RustRecoveryException + +fun Throwable.mapRecoveryException(): RecoveryException { + return when (this) { + is RustRecoveryException.SecretStorage -> RecoveryException.SecretStorage( + message = errorMessage + ) + is RustRecoveryException.BackupExistsOnServer -> RecoveryException.BackupExistsOnServer + is RustRecoveryException.Client -> RecoveryException.Client( + source.mapClientException() + ) + else -> RecoveryException.Client( + ClientException.Other("Unknown error") + ) + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt index c3f1f8e52e..8732645330 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt @@ -17,6 +17,7 @@ package io.element.android.libraries.matrix.impl.encryption import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.core.extensions.mapFailure import io.element.android.libraries.matrix.api.encryption.BackupState import io.element.android.libraries.matrix.api.encryption.BackupUploadState import io.element.android.libraries.matrix.api.encryption.EnableRecoveryProgress @@ -110,6 +111,8 @@ internal class RustEncryptionService( override suspend fun enableBackups(): Result = withContext(dispatchers.io) { runCatching { service.enableBackups() + }.mapFailure { + it.mapRecoveryException() } } @@ -127,6 +130,8 @@ internal class RustEncryptionService( ) // enableRecovery returns the encryption key, but we read it from the state flow .let { } + }.mapFailure { + it.mapRecoveryException() } } @@ -164,24 +169,32 @@ internal class RustEncryptionService( override suspend fun disableRecovery(): Result = withContext(dispatchers.io) { runCatching { service.disableRecovery() + }.mapFailure { + it.mapRecoveryException() } } override suspend fun isLastDevice(): Result = withContext(dispatchers.io) { runCatching { service.isLastDevice() + }.mapFailure { + it.mapRecoveryException() } } override suspend fun resetRecoveryKey(): Result = withContext(dispatchers.io) { runCatching { service.resetRecoveryKey() + }.mapFailure { + it.mapRecoveryException() } } override suspend fun recover(recoveryKey: String): Result = withContext(dispatchers.io) { runCatching { service.recover(recoveryKey) + }.mapFailure { + it.mapRecoveryException() } } }