mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-25 19:05:56 +03:00
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:
commit
e98bfe5c9b
29 changed files with 143 additions and 69 deletions
1
changelog.d/7143.wip
Normal file
1
changelog.d/7143.wip
Normal file
|
@ -0,0 +1 @@
|
|||
[Device management] Verify another session
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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.
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue