@oneuptime/common 7.0.3148 → 7.0.3153

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.
Files changed (222) hide show
  1. package/Models/DatabaseModels/Alert.ts +1010 -0
  2. package/Models/DatabaseModels/AlertCustomField.ts +340 -0
  3. package/Models/DatabaseModels/AlertInternalNote.ts +371 -0
  4. package/Models/DatabaseModels/AlertNoteTemplate.ts +352 -0
  5. package/Models/DatabaseModels/AlertOwnerTeam.ts +416 -0
  6. package/Models/DatabaseModels/AlertOwnerUser.ts +415 -0
  7. package/Models/DatabaseModels/AlertSeverity.ts +426 -0
  8. package/Models/DatabaseModels/AlertState.ts +502 -0
  9. package/Models/DatabaseModels/AlertStateTimeline.ts +525 -0
  10. package/Models/DatabaseModels/Incident.ts +2 -11
  11. package/Models/DatabaseModels/Index.ts +34 -12
  12. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +55 -0
  13. package/Models/DatabaseModels/TableView.ts +452 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1727894983857-MigrationName.ts +51 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/1727906598804-MigrationName.ts +553 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
  17. package/Server/Services/AlertCustomFieldService.ts +9 -0
  18. package/Server/Services/AlertInternalNoteService.ts +10 -0
  19. package/Server/Services/AlertNoteTemplateService.ts +9 -0
  20. package/Server/Services/AlertOwnerTeamService.ts +10 -0
  21. package/Server/Services/AlertOwnerUserService.ts +10 -0
  22. package/Server/Services/AlertService.ts +568 -0
  23. package/Server/Services/AlertSeverityService.ts +154 -0
  24. package/Server/Services/AlertStateService.ts +227 -0
  25. package/Server/Services/AlertStateTimelineService.ts +334 -0
  26. package/Server/Services/CallLogService.ts +4 -1
  27. package/Server/Services/DatabaseService.ts +17 -20
  28. package/Server/Services/EmailLogService.ts +4 -1
  29. package/Server/Services/IncidentService.ts +4 -1
  30. package/Server/Services/IncidentStateTimelineService.ts +4 -1
  31. package/Server/Services/Index.ts +23 -0
  32. package/Server/Services/MonitorStatusTimelineService.ts +4 -1
  33. package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +4 -1
  34. package/Server/Services/OnCallDutyPolicyService.ts +15 -0
  35. package/Server/Services/ProjectService.ts +99 -1
  36. package/Server/Services/ScheduledMaintenanceService.ts +4 -1
  37. package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +4 -1
  38. package/Server/Services/ShortLinkService.ts +4 -1
  39. package/Server/Services/SmsLogService.ts +4 -1
  40. package/Server/Services/TableViewService.ts +10 -0
  41. package/Server/Services/TelemetryUsageBillingService.ts +4 -1
  42. package/Server/Services/UserNotificationSettingService.ts +58 -0
  43. package/Server/Services/UserOnCallLogService.ts +4 -1
  44. package/Server/Services/WorkflowLogService.ts +4 -1
  45. package/Server/Types/Workflow/Components/API/Post.ts +25 -0
  46. package/Server/Utils/Monitor/MonitorAlert.ts +273 -0
  47. package/Server/Utils/Monitor/MonitorIncident.ts +298 -0
  48. package/Server/Utils/Monitor/MonitorResource.ts +67 -387
  49. package/Server/Utils/Monitor/MonitorStatusTimeline.ts +120 -0
  50. package/Server/Utils/Realtime.ts +1 -35
  51. package/Types/Email/EmailTemplateType.ts +7 -0
  52. package/Types/Icon/IconProp.ts +1 -0
  53. package/Types/Monitor/CriteriaAlert.ts +11 -0
  54. package/Types/Monitor/MonitorCriteria.ts +2 -0
  55. package/Types/Monitor/MonitorCriteriaInstance.ts +134 -1
  56. package/Types/Monitor/MonitorStep.ts +1 -0
  57. package/Types/Monitor/MonitorSteps.ts +1 -0
  58. package/Types/NotificationSetting/NotificationSettingEventType.ts +7 -0
  59. package/Types/Permission.ts +369 -1
  60. package/Types/Telemetry/TelemetryQuery.ts +10 -0
  61. package/Types/UserNotification/UserNotificationEventType.ts +1 -0
  62. package/UI/Components/Card/Card.tsx +40 -31
  63. package/UI/Components/Card/CardButtons/MoreButton.ts +15 -0
  64. package/UI/Components/HeaderAlert/HeaderAlert.tsx +75 -16
  65. package/UI/Components/HeaderAlert/HeaderAlertGroup.tsx +50 -0
  66. package/UI/Components/HeaderAlert/HeaderModelAlert.tsx +5 -1
  67. package/UI/Components/Icon/Icon.tsx +8 -0
  68. package/UI/Components/ModelDetail/CardModelDetail.tsx +4 -2
  69. package/UI/Components/ModelTable/BaseModelTable.tsx +70 -2
  70. package/UI/Components/ModelTable/TableView.tsx +317 -0
  71. package/UI/Components/MoreMenu/Divider.tsx +7 -0
  72. package/UI/Components/MoreMenu/MoreMenu.tsx +54 -0
  73. package/UI/Components/MoreMenu/MoreMenuItem.tsx +37 -0
  74. package/UI/Components/MoreMenu/MoreMenuSection.tsx +22 -0
  75. package/UI/Components/Toggle/Toggle.tsx +14 -0
  76. package/build/dist/Models/DatabaseModels/Alert.js +1028 -0
  77. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -0
  78. package/build/dist/Models/DatabaseModels/AlertCustomField.js +360 -0
  79. package/build/dist/Models/DatabaseModels/AlertCustomField.js.map +1 -0
  80. package/build/dist/Models/DatabaseModels/AlertInternalNote.js +391 -0
  81. package/build/dist/Models/DatabaseModels/AlertInternalNote.js.map +1 -0
  82. package/build/dist/Models/DatabaseModels/AlertNoteTemplate.js +372 -0
  83. package/build/dist/Models/DatabaseModels/AlertNoteTemplate.js.map +1 -0
  84. package/build/dist/Models/DatabaseModels/AlertOwnerTeam.js +434 -0
  85. package/build/dist/Models/DatabaseModels/AlertOwnerTeam.js.map +1 -0
  86. package/build/dist/Models/DatabaseModels/AlertOwnerUser.js +433 -0
  87. package/build/dist/Models/DatabaseModels/AlertOwnerUser.js.map +1 -0
  88. package/build/dist/Models/DatabaseModels/AlertSeverity.js +450 -0
  89. package/build/dist/Models/DatabaseModels/AlertSeverity.js.map +1 -0
  90. package/build/dist/Models/DatabaseModels/AlertState.js +530 -0
  91. package/build/dist/Models/DatabaseModels/AlertState.js.map +1 -0
  92. package/build/dist/Models/DatabaseModels/AlertStateTimeline.js +548 -0
  93. package/build/dist/Models/DatabaseModels/AlertStateTimeline.js.map +1 -0
  94. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  95. package/build/dist/Models/DatabaseModels/Index.js +29 -9
  96. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  97. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +55 -0
  98. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
  99. package/build/dist/Models/DatabaseModels/TableView.js +475 -0
  100. package/build/dist/Models/DatabaseModels/TableView.js.map +1 -0
  101. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1727894983857-MigrationName.js +24 -0
  102. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1727894983857-MigrationName.js.map +1 -0
  103. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1727906598804-MigrationName.js +198 -0
  104. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1727906598804-MigrationName.js.map +1 -0
  105. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
  106. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  107. package/build/dist/Server/Services/AlertCustomFieldService.js +9 -0
  108. package/build/dist/Server/Services/AlertCustomFieldService.js.map +1 -0
  109. package/build/dist/Server/Services/AlertInternalNoteService.js +9 -0
  110. package/build/dist/Server/Services/AlertInternalNoteService.js.map +1 -0
  111. package/build/dist/Server/Services/AlertNoteTemplateService.js +9 -0
  112. package/build/dist/Server/Services/AlertNoteTemplateService.js.map +1 -0
  113. package/build/dist/Server/Services/AlertOwnerTeamService.js +9 -0
  114. package/build/dist/Server/Services/AlertOwnerTeamService.js.map +1 -0
  115. package/build/dist/Server/Services/AlertOwnerUserService.js +9 -0
  116. package/build/dist/Server/Services/AlertOwnerUserService.js.map +1 -0
  117. package/build/dist/Server/Services/AlertService.js +418 -0
  118. package/build/dist/Server/Services/AlertService.js.map +1 -0
  119. package/build/dist/Server/Services/AlertSeverityService.js +108 -0
  120. package/build/dist/Server/Services/AlertSeverityService.js.map +1 -0
  121. package/build/dist/Server/Services/AlertStateService.js +158 -0
  122. package/build/dist/Server/Services/AlertStateService.js.map +1 -0
  123. package/build/dist/Server/Services/AlertStateTimelineService.js +267 -0
  124. package/build/dist/Server/Services/AlertStateTimelineService.js.map +1 -0
  125. package/build/dist/Server/Services/CallLogService.js +4 -1
  126. package/build/dist/Server/Services/CallLogService.js.map +1 -1
  127. package/build/dist/Server/Services/DatabaseService.js +9 -9
  128. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  129. package/build/dist/Server/Services/EmailLogService.js +4 -1
  130. package/build/dist/Server/Services/EmailLogService.js.map +1 -1
  131. package/build/dist/Server/Services/IncidentService.js +4 -1
  132. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  133. package/build/dist/Server/Services/IncidentStateTimelineService.js +4 -1
  134. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  135. package/build/dist/Server/Services/Index.js +21 -0
  136. package/build/dist/Server/Services/Index.js.map +1 -1
  137. package/build/dist/Server/Services/MonitorStatusTimelineService.js +4 -1
  138. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  139. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +4 -1
  140. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
  141. package/build/dist/Server/Services/OnCallDutyPolicyService.js +8 -0
  142. package/build/dist/Server/Services/OnCallDutyPolicyService.js.map +1 -1
  143. package/build/dist/Server/Services/ProjectService.js +80 -1
  144. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  145. package/build/dist/Server/Services/ScheduledMaintenanceService.js +4 -1
  146. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  147. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +4 -1
  148. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
  149. package/build/dist/Server/Services/ShortLinkService.js +4 -1
  150. package/build/dist/Server/Services/ShortLinkService.js.map +1 -1
  151. package/build/dist/Server/Services/SmsLogService.js +4 -1
  152. package/build/dist/Server/Services/SmsLogService.js.map +1 -1
  153. package/build/dist/Server/Services/TableViewService.js +9 -0
  154. package/build/dist/Server/Services/TableViewService.js.map +1 -0
  155. package/build/dist/Server/Services/TelemetryUsageBillingService.js +4 -1
  156. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  157. package/build/dist/Server/Services/UserNotificationSettingService.js +49 -0
  158. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  159. package/build/dist/Server/Services/UserOnCallLogService.js +4 -1
  160. package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
  161. package/build/dist/Server/Services/WorkflowLogService.js +4 -1
  162. package/build/dist/Server/Services/WorkflowLogService.js.map +1 -1
  163. package/build/dist/Server/Types/Workflow/Components/API/Post.js +14 -0
  164. package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
  165. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +177 -0
  166. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -0
  167. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +187 -0
  168. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -0
  169. package/build/dist/Server/Utils/Monitor/MonitorResource.js +46 -254
  170. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  171. package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js +79 -0
  172. package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js.map +1 -0
  173. package/build/dist/Server/Utils/Realtime.js +3 -28
  174. package/build/dist/Server/Utils/Realtime.js.map +1 -1
  175. package/build/dist/Types/Email/EmailTemplateType.js +4 -0
  176. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  177. package/build/dist/Types/Icon/IconProp.js +1 -0
  178. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  179. package/build/dist/Types/Monitor/CriteriaAlert.js +2 -0
  180. package/build/dist/Types/Monitor/CriteriaAlert.js.map +1 -0
  181. package/build/dist/Types/Monitor/MonitorCriteria.js +1 -0
  182. package/build/dist/Types/Monitor/MonitorCriteria.js.map +1 -1
  183. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +120 -1
  184. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  185. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  186. package/build/dist/Types/Monitor/MonitorSteps.js.map +1 -1
  187. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +5 -0
  188. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
  189. package/build/dist/Types/Permission.js +323 -1
  190. package/build/dist/Types/Permission.js.map +1 -1
  191. package/build/dist/Types/Telemetry/TelemetryQuery.js +2 -0
  192. package/build/dist/Types/Telemetry/TelemetryQuery.js.map +1 -0
  193. package/build/dist/Types/UserNotification/UserNotificationEventType.js +1 -0
  194. package/build/dist/Types/UserNotification/UserNotificationEventType.js.map +1 -1
  195. package/build/dist/UI/Components/Card/Card.js +3 -2
  196. package/build/dist/UI/Components/Card/Card.js.map +1 -1
  197. package/build/dist/UI/Components/Card/CardButtons/MoreButton.js +12 -0
  198. package/build/dist/UI/Components/Card/CardButtons/MoreButton.js.map +1 -0
  199. package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js +53 -9
  200. package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js.map +1 -1
  201. package/build/dist/UI/Components/HeaderAlert/HeaderAlertGroup.js +25 -0
  202. package/build/dist/UI/Components/HeaderAlert/HeaderAlertGroup.js.map +1 -0
  203. package/build/dist/UI/Components/HeaderAlert/HeaderModelAlert.js +1 -1
  204. package/build/dist/UI/Components/HeaderAlert/HeaderModelAlert.js.map +1 -1
  205. package/build/dist/UI/Components/Icon/Icon.js +3 -0
  206. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  207. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
  208. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +46 -0
  209. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  210. package/build/dist/UI/Components/ModelTable/TableView.js +183 -0
  211. package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -0
  212. package/build/dist/UI/Components/MoreMenu/Divider.js +6 -0
  213. package/build/dist/UI/Components/MoreMenu/Divider.js.map +1 -0
  214. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +19 -0
  215. package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -0
  216. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +13 -0
  217. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -0
  218. package/build/dist/UI/Components/MoreMenu/MoreMenuSection.js +10 -0
  219. package/build/dist/UI/Components/MoreMenu/MoreMenuSection.js.map +1 -0
  220. package/build/dist/UI/Components/Toggle/Toggle.js +7 -1
  221. package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
  222. package/package.json +2 -2
@@ -0,0 +1,568 @@
1
+ import DatabaseConfig from "../DatabaseConfig";
2
+ import CreateBy from "../Types/Database/CreateBy";
3
+ import DeleteBy from "../Types/Database/DeleteBy";
4
+ import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
5
+ import QueryHelper from "../Types/Database/QueryHelper";
6
+ import DatabaseService from "./DatabaseService";
7
+ import AlertOwnerTeamService from "./AlertOwnerTeamService";
8
+ import AlertOwnerUserService from "./AlertOwnerUserService";
9
+ import AlertStateService from "./AlertStateService";
10
+ import AlertStateTimelineService from "./AlertStateTimelineService";
11
+ import OnCallDutyPolicyService from "./OnCallDutyPolicyService";
12
+ import TeamMemberService from "./TeamMemberService";
13
+ import UserService from "./UserService";
14
+ import URL from "../../Types/API/URL";
15
+ import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
16
+ import SortOrder from "../../Types/BaseDatabase/SortOrder";
17
+ import LIMIT_MAX, { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
18
+ import BadDataException from "../../Types/Exception/BadDataException";
19
+ import { JSONObject } from "../../Types/JSON";
20
+ import ObjectID from "../../Types/ObjectID";
21
+ import PositiveNumber from "../../Types/PositiveNumber";
22
+ import Typeof from "../../Types/Typeof";
23
+ import UserNotificationEventType from "../../Types/UserNotification/UserNotificationEventType";
24
+ import Model from "Common/Models/DatabaseModels/Alert";
25
+ import AlertOwnerTeam from "Common/Models/DatabaseModels/AlertOwnerTeam";
26
+ import AlertOwnerUser from "Common/Models/DatabaseModels/AlertOwnerUser";
27
+ import AlertState from "Common/Models/DatabaseModels/AlertState";
28
+ import AlertStateTimeline from "Common/Models/DatabaseModels/AlertStateTimeline";
29
+ import User from "Common/Models/DatabaseModels/User";
30
+ import { IsBillingEnabled } from "../EnvironmentConfig";
31
+
32
+ export class Service extends DatabaseService<Model> {
33
+ public constructor() {
34
+ super(Model);
35
+ if (IsBillingEnabled) {
36
+ this.hardDeleteItemsOlderThanInDays("createdAt", 120);
37
+ }
38
+ }
39
+
40
+ public async isAlertAcknowledged(data: {
41
+ alertId: ObjectID;
42
+ }): Promise<boolean> {
43
+ const alert: Model | null = await this.findOneBy({
44
+ query: {
45
+ _id: data.alertId,
46
+ },
47
+ select: {
48
+ projectId: true,
49
+ currentAlertState: {
50
+ order: true,
51
+ },
52
+ },
53
+ props: {
54
+ isRoot: true,
55
+ },
56
+ });
57
+
58
+ if (!alert) {
59
+ throw new BadDataException("Alert not found");
60
+ }
61
+
62
+ if (!alert.projectId) {
63
+ throw new BadDataException("Incient Project ID not found");
64
+ }
65
+
66
+ const ackAlertState: AlertState =
67
+ await AlertStateService.getAcknowledgedAlertState({
68
+ projectId: alert.projectId,
69
+ props: {
70
+ isRoot: true,
71
+ },
72
+ });
73
+
74
+ const currentAlertStateOrder: number = alert.currentAlertState!.order!;
75
+ const ackAlertStateOrder: number = ackAlertState.order!;
76
+
77
+ if (currentAlertStateOrder >= ackAlertStateOrder) {
78
+ return true;
79
+ }
80
+
81
+ return false;
82
+ }
83
+
84
+ public async acknowledgeAlert(
85
+ alertId: ObjectID,
86
+ acknowledgedByUserId: ObjectID,
87
+ ): Promise<void> {
88
+ const alert: Model | null = await this.findOneById({
89
+ id: alertId,
90
+ select: {
91
+ projectId: true,
92
+ },
93
+ props: {
94
+ isRoot: true,
95
+ },
96
+ });
97
+
98
+ if (!alert || !alert.projectId) {
99
+ throw new BadDataException("Alert not found.");
100
+ }
101
+
102
+ const alertState: AlertState | null = await AlertStateService.findOneBy({
103
+ query: {
104
+ projectId: alert.projectId,
105
+ isAcknowledgedState: true,
106
+ },
107
+ select: {
108
+ _id: true,
109
+ },
110
+ props: {
111
+ isRoot: true,
112
+ },
113
+ });
114
+
115
+ if (!alertState || !alertState.id) {
116
+ throw new BadDataException(
117
+ "Acknowledged state not found for this project. Please add acknowledged state from settings.",
118
+ );
119
+ }
120
+
121
+ const alertStateTimeline: AlertStateTimeline = new AlertStateTimeline();
122
+ alertStateTimeline.projectId = alert.projectId;
123
+ alertStateTimeline.alertId = alertId;
124
+ alertStateTimeline.alertStateId = alertState.id;
125
+ alertStateTimeline.createdByUserId = acknowledgedByUserId;
126
+
127
+ await AlertStateTimelineService.create({
128
+ data: alertStateTimeline,
129
+ props: {
130
+ isRoot: true,
131
+ },
132
+ });
133
+ }
134
+
135
+ protected override async onBeforeCreate(
136
+ createBy: CreateBy<Model>,
137
+ ): Promise<OnCreate<Model>> {
138
+ if (!createBy.props.tenantId && !createBy.props.isRoot) {
139
+ throw new BadDataException("ProjectId required to create alert.");
140
+ }
141
+
142
+ const alertState: AlertState | null = await AlertStateService.findOneBy({
143
+ query: {
144
+ projectId: createBy.props.tenantId || createBy.data.projectId!,
145
+ isCreatedState: true,
146
+ },
147
+ select: {
148
+ _id: true,
149
+ },
150
+ props: {
151
+ isRoot: true,
152
+ },
153
+ });
154
+
155
+ if (!alertState || !alertState.id) {
156
+ throw new BadDataException(
157
+ "Created alert state not found for this project. Please add created alert state from settings.",
158
+ );
159
+ }
160
+
161
+ createBy.data.currentAlertStateId = alertState.id;
162
+
163
+ if (
164
+ (createBy.data.createdByUserId ||
165
+ createBy.data.createdByUser ||
166
+ createBy.props.userId) &&
167
+ !createBy.data.rootCause
168
+ ) {
169
+ let userId: ObjectID | undefined = createBy.data.createdByUserId;
170
+
171
+ if (createBy.props.userId) {
172
+ userId = createBy.props.userId;
173
+ }
174
+
175
+ if (createBy.data.createdByUser && createBy.data.createdByUser.id) {
176
+ userId = createBy.data.createdByUser.id;
177
+ }
178
+
179
+ const user: User | null = await UserService.findOneBy({
180
+ query: {
181
+ _id: userId?.toString() as string,
182
+ },
183
+ select: {
184
+ _id: true,
185
+ name: true,
186
+ email: true,
187
+ },
188
+ props: {
189
+ isRoot: true,
190
+ },
191
+ });
192
+
193
+ if (user) {
194
+ createBy.data.rootCause = `Alert created by ${user.name} (${user.email})`;
195
+ }
196
+ }
197
+
198
+ return { createBy, carryForward: null };
199
+ }
200
+
201
+ protected override async onCreateSuccess(
202
+ onCreate: OnCreate<Model>,
203
+ createdItem: Model,
204
+ ): Promise<Model> {
205
+ if (!createdItem.projectId) {
206
+ throw new BadDataException("projectId is required");
207
+ }
208
+
209
+ if (!createdItem.id) {
210
+ throw new BadDataException("id is required");
211
+ }
212
+
213
+ if (!createdItem.currentAlertStateId) {
214
+ throw new BadDataException("currentAlertStateId is required");
215
+ }
216
+
217
+ await this.changeAlertState({
218
+ projectId: createdItem.projectId,
219
+ alertId: createdItem.id,
220
+ alertStateId: createdItem.currentAlertStateId,
221
+ notifyOwners: false,
222
+ rootCause: createdItem.rootCause,
223
+ stateChangeLog: createdItem.createdStateLog,
224
+ props: {
225
+ isRoot: true,
226
+ },
227
+ });
228
+
229
+ // add owners.
230
+
231
+ if (
232
+ onCreate.createBy.miscDataProps &&
233
+ (onCreate.createBy.miscDataProps["ownerTeams"] ||
234
+ onCreate.createBy.miscDataProps["ownerUsers"])
235
+ ) {
236
+ await this.addOwners(
237
+ createdItem.projectId,
238
+ createdItem.id,
239
+ (onCreate.createBy.miscDataProps["ownerUsers"] as Array<ObjectID>) ||
240
+ [],
241
+ (onCreate.createBy.miscDataProps["ownerTeams"] as Array<ObjectID>) ||
242
+ [],
243
+ false,
244
+ onCreate.createBy.props,
245
+ );
246
+ }
247
+
248
+ if (
249
+ createdItem.onCallDutyPolicies?.length &&
250
+ createdItem.onCallDutyPolicies?.length > 0
251
+ ) {
252
+ for (const policy of createdItem.onCallDutyPolicies) {
253
+ await OnCallDutyPolicyService.executePolicy(
254
+ new ObjectID(policy._id as string),
255
+ {
256
+ triggeredByAlertId: createdItem.id!,
257
+ userNotificationEventType: UserNotificationEventType.AlertCreated,
258
+ },
259
+ );
260
+ }
261
+ }
262
+
263
+ return createdItem;
264
+ }
265
+
266
+ public async getAlertIdentifiedDate(alertId: ObjectID): Promise<Date> {
267
+ const timeline: AlertStateTimeline | null =
268
+ await AlertStateTimelineService.findOneBy({
269
+ query: {
270
+ alertId: alertId,
271
+ },
272
+ select: {
273
+ startsAt: true,
274
+ },
275
+ sort: {
276
+ startsAt: SortOrder.Ascending,
277
+ },
278
+ props: {
279
+ isRoot: true,
280
+ },
281
+ });
282
+
283
+ if (!timeline || !timeline.startsAt) {
284
+ throw new BadDataException("Alert identified date not found.");
285
+ }
286
+
287
+ return timeline.startsAt;
288
+ }
289
+
290
+ public async findOwners(alertId: ObjectID): Promise<Array<User>> {
291
+ if (!alertId) {
292
+ throw new BadDataException("alertId is required");
293
+ }
294
+
295
+ const ownerUsers: Array<AlertOwnerUser> =
296
+ await AlertOwnerUserService.findBy({
297
+ query: {
298
+ alertId: alertId,
299
+ },
300
+ select: {
301
+ _id: true,
302
+ user: {
303
+ _id: true,
304
+ email: true,
305
+ name: true,
306
+ timezone: true,
307
+ },
308
+ },
309
+ props: {
310
+ isRoot: true,
311
+ },
312
+ limit: LIMIT_PER_PROJECT,
313
+ skip: 0,
314
+ });
315
+
316
+ const ownerTeams: Array<AlertOwnerTeam> =
317
+ await AlertOwnerTeamService.findBy({
318
+ query: {
319
+ alertId: alertId,
320
+ },
321
+ select: {
322
+ _id: true,
323
+ teamId: true,
324
+ },
325
+ skip: 0,
326
+ limit: LIMIT_PER_PROJECT,
327
+ props: {
328
+ isRoot: true,
329
+ },
330
+ });
331
+
332
+ const users: Array<User> =
333
+ ownerUsers.map((ownerUser: AlertOwnerUser) => {
334
+ return ownerUser.user!;
335
+ }) || [];
336
+
337
+ if (ownerTeams.length > 0) {
338
+ const teamIds: Array<ObjectID> =
339
+ ownerTeams.map((ownerTeam: AlertOwnerTeam) => {
340
+ return ownerTeam.teamId!;
341
+ }) || [];
342
+
343
+ const teamUsers: Array<User> =
344
+ await TeamMemberService.getUsersInTeams(teamIds);
345
+
346
+ for (const teamUser of teamUsers) {
347
+ //check if the user is already added.
348
+ const isUserAlreadyAdded: User | undefined = users.find(
349
+ (user: User) => {
350
+ return user.id!.toString() === teamUser.id!.toString();
351
+ },
352
+ );
353
+
354
+ if (!isUserAlreadyAdded) {
355
+ users.push(teamUser);
356
+ }
357
+ }
358
+ }
359
+
360
+ return users;
361
+ }
362
+
363
+ public async addOwners(
364
+ projectId: ObjectID,
365
+ alertId: ObjectID,
366
+ userIds: Array<ObjectID>,
367
+ teamIds: Array<ObjectID>,
368
+ notifyOwners: boolean,
369
+ props: DatabaseCommonInteractionProps,
370
+ ): Promise<void> {
371
+ for (let teamId of teamIds) {
372
+ if (typeof teamId === Typeof.String) {
373
+ teamId = new ObjectID(teamId.toString());
374
+ }
375
+
376
+ const teamOwner: AlertOwnerTeam = new AlertOwnerTeam();
377
+ teamOwner.alertId = alertId;
378
+ teamOwner.projectId = projectId;
379
+ teamOwner.teamId = teamId;
380
+ teamOwner.isOwnerNotified = !notifyOwners;
381
+
382
+ await AlertOwnerTeamService.create({
383
+ data: teamOwner,
384
+ props: props,
385
+ });
386
+ }
387
+
388
+ for (let userId of userIds) {
389
+ if (typeof userId === Typeof.String) {
390
+ userId = new ObjectID(userId.toString());
391
+ }
392
+ const teamOwner: AlertOwnerUser = new AlertOwnerUser();
393
+ teamOwner.alertId = alertId;
394
+ teamOwner.projectId = projectId;
395
+ teamOwner.userId = userId;
396
+ teamOwner.isOwnerNotified = !notifyOwners;
397
+ await AlertOwnerUserService.create({
398
+ data: teamOwner,
399
+ props: props,
400
+ });
401
+ }
402
+ }
403
+
404
+ public async getAlertLinkInDashboard(
405
+ projectId: ObjectID,
406
+ alertId: ObjectID,
407
+ ): Promise<URL> {
408
+ const dashboardUrl: URL = await DatabaseConfig.getDashboardUrl();
409
+
410
+ return URL.fromString(dashboardUrl.toString()).addRoute(
411
+ `/${projectId.toString()}/alerts/${alertId.toString()}`,
412
+ );
413
+ }
414
+
415
+ protected override async onUpdateSuccess(
416
+ onUpdate: OnUpdate<Model>,
417
+ updatedItemIds: ObjectID[],
418
+ ): Promise<OnUpdate<Model>> {
419
+ if (
420
+ onUpdate.updateBy.data.currentAlertStateId &&
421
+ onUpdate.updateBy.props.tenantId
422
+ ) {
423
+ for (const itemId of updatedItemIds) {
424
+ await this.changeAlertState({
425
+ projectId: onUpdate.updateBy.props.tenantId as ObjectID,
426
+ alertId: itemId,
427
+ alertStateId: onUpdate.updateBy.data.currentAlertStateId as ObjectID,
428
+ notifyOwners: true,
429
+ rootCause: "This status was changed when the alert was updated.",
430
+ stateChangeLog: undefined,
431
+ props: {
432
+ isRoot: true,
433
+ },
434
+ });
435
+ }
436
+ }
437
+
438
+ return onUpdate;
439
+ }
440
+
441
+ public async doesMonitorHasMoreActiveManualAlerts(
442
+ monitorId: ObjectID,
443
+ proojectId: ObjectID,
444
+ ): Promise<boolean> {
445
+ const resolvedState: AlertState | null = await AlertStateService.findOneBy({
446
+ query: {
447
+ projectId: proojectId,
448
+ isResolvedState: true,
449
+ },
450
+ props: {
451
+ isRoot: true,
452
+ },
453
+ select: {
454
+ _id: true,
455
+ order: true,
456
+ },
457
+ });
458
+
459
+ const alertCount: PositiveNumber = await this.countBy({
460
+ query: {
461
+ monitorId: monitorId,
462
+ currentAlertState: {
463
+ order: QueryHelper.lessThan(resolvedState?.order as number),
464
+ },
465
+ isCreatedAutomatically: false,
466
+ },
467
+ props: {
468
+ isRoot: true,
469
+ },
470
+ });
471
+
472
+ return alertCount.toNumber() > 0;
473
+ }
474
+
475
+ protected override async onBeforeDelete(
476
+ deleteBy: DeleteBy<Model>,
477
+ ): Promise<OnDelete<Model>> {
478
+ const alerts: Array<Model> = await this.findBy({
479
+ query: deleteBy.query,
480
+ limit: LIMIT_MAX,
481
+ skip: 0,
482
+ select: {
483
+ projectId: true,
484
+ monitor: {
485
+ _id: true,
486
+ },
487
+ },
488
+ props: {
489
+ isRoot: true,
490
+ },
491
+ });
492
+
493
+ return {
494
+ deleteBy,
495
+ carryForward: {
496
+ alerts: alerts,
497
+ },
498
+ };
499
+ }
500
+
501
+ public async changeAlertState(data: {
502
+ projectId: ObjectID;
503
+ alertId: ObjectID;
504
+ alertStateId: ObjectID;
505
+ notifyOwners: boolean;
506
+ rootCause: string | undefined;
507
+ stateChangeLog: JSONObject | undefined;
508
+ props: DatabaseCommonInteractionProps | undefined;
509
+ }): Promise<void> {
510
+ const {
511
+ projectId,
512
+ alertId,
513
+ alertStateId,
514
+ notifyOwners,
515
+ rootCause,
516
+ stateChangeLog,
517
+ props,
518
+ } = data;
519
+
520
+ // get last monitor status timeline.
521
+ const lastAlertStatusTimeline: AlertStateTimeline | null =
522
+ await AlertStateTimelineService.findOneBy({
523
+ query: {
524
+ alertId: alertId,
525
+ projectId: projectId,
526
+ },
527
+ select: {
528
+ _id: true,
529
+ alertStateId: true,
530
+ },
531
+ sort: {
532
+ createdAt: SortOrder.Descending,
533
+ },
534
+ props: {
535
+ isRoot: true,
536
+ },
537
+ });
538
+
539
+ if (
540
+ lastAlertStatusTimeline &&
541
+ lastAlertStatusTimeline.alertStateId &&
542
+ lastAlertStatusTimeline.alertStateId.toString() ===
543
+ alertStateId.toString()
544
+ ) {
545
+ return;
546
+ }
547
+
548
+ const statusTimeline: AlertStateTimeline = new AlertStateTimeline();
549
+
550
+ statusTimeline.alertId = alertId;
551
+ statusTimeline.alertStateId = alertStateId;
552
+ statusTimeline.projectId = projectId;
553
+ statusTimeline.isOwnerNotified = !notifyOwners;
554
+
555
+ if (stateChangeLog) {
556
+ statusTimeline.stateChangeLog = stateChangeLog;
557
+ }
558
+ if (rootCause) {
559
+ statusTimeline.rootCause = rootCause;
560
+ }
561
+
562
+ await AlertStateTimelineService.create({
563
+ data: statusTimeline,
564
+ props: props || {},
565
+ });
566
+ }
567
+ }
568
+ export default new Service();
@@ -0,0 +1,154 @@
1
+ import CreateBy from "../Types/Database/CreateBy";
2
+ import DeleteBy from "../Types/Database/DeleteBy";
3
+ import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
4
+ import QueryHelper from "../Types/Database/QueryHelper";
5
+ import UpdateBy from "../Types/Database/UpdateBy";
6
+ import DatabaseService from "./DatabaseService";
7
+ import SortOrder from "../../Types/BaseDatabase/SortOrder";
8
+ import LIMIT_MAX from "../../Types/Database/LimitMax";
9
+ import BadDataException from "../../Types/Exception/BadDataException";
10
+ import ObjectID from "../../Types/ObjectID";
11
+ import Model from "Common/Models/DatabaseModels/AlertSeverity";
12
+
13
+ export class Service extends DatabaseService<Model> {
14
+ public constructor() {
15
+ super(Model);
16
+ }
17
+
18
+ protected override async onBeforeCreate(
19
+ createBy: CreateBy<Model>,
20
+ ): Promise<OnCreate<Model>> {
21
+ if (!createBy.data.order) {
22
+ throw new BadDataException("Alert severity order is required");
23
+ }
24
+
25
+ if (!createBy.data.projectId) {
26
+ throw new BadDataException("Alert severity projectId is required");
27
+ }
28
+
29
+ await this.rearrangeOrder(
30
+ createBy.data.order,
31
+ createBy.data.projectId,
32
+ true,
33
+ );
34
+
35
+ return {
36
+ createBy: createBy,
37
+ carryForward: null,
38
+ };
39
+ }
40
+
41
+ protected override async onBeforeDelete(
42
+ deleteBy: DeleteBy<Model>,
43
+ ): Promise<OnDelete<Model>> {
44
+ if (!deleteBy.query._id && !deleteBy.props.isRoot) {
45
+ throw new BadDataException(
46
+ "_id should be present when deleting alert states. Please try the delete with objectId",
47
+ );
48
+ }
49
+
50
+ let alertSeverity: Model | null = null;
51
+
52
+ if (!deleteBy.props.isRoot) {
53
+ alertSeverity = await this.findOneBy({
54
+ query: deleteBy.query,
55
+ props: {
56
+ isRoot: true,
57
+ },
58
+ select: {
59
+ order: true,
60
+ projectId: true,
61
+ },
62
+ });
63
+ }
64
+
65
+ return {
66
+ deleteBy,
67
+ carryForward: alertSeverity,
68
+ };
69
+ }
70
+
71
+ protected override async onDeleteSuccess(
72
+ onDelete: OnDelete<Model>,
73
+ _itemIdsBeforeDelete: ObjectID[],
74
+ ): Promise<OnDelete<Model>> {
75
+ const deleteBy: DeleteBy<Model> = onDelete.deleteBy;
76
+ const alertSeverity: Model | null = onDelete.carryForward;
77
+
78
+ if (!deleteBy.props.isRoot && alertSeverity) {
79
+ if (alertSeverity && alertSeverity.order && alertSeverity.projectId) {
80
+ await this.rearrangeOrder(
81
+ alertSeverity.order,
82
+ alertSeverity.projectId,
83
+ false,
84
+ );
85
+ }
86
+ }
87
+
88
+ return {
89
+ deleteBy: deleteBy,
90
+ carryForward: null,
91
+ };
92
+ }
93
+
94
+ protected override async onBeforeUpdate(
95
+ updateBy: UpdateBy<Model>,
96
+ ): Promise<OnUpdate<Model>> {
97
+ if (updateBy.data.order && !updateBy.props.isRoot) {
98
+ throw new BadDataException(
99
+ "Alert Severity order should not be updated. Delete this alert state and create a new state with the right order.",
100
+ );
101
+ }
102
+
103
+ return { updateBy, carryForward: null };
104
+ }
105
+
106
+ private async rearrangeOrder(
107
+ currentOrder: number,
108
+ projectId: ObjectID,
109
+ increaseOrder: boolean = true,
110
+ ): Promise<void> {
111
+ // get alert with this order.
112
+ const alertSeverities: Array<Model> = await this.findBy({
113
+ query: {
114
+ order: QueryHelper.greaterThanEqualTo(currentOrder),
115
+ projectId: projectId,
116
+ },
117
+ limit: LIMIT_MAX,
118
+ skip: 0,
119
+ props: {
120
+ isRoot: true,
121
+ },
122
+ select: {
123
+ _id: true,
124
+ order: true,
125
+ },
126
+ sort: {
127
+ order: SortOrder.Ascending,
128
+ },
129
+ });
130
+
131
+ let newOrder: number = currentOrder;
132
+
133
+ for (const alertSeverity of alertSeverities) {
134
+ if (increaseOrder) {
135
+ newOrder = alertSeverity.order! + 1;
136
+ } else {
137
+ newOrder = alertSeverity.order! - 1;
138
+ }
139
+
140
+ await this.updateOneBy({
141
+ query: {
142
+ _id: alertSeverity._id!,
143
+ },
144
+ data: {
145
+ order: newOrder,
146
+ },
147
+ props: {
148
+ isRoot: true,
149
+ },
150
+ });
151
+ }
152
+ }
153
+ }
154
+ export default new Service();