Make the server selection coordinator aware of which flow it is for.

Don't set the authentication state until after registration has been queried to avoid using the wrong client if the user cancelled the selection.
This commit is contained in:
Doug 2022-05-24 13:10:13 +01:00
parent 8b744d4162
commit 857cc8c69c
6 changed files with 26 additions and 25 deletions

View file

@ -187,6 +187,7 @@ final class AuthenticationCoordinator: NSObject, AuthenticationCoordinatorProtoc
@MainActor private func showServerSelectionScreen() {
MXLog.debug("[AuthenticationCoordinator] showServerSelectionScreen")
let parameters = AuthenticationServerSelectionCoordinatorParameters(authenticationService: authenticationService,
flow: .register,
hasModalPresentation: false)
let coordinator = AuthenticationServerSelectionCoordinator(parameters: parameters)
coordinator.callback = { [weak self, weak coordinator] result in

View file

@ -84,14 +84,7 @@ class AuthenticationService: NSObject {
}
func startFlow(_ flow: AuthenticationFlow, for homeserverAddress: String) async throws {
reset()
let loginFlows = try await loginFlow(for: homeserverAddress)
state.homeserver = .init(address: loginFlows.homeserverAddress,
addressFromUser: homeserverAddress,
preferredLoginMode: loginFlows.loginMode,
loginModeSupportedTypes: loginFlows.supportedLoginTypes)
var (client, state) = try await loginFlow(for: homeserverAddress)
let loginWizard = LoginWizard(client: client)
self.loginWizard = loginWizard
@ -100,6 +93,7 @@ class AuthenticationService: NSObject {
do {
let registrationWizard = RegistrationWizard(client: client)
state.homeserver.registrationFlow = try await registrationWizard.registrationFlow()
state.flow = .register
self.registrationWizard = registrationWizard
} catch {
guard state.homeserver.preferredLoginMode.hasSSO, error as? RegistrationError == .registrationDisabled else {
@ -109,7 +103,8 @@ class AuthenticationService: NSObject {
}
}
state.flow = flow
self.state = state
self.client = client
}
/// Get a SSO url
@ -173,7 +168,7 @@ class AuthenticationService: NSObject {
/// Request the supported login flows for this homeserver.
/// This is the first method to call to be able to get a wizard to login or to create an account
/// - Parameter homeserverAddress: The homeserver string entered by the user.
private func loginFlow(for homeserverAddress: String) async throws -> LoginFlowResult {
private func loginFlow(for homeserverAddress: String) async throws -> (AuthenticationRestClient, AuthenticationState) {
let homeserverAddress = HomeserverAddress.sanitized(homeserverAddress)
guard var homeserverURL = URL(string: homeserverAddress) else {
@ -181,8 +176,6 @@ class AuthenticationService: NSObject {
throw AuthenticationError.invalidHomeserver
}
let state = AuthenticationState(flow: .login, homeserverAddress: homeserverAddress)
if let wellKnown = try? await wellKnown(for: homeserverURL),
let baseURL = URL(string: wellKnown.homeServer.baseUrl) {
homeserverURL = baseURL
@ -193,28 +186,28 @@ class AuthenticationService: NSObject {
let loginFlow = try await getLoginFlowResult(client: client)
self.client = client
self.state = state
return loginFlow
let state = AuthenticationState(flow: .login, homeserver: .init(address: loginFlow.homeserverAddress,
addressFromUser: homeserverAddress,
preferredLoginMode: loginFlow.loginMode,
loginModeSupportedTypes: loginFlow.supportedLoginTypes))
return (client, state)
}
/// Request the supported login flows for the corresponding session.
/// This method is used to get the flows for a server after a soft-logout.
/// - Parameter session: The MXSession where a soft-logout has occurred.
private func loginFlow(for session: MXSession) async throws -> LoginFlowResult {
private func loginFlow(for session: MXSession) async throws -> (AuthenticationRestClient, AuthenticationState) {
guard let client = session.matrixRestClient else {
MXLog.error("[AuthenticationService] loginFlow called on a session that doesn't have a matrixRestClient.")
throw AuthenticationError.missingMXRestClient
}
let state = AuthenticationState(flow: .login, homeserverAddress: client.homeserver)
let loginFlow = try await getLoginFlowResult(client: session.matrixRestClient)
self.client = client
self.state = state
return loginFlow
let state = AuthenticationState(flow: .login, homeserver: .init(address: loginFlow.homeserverAddress,
preferredLoginMode: loginFlow.loginMode,
loginModeSupportedTypes: loginFlow.supportedLoginTypes))
return (client, state)
}
private func getLoginFlowResult(client: MXRestClient) async throws -> LoginFlowResult {

View file

@ -30,6 +30,11 @@ struct AuthenticationState {
self.homeserver = Homeserver(address: homeserverAddress)
}
init(flow: AuthenticationFlow, homeserver: Homeserver) {
self.flow = flow
self.homeserver = homeserver
}
struct Homeserver {
/// The homeserver address as returned by the server.
var address: String

View file

@ -194,6 +194,7 @@ final class AuthenticationLoginCoordinator: Coordinator, Presentable {
@MainActor private func presentServerSelectionScreen() {
MXLog.debug("[AuthenticationCoordinator] showServerSelectionScreen")
let parameters = AuthenticationServerSelectionCoordinatorParameters(authenticationService: authenticationService,
flow: .login,
hasModalPresentation: true)
let coordinator = AuthenticationServerSelectionCoordinator(parameters: parameters)
coordinator.callback = { [weak self, weak coordinator] result in

View file

@ -204,6 +204,7 @@ final class AuthenticationRegistrationCoordinator: Coordinator, Presentable {
@MainActor private func presentServerSelectionScreen() {
MXLog.debug("[AuthenticationCoordinator] showServerSelectionScreen")
let parameters = AuthenticationServerSelectionCoordinatorParameters(authenticationService: authenticationService,
flow: .register,
hasModalPresentation: true)
let coordinator = AuthenticationServerSelectionCoordinator(parameters: parameters)
coordinator.callback = { [weak self, weak coordinator] result in

View file

@ -19,6 +19,8 @@ import CommonKit
struct AuthenticationServerSelectionCoordinatorParameters {
let authenticationService: AuthenticationService
/// Whether the server selection is for the login flow or registration flow.
let flow: AuthenticationFlow
/// Whether the screen is presented modally or within a navigation stack.
let hasModalPresentation: Bool
}
@ -111,14 +113,12 @@ final class AuthenticationServerSelectionCoordinator: Coordinator, Presentable {
/// Updates the login flow using the supplied homeserver address, or shows an error when this isn't possible.
@MainActor private func useHomeserver(_ homeserverAddress: String) {
startLoading()
authenticationService.reset()
let homeserverAddress = HomeserverAddress.sanitized(homeserverAddress)
Task {
do {
#warning("The screen should be configuration for .login too.")
try await authenticationService.startFlow(.register, for: homeserverAddress)
try await authenticationService.startFlow(parameters.flow, for: homeserverAddress)
stopLoading()
callback?(.updated)