From 17d25e25972e5ca96300c835b51cbed9fdb608ab Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Wed, 7 Dec 2022 19:40:22 +0530 Subject: [PATCH] Enable reset all and skip options (#7721) * Dismiss bottomsheet on skipping verification * Enable reset all and skip options * Change ResetAll bottomsheet event to no-op for user verification * Fix strings and improve state step logic in SharedSecureStorageViewModel --- .../src/main/res/values/strings.xml | 3 ++ .../room/summary/RoomSummaryUpdater.kt | 3 -- .../timeline/RoomSummaryEventDecryptor.kt | 10 ++-- .../session/crypto/keysbackup/BackupUtils.kt | 2 - .../android/sdk/internal/crypto/OlmMachine.kt | 2 - .../quads/SharedSecureStorageActivity.kt | 13 +++-- .../quads/SharedSecureStorageViewModel.kt | 52 +++++++++++-------- .../crypto/verification/VerificationAction.kt | 1 + .../VerificationBottomSheetViewEvents.kt | 1 + .../self/SelfVerificationBottomSheet.kt | 14 ++++- .../self/SelfVerificationController.kt | 4 +- .../self/SelfVerificationFragment.kt | 4 +- .../self/SelfVerificationViewModel.kt | 13 ++++- .../user/UserVerificationBottomSheet.kt | 3 ++ .../user/UserVerificationViewModel.kt | 3 ++ .../res/layout/fragment_ssss_reset_all.xml | 24 +++------ 16 files changed, 89 insertions(+), 63 deletions(-) diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml index df12d49da6..d6e3cce4b1 100644 --- a/library/ui-strings/src/main/res/values/strings.xml +++ b/library/ui-strings/src/main/res/values/strings.xml @@ -411,6 +411,7 @@ Play Dismiss Reset + Proceed to reset Learn more Next Got it @@ -2635,8 +2636,10 @@ Forgot or lost all recovery options? Reset everything Reset everything Only do this if you have no other device you can verify this device with. + Resetting your verification keys cannot be undone. After resetting, you won\'t have access to old encrypted messages, and any friends who have previously verified you will see security warnings until you re-verify with them. If you reset everything You will restart with no history, no messages, trusted devices or trusted users + Please only proceed if you\'re sure you\'ve lost all of your other devices and your security key. Show the device you can verify with now Show %d devices you can verify with now diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt index 55c73cc05d..0d3f220f9d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt @@ -18,9 +18,7 @@ package org.matrix.android.sdk.internal.session.room.summary import io.realm.Realm import io.realm.kotlin.createObject -import kotlinx.coroutines.runBlocking import org.matrix.android.sdk.api.extensions.orFalse -import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent import org.matrix.android.sdk.api.session.events.model.toModel @@ -41,7 +39,6 @@ import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.sync.model.RoomSyncSummary import org.matrix.android.sdk.api.session.sync.model.RoomSyncUnreadNotifications import org.matrix.android.sdk.api.session.sync.model.RoomSyncUnreadThreadNotifications -import org.matrix.android.sdk.internal.crypto.EventDecryptor import org.matrix.android.sdk.internal.database.mapper.ContentMapper import org.matrix.android.sdk.internal.database.mapper.asDomain import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/RoomSummaryEventDecryptor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/RoomSummaryEventDecryptor.kt index c2692e2a48..d77dec3a45 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/RoomSummaryEventDecryptor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/RoomSummaryEventDecryptor.kt @@ -50,9 +50,9 @@ internal class RoomSummaryEventDecryptor @Inject constructor( } private val scope: CoroutineScope = CoroutineScope( - cryptoCoroutineScope.coroutineContext - + SupervisorJob() - + CoroutineName("RoomSummaryDecryptor") + cryptoCoroutineScope.coroutineContext + + SupervisorJob() + + CoroutineName("RoomSummaryDecryptor") ) private val channel = Channel(capacity = 300) @@ -116,8 +116,8 @@ internal class RoomSummaryEventDecryptor @Inject constructor( } } - if (failure.errorType == MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID - || failure.errorType == MXCryptoError.ErrorType.UNKNOWN_MESSAGE_INDEX) { + if (failure.errorType == MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID || + failure.errorType == MXCryptoError.ErrorType.UNKNOWN_MESSAGE_INDEX) { (event.content["session_id"] as? String)?.let { sessionId -> unknownSessionsFailure.getOrPut(sessionId) { mutableSetOf() } .add(event) diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/api/session/crypto/keysbackup/BackupUtils.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/api/session/crypto/keysbackup/BackupUtils.kt index 46bf9558d5..8b35586c4f 100644 --- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/api/session/crypto/keysbackup/BackupUtils.kt +++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/api/session/crypto/keysbackup/BackupUtils.kt @@ -16,8 +16,6 @@ package org.matrix.android.sdk.api.session.crypto.keysbackup -import org.matrix.android.sdk.api.session.securestorage.SsssPassphrase - object BackupUtils { fun recoveryKeyFromBase58(key: String): IBackupRecoveryKey? = BackupRecoveryKey.fromBase58(key) fun recoveryKeyFromPassphrase(passphrase: String): IBackupRecoveryKey? = BackupRecoveryKey.newFromPassphrase(passphrase) diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt index 949e103ce3..dfa89bafb9 100644 --- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt +++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt @@ -36,7 +36,6 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo import org.matrix.android.sdk.api.session.crypto.crosssigning.PrivateKeysInfo import org.matrix.android.sdk.api.session.crypto.crosssigning.UserTrustResult -import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupAuthData import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult @@ -52,7 +51,6 @@ import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.toOptional import org.matrix.android.sdk.internal.coroutines.builder.safeInvokeOnClose -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.CreateKeysBackupVersionBody import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.DefaultKeysAlgorithmAndData import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysAlgorithmAndData import org.matrix.android.sdk.internal.crypto.network.RequestSender diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageActivity.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageActivity.kt index d393636a8e..54fb2bd59a 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageActivity.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageActivity.kt @@ -49,6 +49,7 @@ class SharedSecureStorageActivity : val requestedSecrets: List = emptyList(), val resultKeyStoreAlias: String, val writeSecrets: List> = emptyList(), + val currentStep: SharedSecureStorageViewState.Step = SharedSecureStorageViewState.Step.EnterPassphrase, ) : Parcelable private val viewModel: SharedSecureStorageViewModel by viewModel() @@ -150,7 +151,8 @@ class SharedSecureStorageActivity : context: Context, keyId: String? = null, requestedSecrets: List, - resultKeyStoreAlias: String = DEFAULT_RESULT_KEYSTORE_ALIAS + resultKeyStoreAlias: String = DEFAULT_RESULT_KEYSTORE_ALIAS, + initialStep: SharedSecureStorageViewState.Step = SharedSecureStorageViewState.Step.EnterPassphrase ): Intent { require(requestedSecrets.isNotEmpty()) return Intent(context, SharedSecureStorageActivity::class.java).also { @@ -159,7 +161,8 @@ class SharedSecureStorageActivity : Args( keyId = keyId, requestedSecrets = requestedSecrets, - resultKeyStoreAlias = resultKeyStoreAlias + resultKeyStoreAlias = resultKeyStoreAlias, + currentStep = initialStep ) ) } @@ -169,7 +172,8 @@ class SharedSecureStorageActivity : context: Context, keyId: String? = null, writeSecrets: List>, - resultKeyStoreAlias: String = DEFAULT_RESULT_KEYSTORE_ALIAS + resultKeyStoreAlias: String = DEFAULT_RESULT_KEYSTORE_ALIAS, + initialStep: SharedSecureStorageViewState.Step = SharedSecureStorageViewState.Step.EnterPassphrase ): Intent { require(writeSecrets.isNotEmpty()) return Intent(context, SharedSecureStorageActivity::class.java).also { @@ -178,7 +182,8 @@ class SharedSecureStorageActivity : Args( keyId = keyId, writeSecrets = writeSecrets, - resultKeyStoreAlias = resultKeyStoreAlias + resultKeyStoreAlias = resultKeyStoreAlias, + currentStep = initialStep, ) ) } diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt index 2dc8eaf283..4ab11a218c 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt @@ -58,7 +58,7 @@ data class SharedSecureStorageViewState( val ready: Boolean = false, val hasPassphrase: Boolean = true, val checkingSSSSAction: Async = Uninitialized, - val step: Step = Step.EnterPassphrase, + val step: Step = Step.ResetAll, val activeDeviceCount: Int = 0, val showResetAllAction: Boolean = false, val userId: String = "", @@ -74,7 +74,8 @@ data class SharedSecureStorageViewState( } else { RequestType.ReadSecrets(args.requestedSecrets) }, - resultKeyStoreAlias = args.resultKeyStoreAlias + resultKeyStoreAlias = args.resultKeyStoreAlias, + step = args.currentStep, ) enum class Step { @@ -113,30 +114,35 @@ class SharedSecureStorageViewModel @AssistedInject constructor( ) } } - val keyResult = initialState.keyId?.let { session.sharedSecretStorageService().getKey(it) } - ?: session.sharedSecretStorageService().getDefaultKey() - if (!keyResult.isSuccess()) { - _viewEvents.post(SharedSecureStorageViewEvent.Dismiss) - } else { - val info = (keyResult as KeyInfoResult.Success).keyInfo - if (info.content.passphrase != null) { - setState { - copy( - hasPassphrase = true, - ready = true, - step = SharedSecureStorageViewState.Step.EnterPassphrase - ) - } + if (initialState.step != SharedSecureStorageViewState.Step.ResetAll) { + val keyResult = initialState.keyId?.let { session.sharedSecretStorageService().getKey(it) } + ?: session.sharedSecretStorageService().getDefaultKey() + + if (!keyResult.isSuccess()) { + _viewEvents.post(SharedSecureStorageViewEvent.Dismiss) } else { - setState { - copy( - hasPassphrase = false, - ready = true, - step = SharedSecureStorageViewState.Step.EnterKey - ) + val info = (keyResult as KeyInfoResult.Success).keyInfo + if (info.content.passphrase != null) { + setState { + copy( + hasPassphrase = true, + ready = true, + step = SharedSecureStorageViewState.Step.EnterPassphrase + ) + } + } else { + setState { + copy( + hasPassphrase = false, + ready = true, + step = SharedSecureStorageViewState.Step.EnterKey + ) + } } } + } else { + setState { copy(ready = true) } } session.flow() @@ -203,6 +209,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor( _viewEvents.post(SharedSecureStorageViewEvent.Dismiss) } } + /* SharedSecureStorageViewState.Step.ResetAll -> { setState { copy( @@ -211,6 +218,7 @@ class SharedSecureStorageViewModel @AssistedInject constructor( ) } } + */ else -> { _viewEvents.post(SharedSecureStorageViewEvent.Dismiss) } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationAction.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationAction.kt index 55b09d4a4b..cc99a94000 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationAction.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationAction.kt @@ -31,6 +31,7 @@ sealed class VerificationAction : VectorViewModelAction { data class GotItConclusion(val verified: Boolean) : VerificationAction() object FailedToGetKeysFrom4S : VerificationAction() object SkipVerification : VerificationAction() + object ForgotResetAll : VerificationAction() object VerifyFromPassphrase : VerificationAction() object ReadyPendingVerification : VerificationAction() object CancelPendingVerification : VerificationAction() diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewEvents.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewEvents.kt index 13d211bf9d..82fe94cbdb 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewEvents.kt @@ -24,6 +24,7 @@ import im.vector.app.core.platform.VectorViewEvents sealed class VerificationBottomSheetViewEvents : VectorViewEvents { object Dismiss : VerificationBottomSheetViewEvents() object AccessSecretStore : VerificationBottomSheetViewEvents() + object ResetAll : VerificationBottomSheetViewEvents() object GoToSettings : VerificationBottomSheetViewEvents() data class ModalError(val errorMessage: CharSequence) : VerificationBottomSheetViewEvents() } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt index 9fabdc3d12..6628c39248 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt @@ -34,6 +34,7 @@ import im.vector.app.core.extensions.toMvRxBundle import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.databinding.BottomSheetVerificationBinding import im.vector.app.features.crypto.quads.SharedSecureStorageActivity +import im.vector.app.features.crypto.quads.SharedSecureStorageViewState import im.vector.app.features.crypto.verification.VerificationAction import im.vector.app.features.crypto.verification.VerificationBottomSheetViewEvents import kotlinx.parcelize.Parcelize @@ -92,7 +93,18 @@ class SelfVerificationBottomSheet : VectorBaseBottomSheetDialogFragment { + secretStartForActivityResult.launch( + SharedSecureStorageActivity.newReadIntent( + requireContext(), + null, // use default key + listOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME, KEYBACKUP_SECRET_SSSS_NAME), + SharedSecureStorageActivity.DEFAULT_RESULT_KEYSTORE_ALIAS, + SharedSecureStorageViewState.Step.ResetAll ) ) } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationController.kt index 6c42481b5a..eaad57c412 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationController.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationController.kt @@ -254,8 +254,8 @@ class SelfVerificationController @Inject constructor( } } is Success -> { - val invoke = action.invoke() - if (invoke) { + val value = action.invoke() + if (value) { verifiedSuccessTile() bottomDone { (host.listener as? InteractionListener)?.onDoneFrom4S() } } else { diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationFragment.kt index ff619eb97d..aa87b98a7f 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationFragment.kt @@ -77,11 +77,11 @@ class SelfVerificationFragment : VectorBaseFragment TODO() - VerificationAction.SkipVerification -> TODO() + VerificationAction.SecuredStorageHasBeenReset -> { + if (session.cryptoService().crossSigningService().allPrivateKeysKnown()) { + _viewEvents.post(VerificationBottomSheetViewEvents.Dismiss) + } + } + VerificationAction.SkipVerification -> { + _viewEvents.post(VerificationBottomSheetViewEvents.Dismiss) + } + VerificationAction.ForgotResetAll -> { + _viewEvents.post(VerificationBottomSheetViewEvents.ResetAll) + } VerificationAction.StartSASVerification -> { withState { state -> val request = state.pendingRequest.invoke() ?: return@withState diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationBottomSheet.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationBottomSheet.kt index 658eda8468..31faec1f4b 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationBottomSheet.kt @@ -90,6 +90,9 @@ class UserVerificationBottomSheet : VectorBaseBottomSheetDialogFragment { + // no-op for user verification + } } } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationViewModel.kt index 6cb8dde8a6..24ec5ae22e 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/user/UserVerificationViewModel.kt @@ -385,6 +385,9 @@ class UserVerificationViewModel @AssistedInject constructor( // Not applicable for user verification } VerificationAction.RequestSelfVerification -> TODO() + VerificationAction.ForgotResetAll -> { + // Not applicable for user verification + } } } diff --git a/vector/src/main/res/layout/fragment_ssss_reset_all.xml b/vector/src/main/res/layout/fragment_ssss_reset_all.xml index 3fba9b11bb..057c480cae 100644 --- a/vector/src/main/res/layout/fragment_ssss_reset_all.xml +++ b/vector/src/main/res/layout/fragment_ssss_reset_all.xml @@ -37,7 +37,7 @@ android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:layout_marginBottom="16dp" - android:text="@string/secure_backup_reset_all_no_other_devices" + android:text="@string/secure_backup_reset_all_no_other_devices_long" android:textColor="?vctr_content_primary" app:layout_constraintBottom_toTopOf="@id/ssss_reset_other_devices" app:layout_constraintTop_toBottomOf="@id/reset_title" /> @@ -60,19 +60,6 @@ tools:text="Show 2 devices you can verify with now" tools:visibility="visible" /> - - + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/ssss_reset_other_devices" />