From 9ea1ccd0c290649ecd0dd99a32ff83caf5211b2a Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Fri, 22 Jan 2021 10:02:42 +1100 Subject: [PATCH] Update ClosedGroupUpdate for new message types --- Session.xcodeproj/project.pbxproj | 8 +-- ...UpdateV2.swift => ClosedGroupUpdate.swift} | 61 ++++++++++++++++++- .../MessageReceiver+Handling.swift | 10 +-- .../Sending & Receiving/MessageReceiver.swift | 2 +- .../MessageSender+ClosedGroups.swift | 16 ++--- .../Sending & Receiving/MessageSender.swift | 2 +- .../NotificationServiceExtension.swift | 2 +- 7 files changed, 78 insertions(+), 23 deletions(-) rename SessionMessagingKit/Messages/Control Messages/{ClosedGroupUpdateV2.swift => ClosedGroupUpdate.swift} (77%) diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index 71e9e6ef3..0452c7013 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -519,7 +519,7 @@ C3471ED42555386B00297E91 /* AESGCM.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D72553860B00C340D1 /* AESGCM.swift */; }; C3471F4C25553AB000297E91 /* MessageReceiver+Decryption.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3471F4B25553AB000297E91 /* MessageReceiver+Decryption.swift */; }; C3471FA42555439E00297E91 /* Notification+MessageSender.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3471FA32555439E00297E91 /* Notification+MessageSender.swift */; }; - C34A977425A3E34A00852C71 /* ClosedGroupUpdateV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = C34A977325A3E34A00852C71 /* ClosedGroupUpdateV2.swift */; }; + C34A977425A3E34A00852C71 /* ClosedGroupUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C34A977325A3E34A00852C71 /* ClosedGroupUpdate.swift */; }; C34C8F7423A7830B00D82669 /* SpaceMono-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C34C8F7323A7830A00D82669 /* SpaceMono-Bold.ttf */; }; C352A2F525574B4700338F3E /* Job.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A2F425574B4700338F3E /* Job.swift */; }; C352A2FF25574B6300338F3E /* MessageSendJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = C352A2FE25574B6300338F3E /* MessageSendJob.swift */; }; @@ -1518,7 +1518,7 @@ C3471ECA2555356A00297E91 /* MessageSender+Encryption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MessageSender+Encryption.swift"; sourceTree = ""; }; C3471F4B25553AB000297E91 /* MessageReceiver+Decryption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MessageReceiver+Decryption.swift"; sourceTree = ""; }; C3471FA32555439E00297E91 /* Notification+MessageSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Notification+MessageSender.swift"; sourceTree = ""; }; - C34A977325A3E34A00852C71 /* ClosedGroupUpdateV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClosedGroupUpdateV2.swift; sourceTree = ""; }; + C34A977325A3E34A00852C71 /* ClosedGroupUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClosedGroupUpdate.swift; sourceTree = ""; }; C34C8F7323A7830A00D82669 /* SpaceMono-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SpaceMono-Bold.ttf"; sourceTree = ""; }; C352A2F425574B4700338F3E /* Job.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Job.swift; sourceTree = ""; }; C352A2FE25574B6300338F3E /* MessageSendJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSendJob.swift; sourceTree = ""; }; @@ -2354,7 +2354,7 @@ C3C2A7702553A41E00C340D1 /* ControlMessage.swift */, C300A5BC2554B00D00555489 /* ReadReceipt.swift */, C300A5D22554B05A00555489 /* TypingIndicator.swift */, - C34A977325A3E34A00852C71 /* ClosedGroupUpdateV2.swift */, + C34A977325A3E34A00852C71 /* ClosedGroupUpdate.swift */, C300A5E62554B07300555489 /* ExpirationTimerUpdate.swift */, ); path = "Control Messages"; @@ -4912,7 +4912,7 @@ C3471FA42555439E00297E91 /* Notification+MessageSender.swift in Sources */, C32C5BEF256DC8EE003C73A2 /* OWSDisappearingMessagesJob.m in Sources */, C3A7222A2558C1E40043A11F /* DotNetAPI.swift in Sources */, - C34A977425A3E34A00852C71 /* ClosedGroupUpdateV2.swift in Sources */, + C34A977425A3E34A00852C71 /* ClosedGroupUpdate.swift in Sources */, C32C5E97256DE0CB003C73A2 /* OWSPrimaryStorage.m in Sources */, C32C5EB9256DE130003C73A2 /* OWSQuotedReplyModel+Conversion.swift in Sources */, C3A71D1F25589AC30043A11F /* WebSocketResources.pb.swift in Sources */, diff --git a/SessionMessagingKit/Messages/Control Messages/ClosedGroupUpdateV2.swift b/SessionMessagingKit/Messages/Control Messages/ClosedGroupUpdate.swift similarity index 77% rename from SessionMessagingKit/Messages/Control Messages/ClosedGroupUpdateV2.swift rename to SessionMessagingKit/Messages/Control Messages/ClosedGroupUpdate.swift index 5bae7d9eb..e1da08ba5 100644 --- a/SessionMessagingKit/Messages/Control Messages/ClosedGroupUpdateV2.swift +++ b/SessionMessagingKit/Messages/Control Messages/ClosedGroupUpdate.swift @@ -1,7 +1,7 @@ import SessionProtocolKit import SessionUtilitiesKit -public final class ClosedGroupUpdateV2 : ControlMessage { +public final class ClosedGroupUpdate : ControlMessage { public var kind: Kind? public override var ttl: UInt64 { @@ -14,14 +14,23 @@ public final class ClosedGroupUpdateV2 : ControlMessage { // MARK: Kind public enum Kind : CustomStringConvertible { case new(publicKey: Data, name: String, encryptionKeyPair: ECKeyPair, members: [Data], admins: [Data]) + /// - Note: Deprecated in favor of more explicit group updates. case update(name: String, members: [Data]) case encryptionKeyPair([KeyPairWrapper]) // The new encryption key pair encrypted for each member individually + case nameChange(name: String) + case usersAdded(members: [Data]) + case usersRemoved(members: [Data]) + case userLeft public var description: String { switch self { case .new: return "new" case .update: return "update" case .encryptionKeyPair: return "encryptionKeyPair" + case .nameChange: return "nameChange" + case .usersAdded: return "usersAdded" + case .usersRemoved: return "usersRemoved" + case .userLeft: return "userLeft" } } } @@ -83,6 +92,10 @@ public final class ClosedGroupUpdateV2 : ControlMessage { case .update(let name, _): return !name.isEmpty case .encryptionKeyPair: return true + case .nameChange(let name): return !name.isEmpty + case .usersAdded(let members): return !members.isEmpty + case .usersRemoved(let members): return !members.isEmpty + case .userLeft: return true } } @@ -105,6 +118,17 @@ public final class ClosedGroupUpdateV2 : ControlMessage { case "encryptionKeyPair": guard let wrappers = coder.decodeObject(forKey: "wrappers") as? [KeyPairWrapper] else { return nil } self.kind = .encryptionKeyPair(wrappers) + case "nameChange": + guard let name = coder.decodeObject(forKey: "name") as? String else { return nil } + self.kind = .nameChange(name: name) + case "usersAdded": + guard let members = coder.decodeObject(forKey: "members") as? [Data] else { return nil } + self.kind = .usersAdded(members: members) + case "usersRemoved": + guard let members = coder.decodeObject(forKey: "members") as? [Data] else { return nil } + self.kind = .usersRemoved(members: members) + case "userLeft": + self.kind = .userLeft default: return nil } } @@ -127,11 +151,22 @@ public final class ClosedGroupUpdateV2 : ControlMessage { case .encryptionKeyPair(let wrappers): coder.encode("encryptionKeyPair", forKey: "kind") coder.encode(wrappers, forKey: "wrappers") + case .nameChange(let name): + coder.encode("nameChange", forKey: "kind") + coder.encode(name, forKey: "name") + case .usersAdded(let members): + coder.encode("usersAdded", forKey: "kind") + coder.encode(members, forKey: "members") + case .usersRemoved(let members): + coder.encode("usersRemoved", forKey: "kind") + coder.encode(members, forKey: "members") + case .userLeft: + coder.encode("userLeft", forKey: "kind") } } // MARK: Proto Conversion - public override class func fromProto(_ proto: SNProtoContent) -> ClosedGroupUpdateV2? { + public override class func fromProto(_ proto: SNProtoContent) -> ClosedGroupUpdate? { guard let closedGroupUpdateProto = proto.dataMessage?.closedGroupUpdateV2 else { return nil } let kind: Kind switch closedGroupUpdateProto.type { @@ -152,8 +187,17 @@ public final class ClosedGroupUpdateV2 : ControlMessage { case .encryptionKeyPair: let wrappers = closedGroupUpdateProto.wrappers.compactMap { KeyPairWrapper.fromProto($0) } kind = .encryptionKeyPair(wrappers) + case .nameChange: + guard let name = closedGroupUpdateProto.name else { return nil } + kind = .nameChange(name: name) + case .usersAdded: + kind = .usersAdded(members: closedGroupUpdateProto.members) + case .usersRemoved: + kind = .usersRemoved(members: closedGroupUpdateProto.members) + case .userLeft: + kind = .userLeft } - return ClosedGroupUpdateV2(kind: kind) + return ClosedGroupUpdate(kind: kind) } public override func toProto(using transaction: YapDatabaseReadWriteTransaction) -> SNProtoContent? { @@ -184,6 +228,17 @@ public final class ClosedGroupUpdateV2 : ControlMessage { case .encryptionKeyPair(let wrappers): closedGroupUpdate = SNProtoDataMessageClosedGroupUpdateV2.builder(type: .encryptionKeyPair) closedGroupUpdate.setWrappers(wrappers.compactMap { $0.toProto() }) + case .nameChange(let name): + closedGroupUpdate = SNProtoDataMessageClosedGroupUpdateV2.builder(type: .nameChange) + closedGroupUpdate.setName(name) + case .usersAdded(let members): + closedGroupUpdate = SNProtoDataMessageClosedGroupUpdateV2.builder(type: .usersAdded) + closedGroupUpdate.setMembers(members) + case .usersRemoved(let members): + closedGroupUpdate = SNProtoDataMessageClosedGroupUpdateV2.builder(type: .usersRemoved) + closedGroupUpdate.setMembers(members) + case .userLeft: + closedGroupUpdate = SNProtoDataMessageClosedGroupUpdateV2.builder(type: .userLeft) } let contentProto = SNProtoContent.builder() let dataMessageProto = SNProtoDataMessage.builder() diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift index 4c98ad91e..049de8995 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift @@ -11,7 +11,7 @@ extension MessageReceiver { switch message { case let message as ReadReceipt: handleReadReceipt(message, using: transaction) case let message as TypingIndicator: handleTypingIndicator(message, using: transaction) - case let message as ClosedGroupUpdateV2: handleClosedGroupUpdateV2(message, using: transaction) + case let message as ClosedGroupUpdate: handleClosedGroupUpdateV2(message, using: transaction) case let message as ExpirationTimerUpdate: handleExpirationTimerUpdate(message, using: transaction) case let message as VisibleMessage: try handleVisibleMessage(message, associatedWithProto: proto, openGroupID: openGroupID, isBackgroundPoll: isBackgroundPoll, using: transaction) default: fatalError() @@ -226,7 +226,7 @@ extension MessageReceiver { return tsIncomingMessageID } - private static func handleClosedGroupUpdateV2(_ message: ClosedGroupUpdateV2, using transaction: Any) { + private static func handleClosedGroupUpdateV2(_ message: ClosedGroupUpdate, using transaction: Any) { switch message.kind! { case .new: handleNewGroupV2(message, using: transaction) case .update: handleGroupUpdateV2(message, using: transaction) @@ -234,7 +234,7 @@ extension MessageReceiver { } } - private static func handleNewGroupV2(_ message: ClosedGroupUpdateV2, using transaction: Any) { + private static func handleNewGroupV2(_ message: ClosedGroupUpdate, using transaction: Any) { // Prepare guard case let .new(publicKeyAsData, name, encryptionKeyPair, membersAsData, adminsAsData) = message.kind else { return } let transaction = transaction as! YapDatabaseReadWriteTransaction @@ -264,7 +264,7 @@ extension MessageReceiver { infoMessage.save(with: transaction) } - private static func handleGroupUpdateV2(_ message: ClosedGroupUpdateV2, using transaction: Any) { + private static func handleGroupUpdateV2(_ message: ClosedGroupUpdate, using transaction: Any) { // Prepare guard case let .update(name, membersAsData) = message.kind else { return } let transaction = transaction as! YapDatabaseReadWriteTransaction @@ -323,7 +323,7 @@ extension MessageReceiver { } } - private static func handleGroupEncryptionKeyPair(_ message: ClosedGroupUpdateV2, using transaction: Any) { + private static func handleGroupEncryptionKeyPair(_ message: ClosedGroupUpdate, using transaction: Any) { // Prepare guard case let .encryptionKeyPair(wrappers) = message.kind, let groupPublicKey = message.groupPublicKey else { return } let transaction = transaction as! YapDatabaseReadWriteTransaction diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift index af6b04af6..4cd74ae39 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver.swift @@ -109,7 +109,7 @@ public enum MessageReceiver { let message: Message? = { if let readReceipt = ReadReceipt.fromProto(proto) { return readReceipt } if let typingIndicator = TypingIndicator.fromProto(proto) { return typingIndicator } - if let closedGroupUpdate = ClosedGroupUpdateV2.fromProto(proto) { return closedGroupUpdate } + if let closedGroupUpdate = ClosedGroupUpdate.fromProto(proto) { return closedGroupUpdate } if let expirationTimerUpdate = ExpirationTimerUpdate.fromProto(proto) { return expirationTimerUpdate } if let visibleMessage = VisibleMessage.fromProto(proto) { return visibleMessage } return nil diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender+ClosedGroups.swift b/SessionMessagingKit/Sending & Receiving/MessageSender+ClosedGroups.swift index 4c16a12c4..bd869c092 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender+ClosedGroups.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender+ClosedGroups.swift @@ -27,9 +27,9 @@ extension MessageSender { guard member != userPublicKey else { continue } let thread = TSContactThread.getOrCreateThread(withContactId: member, transaction: transaction) thread.save(with: transaction) - let closedGroupUpdateKind = ClosedGroupUpdateV2.Kind.new(publicKey: Data(hex: groupPublicKey), name: name, + let closedGroupUpdateKind = ClosedGroupUpdate.Kind.new(publicKey: Data(hex: groupPublicKey), name: name, encryptionKeyPair: encryptionKeyPair, members: membersAsData, admins: adminsAsData) - let closedGroupUpdate = ClosedGroupUpdateV2(kind: closedGroupUpdateKind) + let closedGroupUpdate = ClosedGroupUpdate(kind: closedGroupUpdateKind) let promise = MessageSender.sendNonDurably(closedGroupUpdate, in: thread, using: transaction) promises.append(promise) } @@ -81,7 +81,7 @@ extension MessageSender { } } // Send the update to the group - let mainClosedGroupUpdate = ClosedGroupUpdateV2(kind: .update(name: name, members: membersAsData)) + let mainClosedGroupUpdate = ClosedGroupUpdate(kind: .update(name: name, members: membersAsData)) if isUserLeaving { let _ = MessageSender.sendNonDurably(mainClosedGroupUpdate, in: thread, using: transaction).done { SNMessagingKitConfiguration.shared.storage.write { transaction in @@ -101,9 +101,9 @@ extension MessageSender { for member in newMembers { let thread = TSContactThread.getOrCreateThread(withContactId: member, transaction: transaction) thread.save(with: transaction) - let closedGroupUpdateKind = ClosedGroupUpdateV2.Kind.new(publicKey: Data(hex: groupPublicKey), name: name, + let closedGroupUpdateKind = ClosedGroupUpdate.Kind.new(publicKey: Data(hex: groupPublicKey), name: name, encryptionKeyPair: encryptionKeyPair, members: membersAsData, admins: adminsAsData) - let closedGroupUpdate = ClosedGroupUpdateV2(kind: closedGroupUpdateKind) + let closedGroupUpdate = ClosedGroupUpdate(kind: closedGroupUpdateKind) MessageSender.send(closedGroupUpdate, in: thread, using: transaction) } } @@ -155,11 +155,11 @@ extension MessageSender { let proto = try SNProtoDataMessageClosedGroupUpdateV2KeyPair.builder(publicKey: newKeyPair.publicKey, privateKey: newKeyPair.privateKey).build() let plaintext = try proto.serializedData() - let wrappers = try targetMembers.compactMap { publicKey -> ClosedGroupUpdateV2.KeyPairWrapper in + let wrappers = try targetMembers.compactMap { publicKey -> ClosedGroupUpdate.KeyPairWrapper in let ciphertext = try MessageSender.encryptWithSessionProtocol(plaintext, for: publicKey) - return ClosedGroupUpdateV2.KeyPairWrapper(publicKey: publicKey, encryptedKeyPair: ciphertext) + return ClosedGroupUpdate.KeyPairWrapper(publicKey: publicKey, encryptedKeyPair: ciphertext) } - let closedGroupUpdate = ClosedGroupUpdateV2(kind: .encryptionKeyPair(wrappers)) + let closedGroupUpdate = ClosedGroupUpdate(kind: .encryptionKeyPair(wrappers)) let _ = MessageSender.sendNonDurably(closedGroupUpdate, in: thread, using: transaction).done { // FIXME: It'd be great if we could make this a durable operation // Store it * after * having sent out the message to the group SNMessagingKitConfiguration.shared.storage.write { transaction in diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender.swift b/SessionMessagingKit/Sending & Receiving/MessageSender.swift index aec4a3ca4..2934ba11d 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender.swift @@ -242,7 +242,7 @@ public final class MessageSender : NSObject { storage.write(with: { transaction in MessageSender.handleSuccessfulMessageSend(message, to: destination, using: transaction) var shouldNotify = (message is VisibleMessage) - if let closedGroupUpdate = message as? ClosedGroupUpdateV2, case .new = closedGroupUpdate.kind { + if let closedGroupUpdate = message as? ClosedGroupUpdate, case .new = closedGroupUpdate.kind { shouldNotify = true } if shouldNotify { diff --git a/SessionNotificationServiceExtension/NotificationServiceExtension.swift b/SessionNotificationServiceExtension/NotificationServiceExtension.swift index 1c3d96de5..7676b511e 100644 --- a/SessionNotificationServiceExtension/NotificationServiceExtension.swift +++ b/SessionNotificationServiceExtension/NotificationServiceExtension.swift @@ -53,7 +53,7 @@ public final class NotificationServiceExtension : UNNotificationServiceExtension group.groupModel.groupType == .closedGroup { // Should always be true because we don't get PNs for open groups senderDisplayName = String(format: NotificationStrings.incomingGroupMessageTitleFormat, senderDisplayName, group.groupModel.groupName ?? MessageStrings.newGroupDefaultTitle) } - case let closedGroupUpdate as ClosedGroupUpdateV2: + case let closedGroupUpdate as ClosedGroupUpdate: // TODO: We could consider actually handling the update here. Not sure if there's enough time though, seeing as though // in some cases we need to send messages (e.g. our sender key) to a number of other users. switch closedGroupUpdate.kind {