mobile-ios/CovidSafe/EncounterV2Mapping.swift
2020-05-26 17:13:26 +10:00

102 lines
4.6 KiB
Swift

//
// EncounterV2Mapping.swift
// CovidSafe
//
// Copyright © 2020 Australian Government. All rights reserved.
//
import CoreData
struct MigrationRemoteBlob: Encodable {
enum CodingKeys: String, CodingKey {
case msg
case modelC
case modelP
case rssi
case txPower
}
var msg: String?
var modelC: String?
var modelP: String?
var rssi: NSNumber?
var txPower: NSNumber?
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
if let msg = msg {
try container.encode(msg, forKey: .msg)
}
if let modelC = modelC, modelC != BluetraceConfig.DummyModel{
try container.encode(modelC, forKey: .modelC)
}
if let modelP = modelP, modelP != BluetraceConfig.DummyModel {
try container.encode(modelP, forKey: .modelP)
}
if let rssi = rssi, rssi.intValue != BluetraceConfig.DummyRSSI {
try container.encode(rssi.doubleValue, forKey: .rssi)
}
if let txPower = txPower, txPower.intValue != BluetraceConfig.DummyTxPower {
try container.encode(txPower.doubleValue, forKey: .txPower)
}
}
}
class EncounterV2Mapping: NSEntityMigrationPolicy {
var localEmptyBlob: String = ""
override func begin(_ mapping: NSEntityMapping, with manager: NSMigrationManager) throws {
try super.begin(mapping, with: manager)
let emptyLocal = try JSONEncoder().encode(MigrationRemoteBlob())
localEmptyBlob = try Crypto.encrypt(dataToEncrypt: emptyLocal)
}
override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
if (sInstance.entity.name == "Encounter") {
guard let version = sInstance.primitiveValue(forKey: "v") as? Int64 else {
return
}
let encounterV2 = NSEntityDescription.insertNewObject(forEntityName: "Encounter", into: manager.destinationContext)
let msg = sInstance.primitiveValue(forKey: "msg") as? String
let modelC = sInstance.primitiveValue(forKey: "modelC") as? String
let modelP = sInstance.primitiveValue(forKey: "modelP") as? String
let rssi = sInstance.primitiveValue(forKey: "rssi") as? NSNumber
let txPower = sInstance.primitiveValue(forKey: "txPower") as? NSNumber
let org = sInstance.primitiveValue(forKey: "org") as? String
let timestamp = sInstance.primitiveValue(forKey: "timestamp") as? Date
encounterV2.setPrimitiveValue(org, forKey: "org")
encounterV2.setPrimitiveValue(BluetraceConfig.ProtocolVersion, forKey: "v")
encounterV2.setPrimitiveValue(timestamp, forKey: "timestamp")
do {
try autoreleasepool {
if version == 1 {
//convert a regular old v1 entry
encounterV2.setPrimitiveValue(localEmptyBlob, forKey: "localBlob")
let remoteBlob = MigrationRemoteBlob(msg: msg, modelC: modelC, modelP: modelP, rssi: rssi, txPower: txPower)
let blobJson = try JSONEncoder().encode(remoteBlob)
let remoteBlobEncrypted = try Crypto.encrypt(dataToEncrypt: blobJson)
encounterV2.setPrimitiveValue(remoteBlobEncrypted, forKey: "remoteBlob")
manager.associate(sourceInstance: sInstance, withDestinationInstance: encounterV2, for: mapping)
} else if version == 2 {
//convert an entry that was recieved from an already updated app (the msg will already be encrypted)
let localMigrationBlob = MigrationRemoteBlob(msg: nil, modelC: modelC, modelP: modelP, rssi: rssi, txPower: txPower)
let jsonLocal = try JSONEncoder().encode(localMigrationBlob)
let localBlob = try Crypto.encrypt(dataToEncrypt: jsonLocal)
encounterV2.setPrimitiveValue(localBlob, forKey: "localBlob")
encounterV2.setPrimitiveValue(msg, forKey: "remoteBlob")
manager.associate(sourceInstance: sInstance, withDestinationInstance: encounterV2, for: mapping)
}
}
} catch {
throw(error)
}
// we're dropping all the debug messages save to the db during the migration as they're unnessecary
}
}
}