diff --git a/Development/UID2SDKDevelopmentApp/UID2SDKDevelopmentApp/Info.plist b/Development/UID2SDKDevelopmentApp/UID2SDKDevelopmentApp/Info.plist index 0c67376..01d959e 100644 --- a/Development/UID2SDKDevelopmentApp/UID2SDKDevelopmentApp/Info.plist +++ b/Development/UID2SDKDevelopmentApp/UID2SDKDevelopmentApp/Info.plist @@ -1,5 +1,8 @@ - + + UID2EnvironmentEUID + + diff --git a/Development/UID2SDKDevelopmentApp/UID2SDKDevelopmentApp/Localizable.strings b/Development/UID2SDKDevelopmentApp/UID2SDKDevelopmentApp/Localizable.strings index 48024b2..753cb0f 100644 --- a/Development/UID2SDKDevelopmentApp/UID2SDKDevelopmentApp/Localizable.strings +++ b/Development/UID2SDKDevelopmentApp/UID2SDKDevelopmentApp/Localizable.strings @@ -8,7 +8,8 @@ "common.nil" = "Nil"; -"root.navigation.title" = "UID2 SDK Dev App"; +"root.uid2.navigation.title" = "UID2 SDK Dev App"; +"root.euid.navigation.title" = "EUID SDK Dev App"; "root.title.identitypackage" = "Current Identity"; "root.label.error" = "Error Occurred"; "root.button.reset" = "Reset"; diff --git a/Development/UID2SDKDevelopmentApp/UID2SDKDevelopmentApp/Networking/AppUID2Client.swift b/Development/UID2SDKDevelopmentApp/UID2SDKDevelopmentApp/Networking/AppUID2Client.swift index d04ec19..bfe4b86 100644 --- a/Development/UID2SDKDevelopmentApp/UID2SDKDevelopmentApp/Networking/AppUID2Client.swift +++ b/Development/UID2SDKDevelopmentApp/UID2SDKDevelopmentApp/Networking/AppUID2Client.swift @@ -173,6 +173,7 @@ internal final class AppUID2Client: Sendable { func decryptResponse(_ b64Secret: String, _ responseData: Data, _ isRefresh: Bool = false) -> Data? { // Confirm that responseData is Base64 + // swiftlint:disable:next non_optional_string_data_conversion guard let base64String = String(data: responseData, encoding: .utf8), let decodedData = Data(base64Encoded: base64String, options: .ignoreUnknownCharacters) else { return responseData @@ -211,6 +212,7 @@ internal final class AppUID2Client: Sendable { payload = decryptedData.subdata(in: 16.. Self { + self.init( + subscriptionID: "toPh8vgJgt", + appName: Bundle.main.bundleIdentifier!, + // swiftlint:disable:next line_length + serverPublicKeyString: "UID2-X-I-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKAbPfOz7u25g1fL6riU7p2eeqhjmpALPeYoyjvZmZ1xM2NM8UeOmDZmCIBnKyRZ97pz5bMCjrs38WM22O7LJuw==" + ) + } + + static func euid() -> Self { + self.init( + subscriptionID: "w6yPQzN4dA", + appName: Bundle.main.bundleIdentifier!, + // swiftlint:disable:next line_length + serverPublicKeyString: "EUID-X-I-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEH/k7HYGuWhjhCo8nXgj/ypClo5kek7uRKvzCGwj04Y1eXOWmHDOLAQVCPquZdfVVezIpABNAl9zvsSEC7g+ZGg==" + ) + } + } +} + @MainActor -class RootViewModel: ObservableObject { - +final class RootViewModel: ObservableObject { + + let isEUID: Bool + @Published private(set) var uid2Identity: UID2Identity? { didSet { error = nil @@ -25,19 +54,33 @@ class RootViewModel: ObservableObject { /// `UID2Settings` must be configured prior to accessing the `UID2Manager` instance. /// Configuring them here makes it less likely that an access occurs before configuration. - private let manager: UID2Manager = { + private let manager: UID2Manager + + private let configuration: Configuration + + private let log = OSLog(subsystem: "com.uid2.UID2SDKDevelopmentApp", category: "RootViewModel") + + init() { + isEUID = Bundle.main.object(forInfoDictionaryKey: "UID2EnvironmentEUID") as? Bool ?? false + UID2Settings.shared.isLoggingEnabled = true // Only the development app should use the integration environment. // If you have copied the dev app for testing, you probably want to use the default // environment, which is production. if Bundle.main.bundleIdentifier == "com.uid2.UID2SDKDevelopmentApp" { - UID2Settings.shared.environment = .custom(url: URL(string: "https://operator-integ.uidapi.com")!) + UID2Settings.shared.euidEnvironment = .custom(url: URL(string: "https://integ.euid.eu/v2")!) + UID2Settings.shared.uid2Environment = .custom(url: URL(string: "https://operator-integ.uidapi.com")!) } - return UID2Manager.shared - }() - - init() { + if isEUID { + os_log("Configured for EUID", log: log, type: .info) + configuration = .euid() + manager = EUIDManager.shared + } else { + os_log("Configured for UID2", log: log, type: .info) + configuration = .uid2() + manager = UID2Manager.shared + } Task { for await state in await manager.stateValues() { self.uid2Identity = state?.identity @@ -130,17 +173,13 @@ class RootViewModel: ObservableObject { } func clientSideGenerate(identity: IdentityType) { - let subscriptionID = "toPh8vgJgt" - // swiftlint:disable:next line_length - let serverPublicKeyString = "UID2-X-I-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKAbPfOz7u25g1fL6riU7p2eeqhjmpALPeYoyjvZmZ1xM2NM8UeOmDZmCIBnKyRZ97pz5bMCjrs38WM22O7LJuw==" - Task { do { try await manager.generateIdentity( identity, - subscriptionID: subscriptionID, - serverPublicKey: serverPublicKeyString, - appName: Bundle.main.bundleIdentifier! + subscriptionID: configuration.subscriptionID, + serverPublicKey: configuration.serverPublicKeyString, + appName: configuration.appName ) } catch { self.error = error diff --git a/Sources/UID2/EUIDManager.swift b/Sources/UID2/EUIDManager.swift new file mode 100644 index 0000000..d1ccd02 --- /dev/null +++ b/Sources/UID2/EUIDManager.swift @@ -0,0 +1,17 @@ +// +// EUIDManager.swift +// + +import Foundation + +public final class EUIDManager { + + /// Singleton access point for EUID Manager + /// Returns a manager configured for use with EUID. + public static let shared: UID2Manager = { + UID2Manager( + environment: Environment(UID2Settings.shared.euidEnvironment), + account: .euid + ) + }() +} diff --git a/Sources/UID2/Environment.swift b/Sources/UID2/Environment.swift index 56257ce..533c7f4 100644 --- a/Sources/UID2/Environment.swift +++ b/Sources/UID2/Environment.swift @@ -7,28 +7,74 @@ import Foundation -/// For more information, see https://unifiedid.com/docs/getting-started/gs-environments -public struct Environment: Hashable, Sendable { +/// Internal Environment representation +struct Environment: Hashable, Sendable { /// API base URL - var endpoint: URL - - /// Equivalent to `ohio` - public static let production = ohio - - /// AWS US East (Ohio) - public static let ohio = Self(endpoint: URL(string: "https://prod.uidapi.com")!) - /// AWS US West (Oregon) - public static let oregon = Self(endpoint: URL(string: "https://usw.prod.uidapi.com")!) - /// AWS Asia Pacific (Singapore) - public static let singapore = Self(endpoint: URL(string: "https://sg.prod.uidapi.com")!) - /// AWS Asia Pacific (Sydney) - public static let sydney = Self(endpoint: URL(string: "https://au.prod.uidapi.com")!) - /// AWS Asia Pacific (Tokyo) - public static let tokyo = Self(endpoint: URL(string: "https://jp.prod.uidapi.com")!) - - /// A custom endpoint - public static func custom(url: URL) -> Self { - Self(endpoint: url) + let endpoint: URL + let isProduction: Bool +} + +extension Environment { + init(_ environment: UID2.Environment) { + endpoint = environment.endpoint + isProduction = (environment == .production) + } + + init(_ environment: EUID.Environment) { + endpoint = environment.endpoint + isProduction = (environment == .production) + } +} + +// Namespaces +public enum EUID {} +public enum UID2 {} + +extension UID2 { + /// For more information, see https://unifiedid.com/docs/getting-started/gs-environments + public struct Environment: Hashable, Sendable { + + /// API base URL + var endpoint: URL + + /// Equivalent to `ohio` + public static let production = ohio + + /// AWS US East (Ohio) + public static let ohio = Self(endpoint: URL(string: "https://prod.uidapi.com")!) + /// AWS US West (Oregon) + public static let oregon = Self(endpoint: URL(string: "https://usw.prod.uidapi.com")!) + /// AWS Asia Pacific (Singapore) + public static let singapore = Self(endpoint: URL(string: "https://sg.prod.uidapi.com")!) + /// AWS Asia Pacific (Sydney) + public static let sydney = Self(endpoint: URL(string: "https://au.prod.uidapi.com")!) + /// AWS Asia Pacific (Tokyo) + public static let tokyo = Self(endpoint: URL(string: "https://jp.prod.uidapi.com")!) + + /// A custom endpoint + public static func custom(url: URL) -> Self { + Self(endpoint: url) + } + } +} + +extension EUID { + /// See https://euid.eu/docs/getting-started/gs-environments + public struct Environment: Hashable, Sendable { + + /// API base URL + var endpoint: URL + + /// Equivalent to `london` + public static let production = london + + /// AWS EU West 2 (London) + public static let london = Self(endpoint: URL(string: "https://prod.euid.eu/v2")!) + + /// A custom endpoint + public static func custom(url: URL) -> Self { + Self(endpoint: url) + } } } diff --git a/Sources/UID2/KeychainManager.swift b/Sources/UID2/KeychainManager.swift index 8e9f2aa..1b059c4 100644 --- a/Sources/UID2/KeychainManager.swift +++ b/Sources/UID2/KeychainManager.swift @@ -6,8 +6,8 @@ import Foundation import Security extension Storage { - static func keychainStorage() -> Storage { - let storage = KeychainManager() + static func keychainStorage(account: Account) -> Storage { + let storage = KeychainManager(account: account) return .init( loadIdentity: { await storage.loadIdentity() }, saveIdentity: { await storage.saveIdentity($0) }, @@ -16,13 +16,23 @@ extension Storage { } } +/// These RawValue are used as persistence keys and must not be renamed +enum Account: String { + case uid2 = "uid2" // swiftlint:disable:this redundant_string_enum_value + case euid = "euid" // swiftlint:disable:this redundant_string_enum_value +} + /// Securely manages data in the Keychain actor KeychainManager { - private let attrAccount = "uid2" + private let attrAccount: Account private static let attrService = "auth-state" + init(account: Account = .uid2) { + attrAccount = account + } + func loadIdentity() -> IdentityPackage? { let query = query(with: [ String(kSecReturnData): true @@ -77,7 +87,7 @@ actor KeychainManager { private func query(with queryElements: [String: Any]) -> CFDictionary { let commonElements = [ String(kSecClass): kSecClassGenericPassword, - String(kSecAttrAccount): attrAccount, + String(kSecAttrAccount): attrAccount.rawValue, String(kSecAttrService): Self.attrService ] as [String: Any] diff --git a/Sources/UID2/Networking/DataEnvelope.swift b/Sources/UID2/Networking/DataEnvelope.swift index 389ce31..cc200d6 100644 --- a/Sources/UID2/Networking/DataEnvelope.swift +++ b/Sources/UID2/Networking/DataEnvelope.swift @@ -44,6 +44,8 @@ internal enum DataEnvelope { extension Data { /// A convenience initializer for converting from a Data representation of a base64 encoded string to its decoded Data. init?(base64EncodedData: Data, options: Data.Base64DecodingOptions = []) { + // https://github.com/realm/SwiftLint/issues/5263#issuecomment-2115182747 + // swiftlint:disable:next non_optional_string_data_conversion guard let base64String = String(data: base64EncodedData, encoding: .utf8) else { return nil } diff --git a/Sources/UID2/UID2Client.swift b/Sources/UID2/UID2Client.swift index c9c899b..d82e692 100644 --- a/Sources/UID2/UID2Client.swift +++ b/Sources/UID2/UID2Client.swift @@ -25,7 +25,7 @@ internal final class UID2Client: Sendable { init( sdkVersion: String, isLoggingEnabled: Bool = false, - environment: Environment = .production, + environment: Environment, session: NetworkSession = URLSession.shared, cryptoUtil: CryptoUtil = .liveValue ) { @@ -120,9 +120,11 @@ internal final class UID2Client: Sendable { let decoder = JSONDecoder.apiDecoder() guard response.statusCode == 200 else { let statusCode = response.statusCode + // https://github.com/realm/SwiftLint/issues/5263#issuecomment-2115182747 + // swiftlint:disable:next non_optional_string_data_conversion let responseText = String(data: data, encoding: .utf8) ?? "" os_log("Request failure (%d) %@", log: log, type: .error, statusCode, responseText) - if environment != .production { + if !environment.isProduction { os_log("Failed request is using non-production API endpoint %@, is this intentional?", log: log, type: .error, baseURL.description) } throw TokenGenerationError.requestFailure( diff --git a/Sources/UID2/UID2Manager.swift b/Sources/UID2/UID2Manager.swift index d9f5dba..becb00d 100644 --- a/Sources/UID2/UID2Manager.swift +++ b/Sources/UID2/UID2Manager.swift @@ -32,8 +32,13 @@ public final actor UID2Manager { } /// Singleton access point for UID2Manager - public static let shared = UID2Manager() - + public static let shared: UID2Manager = { + UID2Manager( + environment: Environment(UID2Settings.shared.uid2Environment), + account: .uid2 + ) + }() + /// Enable or Disable Automatic Refresh via RepeatingTimer public var automaticRefreshEnabled = true { didSet { @@ -103,15 +108,18 @@ public final actor UID2Manager { // MARK: - Defaults - internal init() { + init( + environment: Environment, + account: Account + ) { // App Supplied Properties - let environment: Environment - if let apiUrlOverride = Bundle.main.object(forInfoDictionaryKey: "UID2ApiUrl") as? String, + let clientEnvironment: Environment + if let apiUrlOverride = Bundle.main.object(forInfoDictionaryKey: "UID2ApiUrl") as? String, !apiUrlOverride.isEmpty, let apiUrl = URL(string: apiUrlOverride) { - environment = Environment(endpoint: apiUrl) + clientEnvironment = Environment(endpoint: apiUrl, isProduction: false) } else { - environment = UID2Settings.shared.environment + clientEnvironment = environment } let sdkVersion = UID2SDKProperties.getUID2SDKVersion() @@ -126,9 +134,9 @@ public final actor UID2Manager { uid2Client: UID2Client( sdkVersion: clientVersion, isLoggingEnabled: isLoggingEnabled, - environment: environment + environment: clientEnvironment ), - storage: .keychainStorage(), + storage: .keychainStorage(account: account), sdkVersion: sdkVersion, log: log ) @@ -453,4 +461,4 @@ internal struct DateGenerator { generate = { newValue } } } -} +} // swiftlint:disable:this file_length diff --git a/Sources/UID2/UID2Settings.swift b/Sources/UID2/UID2Settings.swift index cf89bf1..d62d2c7 100644 --- a/Sources/UID2/UID2Settings.swift +++ b/Sources/UID2/UID2Settings.swift @@ -32,18 +32,44 @@ public final class UID2Settings: @unchecked Sendable { } } - private var _environment = Environment.production + private var _uid2Environment = UID2.Environment.production + private var _euidEnvironment = EUID.Environment.production - /// API endpoint environment. The default value is `.production`. - public var environment: Environment { + /// UID2 API endpoint environment. The default value is `.production`. + @available(*, deprecated, renamed: "uid2Environment", message: "Use uid2Environment, or see also euid2Environment") + public var environment: UID2.Environment { + get { + uid2Environment + } + set { + uid2Environment = newValue + } + } + + /// UID2 API endpoint environment. The default value is `.production`. + public var uid2Environment: UID2.Environment { + get { + queue.sync { + _uid2Environment + } + } + set { + queue.sync { + _uid2Environment = newValue + } + } + } + + /// EUID API endpoint environment. The default value is `.production`. + public var euidEnvironment: EUID.Environment { get { queue.sync { - _environment + _euidEnvironment } } set { queue.sync { - _environment = newValue + _euidEnvironment = newValue } } } diff --git a/Tests/UID2Tests/Helpers/Client.swift b/Tests/UID2Tests/Helpers/Client.swift new file mode 100644 index 0000000..9f00695 --- /dev/null +++ b/Tests/UID2Tests/Helpers/Client.swift @@ -0,0 +1,24 @@ +// +// Client.swift +// + +import Foundation +@testable import UID2 + +extension UID2Client { + static func test( + sdkVersion: String = "TEST", + session: any NetworkSession = URLSession.shared, + cryptoUtil: CryptoUtil = .liveValue + ) -> UID2Client { + .init( + sdkVersion: sdkVersion, + environment: .init( + endpoint: URL(string: "https://prod.uidapi.com")!, + isProduction: true + ), + session: session, + cryptoUtil: cryptoUtil + ) + } +} diff --git a/Tests/UID2Tests/RefreshRequestTests.swift b/Tests/UID2Tests/RefreshRequestTests.swift index 9df8381..96a7b5c 100644 --- a/Tests/UID2Tests/RefreshRequestTests.swift +++ b/Tests/UID2Tests/RefreshRequestTests.swift @@ -12,7 +12,7 @@ final class RefreshRequestTests: XCTestCase { func testRequest() async throws { let request = Request.refresh(token: "im-a-refresh-token") - let client = UID2Client( + let client = UID2Client.test( sdkVersion: "1.2.3" ) let urlRequest = client.urlRequest(request) diff --git a/Tests/UID2Tests/RefreshTokenAPITests.swift b/Tests/UID2Tests/RefreshTokenAPITests.swift index e6d21f9..c93cfaa 100644 --- a/Tests/UID2Tests/RefreshTokenAPITests.swift +++ b/Tests/UID2Tests/RefreshTokenAPITests.swift @@ -21,8 +21,7 @@ final class RefreshTokenAPITests: XCTestCase { } // Load UID2Client Mocked - let client = UID2Client( - sdkVersion: "TEST", + let client = UID2Client.test( session: MockNetworkSession("refresh-token-200-success-encrypted", "txt") ) @@ -50,8 +49,7 @@ final class RefreshTokenAPITests: XCTestCase { } // Load UID2Client Mocked - let client = UID2Client( - sdkVersion: "TEST", + let client = UID2Client.test( session: MockNetworkSession("refresh-token-200-optout-encrypted", "txt") ) @@ -72,8 +70,7 @@ final class RefreshTokenAPITests: XCTestCase { do { // Load UID2Client Mocked - let client = UID2Client( - sdkVersion: "TEST", + let client = UID2Client.test( session: MockNetworkSession("refresh-token-400-client-error", "json", 400) ) @@ -101,8 +98,7 @@ final class RefreshTokenAPITests: XCTestCase { do { // Load UID2Client Mocked - let client = UID2Client( - sdkVersion: "TEST", + let client = UID2Client.test( session: MockNetworkSession("refresh-token-400-invalid-token", "json", 400) ) @@ -130,8 +126,7 @@ final class RefreshTokenAPITests: XCTestCase { do { // Load UID2Client Mocked - let client = UID2Client( - sdkVersion: "TEST", + let client = UID2Client.test( session: MockNetworkSession("refresh-token-401-unauthorized", "json", 401) ) diff --git a/Tests/UID2Tests/UID2ClientTests.swift b/Tests/UID2Tests/UID2ClientTests.swift index db97803..216ecda 100644 --- a/Tests/UID2Tests/UID2ClientTests.swift +++ b/Tests/UID2Tests/UID2ClientTests.swift @@ -12,21 +12,11 @@ import TestHelpers import XCTest final class UID2ClientTests: XCTestCase { - func testDefaultEnvironment() async throws { - let client = UID2Client( - sdkVersion: "1.0" - ) - let urlRequest = client.urlRequest(.init(path: "/path")) - XCTAssertEqual( - urlRequest.url, - URL(string: "https://prod.uidapi.com/path")! - ) - } - + func testOverridenEnvironment() async throws { let client = UID2Client( sdkVersion: "1.0", - environment: .singapore + environment: Environment(UID2.Environment.singapore) ) let urlRequest = client.urlRequest(.init(path: "/path")) XCTAssertEqual( @@ -38,7 +28,7 @@ final class UID2ClientTests: XCTestCase { func testCustomEnvironment() async throws { let client = UID2Client( sdkVersion: "1.0", - environment: .custom(url: URL(string: "http://localhost:8080/")!) + environment: Environment(UID2.Environment.custom(url: URL(string: "http://localhost:8080/")!)) ) let urlRequest = client.urlRequest(.init(path: "/path")) XCTAssertEqual( @@ -48,8 +38,9 @@ final class UID2ClientTests: XCTestCase { } func testClientVersionHeader() throws { - let client = UID2Client( - sdkVersion: "1.2.3" + let client = UID2Client.test( + sdkVersion: "1.2.3", + session: URLSession.shared ) let request = client.urlRequest(Request(path: "/test")) @@ -76,8 +67,9 @@ final class UID2ClientTests: XCTestCase { private let serverPublicKeyString = "UID2-X-I-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKAbPfOz7u25g1fL6riU7p2eeqhjmpALPeYoyjvZmZ1xM2NM8UeOmDZmCIBnKyRZ97pz5bMCjrs38WM22O7LJuw==" func testClientGenerateServerPublicKeyError() async throws { - let client = UID2Client( - sdkVersion: "1.0" + let client = UID2Client.test( + sdkVersion: "1.0", + session: URLSession.shared ) await assertThrowsError( @@ -104,8 +96,9 @@ final class UID2ClientTests: XCTestCase { let response = HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: nil, headerFields: nil)! return .success((data, response)) } - let client = UID2Client( - sdkVersion: "1.0" + let client = UID2Client.test( + sdkVersion: "1.0", + session: URLSession.shared ) await assertThrowsError( @@ -131,8 +124,9 @@ final class UID2ClientTests: XCTestCase { let response = HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: nil, headerFields: nil)! return .success((data, response)) } - let client = UID2Client( - sdkVersion: "1.0" + let client = UID2Client.test( + sdkVersion: "1.0", + session: URLSession.shared ) await assertThrowsError( @@ -160,8 +154,9 @@ final class UID2ClientTests: XCTestCase { let response = HTTPURLResponse(url: request.url!, statusCode: 400, httpVersion: nil, headerFields: nil)! return .success((data, response)) } - let client = UID2Client( - sdkVersion: "1.0" + let client = UID2Client.test( + sdkVersion: "1.0", + session: URLSession.shared ) await assertThrowsError( @@ -191,8 +186,9 @@ final class UID2ClientTests: XCTestCase { return .success((data, response)) } - let client = UID2Client( + let client = UID2Client.test( sdkVersion: "1.0", + session: URLSession.shared, cryptoUtil: testCrypto.cryptoUtil ) @@ -217,8 +213,9 @@ final class UID2ClientTests: XCTestCase { return .success((data, response)) } - let client = UID2Client( + let client = UID2Client.test( sdkVersion: "1.0", + session: URLSession.shared, cryptoUtil: testCrypto.cryptoUtil ) diff --git a/Tests/UID2Tests/UID2ManagerTests.swift b/Tests/UID2Tests/UID2ManagerTests.swift index d53690d..8a3bc27 100644 --- a/Tests/UID2Tests/UID2ManagerTests.swift +++ b/Tests/UID2Tests/UID2ManagerTests.swift @@ -29,9 +29,7 @@ final class UID2ManagerTests: XCTestCase { func testInitialState() async throws { let manager = UID2Manager( - uid2Client: UID2Client( - sdkVersion: "1.0" - ), + uid2Client: UID2Client.test(), storage: .null, sdkVersion: (1, 0, 0), log: .disabled @@ -48,8 +46,7 @@ final class UID2ManagerTests: XCTestCase { func testClientGenerateServerOptout() async throws { let testCrypto = stubEncrypted("/v2/token/client-generate", fixture: "refresh-token-200-optout-decrypted") let manager = UID2Manager( - uid2Client: UID2Client( - sdkVersion: "1.0", + uid2Client: UID2Client.test( cryptoUtil: testCrypto.cryptoUtil ), storage: .null, @@ -85,8 +82,7 @@ final class UID2ManagerTests: XCTestCase { let testCrypto = stubEncrypted("/v2/token/client-generate", fixture: "refresh-token-200-success-decrypted") let manager = UID2Manager( - uid2Client: UID2Client( - sdkVersion: "1.0", + uid2Client: UID2Client.test( cryptoUtil: testCrypto.cryptoUtil ), storage: .null, @@ -122,8 +118,7 @@ final class UID2ManagerTests: XCTestCase { let testCrypto = stubEncrypted("/v2/token/client-generate", fixture: "refresh-token-200-success-decrypted") let manager = UID2Manager( - uid2Client: UID2Client( - sdkVersion: "1.0", + uid2Client: UID2Client.test( cryptoUtil: testCrypto.cryptoUtil ), storage: .null, @@ -172,9 +167,7 @@ final class UID2ManagerTests: XCTestCase { func testNoneIdentityRestorationFromStorage() async throws { let manager = UID2Manager( - uid2Client: UID2Client( - sdkVersion: "1.0" - ), + uid2Client: UID2Client.test(), storage: .null, sdkVersion: (1, 0, 0), log: .disabled @@ -190,9 +183,7 @@ final class UID2ManagerTests: XCTestCase { func testOptoutIdentityRestorationFromStorage() async throws { let manager = UID2Manager( - uid2Client: UID2Client( - sdkVersion: "1.0" - ), + uid2Client: UID2Client.test(), storage: .init( loadIdentity: { IdentityPackage(valid: true, errorMessage: nil, identity: nil, status: .optOut) @@ -215,9 +206,7 @@ final class UID2ManagerTests: XCTestCase { func testEstablishedIdentityRestorationFromStorage() async throws { let establishedIdentity = UID2Identity.established() let manager = UID2Manager( - uid2Client: UID2Client( - sdkVersion: "1.0" - ), + uid2Client: UID2Client.test(), storage: .init( loadIdentity: { IdentityPackage(valid: true, errorMessage: nil, identity: establishedIdentity, status: .established) @@ -242,9 +231,7 @@ final class UID2ManagerTests: XCTestCase { @MainActor func testStateValuesObservation() async throws { let manager = UID2Manager( - uid2Client: UID2Client( - sdkVersion: "1.0" - ), + uid2Client: UID2Client.test(), storage: .null, sdkVersion: (1, 0, 0), log: .disabled @@ -287,9 +274,7 @@ final class UID2ManagerTests: XCTestCase { @MainActor func testStateValuesMultipleObservers() async throws { let manager = UID2Manager( - uid2Client: UID2Client( - sdkVersion: "1.0" - ), + uid2Client: UID2Client.test(), storage: .null, sdkVersion: (1, 0, 0), log: .disabled diff --git a/UID2Prebid/UID2Prebid.xcodeproj/project.pbxproj b/UID2Prebid/UID2Prebid.xcodeproj/project.pbxproj index 8740c83..b0f1613 100644 --- a/UID2Prebid/UID2Prebid.xcodeproj/project.pbxproj +++ b/UID2Prebid/UID2Prebid.xcodeproj/project.pbxproj @@ -37,6 +37,7 @@ BF16EC4D2C5D8D7100B0CA03 /* UID2Manager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF16EC2F2C5D8D7100B0CA03 /* UID2Manager.swift */; }; BF16EC4E2C5D8D7100B0CA03 /* UID2Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF16EC302C5D8D7100B0CA03 /* UID2Settings.swift */; }; BF2AA21A2C650C8900634831 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF2AA2192C650C8900634831 /* Storage.swift */; }; + BF9673342C666035005D9BC1 /* EUIDManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9673332C666035005D9BC1 /* EUIDManager.swift */; }; BFE641292C5CDCB800E241CF /* UID2Prebid.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BFE641202C5CDCB800E241CF /* UID2Prebid.framework */; }; BFE641392C5CDD0600E241CF /* UID2PrebidTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFE641382C5CDD0600E241CF /* UID2PrebidTests.swift */; }; BFE6413B2C5CDD0B00E241CF /* UID2Prebid.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFE6413A2C5CDD0B00E241CF /* UID2Prebid.swift */; }; @@ -124,6 +125,7 @@ BF16EC2F2C5D8D7100B0CA03 /* UID2Manager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UID2Manager.swift; sourceTree = ""; }; BF16EC302C5D8D7100B0CA03 /* UID2Settings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UID2Settings.swift; sourceTree = ""; }; BF2AA2192C650C8900634831 /* Storage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = ""; }; + BF9673332C666035005D9BC1 /* EUIDManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EUIDManager.swift; sourceTree = ""; }; BFE641202C5CDCB800E241CF /* UID2Prebid.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = UID2Prebid.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BFE641282C5CDCB800E241CF /* UID2PrebidTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UID2PrebidTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; BFE641382C5CDD0600E241CF /* UID2PrebidTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UID2PrebidTests.swift; sourceTree = ""; }; @@ -262,6 +264,7 @@ BF16EC272C5D8D7100B0CA03 /* X509 */, BF16EC282C5D8D7100B0CA03 /* CryptoUtil.swift */, BF16EC292C5D8D7100B0CA03 /* Environment.swift */, + BF9673332C666035005D9BC1 /* EUIDManager.swift */, BF16EC2A2C5D8D7100B0CA03 /* KeychainManager.swift */, BF16EC2B2C5D8D7100B0CA03 /* PrivacyInfo.xcprivacy */, BF16EC2C2C5D8D7100B0CA03 /* UID2Client.swift */, @@ -589,6 +592,7 @@ BF16EC322C5D8D7100B0CA03 /* IdentityPackage.swift in Sources */, BF16EC4E2C5D8D7100B0CA03 /* UID2Settings.swift in Sources */, BF16EC452C5D8D7100B0CA03 /* SubjectPublicKeyInfo.swift in Sources */, + BF9673342C666035005D9BC1 /* EUIDManager.swift in Sources */, BF16EC3B2C5D8D7100B0CA03 /* ClientGenerate.swift in Sources */, BF16EC4C2C5D8D7100B0CA03 /* UID2Manager.State.swift in Sources */, BF16EC342C5D8D7100B0CA03 /* IdentityType.swift in Sources */, diff --git a/UID2Prebid/UID2PrebidTests/UID2PrebidTests.swift b/UID2Prebid/UID2PrebidTests/UID2PrebidTests.swift index 19496ef..e20e10b 100644 --- a/UID2Prebid/UID2PrebidTests/UID2PrebidTests.swift +++ b/UID2Prebid/UID2PrebidTests/UID2PrebidTests.swift @@ -29,7 +29,8 @@ final class UID2PrebidTests: XCTestCase { func testObservation() async throws { let manager = UID2Manager( uid2Client: UID2Client( - sdkVersion: "1.0" + sdkVersion: "1.0", + environment: Environment(UID2.Environment.production) ), storage: .null, sdkVersion: (1, 0, 0), @@ -73,7 +74,8 @@ final class UID2PrebidTests: XCTestCase { func testObservationWithThirdPartyUserIDs() async throws { let manager = UID2Manager( uid2Client: UID2Client( - sdkVersion: "1.0" + sdkVersion: "1.0", + environment: Environment(UID2.Environment.production) ), storage: .null, sdkVersion: (1, 0, 0),