From 0bb13322a12de2afc8e5fe518e81795f1be3a572 Mon Sep 17 00:00:00 2001 From: Sam Peters Date: Tue, 16 Jan 2024 15:53:40 -0600 Subject: [PATCH] feat(core): proxy notification filtering logic --- .env | 3 + core/api/.env | 3 + .../send-default-wallet-balance-to-users.ts | 2 +- .../app/admin/send-admin-push-notification.ts | 2 +- core/api/src/app/payments/send-intraledger.ts | 4 +- core/api/src/app/payments/send-lightning.ts | 6 +- core/api/src/app/payments/send-on-chain.ts | 4 +- .../app/payments/update-pending-payments.ts | 2 +- .../add-pending-on-chain-transaction.ts | 2 +- .../add-settled-on-chain-transaction.ts | 2 +- core/api/src/app/wallets/settle-payout-txn.ts | 2 +- .../wallets/update-single-pending-invoice.ts | 2 +- .../src/domain/notifications/index.types.d.ts | 4 +- core/api/src/services/notifications/index.ts | 10 ++-- .../notifications/push-notifications.ts | 59 +++++++++++++++---- .../push-notifications.types.d.ts | 2 +- .../notifications/notification.spec.ts | 18 ++---- .../notifications/push-notification.spec.ts | 28 --------- 18 files changed, 81 insertions(+), 74 deletions(-) delete mode 100644 core/api/test/legacy-integration/notifications/push-notification.spec.ts diff --git a/.env b/.env index 273934a056..dd3d6f96ac 100644 --- a/.env +++ b/.env @@ -70,6 +70,9 @@ export BRIA_HOST=${DOCKER_HOST_IP} export BRIA_PORT=2742 export BRIA_API_KEY="bria_dev_000000000000000000000" +export NOTIFICATIONS_HOST=${DOCKER_HOST_IP} +export NOTIFICATIONS_PORT=6685 + export PRICE_HOST=${DOCKER_HOST_IP} export PRICE_PORT=50051 diff --git a/core/api/.env b/core/api/.env index 0eaebedf7c..e33d1ae5e7 100644 --- a/core/api/.env +++ b/core/api/.env @@ -70,6 +70,9 @@ export BRIA_HOST=${DOCKER_HOST_IP} export BRIA_PORT=2742 export BRIA_API_KEY="bria_dev_000000000000000000000" +export NOTIFICATIONS_HOST=${DOCKER_HOST_IP} +export NOTIFICATIONS_PORT=6685 + export PRICE_HOST=${DOCKER_HOST_IP} export PRICE_PORT=50051 diff --git a/core/api/src/app/accounts/send-default-wallet-balance-to-users.ts b/core/api/src/app/accounts/send-default-wallet-balance-to-users.ts index 2b63c64e47..4b43a93676 100644 --- a/core/api/src/app/accounts/send-default-wallet-balance-to-users.ts +++ b/core/api/src/app/accounts/send-default-wallet-balance-to-users.ts @@ -64,7 +64,7 @@ export const sendDefaultWalletBalanceToAccounts = async () => { deviceTokens: user.deviceTokens, displayBalanceAmount: displayAmount, recipientLanguage: user.language, - notificationSettings: account.notificationSettings, + recipientUserId: user.id, }) if (result instanceof DeviceTokensNotRegisteredNotificationsServiceError) { diff --git a/core/api/src/app/admin/send-admin-push-notification.ts b/core/api/src/app/admin/send-admin-push-notification.ts index a5451acafe..0fb59126ed 100644 --- a/core/api/src/app/admin/send-admin-push-notification.ts +++ b/core/api/src/app/admin/send-admin-push-notification.ts @@ -44,7 +44,7 @@ export const sendAdminPushNotification = async ({ body, data, notificationCategory: checkedNotificationCategory, - notificationSettings: account.notificationSettings, + userId: kratosUserId, }) return success diff --git a/core/api/src/app/payments/send-intraledger.ts b/core/api/src/app/payments/send-intraledger.ts index 9f34b62fb9..d69ef50c3b 100644 --- a/core/api/src/app/payments/send-intraledger.ts +++ b/core/api/src/app/payments/send-intraledger.ts @@ -357,7 +357,7 @@ const executePaymentViaIntraledger = async < walletId: recipientWalletDescriptor.id, deviceTokens: recipientUser.deviceTokens, language: recipientUser.language, - notificationSettings: recipientAccount.notificationSettings, + userId: recipientUser.id, level: recipientAccount.level, }, transaction: recipientWalletTransaction, @@ -385,7 +385,7 @@ const executePaymentViaIntraledger = async < walletId: senderWalletDescriptor.id, deviceTokens: senderUser.deviceTokens, language: senderUser.language, - notificationSettings: senderAccount.notificationSettings, + userId: senderUser.id, level: senderAccount.level, }, transaction: senderWalletTransaction, diff --git a/core/api/src/app/payments/send-lightning.ts b/core/api/src/app/payments/send-lightning.ts index 650ac2d8a1..48b826ca0c 100644 --- a/core/api/src/app/payments/send-lightning.ts +++ b/core/api/src/app/payments/send-lightning.ts @@ -550,7 +550,7 @@ const executePaymentViaIntraledger = async < walletId: recipientWalletDescriptor.id, deviceTokens: recipientUser.deviceTokens, language: recipientUser.language, - notificationSettings: recipientAccount.notificationSettings, + userId: recipientUser.id, level: recipientAccount.level, }, transaction: recipientWalletTransaction, @@ -578,7 +578,7 @@ const executePaymentViaIntraledger = async < walletId: senderWalletDescriptor.id, deviceTokens: senderUser.deviceTokens, language: senderUser.language, - notificationSettings: senderAccount.notificationSettings, + userId: senderUser.id, level: senderAccount.level, }, transaction: senderWalletTransaction, @@ -819,7 +819,7 @@ const executePaymentViaLn = async ({ walletId: senderWallet.id, deviceTokens: senderUser.deviceTokens, language: senderUser.language, - notificationSettings: senderAccount.notificationSettings, + userId: senderUser.id, level: senderAccount.level, }, transaction: walletTransaction, diff --git a/core/api/src/app/payments/send-on-chain.ts b/core/api/src/app/payments/send-on-chain.ts index ac65bc5992..7074173276 100644 --- a/core/api/src/app/payments/send-on-chain.ts +++ b/core/api/src/app/payments/send-on-chain.ts @@ -440,7 +440,7 @@ const executePaymentViaIntraledger = async < walletId: recipientWallet.id, deviceTokens: recipientUser.deviceTokens, language: recipientUser.language, - notificationSettings: recipientAccount.notificationSettings, + userId: recipientUser.id, level: recipientAccount.level, }, transaction: recipientWalletTransaction, @@ -468,7 +468,7 @@ const executePaymentViaIntraledger = async < walletId: senderWalletDescriptor.id, deviceTokens: senderUser.deviceTokens, language: senderUser.language, - notificationSettings: senderAccount.notificationSettings, + userId: senderUser.id, level: senderAccount.level, }, transaction: senderWalletTransaction, diff --git a/core/api/src/app/payments/update-pending-payments.ts b/core/api/src/app/payments/update-pending-payments.ts index dde75fe9bf..6a8db3c969 100644 --- a/core/api/src/app/payments/update-pending-payments.ts +++ b/core/api/src/app/payments/update-pending-payments.ts @@ -281,7 +281,7 @@ const updatePendingPayment = wrapAsyncToRunInSpan({ walletId, deviceTokens: senderUser.deviceTokens, language: senderUser.language, - notificationSettings: senderAccount.notificationSettings, + userId: senderUser.id, level: senderAccount.level, }, transaction: walletTransaction, diff --git a/core/api/src/app/wallets/add-pending-on-chain-transaction.ts b/core/api/src/app/wallets/add-pending-on-chain-transaction.ts index 0b8f14e56a..1d2755922b 100644 --- a/core/api/src/app/wallets/add-pending-on-chain-transaction.ts +++ b/core/api/src/app/wallets/add-pending-on-chain-transaction.ts @@ -152,7 +152,7 @@ export const addPendingTransaction = async ({ walletId: wallet.id, deviceTokens: recipientUser.deviceTokens, language: recipientUser.language, - notificationSettings: account.notificationSettings, + userId: recipientUser.id, level: account.level, }, transaction: res, diff --git a/core/api/src/app/wallets/add-settled-on-chain-transaction.ts b/core/api/src/app/wallets/add-settled-on-chain-transaction.ts index 25e249ad60..3a03ab90bd 100644 --- a/core/api/src/app/wallets/add-settled-on-chain-transaction.ts +++ b/core/api/src/app/wallets/add-settled-on-chain-transaction.ts @@ -187,7 +187,7 @@ const addSettledTransactionBeforeFinally = async ({ walletId: wallet.id, deviceTokens: user.deviceTokens, language: user.language, - notificationSettings: account.notificationSettings, + userId: user.id, level: account.level, }, transaction: walletTransaction, diff --git a/core/api/src/app/wallets/settle-payout-txn.ts b/core/api/src/app/wallets/settle-payout-txn.ts index 79d4e0744c..a596306a0d 100644 --- a/core/api/src/app/wallets/settle-payout-txn.ts +++ b/core/api/src/app/wallets/settle-payout-txn.ts @@ -66,7 +66,7 @@ export const settlePayout = async ( walletId: wallet.id, deviceTokens: user.deviceTokens, language: user.language, - notificationSettings: account.notificationSettings, + userId: user.id, level: account.level, }, transaction: walletTransaction, diff --git a/core/api/src/app/wallets/update-single-pending-invoice.ts b/core/api/src/app/wallets/update-single-pending-invoice.ts index bdff3b618f..b746baa11e 100644 --- a/core/api/src/app/wallets/update-single-pending-invoice.ts +++ b/core/api/src/app/wallets/update-single-pending-invoice.ts @@ -317,7 +317,7 @@ const lockedUpdatePendingInvoiceSteps = async ({ walletId: recipientWalletDescriptor.id, deviceTokens: recipientUser.deviceTokens, language: recipientUser.language, - notificationSettings: recipientAccount.notificationSettings, + userId: recipientUser.id, level: recipientAccount.level, }, transaction: walletTransaction, diff --git a/core/api/src/domain/notifications/index.types.d.ts b/core/api/src/domain/notifications/index.types.d.ts index de31c422f7..343546dd69 100644 --- a/core/api/src/domain/notifications/index.types.d.ts +++ b/core/api/src/domain/notifications/index.types.d.ts @@ -7,7 +7,7 @@ type NotificationType = type SendBalanceArgs = { balanceAmount: BalanceAmount deviceTokens: DeviceToken[] - notificationSettings: NotificationSettings + recipientUserId: UserId displayBalanceAmount?: DisplayAmount recipientLanguage: UserLanguageOrEmpty } @@ -29,9 +29,9 @@ type NotificationChannelSettings = { type NotificationRecipient = { accountId: AccountId + userId: UserId walletId: WalletId deviceTokens: DeviceToken[] - notificationSettings: NotificationSettings language: UserLanguageOrEmpty level: AccountLevel } diff --git a/core/api/src/services/notifications/index.ts b/core/api/src/services/notifications/index.ts index 014b4a8114..1ede4f9a99 100644 --- a/core/api/src/services/notifications/index.ts +++ b/core/api/src/services/notifications/index.ts @@ -198,7 +198,7 @@ export const NotificationsService = (): INotificationsService => { title, body, notificationCategory: GaloyNotificationCategories.Payments, - notificationSettings: recipient.notificationSettings, + userId: recipient.userId, }) if (result instanceof Error) return result @@ -291,7 +291,7 @@ export const NotificationsService = (): INotificationsService => { const sendBalance = async ({ balanceAmount, deviceTokens, - notificationSettings, + recipientUserId, displayBalanceAmount, recipientLanguage, }: SendBalanceArgs): Promise => { @@ -313,7 +313,7 @@ export const NotificationsService = (): INotificationsService => { title, body, notificationCategory, - notificationSettings, + userId: recipientUserId, }) if (result instanceof NotificationsServiceError) { @@ -352,7 +352,7 @@ export const NotificationsService = (): INotificationsService => { body, data, deviceTokens, - notificationSettings, + userId, notificationCategory, }: SendFilteredPushNotificationArgs): Promise => { const hasDeviceTokens = deviceTokens && deviceTokens.length > 0 @@ -364,8 +364,8 @@ export const NotificationsService = (): INotificationsService => { title, body, data, - notificationSettings, notificationCategory, + userId, }) if (result instanceof NotificationsServiceError) { diff --git a/core/api/src/services/notifications/push-notifications.ts b/core/api/src/services/notifications/push-notifications.ts index 1722e4a506..276dfec1ac 100644 --- a/core/api/src/services/notifications/push-notifications.ts +++ b/core/api/src/services/notifications/push-notifications.ts @@ -2,14 +2,24 @@ import * as admin from "firebase-admin" import { Messaging } from "firebase-admin/lib/messaging/messaging" +import { + ShouldSendNotificationRequest, + NotificationChannel as GrpcNotificationChannel, +} from "./proto/notifications_pb" + +import { + shouldSendNotification as grpcShouldSendNotification, + notificationsMetadata, +} from "./grpc-client" + +import { notificationCategoryToGrpcNotificationCategory } from "./convert" + import { DeviceTokensNotRegisteredNotificationsServiceError, InvalidDeviceNotificationsServiceError, - NotificationChannel, NotificationsServiceError, NotificationsServiceUnreachableServerError, UnknownNotificationsServiceError, - shouldSendNotification, } from "@/domain/notifications" import { ErrorLevel, parseErrorMessageFromUnknown } from "@/domain/shared" import { baseLogger } from "@/services/logger" @@ -116,17 +126,42 @@ export const PushNotificationsService = (): IPushNotificationsService => { })() } + const checkShouldSendNotification = async ({ + userId, + notificationCategory, + }: { + userId: UserId + notificationCategory: NotificationCategory + }): Promise => { + try { + const request = new ShouldSendNotificationRequest() + request.setUserId(userId) + request.setChannel(GrpcNotificationChannel.PUSH) + request.setCategory( + notificationCategoryToGrpcNotificationCategory(notificationCategory), + ) + + const response = await grpcShouldSendNotification(request, notificationsMetadata) + + return response.getShouldSend() + } catch (err) { + return new UnknownNotificationsServiceError(err) + } + } + const sendFilteredNotification = async (args: SendFilteredPushNotificationArgs) => { - const { notificationSettings, notificationCategory, data, ...sendNotificationArgs } = - args - - if ( - !shouldSendNotification({ - notificationCategory, - notificationSettings, - notificationChannel: NotificationChannel.Push, - }) - ) { + const { notificationCategory, data, ...sendNotificationArgs } = args + + const shouldSendNotification = await checkShouldSendNotification({ + userId: args.userId, + notificationCategory, + }) + + if (shouldSendNotification instanceof UnknownNotificationsServiceError) { + return shouldSendNotification + } + + if (!shouldSendNotification) { return { status: SendFilteredPushNotificationStatus.Filtered, } diff --git a/core/api/src/services/notifications/push-notifications.types.d.ts b/core/api/src/services/notifications/push-notifications.types.d.ts index c8a8dd928f..923baf9694 100644 --- a/core/api/src/services/notifications/push-notifications.types.d.ts +++ b/core/api/src/services/notifications/push-notifications.types.d.ts @@ -10,7 +10,7 @@ type SendFilteredPushNotificationArgs = { title: string body: string data?: { [key: string]: string } - notificationSettings: NotificationSettings + userId: UserId notificationCategory: NotificationCategory } diff --git a/core/api/test/legacy-integration/notifications/notification.spec.ts b/core/api/test/legacy-integration/notifications/notification.spec.ts index 4b620b673a..5df141c10b 100644 --- a/core/api/test/legacy-integration/notifications/notification.spec.ts +++ b/core/api/test/legacy-integration/notifications/notification.spec.ts @@ -31,6 +31,7 @@ const walletId = "walletId" as WalletId const paymentHash = "paymentHash" as PaymentHash const txHash = "txHash" as OnChainTxHash const deviceTokens = ["token" as DeviceToken] +const userId = "UserId" as UserId const language = "" as UserLanguageOrEmpty const paymentAmount = { amount: 1000n, @@ -68,13 +69,6 @@ const crcSettlementDisplayPrice = ({ walletCurrency, }) -const unfilteredNotificationSettings: NotificationSettings = { - push: { - enabled: true, - disabledCategories: [], - }, -} - beforeAll(async () => { const usdDisplayPriceRatio = await getCurrentPriceAsDisplayPriceRatio({ currency: UsdDisplayCurrency, @@ -247,7 +241,7 @@ describe("notification", () => { walletId, deviceTokens, language, - notificationSettings: unfilteredNotificationSettings, + userId, level: AccountLevel.One, }, transaction: { @@ -319,7 +313,7 @@ describe("notification", () => { walletId, deviceTokens, language, - notificationSettings: unfilteredNotificationSettings, + userId, level: AccountLevel.One, }, transaction: { @@ -392,7 +386,7 @@ describe("notification", () => { walletId, deviceTokens, language, - notificationSettings: unfilteredNotificationSettings, + userId, level: AccountLevel.One, }, transaction: { @@ -462,7 +456,7 @@ describe("notification", () => { walletId, deviceTokens, language, - notificationSettings: unfilteredNotificationSettings, + userId, level: AccountLevel.One, }, transaction: { @@ -532,7 +526,7 @@ describe("notification", () => { walletId, deviceTokens, language, - notificationSettings: unfilteredNotificationSettings, + userId, level: AccountLevel.One, }, transaction: { diff --git a/core/api/test/legacy-integration/notifications/push-notification.spec.ts b/core/api/test/legacy-integration/notifications/push-notification.spec.ts deleted file mode 100644 index 4c7e4b1f71..0000000000 --- a/core/api/test/legacy-integration/notifications/push-notification.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { - PushNotificationsService, - SendFilteredPushNotificationStatus, -} from "@/services/notifications/push-notifications" - -describe("push notification", () => { - it("should filter a notification", async () => { - const notificationCategory = "transaction" as NotificationCategory - const notificationSettings = { - push: { - enabled: true, - disabledCategories: [notificationCategory], - }, - } - - const result = await PushNotificationsService().sendFilteredNotification({ - body: "body", - title: "title", - deviceTokens: ["deviceToken" as DeviceToken], - notificationCategory, - notificationSettings, - }) - - expect(result).toEqual({ - status: SendFilteredPushNotificationStatus.Filtered, - }) - }) -})