From a3d42153d1b8e1e9c75839333130eb7ea2ea9d7e Mon Sep 17 00:00:00 2001 From: Heikki Hellgren Date: Thu, 25 Jan 2024 10:12:31 +0200 Subject: [PATCH] feat: allow broadcast notifications Signed-off-by: Heikki Hellgren --- packages/backend/src/plugins/notifications.ts | 2 +- plugins/notifications-backend/README.md | 4 ++-- .../src/service/router.ts | 24 +++++++++++++++---- plugins/notifications-node/api-report.md | 17 ++++++++++--- .../src/service/DefaultNotificationService.ts | 7 +++++- .../src/service/NotificationService.ts | 4 ++-- 6 files changed, 45 insertions(+), 13 deletions(-) diff --git a/packages/backend/src/plugins/notifications.ts b/packages/backend/src/plugins/notifications.ts index 74e1915cd4..5926c292ff 100644 --- a/packages/backend/src/plugins/notifications.ts +++ b/packages/backend/src/plugins/notifications.ts @@ -23,7 +23,7 @@ export default async function createPlugin( ): Promise { setInterval(() => { env.notificationService.send({ - entityRef: 'user:default/guest', + receivers: { type: 'broadcast' }, title: 'Test', description: 'Test', link: '/catalog', diff --git a/plugins/notifications-backend/README.md b/plugins/notifications-backend/README.md index ea317afefe..376d38c855 100644 --- a/plugins/notifications-backend/README.md +++ b/plugins/notifications-backend/README.md @@ -4,7 +4,7 @@ Welcome to the notifications backend plugin! ## Getting started -First you have to install `@backstage/plugin-notifications-node` and `@backstage/plugin-signals-node` +First you have to install `@backstage/plugin-notifications-node` and `@backstage/plugin-signals-node` packages. Then create a new file to `packages/backend/src/plugins/notifications.ts`: @@ -23,7 +23,7 @@ export default async function createPlugin( tokenManager: env.tokenManager, database: env.database, discovery: env.discovery, - signalService: env.signalService + signalService: env.signalService, }); } ``` diff --git a/plugins/notifications-backend/src/service/router.ts b/plugins/notifications-backend/src/service/router.ts index 5246bc140a..a31f47861f 100644 --- a/plugins/notifications-backend/src/service/router.ts +++ b/plugins/notifications-backend/src/service/router.ts @@ -89,13 +89,24 @@ export async function createRouter( }; const getUsersForEntityRef = async ( - entityRef: string | string[], + entityRef: string | string[] | null, ): Promise => { - const refs = Array.isArray(entityRef) ? entityRef : [entityRef]; const { token } = await tokenManager.getToken(); + + // Broadcast + if (entityRef === null) { + const users = await catalogClient.getEntities({ + filter: { kind: 'User' }, + fields: ['kind', 'metadata.name', 'metadata.namespace'], + }); + return users.items.map(stringifyEntityRef); + } + + const refs = Array.isArray(entityRef) ? entityRef : [entityRef]; const entities = await catalogClient.getEntitiesByRefs( { entityRefs: refs, + fields: ['kind', 'metadata.name', 'metadata.namespace'], }, { token }, ); @@ -206,7 +217,7 @@ export async function createRouter( }); router.post('/notifications', async (req, res) => { - const { entityRef, title, description, link } = req.body; + const { receivers, title, description, link } = req.body; const notifications = []; let users = []; @@ -218,6 +229,11 @@ export async function createRouter( return; } + let entityRef = null; + if (receivers.entityRef && receivers.type === 'entity') { + entityRef = receivers.entityRef; + } + try { users = await getUsersForEntityRef(entityRef); } catch (e) { @@ -254,7 +270,7 @@ export async function createRouter( if (signalService) { await signalService.publish({ - recipients: users, + recipients: entityRef === null ? null : users, message: { action: 'refresh' }, channel: 'notifications', }); diff --git a/plugins/notifications-node/api-report.md b/plugins/notifications-node/api-report.md index f6b4987c90..806b0400ac 100644 --- a/plugins/notifications-node/api-report.md +++ b/plugins/notifications-node/api-report.md @@ -22,18 +22,29 @@ export class DefaultNotificationService implements NotificationService { send(options: NotificationSendOptions): Promise; } +// @public (undocumented) +export type NotificationReceivers = + | { + type: 'entity'; + entityRef: string | string[]; + } + | { + type: 'broadcast'; + }; + // @public (undocumented) export type NotificationSendOptions = { - entityRef: string | string[]; + receivers: NotificationReceivers; title: string; description: string; link: string; }; // @public (undocumented) -export type NotificationService = { +export interface NotificationService { + // (undocumented) send(options: NotificationSendOptions): Promise; -}; +} // @public (undocumented) export const notificationService: ServiceRef; diff --git a/plugins/notifications-node/src/service/DefaultNotificationService.ts b/plugins/notifications-node/src/service/DefaultNotificationService.ts index 8be0f71799..16de07912a 100644 --- a/plugins/notifications-node/src/service/DefaultNotificationService.ts +++ b/plugins/notifications-node/src/service/DefaultNotificationService.ts @@ -27,9 +27,14 @@ export type NotificationServiceOptions = { signalService: SignalService; }; +/** @public */ +export type NotificationReceivers = + | { type: 'entity'; entityRef: string | string[] } + | { type: 'broadcast' }; + /** @public */ export type NotificationSendOptions = { - entityRef: string | string[]; + receivers: NotificationReceivers; title: string; description: string; link: string; diff --git a/plugins/notifications-node/src/service/NotificationService.ts b/plugins/notifications-node/src/service/NotificationService.ts index b2fc4f8a3d..68b0c13a9e 100644 --- a/plugins/notifications-node/src/service/NotificationService.ts +++ b/plugins/notifications-node/src/service/NotificationService.ts @@ -18,6 +18,6 @@ import { NotificationSendOptions } from './DefaultNotificationService'; import { Notification } from '@backstage/plugin-notifications-common'; /** @public */ -export type NotificationService = { +export interface NotificationService { send(options: NotificationSendOptions): Promise; -}; +}