@oneuptime/common 9.4.0 → 9.4.2
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/StatusPageDomain.ts +2 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1768825402472-MigrationName.ts +317 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -6
- package/Server/Services/DatabaseService.ts +23 -1
- package/Server/Services/DomainService.ts +26 -15
- package/Server/Services/MonitorProbeService.ts +96 -1
- package/Types/Domain.ts +23 -0
- package/build/dist/Models/DatabaseModels/StatusPageDomain.js +2 -0
- package/build/dist/Models/DatabaseModels/StatusPageDomain.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768825402472-MigrationName.js +116 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768825402472-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -6
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +12 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DomainService.js +19 -8
- package/build/dist/Server/Services/DomainService.js.map +1 -1
- package/build/dist/Server/Services/MonitorProbeService.js +77 -0
- package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
- package/build/dist/Types/Domain.js +23 -1
- package/build/dist/Types/Domain.js.map +1 -1
- package/package.json +1 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1768647802022-RemoveAlertPhoneNumberFromUser.ts +0 -22
- package/Server/Infrastructure/Postgres/SchemaMigrations/1768649699509-MigrationName.ts +0 -787
- package/Server/Infrastructure/Postgres/SchemaMigrations/1768682071562-MigrationName.ts +0 -29
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768647802022-RemoveAlertPhoneNumberFromUser.js +0 -34
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768647802022-RemoveAlertPhoneNumberFromUser.js.map +0 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768649699509-MigrationName.js +0 -270
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768649699509-MigrationName.js.map +0 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768682071562-MigrationName.js +0 -16
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768682071562-MigrationName.js.map +0 -1
|
@@ -318,6 +318,7 @@ export default class StatusPageDomain extends BaseModel {
|
|
|
318
318
|
})
|
|
319
319
|
@TableColumn({
|
|
320
320
|
required: true,
|
|
321
|
+
computed: true,
|
|
321
322
|
type: TableColumnType.ShortText,
|
|
322
323
|
title: "Full Domain",
|
|
323
324
|
description:
|
|
@@ -448,6 +449,7 @@ export default class StatusPageDomain extends BaseModel {
|
|
|
448
449
|
})
|
|
449
450
|
@TableColumn({
|
|
450
451
|
required: true,
|
|
452
|
+
computed: true,
|
|
451
453
|
type: TableColumnType.ShortText,
|
|
452
454
|
title: "CNAME Verification Token",
|
|
453
455
|
description: "CNAME Verification Token",
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class MigrationName1768825402472 implements MigrationInterface {
|
|
4
|
+
public name = "MigrationName1768825402472";
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(
|
|
8
|
+
`CREATE TABLE "IncomingCallPolicy" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "name" character varying(100) NOT NULL, "description" character varying(500), "slug" character varying(100) NOT NULL, "routingPhoneNumber" character varying(30), "callProviderPhoneNumberId" character varying(100), "phoneNumberCountryCode" character varying(100), "phoneNumberAreaCode" character varying(100), "phoneNumberPurchasedAt" TIMESTAMP WITH TIME ZONE, "greetingMessage" character varying(500) DEFAULT 'Please wait while we connect you to the on-call engineer.', "noAnswerMessage" character varying(500) DEFAULT 'No one is available. Please try again later.', "noOneAvailableMessage" character varying(500) DEFAULT 'We are sorry, but no on-call engineer is currently available. Please try again later or contact support.', "isEnabled" boolean NOT NULL DEFAULT true, "repeatPolicyIfNoOneAnswers" boolean NOT NULL DEFAULT false, "repeatPolicyIfNoOneAnswersTimes" integer NOT NULL DEFAULT '1', "projectCallSMSConfigId" uuid, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "UQ_5242e2cffd7f4050e6189e569d5" UNIQUE ("slug"), CONSTRAINT "PK_1cce87f0549b0284e23492d0910" PRIMARY KEY ("_id"))`,
|
|
9
|
+
);
|
|
10
|
+
await queryRunner.query(
|
|
11
|
+
`CREATE INDEX "IDX_3c52bf3d9f9aca2ac74848fc0f" ON "IncomingCallPolicy" ("projectId") `,
|
|
12
|
+
);
|
|
13
|
+
await queryRunner.query(
|
|
14
|
+
`CREATE INDEX "IDX_f2f54dca4c8c0bbdea4c37edb2" ON "IncomingCallPolicy" ("name") `,
|
|
15
|
+
);
|
|
16
|
+
await queryRunner.query(
|
|
17
|
+
`CREATE INDEX "IDX_5242e2cffd7f4050e6189e569d" ON "IncomingCallPolicy" ("slug") `,
|
|
18
|
+
);
|
|
19
|
+
await queryRunner.query(
|
|
20
|
+
`CREATE INDEX "IDX_6680fc89e547525f8051bb2599" ON "IncomingCallPolicy" ("routingPhoneNumber") `,
|
|
21
|
+
);
|
|
22
|
+
await queryRunner.query(
|
|
23
|
+
`CREATE TABLE "IncomingCallPolicyEscalationRule" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "incomingCallPolicyId" uuid NOT NULL, "name" character varying(100), "description" character varying(500), "order" integer NOT NULL, "escalateAfterSeconds" integer NOT NULL DEFAULT '30', "onCallDutyPolicyScheduleId" uuid, "userId" uuid, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_162e367fb58da2aea22a14057e1" PRIMARY KEY ("_id"))`,
|
|
24
|
+
);
|
|
25
|
+
await queryRunner.query(
|
|
26
|
+
`CREATE INDEX "IDX_3ff7e49f61d10020a7298c3dc6" ON "IncomingCallPolicyEscalationRule" ("projectId") `,
|
|
27
|
+
);
|
|
28
|
+
await queryRunner.query(
|
|
29
|
+
`CREATE INDEX "IDX_d9358a64a7d4a3f48804844e69" ON "IncomingCallPolicyEscalationRule" ("incomingCallPolicyId") `,
|
|
30
|
+
);
|
|
31
|
+
await queryRunner.query(
|
|
32
|
+
`CREATE INDEX "IDX_2940b1f9392441bcff1a33ebc4" ON "IncomingCallPolicyEscalationRule" ("order") `,
|
|
33
|
+
);
|
|
34
|
+
await queryRunner.query(
|
|
35
|
+
`CREATE TABLE "IncomingCallLog" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "incomingCallPolicyId" uuid NOT NULL, "callerPhoneNumber" character varying(30), "routingPhoneNumber" character varying(30), "callProviderCallId" character varying(100), "status" character varying(100) NOT NULL DEFAULT 'Initiated', "statusMessage" character varying(500), "callDurationInSeconds" integer DEFAULT '0', "callCostInUSDCents" integer DEFAULT '0', "incomingCallCostInUSDCents" integer DEFAULT '0', "outgoingCallCostInUSDCents" integer DEFAULT '0', "startedAt" TIMESTAMP WITH TIME ZONE, "endedAt" TIMESTAMP WITH TIME ZONE, "answeredByUserId" uuid, "currentEscalationRuleOrder" integer DEFAULT '1', "repeatCount" integer DEFAULT '0', CONSTRAINT "PK_c1fd81ebc16e88b441dd8d19108" PRIMARY KEY ("_id"))`,
|
|
36
|
+
);
|
|
37
|
+
await queryRunner.query(
|
|
38
|
+
`CREATE INDEX "IDX_915f3d5f9bf60430bbd89a1efc" ON "IncomingCallLog" ("projectId") `,
|
|
39
|
+
);
|
|
40
|
+
await queryRunner.query(
|
|
41
|
+
`CREATE INDEX "IDX_18e2254401cd580a906808d690" ON "IncomingCallLog" ("incomingCallPolicyId") `,
|
|
42
|
+
);
|
|
43
|
+
await queryRunner.query(
|
|
44
|
+
`CREATE INDEX "IDX_4769731b4e40dd238410b47337" ON "IncomingCallLog" ("callProviderCallId") `,
|
|
45
|
+
);
|
|
46
|
+
await queryRunner.query(
|
|
47
|
+
`CREATE INDEX "IDX_bac28bb0cfff30703cb79e4a9c" ON "IncomingCallLog" ("status") `,
|
|
48
|
+
);
|
|
49
|
+
await queryRunner.query(
|
|
50
|
+
`CREATE INDEX "IDX_0821fb47819572b56836b06102" ON "IncomingCallLog" ("startedAt") `,
|
|
51
|
+
);
|
|
52
|
+
await queryRunner.query(
|
|
53
|
+
`CREATE TABLE "IncomingCallLogItem" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "incomingCallLogId" uuid NOT NULL, "incomingCallPolicyEscalationRuleId" uuid, "userId" uuid, "userPhoneNumber" character varying(30), "status" character varying(100) NOT NULL DEFAULT 'Ringing', "statusMessage" character varying(500), "dialDurationInSeconds" integer DEFAULT '0', "callCostInUSDCents" integer DEFAULT '0', "startedAt" TIMESTAMP WITH TIME ZONE, "endedAt" TIMESTAMP WITH TIME ZONE, "isAnswered" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_00c152a3a8f417339c18000d197" PRIMARY KEY ("_id"))`,
|
|
54
|
+
);
|
|
55
|
+
await queryRunner.query(
|
|
56
|
+
`CREATE INDEX "IDX_4d0e67775a87ffdf8b1413d5bc" ON "IncomingCallLogItem" ("projectId") `,
|
|
57
|
+
);
|
|
58
|
+
await queryRunner.query(
|
|
59
|
+
`CREATE INDEX "IDX_d11a949952998081bed04512a7" ON "IncomingCallLogItem" ("incomingCallLogId") `,
|
|
60
|
+
);
|
|
61
|
+
await queryRunner.query(
|
|
62
|
+
`CREATE INDEX "IDX_cb196303d93ee4044d0a4f076e" ON "IncomingCallLogItem" ("userId") `,
|
|
63
|
+
);
|
|
64
|
+
await queryRunner.query(
|
|
65
|
+
`CREATE INDEX "IDX_5ecd45b8e5c05322459b01f37e" ON "IncomingCallLogItem" ("status") `,
|
|
66
|
+
);
|
|
67
|
+
await queryRunner.query(
|
|
68
|
+
`CREATE INDEX "IDX_c2f339131713708082a01cd880" ON "IncomingCallLogItem" ("startedAt") `,
|
|
69
|
+
);
|
|
70
|
+
await queryRunner.query(
|
|
71
|
+
`CREATE TABLE "UserIncomingCallNumber" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "phone" character varying(30) NOT NULL, "userId" uuid, "createdByUserId" uuid, "deletedByUserId" uuid, "isVerified" boolean NOT NULL DEFAULT false, "verificationCode" character varying(100) NOT NULL, CONSTRAINT "PK_6e487c7ce740c2f21f83904afbe" PRIMARY KEY ("_id"))`,
|
|
72
|
+
);
|
|
73
|
+
await queryRunner.query(
|
|
74
|
+
`CREATE INDEX "IDX_af7375987850451a60f0002ae4" ON "UserIncomingCallNumber" ("projectId") `,
|
|
75
|
+
);
|
|
76
|
+
await queryRunner.query(
|
|
77
|
+
`CREATE INDEX "IDX_3b7f38fb56ffd49e972205cb48" ON "UserIncomingCallNumber" ("userId") `,
|
|
78
|
+
);
|
|
79
|
+
await queryRunner.query(
|
|
80
|
+
`CREATE TABLE "IncomingCallPolicyLabel" ("incomingCallPolicyId" uuid NOT NULL, "labelId" uuid NOT NULL, CONSTRAINT "PK_dbe36f4c556e85705e2ff19e4a5" PRIMARY KEY ("incomingCallPolicyId", "labelId"))`,
|
|
81
|
+
);
|
|
82
|
+
await queryRunner.query(
|
|
83
|
+
`CREATE INDEX "IDX_fb7de9bbc395452347629e9131" ON "IncomingCallPolicyLabel" ("incomingCallPolicyId") `,
|
|
84
|
+
);
|
|
85
|
+
await queryRunner.query(
|
|
86
|
+
`CREATE INDEX "IDX_fb6335122b06a052c29d3d6d8b" ON "IncomingCallPolicyLabel" ("labelId") `,
|
|
87
|
+
);
|
|
88
|
+
await queryRunner.query(
|
|
89
|
+
`ALTER TABLE "User" DROP COLUMN "alertPhoneNumber"`,
|
|
90
|
+
);
|
|
91
|
+
await queryRunner.query(
|
|
92
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
|
|
93
|
+
);
|
|
94
|
+
await queryRunner.query(
|
|
95
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
|
|
96
|
+
);
|
|
97
|
+
await queryRunner.query(
|
|
98
|
+
`ALTER TABLE "IncomingCallPolicy" ADD CONSTRAINT "FK_3c52bf3d9f9aca2ac74848fc0f7" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
99
|
+
);
|
|
100
|
+
await queryRunner.query(
|
|
101
|
+
`ALTER TABLE "IncomingCallPolicy" ADD CONSTRAINT "FK_08a214983b56f6102a4fdecfa65" FOREIGN KEY ("projectCallSMSConfigId") REFERENCES "ProjectCallSMSConfig"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
102
|
+
);
|
|
103
|
+
await queryRunner.query(
|
|
104
|
+
`ALTER TABLE "IncomingCallPolicy" ADD CONSTRAINT "FK_fb8001e77d8907b8e089afa6193" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
105
|
+
);
|
|
106
|
+
await queryRunner.query(
|
|
107
|
+
`ALTER TABLE "IncomingCallPolicy" ADD CONSTRAINT "FK_197d35d96152cbaa101afa670bd" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
108
|
+
);
|
|
109
|
+
await queryRunner.query(
|
|
110
|
+
`ALTER TABLE "IncomingCallPolicyEscalationRule" ADD CONSTRAINT "FK_3ff7e49f61d10020a7298c3dc64" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
111
|
+
);
|
|
112
|
+
await queryRunner.query(
|
|
113
|
+
`ALTER TABLE "IncomingCallPolicyEscalationRule" ADD CONSTRAINT "FK_d9358a64a7d4a3f48804844e698" FOREIGN KEY ("incomingCallPolicyId") REFERENCES "IncomingCallPolicy"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
114
|
+
);
|
|
115
|
+
await queryRunner.query(
|
|
116
|
+
`ALTER TABLE "IncomingCallPolicyEscalationRule" ADD CONSTRAINT "FK_5e2f646a84077a5fd4969ef090b" FOREIGN KEY ("onCallDutyPolicyScheduleId") REFERENCES "OnCallDutyPolicySchedule"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
117
|
+
);
|
|
118
|
+
await queryRunner.query(
|
|
119
|
+
`ALTER TABLE "IncomingCallPolicyEscalationRule" ADD CONSTRAINT "FK_c0c7ea3cb722a94e074c4486b29" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
120
|
+
);
|
|
121
|
+
await queryRunner.query(
|
|
122
|
+
`ALTER TABLE "IncomingCallPolicyEscalationRule" ADD CONSTRAINT "FK_c0726b90365656bd869ad821b3b" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
123
|
+
);
|
|
124
|
+
await queryRunner.query(
|
|
125
|
+
`ALTER TABLE "IncomingCallPolicyEscalationRule" ADD CONSTRAINT "FK_c434cfc9ca11de56e1b5a316559" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
126
|
+
);
|
|
127
|
+
await queryRunner.query(
|
|
128
|
+
`ALTER TABLE "IncomingCallLog" ADD CONSTRAINT "FK_915f3d5f9bf60430bbd89a1efce" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
129
|
+
);
|
|
130
|
+
await queryRunner.query(
|
|
131
|
+
`ALTER TABLE "IncomingCallLog" ADD CONSTRAINT "FK_18e2254401cd580a906808d6908" FOREIGN KEY ("incomingCallPolicyId") REFERENCES "IncomingCallPolicy"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
132
|
+
);
|
|
133
|
+
await queryRunner.query(
|
|
134
|
+
`ALTER TABLE "IncomingCallLog" ADD CONSTRAINT "FK_fb2531b7d8c44e4cad026fb8662" FOREIGN KEY ("answeredByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
135
|
+
);
|
|
136
|
+
await queryRunner.query(
|
|
137
|
+
`ALTER TABLE "IncomingCallLogItem" ADD CONSTRAINT "FK_4d0e67775a87ffdf8b1413d5bcb" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
138
|
+
);
|
|
139
|
+
await queryRunner.query(
|
|
140
|
+
`ALTER TABLE "IncomingCallLogItem" ADD CONSTRAINT "FK_d11a949952998081bed04512a77" FOREIGN KEY ("incomingCallLogId") REFERENCES "IncomingCallLog"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
141
|
+
);
|
|
142
|
+
await queryRunner.query(
|
|
143
|
+
`ALTER TABLE "IncomingCallLogItem" ADD CONSTRAINT "FK_b1fbb2661c86de72ffd61f807b9" FOREIGN KEY ("incomingCallPolicyEscalationRuleId") REFERENCES "IncomingCallPolicyEscalationRule"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
144
|
+
);
|
|
145
|
+
await queryRunner.query(
|
|
146
|
+
`ALTER TABLE "IncomingCallLogItem" ADD CONSTRAINT "FK_cb196303d93ee4044d0a4f076e5" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
147
|
+
);
|
|
148
|
+
await queryRunner.query(
|
|
149
|
+
`ALTER TABLE "UserIncomingCallNumber" ADD CONSTRAINT "FK_af7375987850451a60f0002ae43" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
150
|
+
);
|
|
151
|
+
await queryRunner.query(
|
|
152
|
+
`ALTER TABLE "UserIncomingCallNumber" ADD CONSTRAINT "FK_3b7f38fb56ffd49e972205cb483" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
|
153
|
+
);
|
|
154
|
+
await queryRunner.query(
|
|
155
|
+
`ALTER TABLE "UserIncomingCallNumber" ADD CONSTRAINT "FK_4565a75d2ff8c3f363ac2a9c056" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
156
|
+
);
|
|
157
|
+
await queryRunner.query(
|
|
158
|
+
`ALTER TABLE "UserIncomingCallNumber" ADD CONSTRAINT "FK_cab048905c4eb8f87aff75feaa7" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
159
|
+
);
|
|
160
|
+
await queryRunner.query(
|
|
161
|
+
`ALTER TABLE "IncomingCallPolicyLabel" ADD CONSTRAINT "FK_fb7de9bbc395452347629e91318" FOREIGN KEY ("incomingCallPolicyId") REFERENCES "IncomingCallPolicy"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
|
162
|
+
);
|
|
163
|
+
await queryRunner.query(
|
|
164
|
+
`ALTER TABLE "IncomingCallPolicyLabel" ADD CONSTRAINT "FK_fb6335122b06a052c29d3d6d8b5" FOREIGN KEY ("labelId") REFERENCES "Label"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
169
|
+
await queryRunner.query(
|
|
170
|
+
`ALTER TABLE "IncomingCallPolicyLabel" DROP CONSTRAINT "FK_fb6335122b06a052c29d3d6d8b5"`,
|
|
171
|
+
);
|
|
172
|
+
await queryRunner.query(
|
|
173
|
+
`ALTER TABLE "IncomingCallPolicyLabel" DROP CONSTRAINT "FK_fb7de9bbc395452347629e91318"`,
|
|
174
|
+
);
|
|
175
|
+
await queryRunner.query(
|
|
176
|
+
`ALTER TABLE "UserIncomingCallNumber" DROP CONSTRAINT "FK_cab048905c4eb8f87aff75feaa7"`,
|
|
177
|
+
);
|
|
178
|
+
await queryRunner.query(
|
|
179
|
+
`ALTER TABLE "UserIncomingCallNumber" DROP CONSTRAINT "FK_4565a75d2ff8c3f363ac2a9c056"`,
|
|
180
|
+
);
|
|
181
|
+
await queryRunner.query(
|
|
182
|
+
`ALTER TABLE "UserIncomingCallNumber" DROP CONSTRAINT "FK_3b7f38fb56ffd49e972205cb483"`,
|
|
183
|
+
);
|
|
184
|
+
await queryRunner.query(
|
|
185
|
+
`ALTER TABLE "UserIncomingCallNumber" DROP CONSTRAINT "FK_af7375987850451a60f0002ae43"`,
|
|
186
|
+
);
|
|
187
|
+
await queryRunner.query(
|
|
188
|
+
`ALTER TABLE "IncomingCallLogItem" DROP CONSTRAINT "FK_cb196303d93ee4044d0a4f076e5"`,
|
|
189
|
+
);
|
|
190
|
+
await queryRunner.query(
|
|
191
|
+
`ALTER TABLE "IncomingCallLogItem" DROP CONSTRAINT "FK_b1fbb2661c86de72ffd61f807b9"`,
|
|
192
|
+
);
|
|
193
|
+
await queryRunner.query(
|
|
194
|
+
`ALTER TABLE "IncomingCallLogItem" DROP CONSTRAINT "FK_d11a949952998081bed04512a77"`,
|
|
195
|
+
);
|
|
196
|
+
await queryRunner.query(
|
|
197
|
+
`ALTER TABLE "IncomingCallLogItem" DROP CONSTRAINT "FK_4d0e67775a87ffdf8b1413d5bcb"`,
|
|
198
|
+
);
|
|
199
|
+
await queryRunner.query(
|
|
200
|
+
`ALTER TABLE "IncomingCallLog" DROP CONSTRAINT "FK_fb2531b7d8c44e4cad026fb8662"`,
|
|
201
|
+
);
|
|
202
|
+
await queryRunner.query(
|
|
203
|
+
`ALTER TABLE "IncomingCallLog" DROP CONSTRAINT "FK_18e2254401cd580a906808d6908"`,
|
|
204
|
+
);
|
|
205
|
+
await queryRunner.query(
|
|
206
|
+
`ALTER TABLE "IncomingCallLog" DROP CONSTRAINT "FK_915f3d5f9bf60430bbd89a1efce"`,
|
|
207
|
+
);
|
|
208
|
+
await queryRunner.query(
|
|
209
|
+
`ALTER TABLE "IncomingCallPolicyEscalationRule" DROP CONSTRAINT "FK_c434cfc9ca11de56e1b5a316559"`,
|
|
210
|
+
);
|
|
211
|
+
await queryRunner.query(
|
|
212
|
+
`ALTER TABLE "IncomingCallPolicyEscalationRule" DROP CONSTRAINT "FK_c0726b90365656bd869ad821b3b"`,
|
|
213
|
+
);
|
|
214
|
+
await queryRunner.query(
|
|
215
|
+
`ALTER TABLE "IncomingCallPolicyEscalationRule" DROP CONSTRAINT "FK_c0c7ea3cb722a94e074c4486b29"`,
|
|
216
|
+
);
|
|
217
|
+
await queryRunner.query(
|
|
218
|
+
`ALTER TABLE "IncomingCallPolicyEscalationRule" DROP CONSTRAINT "FK_5e2f646a84077a5fd4969ef090b"`,
|
|
219
|
+
);
|
|
220
|
+
await queryRunner.query(
|
|
221
|
+
`ALTER TABLE "IncomingCallPolicyEscalationRule" DROP CONSTRAINT "FK_d9358a64a7d4a3f48804844e698"`,
|
|
222
|
+
);
|
|
223
|
+
await queryRunner.query(
|
|
224
|
+
`ALTER TABLE "IncomingCallPolicyEscalationRule" DROP CONSTRAINT "FK_3ff7e49f61d10020a7298c3dc64"`,
|
|
225
|
+
);
|
|
226
|
+
await queryRunner.query(
|
|
227
|
+
`ALTER TABLE "IncomingCallPolicy" DROP CONSTRAINT "FK_197d35d96152cbaa101afa670bd"`,
|
|
228
|
+
);
|
|
229
|
+
await queryRunner.query(
|
|
230
|
+
`ALTER TABLE "IncomingCallPolicy" DROP CONSTRAINT "FK_fb8001e77d8907b8e089afa6193"`,
|
|
231
|
+
);
|
|
232
|
+
await queryRunner.query(
|
|
233
|
+
`ALTER TABLE "IncomingCallPolicy" DROP CONSTRAINT "FK_08a214983b56f6102a4fdecfa65"`,
|
|
234
|
+
);
|
|
235
|
+
await queryRunner.query(
|
|
236
|
+
`ALTER TABLE "IncomingCallPolicy" DROP CONSTRAINT "FK_3c52bf3d9f9aca2ac74848fc0f7"`,
|
|
237
|
+
);
|
|
238
|
+
await queryRunner.query(
|
|
239
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
|
|
240
|
+
);
|
|
241
|
+
await queryRunner.query(
|
|
242
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
|
|
243
|
+
);
|
|
244
|
+
await queryRunner.query(
|
|
245
|
+
`ALTER TABLE "User" ADD "alertPhoneNumber" character varying(30)`,
|
|
246
|
+
);
|
|
247
|
+
await queryRunner.query(
|
|
248
|
+
`DROP INDEX "public"."IDX_fb6335122b06a052c29d3d6d8b"`,
|
|
249
|
+
);
|
|
250
|
+
await queryRunner.query(
|
|
251
|
+
`DROP INDEX "public"."IDX_fb7de9bbc395452347629e9131"`,
|
|
252
|
+
);
|
|
253
|
+
await queryRunner.query(`DROP TABLE "IncomingCallPolicyLabel"`);
|
|
254
|
+
await queryRunner.query(
|
|
255
|
+
`DROP INDEX "public"."IDX_3b7f38fb56ffd49e972205cb48"`,
|
|
256
|
+
);
|
|
257
|
+
await queryRunner.query(
|
|
258
|
+
`DROP INDEX "public"."IDX_af7375987850451a60f0002ae4"`,
|
|
259
|
+
);
|
|
260
|
+
await queryRunner.query(`DROP TABLE "UserIncomingCallNumber"`);
|
|
261
|
+
await queryRunner.query(
|
|
262
|
+
`DROP INDEX "public"."IDX_c2f339131713708082a01cd880"`,
|
|
263
|
+
);
|
|
264
|
+
await queryRunner.query(
|
|
265
|
+
`DROP INDEX "public"."IDX_5ecd45b8e5c05322459b01f37e"`,
|
|
266
|
+
);
|
|
267
|
+
await queryRunner.query(
|
|
268
|
+
`DROP INDEX "public"."IDX_cb196303d93ee4044d0a4f076e"`,
|
|
269
|
+
);
|
|
270
|
+
await queryRunner.query(
|
|
271
|
+
`DROP INDEX "public"."IDX_d11a949952998081bed04512a7"`,
|
|
272
|
+
);
|
|
273
|
+
await queryRunner.query(
|
|
274
|
+
`DROP INDEX "public"."IDX_4d0e67775a87ffdf8b1413d5bc"`,
|
|
275
|
+
);
|
|
276
|
+
await queryRunner.query(`DROP TABLE "IncomingCallLogItem"`);
|
|
277
|
+
await queryRunner.query(
|
|
278
|
+
`DROP INDEX "public"."IDX_0821fb47819572b56836b06102"`,
|
|
279
|
+
);
|
|
280
|
+
await queryRunner.query(
|
|
281
|
+
`DROP INDEX "public"."IDX_bac28bb0cfff30703cb79e4a9c"`,
|
|
282
|
+
);
|
|
283
|
+
await queryRunner.query(
|
|
284
|
+
`DROP INDEX "public"."IDX_4769731b4e40dd238410b47337"`,
|
|
285
|
+
);
|
|
286
|
+
await queryRunner.query(
|
|
287
|
+
`DROP INDEX "public"."IDX_18e2254401cd580a906808d690"`,
|
|
288
|
+
);
|
|
289
|
+
await queryRunner.query(
|
|
290
|
+
`DROP INDEX "public"."IDX_915f3d5f9bf60430bbd89a1efc"`,
|
|
291
|
+
);
|
|
292
|
+
await queryRunner.query(`DROP TABLE "IncomingCallLog"`);
|
|
293
|
+
await queryRunner.query(
|
|
294
|
+
`DROP INDEX "public"."IDX_2940b1f9392441bcff1a33ebc4"`,
|
|
295
|
+
);
|
|
296
|
+
await queryRunner.query(
|
|
297
|
+
`DROP INDEX "public"."IDX_d9358a64a7d4a3f48804844e69"`,
|
|
298
|
+
);
|
|
299
|
+
await queryRunner.query(
|
|
300
|
+
`DROP INDEX "public"."IDX_3ff7e49f61d10020a7298c3dc6"`,
|
|
301
|
+
);
|
|
302
|
+
await queryRunner.query(`DROP TABLE "IncomingCallPolicyEscalationRule"`);
|
|
303
|
+
await queryRunner.query(
|
|
304
|
+
`DROP INDEX "public"."IDX_6680fc89e547525f8051bb2599"`,
|
|
305
|
+
);
|
|
306
|
+
await queryRunner.query(
|
|
307
|
+
`DROP INDEX "public"."IDX_5242e2cffd7f4050e6189e569d"`,
|
|
308
|
+
);
|
|
309
|
+
await queryRunner.query(
|
|
310
|
+
`DROP INDEX "public"."IDX_f2f54dca4c8c0bbdea4c37edb2"`,
|
|
311
|
+
);
|
|
312
|
+
await queryRunner.query(
|
|
313
|
+
`DROP INDEX "public"."IDX_3c52bf3d9f9aca2ac74848fc0f"`,
|
|
314
|
+
);
|
|
315
|
+
await queryRunner.query(`DROP TABLE "IncomingCallPolicy"`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
@@ -222,9 +222,7 @@ import { AddOAuthProviderType1768217403078 } from "./1768217403078-AddOAuthProvi
|
|
|
222
222
|
import { AddIncomingEmailMonitor1768335589018 } from "./1768335589018-AddIncomingEmailMonitor";
|
|
223
223
|
import { MigrationName1768422356713 } from "./1768422356713-MigrationName";
|
|
224
224
|
import { MigrationName1768583966447 } from "./1768583966447-MigrationName";
|
|
225
|
-
import {
|
|
226
|
-
import { MigrationName1768649699509 } from "./1768649699509-MigrationName";
|
|
227
|
-
import { MigrationName1768682071562 } from "./1768682071562-MigrationName";
|
|
225
|
+
import { MigrationName1768825402472 } from "./1768825402472-MigrationName";
|
|
228
226
|
|
|
229
227
|
export default [
|
|
230
228
|
InitialMigration,
|
|
@@ -451,7 +449,5 @@ export default [
|
|
|
451
449
|
AddIncomingEmailMonitor1768335589018,
|
|
452
450
|
MigrationName1768422356713,
|
|
453
451
|
MigrationName1768583966447,
|
|
454
|
-
|
|
455
|
-
MigrationName1768649699509,
|
|
456
|
-
MigrationName1768682071562,
|
|
452
|
+
MigrationName1768825402472,
|
|
457
453
|
];
|
|
@@ -59,7 +59,12 @@ import Text from "../../Types/Text";
|
|
|
59
59
|
import Typeof from "../../Types/Typeof";
|
|
60
60
|
import API from "../../Utils/API";
|
|
61
61
|
import Slug from "../../Utils/Slug";
|
|
62
|
-
import {
|
|
62
|
+
import {
|
|
63
|
+
DataSource,
|
|
64
|
+
EntityManager,
|
|
65
|
+
Repository,
|
|
66
|
+
SelectQueryBuilder,
|
|
67
|
+
} from "typeorm";
|
|
63
68
|
import { FindWhere } from "../../Types/BaseDatabase/Query";
|
|
64
69
|
import Realtime from "../Utils/Realtime";
|
|
65
70
|
import ModelEventType from "../../Types/Realtime/ModelEventType";
|
|
@@ -129,6 +134,22 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
129
134
|
throw new DatabaseNotConnectedException();
|
|
130
135
|
}
|
|
131
136
|
|
|
137
|
+
public async executeTransaction<TResult>(
|
|
138
|
+
runInTransaction: (entityManager: EntityManager) => Promise<TResult>,
|
|
139
|
+
): Promise<TResult> {
|
|
140
|
+
if (!PostgresAppInstance.isConnected()) {
|
|
141
|
+
throw new DatabaseNotConnectedException();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const dataSource: DataSource | null = PostgresAppInstance.getDataSource();
|
|
145
|
+
|
|
146
|
+
if (!dataSource) {
|
|
147
|
+
throw new DatabaseNotConnectedException();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return await dataSource.transaction(runInTransaction);
|
|
151
|
+
}
|
|
152
|
+
|
|
132
153
|
protected isValid(data: TBaseModel): boolean {
|
|
133
154
|
if (!data) {
|
|
134
155
|
throw new BadDataException("Data cannot be null");
|
|
@@ -1691,3 +1712,4 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
1691
1712
|
}
|
|
1692
1713
|
|
|
1693
1714
|
export default DatabaseService;
|
|
1715
|
+
export { EntityManager };
|
|
@@ -35,10 +35,18 @@ export class Service extends DatabaseService<Model> {
|
|
|
35
35
|
createBy.data.domain = new Domain(domain.trim().toLowerCase());
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/*
|
|
39
|
+
* Prevent setting isVerified during creation, EXCEPT for test domains
|
|
40
|
+
* Test domains can be auto-verified since they are reserved TLDs that can't have real DNS records
|
|
41
|
+
*/
|
|
38
42
|
if (!createBy.props.isRoot && createBy.data.isVerified) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
)
|
|
43
|
+
const domainStr: string = createBy.data.domain?.toString() || "";
|
|
44
|
+
|
|
45
|
+
if (!Domain.isTestDomain(domainStr)) {
|
|
46
|
+
throw new BadDataException(
|
|
47
|
+
"Domain cannot be verified during creation. Please verify the domain after creation. Please set isVerified to false.",
|
|
48
|
+
);
|
|
49
|
+
}
|
|
42
50
|
}
|
|
43
51
|
|
|
44
52
|
createBy.data.domainVerificationText =
|
|
@@ -96,19 +104,22 @@ export class Service extends DatabaseService<Model> {
|
|
|
96
104
|
);
|
|
97
105
|
}
|
|
98
106
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (!isVerified) {
|
|
105
|
-
throw new BadDataException(
|
|
106
|
-
"Verification TXT record " +
|
|
107
|
-
verificationText +
|
|
108
|
-
" not found in domain " +
|
|
109
|
-
domain +
|
|
110
|
-
". Please add a TXT record to verify the domain. If you have already added the TXT record, please wait for few hours to let DNS to propagate.",
|
|
107
|
+
// Skip DNS verification for test domains (reserved TLDs for testing)
|
|
108
|
+
if (!Domain.isTestDomain(domain)) {
|
|
109
|
+
const isVerified: boolean = await Domain.verifyTxtRecord(
|
|
110
|
+
domain,
|
|
111
|
+
verificationText,
|
|
111
112
|
);
|
|
113
|
+
|
|
114
|
+
if (!isVerified) {
|
|
115
|
+
throw new BadDataException(
|
|
116
|
+
"Verification TXT record " +
|
|
117
|
+
verificationText +
|
|
118
|
+
" not found in domain " +
|
|
119
|
+
domain +
|
|
120
|
+
". Please add a TXT record to verify the domain. If you have already added the TXT record, please wait for few hours to let DNS to propagate.",
|
|
121
|
+
);
|
|
122
|
+
}
|
|
112
123
|
}
|
|
113
124
|
}
|
|
114
125
|
}
|
|
@@ -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>> {
|
package/Types/Domain.ts
CHANGED
|
@@ -5,6 +5,29 @@ import { FindOperator } from "typeorm/find-options/FindOperator";
|
|
|
5
5
|
import Zod, { ZodSchema } from "../Utils/Schema/Zod";
|
|
6
6
|
|
|
7
7
|
export default class Domain extends DatabaseProperty {
|
|
8
|
+
/*
|
|
9
|
+
* Reserved TLDs for testing and documentation (per IANA)
|
|
10
|
+
* These domains can never have real DNS records, so they're safe for testing
|
|
11
|
+
*/
|
|
12
|
+
public static readonly TEST_DOMAIN_SUFFIXES: string[] = [
|
|
13
|
+
".example.com",
|
|
14
|
+
".example.org",
|
|
15
|
+
".example.net",
|
|
16
|
+
".test",
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Checks if a domain is a test/reserved domain that can skip DNS verification.
|
|
21
|
+
* Test domains include .example.com, .example.org, .example.net, and .test TLDs.
|
|
22
|
+
* These are reserved by IANA for documentation and testing purposes.
|
|
23
|
+
*/
|
|
24
|
+
public static isTestDomain(domain: string): boolean {
|
|
25
|
+
const domainLower: string = domain.toLowerCase().trim();
|
|
26
|
+
return Domain.TEST_DOMAIN_SUFFIXES.some((suffix: string) => {
|
|
27
|
+
return domainLower.endsWith(suffix);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
8
31
|
private _domain: string = "";
|
|
9
32
|
public get domain(): string {
|
|
10
33
|
return this._domain;
|
|
@@ -307,6 +307,7 @@ __decorate([
|
|
|
307
307
|
}),
|
|
308
308
|
TableColumn({
|
|
309
309
|
required: true,
|
|
310
|
+
computed: true,
|
|
310
311
|
type: TableColumnType.ShortText,
|
|
311
312
|
title: "Full Domain",
|
|
312
313
|
description: "Full domain of your status page (like status.acmeinc.com). This is autogenerated and is derived from subdomain and domain.",
|
|
@@ -425,6 +426,7 @@ __decorate([
|
|
|
425
426
|
}),
|
|
426
427
|
TableColumn({
|
|
427
428
|
required: true,
|
|
429
|
+
computed: true,
|
|
428
430
|
type: TableColumnType.ShortText,
|
|
429
431
|
title: "CNAME Verification Token",
|
|
430
432
|
description: "CNAME Verification Token",
|