From a6fa53aaf01394fdfb03141d86f2e0da75f78d4d Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Thu, 9 Feb 2023 16:53:29 +1100 Subject: [PATCH 1/4] fix #768 --- Session/Conversations/ConversationViewModel.swift | 12 +++++++++--- .../Shared Models/MessageViewModel.swift | 4 +++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Session/Conversations/ConversationViewModel.swift b/Session/Conversations/ConversationViewModel.swift index 92e55e45b..503691370 100644 --- a/Session/Conversations/ConversationViewModel.swift +++ b/Session/Conversations/ConversationViewModel.swift @@ -82,7 +82,11 @@ public class ConversationViewModel: OWSAudioPlayerDelegate { // distinct stutter) self.pagedDataObserver = self.setupPagedObserver( for: threadId, - userPublicKey: getUserHexEncodedPublicKey() + userPublicKey: getUserHexEncodedPublicKey(), + blindedPublicKey: SessionThread.getUserHexEncodedBlindedKey( + threadId: threadId, + threadVariant: threadVariant + ) ) // Run the initial query on a background thread so we don't block the push transition @@ -166,7 +170,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate { } } - private func setupPagedObserver(for threadId: String, userPublicKey: String) -> PagedDatabaseObserver { + private func setupPagedObserver(for threadId: String, userPublicKey: String, blindedPublicKey: String?) -> PagedDatabaseObserver { return PagedDatabaseObserver( pagedTable: Interaction.self, pageSize: ConversationViewModel.pageSize, @@ -214,6 +218,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate { orderSQL: MessageViewModel.orderSQL, dataQuery: MessageViewModel.baseQuery( userPublicKey: userPublicKey, + blindedPublicKey: blindedPublicKey, orderSQL: MessageViewModel.orderSQL, groupSQL: MessageViewModel.groupSQL ), @@ -443,7 +448,8 @@ public class ConversationViewModel: OWSAudioPlayerDelegate { self.observableThreadData = self.setupObservableThreadData(for: updatedThreadId) self.pagedDataObserver = self.setupPagedObserver( for: updatedThreadId, - userPublicKey: getUserHexEncodedPublicKey() + userPublicKey: getUserHexEncodedPublicKey(), + blindedPublicKey: nil ) // Try load everything up to the initial visible message, fallback to just the initial page of messages diff --git a/SessionMessagingKit/Shared Models/MessageViewModel.swift b/SessionMessagingKit/Shared Models/MessageViewModel.swift index 81c452039..a04fd937b 100644 --- a/SessionMessagingKit/Shared Models/MessageViewModel.swift +++ b/SessionMessagingKit/Shared Models/MessageViewModel.swift @@ -621,6 +621,7 @@ public extension MessageViewModel { static func baseQuery( userPublicKey: String, + blindedPublicKey: String?, orderSQL: SQL, groupSQL: SQL? ) -> (([Int64]) -> AdaptedFetchRequest>) { @@ -717,7 +718,8 @@ public extension MessageViewModel { \(interactionAttachment[.attachmentId]) AS \(Quote.Columns.attachmentId) FROM \(Quote.self) LEFT JOIN \(Interaction.self) ON ( - \(quote[.authorId]) = \(interaction[.authorId]) AND + (\(quote[.authorId]) = \(interaction[.authorId]) OR + \(quote[.authorId]) = \(blindedPublicKey ?? "") AND \(userPublicKey) = \(interaction[.authorId]) ) AND \(quote[.timestampMs]) = \(interaction[.timestampMs]) ) LEFT JOIN \(InteractionAttachment.self) ON \(interaction[.id]) = \(interactionAttachment[.interactionId]) From b271e9c4c92c7ef58078a1a72c583be5cbf2244e Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Mon, 13 Feb 2023 11:55:55 +1100 Subject: [PATCH 2/4] update local open group message to save blinded author id --- SessionMessagingKit/Sending & Receiving/MessageSender.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender.swift b/SessionMessagingKit/Sending & Receiving/MessageSender.swift index 5cf680554..ee0f23da7 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender.swift @@ -597,7 +597,8 @@ public final class MessageSender { // real message has no use when we delete a message. It is OK to let it be. try interaction.with( serverHash: message.serverHash, - + // Update the authorId if blinded id is enabled, otherwise it will remain the same + authorId: message.sender, // Track the open group server message ID and update server timestamp (use server // timestamp for open group messages otherwise the quote messages may not be able // to be found by the timestamp on other devices From 08de65f7745dc0e1ec04572fea68c0a445325fe1 Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Mon, 13 Feb 2023 16:39:59 +1100 Subject: [PATCH 3/4] minor refactor --- .../ConversationVC+Interaction.swift | 9 ++++++- .../Database/Models/SessionThread.swift | 27 ++++++++++++++----- .../Sending & Receiving/MessageSender.swift | 2 -- .../Shared Models/MessageViewModel.swift | 8 ++++-- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index ca2ae2218..dfc94c056 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -436,10 +436,17 @@ extension ConversationVC: .filter(id: threadId) .updateAll(db, SessionThread.Columns.shouldBeVisible.set(to: true)) + let authorId: String = { + if let blindedId = self?.viewModel.threadData.currentUserBlindedPublicKey { + return blindedId + } + return self?.viewModel.threadData.currentUserPublicKey ?? getUserHexEncodedPublicKey(db) + }() + // Create the interaction let interaction: Interaction = try Interaction( threadId: threadId, - authorId: getUserHexEncodedPublicKey(db), + authorId: authorId, variant: .standardOutgoing, body: text, timestampMs: sentTimestampMs, diff --git a/SessionMessagingKit/Database/Models/SessionThread.swift b/SessionMessagingKit/Database/Models/SessionThread.swift index ca08aa182..f5d743acf 100644 --- a/SessionMessagingKit/Database/Models/SessionThread.swift +++ b/SessionMessagingKit/Database/Models/SessionThread.swift @@ -322,18 +322,31 @@ public extension SessionThread { ) -> String? { guard threadVariant == .openGroup, - let blindingInfo: (edkeyPair: Box.KeyPair?, publicKey: String?) = Storage.shared.read({ db in + let blindingInfo: (edkeyPair: Box.KeyPair?, publicKey: String?, capabilities: Set) = Storage.shared.read({ db in + struct OpenGroupInfo: Decodable, FetchableRecord { + let publicKey: String? + let server: String? + } + let openGroupInfo: OpenGroupInfo? = try OpenGroup + .filter(id: threadId) + .select(.publicKey, .server) + .asRequest(of: OpenGroupInfo.self) + .fetchOne(db) + return ( Identity.fetchUserEd25519KeyPair(db), - try OpenGroup - .filter(id: threadId) - .select(.publicKey) - .asRequest(of: String.self) - .fetchOne(db) + openGroupInfo?.publicKey, + (try? Capability + .select(.variant) + .filter(Capability.Columns.openGroupServer == openGroupInfo?.server?.lowercased()) + .asRequest(of: Capability.Variant.self) + .fetchSet(db)) + .defaulting(to: []) ) }), let userEdKeyPair: Box.KeyPair = blindingInfo.edkeyPair, - let publicKey: String = blindingInfo.publicKey + let publicKey: String = blindingInfo.publicKey, + blindingInfo.capabilities.isEmpty || blindingInfo.capabilities.contains(.blind) else { return nil } let sodium: Sodium = Sodium() diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender.swift b/SessionMessagingKit/Sending & Receiving/MessageSender.swift index ee0f23da7..80c0f5ab3 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender.swift @@ -597,8 +597,6 @@ public final class MessageSender { // real message has no use when we delete a message. It is OK to let it be. try interaction.with( serverHash: message.serverHash, - // Update the authorId if blinded id is enabled, otherwise it will remain the same - authorId: message.sender, // Track the open group server message ID and update server timestamp (use server // timestamp for open group messages otherwise the quote messages may not be able // to be found by the timestamp on other devices diff --git a/SessionMessagingKit/Shared Models/MessageViewModel.swift b/SessionMessagingKit/Shared Models/MessageViewModel.swift index a04fd937b..c0a3df33e 100644 --- a/SessionMessagingKit/Shared Models/MessageViewModel.swift +++ b/SessionMessagingKit/Shared Models/MessageViewModel.swift @@ -718,8 +718,12 @@ public extension MessageViewModel { \(interactionAttachment[.attachmentId]) AS \(Quote.Columns.attachmentId) FROM \(Quote.self) LEFT JOIN \(Interaction.self) ON ( - (\(quote[.authorId]) = \(interaction[.authorId]) OR - \(quote[.authorId]) = \(blindedPublicKey ?? "") AND \(userPublicKey) = \(interaction[.authorId]) ) AND + ( + \(quote[.authorId]) = \(interaction[.authorId]) OR ( + \(quote[.authorId]) = \(blindedPublicKey ?? "") AND + \(userPublicKey) = \(interaction[.authorId]) + ) + ) AND \(quote[.timestampMs]) = \(interaction[.timestampMs]) ) LEFT JOIN \(InteractionAttachment.self) ON \(interaction[.id]) = \(interactionAttachment[.interactionId]) From 62b1470b55941c9917a45ed2e3a2ac832a27ad67 Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Mon, 13 Feb 2023 17:20:25 +1100 Subject: [PATCH 4/4] further clean up for message sender --- .../Visible Messages/VisibleMessage.swift | 3 +++ .../Sending & Receiving/MessageSender.swift | 26 ------------------- 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/SessionMessagingKit/Messages/Visible Messages/VisibleMessage.swift b/SessionMessagingKit/Messages/Visible Messages/VisibleMessage.swift index 980d90b70..2780ae0eb 100644 --- a/SessionMessagingKit/Messages/Visible Messages/VisibleMessage.swift +++ b/SessionMessagingKit/Messages/Visible Messages/VisibleMessage.swift @@ -44,6 +44,7 @@ public final class VisibleMessage: Message { // MARK: - Initialization public init( + sender: String? = nil, sentTimestamp: UInt64? = nil, recipient: String? = nil, groupPublicKey: String? = nil, @@ -68,6 +69,7 @@ public final class VisibleMessage: Message { super.init( sentTimestamp: sentTimestamp, recipient: recipient, + sender: sender, groupPublicKey: groupPublicKey ) } @@ -228,6 +230,7 @@ public extension VisibleMessage { let linkPreview: LinkPreview? = try? interaction.linkPreview.fetchOne(db) return VisibleMessage( + sender: interaction.authorId, sentTimestamp: UInt64(interaction.timestampMs), recipient: (try? interaction.recipientStates.fetchOne(db))?.recipientId, groupPublicKey: try? interaction.thread diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender.swift b/SessionMessagingKit/Sending & Receiving/MessageSender.swift index 80c0f5ab3..f98b6b67a 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender.swift @@ -319,7 +319,6 @@ public final class MessageSender { dependencies: SMKDependencies = SMKDependencies() ) -> Promise { let (promise, seal) = Promise.pending() - let threadId: String // Set the timestamp, sender and recipient if message.sentTimestamp == nil { // Visible messages will already have their sent timestamp set @@ -329,7 +328,6 @@ public final class MessageSender { switch destination { case .contact, .closedGroup, .openGroupInbox: preconditionFailure() case .openGroup(let roomToken, let server, let whisperTo, let whisperMods, _): - threadId = OpenGroup.idFor(roomToken: roomToken, server: server) message.recipient = [ server, roomToken, @@ -344,34 +342,12 @@ public final class MessageSender { // which would go into this case, so rather than handling it as an invalid state we just want to // error in a non-retryable way guard - let openGroup: OpenGroup = try? OpenGroup.fetchOne(db, id: threadId), - let userEdKeyPair: Box.KeyPair = Identity.fetchUserEd25519KeyPair(db), case .openGroup(let roomToken, let server, let whisperTo, let whisperMods, let fileIds) = destination else { seal.reject(MessageSenderError.invalidMessage) return promise } - message.sender = { - let capabilities: [Capability.Variant] = (try? Capability - .select(.variant) - .filter(Capability.Columns.openGroupServer == server) - .filter(Capability.Columns.isMissing == false) - .asRequest(of: Capability.Variant.self) - .fetchAll(db)) - .defaulting(to: []) - - // If the server doesn't support blinding then go with an unblinded id - guard capabilities.isEmpty || capabilities.contains(.blind) else { - return SessionId(.unblinded, publicKey: userEdKeyPair.publicKey).hexString - } - guard let blindedKeyPair: Box.KeyPair = dependencies.sodium.blindedKeyPair(serverPublicKey: openGroup.publicKey, edKeyPair: userEdKeyPair, genericHash: dependencies.genericHash) else { - preconditionFailure() - } - - return SessionId(.blinded, publicKey: blindedKeyPair.publicKey).hexString - }() - // Set the failure handler (need it here already for precondition failure handling) func handleFailure(_ db: Database, with error: MessageSenderError) { MessageSender.handleFailedMessageSend(db, message: message, with: error, interactionId: interactionId) @@ -465,7 +441,6 @@ public final class MessageSender { dependencies: SMKDependencies = SMKDependencies() ) -> Promise { let (promise, seal) = Promise.pending() - let userPublicKey: String = getUserHexEncodedPublicKey(db, dependencies: dependencies) guard case .openGroupInbox(let server, let openGroupPublicKey, let recipientBlindedPublicKey) = destination else { preconditionFailure() @@ -476,7 +451,6 @@ public final class MessageSender { message.sentTimestamp = UInt64(SnodeAPI.currentOffsetTimestampMs()) } - message.sender = userPublicKey message.recipient = recipientBlindedPublicKey // Set the failure handler (need it here already for precondition failure handling)