Merge pull request #32619 from kaidubauskas-dd/kaidd/fix-user-slack-dms

fix(notifications-slack): Only DM explicit user recipients
This commit is contained in:
Fredrik Adelöw
2026-03-10 15:33:57 +01:00
committed by GitHub
3 changed files with 60 additions and 2 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-notifications-backend-module-slack': minor
---
**BREAKING**: Only send direct messages to user entity recipients. Notifications sent to non-user entities no longer send Slack direct messages to resolved users.
@@ -355,6 +355,51 @@ describe('SlackNotificationProcessor', () => {
});
});
describe('when recipients include both users and a group', () => {
it('should still DM explicit user recipients', async () => {
const slack = new WebClient();
const processor = SlackNotificationProcessor.fromConfig(config, {
auth,
logger,
catalog: catalogServiceMock({
entities: DEFAULT_ENTITIES_RESPONSE.items,
}),
slack,
})[0];
await processor.processOptions({
recipients: {
type: 'entity',
entityRef: ['group:default/mock', 'user:default/mock'],
},
payload: { title: 'notification' },
});
await processor.postProcess(
{
origin: 'plugin',
id: 'explicit-user-1',
user: 'user:default/mock',
created: new Date(),
payload: { title: 'notification' },
},
{
recipients: {
type: 'entity',
entityRef: ['group:default/mock', 'user:default/mock'],
},
payload: { title: 'notification' },
},
);
expect(slack.chat.postMessage).toHaveBeenCalledTimes(2);
expect(slack.chat.postMessage).toHaveBeenCalledWith(
expect.objectContaining({ channel: 'U12345678' }),
);
});
});
describe('when broadcast channels are not configured', () => {
it('should not send broadcast messages', async () => {
const slack = new WebClient();
@@ -19,6 +19,7 @@ import {
Entity,
isUserEntity,
parseEntityRef,
stringifyEntityRef,
UserEntity,
} from '@backstage/catalog-model';
import { Config, readDurationFromConfig } from '@backstage/config';
@@ -280,8 +281,15 @@ export class SlackNotificationProcessor implements NotificationProcessor {
} else if (options.recipients.type === 'entity') {
// Handle user-specific notification
const entityRefs = [options.recipients.entityRef].flat();
if (entityRefs.some(e => parseEntityRef(e).kind === 'group')) {
// We've already dispatched a slack channel message, so let's not send a DM.
const explicitUserEntityRefs = entityRefs
.filter(entityRef => parseEntityRef(entityRef).kind === 'user')
.map(entityRef => stringifyEntityRef(parseEntityRef(entityRef)));
const normalizedUserRef = stringifyEntityRef(
parseEntityRef(notification.user),
);
if (!explicitUserEntityRefs.includes(normalizedUserRef)) {
// This user was resolved from a non-user entity. Skip sending a DM.
return;
}