mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Adopt Rust's new sessionPath that replaces the basePath (#2903)
This commit is contained in:
@@ -7335,7 +7335,7 @@
|
|||||||
repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift";
|
repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift";
|
||||||
requirement = {
|
requirement = {
|
||||||
kind = exactVersion;
|
kind = exactVersion;
|
||||||
version = 1.0.9;
|
version = 1.0.10;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = {
|
701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = {
|
||||||
|
|||||||
@@ -139,8 +139,8 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/element-hq/matrix-rust-components-swift",
|
"location" : "https://github.com/element-hq/matrix-rust-components-swift",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "4f46a00c5a0ab3053f49f449b769237645f00b18",
|
"revision" : "0f9794c5cba9e0ad2084f0c3547eb1c45d0eefeb",
|
||||||
"version" : "1.0.9"
|
"version" : "1.0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -161,7 +161,8 @@ final class AppSettings {
|
|||||||
tosURI: acceptableUseURL,
|
tosURI: acceptableUseURL,
|
||||||
policyURI: privacyURL,
|
policyURI: privacyURL,
|
||||||
contacts: [supportEmailAddress],
|
contacts: [supportEmailAddress],
|
||||||
staticRegistrations: oidcStaticRegistrations.mapKeys { $0.absoluteString })
|
staticRegistrations: oidcStaticRegistrations.mapKeys { $0.absoluteString },
|
||||||
|
dynamicRegistrationsFile: .sessionsBaseDirectory.appending(path: "oidc/registrations.json"))
|
||||||
|
|
||||||
/// A dictionary of accounts that have performed an initial sync through their proxy.
|
/// A dictionary of accounts that have performed an initial sync through their proxy.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -3688,75 +3688,6 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - basePath
|
|
||||||
|
|
||||||
var basePathPathUnderlyingCallsCount = 0
|
|
||||||
open var basePathPathCallsCount: Int {
|
|
||||||
get {
|
|
||||||
if Thread.isMainThread {
|
|
||||||
return basePathPathUnderlyingCallsCount
|
|
||||||
} else {
|
|
||||||
var returnValue: Int? = nil
|
|
||||||
DispatchQueue.main.sync {
|
|
||||||
returnValue = basePathPathUnderlyingCallsCount
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
if Thread.isMainThread {
|
|
||||||
basePathPathUnderlyingCallsCount = newValue
|
|
||||||
} else {
|
|
||||||
DispatchQueue.main.sync {
|
|
||||||
basePathPathUnderlyingCallsCount = newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
open var basePathPathCalled: Bool {
|
|
||||||
return basePathPathCallsCount > 0
|
|
||||||
}
|
|
||||||
open var basePathPathReceivedPath: String?
|
|
||||||
open var basePathPathReceivedInvocations: [String] = []
|
|
||||||
|
|
||||||
var basePathPathUnderlyingReturnValue: ClientBuilder!
|
|
||||||
open var basePathPathReturnValue: ClientBuilder! {
|
|
||||||
get {
|
|
||||||
if Thread.isMainThread {
|
|
||||||
return basePathPathUnderlyingReturnValue
|
|
||||||
} else {
|
|
||||||
var returnValue: ClientBuilder? = nil
|
|
||||||
DispatchQueue.main.sync {
|
|
||||||
returnValue = basePathPathUnderlyingReturnValue
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
if Thread.isMainThread {
|
|
||||||
basePathPathUnderlyingReturnValue = newValue
|
|
||||||
} else {
|
|
||||||
DispatchQueue.main.sync {
|
|
||||||
basePathPathUnderlyingReturnValue = newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
open var basePathPathClosure: ((String) -> ClientBuilder)?
|
|
||||||
|
|
||||||
open override func basePath(path: String) -> ClientBuilder {
|
|
||||||
basePathPathCallsCount += 1
|
|
||||||
basePathPathReceivedPath = path
|
|
||||||
basePathPathReceivedInvocations.append(path)
|
|
||||||
if let basePathPathClosure = basePathPathClosure {
|
|
||||||
return basePathPathClosure(path)
|
|
||||||
} else {
|
|
||||||
return basePathPathReturnValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//MARK: - build
|
//MARK: - build
|
||||||
|
|
||||||
open var buildThrowableError: Error?
|
open var buildThrowableError: Error?
|
||||||
@@ -4512,6 +4443,75 @@ open class ClientBuilderSDKMock: MatrixRustSDK.ClientBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//MARK: - sessionPath
|
||||||
|
|
||||||
|
var sessionPathPathUnderlyingCallsCount = 0
|
||||||
|
open var sessionPathPathCallsCount: Int {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return sessionPathPathUnderlyingCallsCount
|
||||||
|
} else {
|
||||||
|
var returnValue: Int? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = sessionPathPathUnderlyingCallsCount
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
sessionPathPathUnderlyingCallsCount = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
sessionPathPathUnderlyingCallsCount = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
open var sessionPathPathCalled: Bool {
|
||||||
|
return sessionPathPathCallsCount > 0
|
||||||
|
}
|
||||||
|
open var sessionPathPathReceivedPath: String?
|
||||||
|
open var sessionPathPathReceivedInvocations: [String] = []
|
||||||
|
|
||||||
|
var sessionPathPathUnderlyingReturnValue: ClientBuilder!
|
||||||
|
open var sessionPathPathReturnValue: ClientBuilder! {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return sessionPathPathUnderlyingReturnValue
|
||||||
|
} else {
|
||||||
|
var returnValue: ClientBuilder? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = sessionPathPathUnderlyingReturnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
sessionPathPathUnderlyingReturnValue = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
sessionPathPathUnderlyingReturnValue = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
open var sessionPathPathClosure: ((String) -> ClientBuilder)?
|
||||||
|
|
||||||
|
open override func sessionPath(path: String) -> ClientBuilder {
|
||||||
|
sessionPathPathCallsCount += 1
|
||||||
|
sessionPathPathReceivedPath = path
|
||||||
|
sessionPathPathReceivedInvocations.append(path)
|
||||||
|
if let sessionPathPathClosure = sessionPathPathClosure {
|
||||||
|
return sessionPathPathClosure(path)
|
||||||
|
} else {
|
||||||
|
return sessionPathPathReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//MARK: - setSessionDelegate
|
//MARK: - setSessionDelegate
|
||||||
|
|
||||||
var setSessionDelegateSessionDelegateUnderlyingCallsCount = 0
|
var setSessionDelegateSessionDelegateUnderlyingCallsCount = 0
|
||||||
|
|||||||
@@ -21,19 +21,21 @@ import MatrixRustSDK
|
|||||||
class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
||||||
private let authenticationService: AuthenticationService
|
private let authenticationService: AuthenticationService
|
||||||
private let userSessionStore: UserSessionStoreProtocol
|
private let userSessionStore: UserSessionStoreProtocol
|
||||||
private let passphrase: String?
|
private let sessionDirectory: URL
|
||||||
|
private let passphrase: String
|
||||||
|
|
||||||
private let homeserverSubject: CurrentValueSubject<LoginHomeserver, Never>
|
private let homeserverSubject: CurrentValueSubject<LoginHomeserver, Never>
|
||||||
var homeserver: CurrentValuePublisher<LoginHomeserver, Never> { homeserverSubject.asCurrentValuePublisher() }
|
var homeserver: CurrentValuePublisher<LoginHomeserver, Never> { homeserverSubject.asCurrentValuePublisher() }
|
||||||
|
|
||||||
init(userSessionStore: UserSessionStoreProtocol, encryptionKeyProvider: EncryptionKeyProviderProtocol, appSettings: AppSettings) {
|
init(userSessionStore: UserSessionStoreProtocol, encryptionKeyProvider: EncryptionKeyProviderProtocol, appSettings: AppSettings) {
|
||||||
|
sessionDirectory = .sessionsBaseDirectory.appending(component: UUID().uuidString)
|
||||||
passphrase = encryptionKeyProvider.generateKey().base64EncodedString()
|
passphrase = encryptionKeyProvider.generateKey().base64EncodedString()
|
||||||
self.userSessionStore = userSessionStore
|
self.userSessionStore = userSessionStore
|
||||||
|
|
||||||
homeserverSubject = .init(LoginHomeserver(address: appSettings.defaultHomeserverAddress,
|
homeserverSubject = .init(LoginHomeserver(address: appSettings.defaultHomeserverAddress,
|
||||||
loginMode: .unknown))
|
loginMode: .unknown))
|
||||||
|
|
||||||
authenticationService = AuthenticationService(basePath: userSessionStore.baseDirectory.path,
|
authenticationService = AuthenticationService(sessionPath: sessionDirectory.path(percentEncoded: false),
|
||||||
passphrase: passphrase,
|
passphrase: passphrase,
|
||||||
userAgent: UserAgentBuilder.makeASCIIUserAgent(),
|
userAgent: UserAgentBuilder.makeASCIIUserAgent(),
|
||||||
additionalRootCertificates: [],
|
additionalRootCertificates: [],
|
||||||
@@ -136,7 +138,7 @@ class AuthenticationServiceProxy: AuthenticationServiceProxyProtocol {
|
|||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
private func userSession(for client: Client) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
private func userSession(for client: Client) async -> Result<UserSessionProtocol, AuthenticationServiceError> {
|
||||||
switch await userSessionStore.userSession(for: client, passphrase: passphrase) {
|
switch await userSessionStore.userSession(for: client, sessionDirectory: sessionDirectory, passphrase: passphrase) {
|
||||||
case .success(let clientProxy):
|
case .success(let clientProxy):
|
||||||
return .success(clientProxy)
|
return .success(clientProxy)
|
||||||
case .failure:
|
case .failure:
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ struct OIDCConfigurationProxy {
|
|||||||
let policyURI: URL
|
let policyURI: URL
|
||||||
let contacts: [String]
|
let contacts: [String]
|
||||||
let staticRegistrations: [String: String]
|
let staticRegistrations: [String: String]
|
||||||
|
let dynamicRegistrationsFile: URL
|
||||||
}
|
}
|
||||||
|
|
||||||
#if canImport(MatrixRustSDK)
|
#if canImport(MatrixRustSDK)
|
||||||
@@ -39,7 +40,8 @@ extension OIDCConfigurationProxy {
|
|||||||
tosUri: tosURI.absoluteString,
|
tosUri: tosURI.absoluteString,
|
||||||
policyUri: policyURI.absoluteString,
|
policyUri: policyURI.absoluteString,
|
||||||
contacts: contacts,
|
contacts: contacts,
|
||||||
staticRegistrations: staticRegistrations)
|
staticRegistrations: staticRegistrations,
|
||||||
|
dynamicRegistrationsFile: dynamicRegistrationsFile.path(percentEncoded: false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ class KeychainController: KeychainControllerProtocol {
|
|||||||
fatalError("Something has gone mega wrong, all bets are off.")
|
fatalError("Something has gone mega wrong, all bets are off.")
|
||||||
}
|
}
|
||||||
let restorationToken = RestorationToken(session: session,
|
let restorationToken = RestorationToken(session: session,
|
||||||
|
sessionDirectory: oldToken.sessionDirectory,
|
||||||
passphrase: oldToken.passphrase,
|
passphrase: oldToken.passphrase,
|
||||||
pusherNotificationClientIdentifier: oldToken.pusherNotificationClientIdentifier)
|
pusherNotificationClientIdentifier: oldToken.pusherNotificationClientIdentifier)
|
||||||
setRestorationToken(restorationToken, forUsername: session.userId)
|
setRestorationToken(restorationToken, forUsername: session.userId)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import MatrixRustSDK
|
|||||||
|
|
||||||
final class QRCodeLoginService: QRCodeLoginServiceProtocol {
|
final class QRCodeLoginService: QRCodeLoginServiceProtocol {
|
||||||
private let oidcConfiguration: OidcConfiguration
|
private let oidcConfiguration: OidcConfiguration
|
||||||
|
private let sessionDirectory: URL
|
||||||
private let passphrase: String
|
private let passphrase: String
|
||||||
private let userSessionStore: UserSessionStoreProtocol
|
private let userSessionStore: UserSessionStoreProtocol
|
||||||
|
|
||||||
@@ -34,6 +35,7 @@ final class QRCodeLoginService: QRCodeLoginServiceProtocol {
|
|||||||
userSessionStore: UserSessionStoreProtocol) {
|
userSessionStore: UserSessionStoreProtocol) {
|
||||||
self.oidcConfiguration = oidcConfiguration
|
self.oidcConfiguration = oidcConfiguration
|
||||||
self.userSessionStore = userSessionStore
|
self.userSessionStore = userSessionStore
|
||||||
|
sessionDirectory = .sessionsBaseDirectory.appending(component: UUID().uuidString)
|
||||||
passphrase = encryptionKeyProvider.generateKey().base64EncodedString()
|
passphrase = encryptionKeyProvider.generateKey().base64EncodedString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +54,7 @@ final class QRCodeLoginService: QRCodeLoginServiceProtocol {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
let client = try await ClientBuilder()
|
let client = try await ClientBuilder()
|
||||||
.basePath(path: userSessionStore.baseDirectory.path(percentEncoded: false))
|
.sessionPath(path: sessionDirectory.path(percentEncoded: false))
|
||||||
.passphrase(passphrase: passphrase)
|
.passphrase(passphrase: passphrase)
|
||||||
.userAgent(userAgent: UserAgentBuilder.makeASCIIUserAgent())
|
.userAgent(userAgent: UserAgentBuilder.makeASCIIUserAgent())
|
||||||
.enableCrossProcessRefreshLock(processId: InfoPlistReader.main.bundleIdentifier,
|
.enableCrossProcessRefreshLock(processId: InfoPlistReader.main.bundleIdentifier,
|
||||||
@@ -70,7 +72,7 @@ final class QRCodeLoginService: QRCodeLoginServiceProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func login(client: Client) async -> Result<UserSessionProtocol, QRCodeLoginServiceError> {
|
private func login(client: Client) async -> Result<UserSessionProtocol, QRCodeLoginServiceError> {
|
||||||
switch await userSessionStore.userSession(for: client, passphrase: passphrase) {
|
switch await userSessionStore.userSession(for: client, sessionDirectory: sessionDirectory, passphrase: passphrase) {
|
||||||
case .success(let session):
|
case .success(let session):
|
||||||
return .success(session)
|
return .success(session)
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
|
|||||||
@@ -17,12 +17,27 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import MatrixRustSDK
|
import MatrixRustSDK
|
||||||
|
|
||||||
struct RestorationToken: Codable, Equatable {
|
struct RestorationToken: Equatable {
|
||||||
let session: MatrixRustSDK.Session
|
let session: MatrixRustSDK.Session
|
||||||
|
let sessionDirectory: URL
|
||||||
let passphrase: String?
|
let passphrase: String?
|
||||||
let pusherNotificationClientIdentifier: String?
|
let pusherNotificationClientIdentifier: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension RestorationToken: Codable {
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
let session = try container.decode(MatrixRustSDK.Session.self, forKey: .session)
|
||||||
|
let sessionDirectory = try container.decodeIfPresent(URL.self, forKey: .sessionDirectory)
|
||||||
|
|
||||||
|
self = try .init(session: session,
|
||||||
|
sessionDirectory: sessionDirectory ?? .legacySessionDirectory(for: session.userId),
|
||||||
|
passphrase: container.decodeIfPresent(String.self, forKey: .passphrase),
|
||||||
|
pusherNotificationClientIdentifier: container.decodeIfPresent(String.self, forKey: .pusherNotificationClientIdentifier))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension MatrixRustSDK.Session: Codable {
|
extension MatrixRustSDK.Session: Codable {
|
||||||
public init(from decoder: Decoder) throws {
|
public init(from decoder: Decoder) throws {
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
@@ -50,3 +65,18 @@ extension MatrixRustSDK.Session: Codable {
|
|||||||
case accessToken, refreshToken, userId, deviceId, homeserverUrl, oidcData, slidingSyncProxy
|
case accessToken, refreshToken, userId, deviceId, homeserverUrl, oidcData, slidingSyncProxy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Migrations
|
||||||
|
|
||||||
|
private extension URL {
|
||||||
|
/// Gets the store directory of a legacy session that hasn't been migrated to the new token format.
|
||||||
|
///
|
||||||
|
/// This should only be used to fill in the missing value when restoring a token as older versions of
|
||||||
|
/// the SDK set the session directory for us, based on the user's ID. Newer sessions now use a UUID,
|
||||||
|
/// which is generated app side during authentication.
|
||||||
|
static func legacySessionDirectory(for userID: String) -> URL {
|
||||||
|
// Rust sanitises the user ID replacing invalid characters with an _
|
||||||
|
let sanitisedUserID = userID.replacingOccurrences(of: ":", with: "_")
|
||||||
|
return .sessionsBaseDirectory.appendingPathComponent(sanitisedUserID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,21 +27,16 @@ class UserSessionStore: UserSessionStoreProtocol {
|
|||||||
/// All the user IDs managed by the store.
|
/// All the user IDs managed by the store.
|
||||||
var userIDs: [String] { keychainController.restorationTokens().map(\.userID) }
|
var userIDs: [String] { keychainController.restorationTokens().map(\.userID) }
|
||||||
|
|
||||||
/// The base directory where all session data is stored.
|
|
||||||
let baseDirectory: URL
|
|
||||||
|
|
||||||
var clientSessionDelegate: ClientSessionDelegate { keychainController }
|
var clientSessionDelegate: ClientSessionDelegate { keychainController }
|
||||||
|
|
||||||
init(keychainController: KeychainControllerProtocol) {
|
init(keychainController: KeychainControllerProtocol) {
|
||||||
self.keychainController = keychainController
|
self.keychainController = keychainController
|
||||||
baseDirectory = .sessionsBaseDirectory
|
|
||||||
MXLog.info("Setup base directory at: \(baseDirectory)")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes all data stored in the shared container and keychain
|
/// Deletes all data stored in the shared container and keychain
|
||||||
func reset() {
|
func reset() {
|
||||||
MXLog.warning("Resetting the UserSessionStore. All accounts will be affected.")
|
MXLog.warning("Resetting the UserSessionStore. All accounts will be affected.")
|
||||||
try? FileManager.default.removeItem(at: baseDirectory)
|
try? FileManager.default.removeItem(at: .sessionsBaseDirectory)
|
||||||
keychainController.removeAllRestorationTokens()
|
keychainController.removeAllRestorationTokens()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,20 +54,21 @@ class UserSessionStore: UserSessionStoreProtocol {
|
|||||||
MXLog.error("Failed restoring login with error: \(error)")
|
MXLog.error("Failed restoring login with error: \(error)")
|
||||||
|
|
||||||
// On any restoration failure reset the token and restart
|
// On any restoration failure reset the token and restart
|
||||||
keychainController.removeAllRestorationTokens()
|
keychainController.removeRestorationTokenForUsername(credentials.userID)
|
||||||
deleteSessionDirectory(for: credentials.userID)
|
deleteSessionDirectory(for: credentials)
|
||||||
|
|
||||||
return .failure(error)
|
return .failure(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func userSession(for client: Client, passphrase: String?) async -> Result<UserSessionProtocol, UserSessionStoreError> {
|
func userSession(for client: Client, sessionDirectory: URL, passphrase: String?) async -> Result<UserSessionProtocol, UserSessionStoreError> {
|
||||||
do {
|
do {
|
||||||
let session = try client.session()
|
let session = try client.session()
|
||||||
let userID = try client.userId()
|
let userID = try client.userId()
|
||||||
let clientProxy = await setupProxyForClient(client)
|
let clientProxy = await setupProxyForClient(client)
|
||||||
|
|
||||||
keychainController.setRestorationToken(RestorationToken(session: session,
|
keychainController.setRestorationToken(RestorationToken(session: session,
|
||||||
|
sessionDirectory: sessionDirectory,
|
||||||
passphrase: passphrase,
|
passphrase: passphrase,
|
||||||
pusherNotificationClientIdentifier: clientProxy.pusherNotificationClientIdentifier),
|
pusherNotificationClientIdentifier: clientProxy.pusherNotificationClientIdentifier),
|
||||||
forUsername: userID)
|
forUsername: userID)
|
||||||
@@ -86,12 +82,20 @@ class UserSessionStore: UserSessionStoreProtocol {
|
|||||||
|
|
||||||
func logout(userSession: UserSessionProtocol) {
|
func logout(userSession: UserSessionProtocol) {
|
||||||
let userID = userSession.clientProxy.userID
|
let userID = userSession.clientProxy.userID
|
||||||
|
let credentials = keychainController.restorationTokens().first { $0.userID == userID }
|
||||||
keychainController.removeRestorationTokenForUsername(userID)
|
keychainController.removeRestorationTokenForUsername(userID)
|
||||||
deleteSessionDirectory(for: userID)
|
|
||||||
|
if let credentials {
|
||||||
|
deleteSessionDirectory(for: credentials)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearCache(for userID: String) {
|
func clearCache(for userID: String) {
|
||||||
deleteCaches(for: userID)
|
guard let credentials = keychainController.restorationTokens().first(where: { $0.userID == userID }) else {
|
||||||
|
MXLog.error("Failed to clearing caches: Credentials missing")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
deleteCaches(for: credentials)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
@@ -115,7 +119,7 @@ class UserSessionStore: UserSessionStoreProtocol {
|
|||||||
let homeserverURL = credentials.restorationToken.session.homeserverUrl
|
let homeserverURL = credentials.restorationToken.session.homeserverUrl
|
||||||
|
|
||||||
var builder = ClientBuilder()
|
var builder = ClientBuilder()
|
||||||
.basePath(path: baseDirectory.path)
|
.sessionPath(path: credentials.restorationToken.sessionDirectory.path(percentEncoded: false))
|
||||||
.username(username: credentials.userID)
|
.username(username: credentials.userID)
|
||||||
.homeserverUrl(url: homeserverURL)
|
.homeserverUrl(url: homeserverURL)
|
||||||
.passphrase(passphrase: credentials.restorationToken.passphrase)
|
.passphrase(passphrase: credentials.restorationToken.passphrase)
|
||||||
@@ -148,28 +152,22 @@ class UserSessionStore: UserSessionStoreProtocol {
|
|||||||
networkMonitor: ServiceLocator.shared.networkMonitor)
|
networkMonitor: ServiceLocator.shared.networkMonitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func deleteSessionDirectory(for userID: String) {
|
private func deleteSessionDirectory(for credentials: KeychainCredentials) {
|
||||||
do {
|
do {
|
||||||
try FileManager.default.removeItem(at: basePath(for: userID))
|
try FileManager.default.removeItem(at: credentials.restorationToken.sessionDirectory)
|
||||||
} catch {
|
} catch {
|
||||||
MXLog.failure("Failed deleting the session data: \(error)")
|
MXLog.failure("Failed deleting the session data: \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func deleteCaches(for userID: String) {
|
private func deleteCaches(for credentials: KeychainCredentials) {
|
||||||
do {
|
do {
|
||||||
for url in try FileManager.default.contentsOfDirectory(at: basePath(for: userID), includingPropertiesForKeys: nil) where url.path.contains(matrixSDKStateKey) {
|
let sessionDirectoryContents = try FileManager.default.contentsOfDirectory(at: credentials.restorationToken.sessionDirectory, includingPropertiesForKeys: nil)
|
||||||
|
for url in sessionDirectoryContents where url.path.contains(matrixSDKStateKey) {
|
||||||
try FileManager.default.removeItem(at: url)
|
try FileManager.default.removeItem(at: url)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
MXLog.failure("Failed deleting the session data: \(error)")
|
MXLog.failure("Failed clearing caches: \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#warning("We should move this and the caches cleanup to the rust side")
|
|
||||||
private func basePath(for userID: String) -> URL {
|
|
||||||
// Rust sanitises the user ID replacing invalid characters with an _
|
|
||||||
let sanitisedUserID = userID.replacingOccurrences(of: ":", with: "_")
|
|
||||||
return baseDirectory.appendingPathComponent(sanitisedUserID)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,9 +33,6 @@ protocol UserSessionStoreProtocol {
|
|||||||
/// All the user IDs managed by the store.
|
/// All the user IDs managed by the store.
|
||||||
var userIDs: [String] { get }
|
var userIDs: [String] { get }
|
||||||
|
|
||||||
/// Returns the location to store user data for a particular username.
|
|
||||||
var baseDirectory: URL { get }
|
|
||||||
|
|
||||||
/// Returns the delegate that should handle any changes to a `Client`'s `Session`.
|
/// Returns the delegate that should handle any changes to a `Client`'s `Session`.
|
||||||
var clientSessionDelegate: ClientSessionDelegate { get }
|
var clientSessionDelegate: ClientSessionDelegate { get }
|
||||||
|
|
||||||
@@ -43,7 +40,7 @@ protocol UserSessionStoreProtocol {
|
|||||||
func restoreUserSession() async -> Result<UserSessionProtocol, UserSessionStoreError>
|
func restoreUserSession() async -> Result<UserSessionProtocol, UserSessionStoreError>
|
||||||
|
|
||||||
/// Creates a user session for a new client from the SDK along with the passphrase used for the data stores.
|
/// Creates a user session for a new client from the SDK along with the passphrase used for the data stores.
|
||||||
func userSession(for client: Client, passphrase: String?) async -> Result<UserSessionProtocol, UserSessionStoreError>
|
func userSession(for client: Client, sessionDirectory: URL, passphrase: String?) async -> Result<UserSessionProtocol, UserSessionStoreError>
|
||||||
|
|
||||||
/// Logs out of the specified session.
|
/// Logs out of the specified session.
|
||||||
func logout(userSession: UserSessionProtocol)
|
func logout(userSession: UserSessionProtocol)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ final class NSEUserSession {
|
|||||||
|
|
||||||
let homeserverURL = credentials.restorationToken.session.homeserverUrl
|
let homeserverURL = credentials.restorationToken.session.homeserverUrl
|
||||||
var clientBuilder = ClientBuilder()
|
var clientBuilder = ClientBuilder()
|
||||||
.basePath(path: URL.sessionsBaseDirectory.path)
|
.sessionPath(path: credentials.restorationToken.sessionDirectory.path(percentEncoded: false))
|
||||||
.username(username: credentials.userID)
|
.username(username: credentials.userID)
|
||||||
.homeserverUrl(url: homeserverURL)
|
.homeserverUrl(url: homeserverURL)
|
||||||
.passphrase(passphrase: credentials.restorationToken.passphrase)
|
.passphrase(passphrase: credentials.restorationToken.passphrase)
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/element-hq/swift-command-line-tools.git",
|
"location" : "https://github.com/element-hq/swift-command-line-tools.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "a6ad90808f4f6cac615ab8496c6ff1bc5f9fa192"
|
"revision" : "e5eaab1558ef664e6cd80493f64259381670fb3a"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ let package = Package(
|
|||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.package(url: "https://github.com/apple/swift-argument-parser", .upToNextMinor(from: "1.4.0")),
|
.package(url: "https://github.com/apple/swift-argument-parser", .upToNextMinor(from: "1.4.0")),
|
||||||
.package(url: "https://github.com/element-hq/swift-command-line-tools.git", revision: "a6ad90808f4f6cac615ab8496c6ff1bc5f9fa192"),
|
.package(url: "https://github.com/element-hq/swift-command-line-tools.git", revision: "e5eaab1558ef664e6cd80493f64259381670fb3a"),
|
||||||
// .package(path: "../../../swift-command-line-tools"),
|
// .package(path: "../../../swift-command-line-tools"),
|
||||||
.package(url: "https://github.com/jpsim/Yams", .upToNextMinor(from: "5.1.2"))
|
.package(url: "https://github.com/jpsim/Yams", .upToNextMinor(from: "5.1.2"))
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ struct GenerateSDKMocks: ParsableCommand {
|
|||||||
@Argument(help: "The argument to specify a branch of the SDK. Use `local` to use your local version")
|
@Argument(help: "The argument to specify a branch of the SDK. Use `local` to use your local version")
|
||||||
var version: String
|
var version: String
|
||||||
|
|
||||||
private var fileURLFormat = "https://raw.githubusercontent.com/matrix-org/matrix-rust-components-swift/%@/Sources/MatrixRustSDK/matrix_sdk_ffi.swift"
|
private var fileURLFormat = "https://raw.githubusercontent.com/element-hq/matrix-rust-components-swift/%@/Sources/MatrixRustSDK/matrix_sdk_ffi.swift"
|
||||||
|
|
||||||
func run() throws {
|
func run() throws {
|
||||||
if version == "local" {
|
if version == "local" {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ class KeychainControllerTests: XCTestCase {
|
|||||||
homeserverUrl: "homeserverUrl",
|
homeserverUrl: "homeserverUrl",
|
||||||
oidcData: "oidcData",
|
oidcData: "oidcData",
|
||||||
slidingSyncProxy: "https://my.sync.proxy"),
|
slidingSyncProxy: "https://my.sync.proxy"),
|
||||||
|
sessionDirectory: .homeDirectory.appending(component: UUID().uuidString),
|
||||||
passphrase: "passphrase",
|
passphrase: "passphrase",
|
||||||
pusherNotificationClientIdentifier: "pusherClientID")
|
pusherNotificationClientIdentifier: "pusherClientID")
|
||||||
keychain.setRestorationToken(restorationToken, forUsername: username)
|
keychain.setRestorationToken(restorationToken, forUsername: username)
|
||||||
@@ -58,6 +59,7 @@ class KeychainControllerTests: XCTestCase {
|
|||||||
homeserverUrl: "homeserverUrl",
|
homeserverUrl: "homeserverUrl",
|
||||||
oidcData: "oidcData",
|
oidcData: "oidcData",
|
||||||
slidingSyncProxy: "https://my.sync.proxy"),
|
slidingSyncProxy: "https://my.sync.proxy"),
|
||||||
|
sessionDirectory: .homeDirectory.appending(component: UUID().uuidString),
|
||||||
passphrase: "passphrase",
|
passphrase: "passphrase",
|
||||||
pusherNotificationClientIdentifier: "pusherClientID")
|
pusherNotificationClientIdentifier: "pusherClientID")
|
||||||
keychain.setRestorationToken(restorationToken, forUsername: username)
|
keychain.setRestorationToken(restorationToken, forUsername: username)
|
||||||
@@ -82,6 +84,7 @@ class KeychainControllerTests: XCTestCase {
|
|||||||
homeserverUrl: "homeserverUrl",
|
homeserverUrl: "homeserverUrl",
|
||||||
oidcData: "oidcData",
|
oidcData: "oidcData",
|
||||||
slidingSyncProxy: "https://my.sync.proxy"),
|
slidingSyncProxy: "https://my.sync.proxy"),
|
||||||
|
sessionDirectory: .homeDirectory.appending(component: UUID().uuidString),
|
||||||
passphrase: "passphrase",
|
passphrase: "passphrase",
|
||||||
pusherNotificationClientIdentifier: "pusherClientID")
|
pusherNotificationClientIdentifier: "pusherClientID")
|
||||||
keychain.setRestorationToken(restorationToken, forUsername: "@test\(index):example.com")
|
keychain.setRestorationToken(restorationToken, forUsername: "@test\(index):example.com")
|
||||||
@@ -105,6 +108,7 @@ class KeychainControllerTests: XCTestCase {
|
|||||||
homeserverUrl: "homeserverUrl",
|
homeserverUrl: "homeserverUrl",
|
||||||
oidcData: "oidcData",
|
oidcData: "oidcData",
|
||||||
slidingSyncProxy: "https://my.sync.proxy"),
|
slidingSyncProxy: "https://my.sync.proxy"),
|
||||||
|
sessionDirectory: .homeDirectory.appending(component: UUID().uuidString),
|
||||||
passphrase: "passphrase",
|
passphrase: "passphrase",
|
||||||
pusherNotificationClientIdentifier: "pusherClientID")
|
pusherNotificationClientIdentifier: "pusherClientID")
|
||||||
keychain.setRestorationToken(restorationToken, forUsername: "@test\(index):example.com")
|
keychain.setRestorationToken(restorationToken, forUsername: "@test\(index):example.com")
|
||||||
|
|||||||
+1
-1
@@ -49,7 +49,7 @@ packages:
|
|||||||
# Element/Matrix dependencies
|
# Element/Matrix dependencies
|
||||||
MatrixRustSDK:
|
MatrixRustSDK:
|
||||||
url: https://github.com/element-hq/matrix-rust-components-swift
|
url: https://github.com/element-hq/matrix-rust-components-swift
|
||||||
exactVersion: 1.0.9
|
exactVersion: 1.0.10
|
||||||
# path: ../matrix-rust-sdk
|
# path: ../matrix-rust-sdk
|
||||||
Compound:
|
Compound:
|
||||||
url: https://github.com/element-hq/compound-ios
|
url: https://github.com/element-hq/compound-ios
|
||||||
|
|||||||
Reference in New Issue
Block a user