diff --git a/WireDomain/Sources/WireDomain/Helpers/BackendEnvironmment2+Mappings.swift b/WireDomain/Sources/WireDomain/Helpers/BackendEnvironmment2+Mappings.swift index edd9f905adb..86eb2c779cd 100644 --- a/WireDomain/Sources/WireDomain/Helpers/BackendEnvironmment2+Mappings.swift +++ b/WireDomain/Sources/WireDomain/Helpers/BackendEnvironmment2+Mappings.swift @@ -124,6 +124,8 @@ public extension WireNetwork.APIVersion { self = .v12 case .v13: self = .v13 + case .v14: + self = .v14 } } diff --git a/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/FeatureConfigModelMappings.swift b/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/FeatureConfigModelMappings.swift index e9dd4b9e52d..1bae05829ce 100644 --- a/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/FeatureConfigModelMappings.swift +++ b/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/FeatureConfigModelMappings.swift @@ -132,3 +132,11 @@ extension WireNetwork.ChannelsPermision { } } } + +extension WireNetwork.CellsInternalFeatureConfig { + func toDomainModel() -> Feature.CellsInternal.Config { + Feature.CellsInternal.Config( + backend: .init(url: backendURL) + ) + } +} diff --git a/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/FeatureConfigRepository.swift b/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/FeatureConfigRepository.swift index 2f1b4621029..2420aeb88dc 100644 --- a/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/FeatureConfigRepository.swift +++ b/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/FeatureConfigRepository.swift @@ -105,6 +105,13 @@ public final class FeatureConfigRepository: FeatureConfigRepositoryProtocol { ) } + public func fetchCellsInternal() async throws -> LocalFeature { + try await fetchFeatureConfig( + name: .cellsInternal, + type: Feature.CellsInternal.Config.self + ) + } + // MARK: - Private private func sendFeatureState(for featureConfig: FeatureConfig) async { @@ -223,6 +230,12 @@ public final class FeatureConfigRepository: FeatureConfigRepositoryProtocol { isEnabled: cellsConfig.status == .enabled ) + case let .cellsInternal(cellsInternalConfig): + return FeatureState( + name: .cellsInternal, + isEnabled: cellsInternalConfig.status == .enabled + ) + case let .unknown(featureName): logger.warn( "Unknown feature name: \(featureName)" diff --git a/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/Models/LocalFeature.swift b/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/Models/LocalFeature.swift index 10f020e4958..859c0d565c3 100644 --- a/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/Models/LocalFeature.swift +++ b/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/Models/LocalFeature.swift @@ -20,6 +20,6 @@ import WireDataModel /// A feature fetched locally public struct LocalFeature { - let status: Feature.Status - let config: T? + public let status: Feature.Status + public let config: T? } diff --git a/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/Protocols/FeatureConfigRepositoryProtocol.swift b/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/Protocols/FeatureConfigRepositoryProtocol.swift index e4c7d035119..b5c2d591d5a 100644 --- a/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/Protocols/FeatureConfigRepositoryProtocol.swift +++ b/WireDomain/Sources/WireDomain/Repositories/FeatureConfig/Protocols/FeatureConfigRepositoryProtocol.swift @@ -53,6 +53,7 @@ public protocol FeatureConfigRepositoryProtocol { func fetchMLSConfig() async throws -> LocalFeature func fetchMLSMigrationConfig() async throws -> LocalFeature func fetchAppLock() async throws -> LocalFeature + func fetchCellsInternal() async throws -> LocalFeature func isFeatureEnabled( _ feature: Feature.Name diff --git a/WireDomain/Sources/WireDomain/Synchronization/PullAllFeatureConfigsSync.swift b/WireDomain/Sources/WireDomain/Synchronization/PullAllFeatureConfigsSync.swift index 49f6f6049e8..0d00033deb8 100644 --- a/WireDomain/Sources/WireDomain/Synchronization/PullAllFeatureConfigsSync.swift +++ b/WireDomain/Sources/WireDomain/Synchronization/PullAllFeatureConfigsSync.swift @@ -143,6 +143,12 @@ extension FeatureConfigLocalStoreProtocol { isEnabled: config.status == .enabled, config: nil ) + case let .cellsInternal(config): + await storeFeature( + name: .cellsInternal, + isEnabled: config.status == .enabled, + config: config.toDomainModel() + ) case let .unknown(name): WireLogger.featureConfigs.warn("encountered unknown feature config '\(name)' when storing, skipping") return diff --git a/WireDomain/Sources/WireDomain/Synchronization/RepairFaultyMLSRemovalKeysGenerator.swift b/WireDomain/Sources/WireDomain/Synchronization/RepairFaultyMLSRemovalKeysGenerator.swift index aef79a6d5ce..60afeb1b58e 100644 --- a/WireDomain/Sources/WireDomain/Synchronization/RepairFaultyMLSRemovalKeysGenerator.swift +++ b/WireDomain/Sources/WireDomain/Synchronization/RepairFaultyMLSRemovalKeysGenerator.swift @@ -1,6 +1,6 @@ // // Wire -// Copyright (C) 2025 Wire Swiss GmbH +// Copyright (C) 2026 Wire Swiss GmbH // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/WireDomain/Sources/WireDomain/WorkAgent/WorkItem/RepairFaultyMLSRemovalKeysWorkItem.swift b/WireDomain/Sources/WireDomain/WorkAgent/WorkItem/RepairFaultyMLSRemovalKeysWorkItem.swift index a97ef38789d..e613f423af0 100644 --- a/WireDomain/Sources/WireDomain/WorkAgent/WorkItem/RepairFaultyMLSRemovalKeysWorkItem.swift +++ b/WireDomain/Sources/WireDomain/WorkAgent/WorkItem/RepairFaultyMLSRemovalKeysWorkItem.swift @@ -1,6 +1,6 @@ // // Wire -// Copyright (C) 2025 Wire Swiss GmbH +// Copyright (C) 2026 Wire Swiss GmbH // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/WireDomain/Sources/WireDomainSupport/Sourcery/generated/AutoMockable.generated.swift b/WireDomain/Sources/WireDomainSupport/Sourcery/generated/AutoMockable.generated.swift index 79acc19e766..94a5bd1e31d 100644 --- a/WireDomain/Sources/WireDomainSupport/Sourcery/generated/AutoMockable.generated.swift +++ b/WireDomain/Sources/WireDomainSupport/Sourcery/generated/AutoMockable.generated.swift @@ -2308,6 +2308,29 @@ public class MockFeatureConfigRepositoryProtocol: FeatureConfigRepositoryProtoco } } + // MARK: - fetchCellsInternal + + public var fetchCellsInternal_Invocations: [Void] = [] + public var fetchCellsInternal_MockError: Error? + public var fetchCellsInternal_MockMethod: (() async throws -> LocalFeature)? + public var fetchCellsInternal_MockValue: LocalFeature? + + public func fetchCellsInternal() async throws -> LocalFeature { + fetchCellsInternal_Invocations.append(()) + + if let error = fetchCellsInternal_MockError { + throw error + } + + if let mock = fetchCellsInternal_MockMethod { + return try await mock() + } else if let mock = fetchCellsInternal_MockValue { + return mock + } else { + fatalError("no mock for `fetchCellsInternal`") + } + } + // MARK: - isFeatureEnabled public var isFeatureEnabled_Invocations: [Feature.Name] = [] diff --git a/WireDomain/Sources/WireUpdateEventCoding/Models/FeatureConfigEvent/StorableFeatureConfigUpdateEvent.swift b/WireDomain/Sources/WireUpdateEventCoding/Models/FeatureConfigEvent/StorableFeatureConfigUpdateEvent.swift index c8a8c38f99b..f50c5d49b2d 100644 --- a/WireDomain/Sources/WireUpdateEventCoding/Models/FeatureConfigEvent/StorableFeatureConfigUpdateEvent.swift +++ b/WireDomain/Sources/WireUpdateEventCoding/Models/FeatureConfigEvent/StorableFeatureConfigUpdateEvent.swift @@ -147,6 +147,13 @@ struct StorableFeatureConfigUpdateEvent: Equatable, Codable, Sendable { ) ) ) + case let .cellsInternal(config): + .cellsInternal( + StorableCellsInternalFeatureConfig( + status: StorableFeatureConfigStatus(config.status), + backendURL: config.backendURL + ) + ) case let .unknown(featureName): .unknown(featureName: featureName) } @@ -265,6 +272,13 @@ struct StorableFeatureConfigUpdateEvent: Equatable, Codable, Sendable { .cells( .init(status: config.status.toAPIModel()) ) + case let .cellsInternal(config): + .cellsInternal( + .init( + status: config.status.toAPIModel(), + backendURL: config.backendURL + ) + ) case let .unknown(featureName): .unknown(featureName: featureName) } @@ -297,6 +311,7 @@ enum StorableFeatureConfig: Equatable, Codable, Sendable { case allowedGlobalOperations(StorableAllowedGlobalOperationsFeatureConfig) case consumableNotifications(StorableBasicFeatureConfig) case cells(StorableBasicFeatureConfig) + case cellsInternal(StorableCellsInternalFeatureConfig) case unknown(featureName: String) } @@ -437,3 +452,8 @@ struct StorableChannelsFeatureConfig: Codable, Equatable, Sendable { let allowedToOpenChannels: Permission } + +struct StorableCellsInternalFeatureConfig: Codable, Equatable, Sendable { + let status: StorableFeatureConfigStatus + let backendURL: URL +} diff --git a/WireDomain/Tests/WireDomainTests/Repositories/FeatureConfigRepositoryTests.swift b/WireDomain/Tests/WireDomainTests/Repositories/FeatureConfigRepositoryTests.swift index 92691441426..f86c4d8fe1b 100644 --- a/WireDomain/Tests/WireDomainTests/Repositories/FeatureConfigRepositoryTests.swift +++ b/WireDomain/Tests/WireDomainTests/Repositories/FeatureConfigRepositoryTests.swift @@ -279,6 +279,12 @@ final class FeatureConfigRepositoryTests: XCTestCase { ), .cells( .init(status: .enabled) + ), + .cellsInternal( + .init( + status: .enabled, + backendURL: URL(string: "https://wire.com")! + ) ) ] diff --git a/WireMessaging/Sources/WireMessagingAssembly/WireMessagingFactory.swift b/WireMessaging/Sources/WireMessagingAssembly/WireMessagingFactory.swift index f9b1eee7ddc..6e9ab69626f 100644 --- a/WireMessaging/Sources/WireMessagingAssembly/WireMessagingFactory.swift +++ b/WireMessaging/Sources/WireMessagingAssembly/WireMessagingFactory.swift @@ -27,6 +27,8 @@ public import WireMessagingUI public struct WireMessagingFactory { + public typealias CellsURLResolver = @Sendable () throws -> URL + private let nodesAPI: NodesAPI private let uploadManager: WireCellsNodeUploadManager private let draftsRepository: DraftsRepository @@ -44,29 +46,15 @@ public struct WireMessagingFactory { @MainActor public init( - serverURL: URL, + cellsURLResolver: @escaping CellsURLResolver, accessToken: any AccessTokenProvider, fileCache: any FileCache, contextProvider: any ManagedObjectContextProvider, isFoldersEnabled: Bool, isCollaboraEnabled: Bool ) { - // TODO: [WPB-18798] Remove serverURL temporary override when there exists a method to obtain the correct URL. - let serverURL = switch serverURL.host { - case "prod-nginz-https.wire.com": // Production - URL(string: "https://cells-beta.wire.com")! - case "staging-nginz-https.zinfra.io": // Staging - URL(string: "https://cells.staging.zinfra.io")! - case "nginz-https.fulu.wire.link": // Fulu - URL(string: "https://cells.fulu.wire.link")! - case "nginz-https.imai.wire.link": // Imai - URL(string: "https://cells.imai.wire.link")! - default: - serverURL - } - self.nodeCache = WireCellsNodeCache() - self.nodesAPI = NodesAPI(serverURL: serverURL, accessToken: accessToken) + self.nodesAPI = NodesAPI(serverURLResolver: cellsURLResolver, accessToken: accessToken) self.uploadManager = WireCellsNodeUploadManager(nodesAPI: nodesAPI) self.draftsRepository = DraftsRepository(uploadManager: uploadManager, nodesAPI: nodesAPI) self.fileCache = fileCache diff --git a/WireMessaging/Sources/WireMessagingData/WireCells/NodesAPI/AWSClient.swift b/WireMessaging/Sources/WireMessagingData/WireCells/NodesAPI/AWSClient.swift index 7d3b8581213..9285d1faddf 100644 --- a/WireMessaging/Sources/WireMessagingData/WireCells/NodesAPI/AWSClient.swift +++ b/WireMessaging/Sources/WireMessagingData/WireCells/NodesAPI/AWSClient.swift @@ -20,6 +20,7 @@ import AWSClientRuntime package import AWSS3 package import Foundation import Smithy +import SmithyHTTPAPI import SmithyIdentity import SmithyStreams import WireLogging @@ -62,11 +63,17 @@ final class AWSClient: Sendable { private let s3: any S3ClientProtocol private let makeStream: @Sendable (FileStream) -> ObservableStream - convenience init(serverURL: URL, accessToken: any AccessTokenProvider) { + convenience init( + serverURLResolver: @escaping @Sendable () throws -> URL, + accessToken: any AccessTokenProvider + ) { let config = try! S3Client.S3ClientConfiguration( awsCredentialIdentityResolver: CredentialIdentityResolver(accessTokenProvider: accessToken), region: Constants.region, - endpoint: serverURL.absoluteString + endpointResolver: AWSEndpointResolver( + serverURLResolver: serverURLResolver, + bucket: Constants.bucket + ) ) self.init(s3: S3Client(config: config)) } @@ -275,6 +282,24 @@ private extension WireCellsNodeNetworkModel { } } +private struct AWSEndpointResolver: EndpointResolver { + let serverURLResolver: @Sendable () throws -> URL + let bucket: String + + init( + serverURLResolver: @escaping @Sendable () throws -> URL, + bucket: String + ) { + self.serverURLResolver = serverURLResolver + self.bucket = bucket + } + + func resolve(params: AWSS3.EndpointParams) throws -> SmithyHTTPAPI.Endpoint { + let serverURL = try serverURLResolver().appendingPathComponent("/\(bucket)") + return try SmithyHTTPAPI.Endpoint(urlString: serverURL.absoluteString) + } +} + private struct CredentialIdentityResolver: AWSCredentialIdentityResolver { let accessTokenProvider: any AccessTokenProvider diff --git a/WireMessaging/Sources/WireMessagingData/WireCells/NodesAPI/NodesAPI.swift b/WireMessaging/Sources/WireMessagingData/WireCells/NodesAPI/NodesAPI.swift index b4ea933b992..4ba0bbc779f 100644 --- a/WireMessaging/Sources/WireMessagingData/WireCells/NodesAPI/NodesAPI.swift +++ b/WireMessaging/Sources/WireMessagingData/WireCells/NodesAPI/NodesAPI.swift @@ -31,11 +31,17 @@ package final actor NodesAPI: NodesAPIProtocol, WireCellsNodesRepositoryProtocol private let restAPI: RestAPI private let fileManager: FileManager - package init(serverURL: URL, accessToken: any AccessTokenProvider) { + package init( + serverURLResolver: @escaping @Sendable () throws -> URL, + accessToken: any AccessTokenProvider + ) { self.init( - awsClient: AWSClient(serverURL: serverURL, accessToken: accessToken), + awsClient: AWSClient( + serverURLResolver: serverURLResolver, + accessToken: accessToken + ), restAPI: RestAPI( - serverURL: serverURL.appendingPathComponent("/v2"), + serverURLResolver: serverURLResolver, accessToken: accessToken ) ) diff --git a/WireMessaging/Sources/WireMessagingData/WireCells/NodesAPI/RestAPI.swift b/WireMessaging/Sources/WireMessagingData/WireCells/NodesAPI/RestAPI.swift index a066817dcec..fc5e21de3b4 100644 --- a/WireMessaging/Sources/WireMessagingData/WireCells/NodesAPI/RestAPI.swift +++ b/WireMessaging/Sources/WireMessagingData/WireCells/NodesAPI/RestAPI.swift @@ -35,11 +35,14 @@ final class RestAPI: Sendable { static let renameBackgroundActionName = "move" } - private let serverURL: URL + private let serverURLResolver: @Sendable () throws -> URL private let accessTokenProvider: any AccessTokenProvider - init(serverURL: URL, accessToken: any AccessTokenProvider) { - self.serverURL = serverURL + init( + serverURLResolver: @escaping @Sendable () throws -> URL, + accessToken: any AccessTokenProvider + ) { + self.serverURLResolver = serverURLResolver self.accessTokenProvider = accessToken } @@ -348,7 +351,7 @@ final class RestAPI: Sendable { private func makeConfiguration() async throws -> CellsSDKAPIConfiguration { let config = CellsSDKAPIConfiguration() - config.basePath = serverURL.absoluteString + config.basePath = try serverURLResolver().appendingPathComponent("/v2").absoluteString config.customHeaders = ["Authorization": "Bearer \(try await accessTokenProvider.accessToken().token)"] config.interceptor = LoggingIntercepter() diff --git a/WireMessaging/Sources/WireMessagingData/WireCells/WireCellsNodeUploadManager.swift b/WireMessaging/Sources/WireMessagingData/WireCells/WireCellsNodeUploadManager.swift index 12b70fb88cc..9f1453c9867 100644 --- a/WireMessaging/Sources/WireMessagingData/WireCells/WireCellsNodeUploadManager.swift +++ b/WireMessaging/Sources/WireMessagingData/WireCells/WireCellsNodeUploadManager.swift @@ -111,9 +111,9 @@ package final actor WireCellsNodeUploadManager: WireCellsNodeUploadManagerProtoc ) async -> AsyncStream { let (stream, continuation) = AsyncStream.makeStream(of: WireCellsUploadStatus.self) let task = Task { [nodesAPI] in - let upload = await nodesAPI.uploadFile(path: assetPath, node: node, versionID: versionID) - do { + let upload = try await nodesAPI.uploadFile(path: assetPath, node: node, versionID: versionID) + for try await progress in upload { await self.updateUploadProgress( nodeID: node.id, diff --git a/WireMessaging/Sources/WireMessagingDomain/WireCells/Protocols/NodesAPIProtocol.swift b/WireMessaging/Sources/WireMessagingDomain/WireCells/Protocols/NodesAPIProtocol.swift index e2391e7c0e9..82b5a196d29 100644 --- a/WireMessaging/Sources/WireMessagingDomain/WireCells/Protocols/NodesAPIProtocol.swift +++ b/WireMessaging/Sources/WireMessagingDomain/WireCells/Protocols/NodesAPIProtocol.swift @@ -28,7 +28,7 @@ package protocol NodesAPIProtocol: Sendable { onProgressUpdate: @escaping @Sendable (UInt64) -> Void ) async throws - func uploadFile(path: URL, node: WireCellsNode, versionID: UUID) async -> AsyncThrowingStream + func uploadFile(path: URL, node: WireCellsNode, versionID: UUID) async throws -> AsyncThrowingStream func deleteVersion(nodeID: UUID, versionID: UUID) async throws diff --git a/WireMessaging/Tests/WireMessagingTests/WireCells/ImplementationTests/NodesAPI/NodesAPITests.swift b/WireMessaging/Tests/WireMessagingTests/WireCells/ImplementationTests/NodesAPI/NodesAPITests.swift index 6e20eb6d287..ab728d87371 100644 --- a/WireMessaging/Tests/WireMessagingTests/WireCells/ImplementationTests/NodesAPI/NodesAPITests.swift +++ b/WireMessaging/Tests/WireMessagingTests/WireCells/ImplementationTests/NodesAPI/NodesAPITests.swift @@ -46,7 +46,7 @@ final class NodesAPITests { makeStream: { ObservableStream($0, bufferingPolicy: .unbounded) } ), restAPI: RestAPI( - serverURL: URL(string: "example.com")!, + serverURLResolver: { URL(string: "example.com")! }, accessToken: MockAccessTokenProvider() ), ) diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/AccountsAPI/AccountsAPIBuilder.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/AccountsAPI/AccountsAPIBuilder.swift index ab283cfe946..c3308252121 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/AccountsAPI/AccountsAPIBuilder.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/AccountsAPI/AccountsAPIBuilder.swift @@ -65,6 +65,8 @@ public struct AccountsAPIBuilder { AccountsAPIV12(apiService: apiService) case .v13: AccountsAPIV13(apiService: apiService) + case .v14: + AccountsAPIV14(apiService: apiService) } } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/AccountsAPI/AccountsAPIV13.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/AccountsAPI/AccountsAPIV13.swift index 9b95aff6479..f9776d48709 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/AccountsAPI/AccountsAPIV13.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/AccountsAPI/AccountsAPIV13.swift @@ -16,6 +16,6 @@ // along with this program. If not, see http://www.gnu.org/licenses/. // -final class AccountsAPIV13: AccountsAPIV12 { +class AccountsAPIV13: AccountsAPIV12 { override var apiVersion: APIVersion { .v13 } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/AccountsAPI/AccountsAPIV14.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/AccountsAPI/AccountsAPIV14.swift new file mode 100644 index 00000000000..210da0d5a8e --- /dev/null +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/AccountsAPI/AccountsAPIV14.swift @@ -0,0 +1,21 @@ +// +// Wire +// Copyright (C) 2026 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +final class AccountsAPIV14: AccountsAPIV13 { + override var apiVersion: APIVersion { .v14 } +} diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/AuthenticationAPI/AuthenticationAPIBuilder.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/AuthenticationAPI/AuthenticationAPIBuilder.swift index 2ffa3b08fbc..10920e15a9a 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/AuthenticationAPI/AuthenticationAPIBuilder.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/AuthenticationAPI/AuthenticationAPIBuilder.swift @@ -65,6 +65,8 @@ public struct AuthenticationAPIBuilder { AuthenticationAPIV12(networkService: networkService) case .v13: AuthenticationAPIV13(networkService: networkService) + case .v14: + AuthenticationAPIV14(networkService: networkService) } } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/AuthenticationAPI/AuthenticationAPIV13.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/AuthenticationAPI/AuthenticationAPIV13.swift index 0dc2ce9a23b..d240879d21d 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/AuthenticationAPI/AuthenticationAPIV13.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/AuthenticationAPI/AuthenticationAPIV13.swift @@ -16,7 +16,7 @@ // along with this program. If not, see http://www.gnu.org/licenses/. // -final class AuthenticationAPIV13: AuthenticationAPIV12 { +class AuthenticationAPIV13: AuthenticationAPIV12 { override var apiVersion: APIVersion { .v13 } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/AuthenticationAPI/AuthenticationAPIV14.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/AuthenticationAPI/AuthenticationAPIV14.swift new file mode 100644 index 00000000000..b6cdc9f7731 --- /dev/null +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/AuthenticationAPI/AuthenticationAPIV14.swift @@ -0,0 +1,23 @@ +// +// Wire +// Copyright (C) 2026 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +final class AuthenticationAPIV14: AuthenticationAPIV13 { + + override var apiVersion: APIVersion { .v14 } + +} diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/ConnectionsAPI/ConnectionsAPIBuilder.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/ConnectionsAPI/ConnectionsAPIBuilder.swift index d6c587d2947..79e7b19bfac 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/ConnectionsAPI/ConnectionsAPIBuilder.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/ConnectionsAPI/ConnectionsAPIBuilder.swift @@ -67,6 +67,8 @@ public struct ConnectionsAPIBuilder { ConnectionsAPIV12(apiService: apiService) case .v13: ConnectionsAPIV13(apiService: apiService) + case .v14: + ConnectionsAPIV14(apiService: apiService) } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/ConnectionsAPI/ConnectionsAPIV13.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/ConnectionsAPI/ConnectionsAPIV13.swift index d022f603e81..087451a727a 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/ConnectionsAPI/ConnectionsAPIV13.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/ConnectionsAPI/ConnectionsAPIV13.swift @@ -16,6 +16,6 @@ // along with this program. If not, see http://www.gnu.org/licenses/. // -final class ConnectionsAPIV13: ConnectionsAPIV12 { +class ConnectionsAPIV13: ConnectionsAPIV12 { override var apiVersion: APIVersion { .v13 } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/ConnectionsAPI/ConnectionsAPIV14.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/ConnectionsAPI/ConnectionsAPIV14.swift new file mode 100644 index 00000000000..3d6bcaf4eac --- /dev/null +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/ConnectionsAPI/ConnectionsAPIV14.swift @@ -0,0 +1,21 @@ +// +// Wire +// Copyright (C) 2026 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +final class ConnectionsAPIV14: ConnectionsAPIV13 { + override var apiVersion: APIVersion { .v14 } +} diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/ConversationsAPI/ConversationsAPIBuilder.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/ConversationsAPI/ConversationsAPIBuilder.swift index 83907a2aded..bfa1e735a2c 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/ConversationsAPI/ConversationsAPIBuilder.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/ConversationsAPI/ConversationsAPIBuilder.swift @@ -65,6 +65,8 @@ public struct ConversationsAPIBuilder { ConversationsAPIV12(apiService: apiService) case .v13: ConversationsAPIV13(apiService: apiService) + case .v14: + ConversationsAPIV14(apiService: apiService) } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/ConversationsAPI/ConversationsAPIV13.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/ConversationsAPI/ConversationsAPIV13.swift index 7353a7a0139..ea06b865cf1 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/ConversationsAPI/ConversationsAPIV13.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/ConversationsAPI/ConversationsAPIV13.swift @@ -16,7 +16,7 @@ // along with this program. If not, see http://www.gnu.org/licenses/. // -final class ConversationsAPIV13: ConversationsAPIV12 { +class ConversationsAPIV13: ConversationsAPIV12 { override var apiVersion: APIVersion { .v13 } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/ConversationsAPI/ConversationsAPIV14.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/ConversationsAPI/ConversationsAPIV14.swift new file mode 100644 index 00000000000..317d63079c9 --- /dev/null +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/ConversationsAPI/ConversationsAPIV14.swift @@ -0,0 +1,23 @@ +// +// Wire +// Copyright (C) 2026 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +final class ConversationsAPIV14: ConversationsAPIV13 { + + override var apiVersion: APIVersion { .v14 } + +} diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/FeatureConfigsAPI/FeatureConfigsAPIBuilder.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/FeatureConfigsAPI/FeatureConfigsAPIBuilder.swift index 52bd1c9bb5e..112e81e3f50 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/FeatureConfigsAPI/FeatureConfigsAPIBuilder.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/FeatureConfigsAPI/FeatureConfigsAPIBuilder.swift @@ -67,6 +67,8 @@ public struct FeatureConfigsAPIBuilder { FeatureConfigsAPIV12(apiService: apiService) case .v13: FeatureConfigsAPIV13(apiService: apiService) + case .v14: + FeatureConfigsAPIV14(apiService: apiService) } } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/FeatureConfigsAPI/FeatureConfigsAPIV13.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/FeatureConfigsAPI/FeatureConfigsAPIV13.swift index 03454b5d11e..7f74c0dcc4d 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/FeatureConfigsAPI/FeatureConfigsAPIV13.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/FeatureConfigsAPI/FeatureConfigsAPIV13.swift @@ -16,6 +16,6 @@ // along with this program. If not, see http://www.gnu.org/licenses/. // -final class FeatureConfigsAPIV13: FeatureConfigsAPIV12 { +class FeatureConfigsAPIV13: FeatureConfigsAPIV12 { override var apiVersion: APIVersion { .v13 } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/FeatureConfigsAPI/FeatureConfigsAPIV14.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/FeatureConfigsAPI/FeatureConfigsAPIV14.swift new file mode 100644 index 00000000000..2feb82417a0 --- /dev/null +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/FeatureConfigsAPI/FeatureConfigsAPIV14.swift @@ -0,0 +1,178 @@ +// +// Wire +// Copyright (C) 2026 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +import Foundation + +final class FeatureConfigsAPIV14: FeatureConfigsAPIV13 { + + override var apiVersion: APIVersion { .v14 } + + override func getFeatureConfigs() async throws -> [FeatureConfig] { + let request = try URLRequestBuilder(path: resourcePath) + .withMethod(.get) + .build() + + let (data, response) = try await apiService.executeRequest( + request, + requiringAccessToken: true + ) + + return try ResponseParser() + .success(code: .ok, type: FeatureConfigsResponseAPIV14.self) + .failure(code: .forbidden, label: "operation-denied", error: FeatureConfigsAPIError.insufficientPermissions) + .failure(code: .forbidden, label: "no-team-member", error: FeatureConfigsAPIError.userIsNotTeamMember) + .failure(code: .notFound, label: "no-team", error: FeatureConfigsAPIError.teamNotFound) + .parse(code: response.statusCode, data: data) + } + +} + +struct FeatureConfigsResponseAPIV14: Decodable, ToAPIModelConvertible { + + let appLock: FeatureWithConfig + let apps: FeatureWithoutConfig + let classifiedDomains: FeatureWithConfig + let conferenceCalling: FeatureWithConfig + let conversationGuestLinks: FeatureWithoutConfig + let digitalSignatures: FeatureWithoutConfig + let fileSharing: FeatureWithoutConfig + let selfDeletingMessages: FeatureWithConfig + let mls: FeatureWithConfig + let mlsMigration: FeatureWithConfig + let mlsE2EId: FeatureWithConfig + let channels: FeatureWithConfig + let cells: FeatureWithoutConfig + let allowedGlobalOperations: FeatureWithConfig + let consumableNotifications: FeatureWithoutConfig + let assetAuditLog: FeatureWithoutConfig + + // added in v14 + let cellsInternal: FeatureWithConfig + + func toAPIModel() -> [FeatureConfig] { + var featureConfigs: [FeatureConfig] = [] + + let appLockConfig = appLock.toAPIModel() + featureConfigs.append(.appLock(appLockConfig)) + + let appsFeatureConfig = AppsFeatureConfig(status: apps.status.toAPIModel()) + featureConfigs.append(.apps(appsFeatureConfig)) + + let classifiedDomainsConfig = classifiedDomains.toAPIModel() + featureConfigs.append(.classifiedDomains(classifiedDomainsConfig)) + + let conferenceCallingConfig = ConferenceCallingFeatureConfig( + status: conferenceCalling.status.toAPIModel(), + useSFTForOneToOneCalls: conferenceCalling.config.useSFTForOneToOneCalls + ) + + featureConfigs.append(.conferenceCalling(conferenceCallingConfig)) + + let conversationGuestLinksConfig = ConversationGuestLinksFeatureConfig( + status: conversationGuestLinks.status + .toAPIModel() + ) + featureConfigs.append(.conversationGuestLinks(conversationGuestLinksConfig)) + + let digitalSignaturesConfig = DigitalSignatureFeatureConfig(status: digitalSignatures.status.toAPIModel()) + featureConfigs.append(.digitalSignature(digitalSignaturesConfig)) + + let fileSharingConfig = FileSharingFeatureConfig(status: fileSharing.status.toAPIModel()) + featureConfigs.append(.fileSharing(fileSharingConfig)) + + let selfDeletingMessagesConfig = selfDeletingMessages.toAPIModel() + featureConfigs.append(.selfDeletingMessages(selfDeletingMessagesConfig)) + + let mlsConfig = MLSFeatureConfig( + status: mls.status.toAPIModel(), + protocolToggleUsers: mls.config.protocolToggleUsers, + defaultProtocol: mls.config.defaultProtocol.toAPIModel(), + allowedCipherSuites: mls.config.allowedCipherSuites.map { $0.toAPIModel() }, + defaultCipherSuite: mls.config.defaultCipherSuite.toAPIModel(), + supportedProtocols: Set(mls.config.supportedProtocols.map { $0.toAPIModel() }) + ) + + featureConfigs.append(.mls(mlsConfig)) + + let mlsMigrationConfig = MLSMigrationFeatureConfig( + status: mlsMigration.status.toAPIModel(), + startTime: mlsMigration.config.startTime?.date, + finaliseRegardlessAfter: mlsMigration.config.finaliseRegardlessAfter?.date + ) + + featureConfigs.append(.mlsMigration(mlsMigrationConfig)) + + let mlsE2EIdConfig = EndToEndIdentityFeatureConfig( + status: mlsE2EId.status.toAPIModel(), + acmeDiscoveryURL: mlsE2EId.config.acmeDiscoveryUrl, + verificationExpiration: mlsE2EId.config.verificationExpiration, + crlProxy: mlsE2EId.config.crlProxy, + useProxyOnMobile: mlsE2EId.config.useProxyOnMobile + ) + + featureConfigs.append(.endToEndIdentity(mlsE2EIdConfig)) + + let channelsConfig = ChannelsFeatureConfig( + status: channels.status.toAPIModel(), + allowedToCreateChannels: channels.config.allowedToCreateChannels.toAPIModel(), + allowedToOpenChannels: channels.config.allowedToOpenChannels.toAPIModel() + ) + featureConfigs.append(.channels(channelsConfig)) + + let allowedGlobalOperations = AllowedGlobalOperationsFeatureConfig( + status: allowedGlobalOperations.status.toAPIModel(), + resetMLSConversations: allowedGlobalOperations.config.mlsConversationReset + ) + featureConfigs.append(.allowedGlobalOperations(allowedGlobalOperations)) + + let consumableNotifications = ConsumableNotificationsFeatureConfig( + status: consumableNotifications.status + .toAPIModel() + ) + featureConfigs.append(.consumableNotifications(consumableNotifications)) + + featureConfigs.append(.assetAuditLog(AssetAuditLogFeatureConfig( + status: assetAuditLog.status.toAPIModel() + ))) + + let cellsFeatureConfig = CellsFeatureConfig(status: cells.status.toAPIModel()) + featureConfigs.append(.cells(cellsFeatureConfig)) + + // added in v14 + let cellsInternalConfig = CellsInternalFeatureConfig( + status: cellsInternal.status.toAPIModel(), + backendURL: cellsInternal.config.backend.url + ) + featureConfigs.append(.cellsInternal(cellsInternalConfig)) + + return featureConfigs + } + +} + +extension FeatureConfigResponse { + + struct CellsInternalV14: Decodable { + let backend: BackendV14 + + struct BackendV14: Decodable { + let url: URL + } + } + +} diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/MLSAPI/MLSAPIBuilder.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/MLSAPI/MLSAPIBuilder.swift index 312664e3031..1f0d25b3315 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/MLSAPI/MLSAPIBuilder.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/MLSAPI/MLSAPIBuilder.swift @@ -67,6 +67,8 @@ public struct MLSAPIBuilder { MLSAPIV12(apiService: apiService) case .v13: MLSAPIV13(apiService: apiService) + case .v14: + MLSAPIV14(apiService: apiService) } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/MLSAPI/MLSAPIV13.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/MLSAPI/MLSAPIV13.swift index 4bad1358b72..292b614299e 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/MLSAPI/MLSAPIV13.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/MLSAPI/MLSAPIV13.swift @@ -18,7 +18,7 @@ import Foundation -final class MLSAPIV13: MLSAPIV12 { +class MLSAPIV13: MLSAPIV12 { override var apiVersion: APIVersion { .v13 } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/MLSAPI/MLSAPIV14.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/MLSAPI/MLSAPIV14.swift new file mode 100644 index 00000000000..94c22f5df41 --- /dev/null +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/MLSAPI/MLSAPIV14.swift @@ -0,0 +1,25 @@ +// +// Wire +// Copyright (C) 2026 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +import Foundation + +final class MLSAPIV14: MLSAPIV13 { + + override var apiVersion: APIVersion { .v14 } + +} diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/PushChannelV2API/PushChannelV2APIBuilder.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/PushChannelV2API/PushChannelV2APIBuilder.swift index 0b6d8d5f8fa..0442157e365 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/PushChannelV2API/PushChannelV2APIBuilder.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/PushChannelV2API/PushChannelV2APIBuilder.swift @@ -64,6 +64,8 @@ public struct PushChannelV2APIBuilder { PushChannelV2APIV12(pushChannelService: pushChannelService) case .v13: PushChannelV2APIV13(pushChannelService: pushChannelService) + case .v14: + PushChannelV2APIV14(pushChannelService: pushChannelService) } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/PushChannelV2API/PushChannelV2APIV13.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/PushChannelV2API/PushChannelV2APIV13.swift index cd0c96f8402..f61623e7e08 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/PushChannelV2API/PushChannelV2APIV13.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/PushChannelV2API/PushChannelV2APIV13.swift @@ -16,7 +16,7 @@ // along with this program. If not, see http://www.gnu.org/licenses/. // -final class PushChannelV2APIV13: PushChannelV2APIV12 { +class PushChannelV2APIV13: PushChannelV2APIV12 { override var apiVersion: APIVersion { .v13 } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/PushChannelV2API/PushChannelV2APIV14.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/PushChannelV2API/PushChannelV2APIV14.swift new file mode 100644 index 00000000000..850c8476151 --- /dev/null +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/PushChannelV2API/PushChannelV2APIV14.swift @@ -0,0 +1,23 @@ +// +// Wire +// Copyright (C) 2026 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +final class PushChannelV2APIV14: PushChannelV2APIV13 { + + override var apiVersion: APIVersion { .v14 } + +} diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/SelfUserAPI/SelfUserAPIBuilder.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/SelfUserAPI/SelfUserAPIBuilder.swift index c9627637b7f..ece3dad372d 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/SelfUserAPI/SelfUserAPIBuilder.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/SelfUserAPI/SelfUserAPIBuilder.swift @@ -67,6 +67,8 @@ public struct SelfUserAPIBuilder { SelfUserAPIV12(apiService: apiService) case .v13: SelfUserAPIV13(apiService: apiService) + case .v14: + SelfUserAPIV14(apiService: apiService) } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/SelfUserAPI/SelfUserAPIV13.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/SelfUserAPI/SelfUserAPIV13.swift index 1adfc6cefcd..a835b3fe1a3 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/SelfUserAPI/SelfUserAPIV13.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/SelfUserAPI/SelfUserAPIV13.swift @@ -16,6 +16,6 @@ // along with this program. If not, see http://www.gnu.org/licenses/. // -final class SelfUserAPIV13: SelfUserAPIV12 { +class SelfUserAPIV13: SelfUserAPIV12 { override var apiVersion: APIVersion { .v13 } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/SelfUserAPI/SelfUserAPIV14.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/SelfUserAPI/SelfUserAPIV14.swift new file mode 100644 index 00000000000..f42ad2b9afa --- /dev/null +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/SelfUserAPI/SelfUserAPIV14.swift @@ -0,0 +1,21 @@ +// +// Wire +// Copyright (C) 2026 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +final class SelfUserAPIV14: SelfUserAPIV13 { + override var apiVersion: APIVersion { .v14 } +} diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/TeamsAPI/TeamsAPIBuilder.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/TeamsAPI/TeamsAPIBuilder.swift index e163241b1ec..09b07042cbb 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/TeamsAPI/TeamsAPIBuilder.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/TeamsAPI/TeamsAPIBuilder.swift @@ -67,6 +67,8 @@ public struct TeamsAPIBuilder { TeamsAPIV12(apiService: apiService) case .v13: TeamsAPIV13(apiService: apiService) + case .v14: + TeamsAPIV14(apiService: apiService) } } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/TeamsAPI/TeamsAPIV13.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/TeamsAPI/TeamsAPIV13.swift index e7f93852000..c3793cca266 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/TeamsAPI/TeamsAPIV13.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/TeamsAPI/TeamsAPIV13.swift @@ -16,6 +16,6 @@ // along with this program. If not, see http://www.gnu.org/licenses/. // -final class TeamsAPIV13: TeamsAPIV12 { +class TeamsAPIV13: TeamsAPIV12 { override var apiVersion: APIVersion { .v13 } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/TeamsAPI/TeamsAPIV14.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/TeamsAPI/TeamsAPIV14.swift new file mode 100644 index 00000000000..ac2ad85f8a4 --- /dev/null +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/TeamsAPI/TeamsAPIV14.swift @@ -0,0 +1,21 @@ +// +// Wire +// Copyright (C) 2026 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +final class TeamsAPIV14: TeamsAPIV13 { + override var apiVersion: APIVersion { .v14 } +} diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/UpdateEventsAPI/UpdateEventsAPIBuilder.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/UpdateEventsAPI/UpdateEventsAPIBuilder.swift index e5605f829b5..28c51ce8dbb 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/UpdateEventsAPI/UpdateEventsAPIBuilder.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/UpdateEventsAPI/UpdateEventsAPIBuilder.swift @@ -67,6 +67,8 @@ public struct UpdateEventsAPIBuilder { UpdateEventsAPIV12(apiService: apiService) case .v13: UpdateEventsAPIV13(apiService: apiService) + case .v14: + UpdateEventsAPIV14(apiService: apiService) } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/UpdateEventsAPI/UpdateEventsAPIV13.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/UpdateEventsAPI/UpdateEventsAPIV13.swift index 2aa26dca377..4193119ea30 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/UpdateEventsAPI/UpdateEventsAPIV13.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/UpdateEventsAPI/UpdateEventsAPIV13.swift @@ -16,7 +16,7 @@ // along with this program. If not, see http://www.gnu.org/licenses/. // -final class UpdateEventsAPIV13: UpdateEventsAPIV12 { +class UpdateEventsAPIV13: UpdateEventsAPIV12 { override var apiVersion: APIVersion { .v13 } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/UpdateEventsAPI/UpdateEventsAPIV14.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/UpdateEventsAPI/UpdateEventsAPIV14.swift new file mode 100644 index 00000000000..bb52db01aa8 --- /dev/null +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/UpdateEventsAPI/UpdateEventsAPIV14.swift @@ -0,0 +1,23 @@ +// +// Wire +// Copyright (C) 2026 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +final class UpdateEventsAPIV14: UpdateEventsAPIV13 { + + override var apiVersion: APIVersion { .v14 } + +} diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/UserClientsAPI/UserClientsAPIBuilder.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/UserClientsAPI/UserClientsAPIBuilder.swift index 32c52ee9de8..159fdfa69a2 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/UserClientsAPI/UserClientsAPIBuilder.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/UserClientsAPI/UserClientsAPIBuilder.swift @@ -67,6 +67,8 @@ public struct UserClientsAPIBuilder { UserClientsAPIV12(apiService: apiService) case .v13: UserClientsAPIV13(apiService: apiService) + case .v14: + UserClientsAPIV14(apiService: apiService) } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/UserClientsAPI/UserClientsAPIV13.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/UserClientsAPI/UserClientsAPIV13.swift index 0f03d82a1ed..0f5dddc7ca9 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/UserClientsAPI/UserClientsAPIV13.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/UserClientsAPI/UserClientsAPIV13.swift @@ -16,6 +16,6 @@ // along with this program. If not, see http://www.gnu.org/licenses/. // -final class UserClientsAPIV13: UserClientsAPIV12 { +class UserClientsAPIV13: UserClientsAPIV12 { override var apiVersion: APIVersion { .v13 } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/UserClientsAPI/UserClientsAPIV14.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/UserClientsAPI/UserClientsAPIV14.swift new file mode 100644 index 00000000000..8cdc9f4b3a1 --- /dev/null +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/UserClientsAPI/UserClientsAPIV14.swift @@ -0,0 +1,21 @@ +// +// Wire +// Copyright (C) 2026 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +final class UserClientsAPIV14: UserClientsAPIV13 { + override var apiVersion: APIVersion { .v14 } +} diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/UserPropertiesAPI/UserPropertiesAPIBuilder.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/UserPropertiesAPI/UserPropertiesAPIBuilder.swift index c25864d49bf..d1cc0f5c313 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/UserPropertiesAPI/UserPropertiesAPIBuilder.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/UserPropertiesAPI/UserPropertiesAPIBuilder.swift @@ -67,6 +67,8 @@ public struct UserPropertiesAPIBuilder { UserPropertiesAPIV12(apiService: apiService) case .v13: UserPropertiesAPIV13(apiService: apiService) + case .v14: + UserPropertiesAPIV14(apiService: apiService) } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/UserPropertiesAPI/UserPropertiesAPIV13.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/UserPropertiesAPI/UserPropertiesAPIV13.swift index 83a9ce6119a..35b07d117a4 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/UserPropertiesAPI/UserPropertiesAPIV13.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/UserPropertiesAPI/UserPropertiesAPIV13.swift @@ -16,6 +16,6 @@ // along with this program. If not, see http://www.gnu.org/licenses/. // -final class UserPropertiesAPIV13: UserPropertiesAPIV12 { +class UserPropertiesAPIV13: UserPropertiesAPIV12 { override var apiVersion: APIVersion { .v13 } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/UserPropertiesAPI/UserPropertiesAPIV14.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/UserPropertiesAPI/UserPropertiesAPIV14.swift new file mode 100644 index 00000000000..3ce8fc72b81 --- /dev/null +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/UserPropertiesAPI/UserPropertiesAPIV14.swift @@ -0,0 +1,21 @@ +// +// Wire +// Copyright (C) 2026 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +final class UserPropertiesAPIV14: UserPropertiesAPIV13 { + override var apiVersion: APIVersion { .v14 } +} diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/UsersAPI/UsersAPIBuilder.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/UsersAPI/UsersAPIBuilder.swift index 22ec95d0cfe..825791e1abb 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/UsersAPI/UsersAPIBuilder.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/UsersAPI/UsersAPIBuilder.swift @@ -67,6 +67,8 @@ public struct UsersAPIBuilder { UsersAPIV12(apiService: apiService) case .v13: UsersAPIV13(apiService: apiService) + case .v14: + UsersAPIV14(apiService: apiService) } } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/UsersAPI/UsersAPIV13.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/UsersAPI/UsersAPIV13.swift index 01bdeff12af..434ff4184c1 100644 --- a/WireNetwork/Sources/WireNetwork/APIs/Rest/UsersAPI/UsersAPIV13.swift +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/UsersAPI/UsersAPIV13.swift @@ -16,6 +16,6 @@ // along with this program. If not, see http://www.gnu.org/licenses/. // -final class UsersAPIV13: UsersAPIV12 { +class UsersAPIV13: UsersAPIV12 { override var apiVersion: APIVersion { .v13 } } diff --git a/WireNetwork/Sources/WireNetwork/APIs/Rest/UsersAPI/UsersAPIV14.swift b/WireNetwork/Sources/WireNetwork/APIs/Rest/UsersAPI/UsersAPIV14.swift new file mode 100644 index 00000000000..647964d1b73 --- /dev/null +++ b/WireNetwork/Sources/WireNetwork/APIs/Rest/UsersAPI/UsersAPIV14.swift @@ -0,0 +1,21 @@ +// +// Wire +// Copyright (C) 2026 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +final class UsersAPIV14: UsersAPIV13 { + override var apiVersion: APIVersion { .v14 } +} diff --git a/WireNetwork/Sources/WireNetwork/Models/API/APIVersion.swift b/WireNetwork/Sources/WireNetwork/Models/API/APIVersion.swift index 21d7e237abf..1ec7c3524ab 100644 --- a/WireNetwork/Sources/WireNetwork/Models/API/APIVersion.swift +++ b/WireNetwork/Sources/WireNetwork/Models/API/APIVersion.swift @@ -38,6 +38,7 @@ public enum APIVersion: UInt, CaseIterable, Comparable, Sendable { case v11 case v12 case v13 + case v14 /// API versions considered production ready by the client. /// diff --git a/WireNetwork/Sources/WireNetwork/Models/FeatureConfig/CellsInternalFeatureConfig.swift b/WireNetwork/Sources/WireNetwork/Models/FeatureConfig/CellsInternalFeatureConfig.swift new file mode 100644 index 00000000000..a16507437a8 --- /dev/null +++ b/WireNetwork/Sources/WireNetwork/Models/FeatureConfig/CellsInternalFeatureConfig.swift @@ -0,0 +1,39 @@ +// +// Wire +// Copyright (C) 2026 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +import Foundation + +/// A configuration for the *Cells* (internal) feature. + +public struct CellsInternalFeatureConfig: Equatable, Sendable { + + /// The cells backend URL. + + public let backendURL: URL + + public let status: FeatureConfigStatus + + public init( + status: FeatureConfigStatus, + backendURL: URL + ) { + self.status = status + self.backendURL = backendURL + } + +} diff --git a/WireNetwork/Sources/WireNetwork/Models/FeatureConfig/FeatureConfig.swift b/WireNetwork/Sources/WireNetwork/Models/FeatureConfig/FeatureConfig.swift index 381791a4de4..2d29b005250 100644 --- a/WireNetwork/Sources/WireNetwork/Models/FeatureConfig/FeatureConfig.swift +++ b/WireNetwork/Sources/WireNetwork/Models/FeatureConfig/FeatureConfig.swift @@ -118,6 +118,10 @@ public enum FeatureConfig: Equatable, Sendable { /// **Cells** allow users to send and receive messages with multiple attachments (video, image, files..) case cells(CellsFeatureConfig) + /// Config for **Cells** (internal) feature + /// Provides the proper cells backend URL. + case cellsInternal(CellsInternalFeatureConfig) + /// Global config, that contains other config inside, e.g. 'reset broken mls' case allowedGlobalOperations(AllowedGlobalOperationsFeatureConfig) diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AccountsAPI/__Snapshots__/AccountsAPITests/testUpgradeToTeam_Request_Generation_V7_Onwards.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AccountsAPI/__Snapshots__/AccountsAPITests/testUpgradeToTeam_Request_Generation_V7_Onwards.request-0-v14.txt new file mode 100644 index 00000000000..ad92b483411 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AccountsAPI/__Snapshots__/AccountsAPITests/testUpgradeToTeam_Request_Generation_V7_Onwards.request-0-v14.txt @@ -0,0 +1,5 @@ +curl \ + --request POST \ + --header "Content-Type: application/json" \ + --data "{\"icon\":\"default\",\"name\":\"iOS Team\"}" \ + "/upgrade-personal-to-team" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testGetDomainRegistration_Request_Generation_V8_Onwards.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testGetDomainRegistration_Request_Generation_V8_Onwards.request-0-v14.txt new file mode 100644 index 00000000000..044497b2d03 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testGetDomainRegistration_Request_Generation_V8_Onwards.request-0-v14.txt @@ -0,0 +1,5 @@ +curl \ + --request POST \ + --header "Content-Type: application/json" \ + --data "{\"email\":\"email@example.com\"}" \ + "/v14/get-domain-registration" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testGetOnPremConfigURLEncodeRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testGetOnPremConfigURLEncodeRequest.request-0-v14.txt new file mode 100644 index 00000000000..b81e4aec723 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testGetOnPremConfigURLEncodeRequest.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/custom-backend/by-domain/example%20com" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testGetOnPremConfigURLRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testGetOnPremConfigURLRequest.request-0-v14.txt new file mode 100644 index 00000000000..2c07f131d3c --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testGetOnPremConfigURLRequest.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/custom-backend/by-domain/example.com" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testGetSSOCode.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testGetSSOCode.request-0-v14.txt new file mode 100644 index 00000000000..eb23a87a40b --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testGetSSOCode.request-0-v14.txt @@ -0,0 +1,3 @@ +curl \ + --header "Accept: application/json" \ + "/sso/settings" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testLoginViaEmailRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testLoginViaEmailRequest.request-0-v14.txt new file mode 100644 index 00000000000..b842a0ab900 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testLoginViaEmailRequest.request-0-v14.txt @@ -0,0 +1,5 @@ +curl \ + --request POST \ + --header "Content-Type: application/json" \ + --data "{\"email\":\"email@example.com\",\"password\":\"123456\",\"verification_code\":\"193756\"}" \ + "/v14/login?persist=true" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testRegisterAccount_Request_Generation_V0_Onwards.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testRegisterAccount_Request_Generation_V0_Onwards.request-0-v14.txt new file mode 100644 index 00000000000..4938dd2d914 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testRegisterAccount_Request_Generation_V0_Onwards.request-0-v14.txt @@ -0,0 +1,5 @@ +curl \ + --request POST \ + --header "Content-Type: application/json" \ + --data "{\"accent_id\":1,\"email\":\"john.smith@example.com\",\"email_code\":\"555666\",\"label\":\"label\",\"locale\":\"en\",\"name\":\"John Smith\",\"password\":\"abcd\"}" \ + "/v14/register" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testRequestEmailVerificationCode_Request_Generation_V0_Onwards.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testRequestEmailVerificationCode_Request_Generation_V0_Onwards.request-0-v14.txt new file mode 100644 index 00000000000..8e4175217f8 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testRequestEmailVerificationCode_Request_Generation_V0_Onwards.request-0-v14.txt @@ -0,0 +1,5 @@ +curl \ + --request POST \ + --header "Content-Type: application/json" \ + --data "{\"email\":\"john.smith@example.com\",\"locale\":\"en\"}" \ + "/v14/activate/send" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testRequestVerificationCode_Request_Generation_V0_Onwards.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testRequestVerificationCode_Request_Generation_V0_Onwards.request-0-v14.txt new file mode 100644 index 00000000000..8517ace0d9c --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/AuthenticationAPI/__Snapshots__/AuthenticationAPITests/testRequestVerificationCode_Request_Generation_V0_Onwards.request-0-v14.txt @@ -0,0 +1,5 @@ +curl \ + --request POST \ + --header "Content-Type: application/json" \ + --data "{\"action\":\"login\",\"email\":\"john.smith@example.com\"}" \ + "/v14/verification-code/send" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/ConnectionsAPI/__Snapshots__/ConnectionsAPITests/testGetConnectionsRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/ConnectionsAPI/__Snapshots__/ConnectionsAPITests/testGetConnectionsRequest.request-0-v14.txt new file mode 100644 index 00000000000..87aa3a2cdb2 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/ConnectionsAPI/__Snapshots__/ConnectionsAPITests/testGetConnectionsRequest.request-0-v14.txt @@ -0,0 +1,5 @@ +curl \ + --request POST \ + --header "Content-Type: application/json" \ + --data "{\"size\":500}" \ + "/v14/list-connections" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/ConversationsAPI/__Snapshots__/ConversationsAPITests/testGetConversationGuestLink.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/ConversationsAPI/__Snapshots__/ConversationsAPITests/testGetConversationGuestLink.request-0-v14.txt new file mode 100644 index 00000000000..51fc5392e1f --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/ConversationsAPI/__Snapshots__/ConversationsAPITests/testGetConversationGuestLink.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/conversations/213248A1-5499-418F-8173-5010D1C1E506/code" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/ConversationsAPI/__Snapshots__/ConversationsAPITests/testGetConversationIdentifiers.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/ConversationsAPI/__Snapshots__/ConversationsAPITests/testGetConversationIdentifiers.request-0-v14.txt new file mode 100644 index 00000000000..151903d8a42 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/ConversationsAPI/__Snapshots__/ConversationsAPITests/testGetConversationIdentifiers.request-0-v14.txt @@ -0,0 +1,5 @@ +curl \ + --request POST \ + --header "Content-Type: application/json" \ + --data "{\"size\":500}" \ + "/v14/conversations/list-ids/" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/ConversationsAPI/__Snapshots__/ConversationsAPITests/testGetConversations_givenAllAPIVersions_thenVerifyRequests.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/ConversationsAPI/__Snapshots__/ConversationsAPITests/testGetConversations_givenAllAPIVersions_thenVerifyRequests.request-0-v14.txt new file mode 100644 index 00000000000..66a38c39fe1 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/ConversationsAPI/__Snapshots__/ConversationsAPITests/testGetConversations_givenAllAPIVersions_thenVerifyRequests.request-0-v14.txt @@ -0,0 +1,5 @@ +curl \ + --request POST \ + --header "Content-Type: application/json" \ + --data "{\"qualified_ids\":[{\"domain\":\"wire.com\",\"id\":\"213248A1-5499-418F-8173-5010D1C1E506\"}]}" \ + "/v14/conversations/list" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/ConversationsAPI/__Snapshots__/ConversationsAPITests/testGetMLSOneToOneConversationRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/ConversationsAPI/__Snapshots__/ConversationsAPITests/testGetMLSOneToOneConversationRequest.request-0-v14.txt new file mode 100644 index 00000000000..70ae1eaed73 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/ConversationsAPI/__Snapshots__/ConversationsAPITests/testGetMLSOneToOneConversationRequest.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/one2one-conversations/domain.com/99db9768-04e3-4b5d-9268-831b6a25c4ab" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/FeatureConfigsAPITests.swift b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/FeatureConfigsAPITests.swift index e796ff04f64..0da9ecee5f8 100644 --- a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/FeatureConfigsAPITests.swift +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/FeatureConfigsAPITests.swift @@ -272,6 +272,26 @@ final class FeatureConfigsAPITests: XCTestCase { } } + func testGetFeatureConfigs_SuccessResponse_200_V14_And_Next_Versions_Then_Verify_Requests() async throws { + // Given + let apiService = MockAPIServiceProtocol.withResponses([ + (.ok, "GetFeatureConfigsSuccessResponseV14") + ]) + + let supportedVersions = APIVersion.v14.andNextVersions + + // Then + try await apiSnapshotHelper.verifyRequest(for: supportedVersions, apiService: apiService) { sut in + // When + let result = try await sut.getFeatureConfigs() + // Then + XCTAssertEqual( + result, + Scaffolding.featureConfigsV14 + ) + } + } + } extension FeatureConfigsAPITests { @@ -669,6 +689,12 @@ extension FeatureConfigsAPITests { .cells(.init(status: .enabled)) ] + static let featureConfigsV14: [FeatureConfig] = featureConfigsV12 + [ + .assetAuditLog(.init(status: .enabled)), + .cells(.init(status: .enabled)), + .cellsInternal(.init(status: .enabled, backendURL: URL(string: "https://example.com")!)) + ] + } } diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/Resources/GetFeatureConfigsSuccessResponseV14.json b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/Resources/GetFeatureConfigsSuccessResponseV14.json new file mode 100644 index 00000000000..3b6f92d267f --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/Resources/GetFeatureConfigsSuccessResponseV14.json @@ -0,0 +1,192 @@ + +{ + "appLock": { + "config": { + "enforceAppLock": true, + "inactivityTimeoutSecs": 2147483647 + }, + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "assetAuditLog": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "classifiedDomains": { + "config": { + "domains": [ + "example.com" + ] + }, + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "conferenceCalling": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited", + "config": { + "useSFTForOneToOneCalls": true + } + }, + "cells": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "cellsInternal": { + "config": { + "backend": { + "url": "https://example.com" + }, + "collabora": { + "edition": "NO" + }, + "storage": { + "teamQuotaBytes": "string" + } + }, + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "conversationGuestLinks": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "digitalSignatures": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "enforceFileDownloadLocation": { + "config": { + "enforcedDownloadLocation": "string" + }, + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "exposeInvitationURLsToTeamAdmin": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "fileSharing": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "legalhold": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "limitedEventFanout": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "mls": { + "config": { + "allowedCipherSuites": [ + 1, 2, 3 + ], + "defaultCipherSuite": 2, + "defaultProtocol": "proteus", + "protocolToggleUsers": [ + "99db9768-04e3-4b5d-9268-831b6a25c4ab" + ], + "supportedProtocols": [ + "proteus" + ] + }, + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "mlsE2EId": { + "config": { + "acmeDiscoveryUrl": "https://example.com", + "crlProxy": "https://example.com", + "useProxyOnMobile": true, + "verificationExpiration": 9223372036854776000 + }, + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "mlsMigration": { + "config": { + "finaliseRegardlessAfter": "2021-05-12T10:52:02Z", + "startTime": "2021-05-12T10:52:02Z" + }, + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "outlookCalIntegration": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "searchVisibility": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "searchVisibilityInbound": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "selfDeletingMessages": { + "config": { + "enforcedTimeoutSeconds": 2147483647 + }, + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "sndFactorPasswordChallenge": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "sso": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "validateSAMLemails": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "channels": { + "config": { + "allowed_to_create_channels": "everyone", + "allowed_to_open_channels": "admins" + }, + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + }, + "allowedGlobalOperations": { + "config": { + "mlsConversationReset":true + }, + "lockStatus":"locked", + "status":"enabled", + "ttl":"unlimited" + }, + "consumableNotifications": { + "lockStatus": "locked", + "status": "enabled", + "ttl": "unlimited" + } +} diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/__Snapshots__/FeatureConfigsAPITests/testGetFeatureConfigs.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/__Snapshots__/FeatureConfigsAPITests/testGetFeatureConfigs.request-0-v14.txt new file mode 100644 index 00000000000..afe5bcdf6d3 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/__Snapshots__/FeatureConfigsAPITests/testGetFeatureConfigs.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/feature-configs/" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/__Snapshots__/FeatureConfigsAPITests/testGetFeatureConfigs_SuccessResponse_200_V10_And_Next_Versions_Then_Verify_Requests.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/__Snapshots__/FeatureConfigsAPITests/testGetFeatureConfigs_SuccessResponse_200_V10_And_Next_Versions_Then_Verify_Requests.request-0-v14.txt new file mode 100644 index 00000000000..afe5bcdf6d3 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/__Snapshots__/FeatureConfigsAPITests/testGetFeatureConfigs_SuccessResponse_200_V10_And_Next_Versions_Then_Verify_Requests.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/feature-configs/" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/__Snapshots__/FeatureConfigsAPITests/testGetFeatureConfigs_SuccessResponse_200_V11_And_Next_Versions_Then_Verify_Requests.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/__Snapshots__/FeatureConfigsAPITests/testGetFeatureConfigs_SuccessResponse_200_V11_And_Next_Versions_Then_Verify_Requests.request-0-v14.txt new file mode 100644 index 00000000000..afe5bcdf6d3 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/__Snapshots__/FeatureConfigsAPITests/testGetFeatureConfigs_SuccessResponse_200_V11_And_Next_Versions_Then_Verify_Requests.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/feature-configs/" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/__Snapshots__/FeatureConfigsAPITests/testGetFeatureConfigs_SuccessResponse_200_V12_And_Next_Versions_Then_Verify_Requests.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/__Snapshots__/FeatureConfigsAPITests/testGetFeatureConfigs_SuccessResponse_200_V12_And_Next_Versions_Then_Verify_Requests.request-0-v14.txt new file mode 100644 index 00000000000..afe5bcdf6d3 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/__Snapshots__/FeatureConfigsAPITests/testGetFeatureConfigs_SuccessResponse_200_V12_And_Next_Versions_Then_Verify_Requests.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/feature-configs/" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/__Snapshots__/FeatureConfigsAPITests/testGetFeatureConfigs_SuccessResponse_200_V14_And_Next_Versions_Then_Verify_Requests.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/__Snapshots__/FeatureConfigsAPITests/testGetFeatureConfigs_SuccessResponse_200_V14_And_Next_Versions_Then_Verify_Requests.request-0-v14.txt new file mode 100644 index 00000000000..afe5bcdf6d3 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/FeatureConfigsAPI/__Snapshots__/FeatureConfigsAPITests/testGetFeatureConfigs_SuccessResponse_200_V14_And_Next_Versions_Then_Verify_Requests.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/feature-configs/" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/MLSAPI/__Snapshots__/MLSAPITests/testGetBackendMLSPublicKeysRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/MLSAPI/__Snapshots__/MLSAPITests/testGetBackendMLSPublicKeysRequest.request-0-v14.txt new file mode 100644 index 00000000000..f034e660d72 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/MLSAPI/__Snapshots__/MLSAPITests/testGetBackendMLSPublicKeysRequest.request-0-v14.txt @@ -0,0 +1,3 @@ +curl \ + --header "Accept: application/json" \ + "/v14/mls/public-keys" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/MLSAPI/__Snapshots__/MLSAPITests/testPostCommitBundleRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/MLSAPI/__Snapshots__/MLSAPITests/testPostCommitBundleRequest.request-0-v14.txt new file mode 100644 index 00000000000..d6985bc7c00 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/MLSAPI/__Snapshots__/MLSAPITests/testPostCommitBundleRequest.request-0-v14.txt @@ -0,0 +1,6 @@ +curl \ + --request POST \ + --header "Accept: application/json" \ + --header "Content-Type: message/mls" \ + --data "commitgroupinfo" \ + "/v14/mls/commit-bundles" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/SelfUserAPI/__Snapshots__/SelfUserAPITests/testGetSelfUserRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/SelfUserAPI/__Snapshots__/SelfUserAPITests/testGetSelfUserRequest.request-0-v14.txt new file mode 100644 index 00000000000..2d26a6b5f6d --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/SelfUserAPI/__Snapshots__/SelfUserAPITests/testGetSelfUserRequest.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/self" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/SelfUserAPI/__Snapshots__/SelfUserAPITests/testPushSupportedProtocolsRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/SelfUserAPI/__Snapshots__/SelfUserAPITests/testPushSupportedProtocolsRequest.request-0-v14.txt new file mode 100644 index 00000000000..1e145c48462 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/SelfUserAPI/__Snapshots__/SelfUserAPITests/testPushSupportedProtocolsRequest.request-0-v14.txt @@ -0,0 +1,5 @@ +curl \ + --request PUT \ + --header "Content-Type: application/json" \ + --data "{\"supported_protocols\":[\"mls\"]}" \ + "/v14/self/supported-protocols" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/SelfUserAPI/__Snapshots__/SelfUserAPITests/testPushSupportedProtocols_SuccessResponse_200_V5_And_Next_Versions_Verify_Requests.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/SelfUserAPI/__Snapshots__/SelfUserAPITests/testPushSupportedProtocols_SuccessResponse_200_V5_And_Next_Versions_Verify_Requests.request-0-v14.txt new file mode 100644 index 00000000000..1e145c48462 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/SelfUserAPI/__Snapshots__/SelfUserAPITests/testPushSupportedProtocols_SuccessResponse_200_V5_And_Next_Versions_Verify_Requests.request-0-v14.txt @@ -0,0 +1,5 @@ +curl \ + --request PUT \ + --header "Content-Type: application/json" \ + --data "{\"supported_protocols\":[\"mls\"]}" \ + "/v14/self/supported-protocols" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/TeamsAPI/__Snapshots__/TeamsAPITests/testGetLegalholdInfoRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/TeamsAPI/__Snapshots__/TeamsAPITests/testGetLegalholdInfoRequest.request-0-v14.txt new file mode 100644 index 00000000000..ef38ebecdfd --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/TeamsAPI/__Snapshots__/TeamsAPITests/testGetLegalholdInfoRequest.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/teams/213248a1-5499-418f-8173-5010d1c1e506/legalhold/302c59b0-037c-4b0f-a3ed-ccdbfb4cfe2c" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/TeamsAPI/__Snapshots__/TeamsAPITests/testGetTeamMembersRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/TeamsAPI/__Snapshots__/TeamsAPITests/testGetTeamMembersRequest.request-0-v14.txt new file mode 100644 index 00000000000..327fb961ece --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/TeamsAPI/__Snapshots__/TeamsAPITests/testGetTeamMembersRequest.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/teams/213248a1-5499-418f-8173-5010d1c1e506/members?maxResults=2000" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/TeamsAPI/__Snapshots__/TeamsAPITests/testGetTeamRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/TeamsAPI/__Snapshots__/TeamsAPITests/testGetTeamRequest.request-0-v14.txt new file mode 100644 index 00000000000..11c8a544e20 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/TeamsAPI/__Snapshots__/TeamsAPITests/testGetTeamRequest.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/teams/213248a1-5499-418f-8173-5010d1c1e506" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/TeamsAPI/__Snapshots__/TeamsAPITests/testGetTeamRolesRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/TeamsAPI/__Snapshots__/TeamsAPITests/testGetTeamRolesRequest.request-0-v14.txt new file mode 100644 index 00000000000..76bbc87d119 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/TeamsAPI/__Snapshots__/TeamsAPITests/testGetTeamRolesRequest.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/teams/213248a1-5499-418f-8173-5010d1c1e506/conversations/roles" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UpdateEventsAPI/__Snapshots__/UpdateEventsAPITests/testGetLastUpdateEvent.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UpdateEventsAPI/__Snapshots__/UpdateEventsAPITests/testGetLastUpdateEvent.request-0-v14.txt new file mode 100644 index 00000000000..374fd70f206 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UpdateEventsAPI/__Snapshots__/UpdateEventsAPITests/testGetLastUpdateEvent.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/notifications/last?client=abcd1234" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UpdateEventsAPI/__Snapshots__/UpdateEventsAPITests/testGetServerTime.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UpdateEventsAPI/__Snapshots__/UpdateEventsAPITests/testGetServerTime.request-0-v14.txt new file mode 100644 index 00000000000..e30b5ba8c33 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UpdateEventsAPI/__Snapshots__/UpdateEventsAPITests/testGetServerTime.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/time" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UpdateEventsAPI/__Snapshots__/UpdateEventsAPITests/testGetUpdateEvents.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UpdateEventsAPI/__Snapshots__/UpdateEventsAPITests/testGetUpdateEvents.request-0-v14.txt new file mode 100644 index 00000000000..43faaf8a33b --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UpdateEventsAPI/__Snapshots__/UpdateEventsAPITests/testGetUpdateEvents.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/notifications?client=abcd1234&since=d7f7f946-c4da-4300-998d-5aeba8affeee&size=500" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UpdateEventsAPI/__Snapshots__/UpdateEventsAPITests/testGetUpdateEvents.request-1-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UpdateEventsAPI/__Snapshots__/UpdateEventsAPITests/testGetUpdateEvents.request-1-v14.txt new file mode 100644 index 00000000000..e8878677b26 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UpdateEventsAPI/__Snapshots__/UpdateEventsAPITests/testGetUpdateEvents.request-1-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/notifications?client=abcd1234&since=2eeeb5e4-df85-4aef-9eb2-289981f086ab&size=500" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UserClientsAPI/__Snapshots__/UserClientsAPITests/testGetSelfClients.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UserClientsAPI/__Snapshots__/UserClientsAPITests/testGetSelfClients.request-0-v14.txt new file mode 100644 index 00000000000..60829fc7c7a --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UserClientsAPI/__Snapshots__/UserClientsAPITests/testGetSelfClients.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/clients" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UserClientsAPI/__Snapshots__/UserClientsAPITests/testUpdateClient.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UserClientsAPI/__Snapshots__/UserClientsAPITests/testUpdateClient.request-0-v14.txt new file mode 100644 index 00000000000..2e172c77804 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UserClientsAPI/__Snapshots__/UserClientsAPITests/testUpdateClient.request-0-v14.txt @@ -0,0 +1,5 @@ +curl \ + --request PUT \ + --header "Content-Type: application/json" \ + --data "{\"capabilities\":[\"legalhold-implicit-consent\",\"consumable-notifications\"]}" \ + "/v14/clients/000600d0-000b-9c1a-000d-a4130002c221" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UserPropertiesAPI/__Snapshots__/UserPropertiesAPITests/testGetLabelsRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UserPropertiesAPI/__Snapshots__/UserPropertiesAPITests/testGetLabelsRequest.request-0-v14.txt new file mode 100644 index 00000000000..8a1efd8b0d2 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UserPropertiesAPI/__Snapshots__/UserPropertiesAPITests/testGetLabelsRequest.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/properties/labels" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UserPropertiesAPI/__Snapshots__/UserPropertiesAPITests/testGetWireIndicatorModeRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UserPropertiesAPI/__Snapshots__/UserPropertiesAPITests/testGetWireIndicatorModeRequest.request-0-v14.txt new file mode 100644 index 00000000000..dd7f53089ec --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UserPropertiesAPI/__Snapshots__/UserPropertiesAPITests/testGetWireIndicatorModeRequest.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/properties/WIRE_TYPING_INDICATOR_MODE" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UserPropertiesAPI/__Snapshots__/UserPropertiesAPITests/testGetWireReceiptModeRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UserPropertiesAPI/__Snapshots__/UserPropertiesAPITests/testGetWireReceiptModeRequest.request-0-v14.txt new file mode 100644 index 00000000000..28a14588e52 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UserPropertiesAPI/__Snapshots__/UserPropertiesAPITests/testGetWireReceiptModeRequest.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/properties/WIRE_RECEIPT_MODE" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UsersAPI/__Snapshots__/UsersAPITests/testGetUserRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UsersAPI/__Snapshots__/UsersAPITests/testGetUserRequest.request-0-v14.txt new file mode 100644 index 00000000000..e2bd744dab1 --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UsersAPI/__Snapshots__/UsersAPITests/testGetUserRequest.request-0-v14.txt @@ -0,0 +1,2 @@ +curl \ + "/v14/users/example.com/213248a1-5499-418f-8173-5010d1c1e506" \ No newline at end of file diff --git a/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UsersAPI/__Snapshots__/UsersAPITests/testGetUsersRequest.request-0-v14.txt b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UsersAPI/__Snapshots__/UsersAPITests/testGetUsersRequest.request-0-v14.txt new file mode 100644 index 00000000000..6706a3321db --- /dev/null +++ b/WireNetwork/Tests/WireNetworkTests/APIs/Rest/UsersAPI/__Snapshots__/UsersAPITests/testGetUsersRequest.request-0-v14.txt @@ -0,0 +1,5 @@ +curl \ + --request POST \ + --header "Content-Type: application/json" \ + --data "{\"qualified_ids\":[{\"domain\":\"example.com\",\"id\":\"213248A1-5499-418F-8173-5010D1C1E506\"},{\"domain\":\"example.com\",\"id\":\"302C59B0-037C-4B0F-A3ED-CCDBFB4CFE2C\"},{\"domain\":\"example.com\",\"id\":\"7E23727B-D612-4123-88C0-57E311A7E5A3\"}]}" \ + "/v14/list-users" \ No newline at end of file diff --git a/wire-ios-data-model/Source/Model/FeatureConfig/Cells/Feature.CellsInternal.swift b/wire-ios-data-model/Source/Model/FeatureConfig/Cells/Feature.CellsInternal.swift new file mode 100644 index 00000000000..827edbee8ef --- /dev/null +++ b/wire-ios-data-model/Source/Model/FeatureConfig/Cells/Feature.CellsInternal.swift @@ -0,0 +1,58 @@ +// +// Wire +// Copyright (C) 2026 Wire Swiss GmbH +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +import Foundation + +public extension Feature { + + struct CellsInternal: Codable { + + // MARK: - Properties + + public let status: Status + public let config: Config + + // MARK: - Life cycle + + public init( + status: Feature.Status, + config: Config + ) { + self.status = status + self.config = config + } + + public struct Config: Codable { + public let backend: Backend + + public init(backend: Backend) { + self.backend = backend + } + + public struct Backend: Codable { + public let url: URL? + + public init(url: URL?) { + self.url = url + } + } + } + + } + +} diff --git a/wire-ios-data-model/Source/Model/FeatureConfig/Feature.swift b/wire-ios-data-model/Source/Model/FeatureConfig/Feature.swift index 50af2ef5c64..d25c48a3505 100644 --- a/wire-ios-data-model/Source/Model/FeatureConfig/Feature.swift +++ b/wire-ios-data-model/Source/Model/FeatureConfig/Feature.swift @@ -35,6 +35,7 @@ public class Feature: ZMManagedObject { case apps case assetAuditLog case cells + case cellsInternal case channels case classifiedDomains case conferenceCalling @@ -230,6 +231,7 @@ public class Feature: ZMManagedObject { .apps, .assetAuditLog, .cells, + .cellsInternal, .channels, .classifiedDomains, .conferenceCalling, diff --git a/wire-ios-data-model/Source/Repositories/LegacyFeatureRepository.swift b/wire-ios-data-model/Source/Repositories/LegacyFeatureRepository.swift index 611aa5e425e..9ed786a984e 100644 --- a/wire-ios-data-model/Source/Repositories/LegacyFeatureRepository.swift +++ b/wire-ios-data-model/Source/Repositories/LegacyFeatureRepository.swift @@ -54,6 +54,7 @@ public protocol LegacyFeatureRepositoryInterface { func fetchCells() -> Feature.Cells func storeCells(_ cells: Feature.Cells) func fetchAssetAuditLog() -> Feature.AssetAuditLog + func fetchCellsInternal() -> Feature.CellsInternal? } @@ -566,6 +567,25 @@ public class LegacyFeatureRepository: LegacyFeatureRepositoryInterface { return .init(status: feature.status) } + // MARK: - Cells internal + + public func fetchCellsInternal() -> Feature.CellsInternal? { + guard + let feature = Feature.fetch(name: .cellsInternal, context: context), + let featureConfig = feature.config + else { + return nil + } + + do { + let config = try decoder.decode(Feature.CellsInternal.Config.self, from: featureConfig) + return Feature.CellsInternal(status: feature.status, config: config) + } catch { + logger.error("failed to decode Feature.CellsInternal.Config: \(error)") + return nil + } + } + // MARK: - Methods func createDefaultConfigsIfNeeded() { @@ -616,7 +636,7 @@ public class LegacyFeatureRepository: LegacyFeatureRepositoryInterface { case .cells: storeCells(.init()) - case .assetAuditLog: + case .assetAuditLog, .cellsInternal: // No op: not supported in legacy repository. break } diff --git a/wire-ios-data-model/Support/Sourcery/generated/AutoMockable.generated.swift b/wire-ios-data-model/Support/Sourcery/generated/AutoMockable.generated.swift index 952f740e35d..b829a3f6a3d 100644 --- a/wire-ios-data-model/Support/Sourcery/generated/AutoMockable.generated.swift +++ b/wire-ios-data-model/Support/Sourcery/generated/AutoMockable.generated.swift @@ -3736,6 +3736,24 @@ public class MockLegacyFeatureRepositoryInterface: LegacyFeatureRepositoryInterf } } + // MARK: - fetchCellsInternal + + public var fetchCellsInternal_Invocations: [Void] = [] + public var fetchCellsInternal_MockMethod: (() -> Feature.CellsInternal?)? + public var fetchCellsInternal_MockValue: Feature.CellsInternal?? + + public func fetchCellsInternal() -> Feature.CellsInternal? { + fetchCellsInternal_Invocations.append(()) + + if let mock = fetchCellsInternal_MockMethod { + return mock() + } else if let mock = fetchCellsInternal_MockValue { + return mock + } else { + fatalError("no mock for `fetchCellsInternal`") + } + } + } class MockMLSActionsProviderProtocol: MLSActionsProviderProtocol { diff --git a/wire-ios-request-strategy/Sources/APIs/APIProvider.swift b/wire-ios-request-strategy/Sources/APIs/APIProvider.swift index 8b84cf0593f..f8ec284e364 100644 --- a/wire-ios-request-strategy/Sources/APIs/APIProvider.swift +++ b/wire-ios-request-strategy/Sources/APIs/APIProvider.swift @@ -50,6 +50,7 @@ public struct APIProvider: APIProviderInterface { case .v11: PrekeyAPIV11(httpClient: httpClient) case .v12: PrekeyAPIV12(httpClient: httpClient) case .v13: PrekeyAPIV13(httpClient: httpClient) + case .v14: PrekeyAPIV14(httpClient: httpClient) } } @@ -69,6 +70,7 @@ public struct APIProvider: APIProviderInterface { case .v11: MessageAPIV11(httpClient: httpClient) case .v12: MessageAPIV12(httpClient: httpClient) case .v13: MessageAPIV13(httpClient: httpClient) + case .v14: MessageAPIV14(httpClient: httpClient) } } @@ -84,6 +86,7 @@ public struct APIProvider: APIProviderInterface { case .v11: E2eIAPIV11(httpClient: httpClient) case .v12: E2eIAPIV12(httpClient: httpClient) case .v13: E2eIAPIV13(httpClient: httpClient) + case .v14: E2eIAPIV14(httpClient: httpClient) } } @@ -103,6 +106,7 @@ public struct APIProvider: APIProviderInterface { case .v11: UserClientAPIV11(httpClient: httpClient) case .v12: UserClientAPIV12(httpClient: httpClient) case .v13: UserClientAPIV13(httpClient: httpClient) + case .v14: UserClientAPIV14(httpClient: httpClient) } } } diff --git a/wire-ios-request-strategy/Sources/APIs/E2eIAPI.swift b/wire-ios-request-strategy/Sources/APIs/E2eIAPI.swift index be905c3f9f8..904d6dac697 100644 --- a/wire-ios-request-strategy/Sources/APIs/E2eIAPI.swift +++ b/wire-ios-request-strategy/Sources/APIs/E2eIAPI.swift @@ -102,10 +102,14 @@ class E2eIAPIV12: E2eIAPIV11 { override var apiVersion: APIVersion { .v12 } } -final class E2eIAPIV13: E2eIAPIV12 { +class E2eIAPIV13: E2eIAPIV12 { override var apiVersion: APIVersion { .v13 } } +final class E2eIAPIV14: E2eIAPIV13 { + override var apiVersion: APIVersion { .v14 } +} + private enum Constant { static let pathClients = "clients" static let pathNonce = "nonce" diff --git a/wire-ios-request-strategy/Sources/APIs/MessageAPI.swift b/wire-ios-request-strategy/Sources/APIs/MessageAPI.swift index 676b533b292..cde5dc429b3 100644 --- a/wire-ios-request-strategy/Sources/APIs/MessageAPI.swift +++ b/wire-ios-request-strategy/Sources/APIs/MessageAPI.swift @@ -420,7 +420,7 @@ class MessageAPIV12: MessageAPIV11 { override var apiVersion: APIVersion { .v12 } } -final class MessageAPIV13: MessageAPIV12 { +class MessageAPIV13: MessageAPIV12 { override var apiVersion: APIVersion { .v13 } override func sendMLSMessage( @@ -479,3 +479,7 @@ final class MessageAPIV13: MessageAPIV12 { } } + +final class MessageAPIV14: MessageAPIV13 { + override var apiVersion: APIVersion { .v14 } +} diff --git a/wire-ios-request-strategy/Sources/APIs/PrekeyAPI.swift b/wire-ios-request-strategy/Sources/APIs/PrekeyAPI.swift index a8be71e9f16..4dee8967486 100644 --- a/wire-ios-request-strategy/Sources/APIs/PrekeyAPI.swift +++ b/wire-ios-request-strategy/Sources/APIs/PrekeyAPI.swift @@ -164,10 +164,14 @@ class PrekeyAPIV12: PrekeyAPIV11 { override var apiVersion: APIVersion { .v12 } } -final class PrekeyAPIV13: PrekeyAPIV12 { +class PrekeyAPIV13: PrekeyAPIV12 { override var apiVersion: APIVersion { .v13 } } +final class PrekeyAPIV14: PrekeyAPIV13 { + override var apiVersion: APIVersion { .v14 } +} + extension Collection { var clientListByUserID: Payload.ClientListByUserID { diff --git a/wire-ios-request-strategy/Sources/APIs/UserClientAPI.swift b/wire-ios-request-strategy/Sources/APIs/UserClientAPI.swift index d785f7e9188..a6f065d9889 100644 --- a/wire-ios-request-strategy/Sources/APIs/UserClientAPI.swift +++ b/wire-ios-request-strategy/Sources/APIs/UserClientAPI.swift @@ -113,6 +113,10 @@ class UserClientAPIV12: UserClientAPIV11 { override var apiVersion: APIVersion { .v12 } } -final class UserClientAPIV13: UserClientAPIV12 { +class UserClientAPIV13: UserClientAPIV12 { override var apiVersion: APIVersion { .v13 } } + +final class UserClientAPIV14: UserClientAPIV13 { + override var apiVersion: APIVersion { .v14 } +} diff --git a/wire-ios-request-strategy/Sources/Helpers/AssetRequestFactory.swift b/wire-ios-request-strategy/Sources/Helpers/AssetRequestFactory.swift index c5cdf19c3e8..40e6373cc3e 100644 --- a/wire-ios-request-strategy/Sources/Helpers/AssetRequestFactory.swift +++ b/wire-ios-request-strategy/Sources/Helpers/AssetRequestFactory.swift @@ -102,7 +102,7 @@ public final class AssetRequestFactory: NSObject { case .v0, .v1: "/assets/v3" - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: "/assets" } @@ -140,7 +140,7 @@ public final class AssetRequestFactory: NSObject { case .v0, .v1: "/assets/v3" - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: "/assets" } diff --git a/wire-ios-request-strategy/Sources/Payloads/Conversation/Payload+Conversation.swift b/wire-ios-request-strategy/Sources/Payloads/Conversation/Payload+Conversation.swift index 22f7275a8b8..26cfb2f5672 100644 --- a/wire-ios-request-strategy/Sources/Payloads/Conversation/Payload+Conversation.swift +++ b/wire-ios-request-strategy/Sources/Payloads/Conversation/Payload+Conversation.swift @@ -139,7 +139,7 @@ extension Payload { case .v0, .v1, .v2: self.legacyAccessRole = try container.decodeIfPresent(String.self, forKey: .accessRole) self.accessRoles = try container.decodeIfPresent([String].self, forKey: .accessRoleV2) - case .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: // v3 replaces the field "access_role_v2" with "access_role". // However, since the format of update events does not depend on versioning, @@ -159,13 +159,13 @@ extension Payload { case .v0, .v1, .v2, .v3, .v4: self.cipherSuite = nil self.epochTimestamp = nil - case .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: self.cipherSuite = try container.decodeIfPresent(UInt16.self, forKey: .cipherSuite) self.epochTimestamp = try container.decodeIfPresent(Date.self, forKey: .epochTimestamp) } switch apiVersion { - case .v8, .v9, .v10, .v11, .v12, .v13: + case .v8, .v9, .v10, .v11, .v12, .v13, .v14: self.groupType = try container.decodeIfPresent(ConversationGroupType.self, forKey: .groupType) self.addPermission = try container.decodeIfPresent(ChannelPermission.self, forKey: .addPermission) self.cellsState = try container.decodeIfPresent(CellsState.self, forKey: .cellsState) @@ -197,7 +197,7 @@ extension Payload { case .v0, .v1, .v2: try container.encodeIfPresent(legacyAccessRole, forKey: .accessRole) try container.encodeIfPresent(accessRoles, forKey: .accessRoleV2) - case .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: if legacyAccessRole == nil { try container.encodeIfPresent(accessRoles, forKey: .accessRole) } else { @@ -207,7 +207,7 @@ extension Payload { } switch apiVersion { - case .v8, .v9, .v10, .v11, .v12, .v13: + case .v8, .v9, .v10, .v11, .v12, .v13, .v14: try container.encodeIfPresent(groupType, forKey: .groupType) try container.encodeIfPresent(addPermission, forKey: .addPermission) try container.encodeIfPresent(cellsState, forKey: .cellsState) diff --git a/wire-ios-request-strategy/Sources/Payloads/Conversation/Payload+NewConversation.swift b/wire-ios-request-strategy/Sources/Payloads/Conversation/Payload+NewConversation.swift index 4f198738bb9..66945191e38 100644 --- a/wire-ios-request-strategy/Sources/Payloads/Conversation/Payload+NewConversation.swift +++ b/wire-ios-request-strategy/Sources/Payloads/Conversation/Payload+NewConversation.swift @@ -128,7 +128,7 @@ extension Payload { case .v0, .v1, .v2: self.legacyAccessRole = try container.decodeIfPresent(String.self, forKey: .accessRole) self.accessRoles = try container.decodeIfPresent([String].self, forKey: .accessRoleV2) - case .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: self.accessRoles = try container.decodeIfPresent([String].self, forKey: .accessRole) self.legacyAccessRole = nil } @@ -136,7 +136,7 @@ extension Payload { switch apiVersion { case .v0, .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9: self.skipCreator = nil - case .v10, .v11, .v12, .v13: + case .v10, .v11, .v12, .v13, .v14: self.skipCreator = try container.decodeIfPresent(Bool.self, forKey: .skipCreator) } } @@ -159,14 +159,14 @@ extension Payload { case .v0, .v1, .v2: try container.encodeIfPresent(legacyAccessRole, forKey: .accessRole) try container.encodeIfPresent(accessRoles, forKey: .accessRoleV2) - case .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: try container.encodeIfPresent(accessRoles, forKey: .accessRole) } switch apiVersion { case .v0, .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9: break - case .v10, .v11, .v12, .v13: + case .v10, .v11, .v12, .v13, .v14: try container.encodeIfPresent(skipCreator, forKey: .skipCreator) } } diff --git a/wire-ios-request-strategy/Sources/Protocols/OTREntity.swift b/wire-ios-request-strategy/Sources/Protocols/OTREntity.swift index c3f991be194..13e636656fc 100644 --- a/wire-ios-request-strategy/Sources/Protocols/OTREntity.swift +++ b/wire-ios-request-strategy/Sources/Protocols/OTREntity.swift @@ -167,7 +167,7 @@ extension OTREntity { context: context ) - case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: guard let payload = Payload.MessageSendingStatusV4(response) else { return (missingClients: Set(), deletedClients: Set()) } diff --git a/wire-ios-request-strategy/Sources/Request Strategies/Assets/Helpers/AssetDownloadRequestFactory.swift b/wire-ios-request-strategy/Sources/Request Strategies/Assets/Helpers/AssetDownloadRequestFactory.swift index cff6070bed7..a6307534f7d 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/Assets/Helpers/AssetDownloadRequestFactory.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/Assets/Helpers/AssetDownloadRequestFactory.swift @@ -41,7 +41,7 @@ public final class AssetDownloadRequestFactory { case .v1: guard let domain else { return nil } path = "/assets/v4/\(domain)/\(key)" - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: guard let domain else { return nil } path = "/assets/\(domain)/\(key)" } diff --git a/wire-ios-request-strategy/Sources/Request Strategies/Assets/V2/AssetV2DownloadRequestStrategy.swift b/wire-ios-request-strategy/Sources/Request Strategies/Assets/V2/AssetV2DownloadRequestStrategy.swift index 98b14e4d057..c13266cc2be 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/Assets/V2/AssetV2DownloadRequestStrategy.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/Assets/V2/AssetV2DownloadRequestStrategy.swift @@ -197,7 +197,7 @@ public final class AssetV2DownloadRequestStrategy: AbstractRequestStrategy, ZMDo fatalError("Cannot generate request for \(object.safeForLoggingDescription)") - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: return nil } diff --git a/wire-ios-request-strategy/Sources/Request Strategies/Assets/V2/ImageV2DownloadRequestStrategy.swift b/wire-ios-request-strategy/Sources/Request Strategies/Assets/V2/ImageV2DownloadRequestStrategy.swift index da52633db8b..dc2ce37e78d 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/Assets/V2/ImageV2DownloadRequestStrategy.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/Assets/V2/ImageV2DownloadRequestStrategy.swift @@ -119,7 +119,7 @@ extension ImageV2DownloadRequestStrategy: ZMDownstreamTranscoder { ) } - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: // v2 assets are legacy and no longer supported in API v2 return nil } diff --git a/wire-ios-request-strategy/Sources/Request Strategies/Client Message/ClientMessageRequestFactory.swift b/wire-ios-request-strategy/Sources/Request Strategies/Client Message/ClientMessageRequestFactory.swift index 5290f72333a..16d761e65d5 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/Client Message/ClientMessageRequestFactory.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/Client Message/ClientMessageRequestFactory.swift @@ -65,7 +65,7 @@ public final class ClientMessageRequestFactory: NSObject { missingClientsStrategy: .doNotIgnoreAnyMissingClient ) - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: let domain = if let domain, !domain.isEmpty { domain } else { localDomain } guard let domain else { zmLog.error("could not create request: missing domain") diff --git a/wire-ios-request-strategy/Sources/Request Strategies/Connection/Actions/ConnectToUserActionHandler.swift b/wire-ios-request-strategy/Sources/Request Strategies/Connection/Actions/ConnectToUserActionHandler.swift index 24a442d2ea9..bba765353ba 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/Connection/Actions/ConnectToUserActionHandler.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/Connection/Actions/ConnectToUserActionHandler.swift @@ -43,7 +43,7 @@ class ConnectToUserActionHandler: ActionHandler { switch apiVersion { case .v0: nonFederatedRequest(for: action, apiVersion: apiVersion) - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: federatedRequest(for: action, apiVersion: apiVersion) } } diff --git a/wire-ios-request-strategy/Sources/Request Strategies/Connection/Actions/UpdateConnectionActionHandler.swift b/wire-ios-request-strategy/Sources/Request Strategies/Connection/Actions/UpdateConnectionActionHandler.swift index 27ee171ada7..43432e27307 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/Connection/Actions/UpdateConnectionActionHandler.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/Connection/Actions/UpdateConnectionActionHandler.swift @@ -38,7 +38,7 @@ class UpdateConnectionActionHandler: ActionHandler { case .v0: v0Request(for: action) - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: v1Request(for: action) } } diff --git a/wire-ios-request-strategy/Sources/Request Strategies/Connection/ConnectionRequestStrategy.swift b/wire-ios-request-strategy/Sources/Request Strategies/Connection/ConnectionRequestStrategy.swift index 96cd4d3a41a..76e9ce949a3 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/Connection/ConnectionRequestStrategy.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/Connection/ConnectionRequestStrategy.swift @@ -144,7 +144,7 @@ public class ConnectionRequestStrategy: AbstractRequestStrategy, ZMRequestGenera } } - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: connectionListSync.fetch { [weak self] result in switch result { case let .success(connectionList): @@ -215,7 +215,7 @@ extension ConnectionRequestStrategy: KeyPathObjectSyncTranscoder { connectionByIDSync.sync(identifiers: userIdSet) } - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: if let qualifiedID = object.to.qualifiedID { let qualifiedIdSet: Set = [qualifiedID] connectionByQualifiedIDSync.sync(identifiers: qualifiedIdSet) diff --git a/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/AddParticipantActionHandler.swift b/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/AddParticipantActionHandler.swift index c55d83cd13a..93b0509647e 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/AddParticipantActionHandler.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/AddParticipantActionHandler.swift @@ -70,7 +70,7 @@ class AddParticipantActionHandler: ActionHandler { v0Request(for: action) case .v1: v1Request(for: action) - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: v2Request(for: action, apiVersion: apiVersion) } } diff --git a/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/CreateConversationGuestLinkActionHandler.swift b/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/CreateConversationGuestLinkActionHandler.swift index 59f73ae7c71..bf254c0397f 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/CreateConversationGuestLinkActionHandler.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/CreateConversationGuestLinkActionHandler.swift @@ -38,7 +38,7 @@ final class CreateConversationGuestLinkActionHandler: ActionHandler { switch apiVersion { case .v0: nonFederatedRequest(for: action, apiVersion: apiVersion) - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: federatedRequest(for: action, apiVersion: apiVersion) } } diff --git a/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/SetAllowGuestsAndServicesActionHandler.swift b/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/SetAllowGuestsAndServicesActionHandler.swift index 251aea770ae..da2c7b70361 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/SetAllowGuestsAndServicesActionHandler.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/SetAllowGuestsAndServicesActionHandler.swift @@ -75,7 +75,7 @@ final class SetAllowGuestsAndAppsActionHandler: ActionHandler apiVersion: apiVersion.rawValue ) - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: return ZMTransportRequest( path: "/conversations/list", method: .post, diff --git a/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/SyncUsersActionHandler.swift b/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/SyncUsersActionHandler.swift index 052bc189e69..abce20acec9 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/SyncUsersActionHandler.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/SyncUsersActionHandler.swift @@ -63,7 +63,7 @@ class SyncUsersActionHandler: ActionHandler { action.fail(with: .endpointUnavailable) return nil - case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: guard let payloadData = RequestPayload(qualified_ids: action.qualifiedIDs).payloadString() else { @@ -98,7 +98,7 @@ class SyncUsersActionHandler: ActionHandler { action.fail(with: .endpointUnavailable) return - case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: switch response.httpStatus { case 200: guard let rawData = response.rawData, diff --git a/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/UpdateAccessRolesActionHandler.swift b/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/UpdateAccessRolesActionHandler.swift index ff4df482477..2360eb62632 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/UpdateAccessRolesActionHandler.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/Conversation/Actions/UpdateAccessRolesActionHandler.swift @@ -75,7 +75,7 @@ final class UpdateAccessRolesActionHandler: ActionHandler { switch apiVersion { case .v0, .v1, .v2, .v3, .v4, .v5, .v6: path = "/conversations/\(convID)/members/\(userID)" - case .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: guard let convDomain = conversation.domain ?? localDomain, let userDomain = participant.domain ?? localDomain diff --git a/wire-ios-request-strategy/Sources/Request Strategies/Conversation/ConversationRequestStrategy.swift b/wire-ios-request-strategy/Sources/Request Strategies/Conversation/ConversationRequestStrategy.swift index 85d92e17388..132478afa61 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/Conversation/ConversationRequestStrategy.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/Conversation/ConversationRequestStrategy.swift @@ -216,7 +216,7 @@ public class ConversationRequestStrategy: AbstractRequestStrategy, ZMRequestGene case .v0: conversationByIDSync.sync(identifiers: conversations.compactMap(\.remoteIdentifier)) - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: if let qualifiedIDs = conversations.qualifiedIDs { conversationByQualifiedIDSync.sync(identifiers: qualifiedIDs) } else if let localDomain { @@ -249,7 +249,7 @@ public class ConversationRequestStrategy: AbstractRequestStrategy, ZMRequestGene } } - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: conversationQualifiedIDsSync.fetch { [weak self] result in switch result { case let .success(qualifiedConversationIDList): @@ -425,7 +425,7 @@ extension ConversationRequestStrategy: ZMUpstreamTranscoder { apiVersion: apiVersion.rawValue ) - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: let domain = if let domain = conversation.domain, !domain.isEmpty { domain } else { localDomain } guard let domain else { return nil } @@ -467,7 +467,7 @@ extension ConversationRequestStrategy: ZMUpstreamTranscoder { apiVersion: apiVersion.rawValue ) - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: let domain = if let domain = conversation.domain, !domain.isEmpty { domain } else { localDomain } guard let domain else { return nil } diff --git a/wire-ios-request-strategy/Sources/Request Strategies/Feature configurations/GetFeatureConfigsActionHandler.swift b/wire-ios-request-strategy/Sources/Request Strategies/Feature configurations/GetFeatureConfigsActionHandler.swift index f50cacc0c8d..b9511e80770 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/Feature configurations/GetFeatureConfigsActionHandler.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/Feature configurations/GetFeatureConfigsActionHandler.swift @@ -67,7 +67,7 @@ final class GetFeatureConfigsActionHandler: ActionHandler.self, from: data) repository.storeE2EI(.init(status: response.status, config: response.config)) - case .channels, .consumableNotifications, .allowedGlobalOperations, .cells, .assetAuditLog: + case .channels, .consumableNotifications, .allowedGlobalOperations, .cells, .assetAuditLog, .cellsInternal: WireLogger.featureConfigs.warn( "decoding unsupported feature config: \"\(featureName)\", this should not happen", attributes: .safePublic diff --git a/wire-ios-request-strategy/Sources/Request Strategies/MLS/Actions/FetchBackendMLSPublicKeysActionHandler.swift b/wire-ios-request-strategy/Sources/Request Strategies/MLS/Actions/FetchBackendMLSPublicKeysActionHandler.swift index 54afcc38bff..f3878152b80 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/MLS/Actions/FetchBackendMLSPublicKeysActionHandler.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/MLS/Actions/FetchBackendMLSPublicKeysActionHandler.swift @@ -32,7 +32,7 @@ class FetchBackendMLSPublicKeysActionHandler: ActionHandler action.fail(with: .endpointUnavailable) return nil - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: guard let payloadData = RequestPayload(qualified_users: action.userIDs).payloadData(), let payloadString = String(bytes: payloadData, encoding: .utf8) @@ -80,7 +80,7 @@ final class FetchUserClientsActionHandler: ActionHandler case .v0: return - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: switch response.httpStatus { case 200: guard let rawData = response.rawData else { diff --git a/wire-ios-request-strategy/Sources/Request Strategies/User Clients/FetchingClientRequestStrategy.swift b/wire-ios-request-strategy/Sources/Request Strategies/User Clients/FetchingClientRequestStrategy.swift index 18a2c49c020..2eed26e0492 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/User Clients/FetchingClientRequestStrategy.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/User Clients/FetchingClientRequestStrategy.swift @@ -127,7 +127,7 @@ public final class FetchingClientRequestStrategy: AbstractRequestStrategy { self.userClientsByUserID.sync(identifiers: userIdSet) } - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: let domain = if let domain = user.domain, !domain.isEmpty { domain } else { localDomain } if let domain { let qualifiedID = QualifiedID(uuid: userID, domain: domain) @@ -199,7 +199,7 @@ extension FetchingClientRequestStrategy: ZMContextChangeTracker, ZMContextChange result.1.append(userClientID) } - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: if let qualifiedID = qualifiedIDWithFallback(from: userClient) { result.0.append(qualifiedID) } @@ -349,7 +349,7 @@ final class UserClientByQualifiedUserIDTranscoder: IdentifierObjectSyncTranscode case .v1: return v1Request(for: identifiers) - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: return v2Request(for: identifiers, apiVersion: apiVersion) } } @@ -409,7 +409,7 @@ final class UserClientByQualifiedUserIDTranscoder: IdentifierObjectSyncTranscode completionHandler() return - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: WaitingGroupTask(context: managedObjectContext) { [self] in await commonResponseHandling(response: response, for: identifiers) completionHandler() diff --git a/wire-ios-request-strategy/Sources/Request Strategies/User Clients/VerifyLegalHoldRequestStrategyTests.swift b/wire-ios-request-strategy/Sources/Request Strategies/User Clients/VerifyLegalHoldRequestStrategyTests.swift index 6d76d451807..be7b38cb318 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/User Clients/VerifyLegalHoldRequestStrategyTests.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/User Clients/VerifyLegalHoldRequestStrategyTests.swift @@ -117,7 +117,7 @@ class VerifyLegalHoldRequestStrategyTests: MessagingTestBase { var expectedPath = switch apiVersion { case .v0: "/conversations/\(conversation.remoteIdentifier!.transportString())/otr/messages" - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: "/v\(apiVersion.rawValue)/conversations/\(conversation.domain!)/\(conversation.remoteIdentifier!.transportString())/proteus/messages" } @@ -177,7 +177,7 @@ class VerifyLegalHoldRequestStrategyTests: MessagingTestBase { ClientUpdateResponse(missing: clientListByUserID).transportData case .v1, .v2, .v3: Payload.MessageSendingStatusV1(missing: [self.otherUser.domain!: clientListByUserID]).transportData - case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: Payload.MessageSendingStatusV4(missing: [self.otherUser.domain!: clientListByUserID]).transportData } @@ -238,7 +238,7 @@ class VerifyLegalHoldRequestStrategyTests: MessagingTestBase { ClientUpdateResponse(missing: clientListByUserID).transportData case .v1, .v2, .v3: Payload.MessageSendingStatusV1(missing: [self.otherUser.domain!: clientListByUserID]).transportData - case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: Payload.MessageSendingStatusV4(missing: [self.otherUser.domain!: clientListByUserID]).transportData } @@ -297,7 +297,7 @@ class VerifyLegalHoldRequestStrategyTests: MessagingTestBase { ClientUpdateResponse(missing: ClientListByUser()).transportData case .v1, .v2, .v3: Payload.MessageSendingStatusV1(missing: UserListByDomain()).transportData - case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: Payload.MessageSendingStatusV4(missing: UserListByDomain()).transportData } @@ -347,7 +347,7 @@ class VerifyLegalHoldRequestStrategyTests: MessagingTestBase { ClientUpdateResponse(missing: clientListByUserID).transportData case .v1, .v2, .v3: Payload.MessageSendingStatusV1(missing: [selfUser.domain!: clientListByUserID]).transportData - case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: Payload.MessageSendingStatusV4(missing: [selfUser.domain!: clientListByUserID]).transportData } diff --git a/wire-ios-request-strategy/Sources/Request Strategies/User/UserProfileRequestStrategy.swift b/wire-ios-request-strategy/Sources/Request Strategies/User/UserProfileRequestStrategy.swift index c5bbfdf821b..69f10f0eb89 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/User/UserProfileRequestStrategy.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/User/UserProfileRequestStrategy.swift @@ -129,7 +129,7 @@ public class UserProfileRequestStrategy: AbstractRequestStrategy, IdentifierObje case .v0: userProfileByID.sync(identifiers: users.compactMap(\.remoteIdentifier)) - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: if let qualifiedUserIDs = users.qualifiedUserIDs { userProfileByQualifiedID.sync(identifiers: qualifiedUserIDs) } else if let localDomain { @@ -433,7 +433,7 @@ class UserProfileByQualifiedIDTranscoder: IdentifierObjectSyncTranscoder { let missingIdentifiers = identifiers.subtracting(payload.compactMap(\.qualifiedID)) markUserProfilesAsFetched(missingIdentifiers) - case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: guard let rawData = response.rawData, let payload = Payload.UserProfilesV4(rawData, decoder: decoder) diff --git a/wire-ios-request-strategy/Sources/Request Strategies/User/UserProfileRequestStrategyTests.swift b/wire-ios-request-strategy/Sources/Request Strategies/User/UserProfileRequestStrategyTests.swift index 5ea25463dd6..9e632219247 100644 --- a/wire-ios-request-strategy/Sources/Request Strategies/User/UserProfileRequestStrategyTests.swift +++ b/wire-ios-request-strategy/Sources/Request Strategies/User/UserProfileRequestStrategyTests.swift @@ -551,7 +551,7 @@ class UserProfileRequestStrategyTests: MessagingTestBase { switch apiVersion { case .v0, .v1, .v2, .v3: payloadData = userProfiles.payloadData() - case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: let userProfiles = Payload.UserProfilesV4(found: userProfiles, failed: failed) payloadData = userProfiles.payloadData() } diff --git a/wire-ios-sync-engine/Source/Data Model/Conversation+AccessMode.swift b/wire-ios-sync-engine/Source/Data Model/Conversation+AccessMode.swift index f484c2e0469..f70f60fbbce 100644 --- a/wire-ios-sync-engine/Source/Data Model/Conversation+AccessMode.swift +++ b/wire-ios-sync-engine/Source/Data Model/Conversation+AccessMode.swift @@ -234,7 +234,7 @@ enum WirelessRequestFactory { switch apiVersion { - case .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: let domain = if let domain = conversation.domain, !domain.isEmpty { domain } else { localDomain } guard let domain else { fatal("no domain associated with conversation, can't make the request") diff --git a/wire-ios-sync-engine/Source/Synchronization/Strategies/Asset Deletion/AssetDeletionRequestStrategy.swift b/wire-ios-sync-engine/Source/Synchronization/Strategies/Asset Deletion/AssetDeletionRequestStrategy.swift index 3d7f98b785d..3cf850f6565 100644 --- a/wire-ios-sync-engine/Source/Synchronization/Strategies/Asset Deletion/AssetDeletionRequestStrategy.swift +++ b/wire-ios-sync-engine/Source/Synchronization/Strategies/Asset Deletion/AssetDeletionRequestStrategy.swift @@ -32,7 +32,7 @@ private extension AssetRequestFactory { switch apiVersion { case .v0, .v1: path = "/assets/v3/\(identifier)" - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: guard let localDomain else { return nil } diff --git a/wire-ios-sync-engine/Source/Synchronization/Strategies/CallingRequestStrategy.swift b/wire-ios-sync-engine/Source/Synchronization/Strategies/CallingRequestStrategy.swift index fd74af8188c..ccc605edec5 100644 --- a/wire-ios-sync-engine/Source/Synchronization/Strategies/CallingRequestStrategy.swift +++ b/wire-ios-sync-engine/Source/Synchronization/Strategies/CallingRequestStrategy.swift @@ -629,7 +629,7 @@ extension CallingRequestStrategy { case .v0: // `nestedContainer` contains all the user ids with no notion of domain, we can extract clients directly allClients = try extractClientsFromContainer(nestedContainer, nil) - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: // `nestedContainer` has further nested containers each dynamically keyed by a domain name. // we need to loop over each container to extract the clients. try nestedContainer.allKeys.forEach { domainKey in diff --git a/wire-ios-sync-engine/Source/Synchronization/Strategies/SearchUserImageStrategy.swift b/wire-ios-sync-engine/Source/Synchronization/Strategies/SearchUserImageStrategy.swift index 4a02558ac1d..8f08ba91982 100644 --- a/wire-ios-sync-engine/Source/Synchronization/Strategies/SearchUserImageStrategy.swift +++ b/wire-ios-sync-engine/Source/Synchronization/Strategies/SearchUserImageStrategy.swift @@ -175,7 +175,7 @@ final class SearchUserImageStrategy: AbstractRequestStrategy { path = "/assets/v4/\(domain)/\(key)" - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: let domain = requestedUserDomain[user]?.isEmpty == false ? requestedUserDomain[user]! : BackendInfo .domain guard let domain else { return nil } diff --git a/wire-ios-sync-engine/Source/Synchronization/Strategies/TeamDownloadRequestStrategy.swift b/wire-ios-sync-engine/Source/Synchronization/Strategies/TeamDownloadRequestStrategy.swift index bd389bb96cb..9d31754e271 100644 --- a/wire-ios-sync-engine/Source/Synchronization/Strategies/TeamDownloadRequestStrategy.swift +++ b/wire-ios-sync-engine/Source/Synchronization/Strategies/TeamDownloadRequestStrategy.swift @@ -210,7 +210,7 @@ public final class TeamDownloadRequestStrategy: AbstractRequestStrategy, ZMConte switch apiVersion { case .v0, .v1, .v2, .v3: return TeamDownloadRequestFactory.getTeamsRequest(apiVersion: apiVersion) - case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: guard let teamID = ZMUser.selfUser(in: managedObjectContext).teamIdentifier else { syncStatus.finishCurrentSyncPhase(phase: expectedSyncPhase) return nil @@ -236,7 +236,7 @@ public final class TeamDownloadRequestStrategy: AbstractRequestStrategy, ZMConte syncStatus.finishCurrentSyncPhase(phase: expectedSyncPhase) - case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: guard let rawData = response.rawData, let teamPayload = TeamPayload(rawData) diff --git a/wire-ios-sync-engine/Source/Synchronization/Strategies/TeamImageAssetUpdateStrategy.swift b/wire-ios-sync-engine/Source/Synchronization/Strategies/TeamImageAssetUpdateStrategy.swift index ca8a40af210..a8f62ed63fc 100644 --- a/wire-ios-sync-engine/Source/Synchronization/Strategies/TeamImageAssetUpdateStrategy.swift +++ b/wire-ios-sync-engine/Source/Synchronization/Strategies/TeamImageAssetUpdateStrategy.swift @@ -85,7 +85,7 @@ public final class TeamImageAssetUpdateStrategy: AbstractRequestStrategy, ZMCont switch apiVersion { case .v0, .v1: path = "/assets/v3/\(assetId)" - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: guard let localDomain else { return nil } path = "/assets/\(localDomain)/\(assetId)" } diff --git a/wire-ios-sync-engine/Source/Synchronization/Strategies/TypingStrategy.swift b/wire-ios-sync-engine/Source/Synchronization/Strategies/TypingStrategy.swift index 03393402e03..01b466db00c 100644 --- a/wire-ios-sync-engine/Source/Synchronization/Strategies/TypingStrategy.swift +++ b/wire-ios-sync-engine/Source/Synchronization/Strategies/TypingStrategy.swift @@ -237,7 +237,7 @@ public class TypingStrategy: AbstractRequestStrategy, TearDownCapable, ZMEventCo case .v0, .v1, .v2: path = "/conversations/\(remoteIdentifier.transportString())/typing" - case .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: let domain = if let domain = conversation.domain, !domain.isEmpty { domain } else { localDomain } guard let domain else { return nil } path = "/conversations/\(domain)/\(remoteIdentifier.transportString())/typing" diff --git a/wire-ios-sync-engine/Source/Synchronization/Strategies/UserImageAssetUpdateStrategy.swift b/wire-ios-sync-engine/Source/Synchronization/Strategies/UserImageAssetUpdateStrategy.swift index b1244897f81..759817d1bbf 100644 --- a/wire-ios-sync-engine/Source/Synchronization/Strategies/UserImageAssetUpdateStrategy.swift +++ b/wire-ios-sync-engine/Source/Synchronization/Strategies/UserImageAssetUpdateStrategy.swift @@ -225,7 +225,7 @@ public final class UserImageAssetUpdateStrategy: AbstractRequestStrategy, ZMCont path = "/assets/v4/\(domain)/\(assetId)" - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: let domain = if let domain = user.domain, !domain.isEmpty { domain } else { localDomain } guard let domain else { return nil } diff --git a/wire-ios-sync-engine/Source/UserSession/UserSession.swift b/wire-ios-sync-engine/Source/UserSession/UserSession.swift index 77cb20a6bc5..000d6537568 100644 --- a/wire-ios-sync-engine/Source/UserSession/UserSession.swift +++ b/wire-ios-sync-engine/Source/UserSession/UserSession.swift @@ -226,6 +226,8 @@ public protocol UserSession: AnyObject { var isWireCellsEnabled: Bool { get } + var wireCellsBackendURL: URL? { get } + var isEnterpriseUser: Bool { get } func fetchAllClients() diff --git a/wire-ios-sync-engine/Source/UserSession/ZMUserSession/AppVersionMigrations/AppVersionMigration_4_12_0.swift b/wire-ios-sync-engine/Source/UserSession/ZMUserSession/AppVersionMigrations/AppVersionMigration_4_12_0.swift index aa24fdca04d..3e81f6e9233 100644 --- a/wire-ios-sync-engine/Source/UserSession/ZMUserSession/AppVersionMigrations/AppVersionMigration_4_12_0.swift +++ b/wire-ios-sync-engine/Source/UserSession/ZMUserSession/AppVersionMigrations/AppVersionMigration_4_12_0.swift @@ -1,6 +1,6 @@ // // Wire -// Copyright (C) 2025 Wire Swiss GmbH +// Copyright (C) 2026 Wire Swiss GmbH // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/wire-ios-sync-engine/Source/UserSession/ZMUserSession/ZMUserSession.swift b/wire-ios-sync-engine/Source/UserSession/ZMUserSession/ZMUserSession.swift index 1abb96a7acf..444975214fc 100644 --- a/wire-ios-sync-engine/Source/UserSession/ZMUserSession/ZMUserSession.swift +++ b/wire-ios-sync-engine/Source/UserSession/ZMUserSession/ZMUserSession.swift @@ -172,8 +172,16 @@ public final class ZMUserSession: NSObject { return featureRepository.fetchCells() } + public var wireCellsBackendURL: URL? { + let featureRepository = LegacyFeatureRepository(context: coreDataStack.viewContext) + return featureRepository.fetchCellsInternal()?.config.backend.url + } + public var isWireCellsEnabled: Bool { - wireCellsFeature.status == .enabled + let isFeatureEnabled = wireCellsFeature.status == .enabled + let hasBackendURL = wireCellsBackendURL != nil + + return isFeatureEnabled && hasBackendURL } public var conferenceCallingFeature: Feature.ConferenceCalling { diff --git a/wire-ios-sync-engine/Support/Sourcery/generated/AutoMockable.manual.swift b/wire-ios-sync-engine/Support/Sourcery/generated/AutoMockable.manual.swift index 232d1e7f292..cc425829b00 100644 --- a/wire-ios-sync-engine/Support/Sourcery/generated/AutoMockable.manual.swift +++ b/wire-ios-sync-engine/Support/Sourcery/generated/AutoMockable.manual.swift @@ -511,6 +511,8 @@ public class MockUserSession: UserSession { public var underlyingMlsFeature: Feature.MLS! public var isWireCellsEnabled: Bool = false + + public var wireCellsBackendURL: URL? = nil public var isEnterpriseUser: Bool = false diff --git a/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/AssetDeletionRequestStrategyTests.swift b/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/AssetDeletionRequestStrategyTests.swift index fe6317fcf33..85610ff53c6 100644 --- a/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/AssetDeletionRequestStrategyTests.swift +++ b/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/AssetDeletionRequestStrategyTests.swift @@ -132,7 +132,7 @@ extension AssetDeletionRequestStrategyTests { "/assets/v3/\(identifier)" case .v1: "/v1/assets/v3/\(identifier)" - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: "/v\(apiVersion.rawValue)/assets/\(domain)/\(identifier)" } XCTAssertNotNil(request) diff --git a/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/SearchUserImageStrategyTests.swift b/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/SearchUserImageStrategyTests.swift index 7bd79430089..20dbd6a9060 100644 --- a/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/SearchUserImageStrategyTests.swift +++ b/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/SearchUserImageStrategyTests.swift @@ -307,7 +307,7 @@ final class SearchUserImageStrategyTests: MessagingTest { "/assets/v3/\(assetID)" case .v1: "/v1/assets/v4/\(domain)/\(assetID)" - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: "/v\(apiVersion.rawValue)/assets/\(domain)/\(assetID)" } diff --git a/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/UserImageAssetUpdateStrategyTests.swift b/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/UserImageAssetUpdateStrategyTests.swift index c72911d3af6..1a0d435f517 100644 --- a/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/UserImageAssetUpdateStrategyTests.swift +++ b/wire-ios-sync-engine/Tests/Source/Synchronization/Strategies/UserImageAssetUpdateStrategyTests.swift @@ -355,7 +355,7 @@ class UserImageAssetUpdateStrategyTests: MessagingTest { "/assets/v3/\(assetId)" case .v1: "/v1/assets/v4/\(domain)/\(assetId)" - case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: "/v\(apiVersion.rawValue)/assets/\(domain)/\(assetId)" } diff --git a/wire-ios-sync-engine/Tests/Source/Synchronization/ZMConversationAccessModeTests.swift b/wire-ios-sync-engine/Tests/Source/Synchronization/ZMConversationAccessModeTests.swift index 693c9f0597f..7197499acd2 100644 --- a/wire-ios-sync-engine/Tests/Source/Synchronization/ZMConversationAccessModeTests.swift +++ b/wire-ios-sync-engine/Tests/Source/Synchronization/ZMConversationAccessModeTests.swift @@ -113,7 +113,7 @@ public class ZMConversationAccessModeTests: MessagingTest { switch apiVersion { case .v0: XCTAssertEqual(request.path, "/conversations/\(conversation.remoteIdentifier!.transportString())/access") - case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13: + case .v1, .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v9, .v10, .v11, .v12, .v13, .v14: XCTAssertEqual( request.path, "/v\(apiVersion.rawValue)/conversations/\(conversation.remoteIdentifier!.transportString())/access" diff --git a/wire-ios-transport/Source/Public/APIVersion.swift b/wire-ios-transport/Source/Public/APIVersion.swift index df2f6a30592..5854028371f 100644 --- a/wire-ios-transport/Source/Public/APIVersion.swift +++ b/wire-ios-transport/Source/Public/APIVersion.swift @@ -34,6 +34,7 @@ public enum APIVersion: Int32 { case v11 case v12 case v13 + case v14 } // MARK: - CaseIterable diff --git a/wire-ios/Tests/Mocks/UserSessionMock.swift b/wire-ios/Tests/Mocks/UserSessionMock.swift index 502a7fcd2f4..1c2b1bfb93e 100644 --- a/wire-ios/Tests/Mocks/UserSessionMock.swift +++ b/wire-ios/Tests/Mocks/UserSessionMock.swift @@ -407,6 +407,8 @@ final class UserSessionMock: UserSession { var isWireCellsEnabled: Bool = false + var wireCellsBackendURL: URL? + var isEnterpriseUser: Bool = false func fetchAllClients() {} diff --git a/wire-ios/Wire-iOS/Generated/Strings+Generated.swift b/wire-ios/Wire-iOS/Generated/Strings+Generated.swift index 407e9ce8ba7..b581266c8de 100644 --- a/wire-ios/Wire-iOS/Generated/Strings+Generated.swift +++ b/wire-ios/Wire-iOS/Generated/Strings+Generated.swift @@ -1145,21 +1145,7 @@ internal enum L10n { internal enum InfoPlist { /// Allow Wire to access your camera so you can place video calls and send photos. internal static let nsCameraUsageDescription = L10n.tr("InfoPlist", "NSCameraUsageDescription", fallback: "Allow Wire to access your camera so you can place video calls and send photos.") - /// * Wire - /// * Copyright (C) 2025 Wire Swiss GmbH - /// * - /// * This program is free software: you can redistribute it and/or modify - /// * it under the terms of the GNU General Public License as published by - /// * the Free Software Foundation, either version 3 of the License, or - /// * (at your option) any later version. - /// * - /// * This program is distributed in the hope that it will be useful, - /// * but WITHOUT ANY WARRANTY; without even the implied warranty of - /// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - /// * GNU General Public License for more details. - /// * - /// * You should have received a copy of the GNU General Public License - /// * along with this program. If not, see http://www.gnu.org/licenses/. + /// Allow Wire to access your contacts to connect you with others. We anonymize all information before uploading it to our server and do not share it with anyone else. internal static let nsContactsUsageDescription = L10n.tr("InfoPlist", "NSContactsUsageDescription", fallback: "Allow Wire to access your contacts to connect you with others. We anonymize all information before uploading it to our server and do not share it with anyone else.") /// Is shown to the user when app is locked with AppLock feature on the phone that supports Face ID internal static let nsFaceIDUsageDescription = L10n.tr("InfoPlist", "NSFaceIDUsageDescription", fallback: "In order to authenticate in the app allow Wire to access the Face ID feature.") diff --git a/wire-ios/Wire-iOS/Resources/Localization/sl.lproj/InfoPlist.strings b/wire-ios/Wire-iOS/Resources/Localization/sl.lproj/InfoPlist.strings index 0ad83b22041..a51717b24b7 100644 --- a/wire-ios/Wire-iOS/Resources/Localization/sl.lproj/InfoPlist.strings +++ b/wire-ios/Wire-iOS/Resources/Localization/sl.lproj/InfoPlist.strings @@ -1,6 +1,6 @@ /* * Wire - * Copyright (C) 2025 Wire Swiss GmbH + * Copyright (C) 2026 Wire Swiss GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/wire-ios/Wire-iOS/Sources/UserInterface/MainController/ZClientControllerBuilder.swift b/wire-ios/Wire-iOS/Sources/UserInterface/MainController/ZClientControllerBuilder.swift index 08cf4cbf3bd..56620bad8f8 100644 --- a/wire-ios/Wire-iOS/Sources/UserInterface/MainController/ZClientControllerBuilder.swift +++ b/wire-ios/Wire-iOS/Sources/UserInterface/MainController/ZClientControllerBuilder.swift @@ -20,19 +20,43 @@ import WireCallingAssembly import WireCommonComponents import WireData @preconcurrency import WireDataModel +import WireLogging import WireMessagingAssembly import WireMessagingDomain import WireNetwork @preconcurrency import WireSyncEngine import WireTransport -struct ZClientControllerBuilder { +final class ZClientControllerBuilder { private(set) var account: Account private(set) var userSession: UserSession private(set) var trackingManager: TrackingManager? let legacyEnvironment: WireTransport.BackendEnvironment let newEnvironment: WireNetwork.BackendEnvironment2? + private lazy var wireCellsBackendURL: URL? = { + let contextProvider = userSession.contextProvider + let syncContext = contextProvider.syncContext + let featureRepository = LegacyFeatureRepository(context: syncContext) + + return syncContext.performAndWait { + featureRepository.fetchCellsInternal()?.config.backend.url + } + }() + + init( + account: Account, + userSession: UserSession, + trackingManager: TrackingManager? = nil, + legacyEnvironment: WireTransport.BackendEnvironment, + newEnvironment: WireNetwork.BackendEnvironment2? + ) { + self.account = account + self.userSession = userSession + self.trackingManager = trackingManager + self.legacyEnvironment = legacyEnvironment + self.newEnvironment = newEnvironment + } @MainActor func build(router: AuthenticatedRouterProtocol) -> ZClientViewController { @@ -56,8 +80,20 @@ struct ZClientControllerBuilder { @MainActor private func buildWireMessagingFactory() -> any WireMessagingFactoryProtocol { - WireMessagingFactory( - serverURL: newEnvironment?.config.endpoints.restAPIURL ?? legacyEnvironment.backendURL, + let cellsURLResolver: @Sendable () throws -> URL = { [weak self] in + enum Failure: Error { + case missingCellsBackendURL + } + + guard let self, let wireCellsBackendURL else { + throw Failure.missingCellsBackendURL + } + + return wireCellsBackendURL + } + + return WireMessagingFactory( + cellsURLResolver: cellsURLResolver, // TODO: [WPB-18798] Temporary fix, when multibackend is on we use new backend environment, when off we use the legacy one accessToken: DefaultAccessTokenProvider(userSession: userSession), fileCache: userSession.fileAssetCache, diff --git a/wire-ios/Wire-iOS/Sources/UserInterface/MainController/ZClientViewController.swift b/wire-ios/Wire-iOS/Sources/UserInterface/MainController/ZClientViewController.swift index b1bf01aea5e..e1481a72cbc 100644 --- a/wire-ios/Wire-iOS/Sources/UserInterface/MainController/ZClientViewController.swift +++ b/wire-ios/Wire-iOS/Sources/UserInterface/MainController/ZClientViewController.swift @@ -296,26 +296,33 @@ final class ZClientViewController: UIViewController { .sink { [weak self] featureState in guard let self else { return } switch featureState.name { - case .cells where featureState.isEnabled: - let filesBrowserView = wireMessagingFactory.makeFilesBrowserView { [weak self] in - guard let self else { return .default } - let selfUserColorRawValue = userSession.selfUser.accentColorValue - return WireAccentColor(rawValue: selfUserColorRawValue) ?? .default - } - if UIDevice.current.userInterfaceIdiom == .pad { - guard !sidebarViewController.showFiles else { break } - sidebarViewController.showFiles = true - mainTabBarController.filesUI = filesBrowserView - } else { - guard mainTabBarController.filesUI == nil else { break } - mainTabBarController.filesUI = filesBrowserView - } + case .cells, .cellsInternal: + setupWireCellsFilesTab() default: break } } } + private func setupWireCellsFilesTab() { + guard userSession.isWireCellsEnabled else { return } + + let filesBrowserView = wireMessagingFactory.makeFilesBrowserView { [weak self] in + guard let self else { return .default } + let selfUserColorRawValue = userSession.selfUser.accentColorValue + return WireAccentColor(rawValue: selfUserColorRawValue) ?? .default + } + + if UIDevice.current.userInterfaceIdiom == .pad { + guard !sidebarViewController.showFiles else { return } + sidebarViewController.showFiles = true + mainTabBarController.filesUI = filesBrowserView + } else { + guard mainTabBarController.filesUI == nil else { return } + mainTabBarController.filesUI = filesBrowserView + } + } + @discardableResult private func attemptToPresentInitialConversation() -> Bool { var stateRestored = false