Send and receive PniSignatureMessage

This commit is contained in:
Fedor Indutny 2022-08-15 14:53:33 -07:00 committed by GitHub
parent 95be24e8f7
commit 00cfd92dd0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
43 changed files with 1082 additions and 164 deletions

View file

@ -53,6 +53,7 @@ import type {
ConversationType,
ConversationMetricsType,
DeleteSentProtoRecipientOptionsType,
DeleteSentProtoRecipientResultType,
EmojiType,
GetUnreadByConversationAndMarkReadResultType,
GetConversationRangeCenteredOnMessageResultType,
@ -952,8 +953,8 @@ async function deleteSentProtoRecipient(
options:
| DeleteSentProtoRecipientOptionsType
| ReadonlyArray<DeleteSentProtoRecipientOptionsType>
): Promise<void> {
await channels.deleteSentProtoRecipient(options);
): Promise<DeleteSentProtoRecipientResultType> {
return channels.deleteSentProtoRecipient(options);
}
async function getSentProtoByRecipient(options: {

View file

@ -119,6 +119,7 @@ export type SentProtoType = {
proto: Uint8Array;
timestamp: number;
urgent: boolean;
hasPniSignatureMessage: boolean;
};
export type SentProtoWithMessageIdsType = SentProtoType & {
messageIds: Array<string>;
@ -287,6 +288,10 @@ export type DeleteSentProtoRecipientOptionsType = Readonly<{
deviceId: number;
}>;
export type DeleteSentProtoRecipientResultType = Readonly<{
successfulPhoneNumberShares: ReadonlyArray<string>;
}>;
export type StoryDistributionType = Readonly<{
id: UUIDStringType;
name: string;
@ -381,7 +386,7 @@ export type DataInterface = {
options:
| DeleteSentProtoRecipientOptionsType
| ReadonlyArray<DeleteSentProtoRecipientOptionsType>
) => Promise<void>;
) => Promise<DeleteSentProtoRecipientResultType>;
getSentProtoByRecipient: (options: {
now: number;
recipientUuid: string;

View file

@ -76,6 +76,7 @@ import type {
ConversationMetricsType,
ConversationType,
DeleteSentProtoRecipientOptionsType,
DeleteSentProtoRecipientResultType,
EmojiType,
GetConversationRangeCenteredOnMessageResultType,
GetUnreadByConversationAndMarkReadResultType,
@ -855,17 +856,20 @@ async function insertSentProto(
contentHint,
proto,
timestamp,
urgent
urgent,
hasPniSignatureMessage
) VALUES (
$contentHint,
$proto,
$timestamp,
$urgent
$urgent,
$hasPniSignatureMessage
);
`
).run({
...proto,
urgent: proto.urgent ? 1 : 0,
hasPniSignatureMessage: proto.hasPniSignatureMessage ? 1 : 0,
});
const id = parseIntOrThrow(
info.lastInsertRowid,
@ -999,7 +1003,7 @@ async function deleteSentProtoRecipient(
options:
| DeleteSentProtoRecipientOptionsType
| ReadonlyArray<DeleteSentProtoRecipientOptionsType>
): Promise<void> {
): Promise<DeleteSentProtoRecipientResultType> {
const db = getInstance();
const items = Array.isArray(options) ? options : [options];
@ -1007,7 +1011,9 @@ async function deleteSentProtoRecipient(
// Note: we use `pluck` in this function to fetch only the first column of
// returned row.
db.transaction(() => {
return db.transaction(() => {
const successfulPhoneNumberShares = new Array<string>();
for (const item of items) {
const { timestamp, recipientUuid, deviceId } = item;
@ -1015,7 +1021,8 @@ async function deleteSentProtoRecipient(
const rows = prepare(
db,
`
SELECT sendLogPayloads.id FROM sendLogPayloads
SELECT sendLogPayloads.id, sendLogPayloads.hasPniSignatureMessage
FROM sendLogPayloads
INNER JOIN sendLogRecipients
ON sendLogRecipients.payloadId = sendLogPayloads.id
WHERE
@ -1032,10 +1039,9 @@ async function deleteSentProtoRecipient(
'deleteSentProtoRecipient: More than one payload matches ' +
`recipient and timestamp ${timestamp}. Using the first.`
);
continue;
}
const { id } = rows[0];
const { id, hasPniSignatureMessage } = rows[0];
// 2. Delete the recipient/device combination in question.
prepare(
@ -1050,32 +1056,61 @@ async function deleteSentProtoRecipient(
).run({ id, recipientUuid, deviceId });
// 3. See how many more recipient devices there were for this payload.
const remaining = prepare(
const remainingDevices = prepare(
db,
`
SELECT count(*) FROM sendLogRecipients
WHERE payloadId = $id AND recipientUuid = $recipientUuid;
`
)
.pluck(true)
.get({ id, recipientUuid });
// 4. If there are no remaining devices for this recipient and we included
// the pni signature in the proto - return the recipient to the caller.
if (remainingDevices === 0 && hasPniSignatureMessage) {
logger.info(
'deleteSentProtoRecipient: ' +
`Successfully shared phone number with ${recipientUuid} ` +
`through message ${timestamp}`
);
successfulPhoneNumberShares.push(recipientUuid);
}
strictAssert(
isNumber(remainingDevices),
'deleteSentProtoRecipient: select count() returned non-number!'
);
// 5. See how many more recipients there were for this payload.
const remainingTotal = prepare(
db,
'SELECT count(*) FROM sendLogRecipients WHERE payloadId = $id;'
)
.pluck(true)
.get({ id });
if (!isNumber(remaining)) {
throw new Error(
'deleteSentProtoRecipient: select count() returned non-number!'
);
}
strictAssert(
isNumber(remainingTotal),
'deleteSentProtoRecipient: select count() returned non-number!'
);
if (remaining > 0) {
if (remainingTotal > 0) {
continue;
}
// 4. Delete the entire payload if there are no more recipients left.
// 6. Delete the entire payload if there are no more recipients left.
logger.info(
'deleteSentProtoRecipient: ' +
`Deleting proto payload for timestamp ${timestamp}`
);
prepare(db, 'DELETE FROM sendLogPayloads WHERE id = $id;').run({
id,
});
}
return { successfulPhoneNumberShares };
})();
}
@ -1122,6 +1157,9 @@ async function getSentProtoByRecipient({
return {
...row,
urgent: isNumber(row.urgent) ? Boolean(row.urgent) : true,
hasPniSignatureMessage: isNumber(row.hasPniSignatureMessage)
? Boolean(row.hasPniSignatureMessage)
: true,
messageIds: messageIds ? messageIds.split(',') : [],
};
}
@ -1136,6 +1174,9 @@ async function getAllSentProtos(): Promise<Array<SentProtoType>> {
return rows.map(row => ({
...row,
urgent: isNumber(row.urgent) ? Boolean(row.urgent) : true,
hasPniSignatureMessage: isNumber(row.hasPniSignatureMessage)
? Boolean(row.hasPniSignatureMessage)
: true,
}));
}
async function _getAllSentProtoRecipients(): Promise<

View file

@ -0,0 +1,29 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { Database } from 'better-sqlite3';
import type { LoggerType } from '../../types/Logging';
export default function updateToSchemaVersion66(
currentVersion: number,
db: Database,
logger: LoggerType
): void {
if (currentVersion >= 66) {
return;
}
db.transaction(() => {
db.exec(
`
ALTER TABLE sendLogPayloads
ADD COLUMN hasPniSignatureMessage INTEGER DEFAULT 0 NOT NULL;
`
);
db.pragma('user_version = 66');
})();
logger.info('updateToSchemaVersion66: success!');
}

View file

@ -41,6 +41,7 @@ import updateToSchemaVersion62 from './62-add-urgent-to-send-log';
import updateToSchemaVersion63 from './63-add-urgent-to-unprocessed';
import updateToSchemaVersion64 from './64-uuid-column-for-pre-keys';
import updateToSchemaVersion65 from './65-add-storage-id-to-stickers';
import updateToSchemaVersion66 from './66-add-pni-signature-to-sent-protos';
function updateToSchemaVersion1(
currentVersion: number,
@ -1945,6 +1946,7 @@ export const SCHEMA_VERSIONS = [
updateToSchemaVersion63,
updateToSchemaVersion64,
updateToSchemaVersion65,
updateToSchemaVersion66,
];
export function updateSchema(db: Database, logger: LoggerType): void {