diff --git a/keyserver/src/push/rescind.js b/keyserver/src/push/rescind.js --- a/keyserver/src/push/rescind.js +++ b/keyserver/src/push/rescind.js @@ -6,6 +6,7 @@ import { threadSubscriptions } from 'lib/types/subscription-types.js'; import { threadPermissions } from 'lib/types/thread-permission-types.js'; import { promiseAll } from 'lib/utils/promises.js'; +import { tID } from 'lib/utils/validation-utils.js'; import { prepareEncryptedAndroidNotificationRescinds, @@ -21,6 +22,7 @@ import createIDs from '../creators/id-creator.js'; import { dbQuery, SQL } from '../database/database.js'; import type { SQLStatementType } from '../database/types.js'; +import { validateOutput } from '../utils/validation-utils.js'; type ParsedDelivery = { +platform: 'ios' | 'macos' | 'android', @@ -75,6 +77,7 @@ rowParsedDeliveries.push({ notificationID: delivery.iosID, codeVersion: delivery.codeVersion, + stateVersion: delivery.stateVersion, platform: delivery.deviceType ?? 'ios', deviceTokens, }); @@ -85,6 +88,7 @@ rowParsedDeliveries.push({ notificationID: row.collapse_key ? row.collapse_key : id, codeVersion: delivery.codeVersion, + stateVersion: delivery.stateVersion, platform: 'android', deviceTokens, }); @@ -121,6 +125,7 @@ row.unread_count, threadID, delivery.codeVersion, + delivery.stateVersion, devices, ); return await apnPush({ @@ -143,6 +148,7 @@ row.unread_count, threadID, delivery.codeVersion, + delivery.stateVersion, devices, ); return await fcmPush({ @@ -254,8 +260,17 @@ unreadCount: number, threadID: string, codeVersion: ?number, + stateVersion: ?number, devices: $ReadOnlyArray, ): Promise<$ReadOnlyArray> { + if (codeVersion && stateVersion) { + threadID = validateOutput( + { platform: 'ios', codeVersion, stateVersion }, + tID, + threadID, + ); + } + const notification = new apn.Notification(); notification.topic = getAPNsNotificationTopic({ platform: 'ios', @@ -298,8 +313,17 @@ unreadCount: number, threadID: string, codeVersion: ?number, + stateVersion: ?number, devices: $ReadOnlyArray, ): Promise<$ReadOnlyArray> { + if (codeVersion && stateVersion) { + threadID = validateOutput( + { platform: 'android', codeVersion, stateVersion }, + tID, + threadID, + ); + } + const notification = { data: { badge: unreadCount.toString(), diff --git a/keyserver/src/push/send.js b/keyserver/src/push/send.js --- a/keyserver/src/push/send.js +++ b/keyserver/src/push/send.js @@ -235,6 +235,7 @@ return await sendAPNsNotification('ios', targetedNotifications, { ...notificationInfo, codeVersion, + stateVersion, }); })(); deliveryPromises.push(deliveryPromise); @@ -270,6 +271,7 @@ return await sendAndroidNotification(targetedNotifications, { ...notificationInfo, codeVersion, + stateVersion, }); })(); deliveryPromises.push(deliveryPromise); @@ -296,6 +298,7 @@ return await sendWebNotification(notification, deviceTokens, { ...notificationInfo, codeVersion, + stateVersion, }); })(); deliveryPromises.push(deliveryPromise); @@ -330,6 +333,7 @@ return await sendAPNsNotification('macos', targetedNotifications, { ...notificationInfo, codeVersion, + stateVersion, }); })(); deliveryPromises.push(deliveryPromise); @@ -356,6 +360,7 @@ return await sendWNSNotification(notification, deviceTokens, { ...notificationInfo, codeVersion, + stateVersion, }); })(); deliveryPromises.push(deliveryPromise); @@ -963,12 +968,14 @@ +messageID: string, +collapseKey: ?string, +codeVersion: number, + +stateVersion: number, } | { +source: 'mark_as_unread' | 'mark_as_read' | 'activity_update', +dbID: string, +userID: string, +codeVersion: number, + +stateVersion: number, }; type APNsDelivery = { @@ -977,6 +984,7 @@ iosID: string, deviceTokens: $ReadOnlyArray, codeVersion: number, + stateVersion: number, errors?: $ReadOnlyArray, }; type APNsResult = { @@ -989,7 +997,7 @@ targetedNotifications: $ReadOnlyArray, notificationInfo: NotificationInfo, ): Promise { - const { source, codeVersion } = notificationInfo; + const { source, codeVersion, stateVersion } = notificationInfo; const response = await apnPush({ targetedNotifications, @@ -1010,6 +1018,7 @@ iosID, deviceTokens, codeVersion, + stateVersion, }; if (response.errors) { delivery.errors = response.errors; @@ -1032,6 +1041,7 @@ androidIDs: $ReadOnlyArray, deviceTokens: $ReadOnlyArray, codeVersion: number, + stateVersion: number, errors?: $ReadOnlyArray, }; type AndroidResult = { @@ -1046,7 +1056,7 @@ const collapseKey = notificationInfo.collapseKey ? notificationInfo.collapseKey : null; // for Flow... - const { source, codeVersion } = notificationInfo; + const { source, codeVersion, stateVersion } = notificationInfo; const response = await fcmPush({ targetedNotifications, collapseKey, @@ -1062,6 +1072,7 @@ androidIDs, deviceTokens, codeVersion, + stateVersion, }; if (response.errors) { delivery.errors = response.errors; @@ -1081,6 +1092,7 @@ +deviceType: 'web', +deviceTokens: $ReadOnlyArray, +codeVersion?: number, + stateVersion: number, +errors?: $ReadOnlyArray, }; type WebResult = { @@ -1093,7 +1105,7 @@ deviceTokens: $ReadOnlyArray, notificationInfo: NotificationInfo, ): Promise { - const { source, codeVersion } = notificationInfo; + const { source, codeVersion, stateVersion } = notificationInfo; const response = await webPush({ notification, @@ -1106,6 +1118,7 @@ deviceTokens, codeVersion, errors: response.errors, + stateVersion, }; const result: WebResult = { info: notificationInfo, @@ -1121,6 +1134,7 @@ +wnsIDs: $ReadOnlyArray, +deviceTokens: $ReadOnlyArray, +codeVersion?: number, + stateVersion: number, +errors?: $ReadOnlyArray, }; type WNSResult = { @@ -1133,7 +1147,7 @@ deviceTokens: $ReadOnlyArray, notificationInfo: NotificationInfo, ): Promise { - const { source, codeVersion } = notificationInfo; + const { source, codeVersion, stateVersion } = notificationInfo; const response = await wnsPush({ notification, @@ -1148,6 +1162,7 @@ deviceTokens, codeVersion, errors: response.errors, + stateVersion, }; const result: WNSResult = { info: notificationInfo, @@ -1287,6 +1302,7 @@ dbID, userID, codeVersion, + stateVersion, }); })(); @@ -1297,7 +1313,7 @@ const androidVersionsToTokens = byPlatform.get('android'); if (androidVersionsToTokens) { for (const [versionKey, deviceInfos] of androidVersionsToTokens) { - const [codeVersion] = versionKey.split('|').map(Number); + const [codeVersion, stateVersion] = versionKey.split('|').map(Number); const notificationData = codeVersion < 69 ? { badge: unreadCount.toString() } @@ -1325,6 +1341,7 @@ dbID, userID, codeVersion, + stateVersion, }); })(); deliveryPromises.push(deliveryPromise); @@ -1353,6 +1370,7 @@ dbID, userID, codeVersion, + stateVersion, }), ); }