@oneuptime/common 10.0.19 → 10.0.21
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/Server/API/GitHubAPI.ts +104 -12
- package/Server/API/TelemetryAPI.ts +208 -0
- package/Server/API/UserCallAPI.ts +29 -0
- package/Server/API/UserEmailAPI.ts +29 -0
- package/Server/API/UserSmsAPI.ts +29 -0
- package/Server/API/UserWhatsAppAPI.ts +29 -0
- package/Server/Services/LogAggregationService.ts +251 -0
- package/Server/Utils/VM/VMRunner.ts +45 -0
- package/Types/Log/LogQueryParser.ts +252 -0
- package/Types/Log/LogQueryToFilter.ts +131 -0
- package/UI/Components/CopyTextButton/CopyTextButton.tsx +3 -3
- package/UI/Components/LogsViewer/LogsViewer.tsx +166 -93
- package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +58 -0
- package/UI/Components/LogsViewer/components/FacetSection.tsx +119 -0
- package/UI/Components/LogsViewer/components/FacetValueRow.tsx +102 -0
- package/UI/Components/LogsViewer/components/HistogramTooltip.tsx +122 -0
- package/UI/Components/LogsViewer/components/LiveLogsToggle.tsx +4 -4
- package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +22 -26
- package/UI/Components/LogsViewer/components/LogSearchBar.tsx +360 -0
- package/UI/Components/LogsViewer/components/LogSearchHelp.tsx +128 -0
- package/UI/Components/LogsViewer/components/LogSearchSuggestions.tsx +64 -0
- package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +199 -0
- package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +172 -0
- package/UI/Components/LogsViewer/components/LogsFilterCard.tsx +27 -57
- package/UI/Components/LogsViewer/components/LogsHistogram.tsx +268 -0
- package/UI/Components/LogsViewer/components/LogsPagination.tsx +12 -10
- package/UI/Components/LogsViewer/components/LogsTable.tsx +33 -32
- package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +16 -18
- package/UI/Components/LogsViewer/components/severityColors.ts +31 -0
- package/UI/Components/LogsViewer/components/severityTheme.ts +25 -25
- package/UI/Components/LogsViewer/types.ts +20 -0
- package/build/dist/Server/API/GitHubAPI.js +40 -9
- package/build/dist/Server/API/GitHubAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +136 -0
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/API/UserCallAPI.js +17 -0
- package/build/dist/Server/API/UserCallAPI.js.map +1 -1
- package/build/dist/Server/API/UserEmailAPI.js +17 -0
- package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
- package/build/dist/Server/API/UserSmsAPI.js +17 -0
- package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
- package/build/dist/Server/API/UserWhatsAppAPI.js +17 -0
- package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +163 -0
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -0
- package/build/dist/Server/Utils/VM/VMRunner.js +31 -0
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Types/Log/LogQueryParser.js +200 -0
- package/build/dist/Types/Log/LogQueryParser.js.map +1 -0
- package/build/dist/Types/Log/LogQueryToFilter.js +96 -0
- package/build/dist/Types/Log/LogQueryToFilter.js.map +1 -0
- package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js +3 -3
- package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +64 -42
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +24 -0
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/components/FacetSection.js +46 -0
- package/build/dist/UI/Components/LogsViewer/components/FacetSection.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js +35 -0
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/components/HistogramTooltip.js +64 -0
- package/build/dist/UI/Components/LogsViewer/components/HistogramTooltip.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/components/LiveLogsToggle.js +4 -4
- package/build/dist/UI/Components/LogsViewer/components/LiveLogsToggle.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +19 -21
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogSearchBar.js +230 -0
- package/build/dist/UI/Components/LogsViewer/components/LogSearchBar.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/components/LogSearchHelp.js +84 -0
- package/build/dist/UI/Components/LogsViewer/components/LogSearchHelp.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/components/LogSearchSuggestions.js +27 -0
- package/build/dist/UI/Components/LogsViewer/components/LogSearchSuggestions.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +100 -0
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +104 -0
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/components/LogsFilterCard.js +14 -35
- package/build/dist/UI/Components/LogsViewer/components/LogsFilterCard.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +127 -0
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/components/LogsPagination.js +9 -9
- package/build/dist/UI/Components/LogsViewer/components/LogsPagination.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js +31 -30
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +7 -8
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/severityColors.js +22 -0
- package/build/dist/UI/Components/LogsViewer/components/severityColors.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/components/severityTheme.js +25 -25
- package/build/dist/UI/Components/LogsViewer/components/severityTheme.js.map +1 -1
- package/package.json +1 -1
package/Server/API/GitHubAPI.ts
CHANGED
|
@@ -2,12 +2,19 @@ import Express, {
|
|
|
2
2
|
ExpressRequest,
|
|
3
3
|
ExpressResponse,
|
|
4
4
|
ExpressRouter,
|
|
5
|
+
OneUptimeRequest,
|
|
5
6
|
} from "../Utils/Express";
|
|
6
7
|
import Response from "../Utils/Response";
|
|
7
8
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
9
|
+
import NotAuthenticatedException from "../../Types/Exception/NotAuthenticatedException";
|
|
10
|
+
import NotAuthorizedException from "../../Types/Exception/NotAuthorizedException";
|
|
8
11
|
import logger from "../Utils/Logger";
|
|
9
12
|
import { JSONObject } from "../../Types/JSON";
|
|
10
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
DashboardClientUrl,
|
|
15
|
+
GitHubAppName,
|
|
16
|
+
HomeClientUrl,
|
|
17
|
+
} from "../EnvironmentConfig";
|
|
11
18
|
import ObjectID from "../../Types/ObjectID";
|
|
12
19
|
import GitHubUtil, {
|
|
13
20
|
GitHubRepository,
|
|
@@ -15,11 +22,14 @@ import GitHubUtil, {
|
|
|
15
22
|
} from "../Utils/CodeRepository/GitHub/GitHub";
|
|
16
23
|
import CodeRepositoryService from "../Services/CodeRepositoryService";
|
|
17
24
|
import ProjectService from "../Services/ProjectService";
|
|
25
|
+
import AccessTokenService from "../Services/AccessTokenService";
|
|
18
26
|
import CodeRepository from "../../Models/DatabaseModels/CodeRepository";
|
|
19
27
|
import CodeRepositoryType from "../../Types/CodeRepository/CodeRepositoryType";
|
|
20
28
|
import URL from "../../Types/API/URL";
|
|
21
29
|
import UserMiddleware from "../Middleware/UserAuthorization";
|
|
30
|
+
import JSONWebToken from "../Utils/JsonWebToken";
|
|
22
31
|
import BaseModel from "../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
32
|
+
import { UserTenantAccessPermission } from "../../Types/Permission";
|
|
23
33
|
|
|
24
34
|
export default class GitHubAPI {
|
|
25
35
|
public getRouter(): ExpressRouter {
|
|
@@ -45,20 +55,22 @@ export default class GitHubAPI {
|
|
|
45
55
|
);
|
|
46
56
|
}
|
|
47
57
|
|
|
48
|
-
//
|
|
58
|
+
// Verify and decode the signed state token
|
|
49
59
|
let projectId: string | undefined;
|
|
50
60
|
let userId: string | undefined;
|
|
51
61
|
|
|
52
62
|
try {
|
|
53
|
-
const decodedState:
|
|
54
|
-
|
|
55
|
-
projectId = decodedState
|
|
56
|
-
userId = decodedState
|
|
63
|
+
const decodedState: JSONObject =
|
|
64
|
+
JSONWebToken.decodeJsonPayload(state);
|
|
65
|
+
projectId = decodedState["projectId"] as string | undefined;
|
|
66
|
+
userId = decodedState["userId"] as string | undefined;
|
|
57
67
|
} catch {
|
|
58
68
|
return Response.sendErrorResponse(
|
|
59
69
|
req,
|
|
60
70
|
res,
|
|
61
|
-
new BadDataException(
|
|
71
|
+
new BadDataException(
|
|
72
|
+
"Invalid or expired state parameter. Please restart the GitHub App installation.",
|
|
73
|
+
),
|
|
62
74
|
);
|
|
63
75
|
}
|
|
64
76
|
|
|
@@ -78,6 +90,23 @@ export default class GitHubAPI {
|
|
|
78
90
|
);
|
|
79
91
|
}
|
|
80
92
|
|
|
93
|
+
// Verify the user is a member of this project
|
|
94
|
+
const userTenantAccessPermission: UserTenantAccessPermission | null =
|
|
95
|
+
await AccessTokenService.getUserTenantAccessPermission(
|
|
96
|
+
new ObjectID(userId),
|
|
97
|
+
new ObjectID(projectId),
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
if (!userTenantAccessPermission) {
|
|
101
|
+
return Response.sendErrorResponse(
|
|
102
|
+
req,
|
|
103
|
+
res,
|
|
104
|
+
new NotAuthorizedException(
|
|
105
|
+
"You do not have access to this project.",
|
|
106
|
+
),
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
81
110
|
// GitHub sends installation_id in query params after app installation
|
|
82
111
|
const installationId: string | undefined =
|
|
83
112
|
req.query["installation_id"]?.toString();
|
|
@@ -153,13 +182,16 @@ export default class GitHubAPI {
|
|
|
153
182
|
|
|
154
183
|
/*
|
|
155
184
|
* Redirect to GitHub App installation page
|
|
156
|
-
* The state parameter
|
|
185
|
+
* The state parameter is a signed JWT to prevent tampering
|
|
186
|
+
* It expires in 1 hour to limit the window for replay attacks
|
|
157
187
|
*/
|
|
158
|
-
const state: string =
|
|
159
|
-
|
|
160
|
-
|
|
188
|
+
const state: string = JSONWebToken.signJsonPayload(
|
|
189
|
+
{ projectId, userId },
|
|
190
|
+
3600, // 1 hour expiry
|
|
191
|
+
);
|
|
161
192
|
|
|
162
|
-
const
|
|
193
|
+
const callbackUrl: string = `${HomeClientUrl.toString()}api/github/auth/callback`;
|
|
194
|
+
const installUrl: string = `https://github.com/apps/${GitHubAppName}/installations/new?state=${encodeURIComponent(state)}&redirect_uri=${encodeURIComponent(callbackUrl)}`;
|
|
163
195
|
|
|
164
196
|
return Response.redirect(req, res, URL.fromString(installUrl));
|
|
165
197
|
} catch (error) {
|
|
@@ -182,6 +214,19 @@ export default class GitHubAPI {
|
|
|
182
214
|
UserMiddleware.getUserMiddleware,
|
|
183
215
|
async (req: ExpressRequest, res: ExpressResponse) => {
|
|
184
216
|
try {
|
|
217
|
+
const oneuptimeRequest: OneUptimeRequest = req as OneUptimeRequest;
|
|
218
|
+
|
|
219
|
+
// Require authentication
|
|
220
|
+
if (!oneuptimeRequest.userAuthorization) {
|
|
221
|
+
return Response.sendErrorResponse(
|
|
222
|
+
req,
|
|
223
|
+
res,
|
|
224
|
+
new NotAuthenticatedException(
|
|
225
|
+
"Authentication is required to list repositories.",
|
|
226
|
+
),
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
185
230
|
const projectId: string | undefined =
|
|
186
231
|
req.params["projectId"]?.toString();
|
|
187
232
|
const installationId: string | undefined =
|
|
@@ -203,6 +248,23 @@ export default class GitHubAPI {
|
|
|
203
248
|
);
|
|
204
249
|
}
|
|
205
250
|
|
|
251
|
+
// Verify user has access to this project
|
|
252
|
+
const userTenantAccessPermission: UserTenantAccessPermission | null =
|
|
253
|
+
await AccessTokenService.getUserTenantAccessPermission(
|
|
254
|
+
oneuptimeRequest.userAuthorization.userId,
|
|
255
|
+
new ObjectID(projectId),
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
if (!userTenantAccessPermission) {
|
|
259
|
+
return Response.sendErrorResponse(
|
|
260
|
+
req,
|
|
261
|
+
res,
|
|
262
|
+
new NotAuthorizedException(
|
|
263
|
+
"You do not have access to this project.",
|
|
264
|
+
),
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
206
268
|
const repositories: Array<GitHubRepository> =
|
|
207
269
|
await GitHubUtil.listRepositoriesForInstallation(installationId);
|
|
208
270
|
|
|
@@ -263,6 +325,19 @@ export default class GitHubAPI {
|
|
|
263
325
|
UserMiddleware.getUserMiddleware,
|
|
264
326
|
async (req: ExpressRequest, res: ExpressResponse) => {
|
|
265
327
|
try {
|
|
328
|
+
const oneuptimeRequest: OneUptimeRequest = req as OneUptimeRequest;
|
|
329
|
+
|
|
330
|
+
// Require authentication
|
|
331
|
+
if (!oneuptimeRequest.userAuthorization) {
|
|
332
|
+
return Response.sendErrorResponse(
|
|
333
|
+
req,
|
|
334
|
+
res,
|
|
335
|
+
new NotAuthenticatedException(
|
|
336
|
+
"Authentication is required to connect a repository.",
|
|
337
|
+
),
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
|
|
266
341
|
const body: JSONObject = req.body;
|
|
267
342
|
|
|
268
343
|
const projectId: string | undefined = body["projectId"]?.toString();
|
|
@@ -296,6 +371,23 @@ export default class GitHubAPI {
|
|
|
296
371
|
);
|
|
297
372
|
}
|
|
298
373
|
|
|
374
|
+
// Verify user has access to this project
|
|
375
|
+
const userTenantAccessPermission: UserTenantAccessPermission | null =
|
|
376
|
+
await AccessTokenService.getUserTenantAccessPermission(
|
|
377
|
+
oneuptimeRequest.userAuthorization.userId,
|
|
378
|
+
new ObjectID(projectId),
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
if (!userTenantAccessPermission) {
|
|
382
|
+
return Response.sendErrorResponse(
|
|
383
|
+
req,
|
|
384
|
+
res,
|
|
385
|
+
new NotAuthorizedException(
|
|
386
|
+
"You do not have access to this project.",
|
|
387
|
+
),
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
299
391
|
if (!repositoryName) {
|
|
300
392
|
return Response.sendErrorResponse(
|
|
301
393
|
req,
|
|
@@ -11,6 +11,15 @@ import CommonAPI from "./CommonAPI";
|
|
|
11
11
|
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
12
12
|
import TelemetryType from "../../Types/Telemetry/TelemetryType";
|
|
13
13
|
import TelemetryAttributeService from "../Services/TelemetryAttributeService";
|
|
14
|
+
import LogAggregationService, {
|
|
15
|
+
HistogramBucket,
|
|
16
|
+
HistogramRequest,
|
|
17
|
+
FacetValue,
|
|
18
|
+
FacetRequest,
|
|
19
|
+
} from "../Services/LogAggregationService";
|
|
20
|
+
import ObjectID from "../../Types/ObjectID";
|
|
21
|
+
import OneUptimeDate from "../../Types/Date";
|
|
22
|
+
import { JSONObject } from "../../Types/JSON";
|
|
14
23
|
|
|
15
24
|
const router: ExpressRouter = Express.getRouter();
|
|
16
25
|
|
|
@@ -85,4 +94,203 @@ const getAttributes: GetAttributesFunction = async (
|
|
|
85
94
|
}
|
|
86
95
|
};
|
|
87
96
|
|
|
97
|
+
// --- Log Histogram Endpoint ---
|
|
98
|
+
|
|
99
|
+
router.post(
|
|
100
|
+
"/telemetry/logs/histogram",
|
|
101
|
+
UserMiddleware.getUserMiddleware,
|
|
102
|
+
async (
|
|
103
|
+
req: ExpressRequest,
|
|
104
|
+
res: ExpressResponse,
|
|
105
|
+
next: NextFunction,
|
|
106
|
+
): Promise<void> => {
|
|
107
|
+
try {
|
|
108
|
+
const databaseProps: DatabaseCommonInteractionProps =
|
|
109
|
+
await CommonAPI.getDatabaseCommonInteractionProps(req);
|
|
110
|
+
|
|
111
|
+
if (!databaseProps?.tenantId) {
|
|
112
|
+
return Response.sendErrorResponse(
|
|
113
|
+
req,
|
|
114
|
+
res,
|
|
115
|
+
new BadDataException("Invalid Project ID"),
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const body: JSONObject = req.body as JSONObject;
|
|
120
|
+
|
|
121
|
+
const startTime: Date = body["startTime"]
|
|
122
|
+
? OneUptimeDate.fromString(body["startTime"] as string)
|
|
123
|
+
: OneUptimeDate.addRemoveHours(OneUptimeDate.getCurrentDate(), -1);
|
|
124
|
+
|
|
125
|
+
const endTime: Date = body["endTime"]
|
|
126
|
+
? OneUptimeDate.fromString(body["endTime"] as string)
|
|
127
|
+
: OneUptimeDate.getCurrentDate();
|
|
128
|
+
|
|
129
|
+
const bucketSizeInMinutes: number =
|
|
130
|
+
(body["bucketSizeInMinutes"] as number) ||
|
|
131
|
+
computeDefaultBucketSize(startTime, endTime);
|
|
132
|
+
|
|
133
|
+
const serviceIds: Array<ObjectID> | undefined = body["serviceIds"]
|
|
134
|
+
? (body["serviceIds"] as Array<string>).map((id: string) => {
|
|
135
|
+
return new ObjectID(id);
|
|
136
|
+
})
|
|
137
|
+
: undefined;
|
|
138
|
+
|
|
139
|
+
const severityTexts: Array<string> | undefined = body["severityTexts"]
|
|
140
|
+
? (body["severityTexts"] as Array<string>)
|
|
141
|
+
: undefined;
|
|
142
|
+
|
|
143
|
+
const bodySearchText: string | undefined = body["bodySearchText"]
|
|
144
|
+
? (body["bodySearchText"] as string)
|
|
145
|
+
: undefined;
|
|
146
|
+
|
|
147
|
+
const traceIds: Array<string> | undefined = body["traceIds"]
|
|
148
|
+
? (body["traceIds"] as Array<string>)
|
|
149
|
+
: undefined;
|
|
150
|
+
|
|
151
|
+
const spanIds: Array<string> | undefined = body["spanIds"]
|
|
152
|
+
? (body["spanIds"] as Array<string>)
|
|
153
|
+
: undefined;
|
|
154
|
+
|
|
155
|
+
const request: HistogramRequest = {
|
|
156
|
+
projectId: databaseProps.tenantId,
|
|
157
|
+
startTime,
|
|
158
|
+
endTime,
|
|
159
|
+
bucketSizeInMinutes,
|
|
160
|
+
serviceIds,
|
|
161
|
+
severityTexts,
|
|
162
|
+
bodySearchText,
|
|
163
|
+
traceIds,
|
|
164
|
+
spanIds,
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const buckets: Array<HistogramBucket> =
|
|
168
|
+
await LogAggregationService.getHistogram(request);
|
|
169
|
+
|
|
170
|
+
return Response.sendJsonObjectResponse(req, res, {
|
|
171
|
+
buckets: buckets as unknown as JSONObject,
|
|
172
|
+
});
|
|
173
|
+
} catch (err: unknown) {
|
|
174
|
+
next(err);
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
// --- Log Facets Endpoint ---
|
|
180
|
+
|
|
181
|
+
router.post(
|
|
182
|
+
"/telemetry/logs/facets",
|
|
183
|
+
UserMiddleware.getUserMiddleware,
|
|
184
|
+
async (
|
|
185
|
+
req: ExpressRequest,
|
|
186
|
+
res: ExpressResponse,
|
|
187
|
+
next: NextFunction,
|
|
188
|
+
): Promise<void> => {
|
|
189
|
+
try {
|
|
190
|
+
const databaseProps: DatabaseCommonInteractionProps =
|
|
191
|
+
await CommonAPI.getDatabaseCommonInteractionProps(req);
|
|
192
|
+
|
|
193
|
+
if (!databaseProps?.tenantId) {
|
|
194
|
+
return Response.sendErrorResponse(
|
|
195
|
+
req,
|
|
196
|
+
res,
|
|
197
|
+
new BadDataException("Invalid Project ID"),
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const body: JSONObject = req.body as JSONObject;
|
|
202
|
+
|
|
203
|
+
const facetKeys: Array<string> = body["facetKeys"]
|
|
204
|
+
? (body["facetKeys"] as Array<string>)
|
|
205
|
+
: ["severityText", "serviceId"];
|
|
206
|
+
|
|
207
|
+
const startTime: Date = body["startTime"]
|
|
208
|
+
? OneUptimeDate.fromString(body["startTime"] as string)
|
|
209
|
+
: OneUptimeDate.addRemoveHours(OneUptimeDate.getCurrentDate(), -1);
|
|
210
|
+
|
|
211
|
+
const endTime: Date = body["endTime"]
|
|
212
|
+
? OneUptimeDate.fromString(body["endTime"] as string)
|
|
213
|
+
: OneUptimeDate.getCurrentDate();
|
|
214
|
+
|
|
215
|
+
const limit: number = (body["limit"] as number) || 10;
|
|
216
|
+
|
|
217
|
+
const serviceIds: Array<ObjectID> | undefined = body["serviceIds"]
|
|
218
|
+
? (body["serviceIds"] as Array<string>).map((id: string) => {
|
|
219
|
+
return new ObjectID(id);
|
|
220
|
+
})
|
|
221
|
+
: undefined;
|
|
222
|
+
|
|
223
|
+
const severityTexts: Array<string> | undefined = body["severityTexts"]
|
|
224
|
+
? (body["severityTexts"] as Array<string>)
|
|
225
|
+
: undefined;
|
|
226
|
+
|
|
227
|
+
const bodySearchText: string | undefined = body["bodySearchText"]
|
|
228
|
+
? (body["bodySearchText"] as string)
|
|
229
|
+
: undefined;
|
|
230
|
+
|
|
231
|
+
const traceIds: Array<string> | undefined = body["traceIds"]
|
|
232
|
+
? (body["traceIds"] as Array<string>)
|
|
233
|
+
: undefined;
|
|
234
|
+
|
|
235
|
+
const spanIds: Array<string> | undefined = body["spanIds"]
|
|
236
|
+
? (body["spanIds"] as Array<string>)
|
|
237
|
+
: undefined;
|
|
238
|
+
|
|
239
|
+
const facets: Record<string, Array<FacetValue>> = {};
|
|
240
|
+
|
|
241
|
+
for (const facetKey of facetKeys) {
|
|
242
|
+
const request: FacetRequest = {
|
|
243
|
+
projectId: databaseProps.tenantId,
|
|
244
|
+
startTime,
|
|
245
|
+
endTime,
|
|
246
|
+
facetKey,
|
|
247
|
+
limit,
|
|
248
|
+
serviceIds,
|
|
249
|
+
severityTexts,
|
|
250
|
+
bodySearchText,
|
|
251
|
+
traceIds,
|
|
252
|
+
spanIds,
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
facets[facetKey] = await LogAggregationService.getFacetValues(request);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return Response.sendJsonObjectResponse(req, res, {
|
|
259
|
+
facets: facets as unknown as JSONObject,
|
|
260
|
+
});
|
|
261
|
+
} catch (err: unknown) {
|
|
262
|
+
next(err);
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
// --- Helpers ---
|
|
268
|
+
|
|
269
|
+
function computeDefaultBucketSize(startTime: Date, endTime: Date): number {
|
|
270
|
+
const diffMs: number = endTime.getTime() - startTime.getTime();
|
|
271
|
+
const diffMinutes: number = diffMs / (1000 * 60);
|
|
272
|
+
|
|
273
|
+
if (diffMinutes <= 60) {
|
|
274
|
+
return 1;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (diffMinutes <= 360) {
|
|
278
|
+
return 5;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (diffMinutes <= 1440) {
|
|
282
|
+
return 15;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (diffMinutes <= 10080) {
|
|
286
|
+
return 60;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (diffMinutes <= 43200) {
|
|
290
|
+
return 360;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return 1440;
|
|
294
|
+
}
|
|
295
|
+
|
|
88
296
|
export default router;
|
|
@@ -136,6 +136,35 @@ export default class UserCallAPI extends BaseAPI<
|
|
|
136
136
|
);
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
const item: UserCall | null = await this.service.findOneById({
|
|
140
|
+
id: req.body["itemId"],
|
|
141
|
+
props: {
|
|
142
|
+
isRoot: true,
|
|
143
|
+
},
|
|
144
|
+
select: {
|
|
145
|
+
userId: true,
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
if (!item) {
|
|
150
|
+
return Response.sendErrorResponse(
|
|
151
|
+
req,
|
|
152
|
+
res,
|
|
153
|
+
new BadDataException("Item not found"),
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (
|
|
158
|
+
item.userId?.toString() !==
|
|
159
|
+
(req as OneUptimeRequest)?.userAuthorization?.userId?.toString()
|
|
160
|
+
) {
|
|
161
|
+
return Response.sendErrorResponse(
|
|
162
|
+
req,
|
|
163
|
+
res,
|
|
164
|
+
new BadDataException("Invalid user ID"),
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
139
168
|
await this.service.resendVerificationCode(req.body.itemId);
|
|
140
169
|
|
|
141
170
|
return Response.sendEmptySuccessResponse(req, res);
|
|
@@ -137,6 +137,35 @@ export default class UserEmailAPI extends BaseAPI<
|
|
|
137
137
|
);
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
+
const item: UserEmail | null = await this.service.findOneById({
|
|
141
|
+
id: req.body["itemId"],
|
|
142
|
+
props: {
|
|
143
|
+
isRoot: true,
|
|
144
|
+
},
|
|
145
|
+
select: {
|
|
146
|
+
userId: true,
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
if (!item) {
|
|
151
|
+
return Response.sendErrorResponse(
|
|
152
|
+
req,
|
|
153
|
+
res,
|
|
154
|
+
new BadDataException("Item not found"),
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (
|
|
159
|
+
item.userId?.toString() !==
|
|
160
|
+
(req as OneUptimeRequest)?.userAuthorization?.userId?.toString()
|
|
161
|
+
) {
|
|
162
|
+
return Response.sendErrorResponse(
|
|
163
|
+
req,
|
|
164
|
+
res,
|
|
165
|
+
new BadDataException("Invalid user ID"),
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
140
169
|
await this.service.resendVerificationCode(req.body.itemId);
|
|
141
170
|
|
|
142
171
|
return Response.sendEmptySuccessResponse(req, res);
|
package/Server/API/UserSmsAPI.ts
CHANGED
|
@@ -132,6 +132,35 @@ export default class UserSMSAPI extends BaseAPI<UserSMS, UserSMSServiceType> {
|
|
|
132
132
|
);
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
const item: UserSMS | null = await this.service.findOneById({
|
|
136
|
+
id: req.body["itemId"],
|
|
137
|
+
props: {
|
|
138
|
+
isRoot: true,
|
|
139
|
+
},
|
|
140
|
+
select: {
|
|
141
|
+
userId: true,
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
if (!item) {
|
|
146
|
+
return Response.sendErrorResponse(
|
|
147
|
+
req,
|
|
148
|
+
res,
|
|
149
|
+
new BadDataException("Item not found"),
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (
|
|
154
|
+
item.userId?.toString() !==
|
|
155
|
+
(req as OneUptimeRequest)?.userAuthorization?.userId?.toString()
|
|
156
|
+
) {
|
|
157
|
+
return Response.sendErrorResponse(
|
|
158
|
+
req,
|
|
159
|
+
res,
|
|
160
|
+
new BadDataException("Invalid user ID"),
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
135
164
|
await this.service.resendVerificationCode(req.body.itemId);
|
|
136
165
|
|
|
137
166
|
return Response.sendEmptySuccessResponse(req, res);
|
|
@@ -143,6 +143,35 @@ export default class UserWhatsAppAPI extends BaseAPI<
|
|
|
143
143
|
);
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
const item: UserWhatsApp | null = await this.service.findOneById({
|
|
147
|
+
id: req.body["itemId"],
|
|
148
|
+
props: {
|
|
149
|
+
isRoot: true,
|
|
150
|
+
},
|
|
151
|
+
select: {
|
|
152
|
+
userId: true,
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
if (!item) {
|
|
157
|
+
return Response.sendErrorResponse(
|
|
158
|
+
req,
|
|
159
|
+
res,
|
|
160
|
+
new BadDataException("Item not found"),
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (
|
|
165
|
+
item.userId?.toString() !==
|
|
166
|
+
(req as OneUptimeRequest)?.userAuthorization?.userId?.toString()
|
|
167
|
+
) {
|
|
168
|
+
return Response.sendErrorResponse(
|
|
169
|
+
req,
|
|
170
|
+
res,
|
|
171
|
+
new BadDataException("Invalid user ID"),
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
146
175
|
await this.service.resendVerificationCode(req.body.itemId);
|
|
147
176
|
|
|
148
177
|
return Response.sendEmptySuccessResponse(req, res);
|