From 295c05db695f79f7b762773160393832de74486c Mon Sep 17 00:00:00 2001 From: Heikki Hellgren Date: Wed, 17 Apr 2024 22:58:42 +0300 Subject: [PATCH] feat: support to filter notification recipients after resolving Signed-off-by: Heikki Hellgren --- .changeset/four-cooks-serve.md | 6 ++++++ .../src/service/router.ts | 19 +++++++++++++++++-- plugins/notifications-node/api-report.md | 1 + .../src/service/DefaultNotificationService.ts | 9 +++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 .changeset/four-cooks-serve.md diff --git a/.changeset/four-cooks-serve.md b/.changeset/four-cooks-serve.md new file mode 100644 index 0000000000..864807cc49 --- /dev/null +++ b/.changeset/four-cooks-serve.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-notifications-backend': patch +'@backstage/plugin-notifications-node': patch +--- + +Support for filtering entities from notification recipients after resolving them from the recipients diff --git a/plugins/notifications-backend/src/service/router.ts b/plugins/notifications-backend/src/service/router.ts index 30829a578b..585b1ad104 100644 --- a/plugins/notifications-backend/src/service/router.ts +++ b/plugins/notifications-backend/src/service/router.ts @@ -94,6 +94,7 @@ export async function createRouter( const getUsersForEntityRef = async ( entityRef: string | string[] | null, + excludeEntityRefs: string | string[], ): Promise => { const { token } = await auth.getPluginRequestToken({ onBehalfOf: await auth.getOwnServiceCredentials(), @@ -114,13 +115,23 @@ export async function createRouter( }, { token }, ); + + const excluded = Array.isArray(excludeEntityRefs) + ? excludeEntityRefs + : [excludeEntityRefs]; + const mapEntity = async (entity: Entity | undefined): Promise => { if (!entity) { return []; } + const currentEntityRef = stringifyEntityRef(entity); + if (excluded.includes(currentEntityRef)) { + return []; + } + if (isUserEntity(entity)) { - return [stringifyEntityRef(entity)]; + return [currentEntityRef]; } else if (isGroupEntity(entity) && entity.relations) { const users = entity.relations .filter(relation => relation.type === RELATION_HAS_MEMBER) @@ -162,6 +173,7 @@ export async function createRouter( const u = await mapEntity(entity); users.push(...u); } + return users; }; @@ -482,7 +494,10 @@ export async function createRouter( const entityRef = recipients.entityRef; try { - users = await getUsersForEntityRef(entityRef); + users = await getUsersForEntityRef( + entityRef, + recipients.excludeEntityRef ?? [], + ); } catch (e) { logger.error(`Failed to resolve notification receivers: ${e}`); throw new InputError('Failed to resolve notification receivers', e); diff --git a/plugins/notifications-node/api-report.md b/plugins/notifications-node/api-report.md index a16c141c41..1914b562d1 100644 --- a/plugins/notifications-node/api-report.md +++ b/plugins/notifications-node/api-report.md @@ -41,6 +41,7 @@ export type NotificationRecipients = | { type: 'entity'; entityRef: string | string[]; + excludeEntityRef?: string | string[]; } | { type: 'broadcast'; diff --git a/plugins/notifications-node/src/service/DefaultNotificationService.ts b/plugins/notifications-node/src/service/DefaultNotificationService.ts index a041dd0ecf..950f42ae83 100644 --- a/plugins/notifications-node/src/service/DefaultNotificationService.ts +++ b/plugins/notifications-node/src/service/DefaultNotificationService.ts @@ -28,7 +28,16 @@ export type NotificationServiceOptions = { export type NotificationRecipients = | { type: 'entity'; + /** + * Entity references to send the notifications to + */ entityRef: string | string[]; + /** + * Optional entity reference(s) to filter out of the resolved recipients. + * Usually the currently logged-in user for preventing sending notification + * of user action to him/herself. + */ + excludeEntityRef?: string | string[]; } | { type: 'broadcast' };