Skip to content

Commit

Permalink
Merge pull request #517 from SwissCovid/develop
Browse files Browse the repository at this point in the history
Release 2.4.0
  • Loading branch information
stmitt authored Mar 21, 2022
2 parents edb5565 + 6f52f16 commit de4a937
Show file tree
Hide file tree
Showing 57 changed files with 658 additions and 174 deletions.
155 changes: 27 additions & 128 deletions DP3TApp.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
"repositoryURL": "https://github.com/DP-3T/dp3t-sdk-ios.git",
"state": {
"branch": null,
"revision": "f0897a3e013e8ad3e693288f82757068b4ce08f2",
"version": "2.4.0"
"revision": "002a66ec4a6564c3803d1410e955eabdf0556a3c",
"version": "2.5.1"
}
},
{
Expand Down
10 changes: 9 additions & 1 deletion DP3TApp/Logic/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// defer window initialization if app was launched in
// background because of location change
if shouldSetupWindow(application: application, launchOptions: launchOptions) {
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
// Only schedule warnings if app is not deactivated
if ConfigManager.currentConfig?.deactivate != true {
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
}
setupWindow()
willAppearAfterColdstart(application, coldStart: true, backgroundTime: 0)
}
Expand Down Expand Up @@ -114,6 +117,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

window?.makeKeyAndVisible()

guard !(ConfigManager.currentConfig?.deactivate ?? false) else { return }

if UserStorage.shared.appClipCheckinUrl() != nil {
let checkinOnboardingVC = NSCheckinOnboardingViewController()
checkinOnboardingVC.modalPresentationStyle = .fullScreen
Expand All @@ -140,6 +145,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

// Nothing to do here if device is not supported
guard TracingManager.shared.isSupported else {
startForceUpdateCheck()
return
}

Expand All @@ -162,6 +168,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
_ = jumpToMessageIfRequired(onlyFirst: false)
}

ConfigManager.presentDeactivationIfNeeded(config: ConfigManager.currentConfig, window: window)

startForceUpdateCheck()

FakePublishManager.shared.runTask()
Expand Down
10 changes: 8 additions & 2 deletions DP3TApp/Logic/CheckIn/CheckInManager/CheckInManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,10 @@ class CheckInManager {
switch result {
case let .success(id):
hasCheckedOutOnce = true
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
// Only schedule warnings if app is not deactivated
if ConfigManager.currentConfig?.deactivate != true {
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
}
cc.identifier = id
saveAdditionalInfo(checkIn: cc)
case .failure:
Expand Down Expand Up @@ -122,7 +125,10 @@ class CheckInManager {
switch result {
case let .success(id):
hasCheckedOutOnce = true
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
// Only schedule warnings if app is not deactivated
if ConfigManager.currentConfig?.deactivate != true {
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
}
var intervalCheckIn = CheckIn(identifier: id, qrCode: checkIn.qrCode, checkInTime: arrivalTime, venue: checkIn.venue)
intervalCheckIn.checkOutTime = departureTime
saveAdditionalInfo(checkIn: intervalCheckIn)
Expand Down
4 changes: 3 additions & 1 deletion DP3TApp/Logic/CheckIn/ProblematicEventsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ class ProblematicEventsManager {
syncNeeded = false
}

if syncNeeded {
let deactivated = (ConfigManager.currentConfig?.deactivate ?? false)

if syncNeeded, !deactivated {
sync { _, _ in }
}
}
Expand Down
27 changes: 27 additions & 0 deletions DP3TApp/Logic/Config/ConfigLoadOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,33 @@ class ConfigLoadOperation: Operation {

ConfigLoadOperation.presentedConfigForVersion = ConfigManager.appVersion
}
} else if let c = config, c.deactivate {
if Thread.isMainThread {
let vc = NSNavigationController(rootViewController: NSDeactivatedInfoViewController())
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
appDelegate.window?.rootViewController? = vc
} else {
DispatchQueue.main.async {
let vc = NSNavigationController(rootViewController: NSDeactivatedInfoViewController())
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
appDelegate.window?.rootViewController? = vc
}
}

TracingManager.shared.setBackgroundRefreshEnabled(false)

if TracingManager.shared.isActivated {
TracingManager.shared.endTracing()
UserStorage.shared.tracingWasActivatedBeforeDeaktivation = true
}

NSLocalPush.shared.cancelAllPendingAndDeliveredNotifications()

UBPushManager.shared.setActive(false)
CheckInManager.shared.cleanUpOldData(maxDaysToKeep: 0)

UserStorage.shared.appDeactivated = true

} else {
self.cancel()
}
Expand Down
68 changes: 64 additions & 4 deletions DP3TApp/Logic/Config/ConfigManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class ConfigManager: NSObject {
static let configBackgroundValidityInterval: TimeInterval = 60 * 60 * 6 // 6h

static var allowTracing: Bool {
return true
return !(ConfigManager.currentConfig?.deactivate ?? false)
}

// MARK: - Version Numbers
Expand Down Expand Up @@ -80,7 +80,10 @@ class ConfigManager: NSObject {
}
}

static func shouldLoadConfig(backgroundTask: Bool, url: String?, lastConfigUrl: String?, lastConfigLoad: Date?) -> Bool {
static func shouldLoadConfig(backgroundTask: Bool, url: String?, lastConfigUrl: String?, lastConfigLoad: Date?, deactivate: Bool?) -> Bool {
if deactivate ?? false {
return true
}
// if the config url was changed (by OS version or app version changing) load config in anycase
if url != lastConfigUrl {
return true
Expand Down Expand Up @@ -110,12 +113,14 @@ class ConfigManager: NSObject {
}

public func loadConfig(backgroundTask: Bool, completion: @escaping (ConfigResponseBody?) -> Void) {
let request = Endpoint.config(appversion: ConfigManager.appVersion, osversion: ConfigManager.osVersion, buildnr: ConfigManager.buildNumber).request()
var request = Endpoint.config(appversion: ConfigManager.appVersion, osversion: ConfigManager.osVersion, buildnr: ConfigManager.buildNumber).request()
request.cachePolicy = .reloadIgnoringLocalCacheData

guard Self.shouldLoadConfig(backgroundTask: backgroundTask,
url: request.url?.absoluteString,
lastConfigUrl: Self.lastConfigUrl,
lastConfigLoad: Self.lastConfigLoad) else {
lastConfigLoad: Self.lastConfigLoad,
deactivate: ConfigManager.currentConfig?.deactivate) else {
Logger.log("Skipping config load request and returning from cache", appState: true)
completion(Self.currentConfig)
return
Expand Down Expand Up @@ -160,6 +165,7 @@ class ConfigManager: NSObject {
loadConfig(backgroundTask: false) { config in
// self must be strong
if let config = config {
Self.presentDeactivationIfNeeded(config: config, window: window)
self.presentAlertIfNeeded(config: config, window: window)
}
}
Expand Down Expand Up @@ -210,6 +216,60 @@ class ConfigManager: NSObject {
}
}
}

public static func presentDeactivationIfNeeded(config: ConfigResponseBody?, window: UIWindow? = nil) {
guard let config = config else { return }

if config.deactivate {
NSLocalPush.shared.cancelAllPendingAndDeliveredNotifications()

if (window?.rootViewController as? UINavigationController)?.visibleViewController is NSDeactivatedInfoViewController {
// The NSDeactivatedInfoViewController is already visible
return
}

let vc = NSNavigationController(rootViewController: NSDeactivatedInfoViewController())

if let window = window {
window.rootViewController = vc
}

TracingManager.shared.setBackgroundRefreshEnabled(false)

if TracingManager.shared.isActivated {
UserStorage.shared.tracingWasActivatedBeforeDeaktivation = true
TracingManager.shared.endTracing()
}

UBPushManager.shared.setActive(false)
CheckInManager.shared.cleanUpOldData(maxDaysToKeep: 0)

UserStorage.shared.appDeactivated = true

} else if !config.deactivate, UserStorage.shared.appDeactivated {
if TracingManager.shared.isAuthorized, UserStorage.shared.tracingWasActivatedBeforeDeaktivation {
TracingManager.shared.startTracing()
}

TracingManager.shared.setBackgroundRefreshEnabled(true)

if TracingManager.shared.isSupported {
window?.rootViewController = (UIApplication.shared.delegate as? AppDelegate)?.navigationController

if !UserStorage.shared.hasCompletedOnboarding {
let onboardingViewController = NSOnboardingViewController()
onboardingViewController.modalPresentationStyle = .fullScreen
window?.rootViewController?.present(onboardingViewController, animated: false)
}

} else {
window?.rootViewController = NSUnsupportedOSViewController()
}

UserStorage.shared.appDeactivated = false
UserStorage.shared.tracingWasActivatedBeforeDeaktivation = true
}
}
}

private extension UIViewController {
Expand Down
5 changes: 4 additions & 1 deletion DP3TApp/Logic/Config/ConfigResponseBody.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,11 @@ class ConfigResponseBody: UBCodable {
public var showVaccinationInfo = false
public let vaccinationBookingInfo: LocalizedValue<VaccinationBookingInfo>

public let deactivate: Bool
public let deactivationMessage: LocalizedValue<InfoBox>?

class InfoBox: UBCodable {
let title, msg: String
let title, msg: String?
let url: URL?
let urlTitle: String?
let infoId: String?
Expand Down
6 changes: 6 additions & 0 deletions DP3TApp/Logic/NSLocalPush.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ protocol UserNotificationCenter {
func add(_ request: UNNotificationRequest, withCompletionHandler completionHandler: ((Error?) -> Void)?)
func removeDeliveredNotifications(withIdentifiers identifiers: [String])
func removeAllDeliveredNotifications()
func removeAllPendingNotificationRequests()
func removePendingNotificationRequests(withIdentifiers identifiers: [String])
func setNotificationCategories(_ categories: Set<UNNotificationCategory>)
}
Expand Down Expand Up @@ -140,6 +141,11 @@ class NSLocalPush: NSObject, LocalPushProtocol {
center.removePendingNotificationRequests(withIdentifiers: allIdentifier)
}

func cancelAllPendingAndDeliveredNotifications() {
center.removeAllDeliveredNotifications()
center.removeAllPendingNotificationRequests()
}

var now: Date {
.init()
}
Expand Down
12 changes: 6 additions & 6 deletions DP3TApp/Logic/Networking/Base/URLSession+pinning.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ class CertificateEvaluator: NSObject, URLSessionDelegate {

let bundle = Bundle.main

// all these hosts have a seperate certificate
let hosts = ["www.pt1.bfs.admin.ch",
"www.pt1-d.bfs.admin.ch",
"www.pt1-a.bfs.admin.ch",
Expand All @@ -96,16 +95,17 @@ class CertificateEvaluator: NSObject, URLSessionDelegate {
"www.pt-a.bfs.admin.ch",
"www.pt-t.bfs.admin.ch",
"www.pt.bfs.admin.ch"]
for host in hosts {
if let certificate = bundle.getCertificate(with: host) {
let evaluator = UBPinnedCertificatesTrustEvaluator(certificates: [certificate],

if let QuovadisRootCA = bundle.getCertificate(with: "QuoVadis-Root-CA-2-G3", fileExtension: "cer") {
for host in hosts {
let evaluator = UBPinnedCertificatesTrustEvaluator(certificates: [QuovadisRootCA],
acceptSelfSignedCertificates: true,
performDefaultValidation: false,
validateHost: true)
evaluators[host] = evaluator
} else {
assertionFailure("Could not load certificate for pinned host")
}
} else {
assertionFailure("Could not load certificate for pinned host")
}

return UBServerTrustManager(evaluators: evaluators)
Expand Down
5 changes: 4 additions & 1 deletion DP3TApp/Logic/Push/NSPushHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ class NSPushHandler: UBPushHandler {
}

// data are updated -> reschedule background task warning triggers
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
// Only schedule warnings if app is not deactivated
if ConfigManager.currentConfig?.deactivate != true {
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
}
}

if self.backgroundTask != .invalid {
Expand Down
9 changes: 7 additions & 2 deletions DP3TApp/Logic/Tracing/DatabaseSyncer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ class DatabaseSyncer {
private var databaseSyncInterval: TimeInterval = 10

func syncDatabaseIfNeeded(completionHandler: ((UIBackgroundFetchResult) -> Void)? = nil) {
let deactivated = (ConfigManager.currentConfig?.deactivate ?? false)
guard !databaseIsSyncing,
UserStorage.shared.hasCompletedOnboarding else {
UserStorage.shared.hasCompletedOnboarding,
!deactivated else {
completionHandler?(.noData)
return
}
Expand Down Expand Up @@ -129,7 +131,10 @@ class DatabaseSyncer {
UIStateManager.shared.syncError = nil
}

NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
// Only schedule warnings if app is not deactivated
if ConfigManager.currentConfig?.deactivate != true {
NSLocalPush.shared.resetBackgroundTaskWarningTriggers()
}

// reload status, user could have been exposed
TracingManager.shared.updateStatus(completion: nil)
Expand Down
Loading

0 comments on commit de4a937

Please sign in to comment.