From 1ba0a170c11bc06daf305f7c2d116b93b17511b0 Mon Sep 17 00:00:00 2001 From: Mikunj Date: Wed, 18 Sep 2019 09:26:07 +1000 Subject: [PATCH 1/2] Added database extensions. --- Pods | 2 +- .../LokiPairingAuthorisation.swift | 37 +++++++++++++ .../OWSPrimaryStorage+Multidevice.swift | 31 +++++++++++ .../PairingAuthorisationsIndex.swift | 53 +++++++++++++++++++ 4 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 SignalServiceKit/src/Loki/Multidevice/LokiPairingAuthorisation.swift create mode 100644 SignalServiceKit/src/Loki/Multidevice/OWSPrimaryStorage+Multidevice.swift create mode 100644 SignalServiceKit/src/Loki/Multidevice/PairingAuthorisationsIndex.swift diff --git a/Pods b/Pods index 9188141c9..1ab1cbbeb 160000 --- a/Pods +++ b/Pods @@ -1 +1 @@ -Subproject commit 9188141c9666093156f4b54b9aef025330651505 +Subproject commit 1ab1cbbeb63409bd78306e358eb99de4a8ad3e42 diff --git a/SignalServiceKit/src/Loki/Multidevice/LokiPairingAuthorisation.swift b/SignalServiceKit/src/Loki/Multidevice/LokiPairingAuthorisation.swift new file mode 100644 index 000000000..55fb844ba --- /dev/null +++ b/SignalServiceKit/src/Loki/Multidevice/LokiPairingAuthorisation.swift @@ -0,0 +1,37 @@ +@objc(LKPairingAuthorisation) +public final class LokiPairingAuthorisation : NSObject, NSCoding { + @objc public let primaryDevicePubKey: String + @objc public let secondaryDevicePubKey: String + @objc public let requestSignature: Data? + @objc public let grantSignature: Data? + + @objc public var isGranted: Bool { + return grantSignature != nil + } + + @objc public init(primaryDevicePubKey: String, secondaryDevicePubKey: String, requestSignature: Data? = nil, grantSignature: Data? = nil) { + self.primaryDevicePubKey = primaryDevicePubKey + self.secondaryDevicePubKey = secondaryDevicePubKey + self.requestSignature = requestSignature + self.grantSignature = grantSignature + } + + public convenience init?(coder aDecoder: NSCoder) { + guard let primaryDevicePubKey = aDecoder.decodeObject(forKey: "primaryDevicePubKey") as? String, + let secondaryDevicePubKey = aDecoder.decodeObject(forKey: "secondaryDevicePubKey") as? String else { + return nil + } + + let requestSignature = aDecoder.decodeObject(forKey: "requestSignature") as? Data + let grantSignature = aDecoder.decodeObject(forKey: "grantSignature") as? Data + + self.init(primaryDevicePubKey: primaryDevicePubKey, secondaryDevicePubKey: secondaryDevicePubKey, requestSignature: requestSignature, grantSignature: grantSignature) + } + + public func encode(with aCoder: NSCoder) { + aCoder.encode(primaryDevicePubKey, forKey: "primaryDevicePubKey") + aCoder.encode(secondaryDevicePubKey, forKey: "secondaryDevicePubKey") + aCoder.encode(requestSignature, forKey: "requestSignature") + aCoder.encode(grantSignature, forKey: "grantSignature") + } +} diff --git a/SignalServiceKit/src/Loki/Multidevice/OWSPrimaryStorage+Multidevice.swift b/SignalServiceKit/src/Loki/Multidevice/OWSPrimaryStorage+Multidevice.swift new file mode 100644 index 000000000..fb7c452bf --- /dev/null +++ b/SignalServiceKit/src/Loki/Multidevice/OWSPrimaryStorage+Multidevice.swift @@ -0,0 +1,31 @@ +extension OWSPrimaryStorage { + private func getCollection(for primaryDevice: String) -> String { + return "LokiMultiDevice-\(primaryDevice)" + } + + public func getAuthorisation(forSecondaryDevice secondaryDevice: String, with transaction: YapDatabaseReadTransaction) -> LokiPairingAuthorisation? { + let query = YapDatabaseQuery(string: "WHERE \(PairingAuthorisationsIndex.secondaryDevicePubKey) = ?", parameters: [secondaryDevice]) + let authorisations = PairingAuthorisationsIndex.getPairingAuthorisations(with: query, transaction: transaction) + + // This should never be the case + if (authorisations.count > 1) { owsFailDebug("[Loki][Multidevice] Found multiple authorisations for secondary device: \(secondaryDevice)") } + + return authorisations.first + } + + public func createOrUpdatePairingAuthorisation(_ authorisation: LokiPairingAuthorisation, with transaction: YapDatabaseReadWriteTransaction) { + // iOS makes this easy, we can group all authorizations into the primary device collection + // Then we associate an authorisation with the secondary device key + transaction.setObject(authorisation, forKey: authorisation.secondaryDevicePubKey, inCollection: getCollection(for: authorisation.primaryDevicePubKey)) + } + + public func getSecondaryDevices(forPrimaryDevice primaryDevice: String, with transaction: YapDatabaseReadTransaction) -> [String] { + // primary device collection should have secondary devices as its keys + return transaction.allKeys(inCollection: getCollection(for: primaryDevice)) + } + + public func getPrimaryDevice(forSecondaryDevice secondaryDevice: String, with transaction: YapDatabaseReadTransaction) -> String? { + let authorisation = getAuthorisation(forSecondaryDevice: secondaryDevice, with: transaction) + return authorisation?.primaryDevicePubKey + } +} diff --git a/SignalServiceKit/src/Loki/Multidevice/PairingAuthorisationsIndex.swift b/SignalServiceKit/src/Loki/Multidevice/PairingAuthorisationsIndex.swift new file mode 100644 index 000000000..ec718fd95 --- /dev/null +++ b/SignalServiceKit/src/Loki/Multidevice/PairingAuthorisationsIndex.swift @@ -0,0 +1,53 @@ +@objc(LKPairingAuthorisationsIndex) +public final class PairingAuthorisationsIndex : NSObject { + private static let name = "loki_index_pairing_authorisations" + + // Fields + @objc public static let primaryDevicePubKey = "pairing_primary_device_pub_key" + @objc public static let secondaryDevicePubKey = "pairing_secondary_device_pub_key" + @objc public static let isGranted = "pairing_is_granted" + + // MARK: Database Extension + + @objc public static var indexDatabaseExtension: YapDatabaseSecondaryIndex { + let setup = YapDatabaseSecondaryIndexSetup() + setup.addColumn(primaryDevicePubKey, with: .text) + setup.addColumn(secondaryDevicePubKey, with: .text) + setup.addColumn(isGranted, with: .integer) + + let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { (transaction, dict, collection, key, object) in + guard let pairing = object as? LokiPairingAuthorisation else { return } + dict[primaryDevicePubKey] = pairing.primaryDevicePubKey + dict[secondaryDevicePubKey] = pairing.secondaryDevicePubKey + dict[isGranted] = pairing.isGranted + } + + return YapDatabaseSecondaryIndex(setup: setup, handler: handler) + } + + @objc public static var databaseExtensionName: String { + return name + } + + @objc public static func asyncRegisterDatabaseExtensions(_ storage: OWSStorage) { + storage.register(indexDatabaseExtension, withName: name) + } + + // MARK: Helper + + public static func enumeratePairingAuthorisations(with query: YapDatabaseQuery, transaction: YapDatabaseReadTransaction, block: @escaping (LokiPairingAuthorisation, UnsafeMutablePointer) -> Void) { + let ext = transaction.ext(PairingAuthorisationsIndex.name) as? YapDatabaseSecondaryIndexTransaction + ext?.enumerateKeysAndObjects(matching: query) { (collection, key, object, stop) in + guard let authorisation = object as? LokiPairingAuthorisation else { return } + block(authorisation, stop) + } + } + + public static func getPairingAuthorisations(with query: YapDatabaseQuery, transaction: YapDatabaseReadTransaction) -> [LokiPairingAuthorisation] { + var authorisations = [LokiPairingAuthorisation]() + enumeratePairingAuthorisations(with: query, transaction: transaction) { (authorisation, _) in + authorisations.append(authorisation) + } + return authorisations + } +} From 0b75ce85a2937b5526c3b3e7b5a869e15ab0ff38 Mon Sep 17 00:00:00 2001 From: Mikunj Date: Wed, 18 Sep 2019 14:38:15 +1000 Subject: [PATCH 2/2] Updated pods. --- Pods | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pods b/Pods index 1ab1cbbeb..1b8d82e0d 160000 --- a/Pods +++ b/Pods @@ -1 +1 @@ -Subproject commit 1ab1cbbeb63409bd78306e358eb99de4a8ad3e42 +Subproject commit 1b8d82e0d7917369c92ad5bb116cb61c734533d6