diff --git a/keyserver/src/push/crypto.js b/keyserver/src/push/crypto.js --- a/keyserver/src/push/crypto.js +++ b/keyserver/src/push/crypto.js @@ -8,7 +8,10 @@ import type { PlainTextWebNotification, + PlainTextWebNotificationPayload, WebNotification, + PlainTextWNSNotification, + WNSNotification, } from 'lib/types/notif-types.js'; import { toBase64URL } from 'lib/utils/base64.js'; @@ -238,12 +241,18 @@ }; } -async function encryptWebNotification( +async function encryptBasicPayload( cookieID: string, - notification: PlainTextWebNotification, -): Promise<{ +notification: WebNotification, +encryptionOrder?: number }> { - const { id, ...payloadSansId } = notification; - const unencryptedSerializedPayload = JSON.stringify(payloadSansId); + basicPayload: T, +): Promise< + | { +encryptedPayload: string, +encryptionOrder?: number } + | { ...T, +encryptionFailed: '1' }, +> { + const unencryptedSerializedPayload = JSON.stringify(basicPayload); + + if (!unencryptedSerializedPayload) { + return { ...basicPayload, encryptionFailed: '1' }; + } try { const { @@ -254,21 +263,40 @@ }); return { - notification: { id, encryptedPayload: serializedPayload.body }, + encryptedPayload: serializedPayload.body, encryptionOrder, }; } catch (e) { console.log('Notification encryption failed: ' + e); return { - notification: { - id, - encryptionFailed: '1', - ...payloadSansId, - }, + ...basicPayload, + encryptionFailed: '1', }; } } +async function encryptWebNotification( + cookieID: string, + notification: PlainTextWebNotification, +): Promise<{ +notification: WebNotification, +encryptionOrder?: number }> { + const { id, ...payloadSansId } = notification; + const { encryptionOrder, ...encryptionResult } = + await encryptBasicPayload( + cookieID, + payloadSansId, + ); + return { notification: { id, ...encryptionResult }, encryptionOrder }; +} + +async function encryptWNSNotification( + cookieID: string, + notification: PlainTextWNSNotification, +): Promise<{ +notification: WNSNotification, +encryptionOrder?: number }> { + const { encryptionOrder, ...encryptionResult } = + await encryptBasicPayload(cookieID, notification); + return { notification: encryptionResult, encryptionOrder }; +} + function prepareEncryptedAPNsNotifications( devices: $ReadOnlyArray, notification: apn.Notification, @@ -390,6 +418,25 @@ return Promise.all(notificationPromises); } +function prepareEncryptedWNSNotifications( + devices: $ReadOnlyArray, + notification: PlainTextWNSNotification, +): Promise< + $ReadOnlyArray<{ + +deviceToken: string, + +notification: WNSNotification, + +encryptionOrder?: number, + }>, +> { + const notificationPromises = devices.map( + async ({ deviceToken, cookieID }) => { + const notif = await encryptWNSNotification(cookieID, notification); + return { ...notif, deviceToken }; + }, + ); + return Promise.all(notificationPromises); +} + async function encryptBlobPayload(payload: string): Promise<{ +encryptionKey: string, +encryptedPayload: Blob, @@ -422,5 +469,6 @@ prepareEncryptedAndroidNotifications, prepareEncryptedAndroidNotificationRescinds, prepareEncryptedWebNotifications, + prepareEncryptedWNSNotifications, encryptBlobPayload, }; diff --git a/lib/types/notif-types.js b/lib/types/notif-types.js --- a/lib/types/notif-types.js +++ b/lib/types/notif-types.js @@ -49,10 +49,19 @@ | PlainTextWebNotification | EncryptedWebNotification; -export type WNSNotification = { +export type PlainTextWNSNotification = { +body: string, +prefix?: string, +title: string, +unreadCount: number, +threadID: string, + +encryptionFailed?: '1', }; + +export type EncryptedWNSNotification = { + +encryptedPayload: string, +}; + +export type WNSNotification = + | PlainTextWNSNotification + | EncryptedWNSNotification;