diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewAction.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewAction.kt index cea0281570..c0d428b951 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewAction.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewAction.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 New Vector Ltd + * Copyright (c) 2022 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. @@ -21,4 +21,7 @@ import im.vector.app.core.platform.VectorViewModelAction sealed class SessionOverviewAction : VectorViewModelAction { object VerifySession : SessionOverviewAction() object SignoutSession : SessionOverviewAction() + object SsoAuthDone : SessionOverviewAction() + data class PasswordAuthDone(val password: String) : SessionOverviewAction() + object ReAuthCancelled : SessionOverviewAction() } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt index ccf68a18bc..c369065292 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt @@ -16,6 +16,7 @@ package im.vector.app.features.settings.devices.v2.overview +import android.app.Activity import android.os.Bundle import android.view.LayoutInflater import android.view.MenuItem @@ -30,13 +31,16 @@ import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R import im.vector.app.core.date.VectorDateFormatter +import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.platform.VectorMenuProvider 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.auth.ReAuthActivity import im.vector.app.features.crypto.recover.SetupMode import im.vector.app.features.settings.devices.v2.list.SessionInfoViewState +import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import javax.inject.Inject /** @@ -92,6 +96,7 @@ class SessionOverviewFragment : is SessionOverviewViewEvent.PromptResetSecrets -> { navigator.open4SSetup(requireActivity(), SetupMode.PASSPHRASE_AND_NEEDED_SECRETS_RESET) } + is SessionOverviewViewEvent.RequestReAuth -> askForReAuthentication(it) } } } @@ -157,4 +162,37 @@ class SessionOverviewFragment : views.sessionOverviewInfo.isVisible = false } } + + private val reAuthActivityResultLauncher = registerStartForActivityResult { activityResult -> + if (activityResult.resultCode == Activity.RESULT_OK) { + when (activityResult.data?.extras?.getString(ReAuthActivity.RESULT_FLOW_TYPE)) { + LoginFlowTypes.SSO -> { + viewModel.handle(SessionOverviewAction.SsoAuthDone) + } + LoginFlowTypes.PASSWORD -> { + val password = activityResult.data?.extras?.getString(ReAuthActivity.RESULT_VALUE) ?: "" + viewModel.handle(SessionOverviewAction.PasswordAuthDone(password)) + } + else -> { + viewModel.handle(SessionOverviewAction.ReAuthCancelled) + } + } + } else { + viewModel.handle(SessionOverviewAction.ReAuthCancelled) + } + } + + /** + * Launch the re auth activity to get credentials. + */ + private fun askForReAuthentication(reAuthReq: SessionOverviewViewEvent.RequestReAuth) { + ReAuthActivity.newIntent( + requireContext(), + reAuthReq.registrationFlowResponse, + reAuthReq.lastErrorCode, + getString(R.string.devices_delete_dialog_title) + ).let { intent -> + reAuthActivityResultLauncher.launch(intent) + } + } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt index 2f3116f40f..7dab404167 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt @@ -28,6 +28,7 @@ import im.vector.app.core.platform.VectorViewModel import im.vector.app.features.auth.PendingAuthHandler import im.vector.app.features.settings.devices.v2.IsCurrentSessionUseCase import im.vector.app.features.settings.devices.v2.signout.InterceptSignoutFlowResponseUseCase +import im.vector.app.features.settings.devices.v2.signout.SignoutSessionResult import im.vector.app.features.settings.devices.v2.signout.SignoutSessionUseCase import im.vector.app.features.settings.devices.v2.verification.CheckIfCurrentSessionCanBeVerifiedUseCase import kotlinx.coroutines.flow.distinctUntilChanged @@ -40,6 +41,7 @@ import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth +import timber.log.Timber import kotlin.coroutines.Continuation class SessionOverviewViewModel @AssistedInject constructor( @@ -91,10 +93,14 @@ class SessionOverviewViewModel @AssistedInject constructor( } } + // TODO add unit tests override fun handle(action: SessionOverviewAction) { when (action) { is SessionOverviewAction.VerifySession -> handleVerifySessionAction() SessionOverviewAction.SignoutSession -> handleSignoutSession() + SessionOverviewAction.SsoAuthDone -> handleSsoAuthDone() + is SessionOverviewAction.PasswordAuthDone -> handlePasswordAuthDone(action) + SessionOverviewAction.ReAuthCancelled -> handleReAuthCancelled() } } @@ -129,7 +135,11 @@ class SessionOverviewViewModel @AssistedInject constructor( override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation) { when (val result = interceptSignoutFlowResponseUseCase.execute(flowResponse, errCode, promise)) { is SignoutSessionResult.ReAuthNeeded -> onReAuthNeeded(result) - is SignoutSessionResult.Completed -> Unit // TODO refresh devices list? + post event to close the associated screen + is SignoutSessionResult.Completed -> { + Timber.d("signout completed") + // TODO check if it is called after a reAuth + // TODO refresh devices list? + post event to close the associated screen + } } } }) @@ -137,8 +147,21 @@ class SessionOverviewViewModel @AssistedInject constructor( } private fun onReAuthNeeded(reAuthNeeded: SignoutSessionResult.ReAuthNeeded) { + Timber.d("onReAuthNeeded") pendingAuthHandler.pendingAuth = DefaultBaseAuth(session = reAuthNeeded.flowResponse.session) pendingAuthHandler.uiaContinuation = reAuthNeeded.uiaContinuation _viewEvents.post(SessionOverviewViewEvent.RequestReAuth(reAuthNeeded.flowResponse, reAuthNeeded.errCode)) } + + private fun handleSsoAuthDone() { + pendingAuthHandler.ssoAuthDone() + } + + private fun handlePasswordAuthDone(action: SessionOverviewAction.PasswordAuthDone) { + pendingAuthHandler.passwordAuthDone(action.password) + } + + private fun handleReAuthCancelled() { + pendingAuthHandler.reAuthCancelled() + } }