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)