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 @@ -3,9 +3,11 @@ import apn from '@parse/node-apn'; import invariant from 'invariant'; +import type { PlatformDetails } from 'lib/types/device-types.js'; 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 +23,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 +78,7 @@ rowParsedDeliveries.push({ notificationID: delivery.iosID, codeVersion: delivery.codeVersion, + stateVersion: delivery.stateVersion, platform: delivery.deviceType ?? 'ios', deviceTokens, }); @@ -85,6 +89,7 @@ rowParsedDeliveries.push({ notificationID: row.collapse_key ? row.collapse_key : id, codeVersion: delivery.codeVersion, + stateVersion: delivery.stateVersion, platform: 'android', deviceTokens, }); @@ -110,6 +115,20 @@ }; for (const delivery of parsedDeliveries[id]) { + let platformDetails: PlatformDetails = { platform: delivery.platform }; + if (delivery.codeVersion) { + platformDetails = { + ...platformDetails, + codeVersion: delivery.codeVersion, + }; + } + if (delivery.stateVersion) { + platformDetails = { + ...platformDetails, + stateVersion: delivery.stateVersion, + }; + } + if (delivery.platform === 'ios') { const devices = delivery.deviceTokens.map(deviceToken => ({ deviceToken, @@ -120,7 +139,7 @@ delivery.notificationID, row.unread_count, threadID, - delivery.codeVersion, + platformDetails, devices, ); return await apnPush({ @@ -142,7 +161,7 @@ delivery.notificationID, row.unread_count, threadID, - delivery.codeVersion, + platformDetails, devices, ); return await fcmPush({ @@ -253,13 +272,16 @@ iosID: string, unreadCount: number, threadID: string, - codeVersion: ?number, + platformDetails: PlatformDetails, devices: $ReadOnlyArray, ): Promise<$ReadOnlyArray> { + threadID = validateOutput(platformDetails, tID, threadID); + const { codeVersion } = platformDetails; + const notification = new apn.Notification(); notification.topic = getAPNsNotificationTopic({ platform: 'ios', - codeVersion: codeVersion ?? undefined, + codeVersion, }); if (codeVersion && codeVersion > 198) { @@ -297,9 +319,12 @@ notifID: string, unreadCount: number, threadID: string, - codeVersion: ?number, + platformDetails: PlatformDetails, devices: $ReadOnlyArray, ): Promise<$ReadOnlyArray> { + threadID = validateOutput(platformDetails, tID, threadID); + const { codeVersion } = platformDetails; + 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); @@ -982,12 +987,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 = { @@ -996,6 +1003,7 @@ iosID: string, deviceTokens: $ReadOnlyArray, codeVersion: number, + stateVersion: number, errors?: $ReadOnlyArray, }; type APNsResult = { @@ -1008,7 +1016,7 @@ targetedNotifications: $ReadOnlyArray, notificationInfo: NotificationInfo, ): Promise { - const { source, codeVersion } = notificationInfo; + const { source, codeVersion, stateVersion } = notificationInfo; const response = await apnPush({ targetedNotifications, @@ -1029,6 +1037,7 @@ iosID, deviceTokens, codeVersion, + stateVersion, }; if (response.errors) { delivery.errors = response.errors; @@ -1051,6 +1060,7 @@ androidIDs: $ReadOnlyArray, deviceTokens: $ReadOnlyArray, codeVersion: number, + stateVersion: number, errors?: $ReadOnlyArray, }; type AndroidResult = { @@ -1065,7 +1075,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, @@ -1081,6 +1091,7 @@ androidIDs, deviceTokens, codeVersion, + stateVersion, }; if (response.errors) { delivery.errors = response.errors; @@ -1100,6 +1111,7 @@ +deviceType: 'web', +deviceTokens: $ReadOnlyArray, +codeVersion?: number, + +stateVersion: number, +errors?: $ReadOnlyArray, }; type WebResult = { @@ -1112,7 +1124,7 @@ deviceTokens: $ReadOnlyArray, notificationInfo: NotificationInfo, ): Promise { - const { source, codeVersion } = notificationInfo; + const { source, codeVersion, stateVersion } = notificationInfo; const response = await webPush({ notification, @@ -1125,6 +1137,7 @@ deviceTokens, codeVersion, errors: response.errors, + stateVersion, }; const result: WebResult = { info: notificationInfo, @@ -1140,6 +1153,7 @@ +wnsIDs: $ReadOnlyArray, +deviceTokens: $ReadOnlyArray, +codeVersion?: number, + +stateVersion: number, +errors?: $ReadOnlyArray, }; type WNSResult = { @@ -1152,7 +1166,7 @@ deviceTokens: $ReadOnlyArray, notificationInfo: NotificationInfo, ): Promise { - const { source, codeVersion } = notificationInfo; + const { source, codeVersion, stateVersion } = notificationInfo; const response = await wnsPush({ notification, @@ -1167,6 +1181,7 @@ deviceTokens, codeVersion, errors: response.errors, + stateVersion, }; const result: WNSResult = { info: notificationInfo, @@ -1309,6 +1324,7 @@ dbID, userID, codeVersion, + stateVersion, }); })(); @@ -1319,7 +1335,7 @@ const androidVersionsToTokens = byPlatform.get('android'); if (androidVersionsToTokens) { for (const [versionKey, deviceInfos] of androidVersionsToTokens) { - const { codeVersion } = stringToVersionKey(versionKey); + const { codeVersion, stateVersion } = stringToVersionKey(versionKey); const notificationData = codeVersion < 69 ? { badge: unreadCount.toString() } @@ -1347,6 +1363,7 @@ dbID, userID, codeVersion, + stateVersion, }); })(); deliveryPromises.push(deliveryPromise); @@ -1375,6 +1392,7 @@ dbID, userID, codeVersion, + stateVersion, }), ); }