Implement closed group logic changes

This commit is contained in:
Niels Andriesse 2021-04-16 10:56:10 +10:00
parent b30d6f9add
commit beabf0c9c0
4 changed files with 33 additions and 6 deletions

View File

@ -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<String> {
var result: Set<String> = []
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<String> {
public func getZombieMembers(for groupPublicKey: String) -> Set<String> {
var result: Set<String> = []
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<String> {
result = zombies
}
}
return result
}
public func setZombieMembers(for groupPublicKey: String, to zombies: Set<String>, using transaction: Any) {
(transaction as! YapDatabaseReadWriteTransaction).setObject(zombies, forKey: groupPublicKey, inCollection: Storage.closedGroupZombieMembersCollection)
}
public func isClosedGroup(_ publicKey: String) -> Bool {
getUserClosedGroupPublicKeys().contains(publicKey)

View File

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

View File

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

View File

@ -22,6 +22,8 @@ public protocol SessionMessagingKitStorageProtocol {
// MARK: - Closed Groups
func getUserClosedGroupPublicKeys() -> Set<String>
func getZombieMembers(for groupPublicKey: String) -> Set<String>
func setZombieMembers(for groupPublicKey: String, to zombies: Set<String>, using transaction: Any)
func isClosedGroup(_ publicKey: String) -> Bool
// MARK: - Jobs