Export tombstones for gv1 updates in gv2 groups
Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
This commit is contained in:
parent
0cf4f3da7f
commit
4f2143500c
3 changed files with 112 additions and 4 deletions
|
@ -33,6 +33,7 @@ import { explodePromise } from '../../util/explodePromise';
|
|||
import {
|
||||
isDirectConversation,
|
||||
isGroup,
|
||||
isGroupV1,
|
||||
isGroupV2,
|
||||
isMe,
|
||||
} from '../../util/whatTypeOfConversation';
|
||||
|
@ -307,6 +308,11 @@ export class BackupExportStream extends Readable {
|
|||
window.storage.get('pinnedConversationIds') || [];
|
||||
|
||||
for (const { attributes } of window.ConversationController.getAll()) {
|
||||
if (isGroupV1(attributes)) {
|
||||
log.warn('backups: skipping gv1 conversation');
|
||||
continue;
|
||||
}
|
||||
|
||||
const recipientId = this.getRecipientId(attributes);
|
||||
|
||||
let pinnedOrder: number | null = null;
|
||||
|
@ -773,6 +779,15 @@ export class BackupExportStream extends Readable {
|
|||
message: MessageAttributesType,
|
||||
{ aboutMe, callHistoryByCallId, backupLevel }: ToChatItemOptionsType
|
||||
): Promise<Backups.IChatItem | undefined> {
|
||||
const conversation = window.ConversationController.get(
|
||||
message.conversationId
|
||||
);
|
||||
|
||||
if (conversation && isGroupV1(conversation.attributes)) {
|
||||
log.warn('backups: skipping gv1 message');
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const chatId = this.getRecipientId({ id: message.conversationId });
|
||||
if (chatId === undefined) {
|
||||
log.warn('backups: message chat not found');
|
||||
|
@ -1324,9 +1339,21 @@ export class BackupExportStream extends Readable {
|
|||
return { kind: NonBubbleResultKind.Drop };
|
||||
}
|
||||
|
||||
// Create a GV2 tombstone for a deprecated GV1 notification
|
||||
if (isGroupUpdate(message)) {
|
||||
// GV1 is deprecated.
|
||||
return { kind: NonBubbleResultKind.Drop };
|
||||
updateMessage.groupChange = {
|
||||
updates: [
|
||||
{
|
||||
genericGroupUpdate: {
|
||||
updaterAci: message.sourceServiceId
|
||||
? this.serviceIdToBytes(message.sourceServiceId)
|
||||
: undefined,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return { kind: NonBubbleResultKind.Directionless, patch };
|
||||
}
|
||||
|
||||
if (isUnsupportedMessage(message)) {
|
||||
|
|
|
@ -8,13 +8,22 @@ import type { ConversationModel } from '../../models/conversations';
|
|||
import { GiftBadgeStates } from '../../components/conversation/Message';
|
||||
|
||||
import Data from '../../sql/Client';
|
||||
import { getRandomBytes } from '../../Crypto';
|
||||
import * as Bytes from '../../Bytes';
|
||||
import { generateAci } from '../../types/ServiceId';
|
||||
import { ReadStatus } from '../../messages/MessageReadStatus';
|
||||
import { SeenStatus } from '../../MessageSeenStatus';
|
||||
import { loadCallsHistory } from '../../services/callHistoryLoader';
|
||||
import { setupBasics, symmetricRoundtripHarness, OUR_ACI } from './helpers';
|
||||
import { ID_V1_LENGTH } from '../../groups';
|
||||
import {
|
||||
setupBasics,
|
||||
asymmetricRoundtripHarness,
|
||||
symmetricRoundtripHarness,
|
||||
OUR_ACI,
|
||||
} from './helpers';
|
||||
|
||||
const CONTACT_A = generateAci();
|
||||
const GV1_ID = Bytes.toBinary(getRandomBytes(ID_V1_LENGTH));
|
||||
|
||||
const BADGE_RECEIPT =
|
||||
'AEpyZxbRBT+T5PQw9Wcx1QE2aFvL7LoLir9V4UF09Kk9qiP4SpIlHdlWHrAICy6F' +
|
||||
|
@ -27,6 +36,7 @@ const BADGE_RECEIPT =
|
|||
|
||||
describe('backup/bubble messages', () => {
|
||||
let contactA: ConversationModel;
|
||||
let gv1: ConversationModel;
|
||||
|
||||
beforeEach(async () => {
|
||||
await Data._removeAllMessages();
|
||||
|
@ -41,6 +51,14 @@ describe('backup/bubble messages', () => {
|
|||
{ systemGivenName: 'CONTACT_A' }
|
||||
);
|
||||
|
||||
gv1 = await window.ConversationController.getOrCreateAndWait(
|
||||
GV1_ID,
|
||||
'group',
|
||||
{
|
||||
groupVersion: 1,
|
||||
}
|
||||
);
|
||||
|
||||
await loadCallsHistory();
|
||||
});
|
||||
|
||||
|
@ -383,4 +401,26 @@ describe('backup/bubble messages', () => {
|
|||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('drops gv1 messages', async () => {
|
||||
await asymmetricRoundtripHarness(
|
||||
[
|
||||
{
|
||||
conversationId: gv1.id,
|
||||
id: generateGuid(),
|
||||
type: 'incoming',
|
||||
received_at: 3,
|
||||
received_at_ms: 3,
|
||||
sent_at: 3,
|
||||
timestamp: 3,
|
||||
sourceServiceId: CONTACT_A,
|
||||
body: 'd',
|
||||
readStatus: ReadStatus.Unread,
|
||||
seenStatus: SeenStatus.Unseen,
|
||||
unidentifiedDeliveryReceived: true,
|
||||
},
|
||||
],
|
||||
[]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,7 +17,12 @@ import { DurationInSeconds } from '../../util/durations';
|
|||
import { ReadStatus } from '../../messages/MessageReadStatus';
|
||||
import { SeenStatus } from '../../MessageSeenStatus';
|
||||
import { loadCallsHistory } from '../../services/callHistoryLoader';
|
||||
import { setupBasics, symmetricRoundtripHarness, OUR_ACI } from './helpers';
|
||||
import {
|
||||
setupBasics,
|
||||
asymmetricRoundtripHarness,
|
||||
symmetricRoundtripHarness,
|
||||
OUR_ACI,
|
||||
} from './helpers';
|
||||
|
||||
const CONTACT_A = generateAci();
|
||||
const GROUP_ID = Bytes.toBase64(getRandomBytes(32));
|
||||
|
@ -501,4 +506,40 @@ describe('backup/non-bubble messages', () => {
|
|||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('creates a tombstone for gv1 update in gv2 group', async () => {
|
||||
await asymmetricRoundtripHarness(
|
||||
[
|
||||
{
|
||||
conversationId: group.id,
|
||||
id: generateGuid(),
|
||||
type: 'incoming',
|
||||
received_at: 1,
|
||||
received_at_ms: 1,
|
||||
sourceServiceId: CONTACT_A,
|
||||
sourceDevice: 1,
|
||||
sent_at: 1,
|
||||
timestamp: 1,
|
||||
readStatus: ReadStatus.Unread,
|
||||
seenStatus: SeenStatus.Unseen,
|
||||
group_update: {},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
conversationId: group.id,
|
||||
id: 'does not matter',
|
||||
type: 'group-v2-change',
|
||||
groupV2Change: {
|
||||
details: [{ type: 'summary' }],
|
||||
from: CONTACT_A,
|
||||
},
|
||||
received_at: 1,
|
||||
sent_at: 1,
|
||||
sourceServiceId: CONTACT_A,
|
||||
timestamp: 1,
|
||||
},
|
||||
]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue