diff --git a/desktop/src/push-notifications.js b/desktop/src/push-notifications.js --- a/desktop/src/push-notifications.js +++ b/desktop/src/push-notifications.js @@ -141,7 +141,11 @@ }); } else if (process.platform === 'win32') { windowsPushNotifEventEmitter.on('received-wns-notification', payload => { - showNewNotification(payload, handleClick); + if (payload.encryptedPayload) { + handleEncryptedNotification(payload.encryptedPayload); + } else { + showNewNotification(payload, handleClick); + } }); } } 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 { @@ -34,10 +37,7 @@ type MessageData, } from 'lib/types/message-types.js'; import { rawMessageInfoValidator } from 'lib/types/message-types.js'; -import type { - WNSNotification, - ResolvedNotifTexts, -} from 'lib/types/notif-types.js'; +import type { ResolvedNotifTexts } from 'lib/types/notif-types.js'; import { resolvedNotifTextsValidator } from 'lib/types/notif-types.js'; import type { ServerThreadInfo, ThreadInfo } from 'lib/types/thread-types.js'; import { updateTypes } from 'lib/types/update-types-enum.js'; @@ -50,6 +50,7 @@ prepareEncryptedAPNsNotifications, prepareEncryptedAndroidNotifications, prepareEncryptedWebNotifications, + prepareEncryptedWNSNotifications, } from './crypto.js'; import { getAPNsNotificationTopic } from './providers.js'; import { rescindPushNotifs } from './rescind.js'; @@ -452,27 +453,30 @@ const windowsVersionsToTokens = byPlatform.get('windows'); if (windowsVersionsToTokens) { for (const [versionKey, devices] of windowsVersionsToTokens) { - const { codeVersion, stateVersion } = stringToVersionKey(versionKey); + const { codeVersion, stateVersion, majorDesktopVersion } = + stringToVersionKey(versionKey); const platformDetails = { platform: 'windows', codeVersion, stateVersion, + majorDesktopVersion, }; const preparePromise: Promise<$ReadOnlyArray> = (async () => { - const notification = await prepareWNSNotification({ - notifTexts, - threadID: threadInfo.id, - unreadCount, - platformDetails, - }); + const targetedNotifications = await prepareWNSNotification( + userID, + devices, + { + notifTexts, + threadID: threadInfo.id, + unreadCount, + platformDetails, + }, + ); - return devices.map(({ deviceToken }) => ({ - notification: ({ - deviceToken, - notification, - }: TargetedWNSNotification), + return targetedNotifications.map(notification => ({ + notification, platform: 'windows', notificationInfo: { ...notificationInfo, @@ -1276,8 +1280,10 @@ platformDetails: tPlatformDetails, }); async function prepareWNSNotification( + userID: string, + devices: $ReadOnlyArray, inputData: WNSNotifInputData, -): Promise { +): Promise<$ReadOnlyArray> { const convertedData = validateOutput( inputData.platformDetails, wnsNotifInputDataValidator, @@ -1297,7 +1303,21 @@ ) { console.warn('WNS notification exceeds size limit'); } - return notification; + + const isStaffOrDev = isStaff(userID) || isDev; + const shouldBeEncrypted = + isStaffOrDev && + hasMinCodeVersion(inputData.platformDetails, { + majorDesktop: NEXT_CODE_VERSION, + }); + + if (!shouldBeEncrypted) { + return devices.map(({ deviceToken }) => ({ + deviceToken, + notification, + })); + } + return await prepareEncryptedWNSNotifications(devices, notification); } type NotificationInfo = 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,9 +6,16 @@ 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 Platform, + type PlatformDetails, + isDeviceType, +} from 'lib/types/device-types.js'; import type { CalendarQuery } from 'lib/types/entry-types.js'; import { type ServerSessionChange, @@ -742,18 +749,34 @@ async function isCookieMissingOlmNotificationsSession( viewer: Viewer, ): Promise { + const isDeviceSupportingE2ENotifs = + isDeviceType(viewer.platformDetails?.platform) && + hasMinCodeVersion(viewer.platformDetails, { native: 222 }); + const isStaffOrDev = isStaff(viewer.userID) || isDev; + + const isWebSupportingE2ENotifs = + isStaffOrDev && + viewer.platformDetails?.platform === 'web' && + hasMinCodeVersion(viewer.platformDetails, { web: 43 }); + + const isMacOSSupportingE2ENotifs = + isStaffOrDev && + viewer.platformDetails?.platform === 'macos' && + hasMinCodeVersion(viewer.platformDetails, { web: 43, majorDesktop: 9 }); + + const isWindowsSupportingE2ENotifs = + isStaffOrDev && + viewer.platformDetails?.platform === 'windows' && + hasMinCodeVersion(viewer.platformDetails, { + majorDesktop: NEXT_CODE_VERSION, + }); + if ( - !viewer.platformDetails || - (viewer.platformDetails.platform !== 'ios' && - viewer.platformDetails.platform !== 'android' && - !(viewer.platformDetails.platform === 'web' && isStaffOrDev) && - !(viewer.platformDetails.platform === 'macos' && isStaffOrDev)) || - !hasMinCodeVersion(viewer.platformDetails, { - native: 222, - web: 43, - majorDesktop: 9, - }) + !isDeviceSupportingE2ENotifs && + !isWebSupportingE2ENotifs && + !isMacOSSupportingE2ENotifs && + !isWindowsSupportingE2ENotifs ) { return false; }