mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Make the SessionDirectories type responsible for cleaning up data. (#3261)
This commit is contained in:
@@ -10,10 +10,17 @@ import MatrixRustSDK
|
||||
|
||||
struct RestorationToken: Equatable {
|
||||
let session: MatrixRustSDK.Session
|
||||
let sessionDirectory: URL
|
||||
let cacheDirectory: URL
|
||||
let sessionDirectories: SessionDirectories
|
||||
let passphrase: String?
|
||||
let pusherNotificationClientIdentifier: String?
|
||||
|
||||
enum CodingKeys: CodingKey {
|
||||
case session
|
||||
case sessionDirectory
|
||||
case cacheDirectory
|
||||
case passphrase
|
||||
case pusherNotificationClientIdentifier
|
||||
}
|
||||
}
|
||||
|
||||
extension RestorationToken: Codable {
|
||||
@@ -35,11 +42,19 @@ extension RestorationToken: Codable {
|
||||
}
|
||||
|
||||
self = try .init(session: session,
|
||||
sessionDirectory: sessionDirectories.dataDirectory,
|
||||
cacheDirectory: sessionDirectories.cacheDirectory,
|
||||
sessionDirectories: sessionDirectories,
|
||||
passphrase: container.decodeIfPresent(String.self, forKey: .passphrase),
|
||||
pusherNotificationClientIdentifier: container.decodeIfPresent(String.self, forKey: .pusherNotificationClientIdentifier))
|
||||
}
|
||||
|
||||
func encode(to encoder: any Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(session, forKey: .session)
|
||||
try container.encode(sessionDirectories.dataDirectory, forKey: .sessionDirectory)
|
||||
try container.encode(sessionDirectories.cacheDirectory, forKey: .cacheDirectory)
|
||||
try container.encode(passphrase, forKey: .passphrase)
|
||||
try container.encode(pusherNotificationClientIdentifier, forKey: .pusherNotificationClientIdentifier)
|
||||
}
|
||||
}
|
||||
|
||||
extension MatrixRustSDK.Session: Codable {
|
||||
|
||||
@@ -13,6 +13,50 @@ struct SessionDirectories: Hashable, Codable {
|
||||
|
||||
var dataPath: String { dataDirectory.path(percentEncoded: false) }
|
||||
var cachePath: String { cacheDirectory.path(percentEncoded: false) }
|
||||
|
||||
// MARK: Data Management
|
||||
|
||||
/// Removes the directories from disk if they have been created.
|
||||
func delete() {
|
||||
do {
|
||||
if FileManager.default.directoryExists(at: dataDirectory) {
|
||||
try FileManager.default.removeItem(at: dataDirectory)
|
||||
}
|
||||
} catch {
|
||||
MXLog.failure("Failed deleting the session data: \(error)")
|
||||
}
|
||||
do {
|
||||
if FileManager.default.directoryExists(at: cacheDirectory) {
|
||||
try FileManager.default.removeItem(at: cacheDirectory)
|
||||
}
|
||||
} catch {
|
||||
MXLog.failure("Failed deleting the session caches: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
/// Deletes the Rust state store and event cache data, leaving the crypto store and both
|
||||
/// session directories in place along with any other data that may have been written in them.
|
||||
func deleteTransientUserData() {
|
||||
do {
|
||||
let prefix = "matrix-sdk-state"
|
||||
try deleteFiles(at: dataDirectory, with: prefix)
|
||||
} catch {
|
||||
MXLog.failure("Failed clearing state store: \(error)")
|
||||
}
|
||||
do {
|
||||
let prefix = "matrix-sdk-event-cache"
|
||||
try deleteFiles(at: cacheDirectory, with: prefix)
|
||||
} catch {
|
||||
MXLog.failure("Failed clearing event cache store: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
private func deleteFiles(at url: URL, with prefix: String) throws {
|
||||
let sessionDirectoryContents = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil)
|
||||
for url in sessionDirectoryContents where url.lastPathComponent.hasPrefix(prefix) {
|
||||
try FileManager.default.removeItem(at: url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension SessionDirectories {
|
||||
|
||||
@@ -14,7 +14,6 @@ class UserSessionStore: UserSessionStoreProtocol {
|
||||
private let appSettings: AppSettings
|
||||
private let networkMonitor: NetworkMonitorProtocol
|
||||
private let appHooks: AppHooks
|
||||
private let matrixSDKStateKey = "matrix-sdk-state"
|
||||
|
||||
/// Whether or not there are sessions in the store.
|
||||
var hasSessions: Bool { !keychainController.restorationTokens().isEmpty }
|
||||
@@ -55,7 +54,7 @@ class UserSessionStore: UserSessionStoreProtocol {
|
||||
|
||||
// On any restoration failure reset the token and restart
|
||||
keychainController.removeRestorationTokenForUsername(credentials.userID)
|
||||
deleteSessionDirectories(for: credentials)
|
||||
credentials.restorationToken.sessionDirectories.delete()
|
||||
|
||||
return .failure(error)
|
||||
}
|
||||
@@ -68,8 +67,7 @@ class UserSessionStore: UserSessionStoreProtocol {
|
||||
let clientProxy = await setupProxyForClient(client)
|
||||
|
||||
keychainController.setRestorationToken(RestorationToken(session: session,
|
||||
sessionDirectory: sessionDirectories.dataDirectory,
|
||||
cacheDirectory: sessionDirectories.cacheDirectory,
|
||||
sessionDirectories: sessionDirectories,
|
||||
passphrase: passphrase,
|
||||
pusherNotificationClientIdentifier: clientProxy.pusherNotificationClientIdentifier),
|
||||
forUsername: userID)
|
||||
@@ -87,7 +85,7 @@ class UserSessionStore: UserSessionStoreProtocol {
|
||||
keychainController.removeRestorationTokenForUsername(userID)
|
||||
|
||||
if let credentials {
|
||||
deleteSessionDirectories(for: credentials)
|
||||
credentials.restorationToken.sessionDirectories.delete()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +94,7 @@ class UserSessionStore: UserSessionStoreProtocol {
|
||||
MXLog.error("Failed to clearing caches: Credentials missing")
|
||||
return
|
||||
}
|
||||
deleteCaches(for: credentials)
|
||||
credentials.restorationToken.sessionDirectories.deleteTransientUserData()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
@@ -125,8 +123,8 @@ class UserSessionStore: UserSessionStoreProtocol {
|
||||
slidingSync: .restored,
|
||||
sessionDelegate: keychainController,
|
||||
appHooks: appHooks)
|
||||
.sessionPaths(dataPath: credentials.restorationToken.sessionDirectory.path(percentEncoded: false),
|
||||
cachePath: credentials.restorationToken.cacheDirectory.path(percentEncoded: false))
|
||||
.sessionPaths(dataPath: credentials.restorationToken.sessionDirectories.dataPath,
|
||||
cachePath: credentials.restorationToken.sessionDirectories.cachePath)
|
||||
.username(username: credentials.userID)
|
||||
.homeserverUrl(url: homeserverURL)
|
||||
.passphrase(passphrase: credentials.restorationToken.passphrase)
|
||||
@@ -148,37 +146,4 @@ class UserSessionStore: UserSessionStoreProtocol {
|
||||
networkMonitor: networkMonitor,
|
||||
appSettings: appSettings)
|
||||
}
|
||||
|
||||
private func deleteSessionDirectories(for credentials: KeychainCredentials) {
|
||||
do {
|
||||
try FileManager.default.removeItem(at: credentials.restorationToken.sessionDirectory)
|
||||
} catch {
|
||||
MXLog.failure("Failed deleting the session data: \(error)")
|
||||
}
|
||||
do {
|
||||
try FileManager.default.removeItem(at: credentials.restorationToken.cacheDirectory)
|
||||
} catch {
|
||||
MXLog.failure("Failed deleting the session caches: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
private func deleteCaches(for credentials: KeychainCredentials) {
|
||||
do {
|
||||
try deleteContentsOfDirectory(at: credentials.restorationToken.sessionDirectory)
|
||||
} catch {
|
||||
MXLog.failure("Failed clearing state store: \(error)")
|
||||
}
|
||||
do {
|
||||
try deleteContentsOfDirectory(at: credentials.restorationToken.cacheDirectory)
|
||||
} catch {
|
||||
MXLog.failure("Failed clearing event cache store: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
private func deleteContentsOfDirectory(at url: URL) throws {
|
||||
let sessionDirectoryContents = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil)
|
||||
for url in sessionDirectoryContents where url.path.contains(matrixSDKStateKey) {
|
||||
try FileManager.default.removeItem(at: url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user