Merge pull request #7156 from vector-im/feature/mna/device-manager-verify-other-session

[Device management] Verify another session (PSG-722)
This commit is contained in:
Benoit Marty 2022-09-22 11:46:28 +02:00 committed by GitHub
commit e98bfe5c9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 143 additions and 69 deletions

1
changelog.d/7143.wip Normal file
View File

@ -0,0 +1 @@
[Device management] Verify another session

View File

@ -34,8 +34,8 @@ import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.PublishDataSource
import im.vector.app.features.auth.ReAuthActivity
import im.vector.app.features.login.ReAuthHelper
import im.vector.app.features.settings.devices.v2.GetEncryptionTrustLevelForDeviceUseCase
import im.vector.app.features.settings.devices.v2.list.CheckIfSessionIsInactiveUseCase
import im.vector.app.features.settings.devices.v2.verification.GetEncryptionTrustLevelForDeviceUseCase
import im.vector.lib.core.utils.flow.throttleFirst
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.combine

View File

@ -17,7 +17,7 @@
package im.vector.app.features.settings.devices
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.features.settings.devices.v2.CurrentSessionCrossSigningInfo
import im.vector.app.features.settings.devices.v2.verification.CurrentSessionCrossSigningInfo
import javax.inject.Inject
class GetCurrentSessionCrossSigningInfoUseCase @Inject constructor(

View File

@ -26,6 +26,7 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.features.settings.devices.v2.filter.DeviceManagerFilterType
import im.vector.app.features.settings.devices.v2.verification.CheckIfCurrentSessionCanBeVerifiedUseCase
import im.vector.app.features.settings.devices.v2.verification.GetCurrentSessionCrossSigningInfoUseCase
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch

View File

@ -19,6 +19,7 @@ package im.vector.app.features.settings.devices.v2
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.Uninitialized
import im.vector.app.features.settings.devices.v2.verification.CurrentSessionCrossSigningInfo
data class DevicesViewState(
val currentSessionCrossSigningInfo: CurrentSessionCrossSigningInfo = CurrentSessionCrossSigningInfo(),

View File

@ -20,6 +20,9 @@ import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.features.settings.devices.v2.filter.DeviceManagerFilterType
import im.vector.app.features.settings.devices.v2.filter.FilterDevicesUseCase
import im.vector.app.features.settings.devices.v2.list.CheckIfSessionIsInactiveUseCase
import im.vector.app.features.settings.devices.v2.verification.CurrentSessionCrossSigningInfo
import im.vector.app.features.settings.devices.v2.verification.GetCurrentSessionCrossSigningInfoUseCase
import im.vector.app.features.settings.devices.v2.verification.GetEncryptionTrustLevelForDeviceUseCase
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged

View File

@ -62,6 +62,7 @@ class SessionInfoView @JvmOverloads constructor(
sessionInfoViewState.deviceFullInfo.roomEncryptionTrustLevel,
sessionInfoViewState.isCurrentSession,
sessionInfoViewState.isLearnMoreLinkVisible,
sessionInfoViewState.isVerifyButtonVisible,
)
renderDeviceLastSeenDetails(
sessionInfoViewState.deviceFullInfo.isInactive,
@ -78,12 +79,13 @@ class SessionInfoView @JvmOverloads constructor(
encryptionTrustLevel: RoomEncryptionTrustLevel,
isCurrentSession: Boolean,
hasLearnMoreLink: Boolean,
isVerifyButtonVisible: Boolean,
) {
views.sessionInfoVerificationStatusImageView.render(encryptionTrustLevel)
if (encryptionTrustLevel == RoomEncryptionTrustLevel.Trusted) {
renderCrossSigningVerified(isCurrentSession)
} else {
renderCrossSigningUnverified(isCurrentSession)
renderCrossSigningUnverified(isCurrentSession, isVerifyButtonVisible)
}
if (hasLearnMoreLink) {
appendLearnMoreToVerificationStatus()
@ -120,7 +122,7 @@ class SessionInfoView @JvmOverloads constructor(
views.sessionInfoVerifySessionButton.isVisible = false
}
private fun renderCrossSigningUnverified(isCurrentSession: Boolean) {
private fun renderCrossSigningUnverified(isCurrentSession: Boolean, isVerifyButtonVisible: Boolean) {
views.sessionInfoVerificationStatusTextView.text = context.getString(R.string.device_manager_verification_status_unverified)
views.sessionInfoVerificationStatusTextView.setTextColor(ThemeUtils.getColor(context, R.attr.colorError))
val statusResId = if (isCurrentSession) {
@ -129,7 +131,7 @@ class SessionInfoView @JvmOverloads constructor(
R.string.device_manager_verification_status_detail_other_session_unverified
}
views.sessionInfoVerificationStatusDetailTextView.text = context.getString(statusResId)
views.sessionInfoVerifySessionButton.isVisible = true
views.sessionInfoVerifySessionButton.isVisible = isVerifyButtonVisible
}
// TODO. We don't have this info yet. Update later accordingly.

View File

@ -21,6 +21,7 @@ import im.vector.app.features.settings.devices.v2.DeviceFullInfo
data class SessionInfoViewState(
val isCurrentSession: Boolean,
val deviceFullInfo: DeviceFullInfo,
val isVerifyButtonVisible: Boolean = true,
val isDetailsButtonVisible: Boolean = true,
val isLearnMoreLinkVisible: Boolean = false,
val isLastSeenDetailsVisible: Boolean = false,

View File

@ -19,9 +19,9 @@ package im.vector.app.features.settings.devices.v2.overview
import androidx.lifecycle.asFlow
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.features.settings.devices.v2.DeviceFullInfo
import im.vector.app.features.settings.devices.v2.GetCurrentSessionCrossSigningInfoUseCase
import im.vector.app.features.settings.devices.v2.GetEncryptionTrustLevelForDeviceUseCase
import im.vector.app.features.settings.devices.v2.list.CheckIfSessionIsInactiveUseCase
import im.vector.app.features.settings.devices.v2.verification.GetCurrentSessionCrossSigningInfoUseCase
import im.vector.app.features.settings.devices.v2.verification.GetEncryptionTrustLevelForDeviceUseCase
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.emptyFlow

View File

@ -35,7 +35,6 @@ import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.DrawableProvider
import im.vector.app.databinding.FragmentSessionOverviewBinding
import im.vector.app.features.crypto.recover.SetupMode
import im.vector.app.features.settings.devices.v2.DeviceFullInfo
import im.vector.app.features.settings.devices.v2.list.SessionInfoViewState
import javax.inject.Inject
@ -82,9 +81,12 @@ class SessionOverviewFragment :
private fun observeViewEvents() {
viewModel.observeViewEvents {
when (it) {
is SessionOverviewViewEvent.SelfVerification -> {
is SessionOverviewViewEvent.ShowVerifyCurrentSession -> {
navigator.requestSelfSessionVerification(requireActivity())
}
is SessionOverviewViewEvent.ShowVerifyOtherSession -> {
navigator.requestSessionVerification(requireActivity(), it.deviceId)
}
is SessionOverviewViewEvent.PromptResetSecrets -> {
navigator.open4SSetup(requireActivity(), SetupMode.PASSPHRASE_AND_NEEDED_SECRETS_RESET)
}
@ -104,11 +106,7 @@ class SessionOverviewFragment :
override fun invalidate() = withState(viewModel) { state ->
updateToolbar(state.isCurrentSession)
updateEntryDetails(state.deviceId)
if (state.deviceInfo is Success) {
renderSessionInfo(state.isCurrentSession, state.deviceInfo.invoke())
} else {
hideSessionInfo()
}
updateSessionInfo(state)
}
private fun updateToolbar(isCurrentSession: Boolean) {
@ -124,16 +122,22 @@ class SessionOverviewFragment :
}
}
private fun renderSessionInfo(isCurrentSession: Boolean, deviceFullInfo: DeviceFullInfo) {
views.sessionOverviewInfo.isVisible = true
val viewState = SessionInfoViewState(
isCurrentSession = isCurrentSession,
deviceFullInfo = deviceFullInfo,
isDetailsButtonVisible = false,
isLearnMoreLinkVisible = true,
isLastSeenDetailsVisible = true,
)
views.sessionOverviewInfo.render(viewState, dateFormatter, drawableProvider, colorProvider)
private fun updateSessionInfo(viewState: SessionOverviewViewState) {
if (viewState.deviceInfo is Success) {
views.sessionOverviewInfo.isVisible = true
val isCurrentSession = viewState.isCurrentSession
val infoViewState = SessionInfoViewState(
isCurrentSession = isCurrentSession,
deviceFullInfo = viewState.deviceInfo.invoke(),
isVerifyButtonVisible = isCurrentSession || viewState.isCurrentSessionTrusted,
isDetailsButtonVisible = false,
isLearnMoreLinkVisible = true,
isLastSeenDetailsVisible = true,
)
views.sessionOverviewInfo.render(infoViewState, dateFormatter, drawableProvider, colorProvider)
} else {
hideSessionInfo()
}
}
private fun hideSessionInfo() {

View File

@ -19,6 +19,7 @@ package im.vector.app.features.settings.devices.v2.overview
import im.vector.app.core.platform.VectorViewEvents
sealed class SessionOverviewViewEvent : VectorViewEvents {
object SelfVerification : SessionOverviewViewEvent()
object ShowVerifyCurrentSession : SessionOverviewViewEvent()
data class ShowVerifyOtherSession(val deviceId: String) : SessionOverviewViewEvent()
object PromptResetSecrets : SessionOverviewViewEvent()
}

View File

@ -21,17 +21,22 @@ import com.airbnb.mvrx.Success
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.settings.devices.v2.IsCurrentSessionUseCase
import im.vector.app.features.settings.devices.v2.verification.CheckIfCurrentSessionCanBeVerifiedUseCase
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
class SessionOverviewViewModel @AssistedInject constructor(
@Assisted val initialState: SessionOverviewViewState,
private val activeSessionHolder: ActiveSessionHolder,
private val isCurrentSessionUseCase: IsCurrentSessionUseCase,
private val getDeviceFullInfoUseCase: GetDeviceFullInfoUseCase,
private val checkIfCurrentSessionCanBeVerifiedUseCase: CheckIfCurrentSessionCanBeVerifiedUseCase,
@ -49,6 +54,7 @@ class SessionOverviewViewModel @AssistedInject constructor(
copy(isCurrentSession = isCurrentSession(deviceId))
}
observeSessionInfo(initialState.deviceId)
observeCurrentSessionInfo()
}
private fun isCurrentSession(deviceId: String): Boolean {
@ -61,6 +67,19 @@ class SessionOverviewViewModel @AssistedInject constructor(
.launchIn(viewModelScope)
}
private fun observeCurrentSessionInfo() {
activeSessionHolder.getSafeActiveSession()
?.sessionParams
?.deviceId
?.let { deviceId ->
getDeviceFullInfoUseCase.execute(deviceId)
.map { it.roomEncryptionTrustLevel == RoomEncryptionTrustLevel.Trusted }
.distinctUntilChanged()
.onEach { setState { copy(isCurrentSessionTrusted = it) } }
.launchIn(viewModelScope)
}
}
override fun handle(action: SessionOverviewAction) {
when (action) {
is SessionOverviewAction.VerifySession -> handleVerifySessionAction()
@ -68,8 +87,10 @@ class SessionOverviewViewModel @AssistedInject constructor(
}
private fun handleVerifySessionAction() = withState { viewState ->
if (isCurrentSession(viewState.deviceId)) {
if (viewState.isCurrentSession) {
handleVerifyCurrentSession()
} else {
handleVerifyOtherSession(viewState.deviceId)
}
}
@ -77,10 +98,14 @@ class SessionOverviewViewModel @AssistedInject constructor(
viewModelScope.launch {
val currentSessionCanBeVerified = checkIfCurrentSessionCanBeVerifiedUseCase.execute()
if (currentSessionCanBeVerified) {
_viewEvents.post(SessionOverviewViewEvent.SelfVerification)
_viewEvents.post(SessionOverviewViewEvent.ShowVerifyCurrentSession)
} else {
_viewEvents.post(SessionOverviewViewEvent.PromptResetSecrets)
}
}
}
private fun handleVerifyOtherSession(deviceId: String) {
_viewEvents.post(SessionOverviewViewEvent.ShowVerifyOtherSession(deviceId))
}
}

View File

@ -24,6 +24,7 @@ import im.vector.app.features.settings.devices.v2.DeviceFullInfo
data class SessionOverviewViewState(
val deviceId: String,
val isCurrentSession: Boolean = false,
val isCurrentSessionTrusted: Boolean = false,
val deviceInfo: Async<DeviceFullInfo> = Uninitialized,
) : MavericksState {
constructor(args: SessionOverviewArgs) : this(

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.app.features.settings.devices.v2
package im.vector.app.features.settings.devices.v2.verification
/**
* Used to hold some info about the cross signing of the current Session.

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.app.features.settings.devices.v2
package im.vector.app.features.settings.devices.v2.verification
import im.vector.app.core.di.ActiveSessionHolder
import kotlinx.coroutines.flow.Flow

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.app.features.settings.devices.v2
package im.vector.app.features.settings.devices.v2.verification
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
import javax.inject.Inject

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.app.features.settings.devices.v2
package im.vector.app.features.settings.devices.v2.verification
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.app.features.settings.devices.v2
package im.vector.app.features.settings.devices.v2.verification
import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel

View File

@ -16,13 +16,10 @@
package im.vector.app.features.settings.devices
import im.vector.app.features.settings.devices.v2.CurrentSessionCrossSigningInfo
import im.vector.app.features.settings.devices.v2.verification.CurrentSessionCrossSigningInfo
import im.vector.app.test.fakes.FakeActiveSessionHolder
import io.mockk.every
import io.mockk.mockk
import org.amshove.kluent.shouldBeEqualTo
import org.junit.Test
import org.matrix.android.sdk.api.auth.data.SessionParams
private const val A_DEVICE_ID = "device-id"
@ -36,9 +33,7 @@ class GetCurrentSessionCrossSigningInfoUseCaseTest {
@Test
fun `given the active session when getting cross signing info then the result is correct`() {
val sessionParams = mockk<SessionParams>()
every { sessionParams.deviceId } returns A_DEVICE_ID
fakeActiveSessionHolder.fakeSession.givenSessionParams(sessionParams)
fakeActiveSessionHolder.fakeSession.givenSessionId(A_DEVICE_ID)
val isCrossSigningInitialized = true
fakeActiveSessionHolder.fakeSession
.fakeCryptoService

View File

@ -19,6 +19,8 @@ package im.vector.app.features.settings.devices.v2
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.test.MvRxTestRule
import im.vector.app.features.settings.devices.v2.verification.CheckIfCurrentSessionCanBeVerifiedUseCase
import im.vector.app.features.settings.devices.v2.verification.CurrentSessionCrossSigningInfo
import im.vector.app.features.settings.devices.v2.verification.GetCurrentSessionCrossSigningInfoUseCase
import im.vector.app.test.fakes.FakeActiveSessionHolder
import im.vector.app.test.fakes.FakeVerificationService
import im.vector.app.test.test

View File

@ -19,6 +19,9 @@ package im.vector.app.features.settings.devices.v2
import im.vector.app.features.settings.devices.v2.filter.DeviceManagerFilterType
import im.vector.app.features.settings.devices.v2.filter.FilterDevicesUseCase
import im.vector.app.features.settings.devices.v2.list.CheckIfSessionIsInactiveUseCase
import im.vector.app.features.settings.devices.v2.verification.CurrentSessionCrossSigningInfo
import im.vector.app.features.settings.devices.v2.verification.GetCurrentSessionCrossSigningInfoUseCase
import im.vector.app.features.settings.devices.v2.verification.GetEncryptionTrustLevelForDeviceUseCase
import im.vector.app.test.fakes.FakeActiveSessionHolder
import im.vector.app.test.test
import im.vector.app.test.testDispatcher

View File

@ -17,8 +17,6 @@
package im.vector.app.features.settings.devices.v2
import im.vector.app.test.fakes.FakeActiveSessionHolder
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import org.amshove.kluent.shouldBe
import org.junit.Test
@ -73,10 +71,7 @@ class IsCurrentSessionUseCaseTest {
result shouldBe false
}
private fun givenIdForCurrentSession(deviceId: String): SessionParams {
val sessionParams = mockk<SessionParams>()
every { sessionParams.deviceId } returns deviceId
fakeActiveSessionHolder.fakeSession.givenSessionParams(sessionParams)
return sessionParams
private fun givenIdForCurrentSession(sessionId: String): SessionParams {
return fakeActiveSessionHolder.fakeSession.givenSessionId(sessionId)
}
}

View File

@ -18,11 +18,11 @@ package im.vector.app.features.settings.devices.v2.overview
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.asFlow
import im.vector.app.features.settings.devices.v2.CurrentSessionCrossSigningInfo
import im.vector.app.features.settings.devices.v2.DeviceFullInfo
import im.vector.app.features.settings.devices.v2.GetCurrentSessionCrossSigningInfoUseCase
import im.vector.app.features.settings.devices.v2.GetEncryptionTrustLevelForDeviceUseCase
import im.vector.app.features.settings.devices.v2.list.CheckIfSessionIsInactiveUseCase
import im.vector.app.features.settings.devices.v2.verification.CurrentSessionCrossSigningInfo
import im.vector.app.features.settings.devices.v2.verification.GetCurrentSessionCrossSigningInfoUseCase
import im.vector.app.features.settings.devices.v2.verification.GetEncryptionTrustLevelForDeviceUseCase
import im.vector.app.test.fakes.FakeActiveSessionHolder
import im.vector.app.test.fakes.FakeFlowLiveDataConversions
import im.vector.app.test.fakes.givenAsFlow

View File

@ -21,6 +21,7 @@ import com.airbnb.mvrx.test.MvRxTestRule
import im.vector.app.features.settings.devices.v2.DeviceFullInfo
import im.vector.app.features.settings.devices.v2.IsCurrentSessionUseCase
import im.vector.app.features.settings.devices.v2.verification.CheckIfCurrentSessionCanBeVerifiedUseCase
import im.vector.app.test.fakes.FakeActiveSessionHolder
import im.vector.app.test.test
import im.vector.app.test.testDispatcher
import io.mockk.coEvery
@ -31,8 +32,10 @@ import io.mockk.verify
import kotlinx.coroutines.flow.flowOf
import org.junit.Rule
import org.junit.Test
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
private const val A_SESSION_ID = "session-id"
private const val A_SESSION_ID_1 = "session-id-1"
private const val A_SESSION_ID_2 = "session-id-2"
class SessionOverviewViewModelTest {
@ -40,30 +43,34 @@ class SessionOverviewViewModelTest {
val mvRxTestRule = MvRxTestRule(testDispatcher = testDispatcher)
private val args = SessionOverviewArgs(
deviceId = A_SESSION_ID
deviceId = A_SESSION_ID_1
)
private val fakeActiveSessionHolder = FakeActiveSessionHolder()
private val isCurrentSessionUseCase = mockk<IsCurrentSessionUseCase>()
private val getDeviceFullInfoUseCase = mockk<GetDeviceFullInfoUseCase>()
private val checkIfCurrentSessionCanBeVerifiedUseCase = mockk<CheckIfCurrentSessionCanBeVerifiedUseCase>()
private fun createViewModel() = SessionOverviewViewModel(
initialState = SessionOverviewViewState(args),
activeSessionHolder = fakeActiveSessionHolder.instance,
isCurrentSessionUseCase = isCurrentSessionUseCase,
getDeviceFullInfoUseCase = getDeviceFullInfoUseCase,
checkIfCurrentSessionCanBeVerifiedUseCase = checkIfCurrentSessionCanBeVerifiedUseCase,
)
@Test
fun `given the viewModel has been initialized then viewState is updated with session info`() {
fun `given the viewModel has been initialized then viewState is updated with session info and current session verification status`() {
// Given
val deviceFullInfo = mockk<DeviceFullInfo>()
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID) } returns flowOf(deviceFullInfo)
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
val isCurrentSession = true
every { isCurrentSessionUseCase.execute(any()) } returns isCurrentSession
givenCurrentSessionIsTrusted()
val expectedState = SessionOverviewViewState(
deviceId = A_SESSION_ID,
deviceId = A_SESSION_ID_1,
isCurrentSession = isCurrentSession,
deviceInfo = Success(deviceFullInfo)
deviceInfo = Success(deviceFullInfo),
isCurrentSessionTrusted = true,
)
// When
@ -74,8 +81,8 @@ class SessionOverviewViewModelTest {
.assertLatestState { state -> state == expectedState }
.finish()
verify {
isCurrentSessionUseCase.execute(A_SESSION_ID)
getDeviceFullInfoUseCase.execute(A_SESSION_ID)
isCurrentSessionUseCase.execute(A_SESSION_ID_1)
getDeviceFullInfoUseCase.execute(A_SESSION_ID_1)
}
}
@ -83,10 +90,11 @@ class SessionOverviewViewModelTest {
fun `given current session can be verified when handling verify current session action then self verification event is posted`() {
// Given
val deviceFullInfo = mockk<DeviceFullInfo>()
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID) } returns flowOf(deviceFullInfo)
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
every { isCurrentSessionUseCase.execute(any()) } returns true
val verifySessionAction = SessionOverviewAction.VerifySession
coEvery { checkIfCurrentSessionCanBeVerifiedUseCase.execute() } returns true
givenCurrentSessionIsTrusted()
// When
val viewModel = createViewModel()
@ -95,7 +103,7 @@ class SessionOverviewViewModelTest {
// Then
viewModelTest
.assertEvent { it is SessionOverviewViewEvent.SelfVerification }
.assertEvent { it is SessionOverviewViewEvent.ShowVerifyCurrentSession }
.finish()
coVerify {
checkIfCurrentSessionCanBeVerifiedUseCase.execute()
@ -106,10 +114,11 @@ class SessionOverviewViewModelTest {
fun `given current session cannot be verified when handling verify current session action then reset secrets event is posted`() {
// Given
val deviceFullInfo = mockk<DeviceFullInfo>()
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID) } returns flowOf(deviceFullInfo)
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
every { isCurrentSessionUseCase.execute(any()) } returns true
val verifySessionAction = SessionOverviewAction.VerifySession
coEvery { checkIfCurrentSessionCanBeVerifiedUseCase.execute() } returns false
givenCurrentSessionIsTrusted()
// When
val viewModel = createViewModel()
@ -124,4 +133,31 @@ class SessionOverviewViewModelTest {
checkIfCurrentSessionCanBeVerifiedUseCase.execute()
}
}
@Test
fun `given another session when handling verify session action then verify session event is posted`() {
// Given
val deviceFullInfo = mockk<DeviceFullInfo>()
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo)
every { isCurrentSessionUseCase.execute(any()) } returns false
val verifySessionAction = SessionOverviewAction.VerifySession
givenCurrentSessionIsTrusted()
// When
val viewModel = createViewModel()
val viewModelTest = viewModel.test()
viewModel.handle(verifySessionAction)
// Then
viewModelTest
.assertEvent { it is SessionOverviewViewEvent.ShowVerifyOtherSession }
.finish()
}
private fun givenCurrentSessionIsTrusted() {
fakeActiveSessionHolder.fakeSession.givenSessionId(A_SESSION_ID_2)
val deviceFullInfo = mockk<DeviceFullInfo>()
every { deviceFullInfo.roomEncryptionTrustLevel } returns RoomEncryptionTrustLevel.Trusted
every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_2) } returns flowOf(deviceFullInfo)
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.app.features.settings.devices.v2
package im.vector.app.features.settings.devices.v2.verification
import im.vector.app.test.fakes.FakeActiveSessionHolder
import im.vector.app.test.fakes.FakeSession
@ -30,7 +30,6 @@ import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.matrix.android.sdk.api.auth.data.SessionParams
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
import org.matrix.android.sdk.api.util.toOptional
@ -107,11 +106,8 @@ class GetCurrentSessionCrossSigningInfoUseCaseTest {
}
private fun givenSession(deviceId: String): FakeSession {
val sessionParams = mockk<SessionParams>()
every { sessionParams.deviceId } returns deviceId
val fakeSession = fakeActiveSessionHolder.fakeSession
fakeSession.givenSessionParams(sessionParams)
fakeSession.givenSessionId(deviceId)
return fakeSession
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.app.features.settings.devices.v2
package im.vector.app.features.settings.devices.v2.verification
import org.amshove.kluent.shouldBeEqualTo
import org.junit.Test

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.app.features.settings.devices.v2
package im.vector.app.features.settings.devices.v2.verification
import io.mockk.every
import io.mockk.mockk

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.app.features.settings.devices.v2
package im.vector.app.features.settings.devices.v2.verification
import org.amshove.kluent.shouldBeEqualTo
import org.junit.Test

View File

@ -78,6 +78,13 @@ class FakeSession(
every { this@FakeSession.sessionParams } returns sessionParams
}
fun givenSessionId(sessionId: String): SessionParams {
val sessionParams = mockk<SessionParams>()
every { sessionParams.deviceId } returns sessionId
givenSessionParams(sessionParams)
return sessionParams
}
/**
* Do not forget to call mockkStatic("org.matrix.android.sdk.flow.FlowSessionKt") in the setup method of the tests.
*/