From 58be16822725adef5fee78fe361b412050f853b4 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 14 Jan 2021 14:37:09 +1100 Subject: [PATCH] drop groupUpdates which happened before we joined the group --- js/models/conversations.d.ts | 1 + js/models/conversations.js | 1 + js/views/create_group_dialog_view.js | 2 +- ts/components/session/RegistrationTabs.tsx | 2 +- ts/receiver/closedGroupsV2.ts | 34 ++++++++++++++++++++-- ts/receiver/contentMessage.ts | 2 +- ts/test/test-utils/utils/message.ts | 1 + 7 files changed, 38 insertions(+), 5 deletions(-) diff --git a/js/models/conversations.d.ts b/js/models/conversations.d.ts index fa1ecaf8a..eed53b9de 100644 --- a/js/models/conversations.d.ts +++ b/js/models/conversations.d.ts @@ -14,6 +14,7 @@ interface ConversationAttributes { isArchived: boolean; active_at: number; timestamp: number; // timestamp of what? + lastJoinedTimestamp: number; // ClosedGroupV2: last time we were added to this group groupAdmins?: Array; isKickedFromGroup?: boolean; avatarPath?: string; diff --git a/js/models/conversations.js b/js/models/conversations.js index d60dc75c2..03861a967 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -58,6 +58,7 @@ isKickedFromGroup: false, profileSharing: false, left: false, + lastJoinedTimestamp: new Date('1970-01-01Z00:00:00:000').getTime(), }; }, diff --git a/js/views/create_group_dialog_view.js b/js/views/create_group_dialog_view.js index 7d66a3e0a..802576813 100644 --- a/js/views/create_group_dialog_view.js +++ b/js/views/create_group_dialog_view.js @@ -189,7 +189,7 @@ const xor = _.xor(notPresentInNew, notPresentInOld); if (xor.length === 0) { - window.log.log( + window.log.info( 'skipping group update: no detected changes in group member list' ); diff --git a/ts/components/session/RegistrationTabs.tsx b/ts/components/session/RegistrationTabs.tsx index bd229e86a..970a1678b 100644 --- a/ts/components/session/RegistrationTabs.tsx +++ b/ts/components/session/RegistrationTabs.tsx @@ -961,7 +961,7 @@ export class RegistrationTabs extends React.Component { const secretWords = window.mnemonic.pubkey_to_secret_words(pubkey); this.setState({ secretWords }); } catch (e) { - window.log.log(e); + window.log.info(e); await this.resetRegistration(); this.setState({ diff --git a/ts/receiver/closedGroupsV2.ts b/ts/receiver/closedGroupsV2.ts index 4aef11dd6..d6846f573 100644 --- a/ts/receiver/closedGroupsV2.ts +++ b/ts/receiver/closedGroupsV2.ts @@ -181,6 +181,15 @@ async function handleNewClosedGroupV2( const groupId = toHex(publicKey); const members = membersAsData.map(toHex); const admins = adminsAsData.map(toHex); + + const ourPrimary = await UserUtil.getPrimary(); + if (!members.includes(ourPrimary.key)) { + log.info( + 'Got a new group message but apparently we are not a member of it. Dropping it.' + ); + await removeFromCache(envelope); + return; + } // FIXME maybe we should handle an expiretimer here too? And on ClosedGroupV2 updates? const maybeConvo = ConversationController.getInstance().get(groupId); @@ -198,6 +207,7 @@ async function handleNewClosedGroupV2( // Enable typing: maybeConvo.set('isKickedFromGroup', false); maybeConvo.set('left', false); + maybeConvo.set('lastJoinedTimestamp', Date.now()); } else { log.warn( 'Ignoring a closed group v2 message of type NEW: the conversation already exists' @@ -222,14 +232,13 @@ async function handleNewClosedGroupV2( 'incoming' ); - // TODO: Check that we are even a part of this group - convo.set('name', name); convo.set('members', members); // mark a closed group v2 as a medium group. // this field is used to poll for this groupPubKey on the swarm nodes, among other things convo.set('is_medium_group', true); convo.set('active_at', Date.now()); + convo.set('lastJoinedTimestamp', Date.now()); // We only set group admins on group creation convo.set('groupAdmins', admins); @@ -272,6 +281,25 @@ async function handleUpdateClosedGroupV2( await removeFromCache(envelope); return; } + + // Check that the message isn't from before the group was created + let lastJoinedTimestamp = convo.get('lastJoinedTimestamp'); + // might happen for existing groups + if (!lastJoinedTimestamp) { + const aYearAgo = Date.now() - 1000 * 60 * 24 * 365; + convo.set({ + lastJoinedTimestamp: aYearAgo, + }); + lastJoinedTimestamp = aYearAgo; + } + + if (envelope.timestamp <= lastJoinedTimestamp) { + window.log.warn( + 'Got a group update with an older timestamp than when we joined this group last time. Dropping it' + ); + await removeFromCache(envelope); + return; + } const curAdmins = convo.get('groupAdmins'); // Check that the sender is a member of the group (before the update) @@ -520,6 +548,8 @@ export async function createClosedGroupV2( // be sure to call this before sending the message. // the sending pipeline needs to know from GroupUtils when a message is for a medium group await ClosedGroupV2.updateOrCreateClosedGroupV2(groupDetails); + convo.set('lastJoinedTimestamp', Date.now()); + // Send a closed group update message to all members individually const promises = listOfMembers.map(async m => { const messageParams: ClosedGroupV2NewMessageParams = { diff --git a/ts/receiver/contentMessage.ts b/ts/receiver/contentMessage.ts index 61b850a67..9ce49a3e9 100644 --- a/ts/receiver/contentMessage.ts +++ b/ts/receiver/contentMessage.ts @@ -27,7 +27,7 @@ export async function handleContentMessage(envelope: EnvelopePlus) { const plaintext = await decrypt(envelope, envelope.content); if (!plaintext) { - window.log.warn('handleContentMessage: plaintext was falsey'); + // window.log.warn('handleContentMessage: plaintext was falsey'); return; } else if (plaintext instanceof ArrayBuffer && plaintext.byteLength === 0) { return; diff --git a/ts/test/test-utils/utils/message.ts b/ts/test/test-utils/utils/message.ts index 5ba447207..2e09c7854 100644 --- a/ts/test/test-utils/utils/message.ts +++ b/ts/test/test-utils/utils/message.ts @@ -91,6 +91,7 @@ export class MockConversation { isArchived: false, active_at: Date.now(), timestamp: Date.now(), + lastJoinedTimestamp: Date.now(), secondaryStatus: !this.isPrimary, }; }