finish explicit group updates

pull/1495/head
Audric Ackermann 4 years ago
parent 3342c7fd26
commit 3b3378a2ee
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -3215,6 +3215,12 @@ async function updateExistingClosedGroupToClosedGroup(instance) {
* @param {*} groupPublicKey string | PubKey
*/
async function getAllEncryptionKeyPairsForGroup(groupPublicKey) {
const rows = await getAllEncryptionKeyPairsForGroupRaw(groupPublicKey);
return map(rows, row => jsonToObject(row.json));
}
async function getAllEncryptionKeyPairsForGroupRaw(groupPublicKey) {
const pubkeyAsString = groupPublicKey.key
? groupPublicKey.key
: groupPublicKey;
@ -3225,7 +3231,7 @@ async function getAllEncryptionKeyPairsForGroup(groupPublicKey) {
}
);
return map(rows, row => jsonToObject(row.json));
return rows;
}
async function getLatestClosedGroupEncryptionKeyPair(groupPublicKey) {

@ -21,6 +21,7 @@ import {
import { ECKeyPair } from './keypairs';
import { UserUtils } from '../session/utils';
import { ConversationModel } from '../models/conversation';
import _ from 'lodash';
export async function handleClosedGroupControlMessage(
envelope: EnvelopePlus,
@ -295,6 +296,7 @@ async function handleUpdateClosedGroup(
convo.set('members', members);
await convo.commit();
convo.updateLastMessage();
await removeFromCache(envelope);
}
@ -315,6 +317,9 @@ async function handleClosedGroupEncryptionKeyPair(
return;
}
const ourNumber = UserUtils.getOurPubKeyFromCache();
window.log.info(
`Got a group update for group ${envelope.source}, type: ENCRYPTION_KEY_PAIR`
);
const groupPublicKey = envelope.source;
const ourKeyPair = await UserUtils.getIdentityKeyPair();
@ -485,12 +490,17 @@ async function handleClosedGroupNameChanged(
) {
// Only add update message if we have something to show
const newName = groupUpdate.name;
window.log.info(
`Got a group update for group ${envelope.source}, type: NAME_CHANGED`
);
if (newName !== convo.get('name')) {
const groupDiff: ClosedGroup.GroupDiff = {
newName,
};
await ClosedGroup.addUpdateMessage(convo, groupDiff, 'incoming');
convo.set({ name: newName });
convo.updateLastMessage();
await convo.commit();
}
@ -508,6 +518,10 @@ async function handleClosedGroupMembersAdded(
const membersNotAlreadyPresent = addedMembers.filter(
m => !oldMembers.includes(m)
);
console.warn('membersNotAlreadyPresent', membersNotAlreadyPresent);
window.log.info(
`Got a group update for group ${envelope.source}, type: MEMBERS_ADDED`
);
if (membersNotAlreadyPresent.length === 0) {
window.log.info(
@ -526,6 +540,7 @@ async function handleClosedGroupMembersAdded(
await ClosedGroup.addUpdateMessage(convo, groupDiff, 'incoming');
convo.set({ members });
convo.updateLastMessage();
await convo.commit();
await removeFromCache(envelope);
}
@ -534,7 +549,77 @@ async function handleClosedGroupMembersRemoved(
envelope: EnvelopePlus,
groupUpdate: SignalService.DataMessage.ClosedGroupControlMessage,
convo: ConversationModel
) { }
) {
// Check that the admin wasn't removed
const currentMembers = convo.get('members');
// removedMembers are all members in the diff
const removedMembers = groupUpdate.members.map(toHex);
// effectivelyRemovedMembers are the members which where effectively on this group before the update
// and is used for the group update message only
const effectivelyRemovedMembers = removedMembers.filter(m =>
currentMembers.includes(m)
);
const groupPubKey = envelope.source;
window.log.info(
`Got a group update for group ${envelope.source}, type: MEMBERS_REMOVED`
);
const membersAfterUpdate = _.difference(currentMembers, removedMembers);
const groupAdmins = convo.get('groupAdmins');
if (!groupAdmins?.length) {
throw new Error('No admins found for closed group member removed update.');
}
const firstAdmin = groupAdmins[0];
if (removedMembers.includes(firstAdmin)) {
window.log.warn(
'Ignoring invalid closed group update: trying to remove the admin.'
);
await removeFromCache(envelope);
return;
}
// If the current user was removed:
// • Stop polling for the group
// • Remove the key pairs associated with the group
const ourPubKey = UserUtils.getOurPubKeyFromCache();
const wasCurrentUserRemoved = !membersAfterUpdate.includes(ourPubKey.key);
if (wasCurrentUserRemoved) {
await window.Signal.Data.removeAllClosedGroupEncryptionKeyPairs(
groupPubKey
);
// Disable typing:
convo.set('isKickedFromGroup', true);
window.SwarmPolling.removePubkey(groupPubKey);
}
// Generate and distribute a new encryption key pair if needed
const isCurrentUserAdmin = firstAdmin === ourPubKey.key;
if (isCurrentUserAdmin) {
try {
await ClosedGroup.generateAndSendNewEncryptionKeyPair(
groupPubKey,
membersAfterUpdate
);
} catch (e) {
window.log.warn('Could not distribute new encryption keypair.');
}
}
// Only add update message if we have something to show
if (membersAfterUpdate.length !== currentMembers.length) {
const groupDiff: ClosedGroup.GroupDiff = {
leavingMembers: effectivelyRemovedMembers,
};
await ClosedGroup.addUpdateMessage(convo, groupDiff, 'incoming');
convo.updateLastMessage();
}
// Update the group
convo.set({ members: membersAfterUpdate });
await convo.commit();
await removeFromCache(envelope);
}
async function handleClosedGroupMemberLeft(
envelope: EnvelopePlus,
@ -578,7 +663,6 @@ async function handleClosedGroupMemberLeft(
convo.set('isKickedFromGroup', true);
window.SwarmPolling.removePubkey(groupPublicKey);
}
// Update the group
// Only add update message if we have something to show
if (leftMemberWasPresent) {
@ -586,6 +670,7 @@ async function handleClosedGroupMemberLeft(
leavingMembers: didAdminLeave ? oldMembers : [sender],
};
await ClosedGroup.addUpdateMessage(convo, groupDiff, 'incoming');
convo.updateLastMessage();
}
convo.set('members', members);
@ -648,7 +733,9 @@ export async function createClosedGroup(
// the sending pipeline needs to know from GroupUtils when a message is for a medium group
await ClosedGroup.updateOrCreateClosedGroup(groupDetails);
convo.set('lastJoinedTimestamp', Date.now());
convo.set('active_at', Date.now());
await convo.commit();
convo.updateLastMessage();
// Send a closed group update message to all members individually
const promises = listOfMembers.map(async m => {

@ -1,6 +1,5 @@
import { EnvelopePlus } from './types';
import { handleDataMessage } from './dataMessage';
import { getEnvelopeId } from './common';
import { removeFromCache, updateCache } from './cache';
import { SignalService } from '../protobuf';
@ -75,6 +74,9 @@ async function decryptForClosedGroup(
encryptionKeyPair,
true
);
if (decryptedContent?.byteLength) {
break;
}
keyIndex++;
} catch (e) {
window.log.info(
@ -83,13 +85,21 @@ async function decryptForClosedGroup(
}
} while (encryptionKeyPairs.length > 0);
if (!decryptedContent) {
if (!decryptedContent?.byteLength) {
await removeFromCache(envelope);
throw new Error(
`Could not decrypt message for closed group with any of the ${encryptionKeyPairsCount} keypairs.`
);
}
window.log.info('ClosedGroup Message decrypted successfully.');
if (keyIndex !== 0) {
window.log.warn(
'Decrypted a closed group message with not the latest encryptionkeypair we have'
);
}
window.log.info(
'ClosedGroup Message decrypted successfully with keyIndex:',
keyIndex
);
const ourDevicePubKey = UserUtils.getOurPubKeyStrFromCache();
if (
@ -483,7 +493,7 @@ async function handleTypingMessage(
const started = action === SignalService.TypingMessage.Action.STARTED;
if (conversation) {
conversation.notifyTyping({
await conversation.notifyTyping({
isTyping: started,
sender: source,
});

@ -114,7 +114,7 @@ export async function encryptUsingSessionProtocol(
window?.log?.info(
'encryptUsingSessionProtocol for ',
recipientHexEncodedX25519PublicKey
recipientHexEncodedX25519PublicKey.key
);
const recipientX25519PublicKey = recipientHexEncodedX25519PublicKey.withoutPrefixToArray();

@ -341,13 +341,13 @@ export async function leaveClosedGroup(groupId: string) {
expireTimer: 0,
});
window.getMessageController().register(dbMessage.id, dbMessage);
const existingExpireTimer = convo.get('expireTimer') || 0;
// Send the update to the group
const ourLeavingMessage = new ClosedGroupMemberLeftMessage({
timestamp: Date.now(),
groupId,
identifier: dbMessage.id,
expireTimer: 0,
expireTimer: existingExpireTimer,
});
window.log.info(

Loading…
Cancel
Save