@oneuptime/common 9.3.16 → 9.3.18
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/Monitor.ts +109 -0
- package/Server/EnvironmentConfig.ts +16 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1768335589018-AddIncomingEmailMonitor.ts +53 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Middleware/MultipartFormData.ts +17 -0
- package/Server/Services/InboundEmail/InboundEmailProvider.ts +64 -0
- package/Server/Services/InboundEmail/InboundEmailProviderFactory.ts +80 -0
- package/Server/Services/InboundEmail/Providers/SendGridInboundProvider.ts +211 -0
- package/Server/Services/MonitorService.ts +4 -0
- package/Server/Utils/Monitor/Criteria/IncomingEmailCriteria.ts +248 -0
- package/Server/Utils/Monitor/DataToProcess.ts +2 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +13 -0
- package/Types/Monitor/CriteriaFilter.ts +7 -0
- package/Types/Monitor/IncomingEmailMonitor/IncomingEmailMonitorRequest.ts +25 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +67 -0
- package/Types/Monitor/MonitorType.ts +28 -0
- package/UI/Components/CardSelect/CardSelect.tsx +105 -0
- package/UI/Components/Forms/Fields/FormField.tsx +20 -0
- package/UI/Components/Forms/Types/Field.ts +2 -0
- package/UI/Components/Forms/Types/FormFieldSchemaType.ts +1 -0
- package/UI/Config.ts +3 -0
- package/build/dist/Models/DatabaseModels/Monitor.js +110 -0
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +10 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768335589018-AddIncomingEmailMonitor.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768335589018-AddIncomingEmailMonitor.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/MultipartFormData.js +13 -0
- package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -0
- package/build/dist/Server/Services/InboundEmail/InboundEmailProvider.js +12 -0
- package/build/dist/Server/Services/InboundEmail/InboundEmailProvider.js.map +1 -0
- package/build/dist/Server/Services/InboundEmail/InboundEmailProviderFactory.js +59 -0
- package/build/dist/Server/Services/InboundEmail/InboundEmailProviderFactory.js.map +1 -0
- package/build/dist/Server/Services/InboundEmail/Providers/SendGridInboundProvider.js +148 -0
- package/build/dist/Server/Services/InboundEmail/Providers/SendGridInboundProvider.js.map +1 -0
- package/build/dist/Server/Services/MonitorService.js +3 -0
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingEmailCriteria.js +164 -0
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingEmailCriteria.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +10 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +6 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/IncomingEmailMonitor/IncomingEmailMonitorRequest.js +2 -0
- package/build/dist/Types/Monitor/IncomingEmailMonitor/IncomingEmailMonitorRequest.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +62 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorType.js +26 -0
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/UI/Components/CardSelect/CardSelect.js +30 -0
- package/build/dist/UI/Components/CardSelect/CardSelect.js.map +1 -0
- package/build/dist/UI/Components/Forms/Fields/FormField.js +8 -0
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Forms/Types/Field.js.map +1 -1
- package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js +1 -0
- package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js.map +1 -1
- package/build/dist/UI/Config.js +1 -0
- package/build/dist/UI/Config.js.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import logger from "../../../Utils/Logger";
|
|
2
|
+
import DataToProcess from "../DataToProcess";
|
|
3
|
+
import OneUptimeDate from "../../../../Types/Date";
|
|
4
|
+
import {
|
|
5
|
+
CheckOn,
|
|
6
|
+
CriteriaFilter,
|
|
7
|
+
FilterType,
|
|
8
|
+
} from "../../../../Types/Monitor/CriteriaFilter";
|
|
9
|
+
import IncomingEmailMonitorRequest from "../../../../Types/Monitor/IncomingEmailMonitor/IncomingEmailMonitorRequest";
|
|
10
|
+
import Typeof from "../../../../Types/Typeof";
|
|
11
|
+
import CaptureSpan from "../../Telemetry/CaptureSpan";
|
|
12
|
+
|
|
13
|
+
export default class IncomingEmailCriteria {
|
|
14
|
+
@CaptureSpan()
|
|
15
|
+
public static async isMonitorInstanceCriteriaFilterMet(input: {
|
|
16
|
+
dataToProcess: DataToProcess;
|
|
17
|
+
criteriaFilter: CriteriaFilter;
|
|
18
|
+
}): Promise<string | null> {
|
|
19
|
+
// Incoming Email Monitoring Checks
|
|
20
|
+
|
|
21
|
+
logger.debug(
|
|
22
|
+
"Checking IncomingEmailCriteria for Monitor: " +
|
|
23
|
+
input.dataToProcess.monitorId.toString(),
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
logger.debug(
|
|
27
|
+
"Data to process: " + JSON.stringify(input.dataToProcess, null, 2),
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
logger.debug(
|
|
31
|
+
"Criteria Filter: " + JSON.stringify(input.criteriaFilter, null, 2),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
let value: number | string | undefined = input.criteriaFilter.value;
|
|
35
|
+
|
|
36
|
+
const emailData: IncomingEmailMonitorRequest =
|
|
37
|
+
input.dataToProcess as IncomingEmailMonitorRequest;
|
|
38
|
+
|
|
39
|
+
// Check on Email Received time
|
|
40
|
+
if (input.criteriaFilter.checkOn === CheckOn.EmailReceivedAt) {
|
|
41
|
+
logger.debug(
|
|
42
|
+
"Checking EmailReceivedAt for Monitor: " +
|
|
43
|
+
input.dataToProcess.monitorId.toString(),
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const lastEmailTime: Date = emailData.emailReceivedAt;
|
|
47
|
+
|
|
48
|
+
logger.debug("Last Email Time: " + lastEmailTime);
|
|
49
|
+
|
|
50
|
+
const differenceInMinutes: number = OneUptimeDate.getDifferenceInMinutes(
|
|
51
|
+
lastEmailTime,
|
|
52
|
+
emailData.checkedAt || OneUptimeDate.getCurrentDate(),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
logger.debug("Difference in minutes: " + differenceInMinutes);
|
|
56
|
+
|
|
57
|
+
if (!value) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (typeof value === Typeof.String) {
|
|
62
|
+
try {
|
|
63
|
+
value = parseInt(value as string);
|
|
64
|
+
} catch (err) {
|
|
65
|
+
logger.error(err);
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (typeof value !== Typeof.Number) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (input.criteriaFilter.filterType === FilterType.RecievedInMinutes) {
|
|
75
|
+
logger.debug(
|
|
76
|
+
"Checking RecievedInMinutes for Monitor: " +
|
|
77
|
+
input.dataToProcess.monitorId.toString(),
|
|
78
|
+
);
|
|
79
|
+
if (value && differenceInMinutes <= (value as number)) {
|
|
80
|
+
logger.debug(
|
|
81
|
+
"RecievedInMinutes for Monitor: " +
|
|
82
|
+
input.dataToProcess.monitorId.toString() +
|
|
83
|
+
" is true",
|
|
84
|
+
);
|
|
85
|
+
return `Email received in ${value} minutes. It was received ${differenceInMinutes} minutes ago.`;
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (input.criteriaFilter.filterType === FilterType.NotRecievedInMinutes) {
|
|
91
|
+
logger.debug(
|
|
92
|
+
"Checking NotRecievedInMinutes for Monitor: " +
|
|
93
|
+
input.dataToProcess.monitorId.toString(),
|
|
94
|
+
);
|
|
95
|
+
if (value && differenceInMinutes > (value as number)) {
|
|
96
|
+
logger.debug(
|
|
97
|
+
"NotRecievedInMinutes for Monitor: " +
|
|
98
|
+
input.dataToProcess.monitorId.toString() +
|
|
99
|
+
" is true",
|
|
100
|
+
);
|
|
101
|
+
return `Email not received in ${value} minutes. It was received ${differenceInMinutes} minutes ago.`;
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Check on Email Subject
|
|
108
|
+
if (
|
|
109
|
+
input.criteriaFilter.checkOn === CheckOn.EmailSubject &&
|
|
110
|
+
!emailData.onlyCheckForIncomingEmailReceivedAt
|
|
111
|
+
) {
|
|
112
|
+
const subject: string = emailData.emailSubject || "";
|
|
113
|
+
|
|
114
|
+
return this.evaluateStringCriteria(
|
|
115
|
+
subject,
|
|
116
|
+
input.criteriaFilter,
|
|
117
|
+
"Email subject",
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Check on Email From
|
|
122
|
+
if (
|
|
123
|
+
input.criteriaFilter.checkOn === CheckOn.EmailFrom &&
|
|
124
|
+
!emailData.onlyCheckForIncomingEmailReceivedAt
|
|
125
|
+
) {
|
|
126
|
+
const from: string = emailData.emailFrom || "";
|
|
127
|
+
|
|
128
|
+
return this.evaluateStringCriteria(
|
|
129
|
+
from,
|
|
130
|
+
input.criteriaFilter,
|
|
131
|
+
"Email from",
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Check on Email Body
|
|
136
|
+
if (
|
|
137
|
+
input.criteriaFilter.checkOn === CheckOn.EmailBody &&
|
|
138
|
+
!emailData.onlyCheckForIncomingEmailReceivedAt
|
|
139
|
+
) {
|
|
140
|
+
const body: string = emailData.emailBody || "";
|
|
141
|
+
|
|
142
|
+
return this.evaluateStringCriteria(
|
|
143
|
+
body,
|
|
144
|
+
input.criteriaFilter,
|
|
145
|
+
"Email body",
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Check on Email To
|
|
150
|
+
if (
|
|
151
|
+
input.criteriaFilter.checkOn === CheckOn.EmailTo &&
|
|
152
|
+
!emailData.onlyCheckForIncomingEmailReceivedAt
|
|
153
|
+
) {
|
|
154
|
+
const to: string = emailData.emailTo || "";
|
|
155
|
+
|
|
156
|
+
return this.evaluateStringCriteria(to, input.criteriaFilter, "Email to");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Evaluate string criteria filters
|
|
164
|
+
*/
|
|
165
|
+
private static evaluateStringCriteria(
|
|
166
|
+
fieldValue: string,
|
|
167
|
+
criteriaFilter: CriteriaFilter,
|
|
168
|
+
fieldName: string,
|
|
169
|
+
): string | null {
|
|
170
|
+
const value: string | number | undefined = criteriaFilter.value;
|
|
171
|
+
|
|
172
|
+
if (criteriaFilter.filterType === FilterType.Contains) {
|
|
173
|
+
if (
|
|
174
|
+
value &&
|
|
175
|
+
fieldValue.toLowerCase().includes((value as string).toLowerCase())
|
|
176
|
+
) {
|
|
177
|
+
return `${fieldName} contains "${value}".`;
|
|
178
|
+
}
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (criteriaFilter.filterType === FilterType.NotContains) {
|
|
183
|
+
if (
|
|
184
|
+
value &&
|
|
185
|
+
!fieldValue.toLowerCase().includes((value as string).toLowerCase())
|
|
186
|
+
) {
|
|
187
|
+
return `${fieldName} does not contain "${value}".`;
|
|
188
|
+
}
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (criteriaFilter.filterType === FilterType.EqualTo) {
|
|
193
|
+
if (
|
|
194
|
+
value &&
|
|
195
|
+
fieldValue.toLowerCase() === (value as string).toLowerCase()
|
|
196
|
+
) {
|
|
197
|
+
return `${fieldName} equals "${value}".`;
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (criteriaFilter.filterType === FilterType.NotEqualTo) {
|
|
203
|
+
if (
|
|
204
|
+
value &&
|
|
205
|
+
fieldValue.toLowerCase() !== (value as string).toLowerCase()
|
|
206
|
+
) {
|
|
207
|
+
return `${fieldName} does not equal "${value}".`;
|
|
208
|
+
}
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (criteriaFilter.filterType === FilterType.StartsWith) {
|
|
213
|
+
if (
|
|
214
|
+
value &&
|
|
215
|
+
fieldValue.toLowerCase().startsWith((value as string).toLowerCase())
|
|
216
|
+
) {
|
|
217
|
+
return `${fieldName} starts with "${value}".`;
|
|
218
|
+
}
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (criteriaFilter.filterType === FilterType.EndsWith) {
|
|
223
|
+
if (
|
|
224
|
+
value &&
|
|
225
|
+
fieldValue.toLowerCase().endsWith((value as string).toLowerCase())
|
|
226
|
+
) {
|
|
227
|
+
return `${fieldName} ends with "${value}".`;
|
|
228
|
+
}
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (criteriaFilter.filterType === FilterType.IsEmpty) {
|
|
233
|
+
if (!fieldValue || fieldValue.trim() === "") {
|
|
234
|
+
return `${fieldName} is empty.`;
|
|
235
|
+
}
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (criteriaFilter.filterType === FilterType.IsNotEmpty) {
|
|
240
|
+
if (fieldValue && fieldValue.trim() !== "") {
|
|
241
|
+
return `${fieldName} is not empty.`;
|
|
242
|
+
}
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import IncomingMonitorRequest from "../../../Types/Monitor/IncomingMonitor/IncomingMonitorRequest";
|
|
2
|
+
import IncomingEmailMonitorRequest from "../../../Types/Monitor/IncomingEmailMonitor/IncomingEmailMonitorRequest";
|
|
2
3
|
import ServerMonitorResponse from "../../../Types/Monitor/ServerMonitor/ServerMonitorResponse";
|
|
3
4
|
import ProbeMonitorResponse from "../../../Types/Probe/ProbeMonitorResponse";
|
|
4
5
|
import LogMonitorResponse from "../../../Types/Monitor/LogMonitor/LogMonitorResponse";
|
|
@@ -9,6 +10,7 @@ import ExceptionMonitorResponse from "../../../Types/Monitor/ExceptionMonitor/Ex
|
|
|
9
10
|
type DataToProcess =
|
|
10
11
|
| ProbeMonitorResponse
|
|
11
12
|
| IncomingMonitorRequest
|
|
13
|
+
| IncomingEmailMonitorRequest
|
|
12
14
|
| ServerMonitorResponse
|
|
13
15
|
| LogMonitorResponse
|
|
14
16
|
| TraceMonitorResponse
|
|
@@ -2,6 +2,7 @@ import logger from "../Logger";
|
|
|
2
2
|
import VMUtil from "../VM/VMAPI";
|
|
3
3
|
import APIRequestCriteria from "./Criteria/APIRequestCriteria";
|
|
4
4
|
import CustomCodeMonitoringCriteria from "./Criteria/CustomCodeMonitorCriteria";
|
|
5
|
+
import IncomingEmailCriteria from "./Criteria/IncomingEmailCriteria";
|
|
5
6
|
import IncomingRequestCriteria from "./Criteria/IncomingRequestCriteria";
|
|
6
7
|
import SSLMonitorCriteria from "./Criteria/SSLMonitorCriteria";
|
|
7
8
|
import ServerMonitorCriteria from "./Criteria/ServerMonitorCriteria";
|
|
@@ -394,6 +395,18 @@ ${contextBlock}
|
|
|
394
395
|
}
|
|
395
396
|
}
|
|
396
397
|
|
|
398
|
+
if (input.monitor.monitorType === MonitorType.IncomingEmail) {
|
|
399
|
+
const incomingEmailResult: string | null =
|
|
400
|
+
await IncomingEmailCriteria.isMonitorInstanceCriteriaFilterMet({
|
|
401
|
+
dataToProcess: input.dataToProcess,
|
|
402
|
+
criteriaFilter: input.criteriaFilter,
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
if (incomingEmailResult) {
|
|
406
|
+
return incomingEmailResult;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
397
410
|
if (input.monitor.monitorType === MonitorType.SSLCertificate) {
|
|
398
411
|
const sslMonitorResult: string | null =
|
|
399
412
|
await SSLMonitorCriteria.isMonitorInstanceCriteriaFilterMet({
|
|
@@ -47,6 +47,13 @@ export enum CheckOn {
|
|
|
47
47
|
|
|
48
48
|
// Metric Monitors.
|
|
49
49
|
MetricValue = "Metric Value",
|
|
50
|
+
|
|
51
|
+
// Incoming Email monitors.
|
|
52
|
+
EmailSubject = "Email Subject",
|
|
53
|
+
EmailFrom = "Email From Address",
|
|
54
|
+
EmailBody = "Email Body",
|
|
55
|
+
EmailTo = "Email To Address",
|
|
56
|
+
EmailReceivedAt = "Email Received",
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
export interface ServerMonitorOptions {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import Dictionary from "../../Dictionary";
|
|
2
|
+
import ObjectID from "../../ObjectID";
|
|
3
|
+
import MonitorEvaluationSummary from "../MonitorEvaluationSummary";
|
|
4
|
+
|
|
5
|
+
export interface EmailAttachment {
|
|
6
|
+
filename: string;
|
|
7
|
+
contentType: string;
|
|
8
|
+
size: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default interface IncomingEmailMonitorRequest {
|
|
12
|
+
projectId: ObjectID;
|
|
13
|
+
monitorId: ObjectID;
|
|
14
|
+
emailFrom: string;
|
|
15
|
+
emailTo: string;
|
|
16
|
+
emailSubject: string;
|
|
17
|
+
emailBody: string;
|
|
18
|
+
emailBodyHtml?: string | undefined;
|
|
19
|
+
emailHeaders?: Dictionary<string> | undefined;
|
|
20
|
+
emailReceivedAt: Date;
|
|
21
|
+
checkedAt: Date;
|
|
22
|
+
attachments?: Array<EmailAttachment> | undefined;
|
|
23
|
+
onlyCheckForIncomingEmailReceivedAt?: boolean | undefined;
|
|
24
|
+
evaluationSummary?: MonitorEvaluationSummary | undefined;
|
|
25
|
+
}
|
|
@@ -94,6 +94,33 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
|
|
|
94
94
|
return monitorCriteriaInstance;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
if (arg.monitorType === MonitorType.IncomingEmail) {
|
|
98
|
+
const monitorCriteriaInstance: MonitorCriteriaInstance =
|
|
99
|
+
new MonitorCriteriaInstance();
|
|
100
|
+
|
|
101
|
+
monitorCriteriaInstance.data = {
|
|
102
|
+
id: ObjectID.generate().toString(),
|
|
103
|
+
monitorStatusId: arg.monitorStatusId,
|
|
104
|
+
filterCondition: FilterCondition.All,
|
|
105
|
+
filters: [
|
|
106
|
+
{
|
|
107
|
+
checkOn: CheckOn.EmailReceivedAt,
|
|
108
|
+
filterType: FilterType.RecievedInMinutes,
|
|
109
|
+
value: 30,
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
incidents: [],
|
|
113
|
+
alerts: [],
|
|
114
|
+
createAlerts: false,
|
|
115
|
+
changeMonitorStatus: true,
|
|
116
|
+
createIncidents: false,
|
|
117
|
+
name: `Check if ${arg.monitorName} is online`,
|
|
118
|
+
description: `This criteria checks if the ${arg.monitorName} is online`,
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
return monitorCriteriaInstance;
|
|
122
|
+
}
|
|
123
|
+
|
|
97
124
|
if (arg.monitorType === MonitorType.Logs) {
|
|
98
125
|
const monitorCriteriaInstance: MonitorCriteriaInstance =
|
|
99
126
|
new MonitorCriteriaInstance();
|
|
@@ -658,6 +685,46 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
|
|
|
658
685
|
};
|
|
659
686
|
}
|
|
660
687
|
|
|
688
|
+
if (arg.monitorType === MonitorType.IncomingEmail) {
|
|
689
|
+
monitorCriteriaInstance.data = {
|
|
690
|
+
id: ObjectID.generate().toString(),
|
|
691
|
+
monitorStatusId: arg.monitorStatusId,
|
|
692
|
+
filterCondition: FilterCondition.Any,
|
|
693
|
+
filters: [
|
|
694
|
+
{
|
|
695
|
+
checkOn: CheckOn.EmailReceivedAt,
|
|
696
|
+
filterType: FilterType.NotRecievedInMinutes,
|
|
697
|
+
value: 30, // if email is not received in 30 minutes, then the monitor is offline
|
|
698
|
+
},
|
|
699
|
+
],
|
|
700
|
+
alerts: [
|
|
701
|
+
{
|
|
702
|
+
title: `${arg.monitorName} is offline`,
|
|
703
|
+
description: `${arg.monitorName} is currently offline. No email received.`,
|
|
704
|
+
alertSeverityId: arg.alertSeverityId,
|
|
705
|
+
autoResolveAlert: true,
|
|
706
|
+
id: ObjectID.generate().toString(),
|
|
707
|
+
onCallPolicyIds: [],
|
|
708
|
+
},
|
|
709
|
+
],
|
|
710
|
+
createAlerts: false,
|
|
711
|
+
incidents: [
|
|
712
|
+
{
|
|
713
|
+
title: `${arg.monitorName} is offline`,
|
|
714
|
+
description: `${arg.monitorName} is currently offline. No email received.`,
|
|
715
|
+
incidentSeverityId: arg.incidentSeverityId,
|
|
716
|
+
autoResolveIncident: true,
|
|
717
|
+
id: ObjectID.generate().toString(),
|
|
718
|
+
onCallPolicyIds: [],
|
|
719
|
+
},
|
|
720
|
+
],
|
|
721
|
+
changeMonitorStatus: true,
|
|
722
|
+
createIncidents: true,
|
|
723
|
+
name: `Check if ${arg.monitorName} is offline`,
|
|
724
|
+
description: `This criteria checks if the ${arg.monitorName} is offline`,
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
|
|
661
728
|
if (
|
|
662
729
|
arg.monitorType === MonitorType.CustomJavaScriptCode ||
|
|
663
730
|
arg.monitorType === MonitorType.SyntheticMonitor
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import BadDataException from "../Exception/BadDataException";
|
|
2
|
+
import IconProp from "../Icon/IconProp";
|
|
2
3
|
|
|
3
4
|
enum MonitorType {
|
|
4
5
|
Manual = "Manual",
|
|
@@ -8,6 +9,7 @@ enum MonitorType {
|
|
|
8
9
|
Kubernetes = "Kubernetes",
|
|
9
10
|
IP = "IP",
|
|
10
11
|
IncomingRequest = "Incoming Request",
|
|
12
|
+
IncomingEmail = "Incoming Email",
|
|
11
13
|
Port = "Port",
|
|
12
14
|
Server = "Server",
|
|
13
15
|
SSLCertificate = "SSL Certificate",
|
|
@@ -29,6 +31,7 @@ export interface MonitorTypeProps {
|
|
|
29
31
|
monitorType: MonitorType;
|
|
30
32
|
description: string;
|
|
31
33
|
title: string;
|
|
34
|
+
icon: IconProp;
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
export class MonitorTypeHelper {
|
|
@@ -52,24 +55,28 @@ export class MonitorTypeHelper {
|
|
|
52
55
|
title: "API",
|
|
53
56
|
description:
|
|
54
57
|
"This monitor type lets you monitor any API - GET, POST, PUT, DELETE or more.",
|
|
58
|
+
icon: IconProp.Code,
|
|
55
59
|
},
|
|
56
60
|
{
|
|
57
61
|
monitorType: MonitorType.Manual,
|
|
58
62
|
title: "Manual",
|
|
59
63
|
description:
|
|
60
64
|
"This monitor is a static monitor and will not actually monitor anything. It will however help you to integrate OneUptime with external monitoring tools and utilities.",
|
|
65
|
+
icon: IconProp.EmptyCircle,
|
|
61
66
|
},
|
|
62
67
|
{
|
|
63
68
|
monitorType: MonitorType.Website,
|
|
64
69
|
title: "Website",
|
|
65
70
|
description:
|
|
66
71
|
"This monitor type lets you monitor landing pages like home page of your company / blog or more.",
|
|
72
|
+
icon: IconProp.Globe,
|
|
67
73
|
},
|
|
68
74
|
{
|
|
69
75
|
monitorType: MonitorType.Ping,
|
|
70
76
|
title: "Ping",
|
|
71
77
|
description:
|
|
72
78
|
"This monitor type does the basic ping test of an endpoint.",
|
|
79
|
+
icon: IconProp.Signal,
|
|
73
80
|
},
|
|
74
81
|
/*
|
|
75
82
|
* {
|
|
@@ -77,6 +84,7 @@ export class MonitorTypeHelper {
|
|
|
77
84
|
* title: 'Kubernetes',
|
|
78
85
|
* description:
|
|
79
86
|
* 'This monitor types lets you monitor Kubernetes clusters.',
|
|
87
|
+
* icon: IconProp.Cube,
|
|
80
88
|
* },
|
|
81
89
|
*/
|
|
82
90
|
{
|
|
@@ -84,64 +92,82 @@ export class MonitorTypeHelper {
|
|
|
84
92
|
title: "IP",
|
|
85
93
|
description:
|
|
86
94
|
"This monitor type lets you monitor any IPv4 or IPv6 addresses.",
|
|
95
|
+
icon: IconProp.AltGlobe,
|
|
87
96
|
},
|
|
88
97
|
{
|
|
89
98
|
monitorType: MonitorType.IncomingRequest,
|
|
90
99
|
title: "Incoming Request",
|
|
91
100
|
description:
|
|
92
101
|
"This monitor type lets you ping OneUptime from any external device or service with a custom payload.",
|
|
102
|
+
icon: IconProp.Webhook,
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
monitorType: MonitorType.IncomingEmail,
|
|
106
|
+
title: "Incoming Email",
|
|
107
|
+
description:
|
|
108
|
+
"This monitor type triggers alerts when emails are received at a unique email address with matching criteria.",
|
|
109
|
+
icon: IconProp.Email,
|
|
93
110
|
},
|
|
94
111
|
{
|
|
95
112
|
monitorType: MonitorType.Port,
|
|
96
113
|
title: "Port",
|
|
97
114
|
description: "This monitor type lets you monitor any TCP or UDP port.",
|
|
115
|
+
icon: IconProp.Terminal,
|
|
98
116
|
},
|
|
99
117
|
{
|
|
100
118
|
monitorType: MonitorType.Server,
|
|
101
119
|
title: "Server / VM",
|
|
102
120
|
description:
|
|
103
121
|
"This monitor type lets you monitor any server, VM, or any machine.",
|
|
122
|
+
icon: IconProp.Cube,
|
|
104
123
|
},
|
|
105
124
|
{
|
|
106
125
|
monitorType: MonitorType.SSLCertificate,
|
|
107
126
|
title: "SSL Certificate",
|
|
108
127
|
description:
|
|
109
128
|
"This monitor type lets you monitor SSL certificates of any domain.",
|
|
129
|
+
icon: IconProp.ShieldCheck,
|
|
110
130
|
},
|
|
111
131
|
{
|
|
112
132
|
monitorType: MonitorType.SyntheticMonitor,
|
|
113
133
|
title: "Synthetic Monitor",
|
|
114
134
|
description:
|
|
115
135
|
"This monitor type lets you monitor your web application UI.",
|
|
136
|
+
icon: IconProp.Window,
|
|
116
137
|
},
|
|
117
138
|
{
|
|
118
139
|
monitorType: MonitorType.CustomJavaScriptCode,
|
|
119
140
|
title: "Custom JavaScript Code",
|
|
120
141
|
description:
|
|
121
142
|
"This monitor type lets you run custom JavaScript code on a schedule.",
|
|
143
|
+
icon: IconProp.Code,
|
|
122
144
|
},
|
|
123
145
|
{
|
|
124
146
|
monitorType: MonitorType.Logs,
|
|
125
147
|
title: "Logs",
|
|
126
148
|
description: "This monitor type lets you monitor logs from any source.",
|
|
149
|
+
icon: IconProp.Logs,
|
|
127
150
|
},
|
|
128
151
|
{
|
|
129
152
|
monitorType: MonitorType.Exceptions,
|
|
130
153
|
title: "Exceptions",
|
|
131
154
|
description:
|
|
132
155
|
"This monitor type lets you monitor exceptions and error groups from any source.",
|
|
156
|
+
icon: IconProp.Bug,
|
|
133
157
|
},
|
|
134
158
|
{
|
|
135
159
|
monitorType: MonitorType.Traces,
|
|
136
160
|
title: "Traces",
|
|
137
161
|
description:
|
|
138
162
|
"This monitor type lets you monitor traces from any source.",
|
|
163
|
+
icon: IconProp.Waterfall,
|
|
139
164
|
},
|
|
140
165
|
{
|
|
141
166
|
monitorType: MonitorType.Metrics,
|
|
142
167
|
title: "Metrics",
|
|
143
168
|
description:
|
|
144
169
|
"This monitor type lets you monitor metrics from any source.",
|
|
170
|
+
icon: IconProp.Heartbeat,
|
|
145
171
|
},
|
|
146
172
|
];
|
|
147
173
|
|
|
@@ -202,6 +228,7 @@ export class MonitorTypeHelper {
|
|
|
202
228
|
MonitorType.SyntheticMonitor,
|
|
203
229
|
MonitorType.CustomJavaScriptCode,
|
|
204
230
|
MonitorType.IncomingRequest,
|
|
231
|
+
MonitorType.IncomingEmail,
|
|
205
232
|
MonitorType.Server,
|
|
206
233
|
MonitorType.Logs,
|
|
207
234
|
MonitorType.Metrics,
|
|
@@ -215,6 +242,7 @@ export class MonitorTypeHelper {
|
|
|
215
242
|
): boolean {
|
|
216
243
|
return (
|
|
217
244
|
monitorType === MonitorType.IncomingRequest ||
|
|
245
|
+
monitorType === MonitorType.IncomingEmail ||
|
|
218
246
|
monitorType === MonitorType.Server
|
|
219
247
|
);
|
|
220
248
|
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import IconProp from "../../../Types/Icon/IconProp";
|
|
2
|
+
import Icon, { SizeProp } from "../Icon/Icon";
|
|
3
|
+
import React, { FunctionComponent, ReactElement } from "react";
|
|
4
|
+
|
|
5
|
+
export interface CardSelectOption {
|
|
6
|
+
value: string;
|
|
7
|
+
title: string;
|
|
8
|
+
description: string;
|
|
9
|
+
icon: IconProp;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ComponentProps {
|
|
13
|
+
options: Array<CardSelectOption>;
|
|
14
|
+
value?: string | undefined;
|
|
15
|
+
onChange: (value: string) => void;
|
|
16
|
+
error?: string | undefined;
|
|
17
|
+
tabIndex?: number | undefined;
|
|
18
|
+
dataTestId?: string | undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const CardSelect: FunctionComponent<ComponentProps> = (
|
|
22
|
+
props: ComponentProps,
|
|
23
|
+
): ReactElement => {
|
|
24
|
+
return (
|
|
25
|
+
<div data-testid={props.dataTestId}>
|
|
26
|
+
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
27
|
+
{props.options.map((option: CardSelectOption, index: number) => {
|
|
28
|
+
const isSelected: boolean = props.value === option.value;
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div
|
|
32
|
+
key={index}
|
|
33
|
+
tabIndex={props.tabIndex ? props.tabIndex + index : index}
|
|
34
|
+
onClick={() => {
|
|
35
|
+
props.onChange(option.value);
|
|
36
|
+
}}
|
|
37
|
+
onKeyDown={(e: React.KeyboardEvent) => {
|
|
38
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
39
|
+
e.preventDefault();
|
|
40
|
+
props.onChange(option.value);
|
|
41
|
+
}
|
|
42
|
+
}}
|
|
43
|
+
className={`relative flex cursor-pointer rounded-lg border p-4 shadow-sm focus:outline-none transition-all duration-200 hover:border-indigo-400 hover:shadow-md ${
|
|
44
|
+
isSelected
|
|
45
|
+
? "border-indigo-500 bg-indigo-50/50"
|
|
46
|
+
: "border-gray-200 bg-white"
|
|
47
|
+
}`}
|
|
48
|
+
role="radio"
|
|
49
|
+
aria-checked={isSelected}
|
|
50
|
+
data-testid={`card-select-option-${option.value}`}
|
|
51
|
+
>
|
|
52
|
+
<div className="flex w-full items-start">
|
|
53
|
+
<div
|
|
54
|
+
className={`flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg ${
|
|
55
|
+
isSelected ? "bg-indigo-100" : "bg-gray-100"
|
|
56
|
+
}`}
|
|
57
|
+
>
|
|
58
|
+
<Icon
|
|
59
|
+
icon={option.icon}
|
|
60
|
+
size={SizeProp.Large}
|
|
61
|
+
className={`h-5 w-5 ${
|
|
62
|
+
isSelected ? "text-indigo-600" : "text-gray-600"
|
|
63
|
+
}`}
|
|
64
|
+
/>
|
|
65
|
+
</div>
|
|
66
|
+
<div className="ml-4 flex-1">
|
|
67
|
+
<span
|
|
68
|
+
className={`block text-sm font-semibold ${
|
|
69
|
+
isSelected ? "text-gray-900" : "text-gray-900"
|
|
70
|
+
}`}
|
|
71
|
+
>
|
|
72
|
+
{option.title}
|
|
73
|
+
</span>
|
|
74
|
+
<span
|
|
75
|
+
className={`mt-1 block text-sm ${
|
|
76
|
+
isSelected ? "text-gray-600" : "text-gray-500"
|
|
77
|
+
}`}
|
|
78
|
+
>
|
|
79
|
+
{option.description}
|
|
80
|
+
</span>
|
|
81
|
+
</div>
|
|
82
|
+
{isSelected && (
|
|
83
|
+
<div className="flex-shrink-0 ml-2">
|
|
84
|
+
<Icon
|
|
85
|
+
icon={IconProp.CheckCircle}
|
|
86
|
+
size={SizeProp.Large}
|
|
87
|
+
className="h-5 w-5 text-indigo-500"
|
|
88
|
+
/>
|
|
89
|
+
</div>
|
|
90
|
+
)}
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
);
|
|
94
|
+
})}
|
|
95
|
+
</div>
|
|
96
|
+
{props.error && (
|
|
97
|
+
<p className="mt-2 text-sm text-red-600" role="alert">
|
|
98
|
+
{props.error}
|
|
99
|
+
</p>
|
|
100
|
+
)}
|
|
101
|
+
</div>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export default CardSelect;
|