Merge pull request #1902 from vector-im/feature/verify_one_session
Feature/verify one session
This commit is contained in:
commit
e9b3ab91a0
|
@ -7,6 +7,7 @@ Features ✨:
|
|||
Improvements 🙌:
|
||||
- You can now join room through permalink and within room directory search
|
||||
- Add long click gesture to copy userId, user display name, room name, room topic and room alias (#1774)
|
||||
- Do not propose to verify session if there is only one session and 4S is not configured (#1901)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Display name not shown under Settings/General (#1926)
|
||||
|
|
|
@ -39,7 +39,7 @@ data class DeviceVerificationInfoArgs(
|
|||
val deviceId: String
|
||||
) : Parcelable
|
||||
|
||||
class DeviceVerificationInfoBottomSheet : VectorBaseBottomSheetDialogFragment(), DeviceVerificationInfoEpoxyController.Callback {
|
||||
class DeviceVerificationInfoBottomSheet : VectorBaseBottomSheetDialogFragment(), DeviceVerificationInfoBottomSheetController.Callback {
|
||||
|
||||
private val viewModel: DeviceVerificationInfoBottomSheetViewModel by fragmentViewModel(DeviceVerificationInfoBottomSheetViewModel::class)
|
||||
|
||||
|
@ -54,17 +54,17 @@ class DeviceVerificationInfoBottomSheet : VectorBaseBottomSheetDialogFragment(),
|
|||
injector.inject(this)
|
||||
}
|
||||
|
||||
@Inject lateinit var epoxyController: DeviceVerificationInfoEpoxyController
|
||||
@Inject lateinit var controller: DeviceVerificationInfoBottomSheetController
|
||||
|
||||
override fun getLayoutResId() = R.layout.bottom_sheet_generic_list_with_title
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
recyclerView.configureWith(
|
||||
epoxyController,
|
||||
controller,
|
||||
showDivider = false,
|
||||
hasFixedSize = false)
|
||||
epoxyController.callback = this
|
||||
controller.callback = this
|
||||
bottomSheetTitle.isVisible = false
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ class DeviceVerificationInfoBottomSheet : VectorBaseBottomSheetDialogFragment(),
|
|||
}
|
||||
|
||||
override fun invalidate() = withState(viewModel) {
|
||||
epoxyController.setData(it)
|
||||
controller.setData(it)
|
||||
super.invalidate()
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
package im.vector.app.features.settings.devices
|
||||
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.dividerItem
|
||||
import im.vector.app.core.epoxy.loadingItem
|
||||
|
@ -28,12 +25,14 @@ import im.vector.app.core.ui.list.GenericItem
|
|||
import im.vector.app.core.ui.list.genericFooterItem
|
||||
import im.vector.app.core.ui.list.genericItem
|
||||
import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class DeviceVerificationInfoEpoxyController @Inject constructor(private val stringProvider: StringProvider,
|
||||
private val colorProvider: ColorProvider,
|
||||
private val session: Session)
|
||||
class DeviceVerificationInfoBottomSheetController @Inject constructor(
|
||||
private val stringProvider: StringProvider,
|
||||
private val colorProvider: ColorProvider)
|
||||
: TypedEpoxyController<DeviceVerificationInfoBottomSheetViewState>() {
|
||||
|
||||
var callback: Callback? = null
|
||||
|
@ -67,16 +66,18 @@ class DeviceVerificationInfoEpoxyController @Inject constructor(private val stri
|
|||
|
||||
if (data.hasAccountCrossSigning) {
|
||||
// Cross Signing is enabled
|
||||
handleE2EWithCrossSigning(data.isMine, data.accountCrossSigningIsTrusted, cryptoDeviceInfo, shield)
|
||||
handleE2EWithCrossSigning(data, cryptoDeviceInfo, shield)
|
||||
} else {
|
||||
handleE2EInLegacy(data.isMine, cryptoDeviceInfo, shield)
|
||||
handleE2EInLegacy(data, cryptoDeviceInfo, shield)
|
||||
}
|
||||
|
||||
// COMMON ACTIONS (Rename / signout)
|
||||
addGenericDeviceManageActions(data, cryptoDeviceInfo.deviceId)
|
||||
}
|
||||
|
||||
private fun handleE2EWithCrossSigning(isMine: Boolean, currentSessionIsTrusted: Boolean, cryptoDeviceInfo: CryptoDeviceInfo, shield: Int) {
|
||||
private fun handleE2EWithCrossSigning(data: DeviceVerificationInfoBottomSheetViewState, cryptoDeviceInfo: CryptoDeviceInfo, shield: Int) {
|
||||
val isMine = data.isMine
|
||||
val currentSessionIsTrusted = data.accountCrossSigningIsTrusted
|
||||
Timber.v("handleE2EWithCrossSigning $isMine, $cryptoDeviceInfo, $shield")
|
||||
|
||||
if (isMine) {
|
||||
|
@ -88,14 +89,18 @@ class DeviceVerificationInfoEpoxyController @Inject constructor(private val stri
|
|||
title(stringProvider.getString(R.string.encryption_information_verified))
|
||||
description(stringProvider.getString(R.string.settings_active_sessions_verified_device_desc))
|
||||
}
|
||||
} else {
|
||||
// You need to complete security
|
||||
} else if (data.canVerifySession) {
|
||||
// You need to complete security, only if there are other session(s) available, or if 4S contains secrets
|
||||
genericItem {
|
||||
id("trust${cryptoDeviceInfo.deviceId}")
|
||||
style(GenericItem.STYLE.BIG_TEXT)
|
||||
titleIconResourceId(shield)
|
||||
title(stringProvider.getString(R.string.crosssigning_verify_this_session))
|
||||
description(stringProvider.getString(R.string.confirm_your_identity))
|
||||
if (data.hasOtherSessions) {
|
||||
description(stringProvider.getString(R.string.confirm_your_identity))
|
||||
} else {
|
||||
description(stringProvider.getString(R.string.confirm_your_identity_quad_s))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -132,7 +137,7 @@ class DeviceVerificationInfoEpoxyController @Inject constructor(private val stri
|
|||
description("(${cryptoDeviceInfo.deviceId})")
|
||||
}
|
||||
|
||||
if (isMine && !currentSessionIsTrusted) {
|
||||
if (isMine && !currentSessionIsTrusted && data.canVerifySession) {
|
||||
// Add complete security
|
||||
dividerItem {
|
||||
id("completeSecurityDiv")
|
||||
|
@ -158,8 +163,9 @@ class DeviceVerificationInfoEpoxyController @Inject constructor(private val stri
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleE2EInLegacy(isMine: Boolean, cryptoDeviceInfo: CryptoDeviceInfo, shield: Int) {
|
||||
private fun handleE2EInLegacy(data: DeviceVerificationInfoBottomSheetViewState, cryptoDeviceInfo: CryptoDeviceInfo, shield: Int) {
|
||||
// ==== Legacy
|
||||
val isMine = data.isMine
|
||||
|
||||
// TRUST INFO SECTION
|
||||
if (cryptoDeviceInfo.trustLevel?.isLocallyVerified() == true) {
|
|
@ -15,31 +15,19 @@
|
|||
*/
|
||||
package im.vector.app.features.settings.devices
|
||||
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
||||
import im.vector.app.core.platform.EmptyAction
|
||||
import im.vector.app.core.platform.EmptyViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
||||
import org.matrix.android.sdk.rx.rx
|
||||
|
||||
data class DeviceVerificationInfoBottomSheetViewState(
|
||||
val cryptoDeviceInfo: Async<CryptoDeviceInfo?> = Uninitialized,
|
||||
val deviceInfo: Async<DeviceInfo> = Uninitialized,
|
||||
val hasAccountCrossSigning: Boolean = false,
|
||||
val accountCrossSigningIsTrusted: Boolean = false,
|
||||
val isMine: Boolean = false
|
||||
) : MvRxState
|
||||
|
||||
class DeviceVerificationInfoBottomSheetViewModel @AssistedInject constructor(@Assisted initialState: DeviceVerificationInfoBottomSheetViewState,
|
||||
@Assisted val deviceId: String,
|
||||
val session: Session
|
||||
|
@ -55,7 +43,8 @@ class DeviceVerificationInfoBottomSheetViewModel @AssistedInject constructor(@As
|
|||
setState {
|
||||
copy(
|
||||
hasAccountCrossSigning = session.cryptoService().crossSigningService().isCrossSigningInitialized(),
|
||||
accountCrossSigningIsTrusted = session.cryptoService().crossSigningService().isCrossSigningVerified()
|
||||
accountCrossSigningIsTrusted = session.cryptoService().crossSigningService().isCrossSigningVerified(),
|
||||
isRecoverySetup = session.sharedSecretStorageService.isRecoverySetup()
|
||||
)
|
||||
}
|
||||
session.rx().liveCrossSigningInfo(session.myUserId)
|
||||
|
@ -77,6 +66,14 @@ class DeviceVerificationInfoBottomSheetViewModel @AssistedInject constructor(@As
|
|||
)
|
||||
}
|
||||
|
||||
session.rx().liveUserCryptoDevices(session.myUserId)
|
||||
.map { it.size }
|
||||
.execute {
|
||||
copy(
|
||||
hasOtherSessions = it.invoke() ?: 0 > 1
|
||||
)
|
||||
}
|
||||
|
||||
setState {
|
||||
copy(deviceInfo = Loading())
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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.settings.devices
|
||||
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
||||
|
||||
data class DeviceVerificationInfoBottomSheetViewState(
|
||||
val cryptoDeviceInfo: Async<CryptoDeviceInfo?> = Uninitialized,
|
||||
val deviceInfo: Async<DeviceInfo> = Uninitialized,
|
||||
val hasAccountCrossSigning: Boolean = false,
|
||||
val accountCrossSigningIsTrusted: Boolean = false,
|
||||
val isMine: Boolean = false,
|
||||
val hasOtherSessions: Boolean = false,
|
||||
val isRecoverySetup: Boolean = false
|
||||
) : MvRxState {
|
||||
|
||||
val canVerifySession: Boolean
|
||||
get() = hasOtherSessions || isRecoverySetup
|
||||
}
|
|
@ -2413,6 +2413,7 @@
|
|||
<string name="crosssigning_verify_session">Verify login</string>
|
||||
<string name="cross_signing_verify_by_emoji">Interactively Verify by Emoji</string>
|
||||
<string name="confirm_your_identity">Confirm your identity by verifying this login from one of your other sessions, granting it access to encrypted messages.</string>
|
||||
<string name="confirm_your_identity_quad_s">Confirm your identity by verifying this login, granting it access to encrypted messages.</string>
|
||||
<string name="mark_as_verified">Mark as Trusted</string>
|
||||
|
||||
<string name="error_empty_field_choose_user_name">Please choose a username.</string>
|
||||
|
|
Loading…
Reference in New Issue