@oneuptime/common 7.0.3887 → 7.0.3903
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/WorkspaceNotificationRuleAPI.ts +48 -0
- package/Server/Services/IncidentService.ts +3 -1
- package/Server/Services/WorkspaceNotificationRuleService.ts +209 -1
- package/Server/Utils/Workspace/Slack/Slack.ts +65 -10
- package/Server/Utils/Workspace/WorkspaceBase.ts +9 -0
- package/Utils/CronTime.ts +1 -0
- package/build/dist/Server/API/WorkspaceNotificationRuleAPI.js +29 -0
- package/build/dist/Server/API/WorkspaceNotificationRuleAPI.js.map +1 -0
- package/build/dist/Server/Services/IncidentService.js +3 -1
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +166 -1
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js +57 -24
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/WorkspaceBase.js +9 -0
- package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
- package/build/dist/Utils/CronTime.js +1 -0
- package/build/dist/Utils/CronTime.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import UserMiddleware from "../Middleware/UserAuthorization";
|
|
2
|
+
import WorkspaceNotificationRuleService, {
|
|
3
|
+
Service as WorkspaceNotificationRuleServiceType,
|
|
4
|
+
} from "../Services/WorkspaceNotificationRuleService";
|
|
5
|
+
import {
|
|
6
|
+
ExpressRequest,
|
|
7
|
+
ExpressResponse,
|
|
8
|
+
NextFunction,
|
|
9
|
+
} from "../Utils/Express";
|
|
10
|
+
import Response from "../Utils/Response";
|
|
11
|
+
import BaseAPI from "./BaseAPI";
|
|
12
|
+
import CommonAPI from "./CommonAPI";
|
|
13
|
+
import DatabaseCommonInteractionProps from "Common/Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
14
|
+
import WorkspaceNotificationRule from "Common/Models/DatabaseModels/WorkspaceNotificationRule";
|
|
15
|
+
import ObjectID from "../../Types/ObjectID";
|
|
16
|
+
|
|
17
|
+
export default class WorkspaceNotificationRuleAPI extends BaseAPI<
|
|
18
|
+
WorkspaceNotificationRule,
|
|
19
|
+
WorkspaceNotificationRuleServiceType
|
|
20
|
+
> {
|
|
21
|
+
public constructor() {
|
|
22
|
+
super(WorkspaceNotificationRule, WorkspaceNotificationRuleService);
|
|
23
|
+
|
|
24
|
+
this.router.get(
|
|
25
|
+
`${new this.entityType().getCrudApiPath()?.toString()}/test/:workspaceNotifcationRuleId`,
|
|
26
|
+
UserMiddleware.getUserMiddleware,
|
|
27
|
+
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
28
|
+
try {
|
|
29
|
+
const databaseProps: DatabaseCommonInteractionProps =
|
|
30
|
+
await CommonAPI.getDatabaseCommonInteractionProps(req);
|
|
31
|
+
|
|
32
|
+
await this.service.testRule({
|
|
33
|
+
ruleId: new ObjectID(
|
|
34
|
+
req.params["workspaceNotifcationRuleId"] as string,
|
|
35
|
+
),
|
|
36
|
+
props: databaseProps,
|
|
37
|
+
projectId: databaseProps.tenantId!,
|
|
38
|
+
testByUserId: databaseProps.userId!,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return Response.sendEmptySuccessResponse(req, res);
|
|
42
|
+
} catch (e) {
|
|
43
|
+
next(e);
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -38,6 +38,8 @@ import WorkspaceNotificationRule from "Common/Models/DatabaseModels/WorkspaceNot
|
|
|
38
38
|
import UserService from "./UserService";
|
|
39
39
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
40
40
|
import Monitor from "../../Models/DatabaseModels/Monitor";
|
|
41
|
+
import Text from "../../Types/Text";
|
|
42
|
+
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
41
43
|
|
|
42
44
|
export interface MessageBlocksByWorkspaceType {
|
|
43
45
|
workspaceType: WorkspaceType;
|
|
@@ -56,6 +58,209 @@ export class Service extends DatabaseService<WorkspaceNotificationRule> {
|
|
|
56
58
|
super(WorkspaceNotificationRule);
|
|
57
59
|
}
|
|
58
60
|
|
|
61
|
+
@CaptureSpan()
|
|
62
|
+
public async testRule(data: {
|
|
63
|
+
ruleId: ObjectID;
|
|
64
|
+
projectId: ObjectID;
|
|
65
|
+
testByUserId: ObjectID; // this can be useful to invite user to channels if the channels was created.
|
|
66
|
+
props: DatabaseCommonInteractionProps;
|
|
67
|
+
}): Promise<void> {
|
|
68
|
+
const rule: WorkspaceNotificationRule | null = await this.findOneById({
|
|
69
|
+
id: data.ruleId,
|
|
70
|
+
select: {
|
|
71
|
+
notificationRule: true,
|
|
72
|
+
workspaceType: true,
|
|
73
|
+
eventType: true,
|
|
74
|
+
name: true,
|
|
75
|
+
},
|
|
76
|
+
props: {
|
|
77
|
+
isRoot: true,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (!rule) {
|
|
82
|
+
throw new BadDataException("Rule not found");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// check fi the testUser account is connected to workspace or not.
|
|
86
|
+
const userWOrkspaceAuth: WorkspaceUserAuthToken | null =
|
|
87
|
+
await WorkspaceUserAuthTokenService.findOneBy({
|
|
88
|
+
query: {
|
|
89
|
+
projectId: data.projectId,
|
|
90
|
+
userId: data.testByUserId,
|
|
91
|
+
workspaceType: rule.workspaceType!,
|
|
92
|
+
},
|
|
93
|
+
select: {
|
|
94
|
+
workspaceUserId: true,
|
|
95
|
+
},
|
|
96
|
+
props: {
|
|
97
|
+
isRoot: true,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
if (!userWOrkspaceAuth || !userWOrkspaceAuth.workspaceUserId) {
|
|
102
|
+
throw new BadDataException(
|
|
103
|
+
"This account is not connected to " +
|
|
104
|
+
rule.workspaceType +
|
|
105
|
+
". Please go to User Settings and connect the account.",
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const projectAuth: WorkspaceProjectAuthToken | null =
|
|
110
|
+
await WorkspaceProjectAuthTokenService.findOneBy({
|
|
111
|
+
query: {
|
|
112
|
+
projectId: data.projectId,
|
|
113
|
+
workspaceType: rule.workspaceType!,
|
|
114
|
+
},
|
|
115
|
+
select: {
|
|
116
|
+
workspaceType: true,
|
|
117
|
+
authToken: true,
|
|
118
|
+
},
|
|
119
|
+
props: {
|
|
120
|
+
isRoot: true,
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
if (!projectAuth) {
|
|
125
|
+
throw new BadDataException(
|
|
126
|
+
"This project is not connected to " +
|
|
127
|
+
rule.workspaceType +
|
|
128
|
+
". Please go to Project Settings and connect the account.",
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const projectAuthToken: string = projectAuth.authToken!;
|
|
133
|
+
|
|
134
|
+
const notificationRule: BaseNotificationRule =
|
|
135
|
+
rule.notificationRule as BaseNotificationRule;
|
|
136
|
+
|
|
137
|
+
// now send test message to these channels.
|
|
138
|
+
const messageBlocksByWorkspaceTypes: Array<MessageBlocksByWorkspaceType> =
|
|
139
|
+
[];
|
|
140
|
+
|
|
141
|
+
// use markdown to create blocks
|
|
142
|
+
messageBlocksByWorkspaceTypes.push({
|
|
143
|
+
workspaceType: rule.workspaceType!,
|
|
144
|
+
messageBlocks: [
|
|
145
|
+
{
|
|
146
|
+
_type: "WorkspacePayloadMarkdown",
|
|
147
|
+
text: `This is a test message for rule **${rule.name}**`,
|
|
148
|
+
} as WorkspacePayloadMarkdown,
|
|
149
|
+
],
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
let existingChannelNames: Array<string> = [];
|
|
153
|
+
|
|
154
|
+
let createdChannels: NotificationRuleWorkspaceChannel[] = [];
|
|
155
|
+
|
|
156
|
+
if ((notificationRule as IncidentNotificationRule).shouldCreateNewChannel) {
|
|
157
|
+
const generateRandomString: string = Text.generateRandomText(5);
|
|
158
|
+
|
|
159
|
+
try {
|
|
160
|
+
// create channel
|
|
161
|
+
createdChannels = await this.createChannelsBasedOnRules({
|
|
162
|
+
projectOrUserAuthTokenForWorkspace: projectAuthToken,
|
|
163
|
+
workspaceType: rule.workspaceType!,
|
|
164
|
+
notificationRules: [rule],
|
|
165
|
+
channelNameSiffix: generateRandomString,
|
|
166
|
+
notificationEventType: rule.eventType!,
|
|
167
|
+
});
|
|
168
|
+
} catch (err) {
|
|
169
|
+
throw new BadDataException(
|
|
170
|
+
"Cannot create a new channel. " + (err as Error)?.message,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
await this.inviteUsersBasedOnRulesAndWorkspaceChannels({
|
|
176
|
+
workspaceChannels: createdChannels,
|
|
177
|
+
projectId: data.projectId,
|
|
178
|
+
notificationRules: [rule],
|
|
179
|
+
userIds: [data.testByUserId],
|
|
180
|
+
});
|
|
181
|
+
} catch (err) {
|
|
182
|
+
throw new BadDataException(
|
|
183
|
+
"Cannot invite users to the channel. " + (err as Error)?.message,
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (notificationRule.shouldPostToExistingChannel) {
|
|
189
|
+
existingChannelNames = this.getExistingChannelNamesFromNotificationRules({
|
|
190
|
+
notificationRules: [notificationRule],
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
for (const channelName of existingChannelNames) {
|
|
194
|
+
try {
|
|
195
|
+
// check if these channels exist.
|
|
196
|
+
const channelExists: boolean =
|
|
197
|
+
await WorkspaceUtil.getWorkspaceTypeUtil(
|
|
198
|
+
rule.workspaceType!,
|
|
199
|
+
).doesChannelExist({
|
|
200
|
+
authToken: projectAuthToken,
|
|
201
|
+
channelName: channelName,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
if (!channelExists) {
|
|
205
|
+
throw new BadDataException(
|
|
206
|
+
`Channel ${channelName} does not exist.`,
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
} catch (err) {
|
|
210
|
+
throw new BadDataException((err as Error)?.message);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// post message
|
|
215
|
+
|
|
216
|
+
for (const createdChannel of createdChannels) {
|
|
217
|
+
try {
|
|
218
|
+
await WorkspaceUtil.postMessageToAllWorkspaceChannelsAsBot({
|
|
219
|
+
projectId: data.projectId,
|
|
220
|
+
messagePayloadsByWorkspace: messageBlocksByWorkspaceTypes.map(
|
|
221
|
+
(messageBlocksByWorkspaceType: MessageBlocksByWorkspaceType) => {
|
|
222
|
+
return {
|
|
223
|
+
_type: "WorkspaceMessagePayload",
|
|
224
|
+
workspaceType: messageBlocksByWorkspaceType.workspaceType,
|
|
225
|
+
messageBlocks: messageBlocksByWorkspaceType.messageBlocks,
|
|
226
|
+
channelNames: [],
|
|
227
|
+
channelIds: [createdChannel.id],
|
|
228
|
+
};
|
|
229
|
+
},
|
|
230
|
+
),
|
|
231
|
+
});
|
|
232
|
+
} catch (err) {
|
|
233
|
+
throw new BadDataException(
|
|
234
|
+
"Cannot post message to channel. " + (err as Error)?.message,
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
for (const existingChannelName of existingChannelNames) {
|
|
240
|
+
try {
|
|
241
|
+
await WorkspaceUtil.postMessageToAllWorkspaceChannelsAsBot({
|
|
242
|
+
projectId: data.projectId,
|
|
243
|
+
messagePayloadsByWorkspace: messageBlocksByWorkspaceTypes.map(
|
|
244
|
+
(messageBlocksByWorkspaceType: MessageBlocksByWorkspaceType) => {
|
|
245
|
+
return {
|
|
246
|
+
_type: "WorkspaceMessagePayload",
|
|
247
|
+
workspaceType: messageBlocksByWorkspaceType.workspaceType,
|
|
248
|
+
messageBlocks: messageBlocksByWorkspaceType.messageBlocks,
|
|
249
|
+
channelNames: [existingChannelName],
|
|
250
|
+
channelIds: [],
|
|
251
|
+
};
|
|
252
|
+
},
|
|
253
|
+
),
|
|
254
|
+
});
|
|
255
|
+
} catch (err) {
|
|
256
|
+
throw new BadDataException(
|
|
257
|
+
"Cannot post message to channel. " + (err as Error)?.message,
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
59
264
|
@CaptureSpan()
|
|
60
265
|
public async sendWorkspaceMarkdownNotification(data: {
|
|
61
266
|
projectId: ObjectID;
|
|
@@ -103,6 +308,7 @@ export class Service extends DatabaseService<WorkspaceNotificationRule> {
|
|
|
103
308
|
projectId: data.projectId,
|
|
104
309
|
notificationRuleEventType: NotificationRuleEventType.Monitor,
|
|
105
310
|
workspaceType: messageBlocksByWorkspaceType.workspaceType,
|
|
311
|
+
notificationFor: data.notificationFor,
|
|
106
312
|
});
|
|
107
313
|
|
|
108
314
|
let monitorChannels: Array<WorkspaceChannel> = [];
|
|
@@ -198,15 +404,17 @@ export class Service extends DatabaseService<WorkspaceNotificationRule> {
|
|
|
198
404
|
projectId: ObjectID;
|
|
199
405
|
workspaceType: WorkspaceType;
|
|
200
406
|
notificationRuleEventType: NotificationRuleEventType;
|
|
407
|
+
notificationFor: NotificationFor;
|
|
201
408
|
}): Promise<Array<string>> {
|
|
202
409
|
logger.debug("getExistingChannelNamesBasedOnEventType called with data:");
|
|
203
410
|
logger.debug(data);
|
|
204
411
|
|
|
205
412
|
const notificationRules: Array<WorkspaceNotificationRule> =
|
|
206
|
-
await this.
|
|
413
|
+
await this.getMatchingNotificationRules({
|
|
207
414
|
projectId: data.projectId,
|
|
208
415
|
workspaceType: data.workspaceType,
|
|
209
416
|
notificationRuleEventType: data.notificationRuleEventType,
|
|
417
|
+
notificationFor: data.notificationFor,
|
|
210
418
|
});
|
|
211
419
|
|
|
212
420
|
logger.debug("Notification rules retrieved:");
|
|
@@ -30,6 +30,7 @@ import SlackifyMarkdown from "slackify-markdown";
|
|
|
30
30
|
import { DropdownOption } from "../../../../UI/Components/Dropdown/Dropdown";
|
|
31
31
|
import OneUptimeDate from "../../../../Types/Date";
|
|
32
32
|
import CaptureSpan from "../../Telemetry/CaptureSpan";
|
|
33
|
+
import BadDataException from "../../../../Types/Exception/BadDataException";
|
|
33
34
|
|
|
34
35
|
export default class SlackUtil extends WorkspaceBase {
|
|
35
36
|
@CaptureSpan()
|
|
@@ -123,7 +124,10 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
123
124
|
if ((result.jsonData as JSONObject)?.["ok"] !== true) {
|
|
124
125
|
logger.error("Invalid response from Slack API:");
|
|
125
126
|
logger.error(result.jsonData);
|
|
126
|
-
|
|
127
|
+
const messageFromSlack: string = (result.jsonData as JSONObject)?.[
|
|
128
|
+
"error"
|
|
129
|
+
] as string;
|
|
130
|
+
throw new BadRequestException("Error from Slack " + messageFromSlack);
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
logger.debug("Modal shown to user successfully.");
|
|
@@ -187,7 +191,10 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
187
191
|
if ((response.jsonData as JSONObject)?.["ok"] !== true) {
|
|
188
192
|
logger.error("Invalid response from Slack API:");
|
|
189
193
|
logger.error(response.jsonData);
|
|
190
|
-
|
|
194
|
+
const messageFromSlack: string = (response.jsonData as JSONObject)?.[
|
|
195
|
+
"error"
|
|
196
|
+
] as string;
|
|
197
|
+
throw new BadRequestException("Error from Slack " + messageFromSlack);
|
|
191
198
|
}
|
|
192
199
|
|
|
193
200
|
logger.debug("Channel joined successfully with data:");
|
|
@@ -240,7 +247,10 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
240
247
|
if ((response.jsonData as JSONObject)?.["ok"] !== true) {
|
|
241
248
|
logger.error("Invalid response from Slack API:");
|
|
242
249
|
logger.error(response.jsonData);
|
|
243
|
-
|
|
250
|
+
const messageFromSlack: string = (response.jsonData as JSONObject)?.[
|
|
251
|
+
"error"
|
|
252
|
+
] as string;
|
|
253
|
+
throw new BadRequestException("Error from Slack " + messageFromSlack);
|
|
244
254
|
}
|
|
245
255
|
|
|
246
256
|
logger.debug("User invited to channel successfully.");
|
|
@@ -344,7 +354,7 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
344
354
|
|
|
345
355
|
if (!channels[data.channelName]) {
|
|
346
356
|
logger.error("Channel not found.");
|
|
347
|
-
throw new
|
|
357
|
+
throw new BadDataException("Channel not found.");
|
|
348
358
|
}
|
|
349
359
|
|
|
350
360
|
logger.debug("Workspace channel ID obtained:");
|
|
@@ -386,7 +396,10 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
386
396
|
if ((response.jsonData as JSONObject)?.["ok"] !== true) {
|
|
387
397
|
logger.error("Invalid response from Slack API:");
|
|
388
398
|
logger.error(response.jsonData);
|
|
389
|
-
|
|
399
|
+
const messageFromSlack: string = (response.jsonData as JSONObject)?.[
|
|
400
|
+
"error"
|
|
401
|
+
] as string;
|
|
402
|
+
throw new BadRequestException("Error from Slack " + messageFromSlack);
|
|
390
403
|
}
|
|
391
404
|
|
|
392
405
|
if (
|
|
@@ -440,7 +453,10 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
440
453
|
if ((response.jsonData as JSONObject)?.["ok"] !== true) {
|
|
441
454
|
logger.error("Invalid response from Slack API:");
|
|
442
455
|
logger.error(response.jsonData);
|
|
443
|
-
|
|
456
|
+
const messageFromSlack: string = (response.jsonData as JSONObject)?.[
|
|
457
|
+
"error"
|
|
458
|
+
] as string;
|
|
459
|
+
throw new BadRequestException("Error from Slack " + messageFromSlack);
|
|
444
460
|
}
|
|
445
461
|
|
|
446
462
|
const channels: Dictionary<WorkspaceChannel> = {};
|
|
@@ -527,6 +543,33 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
527
543
|
return values;
|
|
528
544
|
}
|
|
529
545
|
|
|
546
|
+
@CaptureSpan()
|
|
547
|
+
public static override async doesChannelExist(data: {
|
|
548
|
+
authToken: string;
|
|
549
|
+
channelName: string;
|
|
550
|
+
}): Promise<boolean> {
|
|
551
|
+
// if channel name starts with #, remove it
|
|
552
|
+
if (data.channelName && data.channelName.startsWith("#")) {
|
|
553
|
+
data.channelName = data.channelName.substring(1);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// convert channel name to lowercase
|
|
557
|
+
data.channelName = data.channelName.toLowerCase();
|
|
558
|
+
|
|
559
|
+
// get channel id from channel name
|
|
560
|
+
const channels: Dictionary<WorkspaceChannel> =
|
|
561
|
+
await this.getAllWorkspaceChannels({
|
|
562
|
+
authToken: data.authToken,
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
// if this channel exists
|
|
566
|
+
if (channels[data.channelName]) {
|
|
567
|
+
return true;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
return false;
|
|
571
|
+
}
|
|
572
|
+
|
|
530
573
|
@CaptureSpan()
|
|
531
574
|
public static override async sendMessage(data: {
|
|
532
575
|
workspaceMessagePayload: WorkspaceMessagePayload;
|
|
@@ -664,7 +707,10 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
664
707
|
if ((response.jsonData as JSONObject)?.["ok"] !== true) {
|
|
665
708
|
logger.error("Invalid response from Slack API:");
|
|
666
709
|
logger.error(response.jsonData);
|
|
667
|
-
|
|
710
|
+
const messageFromSlack: string = (response.jsonData as JSONObject)?.[
|
|
711
|
+
"error"
|
|
712
|
+
] as string;
|
|
713
|
+
throw new BadRequestException("Error from Slack " + messageFromSlack);
|
|
668
714
|
}
|
|
669
715
|
|
|
670
716
|
logger.debug("Payload blocks sent to channel successfully.");
|
|
@@ -736,7 +782,10 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
736
782
|
if ((response.jsonData as JSONObject)?.["ok"] !== true) {
|
|
737
783
|
logger.error("Invalid response from Slack API:");
|
|
738
784
|
logger.error(response.jsonData);
|
|
739
|
-
|
|
785
|
+
const messageFromSlack: string = (response.jsonData as JSONObject)?.[
|
|
786
|
+
"error"
|
|
787
|
+
] as string;
|
|
788
|
+
throw new BadRequestException("Error from Slack " + messageFromSlack);
|
|
740
789
|
}
|
|
741
790
|
|
|
742
791
|
if (
|
|
@@ -1111,7 +1160,10 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
1111
1160
|
if ((response.jsonData as JSONObject)?.["ok"] !== true) {
|
|
1112
1161
|
logger.error("Invalid response from Slack API:");
|
|
1113
1162
|
logger.error(response.jsonData);
|
|
1114
|
-
|
|
1163
|
+
const messageFromSlack: string = (response.jsonData as JSONObject)?.[
|
|
1164
|
+
"error"
|
|
1165
|
+
] as string;
|
|
1166
|
+
throw new BadRequestException("Error from Slack " + messageFromSlack);
|
|
1115
1167
|
}
|
|
1116
1168
|
|
|
1117
1169
|
// check if the user is in the channel
|
|
@@ -1175,7 +1227,10 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
1175
1227
|
if ((response.jsonData as JSONObject)?.["ok"] !== true) {
|
|
1176
1228
|
logger.error("Invalid response from Slack API:");
|
|
1177
1229
|
logger.error(response.jsonData);
|
|
1178
|
-
|
|
1230
|
+
const messageFromSlack: string = (response.jsonData as JSONObject)?.[
|
|
1231
|
+
"error"
|
|
1232
|
+
] as string;
|
|
1233
|
+
throw new BadRequestException("Error from Slack " + messageFromSlack);
|
|
1179
1234
|
}
|
|
1180
1235
|
|
|
1181
1236
|
// check if the user is in the channel
|
|
@@ -48,6 +48,15 @@ export default class WorkspaceBase {
|
|
|
48
48
|
}): Promise<boolean> {
|
|
49
49
|
throw new NotImplementedException();
|
|
50
50
|
}
|
|
51
|
+
|
|
52
|
+
@CaptureSpan()
|
|
53
|
+
public static async doesChannelExist(_data: {
|
|
54
|
+
authToken: string;
|
|
55
|
+
channelName: string;
|
|
56
|
+
}): Promise<boolean> {
|
|
57
|
+
throw new NotImplementedException();
|
|
58
|
+
}
|
|
59
|
+
|
|
51
60
|
@CaptureSpan()
|
|
52
61
|
public static async getUsernameFromUserId(_data: {
|
|
53
62
|
authToken: string;
|
package/Utils/CronTime.ts
CHANGED
|
@@ -8,3 +8,4 @@ export const EVERY_FIFTEEN_MINUTE: string = "*/15 * * * *";
|
|
|
8
8
|
export const EVERY_THIRTY_SECONDS: string = "*/30 * * * * *";
|
|
9
9
|
export const EVERY_THIRTY_MINUTES: string = "*/30 * * * *";
|
|
10
10
|
export const EVERY_THREE_HOURS: string = "0 */3 * * *";
|
|
11
|
+
export const EVERY_TEN_SECONDS: string = "*/10 * * * * *";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import UserMiddleware from "../Middleware/UserAuthorization";
|
|
2
|
+
import WorkspaceNotificationRuleService from "../Services/WorkspaceNotificationRuleService";
|
|
3
|
+
import Response from "../Utils/Response";
|
|
4
|
+
import BaseAPI from "./BaseAPI";
|
|
5
|
+
import CommonAPI from "./CommonAPI";
|
|
6
|
+
import WorkspaceNotificationRule from "Common/Models/DatabaseModels/WorkspaceNotificationRule";
|
|
7
|
+
import ObjectID from "../../Types/ObjectID";
|
|
8
|
+
export default class WorkspaceNotificationRuleAPI extends BaseAPI {
|
|
9
|
+
constructor() {
|
|
10
|
+
var _a;
|
|
11
|
+
super(WorkspaceNotificationRule, WorkspaceNotificationRuleService);
|
|
12
|
+
this.router.get(`${(_a = new this.entityType().getCrudApiPath()) === null || _a === void 0 ? void 0 : _a.toString()}/test/:workspaceNotifcationRuleId`, UserMiddleware.getUserMiddleware, async (req, res, next) => {
|
|
13
|
+
try {
|
|
14
|
+
const databaseProps = await CommonAPI.getDatabaseCommonInteractionProps(req);
|
|
15
|
+
await this.service.testRule({
|
|
16
|
+
ruleId: new ObjectID(req.params["workspaceNotifcationRuleId"]),
|
|
17
|
+
props: databaseProps,
|
|
18
|
+
projectId: databaseProps.tenantId,
|
|
19
|
+
testByUserId: databaseProps.userId,
|
|
20
|
+
});
|
|
21
|
+
return Response.sendEmptySuccessResponse(req, res);
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
next(e);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=WorkspaceNotificationRuleAPI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkspaceNotificationRuleAPI.js","sourceRoot":"","sources":["../../../../Server/API/WorkspaceNotificationRuleAPI.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,iCAAiC,CAAC;AAC7D,OAAO,gCAEN,MAAM,8CAA8C,CAAC;AAMtD,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AACzC,OAAO,OAAO,MAAM,WAAW,CAAC;AAChC,OAAO,SAAS,MAAM,aAAa,CAAC;AAEpC,OAAO,yBAAyB,MAAM,wDAAwD,CAAC;AAC/F,OAAO,QAAQ,MAAM,sBAAsB,CAAC;AAE5C,MAAM,CAAC,OAAO,OAAO,4BAA6B,SAAQ,OAGzD;IACC;;QACE,KAAK,CAAC,yBAAyB,EAAE,gCAAgC,CAAC,CAAC;QAEnE,IAAI,CAAC,MAAM,CAAC,GAAG,CACb,GAAG,MAAA,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC,cAAc,EAAE,0CAAE,QAAQ,EAAE,mCAAmC,EACxF,cAAc,CAAC,iBAAiB,EAChC,KAAK,EAAE,GAAmB,EAAE,GAAoB,EAAE,IAAkB,EAAE,EAAE;YACtE,IAAI,CAAC;gBACH,MAAM,aAAa,GACjB,MAAM,SAAS,CAAC,iCAAiC,CAAC,GAAG,CAAC,CAAC;gBAEzD,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;oBAC1B,MAAM,EAAE,IAAI,QAAQ,CAClB,GAAG,CAAC,MAAM,CAAC,4BAA4B,CAAW,CACnD;oBACD,KAAK,EAAE,aAAa;oBACpB,SAAS,EAAE,aAAa,CAAC,QAAS;oBAClC,YAAY,EAAE,aAAa,CAAC,MAAO;iBACpC,CAAC,CAAC;gBAEH,OAAO,QAAQ,CAAC,wBAAwB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACrD,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,CAAC,CAAC,CAAC;YACV,CAAC;QACH,CAAC,CACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -228,7 +228,9 @@ export class Service extends DatabaseService {
|
|
|
228
228
|
if (!lastIncident) {
|
|
229
229
|
return 0;
|
|
230
230
|
}
|
|
231
|
-
return lastIncident.incidentNumber
|
|
231
|
+
return lastIncident.incidentNumber
|
|
232
|
+
? Number(lastIncident.incidentNumber)
|
|
233
|
+
: 0;
|
|
232
234
|
}
|
|
233
235
|
async onBeforeCreate(createBy) {
|
|
234
236
|
if (!createBy.props.tenantId && !createBy.props.isRoot) {
|