Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3348997
D12396.id42025.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
20 KB
Referenced Files
None
Subscribers
None
D12396.id42025.diff
View Options
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
@@ -1,6 +1,5 @@
// @flow
-import type { EncryptResult } from '@commapp/olm';
import apn from '@parse/node-apn';
import crypto from 'crypto';
import invariant from 'invariant';
@@ -18,16 +17,17 @@
AndroidNotificationRescind,
NotificationTargetDevice,
SenderDeviceDescriptor,
+ EncryptedNotifUtilsAPI,
} from 'lib/types/notif-types.js';
import { toBase64URL } from 'lib/utils/base64.js';
-import { encryptAndUpdateOlmSession } from '../updaters/olm-session-updater.js';
import { encrypt, generateKey } from '../utils/aes-crypto-utils.js';
import { getOlmUtility } from '../utils/olm-utils.js';
async function encryptAPNsNotification(
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
cookieID: string,
- senderDeviceID: SenderDeviceDescriptor,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
notification: apn.Notification,
codeVersion?: ?number,
notificationSizeValidator?: apn.Notification => boolean,
@@ -71,33 +71,26 @@
let dbPersistCondition;
if (notificationSizeValidator) {
- dbPersistCondition = ({
- serializedPayload,
- }: {
- +[string]: EncryptResult,
- }) => {
+ dbPersistCondition = (serializedPayload: string) => {
const notifCopy = _cloneDeep(encryptedNotification);
- notifCopy.payload.encryptedPayload = serializedPayload.body;
+ notifCopy.payload.encryptedPayload = serializedPayload;
return notificationSizeValidator(notifCopy);
};
}
const {
- encryptedMessages: { serializedPayload },
- dbPersistConditionViolated,
+ encryptedData: serializedPayload,
+ sizeLimitViolated: dbPersistConditionViolated,
encryptionOrder,
- } = await encryptAndUpdateOlmSession(
+ } = await encryptedNotifUtilsAPI.encryptSerializedNotifPayload(
cookieID,
- 'notifications',
- {
- serializedPayload: unencryptedSerializedPayload,
- },
+ unencryptedSerializedPayload,
dbPersistCondition,
);
encryptedNotification.payload.encryptedPayload = serializedPayload.body;
encryptedNotification.payload = {
- ...senderDeviceID,
...encryptedNotification.payload,
+ ...senderDeviceDescriptor,
};
if (codeVersion && codeVersion >= 254 && codeVersion % 2 === 0) {
@@ -140,8 +133,9 @@
}
async function encryptAndroidNotificationPayload<T>(
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
cookieID: string,
- senderDeviceID: SenderDeviceDescriptor,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
unencryptedPayload: T,
payloadSizeValidator?: (
T | $ReadOnly<{ ...SenderDeviceDescriptor, +encryptedPayload: string }>,
@@ -166,33 +160,27 @@
let dbPersistCondition;
if (payloadSizeValidator) {
- dbPersistCondition = ({
- serializedPayload,
- }: {
- +[string]: EncryptResult,
- }) =>
+ dbPersistCondition = (serializedPayload: string) =>
payloadSizeValidator({
- encryptedPayload: serializedPayload.body,
- ...senderDeviceID,
+ encryptedPayload: serializedPayload,
+ ...senderDeviceDescriptor,
});
}
const {
- encryptedMessages: { serializedPayload },
- dbPersistConditionViolated,
+ encryptedData: serializedPayload,
+ sizeLimitViolated: dbPersistConditionViolated,
encryptionOrder,
- } = await encryptAndUpdateOlmSession(
+ } = await encryptedNotifUtilsAPI.encryptSerializedNotifPayload(
cookieID,
- 'notifications',
- {
- serializedPayload: unencryptedSerializedPayload,
- },
+ unencryptedSerializedPayload,
dbPersistCondition,
);
+
return {
resultPayload: {
encryptedPayload: serializedPayload.body,
- ...senderDeviceID,
+ ...senderDeviceDescriptor,
},
payloadSizeExceeded: !!dbPersistConditionViolated,
encryptionOrder,
@@ -213,7 +201,8 @@
}
async function encryptAndroidVisualNotification(
- senderDeviceID: SenderDeviceDescriptor,
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
cookieID: string,
notification: AndroidVisualNotification,
notificationSizeValidator?: AndroidVisualNotification => boolean,
@@ -249,8 +238,9 @@
}
const { resultPayload, payloadSizeExceeded, encryptionOrder } =
await encryptAndroidNotificationPayload(
+ encryptedNotifUtilsAPI,
cookieID,
- senderDeviceID,
+ senderDeviceDescriptor,
unencryptedPayload,
payloadSizeValidator,
);
@@ -267,8 +257,9 @@
}
async function encryptAndroidSilentNotification(
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
cookieID: string,
- senderDeviceID: SenderDeviceDescriptor,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
notification: AndroidNotificationRescind | AndroidBadgeOnlyNotification,
): Promise<AndroidNotificationRescind | AndroidBadgeOnlyNotification> {
// We don't validate payload size for rescind
@@ -276,8 +267,9 @@
// never exceed any FCM limit
const { ...unencryptedPayload } = notification.data;
const { resultPayload } = await encryptAndroidNotificationPayload(
+ encryptedNotifUtilsAPI,
cookieID,
- senderDeviceID,
+ senderDeviceDescriptor,
unencryptedPayload,
);
if (resultPayload.encryptedPayload) {
@@ -300,8 +292,9 @@
}
async function encryptBasicPayload<T>(
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
cookieID: string,
- senderDeviceID: SenderDeviceDescriptor,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
basicPayload: T,
): Promise<
| $ReadOnly<{
@@ -318,15 +311,14 @@
}
try {
- const {
- encryptedMessages: { serializedPayload },
- encryptionOrder,
- } = await encryptAndUpdateOlmSession(cookieID, 'notifications', {
- serializedPayload: unencryptedSerializedPayload,
- });
+ const { encryptedData: serializedPayload, encryptionOrder } =
+ await encryptedNotifUtilsAPI.encryptSerializedNotifPayload(
+ cookieID,
+ unencryptedSerializedPayload,
+ );
return {
- ...senderDeviceID,
+ ...senderDeviceDescriptor,
encryptedPayload: serializedPayload.body,
encryptionOrder,
};
@@ -340,15 +332,17 @@
}
async function encryptWebNotification(
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
cookieID: string,
- senderDeviceID: SenderDeviceDescriptor,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
notification: PlainTextWebNotification,
): Promise<{ +notification: WebNotification, +encryptionOrder?: number }> {
const { id, ...payloadSansId } = notification;
const { encryptionOrder, ...encryptionResult } =
await encryptBasicPayload<PlainTextWebNotificationPayload>(
+ encryptedNotifUtilsAPI,
cookieID,
- senderDeviceID,
+ senderDeviceDescriptor,
payloadSansId,
);
@@ -359,14 +353,16 @@
}
async function encryptWNSNotification(
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
cookieID: string,
- senderDeviceID: SenderDeviceDescriptor,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
notification: PlainTextWNSNotification,
): Promise<{ +notification: WNSNotification, +encryptionOrder?: number }> {
const { encryptionOrder, ...encryptionResult } =
await encryptBasicPayload<PlainTextWNSNotification>(
+ encryptedNotifUtilsAPI,
cookieID,
- senderDeviceID,
+ senderDeviceDescriptor,
notification,
);
return {
@@ -376,7 +372,8 @@
}
function prepareEncryptedAPNsNotifications(
- senderDeviceID: SenderDeviceDescriptor,
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
devices: $ReadOnlyArray<NotificationTargetDevice>,
notification: apn.Notification,
codeVersion?: ?number,
@@ -394,8 +391,9 @@
const notificationPromises = devices.map(
async ({ cookieID, deviceToken, blobHolder }) => {
const notif = await encryptAPNsNotification(
+ encryptedNotifUtilsAPI,
cookieID,
- senderDeviceID,
+ senderDeviceDescriptor,
notification,
codeVersion,
notificationSizeValidator,
@@ -408,7 +406,8 @@
}
function prepareEncryptedIOSNotificationRescind(
- senderDeviceID: SenderDeviceDescriptor,
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
devices: $ReadOnlyArray<NotificationTargetDevice>,
notification: apn.Notification,
codeVersion?: ?number,
@@ -422,8 +421,9 @@
const notificationPromises = devices.map(
async ({ deviceToken, cookieID }) => {
const { notification: notif } = await encryptAPNsNotification(
+ encryptedNotifUtilsAPI,
cookieID,
- senderDeviceID,
+ senderDeviceDescriptor,
notification,
codeVersion,
);
@@ -434,7 +434,8 @@
}
function prepareEncryptedAndroidVisualNotifications(
- senderDeviceID: SenderDeviceDescriptor,
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
devices: $ReadOnlyArray<NotificationTargetDevice>,
notification: AndroidVisualNotification,
notificationSizeValidator?: (
@@ -452,7 +453,8 @@
const notificationPromises = devices.map(
async ({ deviceToken, cookieID, blobHolder }) => {
const notif = await encryptAndroidVisualNotification(
- senderDeviceID,
+ encryptedNotifUtilsAPI,
+ senderDeviceDescriptor,
cookieID,
notification,
notificationSizeValidator,
@@ -465,7 +467,8 @@
}
function prepareEncryptedAndroidSilentNotifications(
- senderDeviceID: SenderDeviceDescriptor,
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
devices: $ReadOnlyArray<NotificationTargetDevice>,
notification: AndroidNotificationRescind | AndroidBadgeOnlyNotification,
): Promise<
@@ -479,8 +482,9 @@
const notificationPromises = devices.map(
async ({ deviceToken, cookieID }) => {
const notif = await encryptAndroidSilentNotification(
+ encryptedNotifUtilsAPI,
cookieID,
- senderDeviceID,
+ senderDeviceDescriptor,
notification,
);
return { deviceToken, cookieID, notification: notif };
@@ -490,7 +494,8 @@
}
function prepareEncryptedWebNotifications(
- senderDeviceID: SenderDeviceDescriptor,
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
devices: $ReadOnlyArray<NotificationTargetDevice>,
notification: PlainTextWebNotification,
): Promise<
@@ -503,8 +508,9 @@
const notificationPromises = devices.map(
async ({ deviceToken, cookieID }) => {
const notif = await encryptWebNotification(
+ encryptedNotifUtilsAPI,
cookieID,
- senderDeviceID,
+ senderDeviceDescriptor,
notification,
);
return { ...notif, deviceToken };
@@ -514,7 +520,8 @@
}
function prepareEncryptedWNSNotifications(
- senderDeviceID: SenderDeviceDescriptor,
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
devices: $ReadOnlyArray<NotificationTargetDevice>,
notification: PlainTextWNSNotification,
): Promise<
@@ -527,8 +534,9 @@
const notificationPromises = devices.map(
async ({ deviceToken, cookieID }) => {
const notif = await encryptWNSNotification(
+ encryptedNotifUtilsAPI,
cookieID,
- senderDeviceID,
+ senderDeviceDescriptor,
notification,
);
return { ...notif, deviceToken };
diff --git a/keyserver/src/push/encrypted-notif-utils-api.js b/keyserver/src/push/encrypted-notif-utils-api.js
new file mode 100644
--- /dev/null
+++ b/keyserver/src/push/encrypted-notif-utils-api.js
@@ -0,0 +1,49 @@
+// @flow
+
+import type { EncryptResult } from '@commapp/olm';
+
+import type { EncryptedNotifUtilsAPI } from 'lib/types/notif-types.js';
+
+import { blobServiceUpload } from './utils.js';
+import { encryptAndUpdateOlmSession } from '../updaters/olm-session-updater.js';
+
+const encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI = {
+ encryptSerializedNotifPayload: async (
+ cryptoID: string,
+ unencryptedPayload: string,
+ encryptedPayloadSizeValidator?: (encryptedPayload: string) => boolean,
+ ) => {
+ let dbPersistCondition;
+ if (encryptedPayloadSizeValidator) {
+ dbPersistCondition = ({
+ serializedPayload,
+ }: {
+ +[string]: EncryptResult,
+ }) => encryptedPayloadSizeValidator(serializedPayload.body);
+ }
+
+ const {
+ encryptedMessages: { serializedPayload },
+ dbPersistConditionViolated,
+ encryptionOrder,
+ } = await encryptAndUpdateOlmSession(
+ cryptoID,
+ 'notifications',
+ {
+ serializedPayload: unencryptedPayload,
+ },
+ dbPersistCondition,
+ );
+
+ return {
+ encryptedData: serializedPayload,
+ sizeLimitViolated: dbPersistConditionViolated,
+ encryptionOrder,
+ };
+ },
+ uploadLargeNotifPayload: blobServiceUpload,
+ getNotifByteSize: (serializedPayload: string) =>
+ Buffer.byteLength(serializedPayload),
+};
+
+export default encryptedNotifUtilsAPI;
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
@@ -10,6 +10,7 @@
NotificationTargetDevice,
TargetedAndroidNotification,
SenderDeviceDescriptor,
+ EncryptedNotifUtilsAPI,
} from 'lib/types/notif-types.js';
import { threadSubscriptions } from 'lib/types/subscription-types.js';
import { threadPermissions } from 'lib/types/thread-permission-types.js';
@@ -20,6 +21,7 @@
prepareEncryptedAndroidSilentNotifications,
prepareEncryptedIOSNotificationRescind,
} from './crypto.js';
+import encryptedNotifUtilsAPI from './encrypted-notif-utils-api.js';
import { getAPNsNotificationTopic } from './providers.js';
import type { TargetedAPNsNotification } from './types.js';
import {
@@ -275,12 +277,14 @@
}
async function conditionallyEncryptNotification<T>(
- senderDeviceID: SenderDeviceDescriptor,
+ encryptedNotifUtilsAPIInstance: EncryptedNotifUtilsAPI,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
notification: T,
codeVersion: ?number,
devices: $ReadOnlyArray<NotificationTargetDevice>,
encryptCallback: (
- senderDeviceID: SenderDeviceDescriptor,
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
devices: $ReadOnlyArray<NotificationTargetDevice>,
notification: T,
codeVersion?: ?number,
@@ -301,7 +305,8 @@
}));
}
const notifications = await encryptCallback(
- senderDeviceID,
+ encryptedNotifUtilsAPI,
+ senderDeviceDescriptor,
devices,
notification,
codeVersion,
@@ -354,6 +359,7 @@
},
};
return await conditionallyEncryptNotification(
+ encryptedNotifUtilsAPI,
{ keyserverID },
notification,
codeVersion,
@@ -383,6 +389,7 @@
},
};
const targetedRescinds = await conditionallyEncryptNotification(
+ encryptedNotifUtilsAPI,
{ keyserverID },
notification,
codeVersion,
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
@@ -56,6 +56,7 @@
prepareEncryptedWebNotifications,
prepareEncryptedWNSNotifications,
} from './crypto.js';
+import encryptedNotifUtilsAPI from './encrypted-notif-utils-api.js';
import { getAPNsNotificationTopic } from './providers.js';
import { rescindPushNotifs } from './rescind.js';
import type { TargetedAPNsNotification } from './types.js';
@@ -70,7 +71,6 @@
wnsMaxNotificationPayloadByteSize,
wnsPush,
type WNSPushError,
- blobServiceUpload,
} from './utils.js';
import createIDs from '../creators/id-creator.js';
import { createUpdates } from '../creators/update-creator.js';
@@ -1032,6 +1032,7 @@
if (platformDetails.platform === 'macos') {
const macOSNotifsWithoutMessageInfos =
await prepareEncryptedAPNsNotifications(
+ encryptedNotifUtilsAPI,
{ keyserverID },
devices,
notification,
@@ -1046,6 +1047,7 @@
}
const notifsWithMessageInfos = await prepareEncryptedAPNsNotifications(
+ encryptedNotifUtilsAPI,
{ keyserverID },
devices,
copyWithMessageInfos,
@@ -1083,7 +1085,7 @@
let blobHash, blobHolders, encryptionKey, blobUploadError;
if (canQueryBlobService) {
({ blobHash, blobHolders, encryptionKey, blobUploadError } =
- await blobServiceUpload(
+ await encryptedNotifUtilsAPI.uploadLargeNotifPayload(
copyWithMessageInfos.compile(),
devicesWithExcessiveSizeNoHolders.length,
));
@@ -1116,6 +1118,7 @@
}
const notifsWithoutMessageInfos = await prepareEncryptedAPNsNotifications(
+ encryptedNotifUtilsAPI,
{ keyserverID },
devicesWithExcessiveSize,
notification,
@@ -1241,8 +1244,9 @@
const priority = 'high';
if (!shouldBeEncrypted) {
const notificationToSend =
- Buffer.byteLength(JSON.stringify(copyWithMessageInfos)) <=
- fcmMaxNotificationPayloadByteSize
+ encryptedNotifUtilsAPI.getNotifByteSize(
+ JSON.stringify(copyWithMessageInfos),
+ ) <= fcmMaxNotificationPayloadByteSize
? copyWithMessageInfos
: notification;
@@ -1257,12 +1261,14 @@
const serializedNotif = JSON.stringify(notif);
return (
!serializedNotif ||
- Buffer.byteLength(serializedNotif) <= fcmMaxNotificationPayloadByteSize
+ encryptedNotifUtilsAPI.getNotifByteSize(serializedNotif) <=
+ fcmMaxNotificationPayloadByteSize
);
};
const notifsWithMessageInfos =
await prepareEncryptedAndroidVisualNotifications(
+ encryptedNotifUtilsAPI,
{ keyserverID },
devices,
copyWithMessageInfos,
@@ -1291,7 +1297,7 @@
let blobHash, blobHolders, encryptionKey, blobUploadError;
if (canQueryBlobService) {
({ blobHash, blobHolders, encryptionKey, blobUploadError } =
- await blobServiceUpload(
+ await encryptedNotifUtilsAPI.uploadLargeNotifPayload(
JSON.stringify(copyWithMessageInfos.data),
devicesWithExcessiveSizeNoHolders.length,
));
@@ -1325,6 +1331,7 @@
const notifsWithoutMessageInfos =
await prepareEncryptedAndroidVisualNotifications(
+ encryptedNotifUtilsAPI,
{ keyserverID },
devicesWithExcessiveSize,
notification,
@@ -1396,6 +1403,7 @@
}
return prepareEncryptedWebNotifications(
+ encryptedNotifUtilsAPI,
{ keyserverID },
devices,
notification,
@@ -1434,7 +1442,7 @@
};
if (
- Buffer.byteLength(JSON.stringify(notification)) >
+ encryptedNotifUtilsAPI.getNotifByteSize(JSON.stringify(notification)) >
wnsMaxNotificationPayloadByteSize
) {
console.warn('WNS notification exceeds size limit');
@@ -1451,6 +1459,7 @@
}));
}
return await prepareEncryptedWNSNotifications(
+ encryptedNotifUtilsAPI,
{ keyserverID },
devices,
notification,
@@ -1807,6 +1816,7 @@
let targetedNotifications: $ReadOnlyArray<TargetedAPNsNotification>;
if (codeVersion > 222) {
const notificationsArray = await prepareEncryptedAPNsNotifications(
+ encryptedNotifUtilsAPI,
{ keyserverID },
deviceInfos,
notification,
@@ -1859,6 +1869,7 @@
if (codeVersion > 222) {
const notificationsArray =
await prepareEncryptedAndroidSilentNotifications(
+ encryptedNotifUtilsAPI,
{ keyserverID },
deviceInfos,
notification,
@@ -1917,6 +1928,7 @@
let targetedNotifications: $ReadOnlyArray<TargetedAPNsNotification>;
if (shouldBeEncrypted) {
const notificationsArray = await prepareEncryptedAPNsNotifications(
+ encryptedNotifUtilsAPI,
{ keyserverID },
deviceInfos,
notification,
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
@@ -1,5 +1,6 @@
// @flow
+import type { EncryptResult } from '@commapp/olm';
import t, { type TInterface } from 'tcomb';
import type { EntityText, ThreadEntity } from '../utils/entity-text.js';
@@ -185,3 +186,27 @@
+deviceToken: string,
+blobHolder?: string,
};
+
+export type EncryptedNotifUtilsAPI = {
+ +encryptSerializedNotifPayload: (
+ cryptoID: string,
+ unencryptedPayload: string,
+ encryptedPayloadSizeValidator?: (encryptedPayload: string) => boolean,
+ ) => Promise<{
+ +encryptedData: EncryptResult,
+ +sizeLimitViolated?: boolean,
+ +encryptionOrder?: number,
+ }>,
+ +uploadLargeNotifPayload: (
+ payload: string,
+ numberOfHolders: number,
+ ) => Promise<
+ | {
+ +blobHolders: $ReadOnlyArray<string>,
+ +blobHash: string,
+ +encryptionKey: string,
+ }
+ | { +blobUploadError: string },
+ >,
+ +getNotifByteSize: (serializedNotification: string) => number,
+};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 23, 4:43 PM (19 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2570552
Default Alt Text
D12396.id42025.diff (20 KB)
Attached To
Mode
D12396: Introduce EncryptedNotifUtilsAPI and implement it on the keyserver
Attached
Detach File
Event Timeline
Log In to Comment