Skip to content

Commit

Permalink
Merge pull request #7083 from vector-im/alfogrillo/sessions_without_e…
Browse files Browse the repository at this point in the history
…ncryption_support

Sessions without encryption support (PSG-1003)
  • Loading branch information
Alfonso Grillo authored Nov 18, 2022
2 parents 47e9a53 + 6b01a72 commit 89fc973
Show file tree
Hide file tree
Showing 15 changed files with 66 additions and 20 deletions.
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
}
}
}

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.

0 comments on commit 89fc973

Please sign in to comment.