Commit 1c02ee69 authored by stopcovid@lunabee.com's avatar stopcovid@lunabee.com

Update to 2.1.1.

parent bef935ae
No preview for this file type
PODS:
- KeychainSwift (19.0.0)
- lottie-ios (3.1.8)
- NMSSH (2.3.1)
- PKHUD (5.3.0)
- ReachabilitySwift (5.0.0)
- Realm (5.3.4):
- Realm/Headers (= 5.3.4)
- Realm/Headers (5.3.4)
......@@ -16,9 +14,7 @@ PODS:
DEPENDENCIES:
- KeychainSwift
- lottie-ios
- NMSSH
- PKHUD
- ReachabilitySwift
- RealmSwift
- SwCrypt
- SwiftGen
......@@ -28,9 +24,7 @@ SPEC REPOS:
trunk:
- KeychainSwift
- lottie-ios
- NMSSH
- PKHUD
- ReachabilitySwift
- Realm
- RealmSwift
- SwCrypt
......@@ -40,15 +34,13 @@ SPEC REPOS:
SPEC CHECKSUMS:
KeychainSwift: a06190cf933ad46b1e0abc3d77d29c06331715c7
lottie-ios: 48fac6be217c76937e36e340e2d09cf7b10b7f5f
NMSSH: cd689ae535a1581a6dd9fd4600ff71247df510a6
PKHUD: 98f3e4bc904b9c916f1c5bb6d765365b5357291b
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
Realm: 4dd457b6ed025041cf7efe05dae78c027ba842e0
RealmSwift: 233af88fffe05ed7f9305eecef100d477c0c2c42
SwCrypt: 0d1f951b8a993d6e107f4776ee0d72c1adafd1df
SwiftGen: 3d5024a47ea79e408cded20763d7a17d18a4548c
TagListView: a1c236d17960a0cf64156725a76ce6d73ebce2be
PODFILE CHECKSUM: 4bffa24562c1bf0effb27887ed79f1efdacbf362
PODFILE CHECKSUM: e0340aeb66997f4685a43b1d51d2aa3b3254a8ee
COCOAPODS: 1.9.3
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>ProximityNotificationTests.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>12</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>AFB3937D24630DF8003A7D58</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>AFC9D3BC246C413F001B7F5B</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -56,6 +56,14 @@ public final class ParametersManager: NSObject {
public var pushDisplayOnSuccess: Bool { valueFor(name: "app.push.displayOnSuccess") as? Bool ?? false }
public var pushDisplayAll: Bool { valueFor(name: "app.push.displayAll") as? Bool ?? false }
public var displayDepartmentLevel: Bool { valueFor(name: "app.keyfigures.displayDepartmentLevel") as? Bool ?? false }
public var qrCodeDeletionHours: Double { valueFor(name: "app.qrCode.deletionHours") as? Double ?? 24.0}
public var qrCodeExpiredHours: Double { valueFor(name: "app.qrCode.expiredHours") as? Double ?? 1.0}
public var qrCodeFormattedString: String { valueFor(name: "app.qrCode.formattedString") as? String ?? "Cree le: <creationDate> a <creationHour>;\nNom: <lastname>;\nPrenom: <firstname>;\nNaissance: <dob> a <cityofbirth>;\nAdresse: <address> <zip> <city>;\nSortie: <datetime-day> a <datetime-hour>;\nMotif: <reason-code>" }
public var qrCodeFormattedStringDisplayed: String { valueFor(name: "app.qrCode.formattedStringDisplayed") as? String ?? "Créé le <creationDate> à <creationHour>\nNom : <lastname>;\nPrénom : <firstname>;\nNaissance : <dob> à <cityofbirth>\nAdresse : <address> <zip> <city>\nSortie : <datetime-day> à <datetime-hour>\nMotif: <reason-code>" }
public var qrCodeFooterString: String { valueFor(name: "app.qrCode.footerString") as? String ?? "<firstname> - <datetime-day>, <datetime-hour>\n<reason-shortlabel>" }
public var statusTimeInterval: Double {
let randomStatusHour: Double = self.randomStatusHour ?? 0.0
let interval: Double = (self.checkStatusFrequency ?? 0.0) * 3600.0 + (randomStatusHour == 0.0 ? 0.0 : Double.random(in: 0..<randomStatusHour * 3600.0))
......@@ -114,6 +122,7 @@ public final class ParametersManager: NSObject {
}
}
// TODO: Fetch config using background url session.
public func fetchConfig(_ completion: @escaping (_ result: Result<Double, Error>) -> ()) {
let requestId: String = UUID().uuidString
completions[requestId] = completion
......
......@@ -240,35 +240,10 @@ public final class Server: NSObject, RBServer {
self.deviceTimeNotAlignedToServerTimeDetected()
completion(.failure(NSError.deviceTime))
} else {
let body: RBServerRegisterBodyV3 = RBServerRegisterBodyV3(captcha: captcha,
captchaId: captchaId,
clientPublicECDHKey: publicKey,
pushInfo: RBServerPushInfo(token: RBManager.shared.pushToken ?? "",
locale: Locale.current.identifier,
timezone: TimeZone.current.identifier))
self.processRequest(url: self.baseUrl().appendingPathComponent("register"), method: .post, body: body) { result in
switch result {
case let .success(data):
do {
let response: RBServerRegisterResponse = try JSONDecoder().decode(RBServerRegisterResponse.self, from: data)
let rootJson: [String: Any] = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String: Any] ?? [:]
let config: [[String: Any]] = rootJson["config"] as? [[String: Any]] ?? []
let transformedResponse: RBRegisterResponse = RBRegisterResponse(tuples: response.tuples,
timeStart: response.timeStart,
config: config)
completion(.success(transformedResponse))
} catch {
completion(.failure(error))
}
case let .failure(error):
completion(.failure(error))
}
}
self.processRegisterV3(captcha: captcha, captchaId: captchaId, publicKey: publicKey, completion: completion)
}
case let .failure(error):
completion(.failure(error))
self.processRegisterV3(captcha: captcha, captchaId: captchaId, publicKey: publicKey, completion: completion)
}
}
}
......@@ -391,6 +366,35 @@ public final class Server: NSObject, RBServer {
}
}
private func processRegisterV3(captcha: String, captchaId: String, publicKey: String, completion: @escaping (_ result: Result<RBRegisterResponse, Error>) -> ()) {
let body: RBServerRegisterBodyV3 = RBServerRegisterBodyV3(captcha: captcha,
captchaId: captchaId,
clientPublicECDHKey: publicKey,
pushInfo: RBServerPushInfo(token: RBManager.shared.pushToken ?? "",
locale: Locale.current.identifier,
timezone: TimeZone.current.identifier))
self.processRequest(url: self.baseUrl().appendingPathComponent("register"), method: .post, body: body) { result in
switch result {
case let .success(data):
do {
let response: RBServerRegisterResponse = try JSONDecoder().decode(RBServerRegisterResponse.self, from: data)
let rootJson: [String: Any] = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String: Any] ?? [:]
let config: [[String: Any]] = rootJson["config"] as? [[String: Any]] ?? []
let transformedResponse: RBRegisterResponse = RBRegisterResponse(tuples: response.tuples,
timeStart: response.timeStart,
config: config)
completion(.success(transformedResponse))
} catch {
completion(.failure(error))
}
case let .failure(error):
completion(.failure(error))
}
}
}
}
extension Server {
......
......@@ -14,5 +14,6 @@ public extension NSNotification.Name {
static var statusDataDidChange: NSNotification.Name = NSNotification.Name(rawValue: "statusDataDidChange")
static var localProximityDataDidChange: NSNotification.Name = NSNotification.Name(rawValue: "localProximityDataDidChange")
static var attestationDataDidChange: NSNotification.Name = NSNotification.Name(rawValue: "attestationDataDidChange")
}
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//
// Attestation.swift
// TousAntiCovid
//
// Created by Lunabee Studio / Date - 29/10/2020 - for the TousAntiCovid project.
//
import Foundation
public struct Attestation {
public let id: String
public let timestamp: Int
public let qrCode: Data
public let footer: String
public let qrCodeString: String
public init(id: String = UUID().uuidString, timestamp: Int, qrCode: Data, footer: String, qrCodeString: String) {
self.id = id
self.timestamp = timestamp
self.qrCode = qrCode
self.footer = footer
self.qrCodeString = qrCodeString
}
}
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//
// RealmAttestation.swift
// TousAntiCovid
//
// Created by Lunabee Studio / Date - 29/10/2020 - for the TousAntiCovid project.
//
import UIKit
import RealmSwift
import RobertSDK
final class RealmAttestation: Object {
@objc dynamic var id: String = UUID().uuidString
@objc dynamic var timestamp: Int = 0
@objc dynamic var qrCode: Data!
@objc dynamic var footer: String!
@objc dynamic var qrCodeString: String!
static func from(attestation: Attestation) -> RealmAttestation {
RealmAttestation(id: attestation.id,
timestamp: attestation.timestamp,
qrCode: attestation.qrCode,
footer: attestation.footer,
qrCodeString: attestation.qrCodeString)
}
convenience init(id: String, timestamp: Int, qrCode: Data, footer: String, qrCodeString: String) {
self.init()
self.id = id
self.timestamp = timestamp
self.qrCode = qrCode
self.footer = footer
self.qrCodeString = qrCodeString
}
override class func primaryKey() -> String? {
return "id"
}
override class func indexedProperties() -> [String] {
return ["id"]
}
func toAttestation() -> Attestation {
Attestation(id: id,
timestamp: timestamp,
qrCode: qrCode,
footer: footer,
qrCodeString: qrCodeString ?? "")
}
}
......@@ -299,6 +299,7 @@ public final class StorageManager: RBStorage {
keychain.delete($0.rawValue)
}
}
deleteAllAttestationFields()
deleteDb(includingFile: includingDBKey)
notifyStatusDataChanged()
}
......@@ -334,6 +335,86 @@ public final class StorageManager: RBStorage {
}
public extension StorageManager {
func saveAttestation(_ attestation: Attestation) {
guard let realm = realm else { return }
let realmAttestation: RealmAttestation = RealmAttestation.from(attestation: attestation)
try! realm.write {
realm.add(realmAttestation, update: .all)
}
notifyAttestationDataChanged()
}
func attestations() -> [Attestation] {
guard let realm = realm else { return [] }
return realm.objects(RealmAttestation.self).map { $0.toAttestation() }
}
func deleteAttestationsData() {
guard let realm = realm else { return }
try! realm.write {
realm.delete(realm.objects(RealmAttestation.self))
}
notifyAttestationDataChanged()
}
func deleteAttestation(_ attestation: Attestation) {
guard let realm = realm else { return }
if let attestation = realm.object(ofType: RealmAttestation.self, forPrimaryKey: attestation.id) {
try! realm.write {
realm.delete(attestation)
}
}
notifyAttestationDataChanged()
}
func deleteExpiredAttestationsData(durationInHours: Double) {
guard let realm = realm else { return }
let now: Date = Date()
let expiredAttestations: [RealmAttestation] = [RealmAttestation](realm.objects(RealmAttestation.self)).filter { attestation in
(now.timeIntervalSince1970 - Double(attestation.timestamp)) >= durationInHours * 3600.0
}
try! realm.write {
realm.delete(expiredAttestations)
}
notifyAttestationDataChanged()
}
func saveAttestationFieldValueForKey(_ key: String, value: String?) {
let keychainKey: String = "attestation-\(key)"
if let value = value {
keychain.set(value, forKey: keychainKey, withAccess: .accessibleAfterFirstUnlockThisDeviceOnly)
} else {
keychain.delete(keychainKey)
}
}
func getAttestationFieldValues() -> [String: String] {
var fieldValues: [String: String] = [:]
keychain.allKeys.forEach { key in
if key.hasPrefix("SCattestation-") {
fieldValues[key.replacingOccurrences(of: "SCattestation-", with: "")] = keychain.get(key.replacingOccurrences(of: "SC", with: ""))
}
}
return fieldValues
}
func getAttestationFieldValueForKey(_ key: String) -> String? {
let keychainKey: String = "attestation-\(key)"
return keychain.get(keychainKey)
}
func deleteAllAttestationFields() {
keychain.allKeys.forEach { key in
if key.hasPrefix("SCattestation-") {
keychain.delete(key.replacingOccurrences(of: "SC", with: ""))
}
}
}
}
private extension StorageManager {
func notifyStatusDataChanged() {
......@@ -344,6 +425,10 @@ private extension StorageManager {
NotificationCenter.default.post(name: .localProximityDataDidChange, object: nil)
}
func notifyAttestationDataChanged() {
NotificationCenter.default.post(name: .attestationDataDidChange, object: nil)
}
}
private extension Realm {
......@@ -378,11 +463,12 @@ private extension Realm {
static private func configuration(key: Data) -> Realm.Configuration {
let classes: [Object.Type] = [RealmEpoch.self,
RealmLocalProximity.self,
RealmAttestation.self,
Permission.self,
PermissionRole.self,
PermissionUser.self]
let databaseUrl: URL = dbsDirectoryUrl().appendingPathComponent("db.realm")
let userConfig: Realm.Configuration = Realm.Configuration(fileURL: databaseUrl, encryptionKey: key, schemaVersion: 6, migrationBlock: { _, _ in }, objectTypes: classes)
let userConfig: Realm.Configuration = Realm.Configuration(fileURL: databaseUrl, encryptionKey: key, schemaVersion: 9, migrationBlock: { _, _ in }, objectTypes: classes)
return userConfig
}
......
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>Proximity.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>11</integer>
</dict>
<key>RobertSDK.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>25</integer>
</dict>
<key>ServerSDK.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>23</integer>
</dict>
<key>StorageSDK.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>22</integer>
</dict>
<key>TAC Multi Plus.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>17</integer>
</dict>
<key>TAC Prod Plus.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>18</integer>
</dict>
<key>TousAntiCovid.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>20</integer>
</dict>
<key>Widget Plus Extension.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>24</integer>
</dict>
<key>WidgetExtension.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>21</integer>
</dict>
</dict>
</dict>
</plist>
This diff is collapsed.
......@@ -28,6 +28,10 @@ extension UIFont {
FontFamily.SFProText.bold.font(size: size)!
}
static func marianneMedium(size: CGFloat) -> UIFont {
FontFamily.Marianne.medium.font(size: size)!
}
static func marianneBold(size: CGFloat) -> UIFont {
FontFamily.Marianne.bold.font(size: size)!
}
......
This diff is collapsed.
This diff is collapsed.