diff --git a/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift index 3d6283d6d..e8f860fae 100644 --- a/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/AuthenticationFlowCoordinator.swift @@ -126,8 +126,7 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol { bugReportFlowCoordinator = BugReportFlowCoordinator(parameters: .init(presentationMode: .sheet(navigationStackCoordinator), userIndicatorController: userIndicatorController, bugReportService: bugReportService, - userID: nil, - deviceID: nil)) + userSession: nil)) bugReportFlowCoordinator?.start() } diff --git a/ElementX/Sources/FlowCoordinators/BugReportFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/BugReportFlowCoordinator.swift index 298a37617..e5a7f9ab4 100644 --- a/ElementX/Sources/FlowCoordinators/BugReportFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/BugReportFlowCoordinator.swift @@ -25,8 +25,7 @@ struct BugReportFlowCoordinatorParameters { let presentationMode: PresentationMode let userIndicatorController: UserIndicatorControllerProtocol let bugReportService: BugReportServiceProtocol - let userID: String? - let deviceID: String? + let userSession: UserSessionProtocol? } class BugReportFlowCoordinator: FlowCoordinatorProtocol { @@ -64,8 +63,7 @@ class BugReportFlowCoordinator: FlowCoordinatorProtocol { private func presentBugReportScreen() { let params = BugReportScreenCoordinatorParameters(bugReportService: parameters.bugReportService, - userID: parameters.userID, - deviceID: parameters.deviceID, + userSession: parameters.userSession, userIndicatorController: parameters.userIndicatorController, screenshot: nil, isModallyPresented: isModallyPresented) diff --git a/ElementX/Sources/FlowCoordinators/SettingsFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/SettingsFlowCoordinator.swift index 269da0a72..6e962f606 100644 --- a/ElementX/Sources/FlowCoordinators/SettingsFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/SettingsFlowCoordinator.swift @@ -123,8 +123,7 @@ class SettingsFlowCoordinator: FlowCoordinatorProtocol { bugReportFlowCoordinator = BugReportFlowCoordinator(parameters: .init(presentationMode: .push(navigationStackCoordinator), userIndicatorController: parameters.userIndicatorController, bugReportService: parameters.bugReportService, - userID: parameters.userSession.userID, - deviceID: parameters.userSession.deviceID)) + userSession: parameters.userSession)) bugReportFlowCoordinator?.start() case .about: presentLegalInformationScreen() diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index 092c7c269..08e750443 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -307,8 +307,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { bugReportFlowCoordinator = BugReportFlowCoordinator(parameters: .init(presentationMode: .sheet(sidebarNavigationStackCoordinator), userIndicatorController: ServiceLocator.shared.userIndicatorController, bugReportService: bugReportService, - userID: userSession.userID, - deviceID: userSession.deviceID)) + userSession: userSession)) bugReportFlowCoordinator?.start() case (.feedbackScreen, .dismissedFeedbackScreen, .roomList): break diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index d7f4a7646..9bc5bb417 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -3799,6 +3799,134 @@ class ClientProxyMock: ClientProxyProtocol { return recentConversationCounterpartsReturnValue } } + //MARK: - ed25519Base64 + + var ed25519Base64UnderlyingCallsCount = 0 + var ed25519Base64CallsCount: Int { + get { + if Thread.isMainThread { + return ed25519Base64UnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = ed25519Base64UnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + ed25519Base64UnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + ed25519Base64UnderlyingCallsCount = newValue + } + } + } + } + var ed25519Base64Called: Bool { + return ed25519Base64CallsCount > 0 + } + + var ed25519Base64UnderlyingReturnValue: String? + var ed25519Base64ReturnValue: String? { + get { + if Thread.isMainThread { + return ed25519Base64UnderlyingReturnValue + } else { + var returnValue: String?? = nil + DispatchQueue.main.sync { + returnValue = ed25519Base64UnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + ed25519Base64UnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + ed25519Base64UnderlyingReturnValue = newValue + } + } + } + } + var ed25519Base64Closure: (() async -> String?)? + + func ed25519Base64() async -> String? { + ed25519Base64CallsCount += 1 + if let ed25519Base64Closure = ed25519Base64Closure { + return await ed25519Base64Closure() + } else { + return ed25519Base64ReturnValue + } + } + //MARK: - curve25519Base64 + + var curve25519Base64UnderlyingCallsCount = 0 + var curve25519Base64CallsCount: Int { + get { + if Thread.isMainThread { + return curve25519Base64UnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = curve25519Base64UnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + curve25519Base64UnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + curve25519Base64UnderlyingCallsCount = newValue + } + } + } + } + var curve25519Base64Called: Bool { + return curve25519Base64CallsCount > 0 + } + + var curve25519Base64UnderlyingReturnValue: String? + var curve25519Base64ReturnValue: String? { + get { + if Thread.isMainThread { + return curve25519Base64UnderlyingReturnValue + } else { + var returnValue: String?? = nil + DispatchQueue.main.sync { + returnValue = curve25519Base64UnderlyingReturnValue + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + curve25519Base64UnderlyingReturnValue = newValue + } else { + DispatchQueue.main.sync { + curve25519Base64UnderlyingReturnValue = newValue + } + } + } + } + var curve25519Base64Closure: (() async -> String?)? + + func curve25519Base64() async -> String? { + curve25519Base64CallsCount += 1 + if let curve25519Base64Closure = curve25519Base64Closure { + return await curve25519Base64Closure() + } else { + return curve25519Base64ReturnValue + } + } //MARK: - loadMediaContentForSource var loadMediaContentForSourceThrowableError: Error? diff --git a/ElementX/Sources/Screens/BugReportScreen/BugReportScreenCoordinator.swift b/ElementX/Sources/Screens/BugReportScreen/BugReportScreenCoordinator.swift index 3c89c82c6..f69bfa593 100644 --- a/ElementX/Sources/Screens/BugReportScreen/BugReportScreenCoordinator.swift +++ b/ElementX/Sources/Screens/BugReportScreen/BugReportScreenCoordinator.swift @@ -25,8 +25,7 @@ enum BugReportScreenCoordinatorAction { struct BugReportScreenCoordinatorParameters { let bugReportService: BugReportServiceProtocol - let userID: String? - let deviceID: String? + let userSession: UserSessionProtocol? let userIndicatorController: UserIndicatorControllerProtocol? let screenshot: UIImage? @@ -47,8 +46,7 @@ final class BugReportScreenCoordinator: CoordinatorProtocol { self.parameters = parameters viewModel = BugReportScreenViewModel(bugReportService: parameters.bugReportService, - userID: parameters.userID, - deviceID: parameters.deviceID, + clientProxy: parameters.userSession?.clientProxy, screenshot: parameters.screenshot, isModallyPresented: parameters.isModallyPresented) } diff --git a/ElementX/Sources/Screens/BugReportScreen/BugReportScreenViewModel.swift b/ElementX/Sources/Screens/BugReportScreen/BugReportScreenViewModel.swift index 506b4eeee..085836b92 100644 --- a/ElementX/Sources/Screens/BugReportScreen/BugReportScreenViewModel.swift +++ b/ElementX/Sources/Screens/BugReportScreen/BugReportScreenViewModel.swift @@ -21,8 +21,7 @@ typealias BugReportScreenViewModelType = StateStoreViewModel = .init() // periphery:ignore - when set to nil this is automatically cancelled @@ -33,13 +32,11 @@ class BugReportScreenViewModel: BugReportScreenViewModelType, BugReportScreenVie } init(bugReportService: BugReportServiceProtocol, - userID: String?, - deviceID: String?, + clientProxy: ClientProxyProtocol?, screenshot: UIImage?, isModallyPresented: Bool) { self.bugReportService = bugReportService - self.userID = userID - self.deviceID = deviceID + self.clientProxy = clientProxy let bindings = BugReportScreenViewStateBindings(reportText: "", sendingLogsEnabled: true, canContact: false) super.init(initialViewState: BugReportScreenViewState(screenshot: screenshot, @@ -86,8 +83,12 @@ class BugReportScreenViewModel: BugReportScreenViewModelType, BugReportScreenVie // Continue anyway without the screenshot. } } - let bugReport = BugReport(userID: userID, - deviceID: deviceID, + let ed25519 = await clientProxy?.ed25519Base64() + let curve25519 = await clientProxy?.curve25519Base64() + let bugReport = BugReport(userID: clientProxy?.userID, + deviceID: clientProxy?.deviceID, + ed25519: ed25519, + curve25519: curve25519, text: context.reportText, includeLogs: context.sendingLogsEnabled, canContact: context.canContact, diff --git a/ElementX/Sources/Screens/BugReportScreen/View/BugReportScreen.swift b/ElementX/Sources/Screens/BugReportScreen/View/BugReportScreen.swift index 7cb4eaf80..ebaaf8460 100644 --- a/ElementX/Sources/Screens/BugReportScreen/View/BugReportScreen.swift +++ b/ElementX/Sources/Screens/BugReportScreen/View/BugReportScreen.swift @@ -149,18 +149,18 @@ struct BugReportScreen: View { struct BugReport_Previews: PreviewProvider, TestablePreview { static var previews: some View { NavigationStack { + let clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))))) BugReportScreen(context: BugReportScreenViewModel(bugReportService: BugReportServiceMock(), - userID: "@mock.client.com", - deviceID: nil, + clientProxy: clientProxy, screenshot: nil, isModallyPresented: false).context) .previewDisplayName("Without Screenshot") } NavigationStack { + let clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))))) BugReportScreen(context: BugReportScreenViewModel(bugReportService: BugReportServiceMock(), - userID: "@mock.client.com", - deviceID: nil, + clientProxy: clientProxy, screenshot: Asset.Images.appLogo.image, isModallyPresented: false).context) .previewDisplayName("With Screenshot") diff --git a/ElementX/Sources/Services/BugReport/BugReportService.swift b/ElementX/Sources/Services/BugReport/BugReportService.swift index 2198675d9..ca8ab5b65 100644 --- a/ElementX/Sources/Services/BugReport/BugReportService.swift +++ b/ElementX/Sources/Services/BugReport/BugReportService.swift @@ -127,6 +127,11 @@ class BugReportService: NSObject, BugReportServiceProtocol { params.append(.init(key: "device_id", type: .text(value: deviceID))) } + if let ed25519 = bugReport.ed25519, let curve25519 = bugReport.curve25519 { + let compactKeys = "curve25519:\(curve25519), ed25519:\(ed25519)" + params.append(.init(key: "device_keys", type: .text(value: compactKeys))) + } + params.append(contentsOf: defaultParams) for label in bugReport.githubLabels { diff --git a/ElementX/Sources/Services/BugReport/BugReportServiceProtocol.swift b/ElementX/Sources/Services/BugReport/BugReportServiceProtocol.swift index 5a2f4d7d1..dae5f1661 100644 --- a/ElementX/Sources/Services/BugReport/BugReportServiceProtocol.swift +++ b/ElementX/Sources/Services/BugReport/BugReportServiceProtocol.swift @@ -21,6 +21,8 @@ import UIKit struct BugReport: Equatable { let userID: String? let deviceID: String? + let ed25519: String? + let curve25519: String? let text: String let includeLogs: Bool let canContact: Bool diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index d11e93fa8..310c3a198 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -803,6 +803,16 @@ class ClientProxy: ClientProxyProtocol { } } } + + // MARK: - Encryption + + func ed25519Base64() async -> String? { + await client.encryption().ed25519Key() + } + + func curve25519Base64() async -> String? { + await client.encryption().curve25519Key() + } } extension ClientProxy: MediaLoaderProtocol { diff --git a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift index 71b7f3115..0f051aa41 100644 --- a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift +++ b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift @@ -174,4 +174,9 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { func recentlyVisitedRooms() async -> Result<[String], ClientProxyError> func recentConversationCounterparts() async -> [UserProfileProxy] + + // MARK: - Encryption Info + + func ed25519Base64() async -> String? + func curve25519Base64() async -> String? } diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index d2f9ee2d2..48ce37f8f 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -228,9 +228,12 @@ class MockScreen: Identifiable { return navigationStackCoordinator case .bugReport: let navigationStackCoordinator = NavigationStackCoordinator() + let clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))))) + let userSession = MockUserSession(clientProxy: clientProxy, + mediaProvider: MockMediaProvider(), + voiceMessageMediaManager: VoiceMessageMediaManagerMock()) let coordinator = BugReportScreenCoordinator(parameters: .init(bugReportService: BugReportServiceMock(), - userID: "@mock:client.com", - deviceID: nil, + userSession: userSession, userIndicatorController: nil, screenshot: nil, isModallyPresented: true)) diff --git a/UnitTests/Sources/BugReportServiceTests.swift b/UnitTests/Sources/BugReportServiceTests.swift index 1e3564036..59415bc65 100644 --- a/UnitTests/Sources/BugReportServiceTests.swift +++ b/UnitTests/Sources/BugReportServiceTests.swift @@ -37,6 +37,8 @@ class BugReportServiceTests: XCTestCase { func testSubmitBugReportWithMockService() async throws { let bugReport = BugReport(userID: "@mock:client.com", deviceID: nil, + ed25519: nil, + curve25519: nil, text: "i cannot send message", includeLogs: true, canContact: false, @@ -67,6 +69,8 @@ class BugReportServiceTests: XCTestCase { let bugReport = BugReport(userID: "@mock:client.com", deviceID: nil, + ed25519: nil, + curve25519: nil, text: "i cannot send message", includeLogs: true, canContact: false, diff --git a/UnitTests/Sources/BugReportViewModelTests.swift b/UnitTests/Sources/BugReportViewModelTests.swift index 82265b974..cafe2ff59 100644 --- a/UnitTests/Sources/BugReportViewModelTests.swift +++ b/UnitTests/Sources/BugReportViewModelTests.swift @@ -25,9 +25,9 @@ class BugReportViewModelTests: XCTestCase { } func testInitialState() { + let clientProxy = ClientProxyMock(.init(userID: "@mock.client.com")) let viewModel = BugReportScreenViewModel(bugReportService: BugReportServiceMock(), - userID: "@mock.client.com", - deviceID: nil, + clientProxy: clientProxy, screenshot: nil, isModallyPresented: false) let context = viewModel.context @@ -38,9 +38,9 @@ class BugReportViewModelTests: XCTestCase { } func testClearScreenshot() async throws { + let clientProxy = ClientProxyMock(.init(userID: "@mock.client.com")) let viewModel = BugReportScreenViewModel(bugReportService: BugReportServiceMock(), - userID: "@mock.client.com", - deviceID: nil, + clientProxy: clientProxy, screenshot: UIImage.actions, isModallyPresented: false) let context = viewModel.context @@ -50,9 +50,9 @@ class BugReportViewModelTests: XCTestCase { } func testAttachScreenshot() async throws { + let clientProxy = ClientProxyMock(.init(userID: "@mock.client.com")) let viewModel = BugReportScreenViewModel(bugReportService: BugReportServiceMock(), - userID: "@mock.client.com", - deviceID: nil, + clientProxy: clientProxy, screenshot: nil, isModallyPresented: false) let context = viewModel.context XCTAssertNil(context.viewState.screenshot) @@ -66,9 +66,13 @@ class BugReportViewModelTests: XCTestCase { await Task.yield() return .success(SubmitBugReportResponse(reportUrl: "https://test.test")) } + + let clientProxy = ClientProxyMock(.init(userID: "@mock.client.com", deviceID: "ABCDEFGH")) + clientProxy.ed25519Base64ReturnValue = "THEEDKEYKEY" + clientProxy.curve25519Base64ReturnValue = "THECURVEKEYKEY" + let viewModel = BugReportScreenViewModel(bugReportService: mockService, - userID: "@mock.client.com", - deviceID: nil, + clientProxy: clientProxy, screenshot: nil, isModallyPresented: false) let context = viewModel.context @@ -86,7 +90,9 @@ class BugReportViewModelTests: XCTestCase { XCTAssert(mockService.submitBugReportProgressListenerCallsCount == 1) XCTAssertEqual(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.userID, "@mock.client.com") - XCTAssertEqual(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.deviceID, nil) + XCTAssertEqual(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.deviceID, "ABCDEFGH") + XCTAssertEqual(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.curve25519, "THECURVEKEYKEY") + XCTAssertEqual(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.ed25519, "THEEDKEYKEY") XCTAssertEqual(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.text, "") XCTAssertEqual(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.includeLogs, true) XCTAssertEqual(mockService.submitBugReportProgressListenerReceivedArguments?.bugReport.canContact, false) @@ -99,9 +105,10 @@ class BugReportViewModelTests: XCTestCase { mockService.submitBugReportProgressListenerClosure = { _, _ in .failure(.uploadFailure(TestError.testError)) } + + let clientProxy = ClientProxyMock(.init(userID: "@mock.client.com")) let viewModel = BugReportScreenViewModel(bugReportService: mockService, - userID: "@mock.client.com", - deviceID: nil, + clientProxy: clientProxy, screenshot: nil, isModallyPresented: false) let deferred = deferFulfillment(viewModel.actions) { action in diff --git a/changelog.d/2550.misc b/changelog.d/2550.misc new file mode 100644 index 000000000..69b2b7e3c --- /dev/null +++ b/changelog.d/2550.misc @@ -0,0 +1 @@ +Rageshake | Add device public curve25519 and ed25519 keys info to rageshake. \ No newline at end of file