Skip to content

Commit

Permalink
Merge pull request #2465 from vector-im/feature/bca/fix_verifypassphr…
Browse files Browse the repository at this point in the history
…ase_bottomsheet

Fix / double bottomsheet effect
  • Loading branch information
bmarty authored Nov 30, 2020
2 parents b004dfb + c8a8e0f commit d759636
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 36 deletions.
2 changes: 1 addition & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Improvements 🙌:
-

Bugfix 🐛:
-
- Double bottomsheet effect after verify with passphrase

Translations 🗣:
-
Expand Down
6 changes: 6 additions & 0 deletions vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import im.vector.app.features.crypto.recover.BootstrapMigrateBackupFragment
import im.vector.app.features.crypto.recover.BootstrapSaveRecoveryKeyFragment
import im.vector.app.features.crypto.recover.BootstrapSetupRecoveryKeyFragment
import im.vector.app.features.crypto.recover.BootstrapWaitingFragment
import im.vector.app.features.crypto.verification.QuadSLoadingFragment
import im.vector.app.features.crypto.verification.cancel.VerificationCancelFragment
import im.vector.app.features.crypto.verification.cancel.VerificationNotMeFragment
import im.vector.app.features.crypto.verification.choose.VerificationChooseMethodFragment
Expand Down Expand Up @@ -418,6 +419,11 @@ interface FragmentModule {
@FragmentKey(VerificationCancelFragment::class)
fun bindVerificationCancelFragment(fragment: VerificationCancelFragment): Fragment

@Binds
@IntoMap
@FragmentKey(QuadSLoadingFragment::class)
fun bindQuadSLoadingFragment(fragment: QuadSLoadingFragment): Fragment

@Binds
@IntoMap
@FragmentKey(VerificationNotMeFragment::class)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2020 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 im.vector.app.features.crypto.verification

import im.vector.app.R
import im.vector.app.core.platform.VectorBaseFragment
import javax.inject.Inject

class QuadSLoadingFragment @Inject constructor() : VectorBaseFragment() {
override fun getLayoutResId() = R.layout.fragment_progress
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ sealed class VerificationAction : VectorViewModelAction {
object SkipVerification : VerificationAction()
object VerifyFromPassphrase : VerificationAction()
data class GotResultFromSsss(val cypherData: String, val alias: String) : VerificationAction()
object CancelledFromSsss : VerificationAction()
object SecuredStorageHasBeenReset : VerificationAction()
}
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() {
// all have been reset, so we are verified?
viewModel.handle(VerificationAction.SecuredStorageHasBeenReset)
}
} else {
viewModel.handle(VerificationAction.CancelledFromSsss)
}
}

Expand Down Expand Up @@ -209,6 +211,10 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() {
return@withState
}

if (state.selfVerificationMode && state.verifyingFrom4S) {
showFragment(QuadSLoadingFragment::class, Bundle())
return@withState
}
if (state.selfVerificationMode && state.verifiedFromPrivateKeys) {
showFragment(VerificationConclusionFragment::class, Bundle().apply {
putParcelable(MvRx.KEY_ARG, VerificationConclusionFragment.Args(true, null, state.isMe))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.session.Session
Expand Down Expand Up @@ -70,6 +71,7 @@ data class VerificationBottomSheetViewState(
// true when we display the loading and we wait for the other (incoming request)
val selfVerificationMode: Boolean = false,
val verifiedFromPrivateKeys: Boolean = false,
val verifyingFrom4S: Boolean = false,
val isMe: Boolean = false,
val currentDeviceCanCrossSign: Boolean = false,
val userWantsToCancel: Boolean = false,
Expand Down Expand Up @@ -170,7 +172,9 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
}
} else {
// if the verification is already done you can't cancel anymore
if (state.pendingRequest.invoke()?.cancelConclusion != null || state.sasTransactionState is VerificationTxState.TerminalTxState) {
if (state.pendingRequest.invoke()?.cancelConclusion != null
|| state.sasTransactionState is VerificationTxState.TerminalTxState
|| state.verifyingFrom4S) {
// you cannot cancel anymore
} else {
setState {
Expand Down Expand Up @@ -346,6 +350,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
_viewEvents.post(VerificationBottomSheetViewEvents.Dismiss)
}
is VerificationAction.VerifyFromPassphrase -> {
setState { copy(verifyingFrom4S = true) }
_viewEvents.post(VerificationBottomSheetViewEvents.AccessSecretStore)
}
is VerificationAction.GotResultFromSsss -> {
Expand All @@ -354,56 +359,73 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
VerificationAction.SecuredStorageHasBeenReset -> {
if (session.cryptoService().crossSigningService().allPrivateKeysKnown()) {
setState {
copy(quadSHasBeenReset = true)
copy(quadSHasBeenReset = true, verifyingFrom4S = false)
}
}
Unit
}
VerificationAction.CancelledFromSsss -> {
setState {
copy(verifyingFrom4S = false)
}
}
}.exhaustive
}

private fun handleSecretBackFromSSSS(action: VerificationAction.GotResultFromSsss) {
try {
action.cypherData.fromBase64().inputStream().use { ins ->
val res = session.loadSecureSecret<Map<String, String>>(ins, action.alias)
val trustResult = session.cryptoService().crossSigningService().checkTrustFromPrivateKeys(
res?.get(MASTER_KEY_SSSS_NAME),
res?.get(USER_SIGNING_KEY_SSSS_NAME),
res?.get(SELF_SIGNING_KEY_SSSS_NAME)
)
if (trustResult.isVerified()) {
// Sign this device and upload the signature
session.sessionParams.deviceId?.let { deviceId ->
session.cryptoService()
.crossSigningService().trustDevice(deviceId, object : MatrixCallback<Unit> {
override fun onFailure(failure: Throwable) {
Timber.w(failure, "Failed to sign my device after recovery")
}
})
}
viewModelScope.launch(Dispatchers.IO) {
try {
action.cypherData.fromBase64().inputStream().use { ins ->
val res = session.loadSecureSecret<Map<String, String>>(ins, action.alias)
val trustResult = session.cryptoService().crossSigningService().checkTrustFromPrivateKeys(
res?.get(MASTER_KEY_SSSS_NAME),
res?.get(USER_SIGNING_KEY_SSSS_NAME),
res?.get(SELF_SIGNING_KEY_SSSS_NAME)
)
if (trustResult.isVerified()) {
// Sign this device and upload the signature
session.sessionParams.deviceId?.let { deviceId ->
session.cryptoService()
.crossSigningService().trustDevice(deviceId, object : MatrixCallback<Unit> {
override fun onFailure(failure: Throwable) {
Timber.w(failure, "Failed to sign my device after recovery")
}
})
}

setState {
copy(verifiedFromPrivateKeys = true)
}
setState {
copy(
verifyingFrom4S = false,
verifiedFromPrivateKeys = true
)
}

// try to get keybackup key
} else {
// POP UP something
_viewEvents.post(VerificationBottomSheetViewEvents.ModalError(stringProvider.getString(R.string.error_failed_to_import_keys)))
// try the keybackup
tentativeRestoreBackup(res)
} else {
setState {
copy(
verifyingFrom4S = false
)
}
// POP UP something
_viewEvents.post(VerificationBottomSheetViewEvents.ModalError(stringProvider.getString(R.string.error_failed_to_import_keys)))
}
}

// try the keybackup
tentativeRestoreBackup(res)
Unit
} catch (failure: Throwable) {
setState {
copy(
verifyingFrom4S = false
)
}
_viewEvents.post(
VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage ?: stringProvider.getString(R.string.unexpected_error)))
}
} catch (failure: Throwable) {
_viewEvents.post(
VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage ?: stringProvider.getString(R.string.unexpected_error)))
}
}

private fun tentativeRestoreBackup(res: Map<String, String>?) {
viewModelScope.launch(Dispatchers.IO) {
GlobalScope.launch(Dispatchers.IO) {
try {
val secret = res?.get(KEYBACKUP_SECRET_SSSS_NAME) ?: return@launch Unit.also {
Timber.v("## Keybackup secret not restored from SSSS")
Expand Down
14 changes: 14 additions & 0 deletions vector/src/main/res/layout/fragment_progress.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginTop="@dimen/layout_vertical_margin_big"
android:indeterminate="true" />

</RelativeLayout>

0 comments on commit d759636

Please sign in to comment.