moving homeserver feature for logout all devices to the selected homeserver state via the LoginFlowResult
This commit is contained in:
parent
2d44e47e6a
commit
6e3283cb34
@ -21,5 +21,6 @@ data class LoginFlowResult(
|
|||||||
val ssoIdentityProviders: List<SsoIdentityProvider>?,
|
val ssoIdentityProviders: List<SsoIdentityProvider>?,
|
||||||
val isLoginAndRegistrationSupported: Boolean,
|
val isLoginAndRegistrationSupported: Boolean,
|
||||||
val homeServerUrl: String,
|
val homeServerUrl: String,
|
||||||
val isOutdatedHomeserver: Boolean
|
val isOutdatedHomeserver: Boolean,
|
||||||
|
val isLogoutDevicesSupported: Boolean
|
||||||
)
|
)
|
||||||
|
@ -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.session.Session
|
||||||
import org.matrix.android.sdk.api.util.JsonDict
|
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.
|
* 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.
|
* [resetPasswordMailConfirmed] is successfully called.
|
||||||
*
|
*
|
||||||
* @param email an email previously associated to the account the user wants the password to be reset.
|
* @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
|
* Confirm the new password, once the user has checked their email
|
||||||
|
@ -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.login.DirectLoginTask
|
||||||
import org.matrix.android.sdk.internal.auth.registration.DefaultRegistrationWizard
|
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.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.isLoginAndRegistrationSupportedBySdk
|
||||||
import org.matrix.android.sdk.internal.auth.version.isSupportedBySdk
|
import org.matrix.android.sdk.internal.auth.version.isSupportedBySdk
|
||||||
import org.matrix.android.sdk.internal.di.Unauthenticated
|
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,
|
ssoIdentityProviders = loginFlowResponse.flows.orEmpty().firstOrNull { it.type == LoginFlowTypes.SSO }?.ssoIdentityProvider,
|
||||||
isLoginAndRegistrationSupported = versions.isLoginAndRegistrationSupportedBySdk(),
|
isLoginAndRegistrationSupported = versions.isLoginAndRegistrationSupportedBySdk(),
|
||||||
homeServerUrl = homeServerUrl,
|
homeServerUrl = homeServerUrl,
|
||||||
isOutdatedHomeserver = !versions.isSupportedBySdk()
|
isOutdatedHomeserver = !versions.isSupportedBySdk(),
|
||||||
|
isLogoutDevicesSupported = versions.doesServerSupportLogoutDevices()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.db.PendingSessionData
|
||||||
import org.matrix.android.sdk.internal.auth.registration.AddThreePidRegistrationParams
|
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.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.network.executeRequest
|
||||||
import org.matrix.android.sdk.internal.session.content.DefaultContentUrlResolver
|
import org.matrix.android.sdk.internal.session.content.DefaultContentUrlResolver
|
||||||
import org.matrix.android.sdk.internal.session.contentscanner.DisabledContentScannerService
|
import org.matrix.android.sdk.internal.session.contentscanner.DisabledContentScannerService
|
||||||
@ -104,7 +103,7 @@ internal class DefaultLoginWizard(
|
|||||||
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
|
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun resetPassword(email: String): ResetCapabilities {
|
override suspend fun resetPassword(email: String) {
|
||||||
val param = RegisterAddThreePidTask.Params(
|
val param = RegisterAddThreePidTask.Params(
|
||||||
RegisterThreePid.Email(email),
|
RegisterThreePid.Email(email),
|
||||||
pendingSessionData.clientSecret,
|
pendingSessionData.clientSecret,
|
||||||
@ -120,12 +119,6 @@ internal class DefaultLoginWizard(
|
|||||||
|
|
||||||
pendingSessionData = pendingSessionData.copy(resetPasswordData = ResetPasswordData(result))
|
pendingSessionData = pendingSessionData.copy(resetPasswordData = ResetPasswordData(result))
|
||||||
.also { pendingSessionStore.savePendingSessionData(it) }
|
.also { pendingSessionStore.savePendingSessionData(it) }
|
||||||
|
|
||||||
val versions = executeRequest(null) {
|
|
||||||
authAPI.versions()
|
|
||||||
}
|
|
||||||
|
|
||||||
return ResetCapabilities(supportsLogoutAllDevices = versions.doesServerSupportLogoutDevices())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun resetPasswordMailConfirmed(newPassword: String, logoutAllDevices: Boolean) {
|
override suspend fun resetPasswordMailConfirmed(newPassword: String, logoutAllDevices: Boolean) {
|
||||||
|
@ -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
|
|
||||||
)
|
|
@ -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.auth.registration.RegistrationWizard
|
||||||
import org.matrix.android.sdk.api.failure.isHomeserverUnavailable
|
import org.matrix.android.sdk.api.failure.isHomeserverUnavailable
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.internal.auth.login.ResetCapabilities
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import java.util.concurrent.CancellationException
|
import java.util.concurrent.CancellationException
|
||||||
@ -444,11 +443,12 @@ class OnboardingViewModel @AssistedInject constructor(
|
|||||||
setState { copy(isLoading = true) }
|
setState { copy(isLoading = true) }
|
||||||
currentJob = viewModelScope.launch {
|
currentJob = viewModelScope.launch {
|
||||||
runCatching { safeLoginWizard.resetPassword(action.email) }.fold(
|
runCatching { safeLoginWizard.resetPassword(action.email) }.fold(
|
||||||
onSuccess = { resetCapabilities ->
|
onSuccess = {
|
||||||
|
val state = awaitState()
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
isLoading = false,
|
isLoading = false,
|
||||||
resetState = createResetState(action, resetCapabilities)
|
resetState = createResetState(action, state.selectedHomeserver)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_viewEvents.post(OnboardingViewEvents.OnResetPasswordSendThreePidDone)
|
_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,
|
email = action.email,
|
||||||
newPassword = action.newPassword,
|
newPassword = action.newPassword,
|
||||||
supportsLogoutAllDevices = it.supportsLogoutAllDevices
|
supportsLogoutAllDevices = selectedHomeserverState.isLogoutDevicesSupported
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun handleResetPasswordMailConfirmed() {
|
private fun handleResetPasswordMailConfirmed() {
|
||||||
|
@ -71,6 +71,7 @@ data class SelectedHomeserverState(
|
|||||||
val upstreamUrl: String? = null,
|
val upstreamUrl: String? = null,
|
||||||
val preferredLoginMode: LoginMode = LoginMode.Unknown,
|
val preferredLoginMode: LoginMode = LoginMode.Unknown,
|
||||||
val supportedLoginTypes: List<String> = emptyList(),
|
val supportedLoginTypes: List<String> = emptyList(),
|
||||||
|
val isLogoutDevicesSupported: Boolean = false,
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
|
@ -53,7 +53,8 @@ class StartAuthenticationFlowUseCase @Inject constructor(
|
|||||||
userFacingUrl = config.homeServerUri.toString(),
|
userFacingUrl = config.homeServerUri.toString(),
|
||||||
upstreamUrl = authFlow.homeServerUrl,
|
upstreamUrl = authFlow.homeServerUrl,
|
||||||
preferredLoginMode = preferredLoginMode,
|
preferredLoginMode = preferredLoginMode,
|
||||||
supportedLoginTypes = authFlow.supportedLoginTypes
|
supportedLoginTypes = authFlow.supportedLoginTypes,
|
||||||
|
isLogoutDevicesSupported = authFlow.isLogoutDevicesSupported
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun matrixOrgUrl() = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash()
|
private fun matrixOrgUrl() = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash()
|
||||||
|
@ -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.auth.registration.Stage
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
|
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_DISPLAY_NAME = "a display name"
|
||||||
private const val A_PICTURE_FILENAME = "a-picture.png"
|
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 const val A_HOMESERVER_URL = "https://edited-homeserver.org"
|
||||||
private val A_HOMESERVER_CONFIG = HomeServerConnectionConfig(FakeUri().instance)
|
private val A_HOMESERVER_CONFIG = HomeServerConnectionConfig(FakeUri().instance)
|
||||||
private val SELECTED_HOMESERVER_STATE = SelectedHomeserverState(preferredLoginMode = LoginMode.Password)
|
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 AN_EMAIL = "hello@example.com"
|
||||||
private const val A_PASSWORD = "a-password"
|
private const val A_PASSWORD = "a-password"
|
||||||
private val A_RESET_CAPABILITIES = ResetCapabilities(supportsLogoutAllDevices = true)
|
|
||||||
|
|
||||||
class OnboardingViewModelTest {
|
class OnboardingViewModelTest {
|
||||||
|
|
||||||
@ -480,8 +479,9 @@ class OnboardingViewModelTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given can successfully reset password, when resetting password, then emits reset done event`() = runTest {
|
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()
|
val test = viewModel.test()
|
||||||
fakeLoginWizard.givenResetPasswordSuccess(AN_EMAIL, A_RESET_CAPABILITIES)
|
fakeLoginWizard.givenResetPasswordSuccess(AN_EMAIL)
|
||||||
fakeAuthenticationService.givenLoginWizard(fakeLoginWizard)
|
fakeAuthenticationService.givenLoginWizard(fakeLoginWizard)
|
||||||
|
|
||||||
viewModel.handle(OnboardingAction.ResetPassword(email = AN_EMAIL, newPassword = A_PASSWORD))
|
viewModel.handle(OnboardingAction.ResetPassword(email = AN_EMAIL, newPassword = A_PASSWORD))
|
||||||
@ -491,7 +491,7 @@ class OnboardingViewModelTest {
|
|||||||
initialState,
|
initialState,
|
||||||
{ copy(isLoading = true) },
|
{ 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)
|
copy(isLoading = false, resetState = resetState)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -128,7 +128,8 @@ class StartAuthenticationFlowUseCaseTest {
|
|||||||
ssoIdentityProviders = SSO_IDENTITY_PROVIDERS,
|
ssoIdentityProviders = SSO_IDENTITY_PROVIDERS,
|
||||||
isLoginAndRegistrationSupported = true,
|
isLoginAndRegistrationSupported = true,
|
||||||
homeServerUrl = A_DECLARED_HOMESERVER_URL,
|
homeServerUrl = A_DECLARED_HOMESERVER_URL,
|
||||||
isOutdatedHomeserver = false
|
isOutdatedHomeserver = false,
|
||||||
|
isLogoutDevicesSupported = false
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun expectedResult(
|
private fun expectedResult(
|
||||||
|
@ -16,16 +16,14 @@
|
|||||||
|
|
||||||
package im.vector.app.test.fakes
|
package im.vector.app.test.fakes
|
||||||
|
|
||||||
import io.mockk.coEvery
|
|
||||||
import io.mockk.coJustRun
|
import io.mockk.coJustRun
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import org.matrix.android.sdk.api.auth.login.LoginWizard
|
import org.matrix.android.sdk.api.auth.login.LoginWizard
|
||||||
import org.matrix.android.sdk.internal.auth.login.ResetCapabilities
|
|
||||||
|
|
||||||
class FakeLoginWizard : LoginWizard by mockk() {
|
class FakeLoginWizard : LoginWizard by mockk() {
|
||||||
|
|
||||||
fun givenResetPasswordSuccess(email: String, resetCapabilities: ResetCapabilities) {
|
fun givenResetPasswordSuccess(email: String) {
|
||||||
coEvery { resetPassword(email) } returns resetCapabilities
|
coJustRun { resetPassword(email) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun givenConfirmResetPasswordSuccess(password: String) {
|
fun givenConfirmResetPasswordSuccess(password: String) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user