@backstage/plugin-notifications-backend 0.2.0-next.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/dist/index.cjs.js +113 -96
- package/dist/index.cjs.js.map +1 -1
- package/package.json +16 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# @backstage/plugin-notifications-backend
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 939b4ec: Notifications-backend URL query parameter changed from `minimal_severity` to `minimumSeverity`.
|
|
8
|
+
- ec40998: On the Notifications page, the user can trigger "Save" or "Mark as read" actions once for multiple selected notifications.
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- 0d99528: Notification processor functions are now renamed to `preProcess` and `postProcess`.
|
|
13
|
+
Additionally, processor name is now required to be returned by `getName`.
|
|
14
|
+
A new processor functionality `processOptions` was added to process options before sending the notification.
|
|
15
|
+
- e003e0e: The ordered list of notifications' severities is exported by notifications-common for reusability.
|
|
16
|
+
- 9a41a7b: Migrate signals and notifications to the new backend in local development
|
|
17
|
+
- 9987066: fix: retrieve relations and children when mapping group entities for notifications
|
|
18
|
+
- 6206039: Fix entity owner resolution in notifications
|
|
19
|
+
- Updated dependencies
|
|
20
|
+
- @backstage/backend-common@0.21.7
|
|
21
|
+
- @backstage/plugin-notifications-common@0.0.3
|
|
22
|
+
- @backstage/plugin-notifications-node@0.1.3
|
|
23
|
+
- @backstage/backend-plugin-api@0.6.17
|
|
24
|
+
- @backstage/plugin-auth-node@0.4.12
|
|
25
|
+
- @backstage/catalog-client@1.6.4
|
|
26
|
+
- @backstage/plugin-events-node@0.3.3
|
|
27
|
+
- @backstage/plugin-signals-node@0.1.3
|
|
28
|
+
- @backstage/catalog-model@1.4.5
|
|
29
|
+
- @backstage/config@1.2.0
|
|
30
|
+
- @backstage/errors@1.2.4
|
|
31
|
+
|
|
3
32
|
## 0.2.0-next.1
|
|
4
33
|
|
|
5
34
|
### Minor Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -6,6 +6,7 @@ var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
|
6
6
|
var backendCommon = require('@backstage/backend-common');
|
|
7
7
|
var express = require('express');
|
|
8
8
|
var Router = require('express-promise-router');
|
|
9
|
+
var pluginNotificationsCommon = require('@backstage/plugin-notifications-common');
|
|
9
10
|
var uuid = require('uuid');
|
|
10
11
|
var catalogClient = require('@backstage/catalog-client');
|
|
11
12
|
var catalogModel = require('@backstage/catalog-model');
|
|
@@ -43,15 +44,9 @@ const NOTIFICATION_COLUMNS = [
|
|
|
43
44
|
"read",
|
|
44
45
|
"saved"
|
|
45
46
|
];
|
|
46
|
-
const severities = [
|
|
47
|
-
"critical",
|
|
48
|
-
"high",
|
|
49
|
-
"normal",
|
|
50
|
-
"low"
|
|
51
|
-
];
|
|
52
47
|
const normalizeSeverity = (input) => {
|
|
53
48
|
let lower = (input != null ? input : "normal").toLowerCase();
|
|
54
|
-
if (
|
|
49
|
+
if (pluginNotificationsCommon.notificationSeverities.indexOf(lower) < 0) {
|
|
55
50
|
lower = "normal";
|
|
56
51
|
}
|
|
57
52
|
return lower;
|
|
@@ -168,8 +163,8 @@ class DatabaseNotificationsStore {
|
|
|
168
163
|
query.whereNull("saved");
|
|
169
164
|
}
|
|
170
165
|
if (options.minimumSeverity !== void 0) {
|
|
171
|
-
const idx =
|
|
172
|
-
const equalOrHigher =
|
|
166
|
+
const idx = pluginNotificationsCommon.notificationSeverities.indexOf(options.minimumSeverity);
|
|
167
|
+
const equalOrHigher = pluginNotificationsCommon.notificationSeverities.slice(0, idx + 1);
|
|
173
168
|
query.whereIn("severity", equalOrHigher);
|
|
174
169
|
}
|
|
175
170
|
return query;
|
|
@@ -354,7 +349,7 @@ async function createRouter(options) {
|
|
|
354
349
|
userInfo,
|
|
355
350
|
discovery,
|
|
356
351
|
catalog,
|
|
357
|
-
processors,
|
|
352
|
+
processors = [],
|
|
358
353
|
signals
|
|
359
354
|
} = options;
|
|
360
355
|
const catalogClient$1 = catalog != null ? catalog : new catalogClient.CatalogClient({ discoveryApi: discovery });
|
|
@@ -372,17 +367,12 @@ async function createRouter(options) {
|
|
|
372
367
|
if (entityRef === null) {
|
|
373
368
|
return [];
|
|
374
369
|
}
|
|
370
|
+
const fields = ["kind", "metadata.name", "metadata.namespace", "relations"];
|
|
375
371
|
const refs = Array.isArray(entityRef) ? entityRef : [entityRef];
|
|
376
372
|
const entities = await catalogClient$1.getEntitiesByRefs(
|
|
377
373
|
{
|
|
378
374
|
entityRefs: refs,
|
|
379
|
-
fields
|
|
380
|
-
"kind",
|
|
381
|
-
"metadata.name",
|
|
382
|
-
"metadata.namespace",
|
|
383
|
-
"relations",
|
|
384
|
-
"spec.owner"
|
|
385
|
-
]
|
|
375
|
+
fields
|
|
386
376
|
},
|
|
387
377
|
{ token }
|
|
388
378
|
);
|
|
@@ -394,22 +384,12 @@ async function createRouter(options) {
|
|
|
394
384
|
if (catalogModel.isUserEntity(entity)) {
|
|
395
385
|
return [catalogModel.stringifyEntityRef(entity)];
|
|
396
386
|
} else if (catalogModel.isGroupEntity(entity) && entity.relations) {
|
|
397
|
-
const users2 = entity.relations.filter(
|
|
398
|
-
|
|
399
|
-
).map((r) => r.targetRef);
|
|
400
|
-
const childGroupRefs = entity.relations.filter(
|
|
401
|
-
(relation) => relation.type === catalogModel.RELATION_PARENT_OF && relation.targetRef
|
|
402
|
-
).map((r) => r.targetRef);
|
|
387
|
+
const users2 = entity.relations.filter((relation) => relation.type === catalogModel.RELATION_HAS_MEMBER).map((r) => r.targetRef);
|
|
388
|
+
const childGroupRefs = entity.relations.filter((relation) => relation.type === catalogModel.RELATION_PARENT_OF).map((r) => r.targetRef);
|
|
403
389
|
const childGroups = await catalogClient$1.getEntitiesByRefs(
|
|
404
390
|
{
|
|
405
391
|
entityRefs: childGroupRefs,
|
|
406
|
-
fields
|
|
407
|
-
"kind",
|
|
408
|
-
"metadata.name",
|
|
409
|
-
"metadata.namespace",
|
|
410
|
-
"relations",
|
|
411
|
-
"spec.owner"
|
|
412
|
-
]
|
|
392
|
+
fields
|
|
413
393
|
},
|
|
414
394
|
{ token }
|
|
415
395
|
);
|
|
@@ -417,13 +397,15 @@ async function createRouter(options) {
|
|
|
417
397
|
childGroups.items.map(mapEntity)
|
|
418
398
|
);
|
|
419
399
|
return [...users2, ...childGroupUsers.flat(2)];
|
|
420
|
-
} else if (
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
)
|
|
425
|
-
|
|
426
|
-
|
|
400
|
+
} else if (entity.relations) {
|
|
401
|
+
const ownerRef = (_a = entity.relations.find(
|
|
402
|
+
(relation) => relation.type === catalogModel.RELATION_OWNED_BY
|
|
403
|
+
)) == null ? void 0 : _a.targetRef;
|
|
404
|
+
if (ownerRef) {
|
|
405
|
+
const owner = await catalogClient$1.getEntityByRef(ownerRef, { token });
|
|
406
|
+
if (owner) {
|
|
407
|
+
return mapEntity(owner);
|
|
408
|
+
}
|
|
427
409
|
}
|
|
428
410
|
}
|
|
429
411
|
return [];
|
|
@@ -435,17 +417,42 @@ async function createRouter(options) {
|
|
|
435
417
|
}
|
|
436
418
|
return users;
|
|
437
419
|
};
|
|
438
|
-
const
|
|
420
|
+
const processOptions = async (opts) => {
|
|
421
|
+
let ret = opts;
|
|
422
|
+
for (const processor of processors) {
|
|
423
|
+
try {
|
|
424
|
+
ret = processor.processOptions ? await processor.processOptions(ret) : ret;
|
|
425
|
+
} catch (e) {
|
|
426
|
+
logger.error(
|
|
427
|
+
`Error while processing notification options with ${processor.getName()}: ${e}`
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
return ret;
|
|
432
|
+
};
|
|
433
|
+
const preProcessNotification = async (notification, opts) => {
|
|
439
434
|
let ret = notification;
|
|
440
|
-
for (const processor of processors
|
|
441
|
-
|
|
435
|
+
for (const processor of processors) {
|
|
436
|
+
try {
|
|
437
|
+
ret = processor.preProcess ? await processor.preProcess(ret, opts) : ret;
|
|
438
|
+
} catch (e) {
|
|
439
|
+
logger.error(
|
|
440
|
+
`Error while pre processing notification with ${processor.getName()}: ${e}`
|
|
441
|
+
);
|
|
442
|
+
}
|
|
442
443
|
}
|
|
443
444
|
return ret;
|
|
444
445
|
};
|
|
445
|
-
const
|
|
446
|
-
for (const processor of processors
|
|
447
|
-
if (processor.
|
|
448
|
-
|
|
446
|
+
const postProcessNotification = async (notification, opts) => {
|
|
447
|
+
for (const processor of processors) {
|
|
448
|
+
if (processor.postProcess) {
|
|
449
|
+
try {
|
|
450
|
+
await processor.postProcess(notification, opts);
|
|
451
|
+
} catch (e) {
|
|
452
|
+
logger.error(
|
|
453
|
+
`Error while post processing notification with ${processor.getName()}: ${e}`
|
|
454
|
+
);
|
|
455
|
+
}
|
|
449
456
|
}
|
|
450
457
|
}
|
|
451
458
|
};
|
|
@@ -489,9 +496,9 @@ async function createRouter(options) {
|
|
|
489
496
|
}
|
|
490
497
|
opts.createdAfter = new Date(sinceEpoch);
|
|
491
498
|
}
|
|
492
|
-
if (req.query.
|
|
499
|
+
if (req.query.minimumSeverity) {
|
|
493
500
|
opts.minimumSeverity = normalizeSeverity(
|
|
494
|
-
req.query.
|
|
501
|
+
req.query.minimumSeverity.toString()
|
|
495
502
|
);
|
|
496
503
|
}
|
|
497
504
|
const [notifications, totalCount] = await Promise.all([
|
|
@@ -555,16 +562,17 @@ async function createRouter(options) {
|
|
|
555
562
|
const notifications = await store.getNotifications({ ids, user });
|
|
556
563
|
res.status(200).send(notifications);
|
|
557
564
|
});
|
|
558
|
-
const sendBroadcastNotification = async (baseNotification, opts) => {
|
|
559
|
-
const { scope
|
|
565
|
+
const sendBroadcastNotification = async (baseNotification, opts, origin) => {
|
|
566
|
+
const { scope } = opts.payload;
|
|
560
567
|
const broadcastNotification = {
|
|
561
568
|
...baseNotification,
|
|
569
|
+
user: null,
|
|
562
570
|
id: uuid.v4()
|
|
563
571
|
};
|
|
564
|
-
const notification = await
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
572
|
+
const notification = await preProcessNotification(
|
|
573
|
+
broadcastNotification,
|
|
574
|
+
opts
|
|
575
|
+
);
|
|
568
576
|
let existingNotification;
|
|
569
577
|
if (scope) {
|
|
570
578
|
existingNotification = await store.getExistingScopeBroadcast({
|
|
@@ -582,7 +590,6 @@ async function createRouter(options) {
|
|
|
582
590
|
} else {
|
|
583
591
|
await store.saveBroadcast(notification);
|
|
584
592
|
}
|
|
585
|
-
processorSendNotification(ret);
|
|
586
593
|
if (signals) {
|
|
587
594
|
await signals.publish({
|
|
588
595
|
recipients: { type: "broadcast" },
|
|
@@ -592,12 +599,13 @@ async function createRouter(options) {
|
|
|
592
599
|
},
|
|
593
600
|
channel: "notifications"
|
|
594
601
|
});
|
|
602
|
+
postProcessNotification(ret, opts);
|
|
595
603
|
}
|
|
596
604
|
return notification;
|
|
597
605
|
};
|
|
598
|
-
const sendUserNotifications = async (baseNotification, users, opts) => {
|
|
606
|
+
const sendUserNotifications = async (baseNotification, users, opts, origin) => {
|
|
599
607
|
const notifications = [];
|
|
600
|
-
const { scope
|
|
608
|
+
const { scope } = opts.payload;
|
|
601
609
|
const uniqueUsers = [...new Set(users)];
|
|
602
610
|
for (const user of uniqueUsers) {
|
|
603
611
|
const userNotification = {
|
|
@@ -605,7 +613,7 @@ async function createRouter(options) {
|
|
|
605
613
|
id: uuid.v4(),
|
|
606
614
|
user
|
|
607
615
|
};
|
|
608
|
-
const notification = await
|
|
616
|
+
const notification = await preProcessNotification(userNotification, opts);
|
|
609
617
|
let existingNotification;
|
|
610
618
|
if (scope) {
|
|
611
619
|
existingNotification = await store.getExistingScopeNotification({
|
|
@@ -624,7 +632,6 @@ async function createRouter(options) {
|
|
|
624
632
|
} else {
|
|
625
633
|
await store.saveNotification(notification);
|
|
626
634
|
}
|
|
627
|
-
processorSendNotification(ret);
|
|
628
635
|
notifications.push(ret);
|
|
629
636
|
if (signals) {
|
|
630
637
|
await signals.publish({
|
|
@@ -636,51 +643,61 @@ async function createRouter(options) {
|
|
|
636
643
|
channel: "notifications"
|
|
637
644
|
});
|
|
638
645
|
}
|
|
646
|
+
postProcessNotification(ret, opts);
|
|
639
647
|
}
|
|
640
648
|
return notifications;
|
|
641
649
|
};
|
|
642
|
-
router.post(
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
}
|
|
653
|
-
const origin = credentials.principal.subject;
|
|
654
|
-
const baseNotification = {
|
|
655
|
-
payload: {
|
|
656
|
-
...payload,
|
|
657
|
-
severity: (_a = payload.severity) != null ? _a : "normal"
|
|
658
|
-
},
|
|
659
|
-
origin,
|
|
660
|
-
created: /* @__PURE__ */ new Date()
|
|
661
|
-
};
|
|
662
|
-
if (recipients.type === "broadcast") {
|
|
663
|
-
const broadcast = await sendBroadcastNotification(baseNotification, {
|
|
664
|
-
scope,
|
|
665
|
-
origin
|
|
650
|
+
router.post(
|
|
651
|
+
"/",
|
|
652
|
+
async (req, res) => {
|
|
653
|
+
var _a;
|
|
654
|
+
const opts = await processOptions(req.body);
|
|
655
|
+
const { recipients, payload } = opts;
|
|
656
|
+
const notifications = [];
|
|
657
|
+
let users = [];
|
|
658
|
+
const credentials = await httpAuth.credentials(req, {
|
|
659
|
+
allow: ["service"]
|
|
666
660
|
});
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
users = await getUsersForEntityRef(entityRef);
|
|
672
|
-
} catch (e) {
|
|
673
|
-
throw new errors.InputError();
|
|
661
|
+
const { title } = payload;
|
|
662
|
+
if (!recipients || !title) {
|
|
663
|
+
logger.error(`Invalid notification request received`);
|
|
664
|
+
throw new errors.InputError(`Invalid notification request received`);
|
|
674
665
|
}
|
|
675
|
-
const
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
666
|
+
const origin = credentials.principal.subject;
|
|
667
|
+
const baseNotification = {
|
|
668
|
+
payload: {
|
|
669
|
+
...payload,
|
|
670
|
+
severity: (_a = payload.severity) != null ? _a : "normal"
|
|
671
|
+
},
|
|
672
|
+
origin,
|
|
673
|
+
created: /* @__PURE__ */ new Date()
|
|
674
|
+
};
|
|
675
|
+
if (recipients.type === "broadcast") {
|
|
676
|
+
const broadcast = await sendBroadcastNotification(
|
|
677
|
+
baseNotification,
|
|
678
|
+
opts,
|
|
679
|
+
origin
|
|
680
|
+
);
|
|
681
|
+
notifications.push(broadcast);
|
|
682
|
+
} else {
|
|
683
|
+
const entityRef = recipients.entityRef;
|
|
684
|
+
try {
|
|
685
|
+
users = await getUsersForEntityRef(entityRef);
|
|
686
|
+
} catch (e) {
|
|
687
|
+
logger.error(`Failed to resolve notification receivers: ${e}`);
|
|
688
|
+
throw new errors.InputError("Failed to resolve notification receivers", e);
|
|
689
|
+
}
|
|
690
|
+
const userNotifications = await sendUserNotifications(
|
|
691
|
+
baseNotification,
|
|
692
|
+
users,
|
|
693
|
+
opts,
|
|
694
|
+
origin
|
|
695
|
+
);
|
|
696
|
+
notifications.push(...userNotifications);
|
|
697
|
+
}
|
|
698
|
+
res.json(notifications);
|
|
681
699
|
}
|
|
682
|
-
|
|
683
|
-
});
|
|
700
|
+
);
|
|
684
701
|
router.use(backendCommon.errorHandler());
|
|
685
702
|
return router;
|
|
686
703
|
}
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/database/DatabaseNotificationsStore.ts","../src/service/parseEntityOrderFieldParams.ts","../src/service/router.ts","../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n PluginDatabaseManager,\n resolvePackagePath,\n} from '@backstage/backend-common';\nimport {\n NotificationGetOptions,\n NotificationModifyOptions,\n NotificationsStore,\n} from './NotificationsStore';\nimport {\n Notification,\n NotificationSeverity,\n} from '@backstage/plugin-notifications-common';\nimport { Knex } from 'knex';\n\nconst migrationsDir = resolvePackagePath(\n '@backstage/plugin-notifications-backend',\n 'migrations',\n);\n\nconst NOTIFICATION_COLUMNS = [\n 'id',\n 'title',\n 'description',\n 'severity',\n 'link',\n 'origin',\n 'scope',\n 'topic',\n 'created',\n 'updated',\n 'user',\n 'read',\n 'saved',\n];\n\nconst severities: NotificationSeverity[] = [\n 'critical',\n 'high',\n 'normal',\n 'low',\n];\n\nexport const normalizeSeverity = (input?: string): NotificationSeverity => {\n let lower = (input ?? 'normal').toLowerCase() as NotificationSeverity;\n if (severities.indexOf(lower) < 0) {\n lower = 'normal';\n }\n return lower;\n};\n\n/** @internal */\nexport class DatabaseNotificationsStore implements NotificationsStore {\n private readonly isSQLite = false;\n\n private constructor(private readonly db: Knex) {\n this.isSQLite = this.db.client.config.client.includes('sqlite3');\n }\n\n static async create({\n database,\n skipMigrations,\n }: {\n database: PluginDatabaseManager;\n skipMigrations?: boolean;\n }): Promise<DatabaseNotificationsStore> {\n const client = await database.getClient();\n\n if (!database.migrations?.skip && !skipMigrations) {\n await client.migrate.latest({\n directory: migrationsDir,\n });\n }\n\n return new DatabaseNotificationsStore(client);\n }\n\n private mapToInteger = (val: string | number | undefined): number => {\n return typeof val === 'string' ? Number.parseInt(val, 10) : val ?? 0;\n };\n\n private mapToNotifications = (rows: any[]): Notification[] => {\n return rows.map(row => ({\n id: row.id,\n user: row.user,\n created: new Date(row.created),\n saved: row.saved,\n read: row.read,\n updated: row.updated,\n origin: row.origin,\n payload: {\n title: row.title,\n description: row.description,\n link: row.link,\n topic: row.topic,\n severity: row.severity,\n scope: row.scope,\n icon: row.icon,\n },\n }));\n };\n\n private mapNotificationToDbRow = (notification: Notification) => {\n return {\n id: notification.id,\n user: notification.user,\n origin: notification.origin,\n created: notification.created,\n topic: notification.payload?.topic,\n link: notification.payload?.link,\n title: notification.payload?.title,\n description: notification.payload?.description,\n severity: normalizeSeverity(notification.payload?.severity),\n scope: notification.payload?.scope,\n saved: notification.saved,\n read: notification.read,\n };\n };\n\n private mapBroadcastToDbRow = (notification: Notification) => {\n return {\n id: notification.id,\n origin: notification.origin,\n created: notification.created,\n topic: notification.payload?.topic,\n link: notification.payload?.link,\n title: notification.payload?.title,\n description: notification.payload?.description,\n severity: normalizeSeverity(notification.payload?.severity),\n scope: notification.payload?.scope,\n };\n };\n\n private getBroadcastUnion = () => {\n return this.db('broadcast')\n .leftJoin(\n 'broadcast_user_status',\n 'id',\n '=',\n 'broadcast_user_status.broadcast_id',\n )\n .select(NOTIFICATION_COLUMNS);\n };\n\n private getNotificationsBaseQuery = (\n options: NotificationGetOptions | NotificationModifyOptions,\n ) => {\n const { user, orderField } = options;\n\n const subQuery = this.db('notification')\n .select(NOTIFICATION_COLUMNS)\n .unionAll([this.getBroadcastUnion()])\n .as('notifications');\n\n const query = this.db.from(subQuery).where(q => {\n q.where('user', user).orWhereNull('user');\n });\n\n if (orderField && orderField.length > 0) {\n orderField.forEach(orderBy => {\n query.orderBy(orderBy.field, orderBy.order);\n });\n } else if (!orderField) {\n query.orderBy('created', 'desc');\n }\n\n if (options.createdAfter) {\n if (this.isSQLite) {\n query.where('created', '>=', options.createdAfter.valueOf());\n } else {\n query.where('created', '>=', options.createdAfter.toISOString());\n }\n }\n\n if (options.limit) {\n query.limit(options.limit);\n }\n\n if (options.offset) {\n query.offset(options.offset);\n }\n\n if (options.search) {\n query.whereRaw(\n `(LOWER(title) LIKE LOWER(?) OR LOWER(description) LIKE LOWER(?))`,\n [`%${options.search}%`, `%${options.search}%`],\n );\n }\n\n if (options.ids) {\n query.whereIn('id', options.ids);\n }\n\n if (options.read) {\n query.whereNotNull('read');\n } else if (options.read === false) {\n query.whereNull('read');\n } // or match both if undefined\n\n if (options.saved) {\n query.whereNotNull('saved');\n } else if (options.saved === false) {\n query.whereNull('saved');\n } // or match both if undefined\n\n if (options.minimumSeverity !== undefined) {\n const idx = severities.indexOf(options.minimumSeverity);\n const equalOrHigher = severities.slice(0, idx + 1);\n query.whereIn('severity', equalOrHigher);\n }\n\n return query;\n };\n\n async getNotifications(options: NotificationGetOptions) {\n const notificationQuery = this.getNotificationsBaseQuery(options);\n const notifications = await notificationQuery.select(NOTIFICATION_COLUMNS);\n return this.mapToNotifications(notifications);\n }\n\n async getNotificationsCount(options: NotificationGetOptions) {\n const countOptions: NotificationGetOptions = { ...options };\n countOptions.limit = undefined;\n countOptions.offset = undefined;\n countOptions.orderField = [];\n const notificationQuery = this.getNotificationsBaseQuery(countOptions);\n const response = await notificationQuery.count('id as CNT');\n return Number(response[0].CNT);\n }\n\n async saveNotification(notification: Notification) {\n await this.db\n .insert(this.mapNotificationToDbRow(notification))\n .into('notification');\n }\n\n async saveBroadcast(notification: Notification) {\n await this.db\n .insert(this.mapBroadcastToDbRow(notification))\n .into('broadcast');\n if (notification.saved || notification.read) {\n await this.db\n .insert({\n user: notification.user,\n broadcast_id: notification.id,\n saved: notification.saved,\n read: notification.read,\n })\n .into('broadcast_user_status');\n }\n }\n\n async getStatus(options: NotificationGetOptions) {\n const notificationQuery = this.getNotificationsBaseQuery({\n ...options,\n orderField: [],\n });\n const readSubQuery = notificationQuery\n .clone()\n .count('id')\n .whereNotNull('read')\n .as('READ');\n const unreadSubQuery = notificationQuery\n .clone()\n .count('id')\n .whereNull('read')\n .as('UNREAD');\n\n const query = await notificationQuery\n .select(readSubQuery, unreadSubQuery)\n .first();\n\n return {\n unread: this.mapToInteger((query as any)?.UNREAD),\n read: this.mapToInteger((query as any)?.READ),\n };\n }\n\n async getExistingScopeNotification(options: {\n user: string;\n scope: string;\n origin: string;\n }) {\n const query = this.db('notification')\n .where('user', options.user)\n .where('scope', options.scope)\n .where('origin', options.origin)\n .limit(1);\n\n const rows = await query;\n if (!rows || rows.length === 0) {\n return null;\n }\n return rows[0] as Notification;\n }\n\n async getExistingScopeBroadcast(options: { scope: string; origin: string }) {\n const query = this.db('broadcast')\n .where('scope', options.scope)\n .where('origin', options.origin)\n .limit(1);\n\n const rows = await query;\n if (!rows || rows.length === 0) {\n return null;\n }\n return rows[0] as Notification;\n }\n\n async restoreExistingNotification({\n id,\n notification,\n }: {\n id: string;\n notification: Notification;\n }) {\n const updateColumns = {\n title: notification.payload.title,\n description: notification.payload.description,\n link: notification.payload.link,\n topic: notification.payload.topic,\n updated: new Date(),\n severity: normalizeSeverity(notification.payload?.severity),\n read: null,\n };\n\n const notificationQuery = this.db('notification')\n .where('id', id)\n .where('user', notification.user);\n const broadcastQuery = this.db('broadcast').where('id', id);\n\n await Promise.all([\n notificationQuery.update(updateColumns),\n broadcastQuery.update({ ...updateColumns, read: undefined }),\n ]);\n\n return await this.getNotification({ id });\n }\n\n async getNotification(options: { id: string }): Promise<Notification | null> {\n const rows = await this.db\n .select('*')\n .from(\n this.db('notification')\n .select(NOTIFICATION_COLUMNS)\n .unionAll([this.getBroadcastUnion()])\n .as('notifications'),\n )\n .where('id', options.id)\n .limit(1);\n if (!rows || rows.length === 0) {\n return null;\n }\n return this.mapToNotifications(rows)[0];\n }\n\n private markReadSaved = async (\n ids: string[],\n user: string,\n read?: Date | null,\n saved?: Date | null,\n ) => {\n await this.db('notification')\n .whereIn('id', ids)\n .where('user', user)\n .update({ read, saved });\n\n const broadcasts = this.mapToNotifications(\n await this.db('broadcast').whereIn('id', ids).select(),\n );\n\n if (broadcasts.length > 0)\n if (!this.isSQLite) {\n await this.db('broadcast_user_status')\n .insert(\n broadcasts.map(b => ({\n broadcast_id: b.id,\n user,\n read,\n saved,\n })),\n )\n .onConflict(['broadcast_id', 'user'])\n .merge(['read', 'saved']);\n } else {\n // SQLite does not support upsert so fall back to this (mostly for tests and local dev)\n for (const b of broadcasts) {\n const baseQuery = this.db('broadcast_user_status')\n .where('broadcast_id', b.id)\n .where('user', user);\n const exists = await baseQuery.clone().limit(1).select().first();\n if (exists) {\n await baseQuery.clone().update({ read, saved });\n } else {\n await baseQuery\n .clone()\n .insert({ broadcast_id: b.id, user, read, saved });\n }\n }\n }\n };\n\n async markRead(options: NotificationModifyOptions): Promise<void> {\n await this.markReadSaved(options.ids, options.user, new Date(), undefined);\n }\n\n async markUnread(options: NotificationModifyOptions): Promise<void> {\n await this.markReadSaved(options.ids, options.user, null, undefined);\n }\n\n async markSaved(options: NotificationModifyOptions): Promise<void> {\n await this.markReadSaved(options.ids, options.user, undefined, new Date());\n }\n\n async markUnsaved(options: NotificationModifyOptions): Promise<void> {\n await this.markReadSaved(options.ids, options.user, undefined, null);\n }\n}\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// This file is based on the plugins/catalog-backend\n\nimport { InputError } from '@backstage/errors';\nimport { EntityOrder } from '../database';\n\n/**\n * Takes a single unknown parameter and makes sure that it's a single string or\n * an array of strings, and returns as an array.\n */\nexport function parseStringsParam(\n param: unknown,\n ctx: string,\n): string[] | undefined {\n if (param === undefined) {\n return undefined;\n }\n\n const array = [param].flat();\n if (array.some(p => typeof p !== 'string')) {\n throw new InputError(`Invalid ${ctx}, not a string`);\n }\n\n return array as string[];\n}\n\nexport function parseEntityOrderFieldParams(\n params: Record<string, unknown>,\n): EntityOrder[] | undefined {\n const orderFieldStrings = parseStringsParam(params.orderField, 'orderField');\n if (!orderFieldStrings) {\n return undefined;\n }\n\n return orderFieldStrings.map(orderFieldString => {\n const [field, order] = orderFieldString.split(',');\n\n if (order !== undefined && !isOrder(order)) {\n throw new InputError('Invalid order field order, must be asc or desc');\n }\n return { field, order };\n });\n}\n\nexport function isOrder(order: string): order is 'asc' | 'desc' {\n return ['asc', 'desc'].includes(order);\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { errorHandler, PluginDatabaseManager } from '@backstage/backend-common';\nimport express, { Request } from 'express';\nimport Router from 'express-promise-router';\nimport {\n DatabaseNotificationsStore,\n normalizeSeverity,\n NotificationGetOptions,\n} from '../database';\nimport { v4 as uuid } from 'uuid';\nimport { CatalogApi, CatalogClient } from '@backstage/catalog-client';\nimport {\n Entity,\n isGroupEntity,\n isUserEntity,\n RELATION_HAS_MEMBER,\n RELATION_PARENT_OF,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { NotificationProcessor } from '@backstage/plugin-notifications-node';\nimport { InputError } from '@backstage/errors';\nimport {\n AuthService,\n DiscoveryService,\n HttpAuthService,\n LoggerService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\nimport { SignalsService } from '@backstage/plugin-signals-node';\nimport {\n NewNotificationSignal,\n Notification,\n NotificationReadSignal,\n} from '@backstage/plugin-notifications-common';\nimport { parseEntityOrderFieldParams } from './parseEntityOrderFieldParams';\n\n/** @internal */\nexport interface RouterOptions {\n logger: LoggerService;\n database: PluginDatabaseManager;\n discovery: DiscoveryService;\n auth: AuthService;\n httpAuth: HttpAuthService;\n userInfo: UserInfoService;\n signals?: SignalsService;\n catalog?: CatalogApi;\n processors?: NotificationProcessor[];\n}\n\n/** @internal */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const {\n logger,\n database,\n auth,\n httpAuth,\n userInfo,\n discovery,\n catalog,\n processors,\n signals,\n } = options;\n\n const catalogClient =\n catalog ?? new CatalogClient({ discoveryApi: discovery });\n const store = await DatabaseNotificationsStore.create({ database });\n\n const getUser = async (req: Request<unknown>) => {\n const credentials = await httpAuth.credentials(req, { allow: ['user'] });\n const info = await userInfo.getUserInfo(credentials);\n return info.userEntityRef;\n };\n\n const getUsersForEntityRef = async (\n entityRef: string | string[] | null,\n ): Promise<string[]> => {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n\n if (entityRef === null) {\n return [];\n }\n\n const refs = Array.isArray(entityRef) ? entityRef : [entityRef];\n const entities = await catalogClient.getEntitiesByRefs(\n {\n entityRefs: refs,\n fields: [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'relations',\n 'spec.owner',\n ],\n },\n { token },\n );\n const mapEntity = async (entity: Entity | undefined): Promise<string[]> => {\n if (!entity) {\n return [];\n }\n\n if (isUserEntity(entity)) {\n return [stringifyEntityRef(entity)];\n } else if (isGroupEntity(entity) && entity.relations) {\n const users = entity.relations\n .filter(\n relation =>\n relation.type === RELATION_HAS_MEMBER && relation.targetRef,\n )\n .map(r => r.targetRef);\n\n const childGroupRefs = entity.relations\n .filter(\n relation =>\n relation.type === RELATION_PARENT_OF && relation.targetRef,\n )\n .map(r => r.targetRef);\n\n const childGroups = await catalogClient.getEntitiesByRefs(\n {\n entityRefs: childGroupRefs,\n fields: [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'relations',\n 'spec.owner',\n ],\n },\n { token },\n );\n const childGroupUsers = await Promise.all(\n childGroups.items.map(mapEntity),\n );\n return [...users, ...childGroupUsers.flat(2)];\n } else if (!isGroupEntity(entity) && entity.spec?.owner) {\n const owner = await catalogClient.getEntityByRef(\n entity.spec.owner as string,\n { token },\n );\n if (owner) {\n return mapEntity(owner);\n }\n }\n\n return [];\n };\n\n const users: string[] = [];\n for (const entity of entities.items) {\n const u = await mapEntity(entity);\n users.push(...u);\n }\n return users;\n };\n\n const decorateNotification = async (notification: Notification) => {\n let ret = notification;\n for (const processor of processors ?? []) {\n ret = processor.decorate ? await processor.decorate(ret) : ret;\n }\n return ret;\n };\n\n const processorSendNotification = async (notification: Notification) => {\n for (const processor of processors ?? []) {\n if (processor.send) {\n processor.send(notification);\n }\n }\n };\n\n // TODO: Move to use OpenAPI router instead\n const router = Router();\n router.use(express.json());\n\n router.get('/health', (_, response) => {\n logger.info('PONG!');\n response.json({ status: 'ok' });\n });\n\n router.get('/', async (req, res) => {\n const user = await getUser(req);\n const opts: NotificationGetOptions = {\n user: user,\n };\n if (req.query.offset) {\n opts.offset = Number.parseInt(req.query.offset.toString(), 10);\n }\n if (req.query.limit) {\n opts.limit = Number.parseInt(req.query.limit.toString(), 10);\n }\n if (req.query.orderField) {\n opts.orderField = parseEntityOrderFieldParams(req.query);\n }\n if (req.query.search) {\n opts.search = req.query.search.toString();\n }\n if (req.query.read === 'true') {\n opts.read = true;\n } else if (req.query.read === 'false') {\n opts.read = false;\n // or keep undefined\n }\n if (req.query.saved === 'true') {\n opts.saved = true;\n } else if (req.query.saved === 'false') {\n opts.saved = false;\n // or keep undefined\n }\n if (req.query.createdAfter) {\n const sinceEpoch = Date.parse(String(req.query.createdAfter));\n if (isNaN(sinceEpoch)) {\n throw new InputError('Unexpected date format');\n }\n opts.createdAfter = new Date(sinceEpoch);\n }\n if (req.query.minimal_severity) {\n opts.minimumSeverity = normalizeSeverity(\n req.query.minimal_severity.toString(),\n );\n }\n\n const [notifications, totalCount] = await Promise.all([\n store.getNotifications(opts),\n store.getNotificationsCount(opts),\n ]);\n res.send({\n totalCount,\n notifications,\n });\n });\n\n router.get('/status', async (req, res) => {\n const user = await getUser(req);\n const status = await store.getStatus({ user });\n res.send(status);\n });\n\n // Make sure this is the last \"GET\" handler\n router.get('/:id', async (req, res) => {\n const user = await getUser(req);\n const opts: NotificationGetOptions = {\n user: user,\n limit: 1,\n ids: [req.params.id],\n };\n const notifications = await store.getNotifications(opts);\n if (notifications.length !== 1) {\n res.status(404).send({ error: 'Not found' });\n return;\n }\n res.send(notifications[0]);\n });\n\n router.post('/update', async (req, res) => {\n const user = await getUser(req);\n const { ids, read, saved } = req.body;\n if (!ids || !Array.isArray(ids)) {\n throw new InputError();\n }\n\n if (read === true) {\n await store.markRead({ user, ids });\n\n if (signals) {\n await signals.publish<NotificationReadSignal>({\n recipients: { type: 'user', entityRef: [user] },\n message: { action: 'notification_read', notification_ids: ids },\n channel: 'notifications',\n });\n }\n } else if (read === false) {\n await store.markUnread({ user: user, ids });\n\n if (signals) {\n await signals.publish<NotificationReadSignal>({\n recipients: { type: 'user', entityRef: [user] },\n message: { action: 'notification_unread', notification_ids: ids },\n channel: 'notifications',\n });\n }\n }\n\n if (saved === true) {\n await store.markSaved({ user: user, ids });\n } else if (saved === false) {\n await store.markUnsaved({ user: user, ids });\n }\n\n const notifications = await store.getNotifications({ ids, user: user });\n res.status(200).send(notifications);\n });\n\n const sendBroadcastNotification = async (\n baseNotification: Omit<Notification, 'user' | 'id'>,\n opts: { scope?: string; origin: string },\n ) => {\n const { scope, origin } = opts;\n const broadcastNotification = {\n ...baseNotification,\n id: uuid(),\n };\n const notification = await decorateNotification({\n ...broadcastNotification,\n user: '',\n });\n let existingNotification;\n if (scope) {\n existingNotification = await store.getExistingScopeBroadcast({\n scope,\n origin,\n });\n }\n\n let ret = notification;\n if (existingNotification) {\n const restored = await store.restoreExistingNotification({\n id: existingNotification.id,\n notification: { ...notification, user: '' },\n });\n ret = restored ?? notification;\n } else {\n await store.saveBroadcast(notification);\n }\n processorSendNotification(ret);\n\n if (signals) {\n await signals.publish<NewNotificationSignal>({\n recipients: { type: 'broadcast' },\n message: {\n action: 'new_notification',\n notification_id: ret.id,\n },\n channel: 'notifications',\n });\n }\n return notification;\n };\n\n const sendUserNotifications = async (\n baseNotification: Omit<Notification, 'user' | 'id'>,\n users: string[],\n opts: { scope?: string; origin: string },\n ) => {\n const notifications = [];\n const { scope, origin } = opts;\n const uniqueUsers = [...new Set(users)];\n for (const user of uniqueUsers) {\n const userNotification = {\n ...baseNotification,\n id: uuid(),\n user,\n };\n const notification = await decorateNotification(userNotification);\n\n let existingNotification;\n if (scope) {\n existingNotification = await store.getExistingScopeNotification({\n user,\n scope,\n origin,\n });\n }\n\n let ret = notification;\n if (existingNotification) {\n const restored = await store.restoreExistingNotification({\n id: existingNotification.id,\n notification,\n });\n ret = restored ?? notification;\n } else {\n await store.saveNotification(notification);\n }\n\n processorSendNotification(ret);\n notifications.push(ret);\n\n if (signals) {\n await signals.publish<NewNotificationSignal>({\n recipients: { type: 'user', entityRef: [user] },\n message: {\n action: 'new_notification',\n notification_id: ret.id,\n },\n channel: 'notifications',\n });\n }\n }\n return notifications;\n };\n\n // Add new notification\n router.post('/', async (req, res) => {\n const { recipients, payload } = req.body;\n const notifications = [];\n let users = [];\n\n const credentials = await httpAuth.credentials(req, { allow: ['service'] });\n\n const { title, scope } = payload;\n\n if (!recipients || !title) {\n logger.error(`Invalid notification request received`);\n throw new InputError();\n }\n\n const origin = credentials.principal.subject;\n const baseNotification = {\n payload: {\n ...payload,\n severity: payload.severity ?? 'normal',\n },\n origin,\n created: new Date(),\n };\n\n if (recipients.type === 'broadcast') {\n const broadcast = await sendBroadcastNotification(baseNotification, {\n scope,\n origin,\n });\n notifications.push(broadcast);\n } else {\n const entityRef = recipients.entityRef;\n\n try {\n users = await getUsersForEntityRef(entityRef);\n } catch (e) {\n throw new InputError();\n }\n const userNotifications = await sendUserNotifications(\n baseNotification,\n users,\n { scope, origin },\n );\n notifications.push(...userNotifications);\n }\n\n res.json(notifications);\n });\n\n router.use(errorHandler());\n return router;\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { createRouter } from './service/router';\nimport { signalsServiceRef } from '@backstage/plugin-signals-node';\nimport {\n NotificationProcessor,\n notificationsProcessingExtensionPoint,\n NotificationsProcessingExtensionPoint,\n} from '@backstage/plugin-notifications-node';\n\nclass NotificationsProcessingExtensionPointImpl\n implements NotificationsProcessingExtensionPoint\n{\n #processors = new Array<NotificationProcessor>();\n\n addProcessor(\n ...processors: Array<NotificationProcessor | Array<NotificationProcessor>>\n ): void {\n this.#processors.push(...processors.flat());\n }\n\n get processors() {\n return this.#processors;\n }\n}\n\n/**\n * Notifications backend plugin\n *\n * @public\n */\nexport const notificationsPlugin = createBackendPlugin({\n pluginId: 'notifications',\n register(env) {\n const processingExtensions =\n new NotificationsProcessingExtensionPointImpl();\n env.registerExtensionPoint(\n notificationsProcessingExtensionPoint,\n processingExtensions,\n );\n\n env.registerInit({\n deps: {\n auth: coreServices.auth,\n httpAuth: coreServices.httpAuth,\n userInfo: coreServices.userInfo,\n httpRouter: coreServices.httpRouter,\n logger: coreServices.logger,\n database: coreServices.database,\n discovery: coreServices.discovery,\n signals: signalsServiceRef,\n },\n async init({\n auth,\n httpAuth,\n userInfo,\n httpRouter,\n logger,\n database,\n discovery,\n signals,\n }) {\n httpRouter.use(\n await createRouter({\n auth,\n httpAuth,\n userInfo,\n logger,\n database,\n discovery,\n signals,\n processors: processingExtensions.processors,\n }),\n );\n httpRouter.addAuthPolicy({\n path: '/health',\n allow: 'unauthenticated',\n });\n },\n });\n },\n});\n"],"names":["resolvePackagePath","InputError","catalogClient","CatalogClient","isUserEntity","stringifyEntityRef","isGroupEntity","users","RELATION_HAS_MEMBER","RELATION_PARENT_OF","Router","express","uuid","errorHandler","createBackendPlugin","notificationsProcessingExtensionPoint","coreServices","signalsServiceRef"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/database/DatabaseNotificationsStore.ts","../src/service/parseEntityOrderFieldParams.ts","../src/service/router.ts","../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n PluginDatabaseManager,\n resolvePackagePath,\n} from '@backstage/backend-common';\nimport {\n NotificationGetOptions,\n NotificationModifyOptions,\n NotificationsStore,\n} from './NotificationsStore';\nimport {\n Notification,\n NotificationSeverity,\n notificationSeverities,\n} from '@backstage/plugin-notifications-common';\nimport { Knex } from 'knex';\n\nconst migrationsDir = resolvePackagePath(\n '@backstage/plugin-notifications-backend',\n 'migrations',\n);\n\nconst NOTIFICATION_COLUMNS = [\n 'id',\n 'title',\n 'description',\n 'severity',\n 'link',\n 'origin',\n 'scope',\n 'topic',\n 'created',\n 'updated',\n 'user',\n 'read',\n 'saved',\n];\n\nexport const normalizeSeverity = (input?: string): NotificationSeverity => {\n let lower = (input ?? 'normal').toLowerCase() as NotificationSeverity;\n if (notificationSeverities.indexOf(lower) < 0) {\n lower = 'normal';\n }\n return lower;\n};\n\n/** @internal */\nexport class DatabaseNotificationsStore implements NotificationsStore {\n private readonly isSQLite = false;\n\n private constructor(private readonly db: Knex) {\n this.isSQLite = this.db.client.config.client.includes('sqlite3');\n }\n\n static async create({\n database,\n skipMigrations,\n }: {\n database: PluginDatabaseManager;\n skipMigrations?: boolean;\n }): Promise<DatabaseNotificationsStore> {\n const client = await database.getClient();\n\n if (!database.migrations?.skip && !skipMigrations) {\n await client.migrate.latest({\n directory: migrationsDir,\n });\n }\n\n return new DatabaseNotificationsStore(client);\n }\n\n private mapToInteger = (val: string | number | undefined): number => {\n return typeof val === 'string' ? Number.parseInt(val, 10) : val ?? 0;\n };\n\n private mapToNotifications = (rows: any[]): Notification[] => {\n return rows.map(row => ({\n id: row.id,\n user: row.user,\n created: new Date(row.created),\n saved: row.saved,\n read: row.read,\n updated: row.updated,\n origin: row.origin,\n payload: {\n title: row.title,\n description: row.description,\n link: row.link,\n topic: row.topic,\n severity: row.severity,\n scope: row.scope,\n icon: row.icon,\n },\n }));\n };\n\n private mapNotificationToDbRow = (notification: Notification) => {\n return {\n id: notification.id,\n user: notification.user,\n origin: notification.origin,\n created: notification.created,\n topic: notification.payload?.topic,\n link: notification.payload?.link,\n title: notification.payload?.title,\n description: notification.payload?.description,\n severity: normalizeSeverity(notification.payload?.severity),\n scope: notification.payload?.scope,\n saved: notification.saved,\n read: notification.read,\n };\n };\n\n private mapBroadcastToDbRow = (notification: Notification) => {\n return {\n id: notification.id,\n origin: notification.origin,\n created: notification.created,\n topic: notification.payload?.topic,\n link: notification.payload?.link,\n title: notification.payload?.title,\n description: notification.payload?.description,\n severity: normalizeSeverity(notification.payload?.severity),\n scope: notification.payload?.scope,\n };\n };\n\n private getBroadcastUnion = () => {\n return this.db('broadcast')\n .leftJoin(\n 'broadcast_user_status',\n 'id',\n '=',\n 'broadcast_user_status.broadcast_id',\n )\n .select(NOTIFICATION_COLUMNS);\n };\n\n private getNotificationsBaseQuery = (\n options: NotificationGetOptions | NotificationModifyOptions,\n ) => {\n const { user, orderField } = options;\n\n const subQuery = this.db('notification')\n .select(NOTIFICATION_COLUMNS)\n .unionAll([this.getBroadcastUnion()])\n .as('notifications');\n\n const query = this.db.from(subQuery).where(q => {\n q.where('user', user).orWhereNull('user');\n });\n\n if (orderField && orderField.length > 0) {\n orderField.forEach(orderBy => {\n query.orderBy(orderBy.field, orderBy.order);\n });\n } else if (!orderField) {\n query.orderBy('created', 'desc');\n }\n\n if (options.createdAfter) {\n if (this.isSQLite) {\n query.where('created', '>=', options.createdAfter.valueOf());\n } else {\n query.where('created', '>=', options.createdAfter.toISOString());\n }\n }\n\n if (options.limit) {\n query.limit(options.limit);\n }\n\n if (options.offset) {\n query.offset(options.offset);\n }\n\n if (options.search) {\n query.whereRaw(\n `(LOWER(title) LIKE LOWER(?) OR LOWER(description) LIKE LOWER(?))`,\n [`%${options.search}%`, `%${options.search}%`],\n );\n }\n\n if (options.ids) {\n query.whereIn('id', options.ids);\n }\n\n if (options.read) {\n query.whereNotNull('read');\n } else if (options.read === false) {\n query.whereNull('read');\n } // or match both if undefined\n\n if (options.saved) {\n query.whereNotNull('saved');\n } else if (options.saved === false) {\n query.whereNull('saved');\n } // or match both if undefined\n\n if (options.minimumSeverity !== undefined) {\n const idx = notificationSeverities.indexOf(options.minimumSeverity);\n const equalOrHigher = notificationSeverities.slice(0, idx + 1);\n query.whereIn('severity', equalOrHigher);\n }\n\n return query;\n };\n\n async getNotifications(options: NotificationGetOptions) {\n const notificationQuery = this.getNotificationsBaseQuery(options);\n const notifications = await notificationQuery.select(NOTIFICATION_COLUMNS);\n return this.mapToNotifications(notifications);\n }\n\n async getNotificationsCount(options: NotificationGetOptions) {\n const countOptions: NotificationGetOptions = { ...options };\n countOptions.limit = undefined;\n countOptions.offset = undefined;\n countOptions.orderField = [];\n const notificationQuery = this.getNotificationsBaseQuery(countOptions);\n const response = await notificationQuery.count('id as CNT');\n return Number(response[0].CNT);\n }\n\n async saveNotification(notification: Notification) {\n await this.db\n .insert(this.mapNotificationToDbRow(notification))\n .into('notification');\n }\n\n async saveBroadcast(notification: Notification) {\n await this.db\n .insert(this.mapBroadcastToDbRow(notification))\n .into('broadcast');\n if (notification.saved || notification.read) {\n await this.db\n .insert({\n user: notification.user,\n broadcast_id: notification.id,\n saved: notification.saved,\n read: notification.read,\n })\n .into('broadcast_user_status');\n }\n }\n\n async getStatus(options: NotificationGetOptions) {\n const notificationQuery = this.getNotificationsBaseQuery({\n ...options,\n orderField: [],\n });\n const readSubQuery = notificationQuery\n .clone()\n .count('id')\n .whereNotNull('read')\n .as('READ');\n const unreadSubQuery = notificationQuery\n .clone()\n .count('id')\n .whereNull('read')\n .as('UNREAD');\n\n const query = await notificationQuery\n .select(readSubQuery, unreadSubQuery)\n .first();\n\n return {\n unread: this.mapToInteger((query as any)?.UNREAD),\n read: this.mapToInteger((query as any)?.READ),\n };\n }\n\n async getExistingScopeNotification(options: {\n user: string;\n scope: string;\n origin: string;\n }) {\n const query = this.db('notification')\n .where('user', options.user)\n .where('scope', options.scope)\n .where('origin', options.origin)\n .limit(1);\n\n const rows = await query;\n if (!rows || rows.length === 0) {\n return null;\n }\n return rows[0] as Notification;\n }\n\n async getExistingScopeBroadcast(options: { scope: string; origin: string }) {\n const query = this.db('broadcast')\n .where('scope', options.scope)\n .where('origin', options.origin)\n .limit(1);\n\n const rows = await query;\n if (!rows || rows.length === 0) {\n return null;\n }\n return rows[0] as Notification;\n }\n\n async restoreExistingNotification({\n id,\n notification,\n }: {\n id: string;\n notification: Notification;\n }) {\n const updateColumns = {\n title: notification.payload.title,\n description: notification.payload.description,\n link: notification.payload.link,\n topic: notification.payload.topic,\n updated: new Date(),\n severity: normalizeSeverity(notification.payload?.severity),\n read: null,\n };\n\n const notificationQuery = this.db('notification')\n .where('id', id)\n .where('user', notification.user);\n const broadcastQuery = this.db('broadcast').where('id', id);\n\n await Promise.all([\n notificationQuery.update(updateColumns),\n broadcastQuery.update({ ...updateColumns, read: undefined }),\n ]);\n\n return await this.getNotification({ id });\n }\n\n async getNotification(options: { id: string }): Promise<Notification | null> {\n const rows = await this.db\n .select('*')\n .from(\n this.db('notification')\n .select(NOTIFICATION_COLUMNS)\n .unionAll([this.getBroadcastUnion()])\n .as('notifications'),\n )\n .where('id', options.id)\n .limit(1);\n if (!rows || rows.length === 0) {\n return null;\n }\n return this.mapToNotifications(rows)[0];\n }\n\n private markReadSaved = async (\n ids: string[],\n user: string,\n read?: Date | null,\n saved?: Date | null,\n ) => {\n await this.db('notification')\n .whereIn('id', ids)\n .where('user', user)\n .update({ read, saved });\n\n const broadcasts = this.mapToNotifications(\n await this.db('broadcast').whereIn('id', ids).select(),\n );\n\n if (broadcasts.length > 0)\n if (!this.isSQLite) {\n await this.db('broadcast_user_status')\n .insert(\n broadcasts.map(b => ({\n broadcast_id: b.id,\n user,\n read,\n saved,\n })),\n )\n .onConflict(['broadcast_id', 'user'])\n .merge(['read', 'saved']);\n } else {\n // SQLite does not support upsert so fall back to this (mostly for tests and local dev)\n for (const b of broadcasts) {\n const baseQuery = this.db('broadcast_user_status')\n .where('broadcast_id', b.id)\n .where('user', user);\n const exists = await baseQuery.clone().limit(1).select().first();\n if (exists) {\n await baseQuery.clone().update({ read, saved });\n } else {\n await baseQuery\n .clone()\n .insert({ broadcast_id: b.id, user, read, saved });\n }\n }\n }\n };\n\n async markRead(options: NotificationModifyOptions): Promise<void> {\n await this.markReadSaved(options.ids, options.user, new Date(), undefined);\n }\n\n async markUnread(options: NotificationModifyOptions): Promise<void> {\n await this.markReadSaved(options.ids, options.user, null, undefined);\n }\n\n async markSaved(options: NotificationModifyOptions): Promise<void> {\n await this.markReadSaved(options.ids, options.user, undefined, new Date());\n }\n\n async markUnsaved(options: NotificationModifyOptions): Promise<void> {\n await this.markReadSaved(options.ids, options.user, undefined, null);\n }\n}\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// This file is based on the plugins/catalog-backend\n\nimport { InputError } from '@backstage/errors';\nimport { EntityOrder } from '../database';\n\n/**\n * Takes a single unknown parameter and makes sure that it's a single string or\n * an array of strings, and returns as an array.\n */\nexport function parseStringsParam(\n param: unknown,\n ctx: string,\n): string[] | undefined {\n if (param === undefined) {\n return undefined;\n }\n\n const array = [param].flat();\n if (array.some(p => typeof p !== 'string')) {\n throw new InputError(`Invalid ${ctx}, not a string`);\n }\n\n return array as string[];\n}\n\nexport function parseEntityOrderFieldParams(\n params: Record<string, unknown>,\n): EntityOrder[] | undefined {\n const orderFieldStrings = parseStringsParam(params.orderField, 'orderField');\n if (!orderFieldStrings) {\n return undefined;\n }\n\n return orderFieldStrings.map(orderFieldString => {\n const [field, order] = orderFieldString.split(',');\n\n if (order !== undefined && !isOrder(order)) {\n throw new InputError('Invalid order field order, must be asc or desc');\n }\n return { field, order };\n });\n}\n\nexport function isOrder(order: string): order is 'asc' | 'desc' {\n return ['asc', 'desc'].includes(order);\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { errorHandler, PluginDatabaseManager } from '@backstage/backend-common';\nimport express, { Request } from 'express';\nimport Router from 'express-promise-router';\nimport {\n DatabaseNotificationsStore,\n normalizeSeverity,\n NotificationGetOptions,\n} from '../database';\nimport { v4 as uuid } from 'uuid';\nimport { CatalogApi, CatalogClient } from '@backstage/catalog-client';\nimport {\n Entity,\n isGroupEntity,\n isUserEntity,\n RELATION_HAS_MEMBER,\n RELATION_OWNED_BY,\n RELATION_PARENT_OF,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport {\n NotificationProcessor,\n NotificationSendOptions,\n} from '@backstage/plugin-notifications-node';\nimport { InputError } from '@backstage/errors';\nimport {\n AuthService,\n DiscoveryService,\n HttpAuthService,\n LoggerService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\nimport { SignalsService } from '@backstage/plugin-signals-node';\nimport {\n NewNotificationSignal,\n Notification,\n NotificationReadSignal,\n NotificationStatus,\n} from '@backstage/plugin-notifications-common';\nimport { parseEntityOrderFieldParams } from './parseEntityOrderFieldParams';\n\n/** @internal */\nexport interface RouterOptions {\n logger: LoggerService;\n database: PluginDatabaseManager;\n discovery: DiscoveryService;\n auth: AuthService;\n httpAuth: HttpAuthService;\n userInfo: UserInfoService;\n signals?: SignalsService;\n catalog?: CatalogApi;\n processors?: NotificationProcessor[];\n}\n\n/** @internal */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const {\n logger,\n database,\n auth,\n httpAuth,\n userInfo,\n discovery,\n catalog,\n processors = [],\n signals,\n } = options;\n\n const catalogClient =\n catalog ?? new CatalogClient({ discoveryApi: discovery });\n const store = await DatabaseNotificationsStore.create({ database });\n\n const getUser = async (req: Request<unknown>) => {\n const credentials = await httpAuth.credentials(req, { allow: ['user'] });\n const info = await userInfo.getUserInfo(credentials);\n return info.userEntityRef;\n };\n\n const getUsersForEntityRef = async (\n entityRef: string | string[] | null,\n ): Promise<string[]> => {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n\n if (entityRef === null) {\n return [];\n }\n\n const fields = ['kind', 'metadata.name', 'metadata.namespace', 'relations'];\n\n const refs = Array.isArray(entityRef) ? entityRef : [entityRef];\n const entities = await catalogClient.getEntitiesByRefs(\n {\n entityRefs: refs,\n fields,\n },\n { token },\n );\n const mapEntity = async (entity: Entity | undefined): Promise<string[]> => {\n if (!entity) {\n return [];\n }\n\n if (isUserEntity(entity)) {\n return [stringifyEntityRef(entity)];\n } else if (isGroupEntity(entity) && entity.relations) {\n const users = entity.relations\n .filter(relation => relation.type === RELATION_HAS_MEMBER)\n .map(r => r.targetRef);\n\n const childGroupRefs = entity.relations\n .filter(relation => relation.type === RELATION_PARENT_OF)\n .map(r => r.targetRef);\n\n const childGroups = await catalogClient.getEntitiesByRefs(\n {\n entityRefs: childGroupRefs,\n fields,\n },\n { token },\n );\n const childGroupUsers = await Promise.all(\n childGroups.items.map(mapEntity),\n );\n return [...users, ...childGroupUsers.flat(2)];\n } else if (entity.relations) {\n const ownerRef = entity.relations.find(\n relation => relation.type === RELATION_OWNED_BY,\n )?.targetRef;\n\n if (ownerRef) {\n const owner = await catalogClient.getEntityByRef(ownerRef, { token });\n if (owner) {\n return mapEntity(owner);\n }\n }\n }\n\n return [];\n };\n\n const users: string[] = [];\n for (const entity of entities.items) {\n const u = await mapEntity(entity);\n users.push(...u);\n }\n return users;\n };\n\n const processOptions = async (opts: NotificationSendOptions) => {\n let ret = opts;\n for (const processor of processors) {\n try {\n ret = processor.processOptions\n ? await processor.processOptions(ret)\n : ret;\n } catch (e) {\n logger.error(\n `Error while processing notification options with ${processor.getName()}: ${e}`,\n );\n }\n }\n return ret;\n };\n\n const preProcessNotification = async (\n notification: Notification,\n opts: NotificationSendOptions,\n ) => {\n let ret = notification;\n for (const processor of processors) {\n try {\n ret = processor.preProcess\n ? await processor.preProcess(ret, opts)\n : ret;\n } catch (e) {\n logger.error(\n `Error while pre processing notification with ${processor.getName()}: ${e}`,\n );\n }\n }\n return ret;\n };\n\n const postProcessNotification = async (\n notification: Notification,\n opts: NotificationSendOptions,\n ) => {\n for (const processor of processors) {\n if (processor.postProcess) {\n try {\n await processor.postProcess(notification, opts);\n } catch (e) {\n logger.error(\n `Error while post processing notification with ${processor.getName()}: ${e}`,\n );\n }\n }\n }\n };\n\n // TODO: Move to use OpenAPI router instead\n const router = Router();\n router.use(express.json());\n\n router.get('/health', (_, response) => {\n logger.info('PONG!');\n response.json({ status: 'ok' });\n });\n\n router.get('/', async (req, res) => {\n const user = await getUser(req);\n const opts: NotificationGetOptions = {\n user: user,\n };\n if (req.query.offset) {\n opts.offset = Number.parseInt(req.query.offset.toString(), 10);\n }\n if (req.query.limit) {\n opts.limit = Number.parseInt(req.query.limit.toString(), 10);\n }\n if (req.query.orderField) {\n opts.orderField = parseEntityOrderFieldParams(req.query);\n }\n if (req.query.search) {\n opts.search = req.query.search.toString();\n }\n if (req.query.read === 'true') {\n opts.read = true;\n } else if (req.query.read === 'false') {\n opts.read = false;\n // or keep undefined\n }\n if (req.query.saved === 'true') {\n opts.saved = true;\n } else if (req.query.saved === 'false') {\n opts.saved = false;\n // or keep undefined\n }\n if (req.query.createdAfter) {\n const sinceEpoch = Date.parse(String(req.query.createdAfter));\n if (isNaN(sinceEpoch)) {\n throw new InputError('Unexpected date format');\n }\n opts.createdAfter = new Date(sinceEpoch);\n }\n if (req.query.minimumSeverity) {\n opts.minimumSeverity = normalizeSeverity(\n req.query.minimumSeverity.toString(),\n );\n }\n\n const [notifications, totalCount] = await Promise.all([\n store.getNotifications(opts),\n store.getNotificationsCount(opts),\n ]);\n res.send({\n totalCount,\n notifications,\n });\n });\n\n router.get('/status', async (req: Request<any, NotificationStatus>, res) => {\n const user = await getUser(req);\n const status = await store.getStatus({ user });\n res.send(status);\n });\n\n // Make sure this is the last \"GET\" handler\n router.get('/:id', async (req, res) => {\n const user = await getUser(req);\n const opts: NotificationGetOptions = {\n user: user,\n limit: 1,\n ids: [req.params.id],\n };\n const notifications = await store.getNotifications(opts);\n if (notifications.length !== 1) {\n res.status(404).send({ error: 'Not found' });\n return;\n }\n res.send(notifications[0]);\n });\n\n router.post('/update', async (req, res) => {\n const user = await getUser(req);\n const { ids, read, saved } = req.body;\n if (!ids || !Array.isArray(ids)) {\n throw new InputError();\n }\n\n if (read === true) {\n await store.markRead({ user, ids });\n\n if (signals) {\n await signals.publish<NotificationReadSignal>({\n recipients: { type: 'user', entityRef: [user] },\n message: { action: 'notification_read', notification_ids: ids },\n channel: 'notifications',\n });\n }\n } else if (read === false) {\n await store.markUnread({ user: user, ids });\n\n if (signals) {\n await signals.publish<NotificationReadSignal>({\n recipients: { type: 'user', entityRef: [user] },\n message: { action: 'notification_unread', notification_ids: ids },\n channel: 'notifications',\n });\n }\n }\n\n if (saved === true) {\n await store.markSaved({ user: user, ids });\n } else if (saved === false) {\n await store.markUnsaved({ user: user, ids });\n }\n\n const notifications = await store.getNotifications({ ids, user: user });\n res.status(200).send(notifications);\n });\n\n const sendBroadcastNotification = async (\n baseNotification: Omit<Notification, 'user' | 'id'>,\n opts: NotificationSendOptions,\n origin: string,\n ) => {\n const { scope } = opts.payload;\n const broadcastNotification = {\n ...baseNotification,\n user: null,\n id: uuid(),\n };\n const notification = await preProcessNotification(\n broadcastNotification,\n opts,\n );\n let existingNotification;\n if (scope) {\n existingNotification = await store.getExistingScopeBroadcast({\n scope,\n origin,\n });\n }\n\n let ret = notification;\n if (existingNotification) {\n const restored = await store.restoreExistingNotification({\n id: existingNotification.id,\n notification: { ...notification, user: '' },\n });\n ret = restored ?? notification;\n } else {\n await store.saveBroadcast(notification);\n }\n\n if (signals) {\n await signals.publish<NewNotificationSignal>({\n recipients: { type: 'broadcast' },\n message: {\n action: 'new_notification',\n notification_id: ret.id,\n },\n channel: 'notifications',\n });\n postProcessNotification(ret, opts);\n }\n return notification;\n };\n\n const sendUserNotifications = async (\n baseNotification: Omit<Notification, 'user' | 'id'>,\n users: string[],\n opts: NotificationSendOptions,\n origin: string,\n ) => {\n const notifications = [];\n const { scope } = opts.payload;\n const uniqueUsers = [...new Set(users)];\n for (const user of uniqueUsers) {\n const userNotification = {\n ...baseNotification,\n id: uuid(),\n user,\n };\n const notification = await preProcessNotification(userNotification, opts);\n\n let existingNotification;\n if (scope) {\n existingNotification = await store.getExistingScopeNotification({\n user,\n scope,\n origin,\n });\n }\n\n let ret = notification;\n if (existingNotification) {\n const restored = await store.restoreExistingNotification({\n id: existingNotification.id,\n notification,\n });\n ret = restored ?? notification;\n } else {\n await store.saveNotification(notification);\n }\n\n notifications.push(ret);\n\n if (signals) {\n await signals.publish<NewNotificationSignal>({\n recipients: { type: 'user', entityRef: [user] },\n message: {\n action: 'new_notification',\n notification_id: ret.id,\n },\n channel: 'notifications',\n });\n }\n postProcessNotification(ret, opts);\n }\n return notifications;\n };\n\n // Add new notification\n router.post(\n '/',\n async (req: Request<any, Notification[], NotificationSendOptions>, res) => {\n const opts = await processOptions(req.body);\n const { recipients, payload } = opts;\n const notifications: Notification[] = [];\n let users = [];\n\n const credentials = await httpAuth.credentials(req, {\n allow: ['service'],\n });\n\n const { title } = payload;\n\n if (!recipients || !title) {\n logger.error(`Invalid notification request received`);\n throw new InputError(`Invalid notification request received`);\n }\n\n const origin = credentials.principal.subject;\n const baseNotification = {\n payload: {\n ...payload,\n severity: payload.severity ?? 'normal',\n },\n origin,\n created: new Date(),\n };\n\n if (recipients.type === 'broadcast') {\n const broadcast = await sendBroadcastNotification(\n baseNotification,\n opts,\n origin,\n );\n notifications.push(broadcast);\n } else {\n const entityRef = recipients.entityRef;\n\n try {\n users = await getUsersForEntityRef(entityRef);\n } catch (e) {\n logger.error(`Failed to resolve notification receivers: ${e}`);\n throw new InputError('Failed to resolve notification receivers', e);\n }\n\n const userNotifications = await sendUserNotifications(\n baseNotification,\n users,\n opts,\n origin,\n );\n notifications.push(...userNotifications);\n }\n\n res.json(notifications);\n },\n );\n\n router.use(errorHandler());\n return router;\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { createRouter } from './service/router';\nimport { signalsServiceRef } from '@backstage/plugin-signals-node';\nimport {\n NotificationProcessor,\n notificationsProcessingExtensionPoint,\n NotificationsProcessingExtensionPoint,\n} from '@backstage/plugin-notifications-node';\n\nclass NotificationsProcessingExtensionPointImpl\n implements NotificationsProcessingExtensionPoint\n{\n #processors = new Array<NotificationProcessor>();\n\n addProcessor(\n ...processors: Array<NotificationProcessor | Array<NotificationProcessor>>\n ): void {\n this.#processors.push(...processors.flat());\n }\n\n get processors() {\n return this.#processors;\n }\n}\n\n/**\n * Notifications backend plugin\n *\n * @public\n */\nexport const notificationsPlugin = createBackendPlugin({\n pluginId: 'notifications',\n register(env) {\n const processingExtensions =\n new NotificationsProcessingExtensionPointImpl();\n env.registerExtensionPoint(\n notificationsProcessingExtensionPoint,\n processingExtensions,\n );\n\n env.registerInit({\n deps: {\n auth: coreServices.auth,\n httpAuth: coreServices.httpAuth,\n userInfo: coreServices.userInfo,\n httpRouter: coreServices.httpRouter,\n logger: coreServices.logger,\n database: coreServices.database,\n discovery: coreServices.discovery,\n signals: signalsServiceRef,\n },\n async init({\n auth,\n httpAuth,\n userInfo,\n httpRouter,\n logger,\n database,\n discovery,\n signals,\n }) {\n httpRouter.use(\n await createRouter({\n auth,\n httpAuth,\n userInfo,\n logger,\n database,\n discovery,\n signals,\n processors: processingExtensions.processors,\n }),\n );\n httpRouter.addAuthPolicy({\n path: '/health',\n allow: 'unauthenticated',\n });\n },\n });\n },\n});\n"],"names":["resolvePackagePath","notificationSeverities","InputError","catalogClient","CatalogClient","isUserEntity","stringifyEntityRef","isGroupEntity","users","RELATION_HAS_MEMBER","RELATION_PARENT_OF","RELATION_OWNED_BY","Router","express","uuid","errorHandler","createBackendPlugin","notificationsProcessingExtensionPoint","coreServices","signalsServiceRef"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-notifications-backend",
|
|
3
|
-
"version": "0.2.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"backstage": {
|
|
5
5
|
"role": "backend-plugin"
|
|
6
6
|
},
|
|
@@ -31,17 +31,17 @@
|
|
|
31
31
|
"test": "backstage-cli package test"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@backstage/backend-common": "^0.21.7
|
|
35
|
-
"@backstage/backend-plugin-api": "^0.6.17
|
|
36
|
-
"@backstage/catalog-client": "^1.6.4
|
|
34
|
+
"@backstage/backend-common": "^0.21.7",
|
|
35
|
+
"@backstage/backend-plugin-api": "^0.6.17",
|
|
36
|
+
"@backstage/catalog-client": "^1.6.4",
|
|
37
37
|
"@backstage/catalog-model": "^1.4.5",
|
|
38
38
|
"@backstage/config": "^1.2.0",
|
|
39
39
|
"@backstage/errors": "^1.2.4",
|
|
40
|
-
"@backstage/plugin-auth-node": "^0.4.12
|
|
41
|
-
"@backstage/plugin-events-node": "^0.3.3
|
|
42
|
-
"@backstage/plugin-notifications-common": "^0.0.
|
|
43
|
-
"@backstage/plugin-notifications-node": "^0.1.3
|
|
44
|
-
"@backstage/plugin-signals-node": "^0.1.3
|
|
40
|
+
"@backstage/plugin-auth-node": "^0.4.12",
|
|
41
|
+
"@backstage/plugin-events-node": "^0.3.3",
|
|
42
|
+
"@backstage/plugin-notifications-common": "^0.0.3",
|
|
43
|
+
"@backstage/plugin-notifications-node": "^0.1.3",
|
|
44
|
+
"@backstage/plugin-signals-node": "^0.1.3",
|
|
45
45
|
"express": "^4.17.1",
|
|
46
46
|
"express-promise-router": "^4.1.0",
|
|
47
47
|
"knex": "^3.0.0",
|
|
@@ -51,8 +51,13 @@
|
|
|
51
51
|
"yn": "^4.0.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@backstage/backend-
|
|
55
|
-
"@backstage/
|
|
54
|
+
"@backstage/backend-defaults": "^0.2.17",
|
|
55
|
+
"@backstage/backend-test-utils": "^0.3.7",
|
|
56
|
+
"@backstage/cli": "^0.26.3",
|
|
57
|
+
"@backstage/plugin-auth-backend": "^0.22.4",
|
|
58
|
+
"@backstage/plugin-auth-backend-module-guest-provider": "^0.1.3",
|
|
59
|
+
"@backstage/plugin-events-backend": "^0.3.4",
|
|
60
|
+
"@backstage/plugin-signals-backend": "^0.1.3",
|
|
56
61
|
"@types/express": "^4.17.6",
|
|
57
62
|
"@types/supertest": "^2.0.8",
|
|
58
63
|
"msw": "^1.0.0",
|