Remove SessionData.needsVerification as the source of truth for session verification status (#2748)

* Remove `SessionData.needsVerification` as the source of truth for session verification status.

- Use the Rust SDK `EncryptionService.verificationState()` instead, but always waiting for the first 'known' result (either verified or not, discarding 'unknown').
- Add a workaround in the super rare case when reading this value gets stuck somehow. We'll assume the user is not verified in that case.
- Make `DefaultFtueService.getNextStep` and dependent checks `suspend`.
- Make the `skip` button use a value in the session preferences instead.

* Log exception when the verification status can't be loaded

Co-authored-by: Benoit Marty <benoit@matrix.org>

* Fix review comments

---------

Co-authored-by: Benoit Marty <benoit@matrix.org>
This commit is contained in:
Jorge Martin Espinosa 2024-04-24 15:55:25 +02:00 committed by GitHub
parent c83712ca91
commit 2cc124bda2
26 changed files with 99 additions and 106 deletions

View file

@ -23,11 +23,11 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import com.freeletics.flowredux.compose.rememberStateAndDispatch
import io.element.android.features.preferences.api.store.SessionPreferencesStore
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.meta.BuildMeta
@ -49,6 +49,7 @@ class VerifySelfSessionPresenter @Inject constructor(
private val encryptionService: EncryptionService,
private val stateMachine: VerifySelfSessionStateMachine,
private val buildMeta: BuildMeta,
private val sessionPreferencesStore: SessionPreferencesStore,
) : Presenter<VerifySelfSessionState> {
@Composable
override fun present(): VerifySelfSessionState {
@ -59,8 +60,8 @@ class VerifySelfSessionPresenter @Inject constructor(
}
val recoveryState by encryptionService.recoveryStateStateFlow.collectAsState()
val stateAndDispatch = stateMachine.rememberStateAndDispatch()
var skipVerification by remember { mutableStateOf(false) }
val needsVerification by sessionVerificationService.needsVerificationFlow.collectAsState()
val skipVerification by sessionPreferencesStore.isSessionVerificationSkipped().collectAsState(initial = false)
val needsVerification by sessionVerificationService.canVerifySessionFlow.collectAsState(initial = true)
val verificationFlowStep by remember {
derivedStateOf {
when {
@ -86,8 +87,7 @@ class VerifySelfSessionPresenter @Inject constructor(
VerifySelfSessionViewEvents.Cancel -> stateAndDispatch.dispatchAction(StateMachineEvent.Cancel)
VerifySelfSessionViewEvents.Reset -> stateAndDispatch.dispatchAction(StateMachineEvent.Reset)
VerifySelfSessionViewEvents.SkipVerification -> coroutineScope.launch {
sessionVerificationService.saveVerifiedState(true)
skipVerification = true
sessionPreferencesStore.setSkipSessionVerification(true)
}
}
}

View file

@ -24,6 +24,7 @@ import com.google.common.truth.Truth.assertThat
import io.element.android.features.verifysession.impl.VerifySelfSessionState.VerificationStep
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.featureflag.test.InMemorySessionPreferencesStore
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.RecoveryState
import io.element.android.libraries.matrix.api.verification.SessionVerificationData
@ -35,7 +36,6 @@ import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.lambda.value
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Rule
@ -289,7 +289,6 @@ class VerifySelfSessionPresenterTests {
}.test {
val state = requestVerificationAndAwaitVerifyingState(service)
state.eventSink(VerifySelfSessionViewEvents.SkipVerification)
service.saveVerifiedStateResult.assertions().isCalledOnce().with(value(true))
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Skipped)
}
}
@ -297,12 +296,16 @@ class VerifySelfSessionPresenterTests {
@Test
fun `present - When verification is not needed, the flow is completed`() = runTest {
val service = FakeSessionVerificationService().apply {
givenNeedsVerification(false)
givenCanVerifySession(false)
givenIsReady(true)
givenVerifiedStatus(SessionVerifiedStatus.Verified)
givenVerificationFlowState(VerificationFlowState.Finished)
}
val presenter = createVerifySelfSessionPresenter(service)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
skipItems(1)
assertThat(awaitItem().verificationFlowStep).isEqualTo(VerificationStep.Completed)
}
}
@ -334,7 +337,6 @@ class VerifySelfSessionPresenterTests {
private fun unverifiedSessionService(): FakeSessionVerificationService {
return FakeSessionVerificationService().apply {
givenVerifiedStatus(SessionVerifiedStatus.NotVerified)
givenNeedsVerification(true)
}
}
@ -342,12 +344,14 @@ class VerifySelfSessionPresenterTests {
service: SessionVerificationService = unverifiedSessionService(),
encryptionService: EncryptionService = FakeEncryptionService(),
buildMeta: BuildMeta = aBuildMeta(),
sessionPreferencesStore: InMemorySessionPreferencesStore = InMemorySessionPreferencesStore(),
): VerifySelfSessionPresenter {
return VerifySelfSessionPresenter(
sessionVerificationService = service,
encryptionService = encryptionService,
stateMachine = VerifySelfSessionStateMachine(service, encryptionService),
buildMeta = buildMeta,
sessionPreferencesStore = sessionPreferencesStore,
)
}
}