From b730815842cdb7af65fd476531dade0abef9dcc7 Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Mon, 13 Jul 2026 14:03:15 +0200 Subject: [PATCH] disable creation and enabling of e2ee if remote preference for disabling it is true --- .../Sources/Application/Settings/AppSettings.swift | 7 +++++++ .../SecurityAndPrivacyScreenViewModel.swift | 2 +- ElementX/Sources/Services/Client/ClientProxy.swift | 4 ++-- Enterprise | 2 +- .../SecurityAndPrivacyScreenViewModelTests.swift | 13 ++++++++++++- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/ElementX/Sources/Application/Settings/AppSettings.swift b/ElementX/Sources/Application/Settings/AppSettings.swift index ac0e107d0..1360dd472 100644 --- a/ElementX/Sources/Application/Settings/AppSettings.swift +++ b/ElementX/Sources/Application/Settings/AppSettings.swift @@ -24,6 +24,7 @@ nonisolated protocol CommonSettingsProtocol: AnyObject, Sendable { var traceLogPacks: Set { get } var bugReportRageshakeURL: RemotePreference { get } var contentScannerURL: RemotePreference { get } + var forceDisableE2EE: RemotePreference { get } var enableOnlySignedDeviceIsolationMode: Bool { get } var threadsEnabled: Bool { get } @@ -272,6 +273,12 @@ final nonisolated class AppSettings: @unchecked Sendable { /// `nil` when content scanning is disabled. let contentScannerURL: RemotePreference = .init(nil) + // MARK: - Encryption + + /// Whether the server forbids the use of E2EE: new rooms are created unencrypted and + /// enabling encryption on existing rooms is not offered. + let forceDisableE2EE: RemotePreference = .init(false) + // MARK: - Analytics /// The configuration to use for analytics. Set to `nil` to disable analytics. diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift index 6bc9bc93e..3398cf595 100644 --- a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift @@ -161,7 +161,7 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType, state.canEditAddress = powerLevels.canOwnUser(sendStateEvent: .roomCanonicalAlias) state.canEditJoinRule = powerLevels.canOwnUser(sendStateEvent: .roomJoinRules) state.canEditHistoryVisibility = powerLevels.canOwnUser(sendStateEvent: .roomHistoryVisibility) - state.canEnableEncryption = powerLevels.canOwnUser(sendStateEvent: .roomEncryption) + state.canEnableEncryption = powerLevels.canOwnUser(sendStateEvent: .roomEncryption) && !appSettings.forceDisableE2EE.publisher.value } private func setupRoomDirectoryVisibility() { diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index 9218f132d..cca900622 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -482,7 +482,7 @@ class ClientProxy: ClientProxyProtocol { do { let parameters = CreateRoomParameters(name: nil, topic: nil, - isEncrypted: true, + isEncrypted: !appSettings.forceDisableE2EE.publisher.value, isDirect: true, visibility: .private, preset: .trustedPrivateChat, @@ -525,7 +525,7 @@ class ClientProxy: ClientProxyProtocol { let parameters = CreateRoomParameters(name: name, topic: topic, - isEncrypted: accessType.isEncrypted, + isEncrypted: !appSettings.forceDisableE2EE.publisher.value && accessType.isEncrypted, isDirect: false, visibility: accessType.visibility, preset: accessType.preset, diff --git a/Enterprise b/Enterprise index ad5860711..5680a2d94 160000 --- a/Enterprise +++ b/Enterprise @@ -1 +1 @@ -Subproject commit ad58607116d14e5363d3c4ea409ffadfa0545f02 +Subproject commit 5680a2d94b8552bae4264a81b906a354ccdd877e diff --git a/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift b/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift index 3ffed9108..5080d9f89 100644 --- a/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift +++ b/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift @@ -434,13 +434,24 @@ final class SecurityAndPrivacyScreenViewModelTests { try await deferred.fulfill() } + @Test + func encryptionOptionAvailability() { + setupViewModel(joinedParentSpaces: [], joinRule: .public) + #expect(context.viewState.canEnableEncryption) + + setupViewModel(joinedParentSpaces: [], joinRule: .public, forceDisableE2EE: true) + #expect(!context.viewState.canEnableEncryption) + } + // MARK: - Helpers private func setupViewModel(joinedParentSpaces: [SpaceServiceRoom], topLevelSpaces: [SpaceServiceRoom] = [], - joinRule: ElementX.JoinRule) { + joinRule: ElementX.JoinRule, + forceDisableE2EE: Bool = false) { let appSettings = AppSettings.volatile() appSettings.knockingEnabled = true + appSettings.forceDisableE2EE.applyRemoteValue(forceDisableE2EE) roomProxy = JoinedRoomProxyMock(.init(isEncrypted: false, canonicalAlias: "#room:matrix.org", members: .allMembersAsCreator,