Stop showing the sliding sync proxy alert to any remaining users.

The session will simply fail to restore and the restoration token deleted.
This commit is contained in:
Doug
2025-07-30 12:18:10 +01:00
committed by Doug
parent df335bd2b1
commit 5762e1c537
10 changed files with 89 additions and 128 deletions
@@ -74,7 +74,6 @@ extension ClientProxyMock {
ignoreUserReturnValue = .success(()) ignoreUserReturnValue = .success(())
unignoreUserReturnValue = .success(()) unignoreUserReturnValue = .success(())
needsSlidingSyncMigration = false
slidingSyncVersion = .native slidingSyncVersion = .native
trackRecentlyVisitedRoomReturnValue = .success(()) trackRecentlyVisitedRoomReturnValue = .success(())
@@ -2093,11 +2093,6 @@ class ClientProxyMock: ClientProxyProtocol, @unchecked Sendable {
set(value) { underlyingHomeserver = value } set(value) { underlyingHomeserver = value }
} }
var underlyingHomeserver: String! var underlyingHomeserver: String!
var needsSlidingSyncMigration: Bool {
get { return underlyingNeedsSlidingSyncMigration }
set(value) { underlyingNeedsSlidingSyncMigration = value }
}
var underlyingNeedsSlidingSyncMigration: Bool!
var slidingSyncVersion: SlidingSyncVersion { var slidingSyncVersion: SlidingSyncVersion {
get { return underlyingSlidingSyncVersion } get { return underlyingSlidingSyncVersion }
set(value) { underlyingSlidingSyncVersion = value } set(value) { underlyingSlidingSyncVersion = value }
@@ -133,10 +133,6 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
setupRoomListSubscriptions() setupRoomListSubscriptions()
updateRooms() updateRooms()
Task {
await checkSlidingSyncMigration()
}
} }
// MARK: - Public // MARK: - Public
@@ -318,24 +314,6 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
state.rooms = rooms state.rooms = rooms
} }
/// Check whether we can inform the user about potential migrations
/// or have him logout as his proxy is no longer available
private func checkSlidingSyncMigration() async {
guard userSession.clientProxy.needsSlidingSyncMigration else {
return
}
// The proxy is no longer supported so a logout is needed.
// Delay setting the alert otherwise it automatically gets dismissed. Same as the crashed last run one
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.state.bindings.alertInfo = AlertInfo(id: UUID(),
title: L10n.bannerMigrateToNativeSlidingSyncAppForceLogoutTitle(InfoPlistReader.main.bundleDisplayName),
primaryButton: .init(title: L10n.bannerMigrateToNativeSlidingSyncAction) { [weak self] in
self?.actionsSubject.send(.logoutWithoutConfirmation)
})
}
}
private func markRoomAsFavourite(_ roomID: String, isFavourite: Bool) async { private func markRoomAsFavourite(_ roomID: String, isFavourite: Bool) async {
guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else { guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else {
MXLog.error("Failed retrieving room for identifier: \(roomID)") MXLog.error("Failed retrieving room for identifier: \(roomID)")
@@ -150,7 +150,6 @@ class ClientProxy: ClientProxyProtocol {
private let sendQueueStatusSubject = CurrentValueSubject<Bool, Never>(false) private let sendQueueStatusSubject = CurrentValueSubject<Bool, Never>(false)
init(client: ClientProtocol, init(client: ClientProtocol,
needsSlidingSyncMigration: Bool,
networkMonitor: NetworkMonitorProtocol, networkMonitor: NetworkMonitorProtocol,
appSettings: AppSettings) async throws { appSettings: AppSettings) async throws {
self.client = client self.client = client
@@ -165,8 +164,6 @@ class ClientProxy: ClientProxyProtocol {
secureBackupController = SecureBackupController(encryption: client.encryption()) secureBackupController = SecureBackupController(encryption: client.encryption())
self.needsSlidingSyncMigration = needsSlidingSyncMigration
let configuredAppService = try await ClientProxyServices(client: client, let configuredAppService = try await ClientProxyServices(client: client,
actionsSubject: actionsSubject, actionsSubject: actionsSubject,
notificationSettings: notificationSettings, notificationSettings: notificationSettings,
@@ -271,7 +268,6 @@ class ClientProxy: ClientProxyProtocol {
client.homeserver() client.homeserver()
} }
let needsSlidingSyncMigration: Bool
var slidingSyncVersion: SlidingSyncVersion { var slidingSyncVersion: SlidingSyncVersion {
client.slidingSyncVersion() client.slidingSyncVersion()
} }
@@ -341,11 +337,6 @@ class ClientProxy: ClientProxyProtocol {
} }
func startSync() { func startSync() {
guard !needsSlidingSyncMigration else {
MXLog.warning("Ignoring request, this client needs to be migrated to native sliding sync.")
return
}
guard !hasEncounteredAuthError else { guard !hasEncounteredAuthError else {
MXLog.warning("Ignoring request, this client has an unknown token.") MXLog.warning("Ignoring request, this client has an unknown token.")
return return
@@ -86,9 +86,6 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol {
var homeserver: String { get } var homeserver: String { get }
// TODO: This is a temporary value, in the future we should throw a migration error
// when decoding a session that contains a sliding sync proxy URL instead of restoring it.
var needsSlidingSyncMigration: Bool { get }
var slidingSyncVersion: SlidingSyncVersion { get } var slidingSyncVersion: SlidingSyncVersion { get }
var canDeactivateAccount: Bool { get } var canDeactivateAccount: Bool { get }
@@ -56,6 +56,10 @@ class KeychainController: KeychainControllerProtocol {
} }
return try JSONDecoder().decode(RestorationToken.self, from: tokenData) return try JSONDecoder().decode(RestorationToken.self, from: tokenData)
} catch RestorationTokenError.slidingSyncProxyNotSupported {
MXLog.error("Unsupported user restore token (contains sliding sync proxy). Deleting token.")
removeRestorationTokenForUsername(username)
return nil
} catch { } catch {
MXLog.error("Failed retrieving user restore token") MXLog.error("Failed retrieving user restore token")
return nil return nil
@@ -112,8 +116,7 @@ class KeychainController: KeychainControllerProtocol {
let restorationToken = RestorationToken(session: session, let restorationToken = RestorationToken(session: session,
sessionDirectories: oldToken.sessionDirectories, sessionDirectories: oldToken.sessionDirectories,
passphrase: oldToken.passphrase, passphrase: oldToken.passphrase,
pusherNotificationClientIdentifier: oldToken.pusherNotificationClientIdentifier, pusherNotificationClientIdentifier: oldToken.pusherNotificationClientIdentifier)
slidingSyncProxyURLString: oldToken.slidingSyncProxyURLString)
setRestorationToken(restorationToken, forUsername: session.userId) setRestorationToken(restorationToken, forUsername: session.userId)
} }
@@ -8,19 +8,16 @@
import Foundation import Foundation
import MatrixRustSDK import MatrixRustSDK
enum RestorationTokenError: Error {
case slidingSyncProxyNotSupported
}
struct RestorationToken: Equatable { struct RestorationToken: Equatable {
let session: MatrixRustSDK.Session let session: MatrixRustSDK.Session
let sessionDirectories: SessionDirectories let sessionDirectories: SessionDirectories
let passphrase: String? let passphrase: String?
let pusherNotificationClientIdentifier: String? let pusherNotificationClientIdentifier: String?
/// The sliding sync proxy URL that was previously encoded in the Session.
/// This is temporary to help make a nicer user migration flow. In the future
/// we will throw when decoding sessions with a sliding sync proxy URL.
let slidingSyncProxyURLString: String?
/// Whether the token is for a session that is using the now unsupported sliding sync proxy.
var needsSlidingSyncMigration: Bool { slidingSyncProxyURLString != nil }
enum CodingKeys: CodingKey { enum CodingKeys: CodingKey {
case session case session
case sessionDirectory case sessionDirectory
@@ -34,7 +31,7 @@ extension RestorationToken: Codable {
init(from decoder: Decoder) throws { init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
let sessionWrapper = try container.decode(SessionWrapper.self, forKey: .session) let session = try container.decode(Session.self, forKey: .session)
let dataDirectory = try container.decodeIfPresent(URL.self, forKey: .sessionDirectory) let dataDirectory = try container.decodeIfPresent(URL.self, forKey: .sessionDirectory)
let cacheDirectory = try container.decodeIfPresent(URL.self, forKey: .cacheDirectory) let cacheDirectory = try container.decodeIfPresent(URL.self, forKey: .cacheDirectory)
@@ -45,19 +42,18 @@ extension RestorationToken: Codable {
SessionDirectories(dataDirectory: dataDirectory) SessionDirectories(dataDirectory: dataDirectory)
} }
} else { } else {
SessionDirectories(userID: sessionWrapper.session.userId) SessionDirectories(userID: session.userId)
} }
self = try .init(session: sessionWrapper.session, self = try .init(session: session,
sessionDirectories: sessionDirectories, sessionDirectories: sessionDirectories,
passphrase: container.decodeIfPresent(String.self, forKey: .passphrase), passphrase: container.decodeIfPresent(String.self, forKey: .passphrase),
pusherNotificationClientIdentifier: container.decodeIfPresent(String.self, forKey: .pusherNotificationClientIdentifier), pusherNotificationClientIdentifier: container.decodeIfPresent(String.self, forKey: .pusherNotificationClientIdentifier))
slidingSyncProxyURLString: sessionWrapper.slidingSyncProxyURLString)
} }
func encode(to encoder: any Encoder) throws { func encode(to encoder: any Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(SessionWrapper(session: session, slidingSyncProxyURLString: slidingSyncProxyURLString), forKey: .session) try container.encode(session, forKey: .session)
try container.encode(sessionDirectories.dataDirectory, forKey: .sessionDirectory) try container.encode(sessionDirectories.dataDirectory, forKey: .sessionDirectory)
try container.encode(sessionDirectories.cacheDirectory, forKey: .cacheDirectory) try container.encode(sessionDirectories.cacheDirectory, forKey: .cacheDirectory)
try container.encode(passphrase, forKey: .passphrase) try container.encode(passphrase, forKey: .passphrase)
@@ -65,33 +61,20 @@ extension RestorationToken: Codable {
} }
} }
/// Temporary struct to smooth the forced migration by keeping a user session.
/// In the future we can remove this and throw a migration error when the URL
/// is decoded to a non-nil value.
private struct SessionWrapper {
let session: MatrixRustSDK.Session
let slidingSyncProxyURLString: String?
}
extension SessionWrapper: Codable {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: MatrixRustSDK.Session.CodingKeys.self)
session = try Session(from: decoder)
// TODO: In the future we should decode this in the Session and throw a migration error if it contains a value.
slidingSyncProxyURLString = try container.decodeIfPresent(String.self, forKey: .slidingSyncProxy)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: MatrixRustSDK.Session.CodingKeys.self)
try session.encode(to: encoder)
try container.encode(slidingSyncProxyURLString, forKey: .slidingSyncProxy)
}
}
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)
// The SDK no longer supports sliding sync proxies. We must bail here otherwise the
// session would be restored using native sliding sync, but if the proxy was still
// active its sync loop would be stealing keys away from us.
//
// Note: As tempting as it is to use container.contains(.slidingSyncProxy), that will always
// return true as our coding keys have resulted in the key being encoded with a nil value 🤦‍♂️.
if (try? container.decodeIfPresent(String.self, forKey: .slidingSyncProxy)) != nil {
throw RestorationTokenError.slidingSyncProxyNotSupported
}
self = try .init(accessToken: container.decode(String.self, forKey: .accessToken), self = try .init(accessToken: container.decode(String.self, forKey: .accessToken),
refreshToken: container.decodeIfPresent(String.self, forKey: .refreshToken), refreshToken: container.decodeIfPresent(String.self, forKey: .refreshToken),
userId: container.decode(String.self, forKey: .userId), userId: container.decode(String.self, forKey: .userId),
@@ -64,13 +64,12 @@ class UserSessionStore: UserSessionStoreProtocol {
do { do {
let session = try client.session() let session = try client.session()
let userID = try client.userId() let userID = try client.userId()
let clientProxy = try await setupProxyForClient(client, needsSlidingSyncMigration: false) let clientProxy = try await setupProxyForClient(client)
keychainController.setRestorationToken(RestorationToken(session: session, keychainController.setRestorationToken(RestorationToken(session: session,
sessionDirectories: sessionDirectories, sessionDirectories: sessionDirectories,
passphrase: passphrase, passphrase: passphrase,
pusherNotificationClientIdentifier: clientProxy.pusherNotificationClientIdentifier, pusherNotificationClientIdentifier: clientProxy.pusherNotificationClientIdentifier),
slidingSyncProxyURLString: nil),
forUsername: userID) forUsername: userID)
MXLog.info("Set up session for user \(userID) at: \(sessionDirectories)") MXLog.info("Set up session for user \(userID) at: \(sessionDirectories)")
@@ -141,7 +140,7 @@ class UserSessionStore: UserSessionStoreProtocol {
Task(priority: .low) { await appHooks.remoteSettingsHook.updateCache(using: client) } Task(priority: .low) { await appHooks.remoteSettingsHook.updateCache(using: client) }
return try await .success(setupProxyForClient(client, needsSlidingSyncMigration: credentials.restorationToken.needsSlidingSyncMigration)) return try await .success(setupProxyForClient(client))
} catch UserSessionStoreError.failedSettingUpClientProxy(let error) { } catch UserSessionStoreError.failedSettingUpClientProxy(let error) {
// If this has failed, there is likely something wrong with the creation of the sync service // If this has failed, there is likely something wrong with the creation of the sync service
// There is nothing we can do, but at the same time we don't want the user to the get logged out // There is nothing we can do, but at the same time we don't want the user to the get logged out
@@ -153,10 +152,9 @@ class UserSessionStore: UserSessionStoreProtocol {
} }
} }
private func setupProxyForClient(_ client: ClientProtocol, needsSlidingSyncMigration: Bool) async throws -> ClientProxyProtocol { private func setupProxyForClient(_ client: ClientProtocol) async throws -> ClientProxyProtocol {
do { do {
return try await ClientProxy(client: client, return try await ClientProxy(client: client,
needsSlidingSyncMigration: needsSlidingSyncMigration,
networkMonitor: networkMonitor, networkMonitor: networkMonitor,
appSettings: appSettings) appSettings: appSettings)
} catch { } catch {
+31 -27
View File
@@ -6,6 +6,7 @@
// //
@testable import ElementX @testable import ElementX
import KeychainAccess
import XCTest import XCTest
class KeychainControllerTests: XCTestCase { class KeychainControllerTests: XCTestCase {
@@ -33,8 +34,7 @@ class KeychainControllerTests: XCTestCase {
slidingSyncVersion: .native), slidingSyncVersion: .native),
sessionDirectories: .init(), sessionDirectories: .init(),
passphrase: "passphrase", passphrase: "passphrase",
pusherNotificationClientIdentifier: "pusherClientID", pusherNotificationClientIdentifier: "pusherClientID")
slidingSyncProxyURLString: "https://my.sync.proxy")
keychain.setRestorationToken(restorationToken, forUsername: username) keychain.setRestorationToken(restorationToken, forUsername: username)
// Then the restoration token should be stored in the keychain. // Then the restoration token should be stored in the keychain.
@@ -53,8 +53,7 @@ class KeychainControllerTests: XCTestCase {
slidingSyncVersion: .native), slidingSyncVersion: .native),
sessionDirectories: .init(), sessionDirectories: .init(),
passphrase: "passphrase", passphrase: "passphrase",
pusherNotificationClientIdentifier: "pusherClientID", pusherNotificationClientIdentifier: "pusherClientID")
slidingSyncProxyURLString: "https://my.sync.proxy")
keychain.setRestorationToken(restorationToken, forUsername: username) keychain.setRestorationToken(restorationToken, forUsername: username)
XCTAssertEqual(keychain.restorationTokens().count, 1, "The keychain should have 1 restoration token.") XCTAssertEqual(keychain.restorationTokens().count, 1, "The keychain should have 1 restoration token.")
XCTAssertEqual(keychain.restorationTokenForUsername(username), restorationToken, "The initial restoration token should match the value that was stored.") XCTAssertEqual(keychain.restorationTokenForUsername(username), restorationToken, "The initial restoration token should match the value that was stored.")
@@ -79,8 +78,7 @@ class KeychainControllerTests: XCTestCase {
slidingSyncVersion: .native), slidingSyncVersion: .native),
sessionDirectories: .init(), sessionDirectories: .init(),
passphrase: "passphrase", passphrase: "passphrase",
pusherNotificationClientIdentifier: "pusherClientID", pusherNotificationClientIdentifier: "pusherClientID")
slidingSyncProxyURLString: "https://my.sync.proxy")
keychain.setRestorationToken(restorationToken, forUsername: "@test\(index):example.com") keychain.setRestorationToken(restorationToken, forUsername: "@test\(index):example.com")
} }
XCTAssertEqual(keychain.restorationTokens().count, 5, "The keychain should have 5 restoration tokens.") XCTAssertEqual(keychain.restorationTokens().count, 5, "The keychain should have 5 restoration tokens.")
@@ -104,8 +102,7 @@ class KeychainControllerTests: XCTestCase {
slidingSyncVersion: .native), slidingSyncVersion: .native),
sessionDirectories: .init(), sessionDirectories: .init(),
passphrase: "passphrase", passphrase: "passphrase",
pusherNotificationClientIdentifier: "pusherClientID", pusherNotificationClientIdentifier: "pusherClientID")
slidingSyncProxyURLString: "https://my.sync.proxy")
keychain.setRestorationToken(restorationToken, forUsername: "@test\(index):example.com") keychain.setRestorationToken(restorationToken, forUsername: "@test\(index):example.com")
} }
XCTAssertEqual(keychain.restorationTokens().count, 5, "The keychain should have 5 restoration tokens.") XCTAssertEqual(keychain.restorationTokens().count, 5, "The keychain should have 5 restoration tokens.")
@@ -122,27 +119,34 @@ class KeychainControllerTests: XCTestCase {
XCTAssertNotNil(keychain.restorationTokenForUsername("@test4:example.com"), "The restoration token should not have been deleted.") XCTAssertNotNil(keychain.restorationTokenForUsername("@test4:example.com"), "The restoration token should not have been deleted.")
} }
func testSimplifiedSlidingSyncRestorationToken() { func testUnsupportedRestorationToken() {
// Given an empty keychain. // Given a keychain with an unsupported restoration token with a sliding sync proxy URL value.
XCTAssertTrue(keychain.restorationTokens().isEmpty, "The keychain should be empty to begin with.") let underlyingKeychain = Keychain(service: KeychainControllerService.tests.restorationTokenID,
accessGroup: InfoPlistReader.main.keychainAccessGroupIdentifier)
// Note: We assert with this underlying keychain's keys as keychain.restorationTokens() triggers the deletion that we're testing.
XCTAssertTrue(underlyingKeychain.allKeys().isEmpty, "The keychain should be empty to begin with.")
// When adding an restoration token that doesn't contain a sliding sync proxy (e.g. for SSS). do {
let username = "@test:example.com" let unsupportedToken = RestorationTokenV1(session: SessionV1(accessToken: "1234",
let restorationToken = RestorationToken(session: .init(accessToken: "accessToken", refreshToken: nil,
refreshToken: "refreshToken", userId: "@test:example.com",
userId: "userId", deviceId: "D3V1C3",
deviceId: "deviceId", homeserverUrl: "https://matrix.example.com",
homeserverUrl: "homeserverUrl", oidcData: nil,
oidcData: "oidcData", slidingSyncVersion: .proxy(url: "https://sync.example.com")))
slidingSyncVersion: .native), let tokenData = try JSONEncoder().encode(unsupportedToken)
sessionDirectories: .init(), try underlyingKeychain.set(tokenData, key: "@test:example.com")
passphrase: "passphrase", XCTAssertEqual(underlyingKeychain.allKeys().count, 1)
pusherNotificationClientIdentifier: "pusherClientID", } catch {
slidingSyncProxyURLString: nil) XCTFail("Failed storing user restore token with error: \(error)")
keychain.setRestorationToken(restorationToken, forUsername: username) }
// Then decoding the restoration token from the keychain should still work. // When attempting to retrieve the unsupported token.
XCTAssertEqual(keychain.restorationTokenForUsername(username), restorationToken, "The retrieved restoration token should match the value that was stored.") let retrievedToken = keychain.restorationTokenForUsername("@test:example.com")
// Then nothing should be returned and the restoration token should be automatically removed.
XCTAssertNil(retrievedToken, "The token should not be decoded.")
XCTAssertTrue(underlyingKeychain.allKeys().isEmpty, "The keychain should be empty again.")
} }
func testAddPINCode() throws { func testAddPINCode() throws {
+28 -15
View File
@@ -11,6 +11,31 @@ import XCTest
import MatrixRustSDK import MatrixRustSDK
class RestorationTokenTests: XCTestCase { class RestorationTokenTests: XCTestCase {
func testDecodeTokenV1WithSlidingSyncProxy() throws {
// Given an encoded restoration token that contains a session with a sliding sync proxy.
let originalToken = RestorationTokenV1(session: SessionV1(accessToken: "1234",
refreshToken: nil,
userId: "@user:example.com",
deviceId: "D3V1C3",
homeserverUrl: "https://matrix.example.com",
oidcData: nil,
slidingSyncVersion: .proxy(url: "https://sync.example.com")))
let data = try JSONEncoder().encode(originalToken)
// When decoding the data to the current restoration token format.
XCTAssertThrowsError(try JSONDecoder().decode(RestorationToken.self, from: data)) { error in
// Then an error should be thrown as it is no longer supported.
switch error {
case RestorationTokenError.slidingSyncProxyNotSupported:
break
default:
XCTFail("Unexpected error thrown: \(error)")
}
}
}
/// Honestly not sure if this test is needed or not – it is quite possible that `RestorationTokenV1` was only encoded at a time
/// when the sliding sync proxy was the only option. But lets keep the test for completeness of the session directory migration coverage.
func testDecodeFromTokenV1() throws { func testDecodeFromTokenV1() throws {
// Given an encoded restoration token in the original format that only contains a Session from the SDK. // Given an encoded restoration token in the original format that only contains a Session from the SDK.
let originalToken = RestorationTokenV1(session: SessionV1(accessToken: "1234", let originalToken = RestorationTokenV1(session: SessionV1(accessToken: "1234",
@@ -19,7 +44,7 @@ class RestorationTokenTests: XCTestCase {
deviceId: "D3V1C3", deviceId: "D3V1C3",
homeserverUrl: "https://matrix.example.com", homeserverUrl: "https://matrix.example.com",
oidcData: nil, oidcData: nil,
slidingSyncVersion: .proxy(url: "https://sync.example.com"))) slidingSyncVersion: .native))
let data = try JSONEncoder().encode(originalToken) let data = try JSONEncoder().encode(originalToken)
// When decoding the data to the current restoration token format. // When decoding the data to the current restoration token format.
@@ -33,10 +58,6 @@ class RestorationTokenTests: XCTestCase {
"The session directory should match the original location set by the Rust SDK from our base directory.") "The session directory should match the original location set by the Rust SDK from our base directory.")
XCTAssertEqual(decodedToken.sessionDirectories.cacheDirectory, .sessionCachesBaseDirectory.appending(component: "@user_example.com"), XCTAssertEqual(decodedToken.sessionDirectories.cacheDirectory, .sessionCachesBaseDirectory.appending(component: "@user_example.com"),
"The cache directory should be derived from the session directory but in the caches directory.") "The cache directory should be derived from the session directory but in the caches directory.")
XCTAssertEqual(decodedToken.slidingSyncProxyURLString, "https://sync.example.com",
"The original sliding sync URL should be preserved in order to trigger the migration prompt.")
XCTAssertTrue(decodedToken.needsSlidingSyncMigration, "The migration flag should be set to true.")
} }
func testDecodeFromTokenV4() throws { func testDecodeFromTokenV4() throws {
@@ -48,7 +69,7 @@ class RestorationTokenTests: XCTestCase {
deviceId: "D3V1C3", deviceId: "D3V1C3",
homeserverUrl: "https://matrix.example.com", homeserverUrl: "https://matrix.example.com",
oidcData: "data-from-mas", oidcData: "data-from-mas",
slidingSyncVersion: .proxy(url: "https://sync.example.com")), slidingSyncVersion: .native),
sessionDirectory: .sessionsBaseDirectory.appending(component: sessionDirectoryName), sessionDirectory: .sessionsBaseDirectory.appending(component: sessionDirectoryName),
passphrase: "passphrase", passphrase: "passphrase",
pusherNotificationClientIdentifier: "pusher-identifier") pusherNotificationClientIdentifier: "pusher-identifier")
@@ -66,10 +87,6 @@ class RestorationTokenTests: XCTestCase {
"The session directory should not be changed.") "The session directory should not be changed.")
XCTAssertEqual(decodedToken.sessionDirectories.cacheDirectory, .sessionCachesBaseDirectory.appending(component: sessionDirectoryName), XCTAssertEqual(decodedToken.sessionDirectories.cacheDirectory, .sessionCachesBaseDirectory.appending(component: sessionDirectoryName),
"The cache directory should be derived from the session directory but in the caches directory.") "The cache directory should be derived from the session directory but in the caches directory.")
XCTAssertEqual(decodedToken.slidingSyncProxyURLString, "https://sync.example.com",
"The original sliding sync URL should be preserved in order to trigger the migration prompt.")
XCTAssertTrue(decodedToken.needsSlidingSyncMigration, "The migration flag should be set to true.")
} }
func testDecodeFromTokenV5() throws { func testDecodeFromTokenV5() throws {
@@ -100,9 +117,6 @@ class RestorationTokenTests: XCTestCase {
"The session directory should not be changed.") "The session directory should not be changed.")
XCTAssertEqual(decodedToken.sessionDirectories.cacheDirectory, originalToken.cacheDirectory, XCTAssertEqual(decodedToken.sessionDirectories.cacheDirectory, originalToken.cacheDirectory,
"The cache directory should not be changed.") "The cache directory should not be changed.")
XCTAssertNil(decodedToken.slidingSyncProxyURLString, "No sliding sync proxy URL should be decoded for native sliding sync.")
XCTAssertFalse(decodedToken.needsSlidingSyncMigration, "The migration flag should not be set.")
} }
func testDecodeFromCurrentToken() throws { func testDecodeFromCurrentToken() throws {
@@ -116,8 +130,7 @@ class RestorationTokenTests: XCTestCase {
slidingSyncVersion: .native), slidingSyncVersion: .native),
sessionDirectories: .init(), sessionDirectories: .init(),
passphrase: "passphrase", passphrase: "passphrase",
pusherNotificationClientIdentifier: "pusher-identifier", pusherNotificationClientIdentifier: "pusher-identifier")
slidingSyncProxyURLString: nil)
let data = try JSONEncoder().encode(originalToken) let data = try JSONEncoder().encode(originalToken)
// When decoding the data. // When decoding the data.