Page MenuHomePhorge

D8377.1768409022.diff
No OneTemporary

Size
10 KB
Referenced Files
None
Subscribers
None

D8377.1768409022.diff

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
@@ -3,11 +3,21 @@
import apn from '@parse/node-apn';
import invariant from 'invariant';
+import { NEXT_CODE_VERSION } from 'lib/shared/version-utils.js';
import { threadSubscriptions } from 'lib/types/subscription-types.js';
import { threadPermissions } from 'lib/types/thread-permission-types.js';
import { promiseAll } from 'lib/utils/promises.js';
+import {
+ prepareEncryptedAndroidNotificationRescinds,
+ prepareEncryptedIOSNotifications,
+} from './crypto.js';
import { getAPNsNotificationTopic } from './providers.js';
+import type {
+ NotificationTargetDevice,
+ TargetedAndroidNotification,
+ TargetedAPNsNotification,
+} from './types.js';
import { apnPush, fcmPush } from './utils.js';
import createIDs from '../creators/id-creator.js';
import { dbQuery, SQL } from '../database/database.js';
@@ -37,85 +47,90 @@
fetchQuery.append(SQL` GROUP BY n.id, m.user`);
const [fetchResult] = await dbQuery(fetchQuery);
+ const allDeviceTokens = [];
+ for (const row of fetchResult) {
+ const rawDelivery = JSON.parse(row.delivery);
+ const deliveries = Array.isArray(rawDelivery) ? rawDelivery : [rawDelivery];
+
+ for (const delivery of deliveries) {
+ if (delivery.iosID || delivery.deviceType === 'ios') {
+ const deviceTokens = delivery.iosDeviceTokens ?? delivery.deviceTokens;
+ allDeviceTokens.push(...deviceTokens);
+ } else if (delivery.androidID || delivery.deviceType === 'android') {
+ const deviceTokens =
+ delivery.androidDeviceTokens ?? delivery.deviceTokens;
+ allDeviceTokens.push(deviceTokens);
+ }
+ }
+ }
+ const deviceTokenToCookieID = await getDeviceTokenToCookieID(allDeviceTokens);
+
const deliveryPromises = {};
const notifInfo = {};
const rescindedIDs = [];
+
for (const row of fetchResult) {
const rawDelivery = JSON.parse(row.delivery);
const deliveries = Array.isArray(rawDelivery) ? rawDelivery : [rawDelivery];
const id = row.id.toString();
const threadID = row.thread.toString();
+
notifInfo[id] = {
userID: row.user.toString(),
threadID,
messageID: row.message.toString(),
};
+
for (const delivery of deliveries) {
- if (delivery.iosID && delivery.iosDeviceTokens) {
- // Old iOS
- const notification = prepareIOSNotification(
- delivery.iosID,
- row.unread_count,
- threadID,
- );
- const targetedNotifications = delivery.iosDeviceTokens.map(
- deviceToken => ({ deviceToken, notification }),
- );
- deliveryPromises[id] = apnPush({
- targetedNotifications,
- platformDetails: { platform: 'ios' },
- });
- } else if (delivery.androidID) {
- // Old Android
- const notification = prepareAndroidNotification(
- row.collapse_key ? row.collapse_key : id,
- row.unread_count,
- threadID,
- );
- deliveryPromises[id] = fcmPush({
- targetedNotifications: delivery.androidDeviceTokens.map(
- deviceToken => ({
- deviceToken,
- notification,
- }),
- ),
- codeVersion: null,
- });
- } else if (delivery.deviceType === 'ios') {
- // New iOS
- const { iosID, deviceTokens, codeVersion } = delivery;
- const notification = prepareIOSNotification(
- iosID,
- row.unread_count,
- threadID,
- codeVersion,
- );
- const targetedNotifications = deviceTokens.map(deviceToken => ({
+ if (delivery.iosID) {
+ const deviceTokens = delivery.iosDeviceTokens ?? delivery.deviceTokens;
+ const devices = deviceTokens.map(deviceToken => ({
deviceToken,
- notification,
+ cookieID: deviceTokenToCookieID[deviceToken],
}));
- deliveryPromises[id] = apnPush({
- targetedNotifications,
- platformDetails: { platform: 'ios', codeVersion },
- });
- } else if (delivery.deviceType === 'android') {
- // New Android
- const { deviceTokens, codeVersion } = delivery;
- const notification = prepareAndroidNotification(
- row.collapse_key ? row.collapse_key : id,
- row.unread_count,
- threadID,
- );
- deliveryPromises[id] = fcmPush({
- targetedNotifications: deviceTokens.map(deviceToken => ({
- deviceToken,
- notification,
- })),
- codeVersion,
- });
+
+ const deliveryPromise = (async () => {
+ const targetedNotifications = await prepareIOSNotification(
+ delivery.iosID,
+ row.unread_count,
+ threadID,
+ delivery.codeVersion,
+ devices,
+ );
+
+ return await apnPush({
+ targetedNotifications,
+ platformDetails: {
+ platform: 'ios',
+ codeVersion: delivery.codeVersion,
+ },
+ });
+ })();
+ deliveryPromises[id] = deliveryPromise;
+ } else if (delivery.androidID || delivery.deviceType === 'android') {
+ const deviceTokens =
+ delivery.androidDeviceTokens ?? delivery.deviceTokens;
+ const devices = deviceTokens.map(deviceToken => ({
+ deviceToken,
+ cookieID: deviceTokenToCookieID[deviceToken],
+ }));
+ const deliveryPromise = (async () => {
+ const targetedNotifications = await prepareAndroidNotification(
+ row.collapse_key ? row.collapse_key : id,
+ row.unread_count,
+ threadID,
+ delivery.codeVersion,
+ devices,
+ );
+ return await fcmPush({
+ targetedNotifications,
+ codeVersion: delivery.codeVersion,
+ });
+ })();
+ deliveryPromises[id] = deliveryPromise;
}
}
- rescindedIDs.push(row.id);
+ rescindedIDs.push(id);
}
const numRescinds = Object.keys(deliveryPromises).length;
@@ -165,12 +180,32 @@
}
}
-function prepareIOSNotification(
+async function getDeviceTokenToCookieID(
+ deviceTokens,
+): Promise<{ +[string]: string }> {
+ if (deviceTokens.length === 0) {
+ return {};
+ }
+
+ const deviceTokenToCookieID = {};
+ const fetchCookiesQuery = SQL`
+ SELECT id, device_token FROM cookies
+ WHERE device_token IN (${deviceTokens})
+ `;
+ const [fetchResult] = await dbQuery(fetchCookiesQuery);
+ for (const row of fetchResult) {
+ deviceTokenToCookieID[row.device_token.toString()] = row.id.toString();
+ }
+ return deviceTokenToCookieID;
+}
+
+async function prepareIOSNotification(
iosID: string,
unreadCount: number,
threadID: string,
codeVersion: ?number,
-): apn.Notification {
+ devices: $ReadOnlyArray<NotificationTargetDevice>,
+): Promise<$ReadOnlyArray<TargetedAPNsNotification>> {
const notification = new apn.Notification();
notification.topic = getAPNsNotificationTopic({
platform: 'ios',
@@ -203,15 +238,35 @@
notificationId: iosID,
},
};
- return notification;
+
+ const deviceTokens = devices.map(({ deviceToken }) => deviceToken);
+ const shouldBeEncrypted = codeVersion && codeVersion > NEXT_CODE_VERSION;
+
+ if (!shouldBeEncrypted) {
+ return deviceTokens.map(deviceToken => ({
+ notification,
+ deviceToken,
+ }));
+ }
+ const cookieIDs = devices.map(({ cookieID }) => cookieID);
+ const notifications = await prepareEncryptedIOSNotifications(
+ cookieIDs,
+ notification,
+ );
+ return notifications.map((notif, idx) => ({
+ notification: notif,
+ deviceToken: deviceTokens[idx],
+ }));
}
-function prepareAndroidNotification(
+async function prepareAndroidNotification(
notifID: string,
unreadCount: number,
threadID: string,
-): Object {
- return {
+ codeVersion: ?number,
+ devices: $ReadOnlyArray<NotificationTargetDevice>,
+): Promise<$ReadOnlyArray<TargetedAndroidNotification>> {
+ const notification = {
data: {
badge: unreadCount.toString(),
rescind: 'true',
@@ -220,6 +275,23 @@
threadID,
},
};
+ const deviceTokens = devices.map(({ deviceToken }) => deviceToken);
+ const shouldBeEncrypted = codeVersion && codeVersion > NEXT_CODE_VERSION;
+ if (!shouldBeEncrypted) {
+ return deviceTokens.map(deviceToken => ({
+ notification,
+ deviceToken,
+ }));
+ }
+ const cookieIDs = devices.map(({ cookieID }) => cookieID);
+ const notifications = await prepareEncryptedAndroidNotificationRescinds(
+ cookieIDs,
+ notification,
+ );
+ return notifications.map((notif, idx) => ({
+ notification: notif,
+ deviceToken: deviceTokens[idx],
+ }));
}
export { rescindPushNotifs };
diff --git a/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java b/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java
--- a/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java
+++ b/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java
@@ -78,12 +78,7 @@
@Override
public void onMessageReceived(RemoteMessage message) {
- String rescind = message.getData().get(RESCIND_KEY);
- if ("true".equals(rescind) &&
- android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
- handleNotificationRescind(message);
- }
-
+ Log.w("COMM", "Received notification");
if (message.getData().get(ENCRYPTED_PAYLOAD_KEY) != null) {
try {
message = this.decryptRemoteMessage(message);
@@ -103,6 +98,16 @@
"Received unencrypted notification for client with existing olm session for notifications");
}
+ String rescind = message.getData().get(RESCIND_KEY);
+ Log.w("COMM", "Received rescind with rescind: " + rescind);
+ if ("true".equals(rescind) &&
+ android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
+ Log.w(
+ "COMM",
+ "Received rescind with id: " + message.getData().get(RESCIND_ID_KEY));
+ handleNotificationRescind(message);
+ }
+
String badge = message.getData().get(BADGE_KEY);
if (badge != null) {
try {

File Metadata

Mime Type
text/plain
Expires
Wed, Jan 14, 4:43 PM (8 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5932922
Default Alt Text
D8377.1768409022.diff (10 KB)

Event Timeline