Update ClosedGroupUpdate for new message types

This commit is contained in:
Niels Andriesse 2021-01-22 10:02:42 +11:00
parent 0e3348dec7
commit 9ea1ccd0c2
7 changed files with 78 additions and 23 deletions

View File

@ -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 = "<group>"; };
C3471F4B25553AB000297E91 /* MessageReceiver+Decryption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MessageReceiver+Decryption.swift"; sourceTree = "<group>"; };
C3471FA32555439E00297E91 /* Notification+MessageSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Notification+MessageSender.swift"; sourceTree = "<group>"; };
C34A977325A3E34A00852C71 /* ClosedGroupUpdateV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClosedGroupUpdateV2.swift; sourceTree = "<group>"; };
C34A977325A3E34A00852C71 /* ClosedGroupUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClosedGroupUpdate.swift; sourceTree = "<group>"; };
C34C8F7323A7830A00D82669 /* SpaceMono-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SpaceMono-Bold.ttf"; sourceTree = "<group>"; };
C352A2F425574B4700338F3E /* Job.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Job.swift; sourceTree = "<group>"; };
C352A2FE25574B6300338F3E /* MessageSendJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSendJob.swift; sourceTree = "<group>"; };
@ -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 */,

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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 {