mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
#40: Use the Rust AuthenticationService.
* Update SDK package to 1.0.12-alpha. * Use an app group for storage and stop stripping the http from the homeserver when configuring the service. * Rename access token to restore token. * Remove matrix.org server description inline with latest FTUE changes.
This commit is contained in:
@@ -16,18 +16,21 @@ protocol AuthenticationCoordinatorDelegate: AnyObject {
|
||||
}
|
||||
|
||||
class AuthenticationCoordinator: Coordinator, Presentable {
|
||||
private let authenticationService: AuthenticationServiceProtocol
|
||||
private let authenticationService: AuthenticationServiceProxyProtocol
|
||||
private let navigationRouter: NavigationRouter
|
||||
private var indicatorPresenter: UserIndicatorTypePresenterProtocol
|
||||
private var activityIndicator: UserIndicator?
|
||||
|
||||
private(set) var clientProxy: ClientProxyProtocol?
|
||||
var childCoordinators: [Coordinator] = []
|
||||
|
||||
weak var delegate: AuthenticationCoordinatorDelegate?
|
||||
|
||||
init(authenticationService: AuthenticationServiceProtocol,
|
||||
init(authenticationService: AuthenticationServiceProxyProtocol,
|
||||
navigationRouter: NavigationRouter) {
|
||||
self.authenticationService = authenticationService
|
||||
self.navigationRouter = navigationRouter
|
||||
|
||||
indicatorPresenter = UserIndicatorTypePresenter(presentingViewController: navigationRouter.toPresentable())
|
||||
}
|
||||
|
||||
func start() {
|
||||
@@ -47,7 +50,7 @@ class AuthenticationCoordinator: Coordinator, Presentable {
|
||||
guard let self = self else { return }
|
||||
switch action {
|
||||
case .login:
|
||||
self.showLoginScreen()
|
||||
Task { await self.startAuthentication() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,19 +62,54 @@ class AuthenticationCoordinator: Coordinator, Presentable {
|
||||
}
|
||||
}
|
||||
|
||||
private func startAuthentication() async {
|
||||
startLoading()
|
||||
|
||||
switch await authenticationService.configure(for: BuildSettings.defaultHomeserverAddress) {
|
||||
case .success:
|
||||
stopLoading()
|
||||
showLoginScreen()
|
||||
case .failure:
|
||||
stopLoading()
|
||||
showServerSelectionScreen()
|
||||
}
|
||||
}
|
||||
|
||||
private func showServerSelectionScreen() {
|
||||
let parameters = ServerSelectionCoordinatorParameters(authenticationService: authenticationService,
|
||||
hasModalPresentation: false)
|
||||
let coordinator = ServerSelectionCoordinator(parameters: parameters)
|
||||
|
||||
coordinator.callback = { [weak self] action in
|
||||
guard let self = self else { return }
|
||||
|
||||
switch action {
|
||||
case .updated:
|
||||
self.showLoginScreen()
|
||||
case .dismiss:
|
||||
MXLog.failure("[AuthenticationCoordinator] ServerSelectionScreen is requesting dismiss when part of a stack.")
|
||||
}
|
||||
}
|
||||
|
||||
coordinator.start()
|
||||
add(childCoordinator: coordinator)
|
||||
|
||||
navigationRouter.push(coordinator) { [weak self] in
|
||||
self?.remove(childCoordinator: coordinator)
|
||||
}
|
||||
}
|
||||
|
||||
private func showLoginScreen() {
|
||||
let parameters = LoginCoordinatorParameters(authenticationService: authenticationService,
|
||||
navigationRouter: navigationRouter)
|
||||
let coordinator = LoginCoordinator(parameters: parameters)
|
||||
|
||||
coordinator.callback = { [weak self, weak coordinator] action in
|
||||
guard let self = self, let coordinator = coordinator else { return }
|
||||
coordinator.callback = { [weak self] action in
|
||||
guard let self = self else { return }
|
||||
|
||||
switch action {
|
||||
case .signedIn(let userSession):
|
||||
self.delegate?.authenticationCoordinator(self, didLoginWithSession: userSession)
|
||||
self.remove(childCoordinator: coordinator)
|
||||
self.navigationRouter.dismissModule()
|
||||
case .continueWithOIDC:
|
||||
break
|
||||
}
|
||||
@@ -84,4 +122,14 @@ class AuthenticationCoordinator: Coordinator, Presentable {
|
||||
self?.remove(childCoordinator: coordinator)
|
||||
}
|
||||
}
|
||||
|
||||
/// Show a blocking activity indicator.
|
||||
private func startLoading() {
|
||||
activityIndicator = indicatorPresenter.present(.loading(label: ElementL10n.loading, isInteractionBlocking: true))
|
||||
}
|
||||
|
||||
/// Hide the currently displayed activity indicator.
|
||||
private func stopLoading() {
|
||||
activityIndicator = nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import SwiftUI
|
||||
|
||||
struct LoginCoordinatorParameters {
|
||||
/// The service used to authenticate the user.
|
||||
let authenticationService: AuthenticationServiceProtocol
|
||||
let authenticationService: AuthenticationServiceProxyProtocol
|
||||
/// The navigation router used to present the server selection screen.
|
||||
let navigationRouter: NavigationRouterType
|
||||
}
|
||||
@@ -46,7 +46,7 @@ final class LoginCoordinator: Coordinator, Presentable {
|
||||
}
|
||||
}
|
||||
|
||||
private var authenticationService: AuthenticationServiceProtocol { parameters.authenticationService }
|
||||
private var authenticationService: AuthenticationServiceProxyProtocol { parameters.authenticationService }
|
||||
private var navigationRouter: NavigationRouterType { parameters.navigationRouter }
|
||||
private var indicatorPresenter: UserIndicatorTypePresenterProtocol
|
||||
private var activityIndicator: UserIndicator?
|
||||
@@ -163,7 +163,7 @@ final class LoginCoordinator: Coordinator, Presentable {
|
||||
startLoading(isInteractionBlocking: false)
|
||||
|
||||
Task {
|
||||
switch await authenticationService.startLogin(for: homeserverDomain) {
|
||||
switch await authenticationService.configure(for: homeserverDomain) {
|
||||
case .success:
|
||||
updateViewModel()
|
||||
stopLoading()
|
||||
|
||||
@@ -20,20 +20,15 @@ import Foundation
|
||||
struct LoginHomeserver: Equatable {
|
||||
/// The homeserver string to be shown to the user.
|
||||
let address: String
|
||||
/// Whether or not the homeserver is matrix.org.
|
||||
let isMatrixDotOrg: Bool
|
||||
/// The types login supported by the homeserver.
|
||||
let loginMode: LoginMode
|
||||
}
|
||||
|
||||
extension LoginHomeserver {
|
||||
/// Temporary initialiser for use until the FFI has homeserver discovery etc.
|
||||
init(address: String) {
|
||||
var loginMode: LoginMode
|
||||
|
||||
/// Creates a new homeserver value.
|
||||
init(address: String, loginMode: LoginMode) {
|
||||
let address = Self.sanitized(address).components(separatedBy: "://").last ?? address
|
||||
|
||||
self.address = address
|
||||
isMatrixDotOrg = address == "matrix.org"
|
||||
loginMode = .password
|
||||
self.loginMode = loginMode
|
||||
}
|
||||
|
||||
/// Sanitizes a user entered homeserver address with the following rules
|
||||
@@ -59,30 +54,23 @@ extension LoginHomeserver {
|
||||
extension LoginHomeserver {
|
||||
/// A mock homeserver that is configured just like matrix.org.
|
||||
static var mockMatrixDotOrg: LoginHomeserver {
|
||||
LoginHomeserver(address: "matrix.org",
|
||||
isMatrixDotOrg: true,
|
||||
loginMode: .password)
|
||||
LoginHomeserver(address: "matrix.org", loginMode: .password)
|
||||
}
|
||||
|
||||
/// A mock homeserver that supports login and registration via a password but has no SSO providers.
|
||||
static var mockBasicServer: LoginHomeserver {
|
||||
LoginHomeserver(address: "example.com",
|
||||
isMatrixDotOrg: false,
|
||||
loginMode: .password)
|
||||
LoginHomeserver(address: "example.com", loginMode: .password)
|
||||
}
|
||||
|
||||
/// A mock homeserver that supports only supports authentication via a single SSO provider.
|
||||
static var mockOIDC: LoginHomeserver {
|
||||
LoginHomeserver(address: "company.com",
|
||||
isMatrixDotOrg: false,
|
||||
// swiftlint:disable:next force_unwrapping
|
||||
loginMode: .oidc(URL(string: "https://auth.company.com")!))
|
||||
// swiftlint:disable:next force_unwrapping
|
||||
let issuerURL = URL(string: "https://auth.company.com")!
|
||||
return LoginHomeserver(address: "company.com", loginMode: .oidc(issuerURL))
|
||||
}
|
||||
|
||||
/// A mock homeserver that only with no supported login flows.
|
||||
static var mockUnsupported: LoginHomeserver {
|
||||
LoginHomeserver(address: "server.net",
|
||||
isMatrixDotOrg: false,
|
||||
loginMode: .unsupported)
|
||||
LoginHomeserver(address: "server.net", loginMode: .unsupported)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,8 +72,7 @@ struct LoginScreen: View {
|
||||
|
||||
/// The sever information section that includes a button to select a different server.
|
||||
var serverInfo: some View {
|
||||
LoginServerInfoSection(address: context.viewState.homeserver.address,
|
||||
showMatrixDotOrgInfo: context.viewState.homeserver.isMatrixDotOrg) {
|
||||
LoginServerInfoSection(address: context.viewState.homeserver.address) {
|
||||
context.send(viewAction: .selectServer)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-14
@@ -23,8 +23,6 @@ struct LoginServerInfoSection: View {
|
||||
|
||||
/// The address shown for the server.
|
||||
let address: String
|
||||
/// Whether or not to show the matrix.org description.
|
||||
let showMatrixDotOrgInfo: Bool
|
||||
/// The action performed when tapping the edit button.
|
||||
let editAction: () -> Void
|
||||
|
||||
@@ -37,18 +35,9 @@ struct LoginServerInfoSection: View {
|
||||
.foregroundColor(.element.secondaryContent)
|
||||
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(address)
|
||||
.font(.element.body)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
|
||||
if showMatrixDotOrgInfo {
|
||||
Text(ElementL10n.authenticationServerInfoMatrixDescription)
|
||||
.font(.element.caption1)
|
||||
.foregroundColor(.element.tertiaryContent)
|
||||
.accessibilityIdentifier("serverDescriptionText")
|
||||
}
|
||||
}
|
||||
Text(address)
|
||||
.font(.element.body)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
|
||||
Spacer()
|
||||
|
||||
|
||||
+4
-4
@@ -18,7 +18,7 @@ import SwiftUI
|
||||
|
||||
struct ServerSelectionCoordinatorParameters {
|
||||
/// The service used to authenticate the user.
|
||||
let authenticationService: AuthenticationServiceProtocol
|
||||
let authenticationService: AuthenticationServiceProxyProtocol
|
||||
/// Whether the screen is presented modally or within a navigation stack.
|
||||
let hasModalPresentation: Bool
|
||||
}
|
||||
@@ -37,7 +37,7 @@ final class ServerSelectionCoordinator: Coordinator, Presentable {
|
||||
private let serverSelectionHostingController: UIViewController
|
||||
private var serverSelectionViewModel: ServerSelectionViewModelProtocol
|
||||
|
||||
private var authenticationService: AuthenticationServiceProtocol { parameters.authenticationService }
|
||||
private var authenticationService: AuthenticationServiceProxyProtocol { parameters.authenticationService }
|
||||
private var indicatorPresenter: UserIndicatorTypePresenterProtocol
|
||||
private var loadingIndicator: UserIndicator?
|
||||
|
||||
@@ -103,7 +103,7 @@ final class ServerSelectionCoordinator: Coordinator, Presentable {
|
||||
startLoading()
|
||||
|
||||
Task {
|
||||
switch await authenticationService.startLogin(for: homeserverAddress) {
|
||||
switch await authenticationService.configure(for: homeserverAddress) {
|
||||
case .success:
|
||||
callback?(.updated)
|
||||
stopLoading()
|
||||
@@ -117,7 +117,7 @@ final class ServerSelectionCoordinator: Coordinator, Presentable {
|
||||
/// Processes an error to either update the flow or display it to the user.
|
||||
private func handleError(_ error: AuthenticationServiceError) {
|
||||
switch error {
|
||||
case .invalidServer:
|
||||
case .invalidServer, .invalidHomeserverAddress:
|
||||
serverSelectionViewModel.displayError(.footerMessage(ElementL10n.loginErrorHomeserverNotFound))
|
||||
default:
|
||||
serverSelectionViewModel.displayError(.footerMessage(ElementL10n.unknownError))
|
||||
|
||||
Reference in New Issue
Block a user