diff --git a/Signal/Signal-Info.plist b/Signal/Signal-Info.plist
index cc0b12e8a..9d303eb69 100644
--- a/Signal/Signal-Info.plist
+++ b/Signal/Signal-Info.plist
@@ -83,6 +83,13 @@
NSThirdPartyExceptionRequiresForwardSecrecy
+ file-dev.lokinet.org
+
+ NSExceptionAllowsInsecureHTTPLoads
+
+ NSIncludesSubdomains
+
+
imaginary.stream
NSExceptionAllowsInsecureHTTPLoads
diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m
index b7dbc7122..89852e4a8 100644
--- a/Signal/src/AppDelegate.m
+++ b/Signal/src/AppDelegate.m
@@ -779,12 +779,15 @@ static NSTimeInterval launchStartedAt;
dispatch_async(dispatch_get_main_queue(), ^{
[self.socketManager requestSocketOpen];
[Environment.shared.contactsManager fetchSystemContactsOnceIfAlreadyAuthorized];
-
- // Loki: Start long polling
- [self startLongPollerIfNeeded];
-
+
// Loki: Tell our friends that we are online
[LKP2PAPI broadcastOnlineStatus];
+
+ // Loki: Start long polling
+ [self startLongPollerIfNeeded];
+
+ // Loki: Get device links
+ [LKStorageAPI getDeviceLinksAssociatedWith:self.tsAccountManager.localNumber];
if (![UIApplication sharedApplication].isRegisteredForRemoteNotifications) {
OWSLogInfo(@"Retrying to register for remote notifications since user hasn't registered yet.");
@@ -1372,15 +1375,18 @@ static NSTimeInterval launchStartedAt;
// enables this feature
[self.disappearingMessagesJob startIfNecessary];
[self.profileManager ensureLocalProfileCached];
-
- // Start Loki friend request expire job
- [self.lokiFriendRequestExpirationJob startIfNecessary];
// For non-legacy users, read receipts are on by default.
[self.readReceiptManager setAreReadReceiptsEnabled:YES];
+
+ // Loki: Start friend request expiration job
+ [self.lokiFriendRequestExpirationJob startIfNecessary];
// Loki: Start long polling
[self startLongPollerIfNeeded];
+
+ // Loki: Get device links
+ [LKStorageAPI getDeviceLinksAssociatedWith:self.tsAccountManager.localNumber];
}
}
diff --git a/Signal/src/Loki/Settings/DeviceLinkingModal.swift b/Signal/src/Loki/Settings/DeviceLinkingModal.swift
index 22e657b1e..ae11a7fb5 100644
--- a/Signal/src/Loki/Settings/DeviceLinkingModal.swift
+++ b/Signal/src/Loki/Settings/DeviceLinkingModal.swift
@@ -143,7 +143,9 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
session.stopListeningForLinkingRequests()
session.markLinkingRequestAsProcessed()
dismiss(animated: true, completion: nil)
- let _ = LokiStorageAPI.addDeviceLink(deviceLink) // TODO: Handle error
+ LokiStorageAPI.addDeviceLink(deviceLink).catch { error in
+ print("[Loki] Failed to add device link due to error: \(error).")
+ }
}
func handleDeviceLinkAuthorized(_ deviceLink: DeviceLink) {
@@ -157,7 +159,9 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
mnemonicLabel.isHidden = true
buttonStackView.isHidden = true
bottomSpacer.isHidden = false
- let _ = LokiStorageAPI.addDeviceLink(deviceLink) // TODO: Handle error
+ LokiStorageAPI.addDeviceLink(deviceLink).catch { error in
+ print("[Loki] Failed to add device link due to error: \(error).")
+ }
Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in
self.delegate?.handleDeviceLinkAuthorized(deviceLink)
self.dismiss(animated: true, completion: nil)
diff --git a/SignalServiceKit/src/Loki/API/LokiStorageAPI.swift b/SignalServiceKit/src/Loki/API/LokiStorageAPI.swift
index 2a76ebe0a..3e019a629 100644
--- a/SignalServiceKit/src/Loki/API/LokiStorageAPI.swift
+++ b/SignalServiceKit/src/Loki/API/LokiStorageAPI.swift
@@ -4,7 +4,11 @@ import PromiseKit
public final class LokiStorageAPI : LokiDotNetAPI {
// MARK: Settings
- private static let server = ""
+ #if DEBUG
+ private static let server = "http://file-dev.lokinet.org"
+ #else
+ private static let server = "https://file.lokinet.org"
+ #endif
private static let deviceLinkType = "network.loki.messenger.devicemapping"
// MARK: Database
@@ -18,7 +22,11 @@ public final class LokiStorageAPI : LokiDotNetAPI {
deviceLinks = storage.getDeviceLinks(for: userHexEncodedPublicKey, in: transaction)
}
deviceLinks.insert(deviceLink)
- return setDeviceLinks(deviceLinks)
+ return setDeviceLinks(deviceLinks).map {
+ storage.dbReadWriteConnection.readWrite { transaction in
+ storage.addDeviceLink(deviceLink, in: transaction)
+ }
+ }
}
/// Removes the given device link from the user's device mapping on the server.
@@ -28,7 +36,11 @@ public final class LokiStorageAPI : LokiDotNetAPI {
deviceLinks = storage.getDeviceLinks(for: userHexEncodedPublicKey, in: transaction)
}
deviceLinks.remove(deviceLink)
- return setDeviceLinks(deviceLinks)
+ return setDeviceLinks(deviceLinks).map {
+ storage.dbReadWriteConnection.readWrite { transaction in
+ storage.removeDeviceLink(deviceLink, in: transaction)
+ }
+ }
}
/// Gets the device links associated with the given hex encoded public key from the
@@ -39,7 +51,7 @@ public final class LokiStorageAPI : LokiDotNetAPI {
let queryParameters = "include_user_annotations=1"
let url = URL(string: "\(server)/users/@\(hexEncodedPublicKey)?\(queryParameters)")!
let request = TSRequest(url: url)
- return TSNetworkManager.shared().makePromise(request: request).map { $0.responseObject }.map { rawResponse in
+ return TSNetworkManager.shared().makePromise(request: request).map { $0.responseObject }.map { rawResponse -> Set in
guard let json = rawResponse as? JSON, let data = json["data"] as? JSON,
let annotations = data["annotations"] as? [JSON], let annotation = annotations.first(where: { $0["type"] as? String == deviceLinkType }),
let rawDeviceLinks = annotation["authorisations"] as? [JSON] else {
@@ -74,10 +86,21 @@ public final class LokiStorageAPI : LokiDotNetAPI {
}
return deviceLink
})
+ }.map { deviceLinks -> Set in
+ storage.dbReadWriteConnection.readWrite { transaction in
+ storage.setDeviceLinks(deviceLinks, in: transaction)
+ }
+ return deviceLinks
}
}
}
+ // MARK: Public API (Obj-C)
+ @objc(getDeviceLinksAssociatedWith:)
+ public static func objc_getDeviceLinks(associatedWith hexEncodedPublicKey: String) -> AnyPromise {
+ return AnyPromise.from(getDeviceLinks(associatedWith: hexEncodedPublicKey))
+ }
+
// MARK: Private API
public static func setDeviceLinks(_ deviceLinks: Set) -> Promise {
print("[Loki] Updating device links.")
diff --git a/SignalServiceKit/src/Loki/Database/OWSPrimaryStorage+Loki.swift b/SignalServiceKit/src/Loki/Database/OWSPrimaryStorage+Loki.swift
index 6853a9c02..daf5b346c 100644
--- a/SignalServiceKit/src/Loki/Database/OWSPrimaryStorage+Loki.swift
+++ b/SignalServiceKit/src/Loki/Database/OWSPrimaryStorage+Loki.swift
@@ -4,11 +4,28 @@ extension OWSPrimaryStorage {
private func getCollection(for primaryDevice: String) -> String {
return "LokiDeviceLinkCollection-\(primaryDevice)"
}
-
- public func storeDeviceLink(_ deviceLink: DeviceLink, in transaction: YapDatabaseReadWriteTransaction) {
+
+ public func setDeviceLinks(_ deviceLinks: Set, in transaction: YapDatabaseReadWriteTransaction) {
+ let masterHexEncodedPublicKeys = deviceLinks.map { $0.master.hexEncodedPublicKey }
+ guard masterHexEncodedPublicKeys.count == 1 else {
+ print("[Loki] Found inconsistent set of device links.")
+ return
+ }
+ let masterHexEncodedPublicKey = masterHexEncodedPublicKeys.first!
+ let collection = getCollection(for: masterHexEncodedPublicKey)
+ transaction.removeAllObjects(inCollection: collection)
+ deviceLinks.forEach { addDeviceLink($0, in: transaction) } // TODO: Check the performance impact of this
+ }
+
+ public func addDeviceLink(_ deviceLink: DeviceLink, in transaction: YapDatabaseReadWriteTransaction) {
let collection = getCollection(for: deviceLink.master.hexEncodedPublicKey)
transaction.setObject(deviceLink, forKey: deviceLink.slave.hexEncodedPublicKey, inCollection: collection)
}
+
+ public func removeDeviceLink(_ deviceLink: DeviceLink, in transaction: YapDatabaseReadWriteTransaction) {
+ let collection = getCollection(for: deviceLink.master.hexEncodedPublicKey)
+ transaction.removeObject(forKey: deviceLink.slave.hexEncodedPublicKey, inCollection: collection)
+ }
public func getDeviceLinks(for masterHexEncodedPublicKey: String, in transaction: YapDatabaseReadTransaction) -> Set {
let collection = getCollection(for: masterHexEncodedPublicKey)
diff --git a/SignalServiceKit/src/Storage/OWSPrimaryStorage.m b/SignalServiceKit/src/Storage/OWSPrimaryStorage.m
index 91a87b3ac..ec3dbcd1d 100644
--- a/SignalServiceKit/src/Storage/OWSPrimaryStorage.m
+++ b/SignalServiceKit/src/Storage/OWSPrimaryStorage.m
@@ -214,7 +214,10 @@ void VerifyRegistrationsForPrimaryStorage(OWSStorage *storage)
[OWSMediaGalleryFinder asyncRegisterDatabaseExtensionsWithPrimaryStorage:self];
[TSDatabaseView asyncRegisterLazyRestoreAttachmentsDatabaseView:self];
[SSKJobRecordFinder asyncRegisterDatabaseExtensionObjCWithStorage:self];
- [LKFriendRequestExpirationMessageFinder asyncRegisterDatabaseExtensions:self]; // Loki
+
+ // Loki
+ [LKFriendRequestExpirationMessageFinder asyncRegisterDatabaseExtensions:self];
+ [LKDeviceLinkIndex asyncRegisterDatabaseExtensions:self];
[self.database
flushExtensionRequestsWithCompletionQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)