diff --git a/SessionMessagingKit/Database/Storage+ClosedGroups.swift b/SessionMessagingKit/Database/Storage+ClosedGroups.swift index 0e9264cdf..f09cdaa87 100644 --- a/SessionMessagingKit/Database/Storage+ClosedGroups.swift +++ b/SessionMessagingKit/Database/Storage+ClosedGroups.swift @@ -8,6 +8,8 @@ extension Storage { private static let closedGroupPublicKeyCollection = "SNClosedGroupPublicKeyCollection" private static let closedGroupFormationTimestampCollection = "SNClosedGroupFormationTimestampCollection" + + private static let closedGroupZombieMembersCollection = "SNClosedGroupZombieMembersCollection" public func getClosedGroupEncryptionKeyPairs(for groupPublicKey: String) -> [ECKeyPair] { let collection = Storage.getClosedGroupEncryptionKeyPairCollection(for: groupPublicKey) @@ -35,6 +37,14 @@ extension Storage { let collection = Storage.getClosedGroupEncryptionKeyPairCollection(for: groupPublicKey) (transaction as! YapDatabaseReadWriteTransaction).removeAllObjects(inCollection: collection) } + + public func getUserClosedGroupPublicKeys() -> Set { + var result: Set = [] + Storage.read { transaction in + result = Set(transaction.allKeys(inCollection: Storage.closedGroupPublicKeyCollection)) + } + return result + } public func addClosedGroupPublicKey(_ groupPublicKey: String, using transaction: Any) { (transaction as! YapDatabaseReadWriteTransaction).setObject(groupPublicKey, forKey: groupPublicKey, inCollection: Storage.closedGroupPublicKeyCollection) @@ -55,14 +65,20 @@ extension Storage { public func setClosedGroupFormationTimestamp(to timestamp: UInt64, for groupPublicKey: String, using transaction: Any) { (transaction as! YapDatabaseReadWriteTransaction).setObject(timestamp, forKey: groupPublicKey, inCollection: Storage.closedGroupFormationTimestampCollection) } - - public func getUserClosedGroupPublicKeys() -> Set { + + public func getZombieMembers(for groupPublicKey: String) -> Set { var result: Set = [] Storage.read { transaction in - result = result.union(Set(transaction.allKeys(inCollection: Storage.closedGroupPublicKeyCollection))) + if let zombies = transaction.object(forKey: groupPublicKey, inCollection: Storage.closedGroupZombieMembersCollection) as? Set { + result = zombies + } } return result } + + public func setZombieMembers(for groupPublicKey: String, to zombies: Set, using transaction: Any) { + (transaction as! YapDatabaseReadWriteTransaction).setObject(zombies, forKey: groupPublicKey, inCollection: Storage.closedGroupZombieMembersCollection) + } public func isClosedGroup(_ publicKey: String) -> Bool { getUserClosedGroupPublicKeys().contains(publicKey) diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift index a85e4b45c..7a73809b2 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift @@ -512,7 +512,8 @@ extension MessageReceiver { guard let groupPublicKey = message.groupPublicKey else { return } performIfValid(for: message, using: transaction) { groupID, thread, group in // Check that the admin wasn't removed - let members = Set(group.groupMemberIds).subtracting(membersAsData.map { $0.toHexString() }) + let removedMembers = membersAsData.map { $0.toHexString() } + let members = Set(group.groupMemberIds).subtracting(removedMembers) guard members.contains(group.groupAdminIds.first!) else { return SNLog("Ignoring invalid closed group update.") } @@ -531,7 +532,9 @@ extension MessageReceiver { Storage.shared.removeAllClosedGroupEncryptionKeyPairs(for: groupPublicKey, using: transaction) let _ = PushNotificationAPI.performOperation(.unsubscribe, for: groupPublicKey, publicKey: userPublicKey) } - // TODO: Remove from zombie list + let storage = SNMessagingKitConfiguration.shared.storage + let zombies = storage.getZombieMembers(for: groupPublicKey).subtracting(removedMembers) + storage.setZombieMembers(for: groupPublicKey, to: zombies, using: transaction) // Update the group let newGroupModel = TSGroupModel(title: group.groupName, memberIds: [String](members), image: nil, groupId: groupID, groupType: .closedGroup, adminIds: group.groupAdminIds) thread.setGroupModel(newGroupModel, with: transaction) @@ -561,7 +564,9 @@ extension MessageReceiver { Storage.shared.removeClosedGroupPublicKey(groupPublicKey, using: transaction) let _ = PushNotificationAPI.performOperation(.unsubscribe, for: groupPublicKey, publicKey: getUserHexEncodedPublicKey()) } else { - // TODO: Mark as zombie + let storage = SNMessagingKitConfiguration.shared.storage + let zombies = storage.getZombieMembers(for: groupPublicKey).union([ message.sender! ]) + storage.setZombieMembers(for: groupPublicKey, to: zombies, using: transaction) } // Update the group let newGroupModel = TSGroupModel(title: group.groupName, memberIds: [String](members), image: nil, groupId: groupID, groupType: .closedGroup, adminIds: group.groupAdminIds) diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender+ClosedGroups.swift b/SessionMessagingKit/Sending & Receiving/MessageSender+ClosedGroups.swift index 622e2e22b..b9700ceb5 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender+ClosedGroups.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender+ClosedGroups.swift @@ -216,6 +216,10 @@ extension MessageSender { return Promise(error: Error.invalidClosedGroupUpdate) } let members = Set(group.groupMemberIds).subtracting(membersToRemove) + // Update zombie list + let storage = SNMessagingKitConfiguration.shared.storage + let zombies = storage.getZombieMembers(for: groupPublicKey).subtracting(membersToRemove) + storage.setZombieMembers(for: groupPublicKey, to: zombies, using: transaction) // Send the update to the group and generate + distribute a new encryption key pair let closedGroupControlMessage = ClosedGroupControlMessage(kind: .membersRemoved(members: membersToRemove.map { Data(hex: $0) })) let promise = MessageSender.sendNonDurably(closedGroupControlMessage, in: thread, using: transaction).map { diff --git a/SessionMessagingKit/Storage.swift b/SessionMessagingKit/Storage.swift index 6440d37ee..16510804b 100644 --- a/SessionMessagingKit/Storage.swift +++ b/SessionMessagingKit/Storage.swift @@ -22,6 +22,8 @@ public protocol SessionMessagingKitStorageProtocol { // MARK: - Closed Groups func getUserClosedGroupPublicKeys() -> Set + func getZombieMembers(for groupPublicKey: String) -> Set + func setZombieMembers(for groupPublicKey: String, to zombies: Set, using transaction: Any) func isClosedGroup(_ publicKey: String) -> Bool // MARK: - Jobs