Browse Source

Prevent verification while initial sync is in progress (#1138)

* Prevent verification while initial sync is in progress

* Add `canVerifySessionFlow` to simplify the check
pull/1146/head
Jorge Martin Espinosa 1 year ago committed by GitHub
parent
commit
c670fc9e9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      changelog.d/1131.bugfix
  2. 11
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt
  3. 5
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt
  4. 2
      features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt
  5. 6
      libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/SessionVerificationService.kt
  6. 17
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt
  7. 11
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt
  8. 11
      libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/verification/FakeSessionVerificationService.kt

1
changelog.d/1131.bugfix

@ -0,0 +1 @@ @@ -0,0 +1 @@
Only display verification prompt after initial sync is done.

11
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt

@ -20,7 +20,6 @@ import androidx.compose.runtime.Composable @@ -20,7 +20,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
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
@ -34,7 +33,6 @@ import io.element.android.libraries.matrix.api.MatrixClient @@ -34,7 +33,6 @@ import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.api.user.getCurrentUser
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
import io.element.android.services.analytics.api.AnalyticsService
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@ -62,11 +60,8 @@ class PreferencesRootPresenter @Inject constructor( @@ -62,11 +60,8 @@ class PreferencesRootPresenter @Inject constructor(
val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState()
val hasAnalyticsProviders = remember { analyticsService.getAvailableAnalyticsProviders().isNotEmpty() }
// Session verification status (unknown, not verified, verified)
val sessionVerifiedStatus by sessionVerificationService.sessionVerifiedStatus.collectAsState()
val sessionIsNotVerified by remember {
derivedStateOf { sessionVerifiedStatus == SessionVerifiedStatus.NotVerified }
}
// We should display the 'complete verification' option if the current session can be verified
val showCompleteVerification by sessionVerificationService.canVerifySessionFlow.collectAsState(false)
val accountManagementUrl: MutableState<String?> = remember {
mutableStateOf(null)
@ -82,7 +77,7 @@ class PreferencesRootPresenter @Inject constructor( @@ -82,7 +77,7 @@ class PreferencesRootPresenter @Inject constructor(
logoutState = logoutState,
myUser = matrixUser.value,
version = versionFormatter.get(),
showCompleteVerification = sessionIsNotVerified,
showCompleteVerification = showCompleteVerification,
accountManagementUrl = accountManagementUrl.value,
showAnalyticsSettings = hasAnalyticsProviders,
showDeveloperSettings = showDeveloperSettings,

5
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt

@ -39,7 +39,6 @@ import io.element.android.libraries.matrix.api.MatrixClient @@ -39,7 +39,6 @@ import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.api.user.getCurrentUser
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import javax.inject.Inject
@ -73,11 +72,11 @@ class RoomListPresenter @Inject constructor( @@ -73,11 +72,11 @@ class RoomListPresenter @Inject constructor(
}
// Session verification status (unknown, not verified, verified)
val sessionVerifiedStatus by sessionVerificationService.sessionVerifiedStatus.collectAsState()
val canVerifySession by sessionVerificationService.canVerifySessionFlow.collectAsState(initial = false)
var verificationPromptDismissed by rememberSaveable { mutableStateOf(false) }
// We combine both values to only display the prompt if the session is not verified and it wasn't dismissed
val displayVerificationPrompt by remember {
derivedStateOf { sessionVerifiedStatus == SessionVerifiedStatus.NotVerified && !verificationPromptDismissed }
derivedStateOf { canVerifySession && !verificationPromptDismissed }
}
var displaySearchResults by rememberSaveable { mutableStateOf(false) }

2
features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt

@ -202,7 +202,7 @@ class RoomListPresenterTests { @@ -202,7 +202,7 @@ class RoomListPresenterTests {
fun `present - handle DismissRequestVerificationPrompt`() = runTest {
val roomListService = FakeRoomListService()
val matrixClient = FakeMatrixClient(
roomListService = roomListService
roomListService = roomListService,
)
val presenter = createRoomListPresenter(
client = matrixClient,

6
libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/verification/SessionVerificationService.kt

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package io.element.android.libraries.matrix.api.verification
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
interface SessionVerificationService {
@ -37,6 +38,11 @@ interface SessionVerificationService { @@ -37,6 +38,11 @@ interface SessionVerificationService {
*/
val sessionVerifiedStatus: StateFlow<SessionVerifiedStatus>
/**
* Returns whether the current session needs to be verified and the SDK is ready to start the verification.
*/
val canVerifySessionFlow: Flow<Boolean>
/**
* Request verification of the current session.
*/

17
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt

@ -35,7 +35,6 @@ import io.element.android.libraries.matrix.api.room.RoomMembershipObserver @@ -35,7 +35,6 @@ import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.roomlist.awaitLoaded
import io.element.android.libraries.matrix.api.sync.SyncService
import io.element.android.libraries.matrix.api.sync.SyncState
import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
@ -93,8 +92,8 @@ class RustMatrixClient constructor( @@ -93,8 +92,8 @@ class RustMatrixClient constructor(
private val innerRoomListService = syncService.roomListService()
private val sessionDispatcher = dispatchers.io.limitedParallelism(64)
private val sessionCoroutineScope = appCoroutineScope.childScope(dispatchers.main, "Session-${sessionId}")
private val verificationService = RustSessionVerificationService()
private val rustSyncService = RustSyncService(syncService, sessionCoroutineScope)
private val verificationService = RustSessionVerificationService(rustSyncService)
private val pushersService = RustPushersService(
client = client,
dispatchers = dispatchers,
@ -149,13 +148,11 @@ class RustMatrixClient constructor( @@ -149,13 +148,11 @@ class RustMatrixClient constructor(
init {
client.setDelegate(clientDelegate)
rustSyncService.syncState
.onEach { syncState ->
if (syncState == SyncState.Running) {
onSlidingSyncUpdate()
roomListService.state.onEach { state ->
if (state == RoomListService.State.Running) {
setupVerificationControllerIfNeeded()
}
}
.launchIn(sessionCoroutineScope)
}.launchIn(sessionCoroutineScope)
}
override suspend fun getRoom(roomId: RoomId): MatrixRoom? = withContext(sessionDispatcher) {
@ -338,8 +335,8 @@ class RustMatrixClient constructor( @@ -338,8 +335,8 @@ class RustMatrixClient constructor(
}
}
private fun onSlidingSyncUpdate() {
if (!verificationService.isReady.value) {
private fun setupVerificationControllerIfNeeded() {
if (verificationService.verificationController == null) {
try {
verificationService.verificationController = client.getSessionVerificationController()
} catch (e: Throwable) {

11
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt

@ -17,20 +17,25 @@ @@ -17,20 +17,25 @@
package io.element.android.libraries.matrix.impl.verification
import io.element.android.libraries.core.data.tryOrNull
import io.element.android.libraries.matrix.api.sync.SyncState
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
import io.element.android.libraries.matrix.api.verification.VerificationFlowState
import io.element.android.libraries.matrix.impl.sync.RustSyncService
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import org.matrix.rustcomponents.sdk.SessionVerificationController
import org.matrix.rustcomponents.sdk.SessionVerificationControllerDelegate
import org.matrix.rustcomponents.sdk.SessionVerificationControllerInterface
import org.matrix.rustcomponents.sdk.SessionVerificationEmoji
import javax.inject.Inject
class RustSessionVerificationService @Inject constructor() : SessionVerificationService, SessionVerificationControllerDelegate {
class RustSessionVerificationService @Inject constructor(
private val syncService: RustSyncService,
) : SessionVerificationService, SessionVerificationControllerDelegate {
var verificationController: SessionVerificationControllerInterface? = null
set(value) {
@ -52,6 +57,10 @@ class RustSessionVerificationService @Inject constructor() : SessionVerification @@ -52,6 +57,10 @@ class RustSessionVerificationService @Inject constructor() : SessionVerification
private val _sessionVerifiedStatus = MutableStateFlow<SessionVerifiedStatus>(SessionVerifiedStatus.Unknown)
override val sessionVerifiedStatus: StateFlow<SessionVerifiedStatus> = _sessionVerifiedStatus.asStateFlow()
override val canVerifySessionFlow = combine(sessionVerifiedStatus, syncService.syncState) { verificationStatus, syncState ->
syncState == SyncState.Running && verificationStatus == SessionVerifiedStatus.NotVerified
}
override suspend fun requestVerification() = tryOrFail {
verificationController?.requestVerification()
}

11
libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/verification/FakeSessionVerificationService.kt

@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.verification.SessionVerificationS @@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.verification.SessionVerificationS
import io.element.android.libraries.matrix.api.verification.VerificationFlowState
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@ -27,13 +28,13 @@ class FakeSessionVerificationService : SessionVerificationService { @@ -27,13 +28,13 @@ class FakeSessionVerificationService : SessionVerificationService {
private val _isReady = MutableStateFlow(false)
private val _sessionVerifiedStatus = MutableStateFlow<SessionVerifiedStatus>(SessionVerifiedStatus.Unknown)
private var _verificationFlowState = MutableStateFlow<VerificationFlowState>(VerificationFlowState.Initial)
private var _canVerifySessionFlow = MutableStateFlow(true)
private var emojiList = emptyList<VerificationEmoji>()
var shouldFail = false
override val verificationFlowState: StateFlow<VerificationFlowState>
get() = _verificationFlowState
override val verificationFlowState: StateFlow<VerificationFlowState> =_verificationFlowState
override val sessionVerifiedStatus: StateFlow<SessionVerifiedStatus> = _sessionVerifiedStatus
override val canVerifySessionFlow: Flow<Boolean> = _canVerifySessionFlow
override val isReady: StateFlow<Boolean> = _isReady
@ -77,6 +78,10 @@ class FakeSessionVerificationService : SessionVerificationService { @@ -77,6 +78,10 @@ class FakeSessionVerificationService : SessionVerificationService {
_verificationFlowState.value = state
}
fun givenCanVerifySession(canVerify: Boolean) {
_canVerifySessionFlow.value = canVerify
}
fun givenIsReady(value: Boolean) {
_isReady.value = value
}

Loading…
Cancel
Save