From 07657995b1d57c4bb3ac22c7bb3252b6fe909ab1 Mon Sep 17 00:00:00 2001 From: Stefan Mitterrutzner Date: Tue, 20 Apr 2021 10:27:59 +0200 Subject: [PATCH 1/5] adds missing @availabel marks --- Sources/DP3TSDK/Networking/ExposeeServiceClient.swift | 2 +- Tests/DP3TSDKTests/DP3TSDKTests.swift | 1 + Tests/DP3TSDKTests/DiagnosisKeysProviderTests.swift | 2 ++ Tests/DP3TSDKTests/ExposureNotificationMatcherTests.swift | 1 + Tests/DP3TSDKTests/ExposureNotificationTracerTests.swift | 1 + Tests/DP3TSDKTests/ExposureWindowTests.swift | 1 + Tests/DP3TSDKTests/Mocks/MockENManager.swift | 2 ++ Tests/DP3TSDKTests/Mocks/MockScanInstance.swift | 1 + Tests/DP3TSDKTests/Mocks/MockWindow.swift | 1 + 9 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Sources/DP3TSDK/Networking/ExposeeServiceClient.swift b/Sources/DP3TSDK/Networking/ExposeeServiceClient.swift index 6b2b2b7e..79a67519 100644 --- a/Sources/DP3TSDK/Networking/ExposeeServiceClient.swift +++ b/Sources/DP3TSDK/Networking/ExposeeServiceClient.swift @@ -54,7 +54,7 @@ class ExposeeServiceClient: ExposeeServiceClientProtocol { private let jwtVerifier: DP3TJWTVerifier? - var federationGateway: FederationGateway + internal var federationGateway: FederationGateway private let log = Logger(ExposeeServiceClient.self, category: "exposeeServiceClient") diff --git a/Tests/DP3TSDKTests/DP3TSDKTests.swift b/Tests/DP3TSDKTests/DP3TSDKTests.swift index 3da11e73..d1db2804 100644 --- a/Tests/DP3TSDKTests/DP3TSDKTests.swift +++ b/Tests/DP3TSDKTests/DP3TSDKTests.swift @@ -26,6 +26,7 @@ private class MockKeyProvider: DiagnosisKeysProvider { } +@available(iOS 12.5, *) class DP3TSDKTests: XCTestCase { fileprivate var keychain: MockKeychain! diff --git a/Tests/DP3TSDKTests/DiagnosisKeysProviderTests.swift b/Tests/DP3TSDKTests/DiagnosisKeysProviderTests.swift index 20971e04..6cce16f0 100644 --- a/Tests/DP3TSDKTests/DiagnosisKeysProviderTests.swift +++ b/Tests/DP3TSDKTests/DiagnosisKeysProviderTests.swift @@ -13,6 +13,7 @@ import Foundation import XCTest import ExposureNotification +@available(iOS 12.5, *) class DiagnosisKeysProviderTests: XCTestCase { var manager: MockENManager! @@ -81,6 +82,7 @@ class DiagnosisKeysProviderTests: XCTestCase { } +@available(iOS 12.5, *) extension ENTemporaryExposureKey { static func initialize(data: Data = Data(capacity: 16), rollingPeriod: ENIntervalNumber = UInt32(TimeInterval.day / (.minute * 10)), diff --git a/Tests/DP3TSDKTests/ExposureNotificationMatcherTests.swift b/Tests/DP3TSDKTests/ExposureNotificationMatcherTests.swift index 9d81fc8e..3b653ee6 100644 --- a/Tests/DP3TSDKTests/ExposureNotificationMatcherTests.swift +++ b/Tests/DP3TSDKTests/ExposureNotificationMatcherTests.swift @@ -15,6 +15,7 @@ import Foundation import XCTest import ZIPFoundation +@available(iOS 12.5, *) final class ExposureNotificationMatcherTests: XCTestCase { var keychain = MockKeychain() diff --git a/Tests/DP3TSDKTests/ExposureNotificationTracerTests.swift b/Tests/DP3TSDKTests/ExposureNotificationTracerTests.swift index 88248b5b..dbda23cf 100644 --- a/Tests/DP3TSDKTests/ExposureNotificationTracerTests.swift +++ b/Tests/DP3TSDKTests/ExposureNotificationTracerTests.swift @@ -11,6 +11,7 @@ @testable import DP3TSDK import XCTest +@available(iOS 12.5, *) class ExposureNotificationTracerTests: XCTestCase { var manager: MockENManager! diff --git a/Tests/DP3TSDKTests/ExposureWindowTests.swift b/Tests/DP3TSDKTests/ExposureWindowTests.swift index d1bc391c..02463984 100644 --- a/Tests/DP3TSDKTests/ExposureWindowTests.swift +++ b/Tests/DP3TSDKTests/ExposureWindowTests.swift @@ -13,6 +13,7 @@ import XCTest import ExposureNotification +@available(iOS 12.5, *) class ExposureWindowTests: XCTestCase { func testDayGroupingSingle(){ var windows: [MockWindow] = [] diff --git a/Tests/DP3TSDKTests/Mocks/MockENManager.swift b/Tests/DP3TSDKTests/Mocks/MockENManager.swift index f96f8032..a6fff1d5 100644 --- a/Tests/DP3TSDKTests/Mocks/MockENManager.swift +++ b/Tests/DP3TSDKTests/Mocks/MockENManager.swift @@ -12,6 +12,7 @@ import Foundation import ExposureNotification +@available(iOS 12.5, *) class MockENManager: ENManager { var activateCallbacks: [ENErrorHandler] = [] @@ -108,6 +109,7 @@ class MockENManager: ENManager { } } +@available(iOS 12.5, *) class MockSummary: ENExposureDetectionSummary { override var attenuationDurations: [NSNumber] { get { diff --git a/Tests/DP3TSDKTests/Mocks/MockScanInstance.swift b/Tests/DP3TSDKTests/Mocks/MockScanInstance.swift index c1a2aa42..f4018f84 100644 --- a/Tests/DP3TSDKTests/Mocks/MockScanInstance.swift +++ b/Tests/DP3TSDKTests/Mocks/MockScanInstance.swift @@ -11,6 +11,7 @@ import Foundation import ExposureNotification +@available(iOS 12.5, *) class MockScanInstance: ENScanInstance { private var internalTypicalAttenuation: ENAttenuation diff --git a/Tests/DP3TSDKTests/Mocks/MockWindow.swift b/Tests/DP3TSDKTests/Mocks/MockWindow.swift index e566b35c..a10ef186 100644 --- a/Tests/DP3TSDKTests/Mocks/MockWindow.swift +++ b/Tests/DP3TSDKTests/Mocks/MockWindow.swift @@ -11,6 +11,7 @@ import Foundation import ExposureNotification +@available(iOS 12.5, *) class MockWindow: ENExposureWindow { private var internalDate: Date private var internalScanInstances: [ENScanInstance] From 26485ba698b48c986a46e5e1ceac5f3182ec4fdd Mon Sep 17 00:00:00 2001 From: Stefan Mitterrutzner Date: Tue, 20 Apr 2021 10:29:26 +0200 Subject: [PATCH 2/5] expose oldest keydate when calling iWasExposed --- Sources/DP3TSDK/DP3TSDK.swift | 9 +++++++-- Sources/DP3TSDK/DP3TTracing.swift | 7 ++++++- Sources/DP3TSDK/Models/ExposeeListModel.swift | 6 ++++++ Tests/DP3TSDKTests/DP3TSDKTests.swift | 16 +++++++++++++--- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/Sources/DP3TSDK/DP3TSDK.swift b/Sources/DP3TSDK/DP3TSDK.swift index e31a6b8e..ce033fa2 100644 --- a/Sources/DP3TSDK/DP3TSDK.swift +++ b/Sources/DP3TSDK/DP3TSDK.swift @@ -246,7 +246,7 @@ class DP3TSDK { func iWasExposed(onset: Date, authentication: ExposeeAuthMethod, isFakeRequest: Bool = false, - callback: @escaping (Result) -> Void) { + callback: @escaping (Result) -> Void) { log.trace() if !isFakeRequest, case .infected = state.infectionStatus { @@ -299,6 +299,11 @@ class DP3TSDK { withFederationGateway = nil } + let oldestNonFakeKeyDate = mutableKeys + .filter { $0.fake == 0 } + .map(\.date) + .min() + let model = ExposeeListModel(gaenKeys: mutableKeys, withFederationGateway: withFederationGateway, fake: isFakeRequest) @@ -313,7 +318,7 @@ class DP3TSDK { self.tracer.setEnabled(false, completionHandler: nil) } - callback(.success(())) + callback(.success((.init(oldestKeyDate: oldestNonFakeKeyDate)))) case let .failure(error): callback(.failure(.networkingError(error: error))) } diff --git a/Sources/DP3TSDK/DP3TTracing.swift b/Sources/DP3TSDK/DP3TTracing.swift index c8f0c5bf..56591f41 100644 --- a/Sources/DP3TSDK/DP3TTracing.swift +++ b/Sources/DP3TSDK/DP3TTracing.swift @@ -135,6 +135,11 @@ public enum DP3TTracing { return instance.status } + + public struct IWasExposedResult { + public let oldestKeyDate: Date? + } + /// tell the SDK that the user was exposed /// - Parameters: /// - onset: Start date of the exposure @@ -145,7 +150,7 @@ public enum DP3TTracing { public static func iWasExposed(onset: Date, authentication: ExposeeAuthMethod, isFakeRequest: Bool = false, - callback: @escaping (Result) -> Void) { + callback: @escaping (Result) -> Void) { instancePrecondition() instance.iWasExposed(onset: onset, authentication: authentication, diff --git a/Sources/DP3TSDK/Models/ExposeeListModel.swift b/Sources/DP3TSDK/Models/ExposeeListModel.swift index 221b1bc3..509c483f 100644 --- a/Sources/DP3TSDK/Models/ExposeeListModel.swift +++ b/Sources/DP3TSDK/Models/ExposeeListModel.swift @@ -18,6 +18,12 @@ struct CodableDiagnosisKey: Codable, Equatable { let fake: UInt8 } +extension CodableDiagnosisKey { + var date: Date { + Date(timeIntervalSince1970: TimeInterval(rollingStartNumber) * TimeInterval.minute * 10) + } +} + /// Model of the exposed person struct ExposeeListModel: Encodable { /// Diagnosis keys diff --git a/Tests/DP3TSDKTests/DP3TSDKTests.swift b/Tests/DP3TSDKTests/DP3TSDKTests.swift index d1db2804..b91292b0 100644 --- a/Tests/DP3TSDKTests/DP3TSDKTests.swift +++ b/Tests/DP3TSDKTests/DP3TSDKTests.swift @@ -96,8 +96,18 @@ class DP3TSDKTests: XCTestCase { XCTAssertEqual(sdk.status.infectionStatus, .healthy) let exp = expectation(description: "infected") - keyProvider.keys = [ .init(keyData: Data(count: 16), rollingPeriod: 144, rollingStartNumber: DayDate().period, transmissionRiskLevel: 0, fake: 0) ] + let oldestDate = Date(timeIntervalSinceNow: -.day * 5) + keyProvider.keys = [ + .init(keyData: Data(count: 16), rollingPeriod: 144, rollingStartNumber: DayDate(date: oldestDate.addingTimeInterval(.day)).period, transmissionRiskLevel: 0, fake: 0), + .init(keyData: Data(count: 16), rollingPeriod: 144, rollingStartNumber: DayDate(date: oldestDate).period, transmissionRiskLevel: 0, fake: 0), + .init(keyData: Data(count: 16), rollingPeriod: 144, rollingStartNumber: DayDate(date: oldestDate.addingTimeInterval(.day * 2)).period, transmissionRiskLevel: 0, fake: 0), + ] sdk.iWasExposed(onset: .init(timeIntervalSinceNow: -.day), authentication: .none) { (result) in + if case let Result.success(wrapper) = result { + XCTAssertEqual(wrapper.oldestKeyDate, DayDate(date: oldestDate).dayMin) + } else { + XCTFail() + } exp.fulfill() } wait(for: [exp], timeout: 0.1) @@ -108,8 +118,8 @@ class DP3TSDKTests: XCTestCase { let rollingStartNumbers = Set(model!.gaenKeys.map(\.rollingStartNumber)) XCTAssertEqual(rollingStartNumbers.count, model!.gaenKeys.count) var runningDate: Date? - for key in model!.gaenKeys { - let date = Date(timeIntervalSince1970: Double(key.rollingStartNumber) * 10 * .minute) + for key in model!.gaenKeys.sorted(by: { $0.date > $1.date }) { + let date = key.date guard runningDate != nil else { runningDate = date continue From e2ee6fc26b763a163944e75551e766fa0aed7a3f Mon Sep 17 00:00:00 2001 From: Stefan Mitterrutzner Date: Tue, 20 Apr 2021 11:21:51 +0200 Subject: [PATCH 3/5] adds changes to changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3524e7d9..b02e9694 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog for DP3T-SDK iOS +## next version +- expose oldest shared keydate when calling iWasExposed + ## Version 2.2.0 (25.03.2021) - Add support for international key exchange with parameter 'federationGateway' From 6529564070353febf0b74db19f10efdf5811f7a5 Mon Sep 17 00:00:00 2001 From: Stefan Mitterrutzner Date: Tue, 20 Apr 2021 11:26:46 +0200 Subject: [PATCH 4/5] remove useless parentheses --- Sources/DP3TSDK/DP3TSDK.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/DP3TSDK/DP3TSDK.swift b/Sources/DP3TSDK/DP3TSDK.swift index ce033fa2..29f2c37c 100644 --- a/Sources/DP3TSDK/DP3TSDK.swift +++ b/Sources/DP3TSDK/DP3TSDK.swift @@ -318,7 +318,7 @@ class DP3TSDK { self.tracer.setEnabled(false, completionHandler: nil) } - callback(.success((.init(oldestKeyDate: oldestNonFakeKeyDate)))) + callback(.success(.init(oldestKeyDate: oldestNonFakeKeyDate))) case let .failure(error): callback(.failure(.networkingError(error: error))) } From 2893d158c47b82dbaf3d4f18da601337471ff419 Mon Sep 17 00:00:00 2001 From: Stefan Mitterrutzner Date: Tue, 20 Apr 2021 11:49:17 +0200 Subject: [PATCH 5/5] use existing logic to get oldestNonFakeKeyDate --- Sources/DP3TSDK/DP3TSDK.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/DP3TSDK/DP3TSDK.swift b/Sources/DP3TSDK/DP3TSDK.swift index 29f2c37c..37dfe312 100644 --- a/Sources/DP3TSDK/DP3TSDK.swift +++ b/Sources/DP3TSDK/DP3TSDK.swift @@ -299,10 +299,10 @@ class DP3TSDK { withFederationGateway = nil } - let oldestNonFakeKeyDate = mutableKeys - .filter { $0.fake == 0 } - .map(\.date) - .min() + var oldestNonFakeKeyDate: Date? = nil + if !isFakeRequest { + oldestNonFakeKeyDate = Date(timeIntervalSince1970: Double(oldestRollingStartNumber) * 10 * .minute) + } let model = ExposeeListModel(gaenKeys: mutableKeys, withFederationGateway: withFederationGateway,