Update the SDK.

Handles changes that removed support for the sliding sync proxy.
This commit is contained in:
Doug
2025-02-18 10:34:32 +00:00
committed by Doug
parent 1e58795a65
commit 74511e0570
33 changed files with 229 additions and 309 deletions

View File

@@ -13,38 +13,42 @@ import MatrixRustSDK
class RestorationTokenTests: XCTestCase {
func testDecodeFromTokenV1() throws {
// Given an encoded restoration token in the original format that only contains a Session from the SDK.
let originalToken = RestorationTokenV1(session: Session(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 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.
let decodedToken = try JSONDecoder().decode(RestorationToken.self, from: data)
// Then the output should be a valid token with the expected store directories.
XCTAssertEqual(decodedToken.session, originalToken.session, "The session should not be changed.")
assertEqual(session: decodedToken.session, originalSession: originalToken.session)
XCTAssertNil(decodedToken.passphrase, "There should not be a passphrase.")
XCTAssertNil(decodedToken.pusherNotificationClientIdentifier, "There should not be a push notification client ID.")
XCTAssertEqual(decodedToken.sessionDirectories.dataDirectory, .sessionsBaseDirectory.appending(component: "@user_example.com"),
"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"),
"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 {
// Given an encoded restoration token in the 4th format that contains a stored session directory.
let sessionDirectoryName = UUID().uuidString
let originalToken = RestorationTokenV4(session: Session(accessToken: "1234",
refreshToken: "5678",
userId: "@user:example.com",
deviceId: "D3V1C3",
homeserverUrl: "https://matrix.example.com",
oidcData: "data-from-mas",
slidingSyncVersion: .proxy(url: "https://sync.example.com")),
let originalToken = RestorationTokenV4(session: SessionV1(accessToken: "1234",
refreshToken: "5678",
userId: "@user:example.com",
deviceId: "D3V1C3",
homeserverUrl: "https://matrix.example.com",
oidcData: "data-from-mas",
slidingSyncVersion: .proxy(url: "https://sync.example.com")),
sessionDirectory: .sessionsBaseDirectory.appending(component: sessionDirectoryName),
passphrase: "passphrase",
pusherNotificationClientIdentifier: "pusher-identifier")
@@ -54,7 +58,7 @@ class RestorationTokenTests: XCTestCase {
let decodedToken = try JSONDecoder().decode(RestorationToken.self, from: data)
// Then the output should be a valid token with the expected store directories.
XCTAssertEqual(decodedToken.session, originalToken.session, "The session should not be changed.")
assertEqual(session: decodedToken.session, originalSession: originalToken.session)
XCTAssertEqual(decodedToken.passphrase, originalToken.passphrase, "The passphrase should not be changed.")
XCTAssertEqual(decodedToken.pusherNotificationClientIdentifier, originalToken.pusherNotificationClientIdentifier,
"The push notification client identifier should not be changed.")
@@ -62,18 +66,22 @@ class RestorationTokenTests: XCTestCase {
"The session directory should not be changed.")
XCTAssertEqual(decodedToken.sessionDirectories.cacheDirectory, .sessionCachesBaseDirectory.appending(component: sessionDirectoryName),
"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 {
// Given an encoded restoration token in the 5th format that contains separate directories for session data and caches.
let sessionDirectoryName = UUID().uuidString
let originalToken = RestorationTokenV5(session: Session(accessToken: "1234",
refreshToken: "5678",
userId: "@user:example.com",
deviceId: "D3V1C3",
homeserverUrl: "https://matrix.example.com",
oidcData: "data-from-mas",
slidingSyncVersion: .native),
let originalToken = RestorationTokenV5(session: SessionV1(accessToken: "1234",
refreshToken: "5678",
userId: "@user:example.com",
deviceId: "D3V1C3",
homeserverUrl: "https://matrix.example.com",
oidcData: "data-from-mas",
slidingSyncVersion: .native),
sessionDirectory: .sessionsBaseDirectory.appending(component: sessionDirectoryName),
cacheDirectory: .sessionCachesBaseDirectory.appending(component: sessionDirectoryName),
passphrase: "passphrase",
@@ -84,7 +92,7 @@ class RestorationTokenTests: XCTestCase {
let decodedToken = try JSONDecoder().decode(RestorationToken.self, from: data)
// Then the output should be a valid token.
XCTAssertEqual(decodedToken.session, originalToken.session, "The session should not be changed.")
assertEqual(session: decodedToken.session, originalSession: originalToken.session)
XCTAssertEqual(decodedToken.passphrase, originalToken.passphrase, "The passphrase should not be changed.")
XCTAssertEqual(decodedToken.pusherNotificationClientIdentifier, originalToken.pusherNotificationClientIdentifier,
"The push notification client identifier should not be changed.")
@@ -92,6 +100,9 @@ class RestorationTokenTests: XCTestCase {
"The session directory should not be changed.")
XCTAssertEqual(decodedToken.sessionDirectories.cacheDirectory, originalToken.cacheDirectory,
"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 {
@@ -105,7 +116,8 @@ class RestorationTokenTests: XCTestCase {
slidingSyncVersion: .native),
sessionDirectories: .init(),
passphrase: "passphrase",
pusherNotificationClientIdentifier: "pusher-identifier")
pusherNotificationClientIdentifier: "pusher-identifier",
slidingSyncProxyURLString: nil)
let data = try JSONEncoder().encode(originalToken)
// When decoding the data.
@@ -114,23 +126,86 @@ class RestorationTokenTests: XCTestCase {
// Then the output should be a valid token.
XCTAssertEqual(decodedToken, originalToken, "The token should remain identical.")
}
func assertEqual(session: Session, originalSession: SessionV1) {
XCTAssertEqual(session.accessToken, originalSession.accessToken, "The access token should not be changed.")
XCTAssertEqual(session.refreshToken, originalSession.refreshToken, "The refresh token should not be changed.")
XCTAssertEqual(session.userId, originalSession.userId, "The user ID should not be changed.")
XCTAssertEqual(session.deviceId, originalSession.deviceId, "The device ID should not be changed.")
XCTAssertEqual(session.homeserverUrl, originalSession.homeserverUrl, "The homeserver URL should not be changed.")
XCTAssertEqual(session.oidcData, originalSession.oidcData, "The OIDC data should not be changed.")
}
}
// MARK: - Token formats
struct RestorationTokenV1: Equatable, Codable {
let session: MatrixRustSDK.Session
let session: SessionV1
}
struct RestorationTokenV4: Equatable, Codable {
let session: MatrixRustSDK.Session
let session: SessionV1
let sessionDirectory: URL
let passphrase: String?
let pusherNotificationClientIdentifier: String?
}
struct RestorationTokenV5: Equatable, Codable {
let session: MatrixRustSDK.Session
let session: SessionV1
let sessionDirectory: URL
let cacheDirectory: URL
let passphrase: String?
let pusherNotificationClientIdentifier: String?
}
// MARK: - Session formats
struct SessionV1: Equatable {
var accessToken: String
var refreshToken: String?
var userId: String
var deviceId: String
var homeserverUrl: String
var oidcData: String?
var slidingSyncVersion: SlidingSyncVersionV1
}
enum SlidingSyncVersionV1: Equatable {
case none
case proxy(url: String)
case native
var proxyURL: String? {
guard case let .proxy(url) = self else { return nil }
return url
}
}
extension SessionV1: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let slidingSyncProxy = try container.decodeIfPresent(String.self, forKey: .slidingSyncProxy)
self = try .init(accessToken: container.decode(String.self, forKey: .accessToken),
refreshToken: container.decodeIfPresent(String.self, forKey: .refreshToken),
userId: container.decode(String.self, forKey: .userId),
deviceId: container.decode(String.self, forKey: .deviceId),
homeserverUrl: container.decode(String.self, forKey: .homeserverUrl),
oidcData: container.decodeIfPresent(String.self, forKey: .oidcData),
slidingSyncVersion: slidingSyncProxy.map { .proxy(url: $0) } ?? .native)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(accessToken, forKey: .accessToken)
try container.encode(refreshToken, forKey: .refreshToken)
try container.encode(userId, forKey: .userId)
try container.encode(deviceId, forKey: .deviceId)
try container.encode(homeserverUrl, forKey: .homeserverUrl)
try container.encode(oidcData, forKey: .oidcData)
try container.encode(slidingSyncVersion.proxyURL, forKey: .slidingSyncProxy)
}
enum CodingKeys: String, CodingKey {
case accessToken, refreshToken, userId, deviceId, homeserverUrl, oidcData, slidingSyncProxy
}
}