diff --git a/keyserver/src/push/crypto.js b/keyserver/src/push/crypto.js index cef2af9ad..ca1b69c80 100644 --- a/keyserver/src/push/crypto.js +++ b/keyserver/src/push/crypto.js @@ -1,78 +1,128 @@ // @flow import apn from '@parse/node-apn'; import invariant from 'invariant'; +import type { AndroidNotification } from './types.js'; import { encryptAndUpdateOlmSession } from '../updaters/olm-session-updater.js'; async function encryptIOSNotification( cookieID: string, notification: apn.Notification, ): Promise { invariant( !notification.collapseId, 'Collapsible notifications encryption currently not implemented', ); const encryptedNotification = new apn.Notification(); encryptedNotification.id = notification.id; encryptedNotification.payload.id = notification.id; encryptedNotification.topic = notification.topic; encryptedNotification.sound = notification.aps.sound; encryptedNotification.pushType = 'alert'; encryptedNotification.mutableContent = true; const { id, ...payloadSansId } = notification.payload; const unencryptedPayload = { ...payloadSansId, badge: notification.aps.badge.toString(), merged: notification.body, }; let encryptedSerializedPayload; try { const unencryptedSerializedPayload = JSON.stringify(unencryptedPayload); const { serializedPayload } = await encryptAndUpdateOlmSession( cookieID, 'notifications', { serializedPayload: unencryptedSerializedPayload, }, ); encryptedSerializedPayload = serializedPayload; } catch (e) { console.log('Notification encryption failed: ' + e); encryptedNotification.body = notification.body; encryptedNotification.threadId = notification.payload.threadID; invariant( typeof notification.aps.badge === 'number', 'Unencrypted notification must have badge as a number', ); encryptedNotification.badge = notification.aps.badge; encryptedNotification.payload = { ...encryptedNotification.payload, ...notification.payload, encryptionFailed: 1, }; return encryptedNotification; } encryptedNotification.payload.encryptedPayload = encryptedSerializedPayload.body; return encryptedNotification; } +async function encryptAndroidNotification( + cookieID: string, + notification: AndroidNotification, +): Promise { + const { id, badgeOnly, ...unencryptedPayload } = notification.data; + const encryptedNotification = { data: { id, badgeOnly } }; + + let encryptedSerializedPayload; + try { + const unencryptedSerializedPayload = JSON.stringify(unencryptedPayload); + const { serializedPayload } = await encryptAndUpdateOlmSession( + cookieID, + 'notifications', + { + serializedPayload: unencryptedSerializedPayload, + }, + ); + encryptedSerializedPayload = serializedPayload; + } catch (e) { + console.log('Notification encryption failed: ' + e); + + encryptedNotification.data = { + ...unencryptedPayload, + ...encryptedNotification.data, + encryptionFailed: '1', + }; + return encryptedNotification; + } + + encryptedNotification.data = { + ...encryptedNotification.data, + encryptedPayload: encryptedSerializedPayload.body, + }; + return encryptedNotification; +} + function prepareEncryptedIOSNotifications( cookieIDs: $ReadOnlyArray, notification: apn.Notification, ): Promise> { const notificationPromises = cookieIDs.map(cookieID => encryptIOSNotification(cookieID, notification), ); return Promise.all(notificationPromises); } -export { prepareEncryptedIOSNotifications }; +function prepareEncryptedAndroidNotifications( + cookieIDs: $ReadOnlyArray, + notification: AndroidNotification, +): Promise> { + const notificationPromises = cookieIDs.map(cookieID => + encryptAndroidNotification(cookieID, notification), + ); + return Promise.all(notificationPromises); +} + +export { + prepareEncryptedIOSNotifications, + prepareEncryptedAndroidNotifications, +}; diff --git a/keyserver/src/push/types.js b/keyserver/src/push/types.js index 11debb9e5..7f2d2c60b 100644 --- a/keyserver/src/push/types.js +++ b/keyserver/src/push/types.js @@ -1,8 +1,16 @@ // @flow import apn from '@parse/node-apn'; export type TargetedAPNsNotification = { +notification: apn.Notification, +deviceToken: string, }; + +export type AndroidNotification = { + +data: { + +id?: string, + +badgeOnly?: string, + +[string]: string, + }, +};