Add an OAuthPresenterHook. (#5545)

* Add an OAuthPresenterHook.

* Update the enterprise submodule.
This commit is contained in:
Doug
2026-05-06 10:29:25 +01:00
committed by GitHub
parent 8b8b2bde0b
commit 345cbcf637
14 changed files with 54 additions and 4 deletions

View File

@@ -34,6 +34,11 @@ class AppHooks: AppHooksProtocol {
certificateValidatorHook = hook
}
private(set) var oAuthPresenterHook: OAuthPresenterHookProtocol = DefaultOAuthPresenterHook()
func registerOAuthPresenterHook(_ hook: OAuthPresenterHookProtocol) {
oAuthPresenterHook = hook
}
private(set) var roomScreenHook: RoomScreenHookProtocol = DefaultRoomScreenHook()
func registerRoomScreenHook(_ hook: RoomScreenHookProtocol) {
roomScreenHook = hook

View File

@@ -0,0 +1,19 @@
//
// Copyright 2025 Element Creations Ltd.
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
// Please see LICENSE files in the repository root for full details.
//
import Foundation
protocol OAuthPresenterHookProtocol {
func update(_ url: URL) -> URL
}
struct DefaultOAuthPresenterHook: OAuthPresenterHookProtocol {
func update(_ url: URL) -> URL {
url
}
}

View File

@@ -720,6 +720,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
keyBackupNeeded: false,
appMediator: appMediator,
appSettings: appSettings,
appHooks: appHooks,
userIndicatorController: ServiceLocator.shared.userIndicatorController)
let coordinator = SoftLogoutScreenCoordinator(parameters: parameters)
self.softLogoutCoordinator = coordinator

View File

@@ -425,6 +425,7 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
redirectURL: appSettings.oAuthRedirectURL,
presentationAnchor: presentationAnchor,
appMediator: appMediator,
appHooks: appHooks,
userIndicatorController: userIndicatorController)
oAuthPresenter = presenter

View File

@@ -692,6 +692,7 @@ class ChatsTabFlowCoordinator: FlowCoordinatorProtocol {
let parameters = EncryptionResetFlowCoordinatorParameters(userSession: userSession,
appMediator: flowParameters.appMediator,
appSettings: flowParameters.appSettings,
appHooks: flowParameters.appHooks,
userIndicatorController: flowParameters.userIndicatorController,
navigationStackCoordinator: sheetNavigationStackCoordinator,
windowManger: flowParameters.windowManager)

View File

@@ -21,6 +21,7 @@ struct EncryptionResetFlowCoordinatorParameters {
let userSession: UserSessionProtocol
let appMediator: AppMediatorProtocol
let appSettings: AppSettings
let appHooks: AppHooks
let userIndicatorController: UserIndicatorControllerProtocol
let navigationStackCoordinator: NavigationStackCoordinator
let windowManger: WindowManagerProtocol
@@ -30,6 +31,7 @@ class EncryptionResetFlowCoordinator: FlowCoordinatorProtocol {
private let userSession: UserSessionProtocol
private let appMediator: AppMediatorProtocol
private let appSettings: AppSettings
private let appHooks: AppHooks
private let userIndicatorController: UserIndicatorControllerProtocol
private let navigationStackCoordinator: NavigationStackCoordinator
@@ -66,6 +68,7 @@ class EncryptionResetFlowCoordinator: FlowCoordinatorProtocol {
userSession = parameters.userSession
appMediator = parameters.appMediator
appSettings = parameters.appSettings
appHooks = parameters.appHooks
userIndicatorController = parameters.userIndicatorController
navigationStackCoordinator = parameters.navigationStackCoordinator
windowManager = parameters.windowManger
@@ -162,7 +165,8 @@ class EncryptionResetFlowCoordinator: FlowCoordinatorProtocol {
accountSettingsPresenter = OAuthAccountSettingsPresenter(accountURL: url,
presentationAnchor: windowManager.mainWindow,
appMediator: appMediator,
appSettings: appSettings)
appSettings: appSettings,
appHooks: appHooks)
accountSettingsPresenter?.start()
}
}

View File

@@ -22,6 +22,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
private let analyticsService: AnalyticsService
private let appMediator: AppMediatorProtocol
private let appSettings: AppSettings
private let appHooks: AppHooks
private let notificationManager: NotificationManagerProtocol
private let userIndicatorController: UserIndicatorControllerProtocol
private let windowManager: WindowManagerProtocol
@@ -69,6 +70,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
analyticsService = flowParameters.analytics
appMediator = flowParameters.appMediator
appSettings = flowParameters.appSettings
appHooks = flowParameters.appHooks
notificationManager = flowParameters.notificationManager
userIndicatorController = flowParameters.userIndicatorController
windowManager = flowParameters.windowManager
@@ -319,6 +321,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
let coordinator = EncryptionResetFlowCoordinator(parameters: .init(userSession: userSession,
appMediator: appMediator,
appSettings: appSettings,
appHooks: appHooks,
userIndicatorController: userIndicatorController,
navigationStackCoordinator: resetNavigationStackCoordinator,
windowManger: windowManager))

View File

@@ -305,6 +305,7 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol {
presentationAnchor: flowParameters.windowManager.mainWindow,
appMediator: flowParameters.appMediator,
appSettings: flowParameters.appSettings,
appHooks: flowParameters.appHooks,
continuation: continuation)
accountSettingsPresenter?.start()
}

View File

@@ -19,6 +19,7 @@ class OAuthAuthenticationPresenter: NSObject {
private let redirectURL: URL
private let presentationAnchor: UIWindow
private let appMediator: AppMediatorProtocol
private let appHooks: AppHooks
private let userIndicatorController: UserIndicatorControllerProtocol
/// The data required to complete a request.
@@ -39,11 +40,13 @@ class OAuthAuthenticationPresenter: NSObject {
redirectURL: URL,
presentationAnchor: UIWindow,
appMediator: AppMediatorProtocol,
appHooks: AppHooks,
userIndicatorController: UserIndicatorControllerProtocol) {
self.authenticationService = authenticationService
self.redirectURL = redirectURL
self.presentationAnchor = presentationAnchor
self.appMediator = appMediator
self.appHooks = appHooks
self.userIndicatorController = userIndicatorController
super.init()
}
@@ -54,9 +57,9 @@ class OAuthAuthenticationPresenter: NSObject {
/// In particular if the authentication URL requires opening an external app, then the user may return
/// to the app without completing (or cancelling) the authentication.
func authenticate(using oAuthData: OAuthAuthorizationDataProxy) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
let authenticationURL = appHooks.oAuthPresenterHook.update(oAuthData.url)
let response = await withCheckedContinuation { continuation in
let authenticationURL = oAuthData.url
let session = ASWebAuthenticationSession(url: authenticationURL, callback: .oAuthRedirectURL(redirectURL)) { url, error in
MXLog.info("Handling callback from the session.")
continuation.resume(returning: Response(url: url, isExternal: false, error: error))

View File

@@ -15,6 +15,7 @@ struct SoftLogoutScreenCoordinatorParameters {
let keyBackupNeeded: Bool
let appMediator: AppMediatorProtocol
let appSettings: AppSettings
let appHooks: AppHooks
let userIndicatorController: UserIndicatorControllerProtocol
}
@@ -160,6 +161,7 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol {
redirectURL: parameters.appSettings.oAuthRedirectURL,
presentationAnchor: presentationAnchor,
appMediator: parameters.appMediator,
appHooks: parameters.appHooks,
userIndicatorController: parameters.userIndicatorController)
self.oAuthPresenter = presenter
switch await presenter.authenticate(using: oAuthData) {

View File

@@ -20,6 +20,7 @@ class OAuthAccountSettingsPresenter: NSObject {
private let redirectURL: URL
private let presentationAnchor: UIWindow
private let appMediator: AppMediatorProtocol
private let appHooks: AppHooks
typealias Continuation = AsyncStream<Result<Void, OAuthError>>.Continuation
private let continuation: Continuation?
@@ -28,11 +29,13 @@ class OAuthAccountSettingsPresenter: NSObject {
presentationAnchor: UIWindow,
appMediator: AppMediatorProtocol,
appSettings: AppSettings,
appHooks: AppHooks,
continuation: Continuation? = nil) {
self.accountURL = accountURL
redirectURL = appSettings.oAuthRedirectURL
self.presentationAnchor = presentationAnchor
self.appMediator = appMediator
self.appHooks = appHooks
self.continuation = continuation
super.init()
@@ -40,6 +43,8 @@ class OAuthAccountSettingsPresenter: NSObject {
/// Presents a web authentication session for the supplied data.
func start() {
let accountURL = appHooks.oAuthPresenterHook.update(accountURL)
let session = ASWebAuthenticationSession(url: accountURL, callback: .oAuthRedirectURL(redirectURL)) { [continuation] _, error in
guard let continuation else { return }

View File

@@ -737,6 +737,7 @@ class MockScreen: Identifiable {
let coordinator = EncryptionResetFlowCoordinator(parameters: .init(userSession: userSession,
appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings,
appHooks: AppHooks(),
userIndicatorController: userIndicatorController,
navigationStackCoordinator: navigationStackCoordinator,
windowManger: windowManager))