@oneuptime/common 9.3.22 → 9.4.1

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 (130) hide show
  1. package/Models/DatabaseModels/IncomingCallLog.ts +521 -0
  2. package/Models/DatabaseModels/IncomingCallLogItem.ts +463 -0
  3. package/Models/DatabaseModels/IncomingCallPolicy.ts +811 -0
  4. package/Models/DatabaseModels/IncomingCallPolicyEscalationRule.ts +597 -0
  5. package/Models/DatabaseModels/Index.ts +18 -0
  6. package/Models/DatabaseModels/ProjectSCIMLog.ts +422 -0
  7. package/Models/DatabaseModels/StatusPageDomain.ts +2 -0
  8. package/Models/DatabaseModels/StatusPageSCIMLog.ts +455 -0
  9. package/Models/DatabaseModels/User.ts +0 -15
  10. package/Models/DatabaseModels/UserIncomingCallNumber.ts +296 -0
  11. package/Server/API/UserIncomingCallNumberAPI.ts +128 -0
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/1768583966447-MigrationName.ts +121 -0
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1768825402472-MigrationName.ts +317 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
  15. package/Server/Services/DatabaseService.ts +23 -1
  16. package/Server/Services/DomainService.ts +26 -15
  17. package/Server/Services/IncomingCallLogItemService.ts +10 -0
  18. package/Server/Services/IncomingCallLogService.ts +10 -0
  19. package/Server/Services/IncomingCallPolicyEscalationRuleService.ts +267 -0
  20. package/Server/Services/IncomingCallPolicyService.ts +10 -0
  21. package/Server/Services/Index.ts +7 -0
  22. package/Server/Services/MonitorProbeService.ts +96 -1
  23. package/Server/Services/ProjectSCIMLogService.ts +11 -0
  24. package/Server/Services/StatusPageSCIMLogService.ts +11 -0
  25. package/Server/Services/UserCallService.ts +31 -0
  26. package/Server/Services/UserIncomingCallNumberService.ts +258 -0
  27. package/Server/Services/UserSmsService.ts +31 -0
  28. package/Server/Utils/StartServer.ts +5 -0
  29. package/Types/Call/CallProvider.ts +99 -0
  30. package/Types/Call/CallProviderType.ts +6 -0
  31. package/Types/Domain.ts +23 -0
  32. package/Types/Icon/IconProp.ts +1 -0
  33. package/Types/IncomingCall/IncomingCallStatus.ts +13 -0
  34. package/Types/Permission.ts +126 -0
  35. package/Types/Phone.ts +53 -4
  36. package/Types/SCIM/SCIMLogStatus.ts +7 -0
  37. package/UI/Components/Diagram/ConceptCards.tsx +74 -0
  38. package/UI/Components/Diagram/HorizontalStepChain.tsx +92 -0
  39. package/UI/Components/Diagram/Index.ts +11 -0
  40. package/UI/Components/Diagram/NumberedSteps.tsx +77 -0
  41. package/UI/Components/Diagram/VerticalFlowSteps.tsx +59 -0
  42. package/UI/Components/Icon/Icon.tsx +10 -0
  43. package/UI/Components/SimpleLogViewer/SimpleLogViewer.tsx +86 -2
  44. package/build/dist/Models/DatabaseModels/IncomingCallLog.js +565 -0
  45. package/build/dist/Models/DatabaseModels/IncomingCallLog.js.map +1 -0
  46. package/build/dist/Models/DatabaseModels/IncomingCallLogItem.js +497 -0
  47. package/build/dist/Models/DatabaseModels/IncomingCallLogItem.js.map +1 -0
  48. package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js +840 -0
  49. package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js.map +1 -0
  50. package/build/dist/Models/DatabaseModels/IncomingCallPolicyEscalationRule.js +619 -0
  51. package/build/dist/Models/DatabaseModels/IncomingCallPolicyEscalationRule.js.map +1 -0
  52. package/build/dist/Models/DatabaseModels/Index.js +16 -0
  53. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  54. package/build/dist/Models/DatabaseModels/ProjectSCIMLog.js +455 -0
  55. package/build/dist/Models/DatabaseModels/ProjectSCIMLog.js.map +1 -0
  56. package/build/dist/Models/DatabaseModels/StatusPageDomain.js +2 -0
  57. package/build/dist/Models/DatabaseModels/StatusPageDomain.js.map +1 -1
  58. package/build/dist/Models/DatabaseModels/StatusPageSCIMLog.js +486 -0
  59. package/build/dist/Models/DatabaseModels/StatusPageSCIMLog.js.map +1 -0
  60. package/build/dist/Models/DatabaseModels/User.js +0 -16
  61. package/build/dist/Models/DatabaseModels/User.js.map +1 -1
  62. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js +315 -0
  63. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js.map +1 -0
  64. package/build/dist/Server/API/UserIncomingCallNumberAPI.js +72 -0
  65. package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -0
  66. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768583966447-MigrationName.js +48 -0
  67. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768583966447-MigrationName.js.map +1 -0
  68. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768825402472-MigrationName.js +116 -0
  69. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768825402472-MigrationName.js.map +1 -0
  70. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
  71. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  72. package/build/dist/Server/Services/DatabaseService.js +12 -0
  73. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  74. package/build/dist/Server/Services/DomainService.js +19 -8
  75. package/build/dist/Server/Services/DomainService.js.map +1 -1
  76. package/build/dist/Server/Services/IncomingCallLogItemService.js +9 -0
  77. package/build/dist/Server/Services/IncomingCallLogItemService.js.map +1 -0
  78. package/build/dist/Server/Services/IncomingCallLogService.js +9 -0
  79. package/build/dist/Server/Services/IncomingCallLogService.js.map +1 -0
  80. package/build/dist/Server/Services/IncomingCallPolicyEscalationRuleService.js +197 -0
  81. package/build/dist/Server/Services/IncomingCallPolicyEscalationRuleService.js.map +1 -0
  82. package/build/dist/Server/Services/IncomingCallPolicyService.js +9 -0
  83. package/build/dist/Server/Services/IncomingCallPolicyService.js.map +1 -0
  84. package/build/dist/Server/Services/Index.js +6 -0
  85. package/build/dist/Server/Services/Index.js.map +1 -1
  86. package/build/dist/Server/Services/MonitorProbeService.js +77 -0
  87. package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
  88. package/build/dist/Server/Services/ProjectSCIMLogService.js +10 -0
  89. package/build/dist/Server/Services/ProjectSCIMLogService.js.map +1 -0
  90. package/build/dist/Server/Services/StatusPageSCIMLogService.js +10 -0
  91. package/build/dist/Server/Services/StatusPageSCIMLogService.js.map +1 -0
  92. package/build/dist/Server/Services/UserCallService.js +21 -0
  93. package/build/dist/Server/Services/UserCallService.js.map +1 -1
  94. package/build/dist/Server/Services/UserIncomingCallNumberService.js +225 -0
  95. package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -0
  96. package/build/dist/Server/Services/UserSmsService.js +21 -0
  97. package/build/dist/Server/Services/UserSmsService.js.map +1 -1
  98. package/build/dist/Server/Utils/StartServer.js +5 -0
  99. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  100. package/build/dist/Types/Call/CallProvider.js +2 -0
  101. package/build/dist/Types/Call/CallProvider.js.map +1 -0
  102. package/build/dist/Types/Call/CallProviderType.js +7 -0
  103. package/build/dist/Types/Call/CallProviderType.js.map +1 -0
  104. package/build/dist/Types/Domain.js +23 -1
  105. package/build/dist/Types/Domain.js.map +1 -1
  106. package/build/dist/Types/Icon/IconProp.js +1 -0
  107. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  108. package/build/dist/Types/IncomingCall/IncomingCallStatus.js +14 -0
  109. package/build/dist/Types/IncomingCall/IncomingCallStatus.js.map +1 -0
  110. package/build/dist/Types/Permission.js +104 -0
  111. package/build/dist/Types/Permission.js.map +1 -1
  112. package/build/dist/Types/Phone.js +47 -3
  113. package/build/dist/Types/Phone.js.map +1 -1
  114. package/build/dist/Types/SCIM/SCIMLogStatus.js +8 -0
  115. package/build/dist/Types/SCIM/SCIMLogStatus.js.map +1 -0
  116. package/build/dist/UI/Components/Diagram/ConceptCards.js +30 -0
  117. package/build/dist/UI/Components/Diagram/ConceptCards.js.map +1 -0
  118. package/build/dist/UI/Components/Diagram/HorizontalStepChain.js +30 -0
  119. package/build/dist/UI/Components/Diagram/HorizontalStepChain.js.map +1 -0
  120. package/build/dist/UI/Components/Diagram/Index.js +5 -0
  121. package/build/dist/UI/Components/Diagram/Index.js.map +1 -0
  122. package/build/dist/UI/Components/Diagram/NumberedSteps.js +18 -0
  123. package/build/dist/UI/Components/Diagram/NumberedSteps.js.map +1 -0
  124. package/build/dist/UI/Components/Diagram/VerticalFlowSteps.js +16 -0
  125. package/build/dist/UI/Components/Diagram/VerticalFlowSteps.js.map +1 -0
  126. package/build/dist/UI/Components/Icon/Icon.js +4 -0
  127. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  128. package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js +30 -1
  129. package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js.map +1 -1
  130. package/package.json +1 -1
@@ -0,0 +1,267 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import CreateBy from "../Types/Database/CreateBy";
3
+ import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
4
+ import DeleteBy from "../Types/Database/DeleteBy";
5
+ import UpdateBy from "../Types/Database/UpdateBy";
6
+ import Query from "../Types/Database/Query";
7
+ import QueryHelper from "../Types/Database/QueryHelper";
8
+ import BadDataException from "../../Types/Exception/BadDataException";
9
+ import PositiveNumber from "../../Types/PositiveNumber";
10
+ import ObjectID from "../../Types/ObjectID";
11
+ import SortOrder from "../../Types/BaseDatabase/SortOrder";
12
+ import LIMIT_MAX from "../../Types/Database/LimitMax";
13
+ import IncomingCallPolicyEscalationRule from "../../Models/DatabaseModels/IncomingCallPolicyEscalationRule";
14
+
15
+ export class Service extends DatabaseService<IncomingCallPolicyEscalationRule> {
16
+ public constructor() {
17
+ super(IncomingCallPolicyEscalationRule);
18
+ }
19
+
20
+ protected override async onBeforeCreate(
21
+ createBy: CreateBy<IncomingCallPolicyEscalationRule>,
22
+ ): Promise<OnCreate<IncomingCallPolicyEscalationRule>> {
23
+ // Validate mutual exclusivity: either userId OR onCallDutyPolicyScheduleId must be set
24
+ const hasUser: boolean = Boolean(createBy.data.userId);
25
+ const hasSchedule: boolean = Boolean(
26
+ createBy.data.onCallDutyPolicyScheduleId,
27
+ );
28
+
29
+ if (!hasUser && !hasSchedule) {
30
+ throw new BadDataException(
31
+ "Either a User or an On-Call Schedule must be specified for the escalation rule",
32
+ );
33
+ }
34
+
35
+ if (hasUser && hasSchedule) {
36
+ throw new BadDataException(
37
+ "Only one of User or On-Call Schedule can be specified, not both",
38
+ );
39
+ }
40
+
41
+ if (!createBy.data.incomingCallPolicyId) {
42
+ throw new BadDataException("incomingCallPolicyId is required");
43
+ }
44
+
45
+ // Auto-generate order if not provided
46
+ if (!createBy.data.order) {
47
+ const query: Query<IncomingCallPolicyEscalationRule> = {
48
+ incomingCallPolicyId: createBy.data.incomingCallPolicyId,
49
+ };
50
+
51
+ const count: PositiveNumber = await this.countBy({
52
+ query: query,
53
+ props: {
54
+ isRoot: true,
55
+ },
56
+ });
57
+
58
+ createBy.data.order = count.toNumber() + 1;
59
+ }
60
+
61
+ await this.rearrangeOrder(
62
+ createBy.data.order,
63
+ createBy.data.incomingCallPolicyId,
64
+ true,
65
+ );
66
+
67
+ return {
68
+ createBy,
69
+ carryForward: null,
70
+ };
71
+ }
72
+
73
+ protected override async onBeforeDelete(
74
+ deleteBy: DeleteBy<IncomingCallPolicyEscalationRule>,
75
+ ): Promise<OnDelete<IncomingCallPolicyEscalationRule>> {
76
+ if (!deleteBy.query._id && !deleteBy.props.isRoot) {
77
+ throw new BadDataException(
78
+ "_id should be present when deleting escalation rule. Please try the delete with objectId",
79
+ );
80
+ }
81
+
82
+ let resource: IncomingCallPolicyEscalationRule | null = null;
83
+
84
+ if (!deleteBy.props.isRoot) {
85
+ resource = await this.findOneBy({
86
+ query: deleteBy.query,
87
+ props: {
88
+ isRoot: true,
89
+ },
90
+ select: {
91
+ order: true,
92
+ incomingCallPolicyId: true,
93
+ projectId: true,
94
+ },
95
+ });
96
+
97
+ if (!resource) {
98
+ throw new BadDataException(
99
+ "IncomingCallPolicyEscalationRule with this id not found",
100
+ );
101
+ }
102
+ }
103
+
104
+ return {
105
+ deleteBy,
106
+ carryForward: resource,
107
+ };
108
+ }
109
+
110
+ protected override async onDeleteSuccess(
111
+ onDelete: OnDelete<IncomingCallPolicyEscalationRule>,
112
+ _itemIdsBeforeDelete: ObjectID[],
113
+ ): Promise<OnDelete<IncomingCallPolicyEscalationRule>> {
114
+ const deleteBy: DeleteBy<IncomingCallPolicyEscalationRule> =
115
+ onDelete.deleteBy;
116
+ const resource: IncomingCallPolicyEscalationRule | null =
117
+ onDelete.carryForward;
118
+
119
+ if (!deleteBy.props.isRoot && resource) {
120
+ if (resource && resource.order && resource.incomingCallPolicyId) {
121
+ await this.rearrangeOrder(
122
+ resource.order,
123
+ resource.incomingCallPolicyId,
124
+ false,
125
+ );
126
+ }
127
+ }
128
+
129
+ return {
130
+ deleteBy: deleteBy,
131
+ carryForward: null,
132
+ };
133
+ }
134
+
135
+ protected override async onBeforeUpdate(
136
+ updateBy: UpdateBy<IncomingCallPolicyEscalationRule>,
137
+ ): Promise<OnUpdate<IncomingCallPolicyEscalationRule>> {
138
+ if (updateBy.data.order && !updateBy.props.isRoot && updateBy.query._id) {
139
+ const resource: IncomingCallPolicyEscalationRule | null =
140
+ await this.findOneBy({
141
+ query: {
142
+ _id: updateBy.query._id!,
143
+ },
144
+ props: {
145
+ isRoot: true,
146
+ },
147
+ select: {
148
+ order: true,
149
+ incomingCallPolicyId: true,
150
+ _id: true,
151
+ },
152
+ });
153
+
154
+ const currentOrder: number = resource?.order as number;
155
+ const newOrder: number = updateBy.data.order as number;
156
+
157
+ const resources: Array<IncomingCallPolicyEscalationRule> =
158
+ await this.findBy({
159
+ query: {
160
+ incomingCallPolicyId: resource?.incomingCallPolicyId as ObjectID,
161
+ },
162
+ limit: LIMIT_MAX,
163
+ skip: 0,
164
+ props: {
165
+ isRoot: true,
166
+ },
167
+ select: {
168
+ order: true,
169
+ incomingCallPolicyId: true,
170
+ _id: true,
171
+ },
172
+ });
173
+
174
+ if (currentOrder > newOrder) {
175
+ // moving up.
176
+ for (const resource of resources) {
177
+ if (resource.order! >= newOrder && resource.order! < currentOrder) {
178
+ // increment order.
179
+ await this.updateOneBy({
180
+ query: {
181
+ _id: resource._id!,
182
+ },
183
+ data: {
184
+ order: resource.order! + 1,
185
+ },
186
+ props: {
187
+ isRoot: true,
188
+ },
189
+ });
190
+ }
191
+ }
192
+ }
193
+
194
+ if (newOrder > currentOrder) {
195
+ // moving down.
196
+ for (const resource of resources) {
197
+ if (resource.order! <= newOrder) {
198
+ // increment order.
199
+ await this.updateOneBy({
200
+ query: {
201
+ _id: resource._id!,
202
+ },
203
+ data: {
204
+ order: resource.order! - 1,
205
+ },
206
+ props: {
207
+ isRoot: true,
208
+ },
209
+ });
210
+ }
211
+ }
212
+ }
213
+ }
214
+
215
+ return { updateBy, carryForward: null };
216
+ }
217
+
218
+ private async rearrangeOrder(
219
+ currentOrder: number,
220
+ incomingCallPolicyId: ObjectID,
221
+ increaseOrder: boolean = true,
222
+ ): Promise<void> {
223
+ const resources: Array<IncomingCallPolicyEscalationRule> =
224
+ await this.findBy({
225
+ query: {
226
+ order: QueryHelper.greaterThanEqualTo(currentOrder),
227
+ incomingCallPolicyId: incomingCallPolicyId,
228
+ },
229
+ limit: LIMIT_MAX,
230
+ skip: 0,
231
+ props: {
232
+ isRoot: true,
233
+ },
234
+ select: {
235
+ _id: true,
236
+ order: true,
237
+ },
238
+ sort: {
239
+ order: SortOrder.Ascending,
240
+ },
241
+ });
242
+
243
+ let newOrder: number = currentOrder;
244
+
245
+ for (const resource of resources) {
246
+ if (increaseOrder) {
247
+ newOrder = resource.order! + 1;
248
+ } else {
249
+ newOrder = resource.order! - 1;
250
+ }
251
+
252
+ await this.updateOneBy({
253
+ query: {
254
+ _id: resource._id!,
255
+ },
256
+ data: {
257
+ order: newOrder,
258
+ },
259
+ props: {
260
+ isRoot: true,
261
+ },
262
+ });
263
+ }
264
+ }
265
+ }
266
+
267
+ export default new Service();
@@ -0,0 +1,10 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import IncomingCallPolicy from "../../Models/DatabaseModels/IncomingCallPolicy";
3
+
4
+ export class Service extends DatabaseService<IncomingCallPolicy> {
5
+ public constructor() {
6
+ super(IncomingCallPolicy);
7
+ }
8
+ }
9
+
10
+ export default new Service();
@@ -134,6 +134,7 @@ import UserSessionService from "./UserSessionService";
134
134
  import UserTotpAuthService from "./UserTotpAuthService";
135
135
  import UserWebAuthnService from "./UserWebAuthnService";
136
136
  import UserSmsService from "./UserSmsService";
137
+ import UserIncomingCallNumberService from "./UserIncomingCallNumberService";
137
138
  import UserWhatsAppService from "./UserWhatsAppService";
138
139
  import WorkflowLogService from "./WorkflowLogService";
139
140
  // Workflows.
@@ -173,6 +174,8 @@ import OnCallDutyPolicyUserOverrideService from "./OnCallDutyPolicyUserOverrideS
173
174
  import MonitorLogService from "./MonitorLogService";
174
175
 
175
176
  import OnCallDutyPolicyTimeLogService from "./OnCallDutyPolicyTimeLogService";
177
+ import ProjectSCIMLogService from "./ProjectSCIMLogService";
178
+ import StatusPageSCIMLogService from "./StatusPageSCIMLogService";
176
179
 
177
180
  const services: Array<BaseService> = [
178
181
  OnCallDutyPolicyTimeLogService,
@@ -299,6 +302,7 @@ const services: Array<BaseService> = [
299
302
  UserOnCallLogService,
300
303
  UserOnCallLogTimelineService,
301
304
  UserSmsService,
305
+ UserIncomingCallNumberService,
302
306
  UserWhatsAppService,
303
307
  UserTotpAuthService,
304
308
  UserWebAuthnService,
@@ -355,6 +359,9 @@ const services: Array<BaseService> = [
355
359
  WorkspaceSettingService,
356
360
  WorkspaceNotificationRuleService,
357
361
  WorkspaceNotificationLogService,
362
+
363
+ ProjectSCIMLogService,
364
+ StatusPageSCIMLogService,
358
365
  ];
359
366
 
360
367
  export const AnalyticsServices: Array<
@@ -1,7 +1,7 @@
1
1
  import ObjectID from "../../Types/ObjectID";
2
2
  import CreateBy from "../Types/Database/CreateBy";
3
3
  import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
4
- import DatabaseService from "./DatabaseService";
4
+ import DatabaseService, { EntityManager } from "./DatabaseService";
5
5
  import OneUptimeDate from "../../Types/Date";
6
6
  import BadDataException from "../../Types/Exception/BadDataException";
7
7
  import MonitorProbe from "../../Models/DatabaseModels/MonitorProbe";
@@ -69,6 +69,101 @@ export class Service extends DatabaseService<MonitorProbe> {
69
69
  }
70
70
  }
71
71
 
72
+ /**
73
+ * Atomically claims monitor probes for a specific probe instance.
74
+ * Uses PostgreSQL's FOR UPDATE SKIP LOCKED to prevent multiple probe instances
75
+ * from picking up the same monitors simultaneously.
76
+ *
77
+ * @param data - Object containing probeId, limit, and nextPingAt
78
+ * @returns Array of claimed MonitorProbe IDs
79
+ */
80
+ public async claimMonitorProbesForProbing(data: {
81
+ probeId: ObjectID;
82
+ limit: number;
83
+ }): Promise<Array<ObjectID>> {
84
+ const currentDate: Date = OneUptimeDate.getCurrentDate();
85
+
86
+ /*
87
+ * Use a transaction with FOR UPDATE SKIP LOCKED to atomically claim monitors
88
+ * This prevents multiple probe instances from picking up the same monitors
89
+ */
90
+ const claimedIds: Array<ObjectID> = await this.executeTransaction(
91
+ async (transactionalEntityManager: EntityManager) => {
92
+ /*
93
+ * First, select and lock the monitor probes that need to be processed
94
+ * FOR UPDATE SKIP LOCKED ensures that:
95
+ * 1. Rows are locked for this transaction
96
+ * 2. Rows already locked by other transactions are skipped
97
+ */
98
+ const selectQuery: string = `
99
+ SELECT mp."_id"
100
+ FROM "MonitorProbe" mp
101
+ INNER JOIN "Monitor" m ON mp."monitorId" = m."_id"
102
+ INNER JOIN "Project" p ON mp."projectId" = p."_id"
103
+ WHERE mp."probeId" = $1
104
+ AND mp."isEnabled" = true
105
+ AND mp."deletedAt" IS NULL
106
+ AND (mp."nextPingAt" IS NULL OR mp."nextPingAt" <= $2)
107
+ AND m."disableActiveMonitoring" = false
108
+ AND m."disableActiveMonitoringBecauseOfManualIncident" = false
109
+ AND m."disableActiveMonitoringBecauseOfScheduledMaintenanceEvent" = false
110
+ AND m."deletedAt" IS NULL
111
+ AND p."deletedAt" IS NULL
112
+ AND (p."paymentProviderSubscriptionStatus" IS NULL
113
+ OR p."paymentProviderSubscriptionStatus" IN ('active', 'trialing'))
114
+ AND (p."paymentProviderMeteredSubscriptionStatus" IS NULL
115
+ OR p."paymentProviderMeteredSubscriptionStatus" IN ('active', 'trialing'))
116
+ ORDER BY mp."nextPingAt" ASC NULLS FIRST
117
+ LIMIT $3
118
+ FOR UPDATE OF mp SKIP LOCKED
119
+ `;
120
+
121
+ const selectedRows: Array<{ _id: string }> =
122
+ await transactionalEntityManager.query(selectQuery, [
123
+ data.probeId.toString(),
124
+ currentDate,
125
+ data.limit,
126
+ ]);
127
+
128
+ if (selectedRows.length === 0) {
129
+ return [];
130
+ }
131
+
132
+ const ids: Array<string> = selectedRows.map((row: { _id: string }) => {
133
+ return row._id;
134
+ });
135
+
136
+ /*
137
+ * Update the claimed monitors to set nextPingAt to 1 minute from now
138
+ * This is a temporary value; the actual nextPingAt will be calculated
139
+ * based on the monitor's interval after the probe fetches the full details
140
+ */
141
+ const tempNextPingAt: Date = OneUptimeDate.addRemoveMinutes(
142
+ currentDate,
143
+ 1,
144
+ );
145
+
146
+ const updateQuery: string = `
147
+ UPDATE "MonitorProbe"
148
+ SET "lastPingAt" = $1, "nextPingAt" = $2
149
+ WHERE "_id" = ANY($3::uuid[])
150
+ `;
151
+
152
+ await transactionalEntityManager.query(updateQuery, [
153
+ currentDate,
154
+ tempNextPingAt,
155
+ ids,
156
+ ]);
157
+
158
+ return ids.map((id: string) => {
159
+ return new ObjectID(id);
160
+ });
161
+ },
162
+ );
163
+
164
+ return claimedIds;
165
+ }
166
+
72
167
  protected override async onBeforeCreate(
73
168
  createBy: CreateBy<MonitorProbe>,
74
169
  ): Promise<OnCreate<MonitorProbe>> {
@@ -0,0 +1,11 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/ProjectSCIMLog";
3
+
4
+ export class Service extends DatabaseService<Model> {
5
+ public constructor() {
6
+ super(Model);
7
+ this.hardDeleteItemsOlderThanInDays("createdAt", 3);
8
+ }
9
+ }
10
+
11
+ export default new Service();
@@ -0,0 +1,11 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/StatusPageSCIMLog";
3
+
4
+ export class Service extends DatabaseService<Model> {
5
+ public constructor() {
6
+ super(Model);
7
+ this.hardDeleteItemsOlderThanInDays("createdAt", 3);
8
+ }
9
+ }
10
+
11
+ export default new Service();
@@ -137,6 +137,37 @@ export class Service extends DatabaseService<Model> {
137
137
  throw new BadDataException("Phone Number already verified");
138
138
  }
139
139
 
140
+ // Check if Call notifications are enabled for this project
141
+ const project: Project | null = await ProjectService.findOneById({
142
+ id: item.projectId!,
143
+ props: {
144
+ isRoot: true,
145
+ },
146
+ select: {
147
+ enableCallNotifications: true,
148
+ smsOrCallCurrentBalanceInUSDCents: true,
149
+ },
150
+ });
151
+
152
+ if (!project) {
153
+ throw new BadDataException("Project not found");
154
+ }
155
+
156
+ if (!project.enableCallNotifications) {
157
+ throw new BadDataException(
158
+ "Call notifications are disabled for this project. Please enable them in Project Settings > Notification Settings.",
159
+ );
160
+ }
161
+
162
+ if (
163
+ (project.smsOrCallCurrentBalanceInUSDCents as number) <= 100 &&
164
+ IsBillingEnabled
165
+ ) {
166
+ throw new BadDataException(
167
+ "Your SMS balance is low. Please recharge your SMS balance in Project Settings > Notification Settings.",
168
+ );
169
+ }
170
+
140
171
  // generate new verification code
141
172
  item.verificationCode = Text.generateRandomNumber(6);
142
173