diff --git a/keyserver/src/push/providers.js b/keyserver/src/push/providers.js --- a/keyserver/src/push/providers.js +++ b/keyserver/src/push/providers.js @@ -7,11 +7,20 @@ import invariant from 'invariant'; import webpush from 'web-push'; +import type { PlatformDetails } from 'lib/types/device-types'; + import { importJSON } from '../utils/import-json.js'; type APNPushProfile = 'apn_config' | 'comm_apn_config'; -function getAPNPushProfileForCodeVersion(codeVersion: ?number): APNPushProfile { - return codeVersion && codeVersion >= 87 ? 'comm_apn_config' : 'apn_config'; +function getAPNPushProfileForCodeVersion( + platformDetails: PlatformDetails, +): APNPushProfile { + if (platformDetails.platform === 'macos') { + return 'comm_apn_config'; + } + return platformDetails.codeVersion && platformDetails.codeVersion >= 87 + ? 'comm_apn_config' + : 'apn_config'; } type FCMPushProfile = 'fcm_config' | 'comm_fcm_config'; @@ -77,8 +86,13 @@ } } -function getAPNsNotificationTopic(codeVersion: ?number): string { - return codeVersion && codeVersion >= 87 ? 'app.comm' : 'org.squadcal.app'; +function getAPNsNotificationTopic(platformDetails: PlatformDetails): string { + if (platformDetails.platform === 'macos') { + return 'app.comm.macos'; + } + return platformDetails.codeVersion && platformDetails.codeVersion >= 87 + ? 'app.comm' + : 'org.squadcal.app'; } type WebPushConfig = { +publicKey: string, +privateKey: string }; 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 @@ -61,7 +61,7 @@ deliveryPromises[id] = apnPush({ notification, deviceTokens: delivery.iosDeviceTokens, - codeVersion: null, + platformDetails: { platform: 'ios' }, }); } else if (delivery.androidID) { // Old Android @@ -87,7 +87,7 @@ deliveryPromises[id] = apnPush({ notification, deviceTokens, - codeVersion, + platformDetails: { platform: 'ios', codeVersion }, }); } else if (delivery.deviceType === 'android') { // New Android @@ -162,7 +162,10 @@ ): apn.Notification { const notification = new apn.Notification(); notification.contentAvailable = true; - notification.topic = getAPNsNotificationTopic(codeVersion); + notification.topic = getAPNsNotificationTopic({ + platform: 'ios', + codeVersion: codeVersion ?? undefined, + }); notification.priority = 5; notification.pushType = 'background'; notification.payload = 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 @@ -22,7 +22,7 @@ rawThreadInfoFromServerThreadInfo, threadInfoFromRawThreadInfo, } from 'lib/shared/thread-utils.js'; -import type { Platform } from 'lib/types/device-types.js'; +import type { Platform, PlatformDetails } from 'lib/types/device-types.js'; import { type RawMessageInfo, type MessageInfo, @@ -167,14 +167,14 @@ { platform: 'ios', codeVersion }, ); const deliveryPromise = (async () => { - const notification = await prepareIOSNotification( + const notification = await prepareAPNsNotification( allMessageInfos, shimmedNewRawMessageInfos, threadInfo, notifInfo.collapseKey, badgeOnly, unreadCounts[userID], - codeVersion, + { platform: 'ios', codeVersion }, ); return await sendIOSNotification(notification, [...deviceTokens], { ...notificationInfo, @@ -491,19 +491,18 @@ return byPlatform; } -async function prepareIOSNotification( +async function prepareAPNsNotification( allMessageInfos: MessageInfo[], newRawMessageInfos: RawMessageInfo[], threadInfo: ThreadInfo, collapseKey: ?string, badgeOnly: boolean, unreadCount: number, - codeVersion: number, + platformDetails: PlatformDetails, ): Promise { const uniqueID = uuidv4(); const notification = new apn.Notification(); - notification.topic = getAPNsNotificationTopic(codeVersion); - + notification.topic = getAPNsNotificationTopic(platformDetails); const { merged, ...rest } = await notifTextsForMessageInfo( allMessageInfos, threadInfo, @@ -524,7 +523,7 @@ notification.pushType = 'alert'; notification.payload.id = uniqueID; notification.payload.threadID = threadInfo.id; - if (codeVersion > 1000) { + if (platformDetails.codeVersion && platformDetails.codeVersion > 1000) { notification.mutableContent = true; } if (collapseKey) { @@ -547,7 +546,8 @@ const notificationCopy = _cloneDeep(notification); if (notificationCopy.length() > apnMaxNotificationPayloadByteSize) { console.warn( - `iOS notification ${uniqueID} exceeds size limit, even with messageInfos omitted`, + `${platformDetails.platform} notification ${uniqueID} ` + + `exceeds size limit, even with messageInfos omitted`, ); } return notification; @@ -671,7 +671,11 @@ notificationInfo: NotificationInfo, ): Promise { const { source, codeVersion } = notificationInfo; - const response = await apnPush({ notification, deviceTokens, codeVersion }); + const response = await apnPush({ + notification, + deviceTokens, + platformDetails: { platform: 'ios', codeVersion }, + }); const delivery: IOSDelivery = { source, deviceType: 'ios', @@ -882,7 +886,10 @@ for (const [codeVer, deviceTokens] of iosVersionsToTokens) { const codeVersion = parseInt(codeVer, 10); // only for Flow const notification = new apn.Notification(); - notification.topic = getAPNsNotificationTopic(codeVersion); + notification.topic = getAPNsNotificationTopic({ + platform: 'ios', + codeVersion, + }); notification.badge = unreadCount; notification.pushType = 'alert'; deliveryPromises.push( diff --git a/keyserver/src/push/utils.js b/keyserver/src/push/utils.js --- a/keyserver/src/push/utils.js +++ b/keyserver/src/push/utils.js @@ -6,6 +6,7 @@ import invariant from 'invariant'; import webpush from 'web-push'; +import type { PlatformDetails } from 'lib/types/device-types.js'; import { threadSubscriptions } from 'lib/types/subscription-types.js'; import { threadPermissions } from 'lib/types/thread-types.js'; @@ -38,13 +39,13 @@ async function apnPush({ notification, deviceTokens, - codeVersion, + platformDetails, }: { +notification: apn.Notification, +deviceTokens: $ReadOnlyArray, - +codeVersion: ?number, + +platformDetails: PlatformDetails, }): Promise { - const pushProfile = getAPNPushProfileForCodeVersion(codeVersion); + const pushProfile = getAPNPushProfileForCodeVersion(platformDetails); const apnProvider = await getAPNProvider(pushProfile); if (!apnProvider && process.env.NODE_ENV === 'development') { console.log(`no keyserver/secrets/${pushProfile}.json so ignoring notifs`);