diff --git a/keyserver/src/creators/message-creator.js b/keyserver/src/creators/message-creator.js --- a/keyserver/src/creators/message-creator.js +++ b/keyserver/src/creators/message-creator.js @@ -385,6 +385,7 @@ cookieID: cookieID.toString(), codeVersion: versions ? versions.codeVersion : null, stateVersion: versions ? versions.stateVersion : null, + majorDesktopVersion: versions ? versions.desktopCodeVersion : null, }); } thisUserInfo.threadIDs.add(threadID); 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 @@ -26,7 +26,10 @@ rawThreadInfoFromServerThreadInfo, threadInfoFromRawThreadInfo, } from 'lib/shared/thread-utils.js'; -import { hasMinCodeVersion } from 'lib/shared/version-utils.js'; +import { + hasMinCodeVersion, + NEXT_CODE_VERSION, +} from 'lib/shared/version-utils.js'; import type { Platform, PlatformDetails } from 'lib/types/device-types.js'; import { messageTypes } from 'lib/types/message-types-enum.js'; import { @@ -90,6 +93,7 @@ +cookieID: string, +codeVersion: ?number, +stateVersion: ?number, + +majorDesktopVersion: ?number, }; export type PushUserInfo = { @@ -303,6 +307,7 @@ const preparePromise: Promise<$ReadOnlyArray> = (async () => { const targetedNotifications = await prepareAPNsNotification( + userID, { notifTexts, newRawMessageInfos: shimmedNewRawMessageInfos, @@ -407,11 +412,13 @@ const macosVersionsToTokens = byPlatform.get('macos'); if (macosVersionsToTokens) { for (const [versionKey, devices] of macosVersionsToTokens) { - const { codeVersion, stateVersion } = stringToVersionKey(versionKey); + const { codeVersion, stateVersion, majorDesktopVersion } = + stringToVersionKey(versionKey); const platformDetails = { platform: 'macos', codeVersion, stateVersion, + majorDesktopVersion, }; const shimmedNewRawMessageInfos = shimUnsupportedRawMessageInfos( newRawMessageInfos, @@ -420,6 +427,7 @@ const preparePromise: Promise<$ReadOnlyArray> = (async () => { const targetedNotifications = await prepareAPNsNotification( + userID, { notifTexts, newRawMessageInfos: shimmedNewRawMessageInfos, @@ -801,10 +809,18 @@ return await createIDs('notifications', numIDsNeeded); } -type VersionKey = { codeVersion: number, stateVersion: number }; +type VersionKey = { + +codeVersion: number, + +stateVersion: number, + +majorDesktopVersion?: number, +}; const versionKeyRegex: RegExp = new RegExp(/^-?\d+\|-?\d+$/); function versionKeyToString(versionKey: VersionKey): string { - return `${versionKey.codeVersion}|${versionKey.stateVersion}`; + const baseStringVersionKey = `${versionKey.codeVersion}|${versionKey.stateVersion}`; + if (!versionKey.majorDesktopVersion) { + return baseStringVersionKey; + } + return `${baseStringVersionKey}|${versionKey.majorDesktopVersion}`; } function stringToVersionKey(versionKeyString: string): VersionKey { @@ -812,8 +828,10 @@ versionKeyRegex.test(versionKeyString), 'should pass correct version key string', ); - const [codeVersion, stateVersion] = versionKeyString.split('|').map(Number); - return { codeVersion, stateVersion }; + const [codeVersion, stateVersion, majorDesktopVersion] = versionKeyString + .split('|') + .map(Number); + return { codeVersion, stateVersion, majorDesktopVersion }; } function getDevicesByPlatform( @@ -830,18 +848,20 @@ byPlatform.set(device.platform, innerMap); } const codeVersion: number = - device.codeVersion !== null && - device.codeVersion !== undefined && - device.platform !== 'windows' && - device.platform !== 'macos' + device.codeVersion !== null && device.codeVersion !== undefined ? device.codeVersion : -1; const stateVersion: number = device.stateVersion ?? -1; - const versionKey = versionKeyToString({ - codeVersion, - stateVersion, - }); + let versionsObject = { codeVersion, stateVersion }; + if (device.majorDesktopVersion) { + versionsObject = { + ...versionsObject, + majorDesktopVersion: device.majorDesktopVersion, + }; + } + + const versionKey = versionKeyToString(versionsObject); let innerMostArrayTmp: ?Array = innerMap.get(versionKey); if (!innerMostArrayTmp) { @@ -877,6 +897,7 @@ platformDetails: tPlatformDetails, }); async function prepareAPNsNotification( + userID: string, inputData: APNsNotifInputData, devices: $ReadOnlyArray, ): Promise<$ReadOnlyArray> { @@ -906,11 +927,22 @@ const canDecryptAllNotifTypes = platformDetails.codeVersion && platformDetails.codeVersion >= 267; - const shouldBeEncrypted = + const canDecryptIOSNotifs = platformDetails.platform === 'ios' && (canDecryptAllNotifTypes || (isNonCollapsibleTextNotification && canDecryptNonCollapsibleTextNotifs)); + const isStaffOrDev = isStaff(userID) || isDev; + const canDecryptMacOSNotifs = + isStaffOrDev && + platformDetails.platform === 'macos' && + hasMinCodeVersion(platformDetails, { + web: NEXT_CODE_VERSION, + majorDesktop: NEXT_CODE_VERSION, + }); + + const shouldBeEncrypted = canDecryptIOSNotifs || canDecryptMacOSNotifs; + const uniqueID = uuidv4(); const notification = new apn.Notification(); notification.topic = getAPNsNotificationTopic(platformDetails); @@ -1710,11 +1742,36 @@ notification.badge = unreadCount; notification.pushType = 'alert'; const preparePromise: Promise = (async () => { - return deviceInfos.map(({ deviceToken }) => ({ - notification: ({ + const isStaffOrDev = isStaff(userID) || isDev; + const shouldBeEncrypted = + isStaffOrDev && + hasMinCodeVersion(viewer.platformDetails, { + web: NEXT_CODE_VERSION, + majorDesktop: NEXT_CODE_VERSION, + }); + let targetedNotifications: $ReadOnlyArray; + if (shouldBeEncrypted) { + const notificationsArray = await prepareEncryptedAPNsNotifications( + deviceInfos, + notification, + codeVersion, + ); + targetedNotifications = notificationsArray.map( + ({ notification: notif, deviceToken, encryptionOrder }) => ({ + notification: notif, + deviceToken, + encryptionOrder, + }), + ); + } else { + targetedNotifications = deviceInfos.map(({ deviceToken }) => ({ deviceToken, notification, - }: TargetedAPNsNotification), + })); + } + + return targetedNotifications.map(targetedNotification => ({ + notification: targetedNotification, platform: 'macos', notificationInfo: { source, diff --git a/keyserver/src/session/cookies.js b/keyserver/src/session/cookies.js --- a/keyserver/src/session/cookies.js +++ b/keyserver/src/session/cookies.js @@ -6,7 +6,10 @@ import url from 'url'; import { isStaff } from 'lib/shared/staff-utils.js'; -import { hasMinCodeVersion } from 'lib/shared/version-utils.js'; +import { + hasMinCodeVersion, + NEXT_CODE_VERSION, +} from 'lib/shared/version-utils.js'; import type { SignedIdentityKeysBlob } from 'lib/types/crypto-types.js'; import type { Platform, PlatformDetails } from 'lib/types/device-types.js'; import type { CalendarQuery } from 'lib/types/entry-types.js'; @@ -729,10 +732,12 @@ !viewer.platformDetails || (viewer.platformDetails.platform !== 'ios' && viewer.platformDetails.platform !== 'android' && - !(viewer.platformDetails.platform === 'web' && isStaffOrDev)) || + !(viewer.platformDetails.platform === 'web' && isStaffOrDev) && + !(viewer.platformDetails.platform === 'macos' && isStaffOrDev)) || !hasMinCodeVersion(viewer.platformDetails, { native: 222, web: 43, + majorDesktop: NEXT_CODE_VERSION, }) ) { return false;