mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Use a Client in AuthenticationService now that the Rust one has been removed. (#2954)
* Replace Rust's Authentication service by building a Client. * Drop the Proxy from AuthenticationServiceProxy[Protocol]. * Make sure to call abortOIDCLogin. * Centralise common ClientBuilder code. * Update the SDK.
This commit is contained in:
@@ -449,12 +449,12 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
|
||||
private func startAuthentication() {
|
||||
let encryptionKeyProvider = EncryptionKeyProvider()
|
||||
let authenticationService = AuthenticationServiceProxy(userSessionStore: userSessionStore,
|
||||
encryptionKeyProvider: encryptionKeyProvider,
|
||||
appSettings: appSettings)
|
||||
let qrCodeLoginService = QRCodeLoginService(oidcConfiguration: appSettings.oidcConfiguration.rustValue,
|
||||
encryptionKeyProvider: encryptionKeyProvider,
|
||||
userSessionStore: userSessionStore)
|
||||
let authenticationService = AuthenticationService(userSessionStore: userSessionStore,
|
||||
encryptionKeyProvider: encryptionKeyProvider,
|
||||
appSettings: appSettings)
|
||||
let qrCodeLoginService = QRCodeLoginService(encryptionKeyProvider: encryptionKeyProvider,
|
||||
userSessionStore: userSessionStore,
|
||||
appSettings: appSettings)
|
||||
|
||||
authenticationFlowCoordinator = AuthenticationFlowCoordinator(authenticationService: authenticationService,
|
||||
qrCodeLoginService: qrCodeLoginService,
|
||||
@@ -480,9 +480,9 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
userDisplayName: userSession.clientProxy.userDisplayNamePublisher.value ?? "",
|
||||
deviceID: userSession.clientProxy.deviceID)
|
||||
|
||||
let authenticationService = AuthenticationServiceProxy(userSessionStore: userSessionStore,
|
||||
encryptionKeyProvider: EncryptionKeyProvider(),
|
||||
appSettings: appSettings)
|
||||
let authenticationService = AuthenticationService(userSessionStore: userSessionStore,
|
||||
encryptionKeyProvider: EncryptionKeyProvider(),
|
||||
appSettings: appSettings)
|
||||
_ = await authenticationService.configure(for: userSession.clientProxy.homeserver)
|
||||
|
||||
let parameters = SoftLogoutScreenCoordinatorParameters(authenticationService: authenticationService,
|
||||
|
||||
@@ -23,7 +23,7 @@ protocol AuthenticationFlowCoordinatorDelegate: AnyObject {
|
||||
}
|
||||
|
||||
class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
|
||||
private let authenticationService: AuthenticationServiceProxyProtocol
|
||||
private let authenticationService: AuthenticationServiceProtocol
|
||||
private let bugReportService: BugReportServiceProtocol
|
||||
private let navigationRootCoordinator: NavigationRootCoordinator
|
||||
private let navigationStackCoordinator: NavigationStackCoordinator
|
||||
@@ -42,7 +42,7 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
weak var delegate: AuthenticationFlowCoordinatorDelegate?
|
||||
|
||||
init(authenticationService: AuthenticationServiceProxyProtocol,
|
||||
init(authenticationService: AuthenticationServiceProtocol,
|
||||
qrCodeLoginService: QRCodeLoginServiceProtocol,
|
||||
bugReportService: BugReportServiceProtocol,
|
||||
navigationRootCoordinator: NavigationRootCoordinator,
|
||||
|
||||
@@ -80,347 +80,6 @@ open class AbortSendHandleSDKMock: MatrixRustSDK.AbortSendHandle {
|
||||
}
|
||||
}
|
||||
}
|
||||
open class AuthenticationServiceSDKMock: MatrixRustSDK.AuthenticationService {
|
||||
init() {
|
||||
super.init(noPointer: .init())
|
||||
}
|
||||
|
||||
public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) {
|
||||
fatalError("init(unsafeFromRawPointer:) has not been implemented")
|
||||
}
|
||||
|
||||
fileprivate var pointer: UnsafeMutableRawPointer!
|
||||
|
||||
//MARK: - configureHomeserver
|
||||
|
||||
open var configureHomeserverServerNameOrHomeserverUrlThrowableError: Error?
|
||||
var configureHomeserverServerNameOrHomeserverUrlUnderlyingCallsCount = 0
|
||||
open var configureHomeserverServerNameOrHomeserverUrlCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return configureHomeserverServerNameOrHomeserverUrlUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = configureHomeserverServerNameOrHomeserverUrlUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
configureHomeserverServerNameOrHomeserverUrlUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
configureHomeserverServerNameOrHomeserverUrlUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var configureHomeserverServerNameOrHomeserverUrlCalled: Bool {
|
||||
return configureHomeserverServerNameOrHomeserverUrlCallsCount > 0
|
||||
}
|
||||
open var configureHomeserverServerNameOrHomeserverUrlReceivedServerNameOrHomeserverUrl: String?
|
||||
open var configureHomeserverServerNameOrHomeserverUrlReceivedInvocations: [String] = []
|
||||
open var configureHomeserverServerNameOrHomeserverUrlClosure: ((String) async throws -> Void)?
|
||||
|
||||
open override func configureHomeserver(serverNameOrHomeserverUrl: String) async throws {
|
||||
if let error = configureHomeserverServerNameOrHomeserverUrlThrowableError {
|
||||
throw error
|
||||
}
|
||||
configureHomeserverServerNameOrHomeserverUrlCallsCount += 1
|
||||
configureHomeserverServerNameOrHomeserverUrlReceivedServerNameOrHomeserverUrl = serverNameOrHomeserverUrl
|
||||
DispatchQueue.main.async {
|
||||
self.configureHomeserverServerNameOrHomeserverUrlReceivedInvocations.append(serverNameOrHomeserverUrl)
|
||||
}
|
||||
try await configureHomeserverServerNameOrHomeserverUrlClosure?(serverNameOrHomeserverUrl)
|
||||
}
|
||||
|
||||
//MARK: - homeserverDetails
|
||||
|
||||
var homeserverDetailsUnderlyingCallsCount = 0
|
||||
open var homeserverDetailsCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return homeserverDetailsUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = homeserverDetailsUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
homeserverDetailsUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
homeserverDetailsUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var homeserverDetailsCalled: Bool {
|
||||
return homeserverDetailsCallsCount > 0
|
||||
}
|
||||
|
||||
var homeserverDetailsUnderlyingReturnValue: HomeserverLoginDetails?
|
||||
open var homeserverDetailsReturnValue: HomeserverLoginDetails? {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return homeserverDetailsUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: HomeserverLoginDetails?? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = homeserverDetailsUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
homeserverDetailsUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
homeserverDetailsUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var homeserverDetailsClosure: (() -> HomeserverLoginDetails?)?
|
||||
|
||||
open override func homeserverDetails() -> HomeserverLoginDetails? {
|
||||
homeserverDetailsCallsCount += 1
|
||||
if let homeserverDetailsClosure = homeserverDetailsClosure {
|
||||
return homeserverDetailsClosure()
|
||||
} else {
|
||||
return homeserverDetailsReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - login
|
||||
|
||||
open var loginUsernamePasswordInitialDeviceNameDeviceIdThrowableError: Error?
|
||||
var loginUsernamePasswordInitialDeviceNameDeviceIdUnderlyingCallsCount = 0
|
||||
open var loginUsernamePasswordInitialDeviceNameDeviceIdCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return loginUsernamePasswordInitialDeviceNameDeviceIdUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = loginUsernamePasswordInitialDeviceNameDeviceIdUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
loginUsernamePasswordInitialDeviceNameDeviceIdUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
loginUsernamePasswordInitialDeviceNameDeviceIdUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var loginUsernamePasswordInitialDeviceNameDeviceIdCalled: Bool {
|
||||
return loginUsernamePasswordInitialDeviceNameDeviceIdCallsCount > 0
|
||||
}
|
||||
open var loginUsernamePasswordInitialDeviceNameDeviceIdReceivedArguments: (username: String, password: String, initialDeviceName: String?, deviceId: String?)?
|
||||
open var loginUsernamePasswordInitialDeviceNameDeviceIdReceivedInvocations: [(username: String, password: String, initialDeviceName: String?, deviceId: String?)] = []
|
||||
|
||||
var loginUsernamePasswordInitialDeviceNameDeviceIdUnderlyingReturnValue: Client!
|
||||
open var loginUsernamePasswordInitialDeviceNameDeviceIdReturnValue: Client! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return loginUsernamePasswordInitialDeviceNameDeviceIdUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: Client? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = loginUsernamePasswordInitialDeviceNameDeviceIdUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
loginUsernamePasswordInitialDeviceNameDeviceIdUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
loginUsernamePasswordInitialDeviceNameDeviceIdUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var loginUsernamePasswordInitialDeviceNameDeviceIdClosure: ((String, String, String?, String?) async throws -> Client)?
|
||||
|
||||
open override func login(username: String, password: String, initialDeviceName: String?, deviceId: String?) async throws -> Client {
|
||||
if let error = loginUsernamePasswordInitialDeviceNameDeviceIdThrowableError {
|
||||
throw error
|
||||
}
|
||||
loginUsernamePasswordInitialDeviceNameDeviceIdCallsCount += 1
|
||||
loginUsernamePasswordInitialDeviceNameDeviceIdReceivedArguments = (username: username, password: password, initialDeviceName: initialDeviceName, deviceId: deviceId)
|
||||
DispatchQueue.main.async {
|
||||
self.loginUsernamePasswordInitialDeviceNameDeviceIdReceivedInvocations.append((username: username, password: password, initialDeviceName: initialDeviceName, deviceId: deviceId))
|
||||
}
|
||||
if let loginUsernamePasswordInitialDeviceNameDeviceIdClosure = loginUsernamePasswordInitialDeviceNameDeviceIdClosure {
|
||||
return try await loginUsernamePasswordInitialDeviceNameDeviceIdClosure(username, password, initialDeviceName, deviceId)
|
||||
} else {
|
||||
return loginUsernamePasswordInitialDeviceNameDeviceIdReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - loginWithOidcCallback
|
||||
|
||||
open var loginWithOidcCallbackAuthenticationDataCallbackUrlThrowableError: Error?
|
||||
var loginWithOidcCallbackAuthenticationDataCallbackUrlUnderlyingCallsCount = 0
|
||||
open var loginWithOidcCallbackAuthenticationDataCallbackUrlCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return loginWithOidcCallbackAuthenticationDataCallbackUrlUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = loginWithOidcCallbackAuthenticationDataCallbackUrlUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
loginWithOidcCallbackAuthenticationDataCallbackUrlUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
loginWithOidcCallbackAuthenticationDataCallbackUrlUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var loginWithOidcCallbackAuthenticationDataCallbackUrlCalled: Bool {
|
||||
return loginWithOidcCallbackAuthenticationDataCallbackUrlCallsCount > 0
|
||||
}
|
||||
open var loginWithOidcCallbackAuthenticationDataCallbackUrlReceivedArguments: (authenticationData: OidcAuthenticationData, callbackUrl: String)?
|
||||
open var loginWithOidcCallbackAuthenticationDataCallbackUrlReceivedInvocations: [(authenticationData: OidcAuthenticationData, callbackUrl: String)] = []
|
||||
|
||||
var loginWithOidcCallbackAuthenticationDataCallbackUrlUnderlyingReturnValue: Client!
|
||||
open var loginWithOidcCallbackAuthenticationDataCallbackUrlReturnValue: Client! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return loginWithOidcCallbackAuthenticationDataCallbackUrlUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: Client? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = loginWithOidcCallbackAuthenticationDataCallbackUrlUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
loginWithOidcCallbackAuthenticationDataCallbackUrlUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
loginWithOidcCallbackAuthenticationDataCallbackUrlUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var loginWithOidcCallbackAuthenticationDataCallbackUrlClosure: ((OidcAuthenticationData, String) async throws -> Client)?
|
||||
|
||||
open override func loginWithOidcCallback(authenticationData: OidcAuthenticationData, callbackUrl: String) async throws -> Client {
|
||||
if let error = loginWithOidcCallbackAuthenticationDataCallbackUrlThrowableError {
|
||||
throw error
|
||||
}
|
||||
loginWithOidcCallbackAuthenticationDataCallbackUrlCallsCount += 1
|
||||
loginWithOidcCallbackAuthenticationDataCallbackUrlReceivedArguments = (authenticationData: authenticationData, callbackUrl: callbackUrl)
|
||||
DispatchQueue.main.async {
|
||||
self.loginWithOidcCallbackAuthenticationDataCallbackUrlReceivedInvocations.append((authenticationData: authenticationData, callbackUrl: callbackUrl))
|
||||
}
|
||||
if let loginWithOidcCallbackAuthenticationDataCallbackUrlClosure = loginWithOidcCallbackAuthenticationDataCallbackUrlClosure {
|
||||
return try await loginWithOidcCallbackAuthenticationDataCallbackUrlClosure(authenticationData, callbackUrl)
|
||||
} else {
|
||||
return loginWithOidcCallbackAuthenticationDataCallbackUrlReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - urlForOidcLogin
|
||||
|
||||
open var urlForOidcLoginThrowableError: Error?
|
||||
var urlForOidcLoginUnderlyingCallsCount = 0
|
||||
open var urlForOidcLoginCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return urlForOidcLoginUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = urlForOidcLoginUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
urlForOidcLoginUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
urlForOidcLoginUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var urlForOidcLoginCalled: Bool {
|
||||
return urlForOidcLoginCallsCount > 0
|
||||
}
|
||||
|
||||
var urlForOidcLoginUnderlyingReturnValue: OidcAuthenticationData!
|
||||
open var urlForOidcLoginReturnValue: OidcAuthenticationData! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return urlForOidcLoginUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: OidcAuthenticationData? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = urlForOidcLoginUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
urlForOidcLoginUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
urlForOidcLoginUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var urlForOidcLoginClosure: (() async throws -> OidcAuthenticationData)?
|
||||
|
||||
open override func urlForOidcLogin() async throws -> OidcAuthenticationData {
|
||||
if let error = urlForOidcLoginThrowableError {
|
||||
throw error
|
||||
}
|
||||
urlForOidcLoginCallsCount += 1
|
||||
if let urlForOidcLoginClosure = urlForOidcLoginClosure {
|
||||
return try await urlForOidcLoginClosure()
|
||||
} else {
|
||||
return urlForOidcLoginReturnValue
|
||||
}
|
||||
}
|
||||
}
|
||||
open class ClientSDKMock: MatrixRustSDK.Client {
|
||||
init() {
|
||||
super.init(noPointer: .init())
|
||||
@@ -432,6 +91,48 @@ open class ClientSDKMock: MatrixRustSDK.Client {
|
||||
|
||||
fileprivate var pointer: UnsafeMutableRawPointer!
|
||||
|
||||
//MARK: - abortOidcLogin
|
||||
|
||||
var abortOidcLoginAuthorizationDataUnderlyingCallsCount = 0
|
||||
open var abortOidcLoginAuthorizationDataCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return abortOidcLoginAuthorizationDataUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = abortOidcLoginAuthorizationDataUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
abortOidcLoginAuthorizationDataUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
abortOidcLoginAuthorizationDataUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var abortOidcLoginAuthorizationDataCalled: Bool {
|
||||
return abortOidcLoginAuthorizationDataCallsCount > 0
|
||||
}
|
||||
open var abortOidcLoginAuthorizationDataReceivedAuthorizationData: OidcAuthorizationData?
|
||||
open var abortOidcLoginAuthorizationDataReceivedInvocations: [OidcAuthorizationData] = []
|
||||
open var abortOidcLoginAuthorizationDataClosure: ((OidcAuthorizationData) async -> Void)?
|
||||
|
||||
open override func abortOidcLogin(authorizationData: OidcAuthorizationData) async {
|
||||
abortOidcLoginAuthorizationDataCallsCount += 1
|
||||
abortOidcLoginAuthorizationDataReceivedAuthorizationData = authorizationData
|
||||
DispatchQueue.main.async {
|
||||
self.abortOidcLoginAuthorizationDataReceivedInvocations.append(authorizationData)
|
||||
}
|
||||
await abortOidcLoginAuthorizationDataClosure?(authorizationData)
|
||||
}
|
||||
|
||||
//MARK: - accountData
|
||||
|
||||
open var accountDataEventTypeThrowableError: Error?
|
||||
@@ -1879,6 +1580,71 @@ open class ClientSDKMock: MatrixRustSDK.Client {
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - homeserverLoginDetails
|
||||
|
||||
var homeserverLoginDetailsUnderlyingCallsCount = 0
|
||||
open var homeserverLoginDetailsCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return homeserverLoginDetailsUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = homeserverLoginDetailsUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
homeserverLoginDetailsUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
homeserverLoginDetailsUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var homeserverLoginDetailsCalled: Bool {
|
||||
return homeserverLoginDetailsCallsCount > 0
|
||||
}
|
||||
|
||||
var homeserverLoginDetailsUnderlyingReturnValue: HomeserverLoginDetails!
|
||||
open var homeserverLoginDetailsReturnValue: HomeserverLoginDetails! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return homeserverLoginDetailsUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: HomeserverLoginDetails? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = homeserverLoginDetailsUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
homeserverLoginDetailsUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
homeserverLoginDetailsUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var homeserverLoginDetailsClosure: (() async -> HomeserverLoginDetails)?
|
||||
|
||||
open override func homeserverLoginDetails() async -> HomeserverLoginDetails {
|
||||
homeserverLoginDetailsCallsCount += 1
|
||||
if let homeserverLoginDetailsClosure = homeserverLoginDetailsClosure {
|
||||
return await homeserverLoginDetailsClosure()
|
||||
} else {
|
||||
return homeserverLoginDetailsReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - ignoreUser
|
||||
|
||||
open var ignoreUserUserIdThrowableError: Error?
|
||||
@@ -2190,6 +1956,52 @@ open class ClientSDKMock: MatrixRustSDK.Client {
|
||||
try await loginUsernamePasswordInitialDeviceNameDeviceIdClosure?(username, password, initialDeviceName, deviceId)
|
||||
}
|
||||
|
||||
//MARK: - loginWithOidcCallback
|
||||
|
||||
open var loginWithOidcCallbackAuthorizationDataCallbackUrlThrowableError: Error?
|
||||
var loginWithOidcCallbackAuthorizationDataCallbackUrlUnderlyingCallsCount = 0
|
||||
open var loginWithOidcCallbackAuthorizationDataCallbackUrlCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return loginWithOidcCallbackAuthorizationDataCallbackUrlUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = loginWithOidcCallbackAuthorizationDataCallbackUrlUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
loginWithOidcCallbackAuthorizationDataCallbackUrlUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
loginWithOidcCallbackAuthorizationDataCallbackUrlUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var loginWithOidcCallbackAuthorizationDataCallbackUrlCalled: Bool {
|
||||
return loginWithOidcCallbackAuthorizationDataCallbackUrlCallsCount > 0
|
||||
}
|
||||
open var loginWithOidcCallbackAuthorizationDataCallbackUrlReceivedArguments: (authorizationData: OidcAuthorizationData, callbackUrl: String)?
|
||||
open var loginWithOidcCallbackAuthorizationDataCallbackUrlReceivedInvocations: [(authorizationData: OidcAuthorizationData, callbackUrl: String)] = []
|
||||
open var loginWithOidcCallbackAuthorizationDataCallbackUrlClosure: ((OidcAuthorizationData, String) async throws -> Void)?
|
||||
|
||||
open override func loginWithOidcCallback(authorizationData: OidcAuthorizationData, callbackUrl: String) async throws {
|
||||
if let error = loginWithOidcCallbackAuthorizationDataCallbackUrlThrowableError {
|
||||
throw error
|
||||
}
|
||||
loginWithOidcCallbackAuthorizationDataCallbackUrlCallsCount += 1
|
||||
loginWithOidcCallbackAuthorizationDataCallbackUrlReceivedArguments = (authorizationData: authorizationData, callbackUrl: callbackUrl)
|
||||
DispatchQueue.main.async {
|
||||
self.loginWithOidcCallbackAuthorizationDataCallbackUrlReceivedInvocations.append((authorizationData: authorizationData, callbackUrl: callbackUrl))
|
||||
}
|
||||
try await loginWithOidcCallbackAuthorizationDataCallbackUrlClosure?(authorizationData, callbackUrl)
|
||||
}
|
||||
|
||||
//MARK: - logout
|
||||
|
||||
open var logoutThrowableError: Error?
|
||||
@@ -3398,6 +3210,81 @@ open class ClientSDKMock: MatrixRustSDK.Client {
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - urlForOidcLogin
|
||||
|
||||
open var urlForOidcLoginOidcConfigurationThrowableError: Error?
|
||||
var urlForOidcLoginOidcConfigurationUnderlyingCallsCount = 0
|
||||
open var urlForOidcLoginOidcConfigurationCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return urlForOidcLoginOidcConfigurationUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = urlForOidcLoginOidcConfigurationUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
urlForOidcLoginOidcConfigurationUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
urlForOidcLoginOidcConfigurationUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var urlForOidcLoginOidcConfigurationCalled: Bool {
|
||||
return urlForOidcLoginOidcConfigurationCallsCount > 0
|
||||
}
|
||||
open var urlForOidcLoginOidcConfigurationReceivedOidcConfiguration: OidcConfiguration?
|
||||
open var urlForOidcLoginOidcConfigurationReceivedInvocations: [OidcConfiguration] = []
|
||||
|
||||
var urlForOidcLoginOidcConfigurationUnderlyingReturnValue: OidcAuthorizationData!
|
||||
open var urlForOidcLoginOidcConfigurationReturnValue: OidcAuthorizationData! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return urlForOidcLoginOidcConfigurationUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: OidcAuthorizationData? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = urlForOidcLoginOidcConfigurationUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
urlForOidcLoginOidcConfigurationUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
urlForOidcLoginOidcConfigurationUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var urlForOidcLoginOidcConfigurationClosure: ((OidcConfiguration) async throws -> OidcAuthorizationData)?
|
||||
|
||||
open override func urlForOidcLogin(oidcConfiguration: OidcConfiguration) async throws -> OidcAuthorizationData {
|
||||
if let error = urlForOidcLoginOidcConfigurationThrowableError {
|
||||
throw error
|
||||
}
|
||||
urlForOidcLoginOidcConfigurationCallsCount += 1
|
||||
urlForOidcLoginOidcConfigurationReceivedOidcConfiguration = oidcConfiguration
|
||||
DispatchQueue.main.async {
|
||||
self.urlForOidcLoginOidcConfigurationReceivedInvocations.append(oidcConfiguration)
|
||||
}
|
||||
if let urlForOidcLoginOidcConfigurationClosure = urlForOidcLoginOidcConfigurationClosure {
|
||||
return try await urlForOidcLoginOidcConfigurationClosure(oidcConfiguration)
|
||||
} else {
|
||||
return urlForOidcLoginOidcConfigurationReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - userId
|
||||
|
||||
open var userIdThrowableError: Error?
|
||||
@@ -4320,6 +4207,71 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - requiresSlidingSync
|
||||
|
||||
var requiresSlidingSyncUnderlyingCallsCount = 0
|
||||
open var requiresSlidingSyncCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return requiresSlidingSyncUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = requiresSlidingSyncUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
requiresSlidingSyncUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
requiresSlidingSyncUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var requiresSlidingSyncCalled: Bool {
|
||||
return requiresSlidingSyncCallsCount > 0
|
||||
}
|
||||
|
||||
var requiresSlidingSyncUnderlyingReturnValue: ClientBuilder!
|
||||
open var requiresSlidingSyncReturnValue: ClientBuilder! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return requiresSlidingSyncUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: ClientBuilder? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = requiresSlidingSyncUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
requiresSlidingSyncUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
requiresSlidingSyncUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var requiresSlidingSyncClosure: (() -> ClientBuilder)?
|
||||
|
||||
open override func requiresSlidingSync() -> ClientBuilder {
|
||||
requiresSlidingSyncCallsCount += 1
|
||||
if let requiresSlidingSyncClosure = requiresSlidingSyncClosure {
|
||||
return requiresSlidingSyncClosure()
|
||||
} else {
|
||||
return requiresSlidingSyncReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - serverName
|
||||
|
||||
var serverNameServerNameUnderlyingCallsCount = 0
|
||||
@@ -9294,82 +9246,6 @@ open class NotificationSettingsSDKMock: MatrixRustSDK.NotificationSettings {
|
||||
try await unmuteRoomRoomIdIsEncryptedIsOneToOneClosure?(roomId, isEncrypted, isOneToOne)
|
||||
}
|
||||
}
|
||||
open class OidcAuthenticationDataSDKMock: MatrixRustSDK.OidcAuthenticationData {
|
||||
init() {
|
||||
super.init(noPointer: .init())
|
||||
}
|
||||
|
||||
public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) {
|
||||
fatalError("init(unsafeFromRawPointer:) has not been implemented")
|
||||
}
|
||||
|
||||
fileprivate var pointer: UnsafeMutableRawPointer!
|
||||
|
||||
//MARK: - loginUrl
|
||||
|
||||
var loginUrlUnderlyingCallsCount = 0
|
||||
open var loginUrlCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return loginUrlUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = loginUrlUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
loginUrlUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
loginUrlUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var loginUrlCalled: Bool {
|
||||
return loginUrlCallsCount > 0
|
||||
}
|
||||
|
||||
var loginUrlUnderlyingReturnValue: String!
|
||||
open var loginUrlReturnValue: String! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return loginUrlUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: String? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = loginUrlUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
loginUrlUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
loginUrlUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var loginUrlClosure: (() -> String)?
|
||||
|
||||
open override func loginUrl() -> String {
|
||||
loginUrlCallsCount += 1
|
||||
if let loginUrlClosure = loginUrlClosure {
|
||||
return loginUrlClosure()
|
||||
} else {
|
||||
return loginUrlReturnValue
|
||||
}
|
||||
}
|
||||
}
|
||||
open class QrCodeDataSDKMock: MatrixRustSDK.QrCodeData {
|
||||
init() {
|
||||
super.init(noPointer: .init())
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// Copyright 2024 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
extension ClientBuilder {
|
||||
/// A helper method that applies the common builder modifiers needed for the app.
|
||||
static func baseBuilder(setupEncryption: Bool = true, httpProxy: String? = nil, slidingSyncProxy: URL? = nil, sessionDelegate: ClientSessionDelegate) -> ClientBuilder {
|
||||
var builder = ClientBuilder()
|
||||
.slidingSyncProxy(slidingSyncProxy: slidingSyncProxy?.absoluteString)
|
||||
.enableCrossProcessRefreshLock(processId: InfoPlistReader.main.bundleIdentifier, sessionDelegate: sessionDelegate)
|
||||
.userAgent(userAgent: UserAgentBuilder.makeASCIIUserAgent())
|
||||
.serverVersions(versions: ["v1.0", "v1.1", "v1.2", "v1.3", "v1.4", "v1.5"]) // FIXME: Quick and dirty fix for stopping version requests on startup https://github.com/matrix-org/matrix-rust-sdk/pull/1376
|
||||
|
||||
if setupEncryption {
|
||||
builder = builder
|
||||
.autoEnableCrossSigning(autoEnableCrossSigning: true)
|
||||
.backupDownloadStrategy(backupDownloadStrategy: .afterDecryptionFailure)
|
||||
.autoEnableBackups(autoEnableBackups: true)
|
||||
}
|
||||
|
||||
if let httpProxy {
|
||||
builder = builder.proxy(url: httpProxy)
|
||||
}
|
||||
|
||||
return builder
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import SwiftUI
|
||||
|
||||
struct LoginScreenCoordinatorParameters {
|
||||
/// The service used to authenticate the user.
|
||||
let authenticationService: AuthenticationServiceProxyProtocol
|
||||
let authenticationService: AuthenticationServiceProtocol
|
||||
|
||||
let analytics: AnalyticsService
|
||||
let userIndicatorController: UserIndicatorControllerProtocol
|
||||
@@ -38,7 +38,7 @@ final class LoginScreenCoordinator: CoordinatorProtocol {
|
||||
private let parameters: LoginScreenCoordinatorParameters
|
||||
private var viewModel: LoginScreenViewModelProtocol
|
||||
|
||||
private var authenticationService: AuthenticationServiceProxyProtocol { parameters.authenticationService }
|
||||
private var authenticationService: AuthenticationServiceProtocol { parameters.authenticationService }
|
||||
|
||||
private let actionsSubject: PassthroughSubject<LoginScreenCoordinatorAction, Never> = .init()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
@@ -19,21 +19,21 @@ import AuthenticationServices
|
||||
/// Presents a web authentication session for an OIDC request.
|
||||
@MainActor
|
||||
class OIDCAuthenticationPresenter: NSObject {
|
||||
private let authenticationService: AuthenticationServiceProxyProtocol
|
||||
private let authenticationService: AuthenticationServiceProtocol
|
||||
private let oidcRedirectURL: URL
|
||||
private let presentationAnchor: UIWindow
|
||||
|
||||
/// The data required to complete a request.
|
||||
struct Request {
|
||||
let session: ASWebAuthenticationSession
|
||||
let oidcData: OIDCAuthenticationDataProxy
|
||||
let oidcData: OIDCAuthorizationDataProxy
|
||||
let continuation: CheckedContinuation<Result<UserSessionProtocol, AuthenticationServiceError>, Never>
|
||||
}
|
||||
|
||||
/// The current request in progress. This is a single use value and will be moved on access.
|
||||
@Consumable private var request: Request?
|
||||
|
||||
init(authenticationService: AuthenticationServiceProxyProtocol, oidcRedirectURL: URL, presentationAnchor: UIWindow) {
|
||||
init(authenticationService: AuthenticationServiceProtocol, oidcRedirectURL: URL, presentationAnchor: UIWindow) {
|
||||
self.authenticationService = authenticationService
|
||||
self.oidcRedirectURL = oidcRedirectURL
|
||||
self.presentationAnchor = presentationAnchor
|
||||
@@ -41,7 +41,7 @@ class OIDCAuthenticationPresenter: NSObject {
|
||||
}
|
||||
|
||||
/// Presents a web authentication session for the supplied data.
|
||||
func authenticate(using oidcData: OIDCAuthenticationDataProxy) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
||||
func authenticate(using oidcData: OIDCAuthorizationDataProxy) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
||||
await withCheckedContinuation { continuation in
|
||||
let session = ASWebAuthenticationSession(url: oidcData.url,
|
||||
callbackURLScheme: oidcRedirectURL.scheme) { [weak self] url, error in
|
||||
@@ -107,7 +107,10 @@ class OIDCAuthenticationPresenter: NSObject {
|
||||
return
|
||||
}
|
||||
|
||||
request.continuation.resume(returning: .failure(error))
|
||||
Task {
|
||||
await authenticationService.abortOIDCLogin(data: request.oidcData)
|
||||
request.continuation.resume(returning: .failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import Combine
|
||||
import SwiftUI
|
||||
|
||||
struct ServerConfirmationScreenCoordinatorParameters {
|
||||
let authenticationService: AuthenticationServiceProxyProtocol
|
||||
let authenticationService: AuthenticationServiceProtocol
|
||||
let authenticationFlow: AuthenticationFlow
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ class ServerConfirmationScreenViewModel: ServerConfirmationScreenViewModelType,
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(authenticationService: AuthenticationServiceProxyProtocol, authenticationFlow: AuthenticationFlow) {
|
||||
init(authenticationService: AuthenticationServiceProtocol, authenticationFlow: AuthenticationFlow) {
|
||||
super.init(initialViewState: ServerConfirmationScreenViewState(homeserverAddress: authenticationService.homeserver.value.address,
|
||||
authenticationFlow: authenticationFlow))
|
||||
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ import SwiftUI
|
||||
|
||||
struct ServerSelectionScreenCoordinatorParameters {
|
||||
/// The service used to authenticate the user.
|
||||
let authenticationService: AuthenticationServiceProxyProtocol
|
||||
let authenticationService: AuthenticationServiceProtocol
|
||||
let userIndicatorController: UserIndicatorControllerProtocol
|
||||
/// Whether the screen is presented modally or within a navigation stack.
|
||||
let isModallyPresented: Bool
|
||||
@@ -34,7 +34,7 @@ final class ServerSelectionScreenCoordinator: CoordinatorProtocol {
|
||||
private let parameters: ServerSelectionScreenCoordinatorParameters
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
private var viewModel: ServerSelectionScreenViewModelProtocol
|
||||
private var authenticationService: AuthenticationServiceProxyProtocol { parameters.authenticationService }
|
||||
private var authenticationService: AuthenticationServiceProtocol { parameters.authenticationService }
|
||||
|
||||
private let actionsSubject: PassthroughSubject<ServerSelectionScreenCoordinatorAction, Never> = .init()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ import Combine
|
||||
import SwiftUI
|
||||
|
||||
struct SoftLogoutScreenCoordinatorParameters {
|
||||
let authenticationService: AuthenticationServiceProxyProtocol
|
||||
let authenticationService: AuthenticationServiceProtocol
|
||||
let credentials: SoftLogoutScreenCredentials
|
||||
let keyBackupNeeded: Bool
|
||||
let userIndicatorController: UserIndicatorControllerProtocol
|
||||
@@ -47,7 +47,7 @@ final class SoftLogoutScreenCoordinator: CoordinatorProtocol {
|
||||
private let actionsSubject: PassthroughSubject<SoftLogoutScreenCoordinatorResult, Never> = .init()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
private var authenticationService: AuthenticationServiceProxyProtocol { parameters.authenticationService }
|
||||
private var authenticationService: AuthenticationServiceProtocol { parameters.authenticationService }
|
||||
private var oidcPresenter: OIDCAuthenticationPresenter?
|
||||
|
||||
var actions: AnyPublisher<SoftLogoutScreenCoordinatorResult, Never> {
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ struct WaitlistScreenCoordinatorParameters {
|
||||
/// The credentials for the login.
|
||||
let credentials: WaitlistScreenCredentials
|
||||
/// The service used to authenticate the user.
|
||||
let authenticationService: AuthenticationServiceProxyProtocol
|
||||
let authenticationService: AuthenticationServiceProtocol
|
||||
/// The service locator for the screen.
|
||||
var userIndicatorController: UserIndicatorControllerProtocol = ServiceLocator.shared.userIndicatorController
|
||||
}
|
||||
|
||||
+45
-36
@@ -18,12 +18,14 @@ import Combine
|
||||
import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
||||
private let authenticationService: AuthenticationService
|
||||
private let userSessionStore: UserSessionStoreProtocol
|
||||
class AuthenticationService: AuthenticationServiceProtocol {
|
||||
private var client: Client?
|
||||
private let sessionDirectory: URL
|
||||
private let passphrase: String
|
||||
|
||||
private let userSessionStore: UserSessionStoreProtocol
|
||||
private let appSettings: AppSettings
|
||||
|
||||
private let homeserverSubject: CurrentValueSubject<LoginHomeserver, Never>
|
||||
var homeserver: CurrentValuePublisher<LoginHomeserver, Never> { homeserverSubject.asCurrentValuePublisher() }
|
||||
|
||||
@@ -31,19 +33,10 @@ class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
||||
sessionDirectory = .sessionsBaseDirectory.appending(component: UUID().uuidString)
|
||||
passphrase = encryptionKeyProvider.generateKey().base64EncodedString()
|
||||
self.userSessionStore = userSessionStore
|
||||
self.appSettings = appSettings
|
||||
|
||||
homeserverSubject = .init(LoginHomeserver(address: appSettings.defaultHomeserverAddress,
|
||||
loginMode: .unknown))
|
||||
|
||||
authenticationService = AuthenticationService(sessionPath: sessionDirectory.path(percentEncoded: false),
|
||||
passphrase: passphrase,
|
||||
userAgent: UserAgentBuilder.makeASCIIUserAgent(),
|
||||
additionalRootCertificates: [],
|
||||
proxy: appSettings.websiteURL.globalProxy,
|
||||
oidcConfiguration: appSettings.oidcConfiguration.rustValue,
|
||||
customSlidingSyncProxy: appSettings.slidingSyncProxyURL?.absoluteString,
|
||||
sessionDelegate: userSessionStore.clientSessionDelegate,
|
||||
crossProcessRefreshLockId: InfoPlistReader.main.bundleIdentifier)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
@@ -52,24 +45,24 @@ class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
||||
do {
|
||||
var homeserver = LoginHomeserver(address: homeserverAddress, loginMode: .unknown)
|
||||
|
||||
try await authenticationService.configureHomeserver(serverNameOrHomeserverUrl: homeserverAddress)
|
||||
let client = try await makeClientBuilder().serverNameOrHomeserverUrl(serverNameOrUrl: homeserverAddress).build()
|
||||
let loginDetails = await client.homeserverLoginDetails()
|
||||
|
||||
if let details = authenticationService.homeserverDetails() {
|
||||
if details.supportsOidcLogin() {
|
||||
homeserver.loginMode = .oidc
|
||||
} else if details.supportsPasswordLogin() {
|
||||
homeserver.loginMode = .password
|
||||
} else {
|
||||
homeserver.loginMode = .unsupported
|
||||
}
|
||||
if loginDetails.supportsOidcLogin() {
|
||||
homeserver.loginMode = .oidc
|
||||
} else if loginDetails.supportsPasswordLogin() {
|
||||
homeserver.loginMode = .password
|
||||
} else {
|
||||
homeserver.loginMode = .unsupported
|
||||
}
|
||||
|
||||
self.client = client
|
||||
homeserverSubject.send(homeserver)
|
||||
return .success(())
|
||||
} catch AuthenticationError.WellKnownDeserializationError(let error) {
|
||||
} catch ClientBuildError.WellKnownDeserializationError(let error) {
|
||||
MXLog.error("The user entered a server with an invalid well-known file: \(error)")
|
||||
return .failure(.invalidWellKnown(error))
|
||||
} catch AuthenticationError.SlidingSyncNotAvailable {
|
||||
} catch ClientBuildError.SlidingSyncNotAvailable {
|
||||
MXLog.info("User entered a homeserver that isn't configured for sliding sync.")
|
||||
return .failure(.slidingSyncNotAvailable)
|
||||
} catch {
|
||||
@@ -78,21 +71,29 @@ class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func urlForOIDCLogin() async -> Result<OIDCAuthenticationDataProxy, AuthenticationServiceError> {
|
||||
func urlForOIDCLogin() async -> Result<OIDCAuthorizationDataProxy, AuthenticationServiceError> {
|
||||
guard let client else { return .failure(.oidcError(.urlFailure)) }
|
||||
do {
|
||||
let oidcData = try await authenticationService.urlForOidcLogin()
|
||||
return .success(OIDCAuthenticationDataProxy(underlyingData: oidcData))
|
||||
let oidcData = try await client.urlForOidcLogin(oidcConfiguration: appSettings.oidcConfiguration.rustValue)
|
||||
return .success(OIDCAuthorizationDataProxy(underlyingData: oidcData))
|
||||
} catch {
|
||||
MXLog.error("Failed to get URL for OIDC login: \(error)")
|
||||
return .failure(.oidcError(.urlFailure))
|
||||
}
|
||||
}
|
||||
|
||||
func loginWithOIDCCallback(_ callbackURL: URL, data: OIDCAuthenticationDataProxy) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
||||
func abortOIDCLogin(data: OIDCAuthorizationDataProxy) async {
|
||||
guard let client else { return }
|
||||
MXLog.info("Aborting OIDC login.")
|
||||
await client.abortOidcLogin(authorizationData: data.underlyingData)
|
||||
}
|
||||
|
||||
func loginWithOIDCCallback(_ callbackURL: URL, data: OIDCAuthorizationDataProxy) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
||||
guard let client else { return .failure(.failedLoggingIn) }
|
||||
do {
|
||||
let client = try await authenticationService.loginWithOidcCallback(authenticationData: data.underlyingData, callbackUrl: callbackURL.absoluteString)
|
||||
try await client.loginWithOidcCallback(authorizationData: data.underlyingData, callbackUrl: callbackURL.absoluteString)
|
||||
return await userSession(for: client)
|
||||
} catch AuthenticationError.OidcCancelled {
|
||||
} catch OidcError.Cancelled {
|
||||
return .failure(.oidcError(.userCancellation))
|
||||
} catch {
|
||||
MXLog.error("Login with OIDC failed: \(error)")
|
||||
@@ -101,14 +102,11 @@ class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
||||
}
|
||||
|
||||
func login(username: String, password: String, initialDeviceName: String?, deviceID: String?) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
||||
guard let client else { return .failure(.failedLoggingIn) }
|
||||
do {
|
||||
let client = try await authenticationService.login(username: username,
|
||||
password: password,
|
||||
initialDeviceName: initialDeviceName,
|
||||
deviceId: deviceID)
|
||||
try await client.login(username: username, password: password, initialDeviceName: initialDeviceName, deviceId: deviceID)
|
||||
|
||||
let refreshToken = try? client.session().refreshToken
|
||||
|
||||
if refreshToken != nil {
|
||||
MXLog.warning("Refresh token found for a non oidc session, can't restore session, logging out")
|
||||
_ = try? await client.logout()
|
||||
@@ -118,7 +116,8 @@ class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
||||
return await userSession(for: client)
|
||||
} catch {
|
||||
MXLog.error("Failed logging in with error: \(error)")
|
||||
guard let error = error as? AuthenticationError else { return .failure(.failedLoggingIn) }
|
||||
// FIXME: How about we make a proper type in the FFI? 😅
|
||||
guard let error = error as? ClientError else { return .failure(.failedLoggingIn) }
|
||||
|
||||
if error.isElementWaitlist {
|
||||
return .failure(.isOnWaitlist)
|
||||
@@ -137,6 +136,16 @@ class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func makeClientBuilder() -> ClientBuilder {
|
||||
ClientBuilder
|
||||
.baseBuilder(httpProxy: appSettings.websiteURL.globalProxy,
|
||||
slidingSyncProxy: appSettings.slidingSyncProxyURL,
|
||||
sessionDelegate: userSessionStore.clientSessionDelegate)
|
||||
.sessionPath(path: sessionDirectory.path(percentEncoded: false))
|
||||
.passphrase(passphrase: passphrase)
|
||||
.requiresSlidingSync()
|
||||
}
|
||||
|
||||
private func userSession(for client: Client) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
||||
switch await userSessionStore.userSession(for: client, sessionDirectory: sessionDirectory, passphrase: passphrase) {
|
||||
case .success(let clientProxy):
|
||||
+10
-8
@@ -39,16 +39,18 @@ enum AuthenticationServiceError: Error {
|
||||
case sessionTokenRefreshNotSupported
|
||||
}
|
||||
|
||||
protocol AuthenticationServiceProxyProtocol {
|
||||
protocol AuthenticationServiceProtocol {
|
||||
/// The currently configured homeserver.
|
||||
var homeserver: CurrentValuePublisher<LoginHomeserver, Never> { get }
|
||||
|
||||
/// Sets up the service for login on the specified homeserver address.
|
||||
func configure(for homeserverAddress: String) async -> Result<Void, AuthenticationServiceError>
|
||||
/// Performs login using OIDC for the current homeserver.
|
||||
func urlForOIDCLogin() async -> Result<OIDCAuthenticationDataProxy, AuthenticationServiceError>
|
||||
/// Add docs.
|
||||
func loginWithOIDCCallback(_ callbackURL: URL, data: OIDCAuthenticationDataProxy) async -> Result<UserSessionProtocol, AuthenticationServiceError>
|
||||
func urlForOIDCLogin() async -> Result<OIDCAuthorizationDataProxy, AuthenticationServiceError>
|
||||
/// Asks the SDK to abort an ongoing OIDC login if we didn't get a callback to complete the request with.
|
||||
func abortOIDCLogin(data: OIDCAuthorizationDataProxy) async
|
||||
/// Completes an OIDC login that was started using ``urlForOIDCLogin``.
|
||||
func loginWithOIDCCallback(_ callbackURL: URL, data: OIDCAuthorizationDataProxy) async -> Result<UserSessionProtocol, AuthenticationServiceError>
|
||||
/// Performs a password login using the current homeserver.
|
||||
func login(username: String, password: String, initialDeviceName: String?, deviceID: String?) async -> Result<UserSessionProtocol, AuthenticationServiceError>
|
||||
}
|
||||
@@ -66,8 +68,8 @@ enum OIDCError: Error {
|
||||
case unknown
|
||||
}
|
||||
|
||||
struct OIDCAuthenticationDataProxy: Equatable {
|
||||
let underlyingData: OidcAuthenticationData
|
||||
struct OIDCAuthorizationDataProxy: Equatable {
|
||||
let underlyingData: OidcAuthorizationData
|
||||
|
||||
var url: URL {
|
||||
guard let url = URL(string: underlyingData.loginUrl()) else {
|
||||
@@ -77,8 +79,8 @@ struct OIDCAuthenticationDataProxy: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
extension OidcAuthenticationData: Equatable {
|
||||
public static func == (lhs: MatrixRustSDK.OidcAuthenticationData, rhs: MatrixRustSDK.OidcAuthenticationData) -> Bool {
|
||||
extension OidcAuthorizationData: Equatable {
|
||||
public static func == (lhs: MatrixRustSDK.OidcAuthorizationData, rhs: MatrixRustSDK.OidcAuthorizationData) -> Bool {
|
||||
lhs.loginUrl() == rhs.loginUrl()
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ import Combine
|
||||
import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
class MockAuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
||||
class MockAuthenticationServiceProxy: AuthenticationServiceProtocol {
|
||||
let validCredentials = (username: "alice", password: "12345678")
|
||||
|
||||
private let homeserverSubject: CurrentValueSubject<LoginHomeserver, Never>
|
||||
@@ -48,11 +48,13 @@ class MockAuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func urlForOIDCLogin() async -> Result<OIDCAuthenticationDataProxy, AuthenticationServiceError> {
|
||||
func urlForOIDCLogin() async -> Result<OIDCAuthorizationDataProxy, AuthenticationServiceError> {
|
||||
.failure(.oidcError(.notSupported))
|
||||
}
|
||||
|
||||
func loginWithOIDCCallback(_ callbackURL: URL, data: OIDCAuthenticationDataProxy) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
||||
func abortOIDCLogin(data: OIDCAuthorizationDataProxy) async { }
|
||||
|
||||
func loginWithOIDCCallback(_ callbackURL: URL, data: OIDCAuthorizationDataProxy) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
||||
.failure(.oidcError(.notSupported))
|
||||
}
|
||||
|
||||
|
||||
@@ -34,18 +34,6 @@ extension ClientError {
|
||||
|
||||
return first
|
||||
}
|
||||
}
|
||||
|
||||
extension AuthenticationError {
|
||||
var code: MatrixErrorCode {
|
||||
guard case let .Generic(message) = self else { return .unknown }
|
||||
|
||||
guard let first = MatrixErrorCode.allCases.first(where: { message.contains($0.rawValue) }) else {
|
||||
return .unknown
|
||||
}
|
||||
|
||||
return first
|
||||
}
|
||||
|
||||
/// Whether or not the error is related to the sliding sync proxy being full.
|
||||
///
|
||||
|
||||
@@ -20,21 +20,21 @@ import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
final class QRCodeLoginService: QRCodeLoginServiceProtocol {
|
||||
private let oidcConfiguration: OidcConfiguration
|
||||
private let sessionDirectory: URL
|
||||
private let passphrase: String
|
||||
private let userSessionStore: UserSessionStoreProtocol
|
||||
private let appSettings: AppSettings
|
||||
|
||||
private let qrLoginProgressSubject = PassthroughSubject<QrLoginProgress, Never>()
|
||||
var qrLoginProgressPublisher: AnyPublisher<QrLoginProgress, Never> {
|
||||
qrLoginProgressSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(oidcConfiguration: OidcConfiguration,
|
||||
encryptionKeyProvider: EncryptionKeyProviderProtocol,
|
||||
userSessionStore: UserSessionStoreProtocol) {
|
||||
self.oidcConfiguration = oidcConfiguration
|
||||
init(encryptionKeyProvider: EncryptionKeyProviderProtocol,
|
||||
userSessionStore: UserSessionStoreProtocol,
|
||||
appSettings: AppSettings) {
|
||||
self.userSessionStore = userSessionStore
|
||||
self.appSettings = appSettings
|
||||
sessionDirectory = .sessionsBaseDirectory.appending(component: UUID().uuidString)
|
||||
passphrase = encryptionKeyProvider.generateKey().base64EncodedString()
|
||||
}
|
||||
@@ -53,14 +53,14 @@ final class QRCodeLoginService: QRCodeLoginServiceProtocol {
|
||||
}
|
||||
|
||||
do {
|
||||
let client = try await ClientBuilder()
|
||||
let client = try await ClientBuilder
|
||||
.baseBuilder(httpProxy: appSettings.websiteURL.globalProxy,
|
||||
slidingSyncProxy: appSettings.slidingSyncProxyURL,
|
||||
sessionDelegate: userSessionStore.clientSessionDelegate)
|
||||
.sessionPath(path: sessionDirectory.path(percentEncoded: false))
|
||||
.passphrase(passphrase: passphrase)
|
||||
.userAgent(userAgent: UserAgentBuilder.makeASCIIUserAgent())
|
||||
.enableCrossProcessRefreshLock(processId: InfoPlistReader.main.bundleIdentifier,
|
||||
sessionDelegate: userSessionStore.clientSessionDelegate)
|
||||
.serverVersions(versions: ["v1.0", "v1.1", "v1.2", "v1.3", "v1.4", "v1.5"]) // FIXME: Quick and dirty fix for stopping version requests on startup https://github.com/matrix-org/matrix-rust-sdk/pull/1376
|
||||
.buildWithQrCode(qrCodeData: qrData, oidcConfiguration: oidcConfiguration, progressListener: listener)
|
||||
.requiresSlidingSync()
|
||||
.buildWithQrCode(qrCodeData: qrData, oidcConfiguration: appSettings.oidcConfiguration.rustValue, progressListener: listener)
|
||||
return await login(client: client)
|
||||
} catch let error as HumanQrLoginError {
|
||||
MXLog.error("QRCode login error: \(error)")
|
||||
|
||||
@@ -118,24 +118,16 @@ class UserSessionStore: UserSessionStoreProtocol {
|
||||
|
||||
let homeserverURL = credentials.restorationToken.session.homeserverUrl
|
||||
|
||||
var builder = ClientBuilder()
|
||||
let builder = ClientBuilder
|
||||
.baseBuilder(httpProxy: URL(string: homeserverURL)?.globalProxy,
|
||||
sessionDelegate: keychainController)
|
||||
.sessionPath(path: credentials.restorationToken.sessionDirectory.path(percentEncoded: false))
|
||||
.username(username: credentials.userID)
|
||||
.homeserverUrl(url: homeserverURL)
|
||||
.passphrase(passphrase: credentials.restorationToken.passphrase)
|
||||
.userAgent(userAgent: UserAgentBuilder.makeASCIIUserAgent())
|
||||
.enableCrossProcessRefreshLock(processId: InfoPlistReader.main.bundleIdentifier,
|
||||
sessionDelegate: keychainController)
|
||||
.serverVersions(versions: ["v1.0", "v1.1", "v1.2", "v1.3", "v1.4", "v1.5"]) // FIXME: Quick and dirty fix for stopping version requests on startup https://github.com/matrix-org/matrix-rust-sdk/pull/1376
|
||||
|
||||
if let homeserverURL = URL(string: homeserverURL),
|
||||
let proxy = homeserverURL.globalProxy {
|
||||
builder = builder.proxy(url: proxy)
|
||||
}
|
||||
let completeBuilder = builder
|
||||
|
||||
do {
|
||||
let client = try await completeBuilder.build()
|
||||
let client = try await builder.build()
|
||||
|
||||
try await client.restoreSession(session: credentials.restorationToken.session)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user