From 5eab6dea7e6bd50ab965a97ada6d86a74ed17dc9 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Fri, 27 Oct 2023 21:39:21 +0300 Subject: [PATCH] Session verification fixes and bump SDK to v0.0.1-october23 (#1954) * Fixes vector-im/element-x-ios/issues/1868 Incorrect `is_verified` flag after successfully running verification flow - the inner user_identity isn't automatically updated when the flow finishes, needs to be fetched again from encryption - also replaces `UserIdentity.is_verified` with `Device.is_cross_signed_by_owner` - depends on matrix-org/matrix-rust-sdk/pull/2775 --------- Co-authored-by: Doug --- ElementX.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 6 ++--- .../Mocks/Generated/GeneratedMocks.swift | 22 ++++++++++++++----- .../Mocks/Generated/SDKGeneratedMocks.swift | 17 ++++++++++++++ ...ssionVerificationControllerProxyMock.swift | 2 +- .../SettingsScreen/SettingsScreenModels.swift | 2 +- .../SettingsScreenViewModel.swift | 11 +++++----- .../SettingsScreen/View/SettingsScreen.swift | 2 +- .../Services/Session/UserSession.swift | 7 +++++- .../SessionVerificationControllerProxy.swift | 9 ++++++-- ...nVerificationControllerProxyProtocol.swift | 3 ++- project.yml | 2 +- 12 files changed, 62 insertions(+), 23 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 16ecb3017..27b2b012f 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -6588,7 +6588,7 @@ repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.1.26; + version = "0.0.1-october23"; }; }; 821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index c0744d988..c763fb312 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -129,8 +129,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/matrix-org/matrix-rust-components-swift", "state" : { - "revision" : "e7bacee684806d125077b032e3848189ad370f3b", - "version" : "1.1.26" + "revision" : "f53f5302ddcd81e4134fa7437fedd5c33cd7c1bf", + "version" : "0.0.1-october23" } }, { @@ -262,7 +262,7 @@ { "identity" : "swiftui-introspect", "kind" : "remoteSourceControl", - "location" : "https://github.com/siteline/SwiftUI-Introspect.git", + "location" : "https://github.com/siteline/SwiftUI-Introspect", "state" : { "revision" : "b94da693e57eaf79d16464b8b7c90d09cba4e290", "version" : "0.9.2" diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index ff0da9e23..e796cf3f5 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -2704,12 +2704,24 @@ class SessionVerificationControllerProxyMock: SessionVerificationControllerProxy set(value) { underlyingCallbacks = value } } var underlyingCallbacks: PassthroughSubject! - var isVerified: Bool { - get { return underlyingIsVerified } - set(value) { underlyingIsVerified = value } - } - var underlyingIsVerified: Bool! + //MARK: - isVerified + + var isVerifiedCallsCount = 0 + var isVerifiedCalled: Bool { + return isVerifiedCallsCount > 0 + } + var isVerifiedReturnValue: Result! + var isVerifiedClosure: (() async -> Result)? + + func isVerified() async -> Result { + isVerifiedCallsCount += 1 + if let isVerifiedClosure = isVerifiedClosure { + return await isVerifiedClosure() + } else { + return isVerifiedReturnValue + } + } //MARK: - requestVerification var requestVerificationCallsCount = 0 diff --git a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift index ae659fbd9..2a3aebbd6 100644 --- a/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/SDKGeneratedMocks.swift @@ -165,6 +165,23 @@ class SDKClientMock: SDKClientProtocol { return displayNameReturnValue } } + //MARK: - encryption + + public var encryptionCallsCount = 0 + public var encryptionCalled: Bool { + return encryptionCallsCount > 0 + } + public var encryptionReturnValue: Encryption! + public var encryptionClosure: (() -> Encryption)? + + public func encryption() -> Encryption { + encryptionCallsCount += 1 + if let encryptionClosure = encryptionClosure { + return encryptionClosure() + } else { + return encryptionReturnValue + } + } //MARK: - getDmRoom public var getDmRoomUserIdThrowableError: Error? diff --git a/ElementX/Sources/Mocks/SessionVerificationControllerProxyMock.swift b/ElementX/Sources/Mocks/SessionVerificationControllerProxyMock.swift index c747e3927..36aaba3cb 100644 --- a/ElementX/Sources/Mocks/SessionVerificationControllerProxyMock.swift +++ b/ElementX/Sources/Mocks/SessionVerificationControllerProxyMock.swift @@ -30,7 +30,7 @@ extension SessionVerificationControllerProxyMock { requestDelay: Duration = .seconds(1)) -> SessionVerificationControllerProxyMock { let mock = SessionVerificationControllerProxyMock() mock.underlyingCallbacks = callbacks - mock.underlyingIsVerified = isVerified + mock.isVerifiedReturnValue = .success(isVerified) mock.requestVerificationClosure = { [unowned mock] in Task.detached { diff --git a/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenModels.swift b/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenModels.swift index 1a65c55dd..da7053e04 100644 --- a/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenModels.swift @@ -41,7 +41,7 @@ struct SettingsScreenViewState: BindableState { var accountSessionsListURL: URL? var userAvatarURL: URL? var userDisplayName: String? - var isSessionVerified: Bool + var isSessionVerified = false var chatBackupEnabled = false var showSecureBackupBadge = false var showAppLockSettings: Bool diff --git a/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenViewModel.swift b/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenViewModel.swift index b3716af3c..3081b59f4 100644 --- a/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenViewModel.swift +++ b/ElementX/Sources/Screens/Settings/SettingsScreen/SettingsScreenViewModel.swift @@ -33,16 +33,10 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo self.userSession = userSession self.appSettings = appSettings - var isSessionVerified = true - if let sessionVerificationController = userSession.sessionVerificationController { - isSessionVerified = sessionVerificationController.isVerified - } - super.init(initialViewState: .init(deviceID: userSession.deviceID, userID: userSession.userID, accountProfileURL: userSession.clientProxy.accountURL(action: .profile), accountSessionsListURL: userSession.clientProxy.accountURL(action: .sessionsList), - isSessionVerified: isSessionVerified, showAppLockSettings: appSettings.appLockFlowEnabled, showDeveloperOptions: appSettings.canShowDeveloperOptions), imageProvider: userSession.mediaProvider) @@ -77,6 +71,11 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo Task { await userSession.clientProxy.loadUserAvatarURL() await userSession.clientProxy.loadUserDisplayName() + + if let sessionVerificationController = userSession.sessionVerificationController, + case let .success(isVerified) = await sessionVerificationController.isVerified() { + state.isSessionVerified = isVerified + } } userSession.callbacks diff --git a/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift b/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift index a248d4427..7bdc4b43f 100644 --- a/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift +++ b/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift @@ -247,7 +247,7 @@ private extension TimelineStyle { struct SettingsScreen_Previews: PreviewProvider, TestablePreview { static let viewModel = { let verificationController = SessionVerificationControllerProxyMock() - verificationController.isVerified = false + verificationController.isVerifiedReturnValue = .success(false) let userSession = MockUserSession(sessionVerificationController: verificationController, clientProxy: MockClientProxy(userID: "@userid:example.com", deviceID: "AAAAAAAAAAA"), diff --git a/ElementX/Sources/Services/Session/UserSession.swift b/ElementX/Sources/Services/Session/UserSession.swift index 91c290091..bc503f4d2 100644 --- a/ElementX/Sources/Services/Session/UserSession.swift +++ b/ElementX/Sources/Services/Session/UserSession.swift @@ -57,9 +57,14 @@ class UserSession: UserSessionProtocol { Task { switch await clientProxy.sessionVerificationControllerProxy() { case .success(let sessionVerificationController): + guard case let .success(isVerified) = await sessionVerificationController.isVerified() else { + MXLog.error("Failed checking verification state. Will retry on the next sync update.") + return + } + tearDownSessionVerificationControllerWatchdog() - if !sessionVerificationController.isVerified { + if !isVerified { callbacks.send(.sessionVerificationNeeded) } diff --git a/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxy.swift b/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxy.swift index 4757f35c2..533278a51 100644 --- a/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxy.swift +++ b/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxy.swift @@ -65,8 +65,13 @@ class SessionVerificationControllerProxy: SessionVerificationControllerProxyProt let callbacks = PassthroughSubject() - var isVerified: Bool { - sessionVerificationController.isVerified() + func isVerified() async -> Result { + do { + let result = try await sessionVerificationController.isVerified() + return .success(result) + } catch { + return .failure(.failedCheckingVerificationState) + } } func requestVerification() async -> Result { diff --git a/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxyProtocol.swift b/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxyProtocol.swift index a4fc7428b..4d301a872 100644 --- a/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxyProtocol.swift +++ b/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxyProtocol.swift @@ -18,6 +18,7 @@ import Combine import Foundation enum SessionVerificationControllerProxyError: Error { + case failedCheckingVerificationState case failedRequestingVerification case failedStartingSasVerification case failedApprovingVerification @@ -43,7 +44,7 @@ struct SessionVerificationEmoji: Hashable { protocol SessionVerificationControllerProxyProtocol { var callbacks: PassthroughSubject { get } - var isVerified: Bool { get } + func isVerified() async -> Result func requestVerification() async -> Result diff --git a/project.yml b/project.yml index 69cd46d59..f2ae62e8a 100644 --- a/project.yml +++ b/project.yml @@ -45,7 +45,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/matrix-org/matrix-rust-components-swift - exactVersion: 1.1.26 + exactVersion: 0.0.1-october23 # path: ../matrix-rust-sdk Compound: url: https://github.com/vector-im/compound-ios