Export tombstones for gv1 updates in gv2 groups
This commit is contained in:
parent
d9f514fe96
commit
82941c6c4a
3 changed files with 112 additions and 4 deletions
|
@ -33,6 +33,7 @@ import { explodePromise } from '../../util/explodePromise';
|
||||||
import {
|
import {
|
||||||
isDirectConversation,
|
isDirectConversation,
|
||||||
isGroup,
|
isGroup,
|
||||||
|
isGroupV1,
|
||||||
isGroupV2,
|
isGroupV2,
|
||||||
isMe,
|
isMe,
|
||||||
} from '../../util/whatTypeOfConversation';
|
} from '../../util/whatTypeOfConversation';
|
||||||
|
@ -307,6 +308,11 @@ export class BackupExportStream extends Readable {
|
||||||
window.storage.get('pinnedConversationIds') || [];
|
window.storage.get('pinnedConversationIds') || [];
|
||||||
|
|
||||||
for (const { attributes } of window.ConversationController.getAll()) {
|
for (const { attributes } of window.ConversationController.getAll()) {
|
||||||
|
if (isGroupV1(attributes)) {
|
||||||
|
log.warn('backups: skipping gv1 conversation');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const recipientId = this.getRecipientId(attributes);
|
const recipientId = this.getRecipientId(attributes);
|
||||||
|
|
||||||
let pinnedOrder: number | null = null;
|
let pinnedOrder: number | null = null;
|
||||||
|
@ -773,6 +779,15 @@ export class BackupExportStream extends Readable {
|
||||||
message: MessageAttributesType,
|
message: MessageAttributesType,
|
||||||
{ aboutMe, callHistoryByCallId, backupLevel }: ToChatItemOptionsType
|
{ aboutMe, callHistoryByCallId, backupLevel }: ToChatItemOptionsType
|
||||||
): Promise<Backups.IChatItem | undefined> {
|
): 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 });
|
const chatId = this.getRecipientId({ id: message.conversationId });
|
||||||
if (chatId === undefined) {
|
if (chatId === undefined) {
|
||||||
log.warn('backups: message chat not found');
|
log.warn('backups: message chat not found');
|
||||||
|
@ -1324,9 +1339,21 @@ export class BackupExportStream extends Readable {
|
||||||
return { kind: NonBubbleResultKind.Drop };
|
return { kind: NonBubbleResultKind.Drop };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a GV2 tombstone for a deprecated GV1 notification
|
||||||
if (isGroupUpdate(message)) {
|
if (isGroupUpdate(message)) {
|
||||||
// GV1 is deprecated.
|
updateMessage.groupChange = {
|
||||||
return { kind: NonBubbleResultKind.Drop };
|
updates: [
|
||||||
|
{
|
||||||
|
genericGroupUpdate: {
|
||||||
|
updaterAci: message.sourceServiceId
|
||||||
|
? this.serviceIdToBytes(message.sourceServiceId)
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
return { kind: NonBubbleResultKind.Directionless, patch };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUnsupportedMessage(message)) {
|
if (isUnsupportedMessage(message)) {
|
||||||
|
|
|
@ -8,13 +8,22 @@ import type { ConversationModel } from '../../models/conversations';
|
||||||
import { GiftBadgeStates } from '../../components/conversation/Message';
|
import { GiftBadgeStates } from '../../components/conversation/Message';
|
||||||
|
|
||||||
import Data from '../../sql/Client';
|
import Data from '../../sql/Client';
|
||||||
|
import { getRandomBytes } from '../../Crypto';
|
||||||
|
import * as Bytes from '../../Bytes';
|
||||||
import { generateAci } from '../../types/ServiceId';
|
import { generateAci } from '../../types/ServiceId';
|
||||||
import { ReadStatus } from '../../messages/MessageReadStatus';
|
import { ReadStatus } from '../../messages/MessageReadStatus';
|
||||||
import { SeenStatus } from '../../MessageSeenStatus';
|
import { SeenStatus } from '../../MessageSeenStatus';
|
||||||
import { loadCallsHistory } from '../../services/callHistoryLoader';
|
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 CONTACT_A = generateAci();
|
||||||
|
const GV1_ID = Bytes.toBinary(getRandomBytes(ID_V1_LENGTH));
|
||||||
|
|
||||||
const BADGE_RECEIPT =
|
const BADGE_RECEIPT =
|
||||||
'AEpyZxbRBT+T5PQw9Wcx1QE2aFvL7LoLir9V4UF09Kk9qiP4SpIlHdlWHrAICy6F' +
|
'AEpyZxbRBT+T5PQw9Wcx1QE2aFvL7LoLir9V4UF09Kk9qiP4SpIlHdlWHrAICy6F' +
|
||||||
|
@ -27,6 +36,7 @@ const BADGE_RECEIPT =
|
||||||
|
|
||||||
describe('backup/bubble messages', () => {
|
describe('backup/bubble messages', () => {
|
||||||
let contactA: ConversationModel;
|
let contactA: ConversationModel;
|
||||||
|
let gv1: ConversationModel;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await Data._removeAllMessages();
|
await Data._removeAllMessages();
|
||||||
|
@ -41,6 +51,14 @@ describe('backup/bubble messages', () => {
|
||||||
{ systemGivenName: 'CONTACT_A' }
|
{ systemGivenName: 'CONTACT_A' }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
gv1 = await window.ConversationController.getOrCreateAndWait(
|
||||||
|
GV1_ID,
|
||||||
|
'group',
|
||||||
|
{
|
||||||
|
groupVersion: 1,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
await loadCallsHistory();
|
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 { ReadStatus } from '../../messages/MessageReadStatus';
|
||||||
import { SeenStatus } from '../../MessageSeenStatus';
|
import { SeenStatus } from '../../MessageSeenStatus';
|
||||||
import { loadCallsHistory } from '../../services/callHistoryLoader';
|
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 CONTACT_A = generateAci();
|
||||||
const GROUP_ID = Bytes.toBase64(getRandomBytes(32));
|
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…
Add table
Add a link
Reference in a new issue