diff --git a/Signal/src/Loki/View Controllers/DeviceLinksVC.swift b/Signal/src/Loki/View Controllers/DeviceLinksVC.swift index 952c70820..c0599155f 100644 --- a/Signal/src/Loki/View Controllers/DeviceLinksVC.swift +++ b/Signal/src/Loki/View Controllers/DeviceLinksVC.swift @@ -162,13 +162,13 @@ final class DeviceLinksVC : BaseVC, UITableViewDataSource, UITableViewDelegate, storage.dbReadWriteConnection.readWrite { transaction in storage.deleteAllSessions(forContact: linkedDeviceHexEncodedPublicKey, protocolContext: transaction) } - }) { _ in + }, failure: { _ in print("[Loki] Failed to send unlink device message.") let storage = OWSPrimaryStorage.shared() storage.dbReadWriteConnection.readWrite { transaction in storage.deleteAllSessions(forContact: linkedDeviceHexEncodedPublicKey, protocolContext: transaction) } - } + }) self?.updateDeviceLinks() }.catch { [weak self] _ in let alert = UIAlertController(title: NSLocalizedString("Couldn't Unlink Device", comment: ""), message: NSLocalizedString("Please check your internet connection and try again", comment: ""), preferredStyle: .alert) diff --git a/SignalServiceKit/src/Loki/Protocol/Meta/SessionMetaProtocol.swift b/SignalServiceKit/src/Loki/Protocol/Meta/SessionMetaProtocol.swift index 7a4edc7f1..b21dc08b2 100644 --- a/SignalServiceKit/src/Loki/Protocol/Meta/SessionMetaProtocol.swift +++ b/SignalServiceKit/src/Loki/Protocol/Meta/SessionMetaProtocol.swift @@ -9,6 +9,7 @@ import PromiseKit // • Document the expected cases for everything. // • Express those cases in tests. +/// See [Receipts, Transcripts & Typing Indicators](https://github.com/loki-project/session-protocol-docs/wiki/Receipts,-Transcripts-&-Typing-Indicators) for more information. @objc(LKSessionMetaProtocol) public final class SessionMetaProtocol : NSObject { diff --git a/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift b/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift index 95ec10e6f..29630c58f 100644 --- a/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift +++ b/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift @@ -92,6 +92,7 @@ public final class MultiDeviceProtocol : NSObject { } } + /// See [Multi Device Message Sending](https://github.com/loki-project/session-protocol-docs/wiki/Multi-Device-Message-Sending) for more information. @objc(sendMessageToDestinationAndLinkedDevices:in:) public static func sendMessageToDestinationAndLinkedDevices(_ messageSend: OWSMessageSend, in transaction: YapDatabaseReadTransaction) { let message = messageSend.message @@ -146,6 +147,7 @@ public final class MultiDeviceProtocol : NSObject { return AnyPromise.from(promise) } + /// See [Auto-Generated Friend Requests](https://github.com/loki-project/session-protocol-docs/wiki/Auto-Generated-Friend-Requests) for more information. @objc(getAutoGeneratedMultiDeviceFRMessageForHexEncodedPublicKey:in:) public static func getAutoGeneratedMultiDeviceFRMessage(for hexEncodedPublicKey: String, in transaction: YapDatabaseReadWriteTransaction) -> FriendRequestMessage { let thread = TSContactThread.getOrCreateThread(withContactId: hexEncodedPublicKey, transaction: transaction) @@ -162,11 +164,13 @@ public final class MultiDeviceProtocol : NSObject { return result } + /// See [Auto-Generated Friend Requests](https://github.com/loki-project/session-protocol-docs/wiki/Auto-Generated-Friend-Requests) for more information. @objc(getAutoGeneratedMultiDeviceFRMessageSendForHexEncodedPublicKey:in:) public static func objc_getAutoGeneratedMultiDeviceFRMessageSend(for hexEncodedPublicKey: String, in transaction: YapDatabaseReadWriteTransaction) -> AnyPromise { return AnyPromise.from(getAutoGeneratedMultiDeviceFRMessageSend(for: hexEncodedPublicKey, in: transaction)) } + /// See [Auto-Generated Friend Requests](https://github.com/loki-project/session-protocol-docs/wiki/Auto-Generated-Friend-Requests) for more information. public static func getAutoGeneratedMultiDeviceFRMessageSend(for hexEncodedPublicKey: String, in transaction: YapDatabaseReadWriteTransaction, seal externalSeal: Resolver? = nil) -> Promise { // We don't update friend request status here as it is done in OWSMessageSender.sendMessage(:) let thread = TSContactThread.getOrCreateThread(withContactId: hexEncodedPublicKey, transaction: transaction) @@ -235,15 +239,27 @@ public final class MultiDeviceProtocol : NSObject { public static func handleUnlinkDeviceMessage(_ dataMessage: SSKProtoDataMessage, wrappedIn envelope: SSKProtoEnvelope, using transaction: YapDatabaseReadWriteTransaction) { // The envelope source is set during UD decryption let hexEncodedPublicKey = envelope.source! + // Check that the request was sent by our master device guard let masterHexEncodedPublicKey = storage.getMasterHexEncodedPublicKey(for: getUserHexEncodedPublicKey(), in: transaction) else { return } let wasSentByMasterDevice = (masterHexEncodedPublicKey == hexEncodedPublicKey) guard wasSentByMasterDevice else { return } - let deviceLinks = storage.getDeviceLinks(for: hexEncodedPublicKey, in: transaction) - if !deviceLinks.contains(where: { $0.master.hexEncodedPublicKey == hexEncodedPublicKey && $0.slave.hexEncodedPublicKey == getUserHexEncodedPublicKey() }) { + // Ignore the request if we don't know about the device link in question + let masterDeviceLinks = storage.getDeviceLinks(for: masterHexEncodedPublicKey, in: transaction) + if !masterDeviceLinks.contains(where: { + $0.master.hexEncodedPublicKey == masterHexEncodedPublicKey && $0.slave.hexEncodedPublicKey == getUserHexEncodedPublicKey() + }) { return } - LokiFileServerAPI.getDeviceLinks(associatedWith: getUserHexEncodedPublicKey()).done(on: DispatchQueue.main) { deviceLinks in - if deviceLinks.contains(where: { $0.master.hexEncodedPublicKey == hexEncodedPublicKey && $0.slave.hexEncodedPublicKey == getUserHexEncodedPublicKey() }) { + LokiFileServerAPI.getDeviceLinks(associatedWith: getUserHexEncodedPublicKey()).done(on: DispatchQueue.main) { slaveDeviceLinks in + // Check that the device link IS present on the file server. + // Note that the device link as seen from the master device's perspective has been deleted at this point, but the + // device link as seen from the slave perspective hasn't. + if slaveDeviceLinks.contains(where: { + $0.master.hexEncodedPublicKey == masterHexEncodedPublicKey && $0.slave.hexEncodedPublicKey == getUserHexEncodedPublicKey() + }) { + for deviceLink in slaveDeviceLinks { // In theory there should only be one + LokiFileServerAPI.removeDeviceLink(deviceLink) // Attempt to clean up on the file server + } UserDefaults.standard[.wasUnlinked] = true NotificationCenter.default.post(name: .dataNukeRequested, object: nil) }