@oneuptime/common 7.0.3517 → 7.0.3538
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/Models/DatabaseModels/AlertFeed.ts +12 -4
- package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +2 -0
- package/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.ts +59 -2
- package/Models/DatabaseModels/ScheduledMaintenanceFeed.ts +15 -7
- package/Models/DatabaseModels/UserNotificationRule.ts +50 -0
- package/Models/DatabaseModels/UserOnCallLog.ts +48 -1
- package/Models/DatabaseModels/UserOnCallLogTimeline.ts +49 -2
- package/Server/API/BillingInvoiceAPI.ts +2 -32
- package/Server/API/UserOnCallLogTimelineAPI.ts +32 -8
- package/Server/Infrastructure/Postgres/SchemaMigrations/1737141420441-MigrationName.ts +131 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Services/AlertFeedService.ts +44 -37
- package/Server/Services/AlertInternalNoteService.ts +73 -0
- package/Server/Services/AlertOwnerTeamService.ts +112 -0
- package/Server/Services/AlertOwnerUserService.ts +114 -0
- package/Server/Services/AlertService.ts +121 -0
- package/Server/Services/AlertStateTimelineService.ts +52 -0
- package/Server/Services/BillingInvoiceService.ts +170 -0
- package/Server/Services/IncidentFeedService.ts +59 -54
- package/Server/Services/IncidentInternalNoteService.ts +46 -1
- package/Server/Services/IncidentPublicNoteService.ts +47 -2
- package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +32 -14
- package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +86 -27
- package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +30 -12
- package/Server/Services/ScheduledMaintenanceFeedService.ts +51 -40
- package/Server/Services/ScheduledMaintenanceInternalNoteService.ts +75 -0
- package/Server/Services/ScheduledMaintenanceOwnerTeamService.ts +116 -0
- package/Server/Services/ScheduledMaintenanceOwnerUserService.ts +118 -0
- package/Server/Services/ScheduledMaintenancePublicNoteService.ts +74 -1
- package/Server/Services/ScheduledMaintenanceService.ts +68 -0
- package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +30 -0
- package/Server/Services/UserNotificationRuleService.ts +450 -67
- package/Server/Services/UserOnCallLogService.ts +61 -18
- package/Server/Services/UserOnCallLogTimelineService.ts +25 -11
- package/Server/Utils/Logger.ts +14 -0
- package/Types/Email/EmailTemplateType.ts +1 -0
- package/Types/NotificationRule/NotificationRuleType.ts +1 -1
- package/UI/Utils/Project.ts +25 -0
- package/build/dist/Models/DatabaseModels/AlertFeed.js +12 -4
- package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +2 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js +60 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceFeed.js +15 -7
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserNotificationRule.js +49 -0
- package/build/dist/Models/DatabaseModels/UserNotificationRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js +48 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +50 -2
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
- package/build/dist/Server/API/BillingInvoiceAPI.js +2 -19
- package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
- package/build/dist/Server/API/UserOnCallLogTimelineAPI.js +10 -2
- package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1737141420441-MigrationName.js +50 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1737141420441-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AlertFeedService.js +43 -35
- package/build/dist/Server/Services/AlertFeedService.js.map +1 -1
- package/build/dist/Server/Services/AlertInternalNoteService.js +56 -0
- package/build/dist/Server/Services/AlertInternalNoteService.js.map +1 -1
- package/build/dist/Server/Services/AlertOwnerTeamService.js +86 -0
- package/build/dist/Server/Services/AlertOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/AlertOwnerUserService.js +89 -0
- package/build/dist/Server/Services/AlertOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +107 -3
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/AlertStateTimelineService.js +44 -1
- package/build/dist/Server/Services/AlertStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/BillingInvoiceService.js +123 -0
- package/build/dist/Server/Services/BillingInvoiceService.js.map +1 -1
- package/build/dist/Server/Services/IncidentFeedService.js +45 -39
- package/build/dist/Server/Services/IncidentFeedService.js.map +1 -1
- package/build/dist/Server/Services/IncidentInternalNoteService.js +37 -0
- package/build/dist/Server/Services/IncidentInternalNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js +38 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +18 -8
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +70 -24
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +26 -11
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceFeedService.js +45 -37
- package/build/dist/Server/Services/ScheduledMaintenanceFeedService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js +56 -0
- package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerTeamService.js +86 -0
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerUserService.js +89 -0
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +56 -0
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +57 -0
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +24 -0
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js +334 -67
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserOnCallLogService.js +66 -27
- package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
- package/build/dist/Server/Services/UserOnCallLogTimelineService.js +16 -5
- package/build/dist/Server/Services/UserOnCallLogTimelineService.js.map +1 -1
- package/build/dist/Server/Utils/Logger.js +11 -0
- package/build/dist/Server/Utils/Logger.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/NotificationRule/NotificationRuleType.js +1 -1
- package/build/dist/Types/NotificationRule/NotificationRuleType.js.map +1 -1
- package/build/dist/UI/Utils/Project.js +11 -0
- package/build/dist/UI/Utils/Project.js.map +1 -1
- package/package.json +2 -2
|
@@ -4,6 +4,7 @@ import OneUptimeDate from "../../Types/Date";
|
|
|
4
4
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
5
5
|
import ObjectID from "../../Types/ObjectID";
|
|
6
6
|
import { IsBillingEnabled } from "../EnvironmentConfig";
|
|
7
|
+
import logger from "../Utils/Logger";
|
|
7
8
|
import DatabaseService from "./DatabaseService";
|
|
8
9
|
import Model, {
|
|
9
10
|
AlertFeedEventType,
|
|
@@ -27,54 +28,60 @@ export class Service extends DatabaseService<Model> {
|
|
|
27
28
|
displayColor?: Color | undefined;
|
|
28
29
|
userId?: ObjectID | undefined;
|
|
29
30
|
postedAt?: Date | undefined;
|
|
30
|
-
}): Promise<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
}): Promise<void> {
|
|
32
|
+
try {
|
|
33
|
+
if (!data.alertId) {
|
|
34
|
+
throw new BadDataException("Alert ID is required");
|
|
35
|
+
}
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
if (!data.feedInfoInMarkdown) {
|
|
38
|
+
throw new BadDataException("Log in markdown is required");
|
|
39
|
+
}
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
if (!data.alertFeedEventType) {
|
|
42
|
+
throw new BadDataException("Alert log event is required");
|
|
43
|
+
}
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
if (!data.projectId) {
|
|
46
|
+
throw new BadDataException("Project ID is required");
|
|
47
|
+
}
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
const alertFeed: Model = new Model();
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
if (!data.displayColor) {
|
|
52
|
+
data.displayColor = Blue500;
|
|
53
|
+
}
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
if (data.userId) {
|
|
56
|
+
alertFeed.userId = data.userId;
|
|
57
|
+
}
|
|
56
58
|
|
|
57
|
-
|
|
59
|
+
alertFeed.displayColor = data.displayColor;
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
alertFeed.alertId = data.alertId;
|
|
62
|
+
alertFeed.feedInfoInMarkdown = data.feedInfoInMarkdown;
|
|
63
|
+
alertFeed.alertFeedEventType = data.alertFeedEventType;
|
|
64
|
+
alertFeed.projectId = data.projectId;
|
|
63
65
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
if (!data.postedAt) {
|
|
67
|
+
alertFeed.postedAt = OneUptimeDate.getCurrentDate();
|
|
68
|
+
}
|
|
67
69
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
if (data.moreInformationInMarkdown) {
|
|
71
|
+
alertFeed.moreInformationInMarkdown = data.moreInformationInMarkdown;
|
|
72
|
+
}
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
await this.create({
|
|
75
|
+
data: alertFeed,
|
|
76
|
+
props: {
|
|
77
|
+
isRoot: true,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
} catch (error) {
|
|
81
|
+
logger.error("AlertFeedService.createAlertFeed");
|
|
82
|
+
logger.error(error);
|
|
83
|
+
// we dont want to throw the error here, as this is a non-critical operation
|
|
84
|
+
}
|
|
78
85
|
}
|
|
79
86
|
}
|
|
80
87
|
|
|
@@ -1,10 +1,83 @@
|
|
|
1
|
+
import ObjectID from "../../Types/ObjectID";
|
|
1
2
|
import DatabaseService from "./DatabaseService";
|
|
2
3
|
import Model from "Common/Models/DatabaseModels/AlertInternalNote";
|
|
4
|
+
import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
|
|
5
|
+
import AlertFeedService from "./AlertFeedService";
|
|
6
|
+
import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
|
|
7
|
+
import { Blue500 } from "../../Types/BrandColors";
|
|
8
|
+
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
3
9
|
|
|
4
10
|
export class Service extends DatabaseService<Model> {
|
|
5
11
|
public constructor() {
|
|
6
12
|
super(Model);
|
|
7
13
|
}
|
|
14
|
+
|
|
15
|
+
public override async onCreateSuccess(
|
|
16
|
+
_onCreate: OnCreate<Model>,
|
|
17
|
+
createdItem: Model,
|
|
18
|
+
): Promise<Model> {
|
|
19
|
+
const userId: ObjectID | null | undefined =
|
|
20
|
+
createdItem.createdByUserId || createdItem.createdByUser?.id;
|
|
21
|
+
|
|
22
|
+
await AlertFeedService.createAlertFeed({
|
|
23
|
+
alertId: createdItem.alertId!,
|
|
24
|
+
projectId: createdItem.projectId!,
|
|
25
|
+
alertFeedEventType: AlertFeedEventType.PrivateNote,
|
|
26
|
+
displayColor: Blue500,
|
|
27
|
+
userId: userId || undefined,
|
|
28
|
+
|
|
29
|
+
feedInfoInMarkdown: `**Posted Internal / Private Note**
|
|
30
|
+
|
|
31
|
+
${createdItem.note}
|
|
32
|
+
`,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return createdItem;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public override async onUpdateSuccess(
|
|
39
|
+
onUpdate: OnUpdate<Model>,
|
|
40
|
+
_updatedItemIds: Array<ObjectID>,
|
|
41
|
+
): Promise<OnUpdate<Model>> {
|
|
42
|
+
if (onUpdate.updateBy.data.note) {
|
|
43
|
+
const updatedItems: Array<Model> = await this.findBy({
|
|
44
|
+
query: onUpdate.updateBy.query,
|
|
45
|
+
limit: LIMIT_PER_PROJECT,
|
|
46
|
+
skip: 0,
|
|
47
|
+
props: {
|
|
48
|
+
isRoot: true,
|
|
49
|
+
},
|
|
50
|
+
select: {
|
|
51
|
+
alertId: true,
|
|
52
|
+
projectId: true,
|
|
53
|
+
note: true,
|
|
54
|
+
createdByUserId: true,
|
|
55
|
+
createdByUser: {
|
|
56
|
+
_id: true,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const userId: ObjectID | null | undefined =
|
|
62
|
+
onUpdate.updateBy.props.userId;
|
|
63
|
+
|
|
64
|
+
for (const updatedItem of updatedItems) {
|
|
65
|
+
await AlertFeedService.createAlertFeed({
|
|
66
|
+
alertId: updatedItem.alertId!,
|
|
67
|
+
projectId: updatedItem.projectId!,
|
|
68
|
+
alertFeedEventType: AlertFeedEventType.PrivateNote,
|
|
69
|
+
displayColor: Blue500,
|
|
70
|
+
userId: userId || undefined,
|
|
71
|
+
|
|
72
|
+
feedInfoInMarkdown: `**Updated Internal / Private Note**
|
|
73
|
+
|
|
74
|
+
${updatedItem.note}
|
|
75
|
+
`,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return onUpdate;
|
|
80
|
+
}
|
|
8
81
|
}
|
|
9
82
|
|
|
10
83
|
export default new Service();
|
|
@@ -1,10 +1,122 @@
|
|
|
1
|
+
import Team from "../../Models/DatabaseModels/Team";
|
|
2
|
+
import ObjectID from "../../Types/ObjectID";
|
|
3
|
+
import DeleteBy from "../Types/Database/DeleteBy";
|
|
4
|
+
import { OnCreate, OnDelete } from "../Types/Database/Hooks";
|
|
1
5
|
import DatabaseService from "./DatabaseService";
|
|
2
6
|
import Model from "Common/Models/DatabaseModels/AlertOwnerTeam";
|
|
7
|
+
import TeamService from "./TeamService";
|
|
8
|
+
import AlertFeedService from "./AlertFeedService";
|
|
9
|
+
import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
|
|
10
|
+
import { Gray500, Red500 } from "../../Types/BrandColors";
|
|
3
11
|
|
|
4
12
|
export class Service extends DatabaseService<Model> {
|
|
5
13
|
public constructor() {
|
|
6
14
|
super(Model);
|
|
7
15
|
}
|
|
16
|
+
|
|
17
|
+
protected override async onBeforeDelete(
|
|
18
|
+
deleteBy: DeleteBy<Model>,
|
|
19
|
+
): Promise<OnDelete<Model>> {
|
|
20
|
+
const itemsToDelete: Model[] = await this.findBy({
|
|
21
|
+
query: deleteBy.query,
|
|
22
|
+
limit: deleteBy.limit,
|
|
23
|
+
skip: deleteBy.skip,
|
|
24
|
+
props: {
|
|
25
|
+
isRoot: true,
|
|
26
|
+
},
|
|
27
|
+
select: {
|
|
28
|
+
alertId: true,
|
|
29
|
+
projectId: true,
|
|
30
|
+
teamId: true,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
carryForward: {
|
|
36
|
+
itemsToDelete: itemsToDelete,
|
|
37
|
+
},
|
|
38
|
+
deleteBy: deleteBy,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
protected override async onDeleteSuccess(
|
|
43
|
+
onDelete: OnDelete<Model>,
|
|
44
|
+
_itemIdsBeforeDelete: Array<ObjectID>,
|
|
45
|
+
): Promise<OnDelete<Model>> {
|
|
46
|
+
const deleteByUserId: ObjectID | undefined =
|
|
47
|
+
onDelete.deleteBy.deletedByUser?.id || onDelete.deleteBy.props.userId;
|
|
48
|
+
|
|
49
|
+
const itemsToDelete: Model[] = onDelete.carryForward.itemsToDelete;
|
|
50
|
+
|
|
51
|
+
for (const item of itemsToDelete) {
|
|
52
|
+
const alertId: ObjectID | undefined = item.alertId;
|
|
53
|
+
const projectId: ObjectID | undefined = item.projectId;
|
|
54
|
+
const teamId: ObjectID | undefined = item.teamId;
|
|
55
|
+
|
|
56
|
+
if (alertId && teamId && projectId) {
|
|
57
|
+
const team: Team | null = await TeamService.findOneById({
|
|
58
|
+
id: teamId,
|
|
59
|
+
select: {
|
|
60
|
+
name: true,
|
|
61
|
+
},
|
|
62
|
+
props: {
|
|
63
|
+
isRoot: true,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (team && team.name) {
|
|
68
|
+
await AlertFeedService.createAlertFeed({
|
|
69
|
+
alertId: alertId,
|
|
70
|
+
projectId: projectId,
|
|
71
|
+
alertFeedEventType: AlertFeedEventType.OwnerTeamRemoved,
|
|
72
|
+
displayColor: Red500,
|
|
73
|
+
feedInfoInMarkdown: `**Team ${team.name}** was removed from the alert as the owner.`,
|
|
74
|
+
userId: deleteByUserId || undefined,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return onDelete;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public override async onCreateSuccess(
|
|
84
|
+
onCreate: OnCreate<Model>,
|
|
85
|
+
createdItem: Model,
|
|
86
|
+
): Promise<Model> {
|
|
87
|
+
// add alert feed.
|
|
88
|
+
|
|
89
|
+
const alertId: ObjectID | undefined = createdItem.alertId;
|
|
90
|
+
const projectId: ObjectID | undefined = createdItem.projectId;
|
|
91
|
+
const teamId: ObjectID | undefined = createdItem.teamId;
|
|
92
|
+
const createdByUserId: ObjectID | undefined =
|
|
93
|
+
createdItem.createdByUserId || onCreate.createBy.props.userId;
|
|
94
|
+
|
|
95
|
+
if (alertId && teamId && projectId) {
|
|
96
|
+
const team: Team | null = await TeamService.findOneById({
|
|
97
|
+
id: teamId,
|
|
98
|
+
select: {
|
|
99
|
+
name: true,
|
|
100
|
+
},
|
|
101
|
+
props: {
|
|
102
|
+
isRoot: true,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
if (team && team.name) {
|
|
107
|
+
await AlertFeedService.createAlertFeed({
|
|
108
|
+
alertId: alertId,
|
|
109
|
+
projectId: projectId,
|
|
110
|
+
alertFeedEventType: AlertFeedEventType.OwnerTeamAdded,
|
|
111
|
+
displayColor: Gray500,
|
|
112
|
+
feedInfoInMarkdown: `**Team ${team.name}** was added to the alert as the owner.`,
|
|
113
|
+
userId: createdByUserId || undefined,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return createdItem;
|
|
119
|
+
}
|
|
8
120
|
}
|
|
9
121
|
|
|
10
122
|
export default new Service();
|
|
@@ -1,10 +1,124 @@
|
|
|
1
|
+
import User from "../../Models/DatabaseModels/User";
|
|
2
|
+
import ObjectID from "../../Types/ObjectID";
|
|
3
|
+
import DeleteBy from "../Types/Database/DeleteBy";
|
|
4
|
+
import { OnCreate, OnDelete } from "../Types/Database/Hooks";
|
|
1
5
|
import DatabaseService from "./DatabaseService";
|
|
2
6
|
import Model from "Common/Models/DatabaseModels/AlertOwnerUser";
|
|
7
|
+
import UserService from "./UserService";
|
|
8
|
+
import AlertFeedService from "./AlertFeedService";
|
|
9
|
+
import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
|
|
10
|
+
import { Gray500, Red500 } from "../../Types/BrandColors";
|
|
3
11
|
|
|
4
12
|
export class Service extends DatabaseService<Model> {
|
|
5
13
|
public constructor() {
|
|
6
14
|
super(Model);
|
|
7
15
|
}
|
|
16
|
+
|
|
17
|
+
protected override async onBeforeDelete(
|
|
18
|
+
deleteBy: DeleteBy<Model>,
|
|
19
|
+
): Promise<OnDelete<Model>> {
|
|
20
|
+
const itemsToDelete: Model[] = await this.findBy({
|
|
21
|
+
query: deleteBy.query,
|
|
22
|
+
limit: deleteBy.limit,
|
|
23
|
+
skip: deleteBy.skip,
|
|
24
|
+
props: {
|
|
25
|
+
isRoot: true,
|
|
26
|
+
},
|
|
27
|
+
select: {
|
|
28
|
+
alertId: true,
|
|
29
|
+
projectId: true,
|
|
30
|
+
userId: true,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
carryForward: {
|
|
36
|
+
itemsToDelete: itemsToDelete,
|
|
37
|
+
},
|
|
38
|
+
deleteBy: deleteBy,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
protected override async onDeleteSuccess(
|
|
43
|
+
onDelete: OnDelete<Model>,
|
|
44
|
+
_itemIdsBeforeDelete: Array<ObjectID>,
|
|
45
|
+
): Promise<OnDelete<Model>> {
|
|
46
|
+
const deleteByUserId: ObjectID | undefined =
|
|
47
|
+
onDelete.deleteBy.deletedByUser?.id || onDelete.deleteBy.props.userId;
|
|
48
|
+
|
|
49
|
+
const itemsToDelete: Model[] = onDelete.carryForward.itemsToDelete;
|
|
50
|
+
|
|
51
|
+
for (const item of itemsToDelete) {
|
|
52
|
+
const alertId: ObjectID | undefined = item.alertId;
|
|
53
|
+
const projectId: ObjectID | undefined = item.projectId;
|
|
54
|
+
const userId: ObjectID | undefined = item.userId;
|
|
55
|
+
|
|
56
|
+
if (alertId && userId && projectId) {
|
|
57
|
+
const user: User | null = await UserService.findOneById({
|
|
58
|
+
id: userId,
|
|
59
|
+
select: {
|
|
60
|
+
name: true,
|
|
61
|
+
email: true,
|
|
62
|
+
},
|
|
63
|
+
props: {
|
|
64
|
+
isRoot: true,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (user && user.name) {
|
|
69
|
+
await AlertFeedService.createAlertFeed({
|
|
70
|
+
alertId: alertId,
|
|
71
|
+
projectId: projectId,
|
|
72
|
+
alertFeedEventType: AlertFeedEventType.OwnerUserRemoved,
|
|
73
|
+
displayColor: Red500,
|
|
74
|
+
feedInfoInMarkdown: `**${user.name.toString()}** (${user.email?.toString()}) was removed from the alert as the owner.`,
|
|
75
|
+
userId: deleteByUserId || undefined,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return onDelete;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public override async onCreateSuccess(
|
|
85
|
+
onCreate: OnCreate<Model>,
|
|
86
|
+
createdItem: Model,
|
|
87
|
+
): Promise<Model> {
|
|
88
|
+
// add alert feed.
|
|
89
|
+
|
|
90
|
+
const alertId: ObjectID | undefined = createdItem.alertId;
|
|
91
|
+
const projectId: ObjectID | undefined = createdItem.projectId;
|
|
92
|
+
const userId: ObjectID | undefined = createdItem.userId;
|
|
93
|
+
const createdByUserId: ObjectID | undefined =
|
|
94
|
+
createdItem.createdByUserId || onCreate.createBy.props.userId;
|
|
95
|
+
|
|
96
|
+
if (alertId && userId && projectId) {
|
|
97
|
+
const user: User | null = await UserService.findOneById({
|
|
98
|
+
id: userId,
|
|
99
|
+
select: {
|
|
100
|
+
name: true,
|
|
101
|
+
email: true,
|
|
102
|
+
},
|
|
103
|
+
props: {
|
|
104
|
+
isRoot: true,
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
if (user && user.name) {
|
|
109
|
+
await AlertFeedService.createAlertFeed({
|
|
110
|
+
alertId: alertId,
|
|
111
|
+
projectId: projectId,
|
|
112
|
+
alertFeedEventType: AlertFeedEventType.OwnerUserAdded,
|
|
113
|
+
displayColor: Gray500,
|
|
114
|
+
feedInfoInMarkdown: `**${user.name.toString()}** (${user.email?.toString()}) was added to the alert as the owner.`,
|
|
115
|
+
userId: createdByUserId || undefined,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return createdItem;
|
|
121
|
+
}
|
|
8
122
|
}
|
|
9
123
|
|
|
10
124
|
export default new Service();
|
|
@@ -38,6 +38,9 @@ import Metric, {
|
|
|
38
38
|
ServiceType,
|
|
39
39
|
} from "../../Models/AnalyticsModels/Metric";
|
|
40
40
|
import AlertMetricType from "../../Types/Alerts/AlertMetricType";
|
|
41
|
+
import AlertFeedService from "./AlertFeedService";
|
|
42
|
+
import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
|
|
43
|
+
import { Gray500, Red500 } from "../../Types/BrandColors";
|
|
41
44
|
|
|
42
45
|
export class Service extends DatabaseService<Model> {
|
|
43
46
|
public constructor() {
|
|
@@ -224,6 +227,48 @@ export class Service extends DatabaseService<Model> {
|
|
|
224
227
|
throw new BadDataException("currentAlertStateId is required");
|
|
225
228
|
}
|
|
226
229
|
|
|
230
|
+
const createdByUserId: ObjectID | undefined | null =
|
|
231
|
+
createdItem.createdByUserId || createdItem.createdByUser?.id;
|
|
232
|
+
|
|
233
|
+
await AlertFeedService.createAlertFeed({
|
|
234
|
+
alertId: createdItem.id!,
|
|
235
|
+
projectId: createdItem.projectId!,
|
|
236
|
+
alertFeedEventType: AlertFeedEventType.AlertCreated,
|
|
237
|
+
displayColor: Red500,
|
|
238
|
+
feedInfoInMarkdown: `**Alert Created**:
|
|
239
|
+
|
|
240
|
+
**Alert Title**:
|
|
241
|
+
|
|
242
|
+
${createdItem.title || "No title provided."}
|
|
243
|
+
|
|
244
|
+
**Description**:
|
|
245
|
+
|
|
246
|
+
${createdItem.description || "No description provided."}
|
|
247
|
+
|
|
248
|
+
`,
|
|
249
|
+
userId: createdByUserId || undefined,
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
await AlertFeedService.createAlertFeed({
|
|
253
|
+
alertId: createdItem.id!,
|
|
254
|
+
projectId: createdItem.projectId!,
|
|
255
|
+
alertFeedEventType: AlertFeedEventType.RootCause,
|
|
256
|
+
displayColor: Red500,
|
|
257
|
+
feedInfoInMarkdown: `**Root Cause**
|
|
258
|
+
|
|
259
|
+
${createdItem.rootCause || "No root cause provided."}`,
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
await AlertFeedService.createAlertFeed({
|
|
263
|
+
alertId: createdItem.id!,
|
|
264
|
+
projectId: createdItem.projectId!,
|
|
265
|
+
alertFeedEventType: AlertFeedEventType.RemediationNotes,
|
|
266
|
+
displayColor: Red500,
|
|
267
|
+
feedInfoInMarkdown: `**Remediation Notes**
|
|
268
|
+
|
|
269
|
+
${createdItem.remediationNotes || "No remediation notes provided."}`,
|
|
270
|
+
});
|
|
271
|
+
|
|
227
272
|
await this.changeAlertState({
|
|
228
273
|
projectId: createdItem.projectId,
|
|
229
274
|
alertId: createdItem.id,
|
|
@@ -445,6 +490,82 @@ export class Service extends DatabaseService<Model> {
|
|
|
445
490
|
}
|
|
446
491
|
}
|
|
447
492
|
|
|
493
|
+
if (updatedItemIds.length > 0) {
|
|
494
|
+
for (const alertId of updatedItemIds) {
|
|
495
|
+
if (onUpdate.updateBy.data.title) {
|
|
496
|
+
// add alert feed.
|
|
497
|
+
const createdByUserId: ObjectID | undefined | null =
|
|
498
|
+
onUpdate.updateBy.props.userId;
|
|
499
|
+
|
|
500
|
+
await AlertFeedService.createAlertFeed({
|
|
501
|
+
alertId: alertId,
|
|
502
|
+
projectId: onUpdate.updateBy.props.tenantId as ObjectID,
|
|
503
|
+
alertFeedEventType: AlertFeedEventType.AlertUpdated,
|
|
504
|
+
displayColor: Gray500,
|
|
505
|
+
feedInfoInMarkdown: `**Alert title was updated.** Here's the new title.
|
|
506
|
+
|
|
507
|
+
${onUpdate.updateBy.data.title || "No title provided."}
|
|
508
|
+
`,
|
|
509
|
+
userId: createdByUserId || undefined,
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (onUpdate.updateBy.data.rootCause) {
|
|
514
|
+
// add alert feed.
|
|
515
|
+
const createdByUserId: ObjectID | undefined | null =
|
|
516
|
+
onUpdate.updateBy.props.userId;
|
|
517
|
+
|
|
518
|
+
await AlertFeedService.createAlertFeed({
|
|
519
|
+
alertId: alertId,
|
|
520
|
+
projectId: onUpdate.updateBy.props.tenantId as ObjectID,
|
|
521
|
+
alertFeedEventType: AlertFeedEventType.AlertUpdated,
|
|
522
|
+
displayColor: Gray500,
|
|
523
|
+
feedInfoInMarkdown: `**Alert root cause was updated.** Here's the new root cause.
|
|
524
|
+
|
|
525
|
+
${onUpdate.updateBy.data.rootCause || "No root cause provided."}
|
|
526
|
+
`,
|
|
527
|
+
userId: createdByUserId || undefined,
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if (onUpdate.updateBy.data.description) {
|
|
532
|
+
// add alert feed.
|
|
533
|
+
const createdByUserId: ObjectID | undefined | null =
|
|
534
|
+
onUpdate.updateBy.props.userId;
|
|
535
|
+
|
|
536
|
+
await AlertFeedService.createAlertFeed({
|
|
537
|
+
alertId: alertId,
|
|
538
|
+
projectId: onUpdate.updateBy.props.tenantId as ObjectID,
|
|
539
|
+
alertFeedEventType: AlertFeedEventType.AlertUpdated,
|
|
540
|
+
displayColor: Gray500,
|
|
541
|
+
feedInfoInMarkdown: `**Alert description was updated.** Here's the new description.
|
|
542
|
+
|
|
543
|
+
${onUpdate.updateBy.data.description || "No description provided."}
|
|
544
|
+
`,
|
|
545
|
+
userId: createdByUserId || undefined,
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
if (onUpdate.updateBy.data.remediationNotes) {
|
|
550
|
+
// add alert feed.
|
|
551
|
+
const createdByUserId: ObjectID | undefined | null =
|
|
552
|
+
onUpdate.updateBy.props.userId;
|
|
553
|
+
|
|
554
|
+
await AlertFeedService.createAlertFeed({
|
|
555
|
+
alertId: alertId,
|
|
556
|
+
projectId: onUpdate.updateBy.props.tenantId as ObjectID,
|
|
557
|
+
alertFeedEventType: AlertFeedEventType.AlertUpdated,
|
|
558
|
+
displayColor: Gray500,
|
|
559
|
+
feedInfoInMarkdown: `**Remediation notes were updated.** Here are the new notes.
|
|
560
|
+
|
|
561
|
+
${onUpdate.updateBy.data.remediationNotes || "No remediation notes provided."}
|
|
562
|
+
`,
|
|
563
|
+
userId: createdByUserId || undefined,
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
448
569
|
return onUpdate;
|
|
449
570
|
}
|
|
450
571
|
|
|
@@ -19,6 +19,8 @@ import { JSONObject } from "../../Types/JSON";
|
|
|
19
19
|
import AlertInternalNote from "../../Models/DatabaseModels/AlertInternalNote";
|
|
20
20
|
import AlertInternalNoteService from "./AlertInternalNoteService";
|
|
21
21
|
import logger from "../Utils/Logger";
|
|
22
|
+
import AlertFeedService from "./AlertFeedService";
|
|
23
|
+
import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
|
|
22
24
|
|
|
23
25
|
export class Service extends DatabaseService<AlertStateTimeline> {
|
|
24
26
|
public constructor() {
|
|
@@ -130,10 +132,15 @@ export class Service extends DatabaseService<AlertStateTimeline> {
|
|
|
130
132
|
});
|
|
131
133
|
}
|
|
132
134
|
|
|
135
|
+
const privateNote: string | undefined = (
|
|
136
|
+
createBy.miscDataProps as JSONObject | undefined
|
|
137
|
+
)?.["privateNote"] as string | undefined;
|
|
138
|
+
|
|
133
139
|
return {
|
|
134
140
|
createBy,
|
|
135
141
|
carryForward: {
|
|
136
142
|
lastAlertStateTimelineId: lastAlertStateTimeline?.id || null,
|
|
143
|
+
privateNote: privateNote,
|
|
137
144
|
},
|
|
138
145
|
};
|
|
139
146
|
}
|
|
@@ -164,6 +171,36 @@ export class Service extends DatabaseService<AlertStateTimeline> {
|
|
|
164
171
|
});
|
|
165
172
|
}
|
|
166
173
|
|
|
174
|
+
const alertState: AlertState | null = await AlertStateService.findOneBy({
|
|
175
|
+
query: {
|
|
176
|
+
_id: createdItem.alertStateId.toString()!,
|
|
177
|
+
},
|
|
178
|
+
props: {
|
|
179
|
+
isRoot: true,
|
|
180
|
+
},
|
|
181
|
+
select: {
|
|
182
|
+
_id: true,
|
|
183
|
+
isResolvedState: true,
|
|
184
|
+
isAcknowledgedState: true,
|
|
185
|
+
isCreatedState: true,
|
|
186
|
+
color: true,
|
|
187
|
+
name: true,
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
const stateName: string = alertState?.name || "";
|
|
192
|
+
|
|
193
|
+
await AlertFeedService.createAlertFeed({
|
|
194
|
+
alertId: createdItem.alertId!,
|
|
195
|
+
projectId: createdItem.projectId!,
|
|
196
|
+
alertFeedEventType: AlertFeedEventType.AlertStateChanged,
|
|
197
|
+
displayColor: alertState?.color,
|
|
198
|
+
feedInfoInMarkdown: "**Alert State** changed to **" + stateName + "**",
|
|
199
|
+
moreInformationInMarkdown: `**Cause:**
|
|
200
|
+
${createdItem.rootCause}`,
|
|
201
|
+
userId: createdItem.createdByUserId || onCreate.createBy.props.userId,
|
|
202
|
+
});
|
|
203
|
+
|
|
167
204
|
await AlertService.updateOneBy({
|
|
168
205
|
query: {
|
|
169
206
|
_id: createdItem.alertId?.toString(),
|
|
@@ -174,6 +211,21 @@ export class Service extends DatabaseService<AlertStateTimeline> {
|
|
|
174
211
|
props: onCreate.createBy.props,
|
|
175
212
|
});
|
|
176
213
|
|
|
214
|
+
if (onCreate.carryForward.privateNote) {
|
|
215
|
+
const privateNote: string = onCreate.carryForward.privateNote;
|
|
216
|
+
|
|
217
|
+
const alertInternalNote: AlertInternalNote = new AlertInternalNote();
|
|
218
|
+
alertInternalNote.alertId = createdItem.alertId;
|
|
219
|
+
alertInternalNote.note = privateNote;
|
|
220
|
+
alertInternalNote.createdAt = createdItem.startsAt!;
|
|
221
|
+
alertInternalNote.projectId = createdItem.projectId!;
|
|
222
|
+
|
|
223
|
+
await AlertInternalNoteService.create({
|
|
224
|
+
data: alertInternalNote,
|
|
225
|
+
props: onCreate.createBy.props,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
177
229
|
AlertService.refreshAlertMetrics({
|
|
178
230
|
alertId: createdItem.alertId,
|
|
179
231
|
}).catch((error: Error) => {
|