@oneuptime/common 9.5.8 → 9.5.9
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/Alert.ts +8 -9
- package/Models/DatabaseModels/Incident.ts +5 -5
- package/Models/DatabaseModels/IncidentTemplate.ts +4 -3
- package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +1 -1
- package/Models/DatabaseModels/UserOnCallLog.ts +1 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1770833704656-MigrationName.ts +156 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1770834237090-MigrationName.ts +119 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Services/AlertEpisodeFeedService.ts +50 -0
- package/Server/Services/AlertEpisodeInternalNoteService.ts +162 -0
- package/Server/Services/AlertEpisodeMemberService.ts +7 -0
- package/Server/Services/AlertEpisodeOwnerTeamService.ts +186 -0
- package/Server/Services/AlertEpisodeOwnerUserService.ts +180 -0
- package/Server/Services/AlertEpisodeService.ts +68 -0
- package/Server/Services/AlertEpisodeStateTimelineService.ts +5 -0
- package/Server/Services/AlertService.ts +3 -0
- package/Server/Services/IncidentEpisodeFeedService.ts +50 -0
- package/Server/Services/IncidentEpisodeInternalNoteService.ts +163 -0
- package/Server/Services/IncidentEpisodeMemberService.ts +7 -0
- package/Server/Services/IncidentEpisodeOwnerTeamService.ts +189 -0
- package/Server/Services/IncidentEpisodeOwnerUserService.ts +183 -0
- package/Server/Services/IncidentEpisodePublicNoteService.ts +8 -0
- package/Server/Services/IncidentEpisodeService.ts +91 -12
- package/Server/Services/IncidentEpisodeStateTimelineService.ts +5 -0
- package/Server/Services/IncidentService.ts +5 -0
- package/Server/Services/WorkspaceNotificationRuleService.ts +20 -0
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +1 -1
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.ts +7 -6
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +1 -1
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +7 -6
- package/Server/Utils/Workspace/Slack/Actions/Alert.ts +17 -0
- package/Server/Utils/Workspace/Slack/Actions/AlertEpisode.ts +27 -12
- package/Server/Utils/Workspace/Slack/Actions/Incident.ts +17 -0
- package/Server/Utils/Workspace/Slack/Actions/IncidentEpisode.ts +86 -28
- package/Server/Utils/Workspace/Slack/Messages/IncidentEpisode.ts +6 -6
- package/Server/Utils/Workspace/Slack/Slack.ts +49 -0
- package/Server/Utils/Workspace/WorkspaceMessages/Alert.ts +2 -1
- package/Server/Utils/Workspace/WorkspaceMessages/AlertEpisode.ts +3 -1
- package/Server/Utils/Workspace/WorkspaceMessages/Incident.ts +2 -1
- package/Server/Utils/Workspace/WorkspaceMessages/IncidentEpisode.ts +3 -1
- package/Types/Permission.ts +641 -0
- package/UI/Components/Detail/Detail.tsx +13 -4
- package/UI/Components/Detail/Field.ts +2 -2
- package/UI/Components/Dropdown/Dropdown.tsx +38 -7
- package/UI/Components/Forms/BasicForm.tsx +35 -5
- package/UI/Components/Forms/Fields/PermissionPicker.tsx +261 -0
- package/UI/Components/Forms/Types/Field.ts +5 -3
- package/UI/Utils/Permission.ts +29 -6
- package/build/dist/Models/DatabaseModels/Alert.js +8 -8
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +5 -5
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js +3 -3
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770833704656-MigrationName.js +63 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770833704656-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770834237090-MigrationName.js +46 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1770834237090-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeFeedService.js +33 -0
- package/build/dist/Server/Services/AlertEpisodeFeedService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeInternalNoteService.js +132 -0
- package/build/dist/Server/Services/AlertEpisodeInternalNoteService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeMemberService.js +7 -0
- package/build/dist/Server/Services/AlertEpisodeMemberService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeOwnerTeamService.js +163 -0
- package/build/dist/Server/Services/AlertEpisodeOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeOwnerUserService.js +156 -0
- package/build/dist/Server/Services/AlertEpisodeOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeService.js +53 -0
- package/build/dist/Server/Services/AlertEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeStateTimelineService.js +4 -0
- package/build/dist/Server/Services/AlertEpisodeStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +3 -5
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeFeedService.js +33 -0
- package/build/dist/Server/Services/IncidentEpisodeFeedService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeInternalNoteService.js +132 -0
- package/build/dist/Server/Services/IncidentEpisodeInternalNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeMemberService.js +7 -0
- package/build/dist/Server/Services/IncidentEpisodeMemberService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeOwnerTeamService.js +163 -0
- package/build/dist/Server/Services/IncidentEpisodeOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeOwnerUserService.js +156 -0
- package/build/dist/Server/Services/IncidentEpisodeOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +8 -0
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js +72 -10
- package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js +4 -0
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +5 -5
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +16 -0
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js +7 -6
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +7 -6
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js +16 -0
- package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Actions/AlertEpisode.js +25 -9
- package/build/dist/Server/Utils/Workspace/Slack/Actions/AlertEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js +16 -0
- package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Actions/IncidentEpisode.js +71 -25
- package/build/dist/Server/Utils/Workspace/Slack/Actions/IncidentEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Messages/IncidentEpisode.js +6 -6
- package/build/dist/Server/Utils/Workspace/Slack/Messages/IncidentEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js +40 -0
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/WorkspaceMessages/Alert.js +1 -1
- package/build/dist/Server/Utils/Workspace/WorkspaceMessages/Alert.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/WorkspaceMessages/AlertEpisode.js +1 -1
- package/build/dist/Server/Utils/Workspace/WorkspaceMessages/AlertEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/WorkspaceMessages/Incident.js +1 -1
- package/build/dist/Server/Utils/Workspace/WorkspaceMessages/Incident.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/WorkspaceMessages/IncidentEpisode.js +1 -1
- package/build/dist/Server/Utils/Workspace/WorkspaceMessages/IncidentEpisode.js.map +1 -1
- package/build/dist/Types/Permission.js +637 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/UI/Components/Detail/Detail.js +7 -1
- package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js +17 -2
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js +17 -3
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/PermissionPicker.js +129 -0
- package/build/dist/UI/Components/Forms/Fields/PermissionPicker.js.map +1 -0
- package/build/dist/UI/Utils/Permission.js +17 -4
- package/build/dist/UI/Utils/Permission.js.map +1 -1
- package/package.json +1 -1
|
@@ -33,6 +33,8 @@ import User from "../../Models/DatabaseModels/User";
|
|
|
33
33
|
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
34
34
|
import NotificationRuleWorkspaceChannel from "../../Types/Workspace/NotificationRules/NotificationRuleWorkspaceChannel";
|
|
35
35
|
import WorkspaceType from "../../Types/Workspace/WorkspaceType";
|
|
36
|
+
import IncidentEpisodeWorkspaceMessages from "../Utils/Workspace/WorkspaceMessages/IncidentEpisode";
|
|
37
|
+
import { MessageBlocksByWorkspaceType } from "./WorkspaceNotificationRuleService";
|
|
36
38
|
import IncidentService from "./IncidentService";
|
|
37
39
|
import OnCallDutyPolicyService from "./OnCallDutyPolicyService";
|
|
38
40
|
import OnCallDutyPolicy from "../../Models/DatabaseModels/OnCallDutyPolicy";
|
|
@@ -147,6 +149,17 @@ export class Service extends DatabaseService<Model> {
|
|
|
147
149
|
|
|
148
150
|
// Create initial state timeline entry
|
|
149
151
|
Promise.resolve()
|
|
152
|
+
.then(async () => {
|
|
153
|
+
try {
|
|
154
|
+
if (createdItem.projectId && createdItem.id) {
|
|
155
|
+
await this.handleEpisodeWorkspaceOperationsAsync(createdItem);
|
|
156
|
+
}
|
|
157
|
+
} catch (error) {
|
|
158
|
+
logger.error(
|
|
159
|
+
`Workspace operations failed in IncidentEpisodeService.onCreateSuccess: ${error}`,
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
})
|
|
150
163
|
.then(async () => {
|
|
151
164
|
try {
|
|
152
165
|
await this.changeEpisodeState({
|
|
@@ -193,6 +206,51 @@ export class Service extends DatabaseService<Model> {
|
|
|
193
206
|
return createdItem;
|
|
194
207
|
}
|
|
195
208
|
|
|
209
|
+
@CaptureSpan()
|
|
210
|
+
private async handleEpisodeWorkspaceOperationsAsync(
|
|
211
|
+
createdItem: Model,
|
|
212
|
+
): Promise<void> {
|
|
213
|
+
try {
|
|
214
|
+
if (!createdItem.projectId || !createdItem.id) {
|
|
215
|
+
throw new BadDataException(
|
|
216
|
+
"projectId and id are required for workspace operations",
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const workspaceResult: {
|
|
221
|
+
channelsCreated: Array<NotificationRuleWorkspaceChannel>;
|
|
222
|
+
} | null =
|
|
223
|
+
await IncidentEpisodeWorkspaceMessages.createChannelsAndInviteUsersToChannels(
|
|
224
|
+
{
|
|
225
|
+
projectId: createdItem.projectId,
|
|
226
|
+
incidentEpisodeId: createdItem.id,
|
|
227
|
+
episodeNumber: createdItem.episodeNumber || 0,
|
|
228
|
+
...(createdItem.episodeNumberWithPrefix
|
|
229
|
+
? {
|
|
230
|
+
episodeNumberWithPrefix: createdItem.episodeNumberWithPrefix,
|
|
231
|
+
}
|
|
232
|
+
: {}),
|
|
233
|
+
},
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
if (workspaceResult && workspaceResult.channelsCreated?.length > 0) {
|
|
237
|
+
await this.updateOneById({
|
|
238
|
+
id: createdItem.id,
|
|
239
|
+
data: {
|
|
240
|
+
postUpdatesToWorkspaceChannels:
|
|
241
|
+
workspaceResult.channelsCreated || [],
|
|
242
|
+
},
|
|
243
|
+
props: {
|
|
244
|
+
isRoot: true,
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
} catch (error) {
|
|
249
|
+
logger.error(`Error in handleEpisodeWorkspaceOperationsAsync: ${error}`);
|
|
250
|
+
throw error;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
196
254
|
@CaptureSpan()
|
|
197
255
|
private async createEpisodeCreatedFeed(episode: Model): Promise<void> {
|
|
198
256
|
if (!episode.id || !episode.projectId) {
|
|
@@ -213,6 +271,14 @@ export class Service extends DatabaseService<Model> {
|
|
|
213
271
|
feedInfoInMarkdown += `This episode was manually created.\n\n`;
|
|
214
272
|
}
|
|
215
273
|
|
|
274
|
+
const episodeCreateMessageBlocks: Array<MessageBlocksByWorkspaceType> =
|
|
275
|
+
await IncidentEpisodeWorkspaceMessages.getIncidentEpisodeCreateMessageBlocks(
|
|
276
|
+
{
|
|
277
|
+
incidentEpisodeId: episode.id,
|
|
278
|
+
projectId: episode.projectId,
|
|
279
|
+
},
|
|
280
|
+
);
|
|
281
|
+
|
|
216
282
|
await IncidentEpisodeFeedService.createIncidentEpisodeFeedItem({
|
|
217
283
|
incidentEpisodeId: episode.id,
|
|
218
284
|
projectId: episode.projectId,
|
|
@@ -220,6 +286,10 @@ export class Service extends DatabaseService<Model> {
|
|
|
220
286
|
displayColor: Red500,
|
|
221
287
|
feedInfoInMarkdown: feedInfoInMarkdown,
|
|
222
288
|
userId: episode.createdByUserId || undefined,
|
|
289
|
+
workspaceNotification: {
|
|
290
|
+
appendMessageBlocks: episodeCreateMessageBlocks,
|
|
291
|
+
sendWorkspaceNotification: true,
|
|
292
|
+
},
|
|
223
293
|
});
|
|
224
294
|
}
|
|
225
295
|
|
|
@@ -952,21 +1022,30 @@ export class Service extends DatabaseService<Model> {
|
|
|
952
1022
|
}
|
|
953
1023
|
|
|
954
1024
|
@CaptureSpan()
|
|
955
|
-
public getWorkspaceChannelForEpisode(
|
|
956
|
-
|
|
957
|
-
workspaceType
|
|
958
|
-
): Array<NotificationRuleWorkspaceChannel
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1025
|
+
public async getWorkspaceChannelForEpisode(data: {
|
|
1026
|
+
episodeId: ObjectID;
|
|
1027
|
+
workspaceType?: WorkspaceType | null;
|
|
1028
|
+
}): Promise<Array<NotificationRuleWorkspaceChannel>> {
|
|
1029
|
+
const episode: Model | null = await this.findOneById({
|
|
1030
|
+
id: data.episodeId,
|
|
1031
|
+
select: {
|
|
1032
|
+
postUpdatesToWorkspaceChannels: true,
|
|
1033
|
+
},
|
|
1034
|
+
props: {
|
|
1035
|
+
isRoot: true,
|
|
1036
|
+
},
|
|
1037
|
+
});
|
|
1038
|
+
|
|
1039
|
+
if (!episode) {
|
|
1040
|
+
throw new BadDataException("Incident Episode not found.");
|
|
965
1041
|
}
|
|
966
1042
|
|
|
967
|
-
return episode.postUpdatesToWorkspaceChannels.filter(
|
|
1043
|
+
return (episode.postUpdatesToWorkspaceChannels || []).filter(
|
|
968
1044
|
(channel: NotificationRuleWorkspaceChannel) => {
|
|
969
|
-
|
|
1045
|
+
if (!data.workspaceType) {
|
|
1046
|
+
return true;
|
|
1047
|
+
}
|
|
1048
|
+
return channel.workspaceType === data.workspaceType;
|
|
970
1049
|
},
|
|
971
1050
|
);
|
|
972
1051
|
}
|
|
@@ -383,6 +383,11 @@ export class Service extends DatabaseService<IncidentEpisodeStateTimeline> {
|
|
|
383
383
|
? `**Cause:** \n${createdItem.rootCause}`
|
|
384
384
|
: undefined,
|
|
385
385
|
userId: createdItem.createdByUserId || onCreate.createBy.props.userId,
|
|
386
|
+
workspaceNotification: {
|
|
387
|
+
sendWorkspaceNotification: true,
|
|
388
|
+
notifyUserId:
|
|
389
|
+
createdItem.createdByUserId || onCreate.createBy.props.userId,
|
|
390
|
+
},
|
|
386
391
|
});
|
|
387
392
|
|
|
388
393
|
return createdItem;
|
|
@@ -843,6 +843,11 @@ export class Service extends DatabaseService<Model> {
|
|
|
843
843
|
projectId: createdItem.projectId,
|
|
844
844
|
incidentId: createdItem.id,
|
|
845
845
|
incidentNumber: createdItem.incidentNumber!,
|
|
846
|
+
...(createdItem.incidentNumberWithPrefix
|
|
847
|
+
? {
|
|
848
|
+
incidentNumberWithPrefix: createdItem.incidentNumberWithPrefix,
|
|
849
|
+
}
|
|
850
|
+
: {}),
|
|
846
851
|
});
|
|
847
852
|
|
|
848
853
|
if (workspaceResult && workspaceResult.channelsCreated?.length > 0) {
|
|
@@ -52,6 +52,7 @@ import WorkspaceNotificationActionType from "../../Types/Workspace/WorkspaceNoti
|
|
|
52
52
|
import ExceptionMessages from "../../Types/Exception/ExceptionMessages";
|
|
53
53
|
import IncidentEpisode from "../../Models/DatabaseModels/IncidentEpisode";
|
|
54
54
|
import IncidentEpisodeService from "./IncidentEpisodeService";
|
|
55
|
+
import AlertEpisodeService from "./AlertEpisodeService";
|
|
55
56
|
|
|
56
57
|
export interface MessageBlocksByWorkspaceType {
|
|
57
58
|
workspaceType: WorkspaceType;
|
|
@@ -735,6 +736,25 @@ export class Service extends DatabaseService<WorkspaceNotificationRule> {
|
|
|
735
736
|
);
|
|
736
737
|
}
|
|
737
738
|
|
|
739
|
+
// incident episodes
|
|
740
|
+
if (data.notificationFor.incidentEpisodeId) {
|
|
741
|
+
monitorChannels =
|
|
742
|
+
await IncidentEpisodeService.getWorkspaceChannelForEpisode({
|
|
743
|
+
episodeId: data.notificationFor.incidentEpisodeId,
|
|
744
|
+
workspaceType: data.workspaceType,
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// alert episodes
|
|
749
|
+
if (data.notificationFor.alertEpisodeId) {
|
|
750
|
+
monitorChannels = await AlertEpisodeService.getWorkspaceChannelForEpisode(
|
|
751
|
+
{
|
|
752
|
+
episodeId: data.notificationFor.alertEpisodeId,
|
|
753
|
+
workspaceType: data.workspaceType,
|
|
754
|
+
},
|
|
755
|
+
);
|
|
756
|
+
}
|
|
757
|
+
|
|
738
758
|
logger.debug("Workspace channels found:");
|
|
739
759
|
logger.debug(monitorChannels);
|
|
740
760
|
|
|
@@ -361,7 +361,7 @@ export default class MicrosoftTeamsAlertActions {
|
|
|
361
361
|
await this.buildExecuteAlertOnCallPolicyCard(actionValue, projectId);
|
|
362
362
|
if (!card) {
|
|
363
363
|
await turnContext.sendActivity(
|
|
364
|
-
"No on-call policies
|
|
364
|
+
"No on-call policies have been configured for this project yet. Please add an on-call policy in the OneUptime Dashboard under On-Call Duty > Policies to use this feature.",
|
|
365
365
|
);
|
|
366
366
|
return;
|
|
367
367
|
}
|
|
@@ -391,7 +391,7 @@ export default class MicrosoftTeamsAlertEpisodeActions {
|
|
|
391
391
|
);
|
|
392
392
|
if (!card) {
|
|
393
393
|
await turnContext.sendActivity(
|
|
394
|
-
"No on-call policies
|
|
394
|
+
"No on-call policies have been configured for this project yet. Please add an on-call policy in the OneUptime Dashboard under On-Call Duty > Policies to use this feature.",
|
|
395
395
|
);
|
|
396
396
|
return;
|
|
397
397
|
}
|
|
@@ -495,11 +495,12 @@ export default class MicrosoftTeamsAlertEpisodeActions {
|
|
|
495
495
|
// Update the state
|
|
496
496
|
const episodeId: ObjectID = new ObjectID(actionValue);
|
|
497
497
|
|
|
498
|
-
await AlertEpisodeService.
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
498
|
+
await AlertEpisodeService.changeEpisodeState({
|
|
499
|
+
projectId: projectId,
|
|
500
|
+
episodeId: episodeId,
|
|
501
|
+
alertStateId: new ObjectID(alertStateId.toString()),
|
|
502
|
+
notifyOwners: true,
|
|
503
|
+
rootCause: "State changed via Microsoft Teams.",
|
|
503
504
|
props: {
|
|
504
505
|
isRoot: true,
|
|
505
506
|
},
|
|
@@ -424,7 +424,7 @@ export default class MicrosoftTeamsIncidentActions {
|
|
|
424
424
|
);
|
|
425
425
|
if (!card) {
|
|
426
426
|
await turnContext.sendActivity(
|
|
427
|
-
"No on-call policies
|
|
427
|
+
"No on-call policies have been configured for this project yet. Please add an on-call policy in the OneUptime Dashboard under On-Call Duty > Policies to use this feature.",
|
|
428
428
|
);
|
|
429
429
|
return;
|
|
430
430
|
}
|
|
@@ -403,7 +403,7 @@ export default class MicrosoftTeamsIncidentEpisodeActions {
|
|
|
403
403
|
);
|
|
404
404
|
if (!card) {
|
|
405
405
|
await turnContext.sendActivity(
|
|
406
|
-
"No on-call policies
|
|
406
|
+
"No on-call policies have been configured for this project yet. Please add an on-call policy in the OneUptime Dashboard under On-Call Duty > Policies to use this feature.",
|
|
407
407
|
);
|
|
408
408
|
return;
|
|
409
409
|
}
|
|
@@ -505,11 +505,12 @@ export default class MicrosoftTeamsIncidentEpisodeActions {
|
|
|
505
505
|
// Update the state
|
|
506
506
|
const episodeId: ObjectID = new ObjectID(actionValue);
|
|
507
507
|
|
|
508
|
-
await IncidentEpisodeService.
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
508
|
+
await IncidentEpisodeService.changeEpisodeState({
|
|
509
|
+
projectId: projectId,
|
|
510
|
+
episodeId: episodeId,
|
|
511
|
+
incidentStateId: new ObjectID(incidentStateId.toString()),
|
|
512
|
+
notifyOwners: true,
|
|
513
|
+
rootCause: "State changed via Microsoft Teams.",
|
|
513
514
|
props: {
|
|
514
515
|
isRoot: true,
|
|
515
516
|
},
|
|
@@ -322,6 +322,23 @@ export default class SlackAlertActions {
|
|
|
322
322
|
return option.label !== "" || option.value !== "";
|
|
323
323
|
});
|
|
324
324
|
|
|
325
|
+
if (dropdownOption.length === 0) {
|
|
326
|
+
if (data.slackRequest.slackChannelId) {
|
|
327
|
+
await SlackUtil.sendEphemeralMessageToChannel({
|
|
328
|
+
messageBlocks: [
|
|
329
|
+
{
|
|
330
|
+
_type: "WorkspacePayloadMarkdown",
|
|
331
|
+
text: "No on-call policies have been configured for this project yet. Please add an on-call policy in the OneUptime Dashboard under On-Call Duty > Policies to use this feature.",
|
|
332
|
+
} as WorkspacePayloadMarkdown,
|
|
333
|
+
],
|
|
334
|
+
authToken: data.slackRequest.projectAuthToken!,
|
|
335
|
+
channelId: data.slackRequest.slackChannelId,
|
|
336
|
+
userId: data.slackRequest.slackUserId!,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
325
342
|
const onCallPolicyDropdown: WorkspaceDropdownBlock = {
|
|
326
343
|
_type: "WorkspaceDropdownBlock",
|
|
327
344
|
label: "On Call Policy",
|
|
@@ -21,7 +21,7 @@ import UserNotificationEventType from "../../../../../Types/UserNotification/Use
|
|
|
21
21
|
import AlertState from "../../../../../Models/DatabaseModels/AlertState";
|
|
22
22
|
import AlertStateService from "../../../../Services/AlertStateService";
|
|
23
23
|
import logger from "../../../Logger";
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
import CaptureSpan from "../../../Telemetry/CaptureSpan";
|
|
26
26
|
import WorkspaceNotificationLogService from "../../../../Services/WorkspaceNotificationLogService";
|
|
27
27
|
import WorkspaceUserAuthTokenService from "../../../../Services/WorkspaceUserAuthTokenService";
|
|
@@ -305,6 +305,23 @@ export default class SlackAlertEpisodeActions {
|
|
|
305
305
|
return option.label !== "" || option.value !== "";
|
|
306
306
|
});
|
|
307
307
|
|
|
308
|
+
if (dropdownOption.length === 0) {
|
|
309
|
+
if (data.slackRequest.slackChannelId) {
|
|
310
|
+
await SlackUtil.sendEphemeralMessageToChannel({
|
|
311
|
+
messageBlocks: [
|
|
312
|
+
{
|
|
313
|
+
_type: "WorkspacePayloadMarkdown",
|
|
314
|
+
text: "No on-call policies have been configured for this project yet. Please add an on-call policy in the OneUptime Dashboard under On-Call Duty > Policies to use this feature.",
|
|
315
|
+
} as WorkspacePayloadMarkdown,
|
|
316
|
+
],
|
|
317
|
+
authToken: data.slackRequest.projectAuthToken!,
|
|
318
|
+
channelId: data.slackRequest.slackChannelId,
|
|
319
|
+
userId: data.slackRequest.slackUserId!,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
|
|
308
325
|
const onCallPolicyDropdown: WorkspaceDropdownBlock = {
|
|
309
326
|
_type: "WorkspaceDropdownBlock",
|
|
310
327
|
label: "On Call Policy",
|
|
@@ -438,18 +455,16 @@ export default class SlackAlertEpisodeActions {
|
|
|
438
455
|
|
|
439
456
|
const stateId: ObjectID = new ObjectID(stateString);
|
|
440
457
|
|
|
441
|
-
await AlertEpisodeService.
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
458
|
+
await AlertEpisodeService.changeEpisodeState({
|
|
459
|
+
projectId: data.slackRequest.projectId!,
|
|
460
|
+
episodeId: episodeId,
|
|
461
|
+
alertStateId: stateId,
|
|
462
|
+
notifyOwners: true,
|
|
463
|
+
rootCause: "State changed via Slack.",
|
|
464
|
+
props: {
|
|
465
|
+
isRoot: true,
|
|
466
|
+
userId: data.slackRequest.userId!,
|
|
445
467
|
},
|
|
446
|
-
props:
|
|
447
|
-
await AccessTokenService.getDatabaseCommonInteractionPropsByUserAndProject(
|
|
448
|
-
{
|
|
449
|
-
userId: data.slackRequest.userId!,
|
|
450
|
-
projectId: data.slackRequest.projectId!,
|
|
451
|
-
},
|
|
452
|
-
),
|
|
453
468
|
});
|
|
454
469
|
|
|
455
470
|
// Log the button interaction
|
|
@@ -782,6 +782,23 @@ export default class SlackIncidentActions {
|
|
|
782
782
|
return option.label !== "" || option.value !== "";
|
|
783
783
|
});
|
|
784
784
|
|
|
785
|
+
if (dropdownOption.length === 0) {
|
|
786
|
+
if (data.slackRequest.slackChannelId) {
|
|
787
|
+
await SlackUtil.sendEphemeralMessageToChannel({
|
|
788
|
+
messageBlocks: [
|
|
789
|
+
{
|
|
790
|
+
_type: "WorkspacePayloadMarkdown",
|
|
791
|
+
text: "No on-call policies have been configured for this project yet. Please add an on-call policy in the OneUptime Dashboard under On-Call Duty > Policies to use this feature.",
|
|
792
|
+
} as WorkspacePayloadMarkdown,
|
|
793
|
+
],
|
|
794
|
+
authToken: data.slackRequest.projectAuthToken!,
|
|
795
|
+
channelId: data.slackRequest.slackChannelId,
|
|
796
|
+
userId: data.slackRequest.slackUserId!,
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
|
|
785
802
|
const onCallPolicyDropdown: WorkspaceDropdownBlock = {
|
|
786
803
|
_type: "WorkspaceDropdownBlock",
|
|
787
804
|
label: "On Call Policy",
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
WorkspaceTextAreaBlock,
|
|
14
14
|
} from "../../../../../Types/Workspace/WorkspaceMessagePayload";
|
|
15
15
|
import IncidentEpisodeInternalNoteService from "../../../../Services/IncidentEpisodeInternalNoteService";
|
|
16
|
+
import IncidentEpisodePublicNoteService from "../../../../Services/IncidentEpisodePublicNoteService";
|
|
16
17
|
import OnCallDutyPolicy from "../../../../../Models/DatabaseModels/OnCallDutyPolicy";
|
|
17
18
|
import OnCallDutyPolicyService from "../../../../Services/OnCallDutyPolicyService";
|
|
18
19
|
import { LIMIT_PER_PROJECT } from "../../../../../Types/Database/LimitMax";
|
|
@@ -21,7 +22,7 @@ import UserNotificationEventType from "../../../../../Types/UserNotification/Use
|
|
|
21
22
|
import IncidentState from "../../../../../Models/DatabaseModels/IncidentState";
|
|
22
23
|
import IncidentStateService from "../../../../Services/IncidentStateService";
|
|
23
24
|
import logger from "../../../Logger";
|
|
24
|
-
|
|
25
|
+
|
|
25
26
|
import CaptureSpan from "../../../Telemetry/CaptureSpan";
|
|
26
27
|
import WorkspaceNotificationLogService from "../../../../Services/WorkspaceNotificationLogService";
|
|
27
28
|
import WorkspaceUserAuthTokenService from "../../../../Services/WorkspaceUserAuthTokenService";
|
|
@@ -275,9 +276,7 @@ export default class SlackIncidentEpisodeActions {
|
|
|
275
276
|
}
|
|
276
277
|
|
|
277
278
|
// We send this early let slack know we're ok. We'll do the rest in the background.
|
|
278
|
-
Response.
|
|
279
|
-
response_action: "clear",
|
|
280
|
-
});
|
|
279
|
+
Response.sendTextResponse(req, res, "");
|
|
281
280
|
|
|
282
281
|
const onCallPolicies: Array<OnCallDutyPolicy> =
|
|
283
282
|
await OnCallDutyPolicyService.findBy({
|
|
@@ -305,6 +304,23 @@ export default class SlackIncidentEpisodeActions {
|
|
|
305
304
|
return option.label !== "" || option.value !== "";
|
|
306
305
|
});
|
|
307
306
|
|
|
307
|
+
if (dropdownOption.length === 0) {
|
|
308
|
+
if (data.slackRequest.slackChannelId) {
|
|
309
|
+
await SlackUtil.sendEphemeralMessageToChannel({
|
|
310
|
+
messageBlocks: [
|
|
311
|
+
{
|
|
312
|
+
_type: "WorkspacePayloadMarkdown",
|
|
313
|
+
text: "No on-call policies have been configured for this project yet. Please add an on-call policy in the OneUptime Dashboard under On-Call Duty > Policies to use this feature.",
|
|
314
|
+
} as WorkspacePayloadMarkdown,
|
|
315
|
+
],
|
|
316
|
+
authToken: data.slackRequest.projectAuthToken!,
|
|
317
|
+
channelId: data.slackRequest.slackChannelId,
|
|
318
|
+
userId: data.slackRequest.slackUserId!,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
308
324
|
const onCallPolicyDropdown: WorkspaceDropdownBlock = {
|
|
309
325
|
_type: "WorkspaceDropdownBlock",
|
|
310
326
|
label: "On Call Policy",
|
|
@@ -349,9 +365,7 @@ export default class SlackIncidentEpisodeActions {
|
|
|
349
365
|
}
|
|
350
366
|
|
|
351
367
|
// We send this early let slack know we're ok. We'll do the rest in the background.
|
|
352
|
-
Response.
|
|
353
|
-
response_action: "clear",
|
|
354
|
-
});
|
|
368
|
+
Response.sendTextResponse(req, res, "");
|
|
355
369
|
|
|
356
370
|
// Incident Episodes use incident states
|
|
357
371
|
const incidentStates: Array<IncidentState> =
|
|
@@ -438,18 +452,16 @@ export default class SlackIncidentEpisodeActions {
|
|
|
438
452
|
|
|
439
453
|
const stateId: ObjectID = new ObjectID(stateString);
|
|
440
454
|
|
|
441
|
-
await IncidentEpisodeService.
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
455
|
+
await IncidentEpisodeService.changeEpisodeState({
|
|
456
|
+
projectId: data.slackRequest.projectId!,
|
|
457
|
+
episodeId: episodeId,
|
|
458
|
+
incidentStateId: stateId,
|
|
459
|
+
notifyOwners: true,
|
|
460
|
+
rootCause: "State changed via Slack.",
|
|
461
|
+
props: {
|
|
462
|
+
isRoot: true,
|
|
463
|
+
userId: data.slackRequest.userId!,
|
|
445
464
|
},
|
|
446
|
-
props:
|
|
447
|
-
await AccessTokenService.getDatabaseCommonInteractionPropsByUserAndProject(
|
|
448
|
-
{
|
|
449
|
-
userId: data.slackRequest.userId!,
|
|
450
|
-
projectId: data.slackRequest.projectId!,
|
|
451
|
-
},
|
|
452
|
-
),
|
|
453
465
|
});
|
|
454
466
|
|
|
455
467
|
// Log the button interaction
|
|
@@ -610,6 +622,14 @@ export default class SlackIncidentEpisodeActions {
|
|
|
610
622
|
);
|
|
611
623
|
}
|
|
612
624
|
|
|
625
|
+
if (!data.slackRequest.viewValues["noteType"]) {
|
|
626
|
+
return Response.sendErrorResponse(
|
|
627
|
+
req,
|
|
628
|
+
res,
|
|
629
|
+
new BadDataException("Invalid Note Type"),
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
|
|
613
633
|
if (!data.slackRequest.viewValues["note"]) {
|
|
614
634
|
return Response.sendErrorResponse(
|
|
615
635
|
req,
|
|
@@ -620,18 +640,41 @@ export default class SlackIncidentEpisodeActions {
|
|
|
620
640
|
|
|
621
641
|
const episodeId: ObjectID = new ObjectID(actionValue);
|
|
622
642
|
const note: string = data.slackRequest.viewValues["note"].toString();
|
|
643
|
+
const noteType: string =
|
|
644
|
+
data.slackRequest.viewValues["noteType"].toString();
|
|
645
|
+
|
|
646
|
+
if (noteType !== "public" && noteType !== "private") {
|
|
647
|
+
return Response.sendErrorResponse(
|
|
648
|
+
req,
|
|
649
|
+
res,
|
|
650
|
+
new BadDataException("Invalid Note Type"),
|
|
651
|
+
);
|
|
652
|
+
}
|
|
623
653
|
|
|
624
654
|
// send empty response.
|
|
625
655
|
Response.sendJsonObjectResponse(req, res, {
|
|
626
656
|
response_action: "clear",
|
|
627
657
|
});
|
|
628
658
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
659
|
+
// if public note then, add a note.
|
|
660
|
+
if (noteType === "public") {
|
|
661
|
+
await IncidentEpisodePublicNoteService.addNote({
|
|
662
|
+
incidentEpisodeId: episodeId!,
|
|
663
|
+
note: note || "",
|
|
664
|
+
projectId: data.slackRequest.projectId!,
|
|
665
|
+
userId: data.slackRequest.userId!,
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// if private note then, add a note.
|
|
670
|
+
if (noteType === "private") {
|
|
671
|
+
await IncidentEpisodeInternalNoteService.addNote({
|
|
672
|
+
incidentEpisodeId: episodeId!,
|
|
673
|
+
note: note || "",
|
|
674
|
+
projectId: data.slackRequest.projectId!,
|
|
675
|
+
userId: data.slackRequest.userId!,
|
|
676
|
+
});
|
|
677
|
+
}
|
|
635
678
|
}
|
|
636
679
|
|
|
637
680
|
@CaptureSpan()
|
|
@@ -653,9 +696,24 @@ export default class SlackIncidentEpisodeActions {
|
|
|
653
696
|
}
|
|
654
697
|
|
|
655
698
|
// We send this early let slack know we're ok. We'll do the rest in the background.
|
|
656
|
-
Response.
|
|
657
|
-
|
|
658
|
-
|
|
699
|
+
Response.sendTextResponse(req, res, "");
|
|
700
|
+
|
|
701
|
+
const notePickerDropdown: WorkspaceDropdownBlock = {
|
|
702
|
+
_type: "WorkspaceDropdownBlock",
|
|
703
|
+
label: "Note Type",
|
|
704
|
+
blockId: "noteType",
|
|
705
|
+
placeholder: "Select Note Type",
|
|
706
|
+
options: [
|
|
707
|
+
{
|
|
708
|
+
label: "Public Note (Will be posted on Status Page)",
|
|
709
|
+
value: "public",
|
|
710
|
+
},
|
|
711
|
+
{
|
|
712
|
+
label: "Private Note (Only visible to team members)",
|
|
713
|
+
value: "private",
|
|
714
|
+
},
|
|
715
|
+
],
|
|
716
|
+
};
|
|
659
717
|
|
|
660
718
|
const noteTextArea: WorkspaceTextAreaBlock = {
|
|
661
719
|
_type: "WorkspaceTextAreaBlock",
|
|
@@ -672,7 +730,7 @@ export default class SlackIncidentEpisodeActions {
|
|
|
672
730
|
cancelButtonTitle: "Cancel",
|
|
673
731
|
actionId: SlackActionType.SubmitIncidentEpisodeNote,
|
|
674
732
|
actionValue: actionValue,
|
|
675
|
-
blocks: [noteTextArea],
|
|
733
|
+
blocks: [notePickerDropdown, noteTextArea],
|
|
676
734
|
};
|
|
677
735
|
|
|
678
736
|
await SlackUtil.showModalToUser({
|
|
@@ -47,7 +47,7 @@ export default class SlackIncidentEpisodeMessages {
|
|
|
47
47
|
// view data.
|
|
48
48
|
const viewIncidentEpisodeButton: WorkspaceMessagePayloadButton = {
|
|
49
49
|
_type: "WorkspaceMessagePayloadButton",
|
|
50
|
-
title: "View Episode",
|
|
50
|
+
title: "🔗 View Episode",
|
|
51
51
|
url: await IncidentEpisodeService.getEpisodeLinkInDashboard(
|
|
52
52
|
data.projectId!,
|
|
53
53
|
data.incidentEpisodeId!,
|
|
@@ -61,7 +61,7 @@ export default class SlackIncidentEpisodeMessages {
|
|
|
61
61
|
// execute on call.
|
|
62
62
|
const executeOnCallButton: WorkspaceMessagePayloadButton = {
|
|
63
63
|
_type: "WorkspaceMessagePayloadButton",
|
|
64
|
-
title: "Execute On Call",
|
|
64
|
+
title: "📞 Execute On Call",
|
|
65
65
|
value: data.incidentEpisodeId?.toString() || "",
|
|
66
66
|
actionId: SlackActionType.ViewExecuteIncidentEpisodeOnCallPolicy,
|
|
67
67
|
};
|
|
@@ -71,7 +71,7 @@ export default class SlackIncidentEpisodeMessages {
|
|
|
71
71
|
// acknowledge data.
|
|
72
72
|
const acknowledgeIncidentEpisodeButton: WorkspaceMessagePayloadButton = {
|
|
73
73
|
_type: "WorkspaceMessagePayloadButton",
|
|
74
|
-
title: "Acknowledge Episode",
|
|
74
|
+
title: "👀 Acknowledge Episode",
|
|
75
75
|
value: data.incidentEpisodeId?.toString() || "",
|
|
76
76
|
actionId: SlackActionType.AcknowledgeIncidentEpisode,
|
|
77
77
|
};
|
|
@@ -81,7 +81,7 @@ export default class SlackIncidentEpisodeMessages {
|
|
|
81
81
|
// resolve data.
|
|
82
82
|
const resolveIncidentEpisodeButton: WorkspaceMessagePayloadButton = {
|
|
83
83
|
_type: "WorkspaceMessagePayloadButton",
|
|
84
|
-
title: "Resolve Episode",
|
|
84
|
+
title: "✅ Resolve Episode",
|
|
85
85
|
value: data.incidentEpisodeId?.toString() || "",
|
|
86
86
|
actionId: SlackActionType.ResolveIncidentEpisode,
|
|
87
87
|
};
|
|
@@ -91,7 +91,7 @@ export default class SlackIncidentEpisodeMessages {
|
|
|
91
91
|
// change incident episode state.
|
|
92
92
|
const changeIncidentEpisodeStateButton: WorkspaceMessagePayloadButton = {
|
|
93
93
|
_type: "WorkspaceMessagePayloadButton",
|
|
94
|
-
title: "Change Episode State",
|
|
94
|
+
title: "➡️ Change Episode State",
|
|
95
95
|
value: data.incidentEpisodeId?.toString() || "",
|
|
96
96
|
actionId: SlackActionType.ViewChangeIncidentEpisodeState,
|
|
97
97
|
};
|
|
@@ -101,7 +101,7 @@ export default class SlackIncidentEpisodeMessages {
|
|
|
101
101
|
// add note.
|
|
102
102
|
const addNoteButton: WorkspaceMessagePayloadButton = {
|
|
103
103
|
_type: "WorkspaceMessagePayloadButton",
|
|
104
|
-
title: "Add Note",
|
|
104
|
+
title: "📄 Add Note",
|
|
105
105
|
value: data.incidentEpisodeId?.toString() || "",
|
|
106
106
|
actionId: SlackActionType.ViewAddIncidentEpisodeNote,
|
|
107
107
|
};
|