moving homeserver feature for logout all devices to the selected homeserver state via the LoginFlowResult

This commit is contained in:
Adam Brown 2022-05-31 12:50:26 +01:00
parent 2d44e47e6a
commit 6e3283cb34
11 changed files with 23 additions and 55 deletions

View File

@ -21,5 +21,6 @@ data class LoginFlowResult(
val ssoIdentityProviders: List<SsoIdentityProvider>?,
val isLoginAndRegistrationSupported: Boolean,
val homeServerUrl: String,
val isOutdatedHomeserver: Boolean
val isOutdatedHomeserver: Boolean,
val isLogoutDevicesSupported: Boolean
)

View File

@ -18,7 +18,6 @@ package org.matrix.android.sdk.api.auth.login
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.internal.auth.login.ResetCapabilities
/**
* Set of methods to be able to login to an existing account on a homeserver.
@ -66,9 +65,8 @@ interface LoginWizard {
* [resetPasswordMailConfirmed] is successfully called.
*
* @param email an email previously associated to the account the user wants the password to be reset.
* @return a [ResetCapabilities] if the reset is successful.
*/
suspend fun resetPassword(email: String): ResetCapabilities
suspend fun resetPassword(email: String)
/**
* Confirm the new password, once the user has checked their email

View File

@ -40,6 +40,7 @@ import org.matrix.android.sdk.internal.auth.login.DefaultLoginWizard
import org.matrix.android.sdk.internal.auth.login.DirectLoginTask
import org.matrix.android.sdk.internal.auth.registration.DefaultRegistrationWizard
import org.matrix.android.sdk.internal.auth.version.Versions
import org.matrix.android.sdk.internal.auth.version.doesServerSupportLogoutDevices
import org.matrix.android.sdk.internal.auth.version.isLoginAndRegistrationSupportedBySdk
import org.matrix.android.sdk.internal.auth.version.isSupportedBySdk
import org.matrix.android.sdk.internal.di.Unauthenticated
@ -292,7 +293,8 @@ internal class DefaultAuthenticationService @Inject constructor(
ssoIdentityProviders = loginFlowResponse.flows.orEmpty().firstOrNull { it.type == LoginFlowTypes.SSO }?.ssoIdentityProvider,
isLoginAndRegistrationSupported = versions.isLoginAndRegistrationSupportedBySdk(),
homeServerUrl = homeServerUrl,
isOutdatedHomeserver = !versions.isSupportedBySdk()
isOutdatedHomeserver = !versions.isSupportedBySdk(),
isLogoutDevicesSupported = versions.doesServerSupportLogoutDevices()
)
}

View File

@ -31,7 +31,6 @@ import org.matrix.android.sdk.internal.auth.data.TokenLoginParams
import org.matrix.android.sdk.internal.auth.db.PendingSessionData
import org.matrix.android.sdk.internal.auth.registration.AddThreePidRegistrationParams
import org.matrix.android.sdk.internal.auth.registration.RegisterAddThreePidTask
import org.matrix.android.sdk.internal.auth.version.doesServerSupportLogoutDevices
import org.matrix.android.sdk.internal.network.executeRequest
import org.matrix.android.sdk.internal.session.content.DefaultContentUrlResolver
import org.matrix.android.sdk.internal.session.contentscanner.DisabledContentScannerService
@ -104,7 +103,7 @@ internal class DefaultLoginWizard(
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
}
override suspend fun resetPassword(email: String): ResetCapabilities {
override suspend fun resetPassword(email: String) {
val param = RegisterAddThreePidTask.Params(
RegisterThreePid.Email(email),
pendingSessionData.clientSecret,
@ -120,12 +119,6 @@ internal class DefaultLoginWizard(
pendingSessionData = pendingSessionData.copy(resetPasswordData = ResetPasswordData(result))
.also { pendingSessionStore.savePendingSessionData(it) }
val versions = executeRequest(null) {
authAPI.versions()
}
return ResetCapabilities(supportsLogoutAllDevices = versions.doesServerSupportLogoutDevices())
}
override suspend fun resetPasswordMailConfirmed(newPassword: String, logoutAllDevices: Boolean) {

View File

@ -1,27 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.internal.auth.login
/**
* The reset capabilities of the selected Homeserver
*/
data class ResetCapabilities(
/**
* True if the server supports MSC2457 `logout_devices` parameter when setting a new password.
*/
val supportsLogoutAllDevices: Boolean
)

View File

@ -60,7 +60,6 @@ import org.matrix.android.sdk.api.auth.login.LoginWizard
import org.matrix.android.sdk.api.auth.registration.RegistrationWizard
import org.matrix.android.sdk.api.failure.isHomeserverUnavailable
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.internal.auth.login.ResetCapabilities
import timber.log.Timber
import java.util.UUID
import java.util.concurrent.CancellationException
@ -444,11 +443,12 @@ class OnboardingViewModel @AssistedInject constructor(
setState { copy(isLoading = true) }
currentJob = viewModelScope.launch {
runCatching { safeLoginWizard.resetPassword(action.email) }.fold(
onSuccess = { resetCapabilities ->
onSuccess = {
val state = awaitState()
setState {
copy(
isLoading = false,
resetState = createResetState(action, resetCapabilities)
resetState = createResetState(action, state.selectedHomeserver)
)
}
_viewEvents.post(OnboardingViewEvents.OnResetPasswordSendThreePidDone)
@ -461,10 +461,10 @@ class OnboardingViewModel @AssistedInject constructor(
}
}
private fun createResetState(action: OnboardingAction.ResetPassword, it: ResetCapabilities) = ResetState(
private fun createResetState(action: OnboardingAction.ResetPassword, selectedHomeserverState: SelectedHomeserverState) = ResetState(
email = action.email,
newPassword = action.newPassword,
supportsLogoutAllDevices = it.supportsLogoutAllDevices
supportsLogoutAllDevices = selectedHomeserverState.isLogoutDevicesSupported
)
private fun handleResetPasswordMailConfirmed() {

View File

@ -71,6 +71,7 @@ data class SelectedHomeserverState(
val upstreamUrl: String? = null,
val preferredLoginMode: LoginMode = LoginMode.Unknown,
val supportedLoginTypes: List<String> = emptyList(),
val isLogoutDevicesSupported: Boolean = false,
) : Parcelable
@Parcelize

View File

@ -53,7 +53,8 @@ class StartAuthenticationFlowUseCase @Inject constructor(
userFacingUrl = config.homeServerUri.toString(),
upstreamUrl = authFlow.homeServerUrl,
preferredLoginMode = preferredLoginMode,
supportedLoginTypes = authFlow.supportedLoginTypes
supportedLoginTypes = authFlow.supportedLoginTypes,
isLogoutDevicesSupported = authFlow.isLogoutDevicesSupported
)
private fun matrixOrgUrl() = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash()

View File

@ -52,7 +52,6 @@ import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.api.auth.registration.Stage
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
import org.matrix.android.sdk.internal.auth.login.ResetCapabilities
private const val A_DISPLAY_NAME = "a display name"
private const val A_PICTURE_FILENAME = "a-picture.png"
@ -66,9 +65,9 @@ private val A_DIRECT_LOGIN = OnboardingAction.AuthenticateAction.LoginDirect("@a
private const val A_HOMESERVER_URL = "https://edited-homeserver.org"
private val A_HOMESERVER_CONFIG = HomeServerConnectionConfig(FakeUri().instance)
private val SELECTED_HOMESERVER_STATE = SelectedHomeserverState(preferredLoginMode = LoginMode.Password)
private val SELECTED_HOMESERVER_STATE_SUPPORTED_LOGOUT_DEVICES = SelectedHomeserverState(isLogoutDevicesSupported = true)
private const val AN_EMAIL = "hello@example.com"
private const val A_PASSWORD = "a-password"
private val A_RESET_CAPABILITIES = ResetCapabilities(supportsLogoutAllDevices = true)
class OnboardingViewModelTest {
@ -480,8 +479,9 @@ class OnboardingViewModelTest {
@Test
fun `given can successfully reset password, when resetting password, then emits reset done event`() = runTest {
viewModelWith(initialState.copy(selectedHomeserver = SELECTED_HOMESERVER_STATE_SUPPORTED_LOGOUT_DEVICES))
val test = viewModel.test()
fakeLoginWizard.givenResetPasswordSuccess(AN_EMAIL, A_RESET_CAPABILITIES)
fakeLoginWizard.givenResetPasswordSuccess(AN_EMAIL)
fakeAuthenticationService.givenLoginWizard(fakeLoginWizard)
viewModel.handle(OnboardingAction.ResetPassword(email = AN_EMAIL, newPassword = A_PASSWORD))
@ -491,7 +491,7 @@ class OnboardingViewModelTest {
initialState,
{ copy(isLoading = true) },
{
val resetState = ResetState(AN_EMAIL, A_PASSWORD, supportsLogoutAllDevices = A_RESET_CAPABILITIES.supportsLogoutAllDevices)
val resetState = ResetState(AN_EMAIL, A_PASSWORD, supportsLogoutAllDevices = true)
copy(isLoading = false, resetState = resetState)
}
)

View File

@ -128,7 +128,8 @@ class StartAuthenticationFlowUseCaseTest {
ssoIdentityProviders = SSO_IDENTITY_PROVIDERS,
isLoginAndRegistrationSupported = true,
homeServerUrl = A_DECLARED_HOMESERVER_URL,
isOutdatedHomeserver = false
isOutdatedHomeserver = false,
isLogoutDevicesSupported = false
)
private fun expectedResult(

View File

@ -16,16 +16,14 @@
package im.vector.app.test.fakes
import io.mockk.coEvery
import io.mockk.coJustRun
import io.mockk.mockk
import org.matrix.android.sdk.api.auth.login.LoginWizard
import org.matrix.android.sdk.internal.auth.login.ResetCapabilities
class FakeLoginWizard : LoginWizard by mockk() {
fun givenResetPasswordSuccess(email: String, resetCapabilities: ResetCapabilities) {
coEvery { resetPassword(email) } returns resetCapabilities
fun givenResetPasswordSuccess(email: String) {
coJustRun { resetPassword(email) }
}
fun givenConfirmResetPasswordSuccess(password: String) {