Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sessions without encryption support (PSG-1003) #7083

Merged
merged 6 commits into from
Nov 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Riot/Assets/en.lproj/Vector.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2444,6 +2444,7 @@ To enable access, tap Settings> Location and select Always";
"user_session_unverified_additional_info" = "Verify your current session for enhanced secure messaging.";
"user_session_verification_unknown_additional_info" = "Verify your current session to reveal this session's verification status.";
"user_other_session_unverified_additional_info" = "Verify or sign out from this session for best security and reliability.";
"user_other_session_permanently_unverified_additional_info" = "This session cannot be verified because it does not support encryption.";
"user_other_session_verified_additional_info" = "This session is ready for secure messaging.";
"user_session_push_notifications" = "Push notifications";
"user_session_push_notifications_message" = "When turned on, this session will receive push notifications.";
Expand Down
4 changes: 4 additions & 0 deletions Riot/Generated/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8699,6 +8699,10 @@ public class VectorL10n: NSObject {
public static var userOtherSessionNoVerifiedSessions: String {
return VectorL10n.tr("Vector", "user_other_session_no_verified_sessions")
}
/// This session cannot be verified because it does not support encryption.
public static var userOtherSessionPermanentlyUnverifiedAdditionalInfo: String {
return VectorL10n.tr("Vector", "user_other_session_permanently_unverified_additional_info")
}
/// Security recommendation
public static var userOtherSessionSecurityRecommendationTitle: String {
return VectorL10n.tr("Vector", "user_other_session_security_recommendation_title")
Expand Down
6 changes: 6 additions & 0 deletions RiotSwiftUI/Modules/UserSessions/Common/UserSessionInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ struct UserSessionInfo: Identifiable {
case unverified
/// The session has been verified.
case verified
/// A session which cannot be never verified due to lack of crypto support
case permanentlyUnverified

var isUnverified: Bool {
self == .unverified || self == .permanentlyUnverified
}
}
Velin92 marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ struct DeviceAvatarViewData: Hashable {
switch verificationState {
case .verified:
return Asset.Images.userSessionVerified.name
case .unverified:
case .unverified, .permanentlyUnverified:
return Asset.Images.userSessionUnverified.name
case .unknown:
return Asset.Images.userSessionVerificationUnknown.name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct UserSessionCardViewData {
switch verificationState {
case .verified:
return Asset.Images.userSessionVerified.name
case .unverified:
case .unverified, .permanentlyUnverified:
return Asset.Images.userSessionUnverified.name
case .unknown:
return Asset.Images.userSessionVerificationUnknown.name
Expand All @@ -59,7 +59,7 @@ struct UserSessionCardViewData {
switch verificationState {
case .verified:
return VectorL10n.userSessionVerified
case .unverified:
case .unverified, .permanentlyUnverified:
return VectorL10n.userSessionUnverified
case .unknown:
return VectorL10n.userSessionVerificationUnknown
Expand All @@ -71,7 +71,7 @@ struct UserSessionCardViewData {
switch verificationState {
case .verified:
return \.accent
case .unverified:
case .unverified, .permanentlyUnverified:
return \.alert
case .unknown:
return \.secondaryContent
Expand All @@ -85,6 +85,8 @@ struct UserSessionCardViewData {
return isCurrentSessionDisplayMode ? VectorL10n.userSessionVerifiedAdditionalInfo : VectorL10n.userOtherSessionVerifiedAdditionalInfo + " %@"
case .unverified:
return isCurrentSessionDisplayMode ? VectorL10n.userSessionUnverifiedAdditionalInfo : VectorL10n.userOtherSessionUnverifiedAdditionalInfo + " %@"
case .permanentlyUnverified:
return VectorL10n.userOtherSessionPermanentlyUnverifiedAdditionalInfo
case .unknown:
return VectorL10n.userSessionVerificationUnknownAdditionalInfo
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ private extension InfoSheetCoordinatorParameters {
private extension UserSessionInfo {
var bottomSheetTitle: String {
switch verificationState {
case .unverified:
case .unverified, .permanentlyUnverified:
return VectorL10n.userSessionUnverifiedSessionTitle
case .verified:
return VectorL10n.userSessionVerifiedSessionTitle
Expand All @@ -476,7 +476,7 @@ private extension UserSessionInfo {

var bottomSheetDescription: String {
switch verificationState {
case .unverified:
case .unverified, .permanentlyUnverified:
return VectorL10n.userSessionUnverifiedSessionDescription
case .verified:
return VectorL10n.userSessionVerifiedSessionDescription
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,15 @@ class UserOtherSessionsViewModelTests: XCTestCase {

func test_whenModelCreated_withUnverifiedFilter_viewStateIsCorrect() {
let sessionInfos = [createUserSessionInfo(sessionId: "session 1"),
createUserSessionInfo(sessionId: "session 2")]
createUserSessionInfo(sessionId: "session 2", verificationState: .permanentlyUnverified),
createUserSessionInfo(sessionId: "session 3", verificationState: .unknown)]
let sut = createSUT(sessionInfos: sessionInfos, filter: .unverified)

let expectedItems = sessionInfos.filter { !$0.isCurrent }.asViewData()
let expectedItems = sessionInfos
.filter {
!$0.isCurrent && $0.verificationState.isUnverified
}
.asViewData()
let bindings = UserOtherSessionsBindings(filter: .unverified, isEditModeEnabled: false)
let expectedState = UserOtherSessionsViewState(bindings: bindings,
title: "Title",
Expand All @@ -100,12 +105,13 @@ class UserOtherSessionsViewModelTests: XCTestCase {
allItemsSelected: false,
enableSignOutButton: false,
showLocationInfo: false)
XCTAssertEqual(expectedItems.count, 2)
XCTAssertEqual(sut.state, expectedState)
}

func test_whenModelCreated_withVerifiedFilter_viewStateIsCorrect() {
let sessionInfos = [createUserSessionInfo(sessionId: "session 1", isVerified: true),
createUserSessionInfo(sessionId: "session 2", isVerified: true)]
let sessionInfos = [createUserSessionInfo(sessionId: "session 1", verificationState: .verified),
createUserSessionInfo(sessionId: "session 2", verificationState: .verified)]
let sut = createSUT(sessionInfos: sessionInfos, filter: .verified)

let expectedItems = sessionInfos.filter { !$0.isCurrent }.asViewData()
Expand All @@ -122,8 +128,8 @@ class UserOtherSessionsViewModelTests: XCTestCase {
}

func test_whenModelCreated_withVerifiedFilterWithNoVerifiedSessions_viewStateIsCorrect() {
let sessionInfos = [createUserSessionInfo(sessionId: "session 1", isVerified: false),
createUserSessionInfo(sessionId: "session 2", isVerified: false)]
let sessionInfos = [createUserSessionInfo(sessionId: "session 1"),
createUserSessionInfo(sessionId: "session 2")]
let sut = createSUT(sessionInfos: sessionInfos, filter: .verified)
let bindings = UserOtherSessionsBindings(filter: .verified, isEditModeEnabled: false)
let expectedState = UserOtherSessionsViewState(bindings: bindings,
Expand All @@ -138,8 +144,8 @@ class UserOtherSessionsViewModelTests: XCTestCase {
}

func test_whenModelCreated_withUnverifiedFilterWithNoUnverifiedSessions_viewStateIsCorrect() {
let sessionInfos = [createUserSessionInfo(sessionId: "session 1", isVerified: true),
createUserSessionInfo(sessionId: "session 2", isVerified: true)]
let sessionInfos = [createUserSessionInfo(sessionId: "session 1", verificationState: .verified),
createUserSessionInfo(sessionId: "session 2", verificationState: .verified)]
let sut = createSUT(sessionInfos: sessionInfos, filter: .unverified)
let bindings = UserOtherSessionsBindings(filter: .unverified, isEditModeEnabled: false)
let expectedState = UserOtherSessionsViewState(bindings: bindings,
Expand Down Expand Up @@ -350,13 +356,13 @@ class UserOtherSessionsViewModelTests: XCTestCase {
}

private func createUserSessionInfo(sessionId: String,
isVerified: Bool = false,
verificationState: UserSessionInfo.VerificationState = .unverified,
isActive: Bool = true,
isCurrent: Bool = false) -> UserSessionInfo {
UserSessionInfo(id: sessionId,
name: "iOS",
deviceType: .mobile,
verificationState: isVerified ? .verified : .unverified,
verificationState: verificationState,
lastSeenIP: "10.0.0.10",
lastSeenTimestamp: Date().timeIntervalSince1970 - 100,
applicationName: nil,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ private extension UserOtherSessionsFilter {
case .inactive:
return sessionInfos.filter { !$0.isActive }
case .unverified:
return sessionInfos.filter { $0.verificationState != .verified }
return sessionInfos.filter { $0.verificationState.isUnverified }
case .verified:
return sessionInfos.filter { $0.verificationState == .verified }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ enum MockUserSessionOverviewScreenState: MockScreenState, CaseIterable {
.currentSession(sessionState: .verified),
.otherSession(sessionState: .verified),
.otherSession(sessionState: .unverified),
.otherSession(sessionState: .permanentlyUnverified),
.sessionWithPushNotifications(enabled: true),
.sessionWithPushNotifications(enabled: false),
.remotelyTogglingPushersNotAvailable]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,9 @@ class UserSessionOverviewUITests: MockScreenTestCase {
let button = app.buttons[buttonId]
XCTAssertTrue(button.exists)
}

func test_whenPermanentlySessionSelected_copyIsCorrect() {
app.goToScreenWithIdentifier(MockUserSessionOverviewScreenState.otherSession(sessionState: .permanentlyUnverified).title)
XCTAssertTrue(app.buttons[VectorL10n.userOtherSessionPermanentlyUnverifiedAdditionalInfo].exists)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ class UserSessionsDataProvider: UserSessionsDataProviderProtocol {
}

func verificationState(for deviceInfo: MXDeviceInfo?) -> UserSessionInfo.VerificationState {
guard let deviceInfo = deviceInfo else { return .unknown }
guard let deviceInfo = deviceInfo else {
return .permanentlyUnverified
}

guard session.crypto?.crossSigning.canCrossSign == true else {
return deviceInfo.deviceId == session.myDeviceId ? .unverified : .unknown
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class UserSessionsOverviewService: UserSessionsOverviewServiceProtocol {
private func sessionsOverviewData(from allSessions: [UserSessionInfo],
linkDeviceEnabled: Bool) -> UserSessionsOverviewData {
UserSessionsOverviewData(currentSession: allSessions.filter(\.isCurrent).first,
unverifiedSessions: allSessions.filter { $0.verificationState == .unverified && !$0.isCurrent },
unverifiedSessions: allSessions.filter { $0.verificationState.isUnverified && !$0.isCurrent },
inactiveSessions: allSessions.filter { !$0.isActive },
otherSessions: allSessions.filter { !$0.isCurrent },
linkDeviceEnabled: linkDeviceEnabled)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ struct UserSessionListItemViewDataFactory {
switch sessionInfo.verificationState {
case .verified:
sessionStatusText = VectorL10n.userSessionVerifiedShort
case .unverified:
case .unverified, .permanentlyUnverified:
sessionStatusText = VectorL10n.userSessionUnverifiedShort
case .unknown:
sessionStatusText = nil
Expand Down
18 changes: 18 additions & 0 deletions RiotTests/UserSessionsDataProviderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,24 @@ class UserSessionCardViewDataTests: XCTestCase {
XCTAssertEqual(verificationStateVerified, .unverified)
XCTAssertEqual(verificationStateUnverified, .unverified)
}

func testDeviceNotHavingCryptoSupportOnVerifiedDevice() {
let mxSession = MockSession(canCrossSign: true)
let dataProvider = UserSessionsDataProvider(session: mxSession)

let verificationState = dataProvider.verificationState(for: nil)

XCTAssertEqual(verificationState, .permanentlyUnverified)
}

func testDeviceNotHavingCryptoSupportOnUnverifiedDevice() {
let mxSession = MockSession(canCrossSign: false)
let dataProvider = UserSessionsDataProvider(session: mxSession)

let verificationState = dataProvider.verificationState(for: nil)

XCTAssertEqual(verificationState, .permanentlyUnverified)
}
}

// MARK: Mocks
Expand Down
1 change: 1 addition & 0 deletions changelog.d/pr-7083.change
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support in the new Device Manager to sessions without crypto support.