@oneuptime/common 9.2.12 → 9.2.14

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.
Files changed (190) hide show
  1. package/Models/DatabaseModels/AlertInternalNote.ts +29 -0
  2. package/Models/DatabaseModels/IncidentInternalNote.ts +29 -0
  3. package/Models/DatabaseModels/IncidentPublicNote.ts +29 -0
  4. package/Models/DatabaseModels/Index.ts +3 -11
  5. package/Models/DatabaseModels/{CopilotPullRequest.ts → LlmProvider.ts} +243 -248
  6. package/Models/DatabaseModels/ScheduledMaintenanceInternalNote.ts +29 -0
  7. package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +29 -0
  8. package/Server/API/LlmProviderAPI.ts +57 -0
  9. package/Server/API/MicrosoftTeamsAPI.ts +2 -146
  10. package/Server/API/SlackAPI.ts +105 -0
  11. package/Server/API/StatusPageAPI.ts +6 -0
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/1765477339178-MigrationName.ts +71 -0
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1765540325149-MigrationName.ts +45 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1765540549739-MigrationName.ts +61 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/1765544010078-MigrationName.ts +35 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  17. package/Server/Middleware/SlackAuthorization.ts +4 -1
  18. package/Server/Services/AlertInternalNoteService.ts +26 -0
  19. package/Server/Services/IncidentInternalNoteService.ts +26 -0
  20. package/Server/Services/IncidentPublicNoteService.ts +26 -0
  21. package/Server/Services/Index.ts +2 -11
  22. package/Server/Services/LlmProviderService.ts +100 -0
  23. package/Server/Services/ScheduledMaintenanceInternalNoteService.ts +26 -0
  24. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +26 -0
  25. package/Server/Services/StatusPageService.ts +3 -0
  26. package/Server/Utils/Express.ts +1 -0
  27. package/Server/Utils/StartServer.ts +5 -0
  28. package/Server/Utils/StatusPageResource.ts +89 -0
  29. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +96 -55
  30. package/Server/Utils/Workspace/Slack/Actions/ActionTypes.ts +16 -0
  31. package/Server/Utils/Workspace/Slack/Actions/Alert.ts +184 -1
  32. package/Server/Utils/Workspace/Slack/Actions/Incident.ts +224 -1
  33. package/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.ts +232 -1
  34. package/Server/Utils/Workspace/Slack/Slack.ts +113 -0
  35. package/Server/Utils/Workspace/Slack/app-manifest.json +13 -2
  36. package/Tests/Server/Utils/StatusPageResource.test.ts +161 -0
  37. package/Types/Icon/IconProp.ts +1 -0
  38. package/Types/LLM/Index.ts +4 -0
  39. package/Types/LLM/LlmType.ts +7 -0
  40. package/Types/Permission.ts +38 -113
  41. package/UI/Components/Icon/Icon.tsx +8 -0
  42. package/UI/Components/Link/Link.tsx +5 -1
  43. package/build/dist/Models/DatabaseModels/AlertInternalNote.js +30 -0
  44. package/build/dist/Models/DatabaseModels/AlertInternalNote.js.map +1 -1
  45. package/build/dist/Models/DatabaseModels/IncidentInternalNote.js +30 -0
  46. package/build/dist/Models/DatabaseModels/IncidentInternalNote.js.map +1 -1
  47. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +30 -0
  48. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
  49. package/build/dist/Models/DatabaseModels/Index.js +2 -10
  50. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  51. package/build/dist/Models/DatabaseModels/{CopilotPullRequest.js → LlmProvider.js} +263 -255
  52. package/build/dist/Models/DatabaseModels/LlmProvider.js.map +1 -0
  53. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceInternalNote.js +30 -0
  54. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceInternalNote.js.map +1 -1
  55. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +30 -0
  56. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
  57. package/build/dist/Server/API/LlmProviderAPI.js +36 -0
  58. package/build/dist/Server/API/LlmProviderAPI.js.map +1 -0
  59. package/build/dist/Server/API/MicrosoftTeamsAPI.js +2 -91
  60. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  61. package/build/dist/Server/API/SlackAPI.js +74 -0
  62. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  63. package/build/dist/Server/API/StatusPageAPI.js +6 -0
  64. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  65. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765477339178-MigrationName.js +30 -0
  66. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765477339178-MigrationName.js.map +1 -0
  67. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765540325149-MigrationName.js +22 -0
  68. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765540325149-MigrationName.js.map +1 -0
  69. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765540549739-MigrationName.js +39 -0
  70. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765540549739-MigrationName.js.map +1 -0
  71. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765544010078-MigrationName.js +18 -0
  72. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1765544010078-MigrationName.js.map +1 -0
  73. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  74. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  75. package/build/dist/Server/Middleware/SlackAuthorization.js +4 -1
  76. package/build/dist/Server/Middleware/SlackAuthorization.js.map +1 -1
  77. package/build/dist/Server/Services/AlertInternalNoteService.js +24 -0
  78. package/build/dist/Server/Services/AlertInternalNoteService.js.map +1 -1
  79. package/build/dist/Server/Services/IncidentInternalNoteService.js +24 -0
  80. package/build/dist/Server/Services/IncidentInternalNoteService.js.map +1 -1
  81. package/build/dist/Server/Services/IncidentPublicNoteService.js +24 -0
  82. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  83. package/build/dist/Server/Services/Index.js +2 -10
  84. package/build/dist/Server/Services/Index.js.map +1 -1
  85. package/build/dist/Server/Services/LlmProviderService.js +85 -0
  86. package/build/dist/Server/Services/LlmProviderService.js.map +1 -0
  87. package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js +24 -0
  88. package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js.map +1 -1
  89. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +24 -0
  90. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  91. package/build/dist/Server/Services/StatusPageService.js +3 -0
  92. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  93. package/build/dist/Server/Utils/Express.js.map +1 -1
  94. package/build/dist/Server/Utils/StartServer.js +5 -0
  95. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  96. package/build/dist/Server/Utils/StatusPageResource.js +68 -0
  97. package/build/dist/Server/Utils/StatusPageResource.js.map +1 -0
  98. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +73 -42
  99. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  100. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js +13 -0
  101. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js.map +1 -1
  102. package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js +143 -1
  103. package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js.map +1 -1
  104. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js +173 -1
  105. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js.map +1 -1
  106. package/build/dist/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.js +173 -1
  107. package/build/dist/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.js.map +1 -1
  108. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +92 -0
  109. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  110. package/build/dist/Server/Utils/Workspace/Slack/app-manifest.json +12 -2
  111. package/build/dist/Tests/Server/Utils/StatusPageResource.test.js +122 -0
  112. package/build/dist/Tests/Server/Utils/StatusPageResource.test.js.map +1 -0
  113. package/build/dist/Types/Icon/IconProp.js +1 -0
  114. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  115. package/build/dist/Types/LLM/Index.js +4 -0
  116. package/build/dist/Types/LLM/Index.js.map +1 -0
  117. package/build/dist/Types/LLM/LlmType.js +8 -0
  118. package/build/dist/Types/LLM/LlmType.js.map +1 -0
  119. package/build/dist/Types/Permission.js +32 -97
  120. package/build/dist/Types/Permission.js.map +1 -1
  121. package/build/dist/UI/Components/Icon/Icon.js +3 -0
  122. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  123. package/build/dist/UI/Components/Link/Link.js +4 -1
  124. package/build/dist/UI/Components/Link/Link.js.map +1 -1
  125. package/package.json +5 -1
  126. package/Models/DatabaseModels/CopilotAction.ts +0 -772
  127. package/Models/DatabaseModels/CopilotActionTypePriority.ts +0 -340
  128. package/Models/DatabaseModels/CopilotCodeRepository.ts +0 -637
  129. package/Models/DatabaseModels/ServiceCopilotCodeRepository.ts +0 -544
  130. package/Server/API/CopilotActionAPI.ts +0 -418
  131. package/Server/API/CopilotCodeRepositoryAPI.ts +0 -127
  132. package/Server/API/CopilotPullRequestAPI.ts +0 -243
  133. package/Server/Docs/CodeRepository.md +0 -43
  134. package/Server/Middleware/CodeRepositoryAuthorization.ts +0 -50
  135. package/Server/Services/CopilotActionService.ts +0 -10
  136. package/Server/Services/CopilotActionTypePriorityService.ts +0 -67
  137. package/Server/Services/CopilotCodeRepositoryService.ts +0 -62
  138. package/Server/Services/CopilotPullRequestService.ts +0 -10
  139. package/Server/Services/ServiceCopilotCodeRepositoryService.ts +0 -10
  140. package/Types/Copilot/CopilotActionProps/DirectoryActionProp.ts +0 -3
  141. package/Types/Copilot/CopilotActionProps/ExceptionActionProp.ts +0 -4
  142. package/Types/Copilot/CopilotActionProps/FileActionProp.ts +0 -7
  143. package/Types/Copilot/CopilotActionProps/FunctionActionProp.ts +0 -5
  144. package/Types/Copilot/CopilotActionProps/Index.ts +0 -96
  145. package/Types/Copilot/CopilotActionProps/SpanActionProp.ts +0 -4
  146. package/Types/Copilot/CopilotActionStatus.ts +0 -114
  147. package/Types/Copilot/CopilotActionType.ts +0 -212
  148. package/build/dist/Models/DatabaseModels/CopilotAction.js +0 -793
  149. package/build/dist/Models/DatabaseModels/CopilotAction.js.map +0 -1
  150. package/build/dist/Models/DatabaseModels/CopilotActionTypePriority.js +0 -358
  151. package/build/dist/Models/DatabaseModels/CopilotActionTypePriority.js.map +0 -1
  152. package/build/dist/Models/DatabaseModels/CopilotCodeRepository.js +0 -656
  153. package/build/dist/Models/DatabaseModels/CopilotCodeRepository.js.map +0 -1
  154. package/build/dist/Models/DatabaseModels/CopilotPullRequest.js.map +0 -1
  155. package/build/dist/Models/DatabaseModels/ServiceCopilotCodeRepository.js +0 -561
  156. package/build/dist/Models/DatabaseModels/ServiceCopilotCodeRepository.js.map +0 -1
  157. package/build/dist/Server/API/CopilotActionAPI.js +0 -295
  158. package/build/dist/Server/API/CopilotActionAPI.js.map +0 -1
  159. package/build/dist/Server/API/CopilotCodeRepositoryAPI.js +0 -91
  160. package/build/dist/Server/API/CopilotCodeRepositoryAPI.js.map +0 -1
  161. package/build/dist/Server/API/CopilotPullRequestAPI.js +0 -166
  162. package/build/dist/Server/API/CopilotPullRequestAPI.js.map +0 -1
  163. package/build/dist/Server/Middleware/CodeRepositoryAuthorization.js +0 -48
  164. package/build/dist/Server/Middleware/CodeRepositoryAuthorization.js.map +0 -1
  165. package/build/dist/Server/Services/CopilotActionService.js +0 -9
  166. package/build/dist/Server/Services/CopilotActionService.js.map +0 -1
  167. package/build/dist/Server/Services/CopilotActionTypePriorityService.js +0 -61
  168. package/build/dist/Server/Services/CopilotActionTypePriorityService.js.map +0 -1
  169. package/build/dist/Server/Services/CopilotCodeRepositoryService.js +0 -61
  170. package/build/dist/Server/Services/CopilotCodeRepositoryService.js.map +0 -1
  171. package/build/dist/Server/Services/CopilotPullRequestService.js +0 -9
  172. package/build/dist/Server/Services/CopilotPullRequestService.js.map +0 -1
  173. package/build/dist/Server/Services/ServiceCopilotCodeRepositoryService.js +0 -9
  174. package/build/dist/Server/Services/ServiceCopilotCodeRepositoryService.js.map +0 -1
  175. package/build/dist/Types/Copilot/CopilotActionProps/DirectoryActionProp.js +0 -2
  176. package/build/dist/Types/Copilot/CopilotActionProps/DirectoryActionProp.js.map +0 -1
  177. package/build/dist/Types/Copilot/CopilotActionProps/ExceptionActionProp.js +0 -2
  178. package/build/dist/Types/Copilot/CopilotActionProps/ExceptionActionProp.js.map +0 -1
  179. package/build/dist/Types/Copilot/CopilotActionProps/FileActionProp.js +0 -2
  180. package/build/dist/Types/Copilot/CopilotActionProps/FileActionProp.js.map +0 -1
  181. package/build/dist/Types/Copilot/CopilotActionProps/FunctionActionProp.js +0 -2
  182. package/build/dist/Types/Copilot/CopilotActionProps/FunctionActionProp.js.map +0 -1
  183. package/build/dist/Types/Copilot/CopilotActionProps/Index.js +0 -64
  184. package/build/dist/Types/Copilot/CopilotActionProps/Index.js.map +0 -1
  185. package/build/dist/Types/Copilot/CopilotActionProps/SpanActionProp.js +0 -2
  186. package/build/dist/Types/Copilot/CopilotActionProps/SpanActionProp.js.map +0 -1
  187. package/build/dist/Types/Copilot/CopilotActionStatus.js +0 -96
  188. package/build/dist/Types/Copilot/CopilotActionStatus.js.map +0 -1
  189. package/build/dist/Types/Copilot/CopilotActionType.js +0 -175
  190. package/build/dist/Types/Copilot/CopilotActionType.js.map +0 -1
@@ -37,8 +37,11 @@ export default class SlackAuthorization {
37
37
  const timestamp: string = req.headers[
38
38
  "x-slack-request-timestamp"
39
39
  ] as string;
40
+ // Use rawBody for both JSON and URL-encoded requests, fallback to rawFormUrlEncodedBody for backward compatibility
40
41
  const requestBody: string =
41
- (req as OneUptimeRequest).rawFormUrlEncodedBody || "";
42
+ (req as OneUptimeRequest).rawBody ||
43
+ (req as OneUptimeRequest).rawFormUrlEncodedBody ||
44
+ "";
42
45
 
43
46
  logger.debug(`slackSignature: ${slackSignature}`);
44
47
  logger.debug(`timestamp: ${timestamp}`);
@@ -24,6 +24,7 @@ export class Service extends DatabaseService<Model> {
24
24
  projectId: ObjectID;
25
25
  note: string;
26
26
  attachmentFileIds?: Array<ObjectID>;
27
+ postedFromSlackMessageId?: string;
27
28
  }): Promise<Model> {
28
29
  const internalNote: Model = new Model();
29
30
  internalNote.createdByUserId = data.userId;
@@ -31,6 +32,10 @@ export class Service extends DatabaseService<Model> {
31
32
  internalNote.projectId = data.projectId;
32
33
  internalNote.note = data.note;
33
34
 
35
+ if (data.postedFromSlackMessageId) {
36
+ internalNote.postedFromSlackMessageId = data.postedFromSlackMessageId;
37
+ }
38
+
34
39
  if (data.attachmentFileIds && data.attachmentFileIds.length > 0) {
35
40
  internalNote.attachments = data.attachmentFileIds.map(
36
41
  (fileId: ObjectID) => {
@@ -49,6 +54,27 @@ export class Service extends DatabaseService<Model> {
49
54
  });
50
55
  }
51
56
 
57
+ @CaptureSpan()
58
+ public async hasNoteFromSlackMessage(data: {
59
+ alertId: ObjectID;
60
+ postedFromSlackMessageId: string;
61
+ }): Promise<boolean> {
62
+ const existingNote: Model | null = await this.findOneBy({
63
+ query: {
64
+ alertId: data.alertId,
65
+ postedFromSlackMessageId: data.postedFromSlackMessageId,
66
+ },
67
+ select: {
68
+ _id: true,
69
+ },
70
+ props: {
71
+ isRoot: true,
72
+ },
73
+ });
74
+
75
+ return existingNote !== null;
76
+ }
77
+
52
78
  @CaptureSpan()
53
79
  public override async onCreateSuccess(
54
80
  _onCreate: OnCreate<Model>,
@@ -24,6 +24,7 @@ export class Service extends DatabaseService<Model> {
24
24
  projectId: ObjectID;
25
25
  note: string;
26
26
  attachmentFileIds?: Array<ObjectID>;
27
+ postedFromSlackMessageId?: string;
27
28
  }): Promise<Model> {
28
29
  const internalNote: Model = new Model();
29
30
  internalNote.createdByUserId = data.userId;
@@ -31,6 +32,10 @@ export class Service extends DatabaseService<Model> {
31
32
  internalNote.projectId = data.projectId;
32
33
  internalNote.note = data.note;
33
34
 
35
+ if (data.postedFromSlackMessageId) {
36
+ internalNote.postedFromSlackMessageId = data.postedFromSlackMessageId;
37
+ }
38
+
34
39
  if (data.attachmentFileIds && data.attachmentFileIds.length > 0) {
35
40
  internalNote.attachments = data.attachmentFileIds.map(
36
41
  (fileId: ObjectID) => {
@@ -49,6 +54,27 @@ export class Service extends DatabaseService<Model> {
49
54
  });
50
55
  }
51
56
 
57
+ @CaptureSpan()
58
+ public async hasNoteFromSlackMessage(data: {
59
+ incidentId: ObjectID;
60
+ postedFromSlackMessageId: string;
61
+ }): Promise<boolean> {
62
+ const existingNote: Model | null = await this.findOneBy({
63
+ query: {
64
+ incidentId: data.incidentId,
65
+ postedFromSlackMessageId: data.postedFromSlackMessageId,
66
+ },
67
+ select: {
68
+ _id: true,
69
+ },
70
+ props: {
71
+ isRoot: true,
72
+ },
73
+ });
74
+
75
+ return existingNote !== null;
76
+ }
77
+
52
78
  @CaptureSpan()
53
79
  public override async onCreateSuccess(
54
80
  _onCreate: OnCreate<Model>,
@@ -27,6 +27,7 @@ export class Service extends DatabaseService<Model> {
27
27
  projectId: ObjectID;
28
28
  note: string;
29
29
  attachmentFileIds?: Array<ObjectID>;
30
+ postedFromSlackMessageId?: string;
30
31
  }): Promise<Model> {
31
32
  const publicNote: Model = new Model();
32
33
  publicNote.createdByUserId = data.userId;
@@ -35,6 +36,10 @@ export class Service extends DatabaseService<Model> {
35
36
  publicNote.note = data.note;
36
37
  publicNote.postedAt = OneUptimeDate.getCurrentDate();
37
38
 
39
+ if (data.postedFromSlackMessageId) {
40
+ publicNote.postedFromSlackMessageId = data.postedFromSlackMessageId;
41
+ }
42
+
38
43
  if (data.attachmentFileIds && data.attachmentFileIds.length > 0) {
39
44
  publicNote.attachments = data.attachmentFileIds.map(
40
45
  (fileId: ObjectID) => {
@@ -53,6 +58,27 @@ export class Service extends DatabaseService<Model> {
53
58
  });
54
59
  }
55
60
 
61
+ @CaptureSpan()
62
+ public async hasNoteFromSlackMessage(data: {
63
+ incidentId: ObjectID;
64
+ postedFromSlackMessageId: string;
65
+ }): Promise<boolean> {
66
+ const existingNote: Model | null = await this.findOneBy({
67
+ query: {
68
+ incidentId: data.incidentId,
69
+ postedFromSlackMessageId: data.postedFromSlackMessageId,
70
+ },
71
+ select: {
72
+ _id: true,
73
+ },
74
+ props: {
75
+ isRoot: true,
76
+ },
77
+ });
78
+
79
+ return existingNote !== null;
80
+ }
81
+
56
82
  @CaptureSpan()
57
83
  protected override async onBeforeCreate(
58
84
  createBy: CreateBy<Model>,
@@ -11,8 +11,6 @@ import BillingPaymentMethodsService from "./BillingPaymentMethodService";
11
11
  import BillingService from "./BillingService";
12
12
  import CallLogService from "./CallLogService";
13
13
  import CallService from "./CallService";
14
- import CodeRepositoryService from "./CopilotCodeRepositoryService";
15
- import CopilotActionService from "./CopilotActionService";
16
14
  import DataMigrationService from "./DataMigrationService";
17
15
  import DomainService from "./DomainService";
18
16
  import EmailLogService from "./EmailLogService";
@@ -33,6 +31,7 @@ import IncidentStateService from "./IncidentStateService";
33
31
  import IncidentStateTimelineService from "./IncidentStateTimelineService";
34
32
  //Labels.
35
33
  import LabelService from "./LabelService";
34
+ import LlmProviderService from "./LlmProviderService";
36
35
  import LogService from "./LogService";
37
36
  import MailService from "./MailService";
38
37
  import MetricService from "./MetricService";
@@ -88,7 +87,6 @@ import ServiceCatalogOwnerUserService from "./ServiceCatalogOwnerUserService";
88
87
  import ServiceCatalogService from "./ServiceCatalogService";
89
88
  import ServiceCatalogMonitorService from "./ServiceCatalogMonitorService";
90
89
  import ServiceCatalogTelemetryServiceService from "./ServiceCatalogTelemetryServiceService";
91
- import ServiceCopilotCodeRepositoryService from "./ServiceCopilotCodeRepositoryService";
92
90
  import ShortLinkService from "./ShortLinkService";
93
91
  // SMS Log Service
94
92
  import SmsLogService from "./SmsLogService";
@@ -138,11 +136,9 @@ import WorkflowLogService from "./WorkflowLogService";
138
136
  import WorkflowService from "./WorkflowService";
139
137
  import WorkflowVariablesService from "./WorkflowVariableService";
140
138
  import AnalyticsBaseModel from "../../Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
141
- import CopilotPullRequestService from "./CopilotPullRequestService";
142
139
  import ServiceCatalogDependencyService from "./ServiceCatalogDependencyService";
143
140
  import TelemetryExceptionService from "./TelemetryExceptionService";
144
141
  import ExceptionInstanceService from "./ExceptionInstanceService";
145
- import CopilotActionTypePriorityService from "./CopilotActionTypePriorityService";
146
142
  import ScheduledMaintenanceTemplateService from "./ScheduledMaintenanceTemplateService";
147
143
  import ScheduledMaintenanceTemplateOwnerTeamService from "./ScheduledMaintenanceTemplateOwnerTeamService";
148
144
  import ScheduledMaintenanceTemplateOwnerUserService from "./ScheduledMaintenanceTemplateOwnerUserService";
@@ -217,6 +213,7 @@ const services: Array<BaseService> = [
217
213
  IncidentFeedService,
218
214
 
219
215
  LabelService,
216
+ LlmProviderService,
220
217
 
221
218
  MailService,
222
219
  MonitorCustomFieldService,
@@ -325,12 +322,6 @@ const services: Array<BaseService> = [
325
322
  ServiceCatalogMonitorService,
326
323
  ServiceCatalogTelemetryServiceService,
327
324
 
328
- CodeRepositoryService,
329
- CopilotActionService,
330
- ServiceCopilotCodeRepositoryService,
331
- CopilotPullRequestService,
332
- CopilotActionTypePriorityService,
333
-
334
325
  TelemetryExceptionService,
335
326
 
336
327
  // scheduled maintenance templates
@@ -0,0 +1,100 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/LlmProvider";
3
+ import CreateBy from "../Types/Database/CreateBy";
4
+ import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
5
+ import ObjectID from "../../Types/ObjectID";
6
+ import UpdateBy from "../Types/Database/UpdateBy";
7
+ import QueryHelper from "../Types/Database/QueryHelper";
8
+ import LIMIT_MAX from "../../Types/Database/LimitMax";
9
+
10
+ export class Service extends DatabaseService<Model> {
11
+ public constructor() {
12
+ super(Model);
13
+ }
14
+
15
+ protected override async onBeforeCreate(
16
+ createBy: CreateBy<Model>,
17
+ ): Promise<OnCreate<Model>> {
18
+ // When creating a new LLM provider, set it as default by default
19
+ if (createBy.data.isDefault === undefined) {
20
+ createBy.data.isDefault = true;
21
+ }
22
+
23
+ // If this provider is being set as default, unset other defaults in the same project
24
+ if (createBy.data.isDefault && createBy.data.projectId) {
25
+ await this.updateBy({
26
+ query: {
27
+ projectId: createBy.data.projectId,
28
+ isDefault: true,
29
+ },
30
+ data: {
31
+ isDefault: false,
32
+ },
33
+ props: {
34
+ isRoot: true,
35
+ },
36
+ limit: LIMIT_MAX,
37
+ skip: 0,
38
+ });
39
+ }
40
+
41
+ return { createBy, carryForward: null };
42
+ }
43
+
44
+ protected override async onBeforeUpdate(
45
+ updateBy: UpdateBy<Model>,
46
+ ): Promise<OnUpdate<Model>> {
47
+ // If setting isDefault to true, we need to unset other defaults in the same project
48
+ if (updateBy.data.isDefault === true) {
49
+ // Get the items being updated to find their project IDs
50
+ const itemsToUpdate: Array<Model> = await this.findBy({
51
+ query: updateBy.query,
52
+ select: {
53
+ _id: true,
54
+ projectId: true,
55
+ },
56
+ props: {
57
+ isRoot: true,
58
+ },
59
+ limit: LIMIT_MAX,
60
+ skip: 0,
61
+ });
62
+
63
+ // Collect unique project IDs
64
+ const projectIds: Set<string> = new Set();
65
+ const itemIds: Set<string> = new Set();
66
+ for (const item of itemsToUpdate) {
67
+ if (item.projectId) {
68
+ projectIds.add(item.projectId.toString());
69
+ }
70
+ if (item._id) {
71
+ itemIds.add(item._id);
72
+ }
73
+ }
74
+
75
+ // For each project, unset the default on other providers
76
+ for (const projectIdStr of projectIds) {
77
+ const projectId: ObjectID = new ObjectID(projectIdStr);
78
+ await this.updateBy({
79
+ query: {
80
+ projectId: projectId,
81
+ isDefault: true,
82
+ _id: QueryHelper.notInOrNull(Array.from(itemIds)),
83
+ },
84
+ data: {
85
+ isDefault: false,
86
+ },
87
+ props: {
88
+ isRoot: true,
89
+ },
90
+ limit: LIMIT_MAX,
91
+ skip: 0,
92
+ });
93
+ }
94
+ }
95
+
96
+ return { updateBy, carryForward: null };
97
+ }
98
+ }
99
+
100
+ export default new Service();
@@ -24,6 +24,7 @@ export class Service extends DatabaseService<Model> {
24
24
  projectId: ObjectID;
25
25
  note: string;
26
26
  attachmentFileIds?: Array<ObjectID>;
27
+ postedFromSlackMessageId?: string;
27
28
  }): Promise<Model> {
28
29
  const internalNote: Model = new Model();
29
30
  internalNote.createdByUserId = data.userId;
@@ -31,6 +32,10 @@ export class Service extends DatabaseService<Model> {
31
32
  internalNote.projectId = data.projectId;
32
33
  internalNote.note = data.note;
33
34
 
35
+ if (data.postedFromSlackMessageId) {
36
+ internalNote.postedFromSlackMessageId = data.postedFromSlackMessageId;
37
+ }
38
+
34
39
  if (data.attachmentFileIds && data.attachmentFileIds.length > 0) {
35
40
  internalNote.attachments = data.attachmentFileIds.map(
36
41
  (fileId: ObjectID) => {
@@ -49,6 +54,27 @@ export class Service extends DatabaseService<Model> {
49
54
  });
50
55
  }
51
56
 
57
+ @CaptureSpan()
58
+ public async hasNoteFromSlackMessage(data: {
59
+ scheduledMaintenanceId: ObjectID;
60
+ postedFromSlackMessageId: string;
61
+ }): Promise<boolean> {
62
+ const existingNote: Model | null = await this.findOneBy({
63
+ query: {
64
+ scheduledMaintenanceId: data.scheduledMaintenanceId,
65
+ postedFromSlackMessageId: data.postedFromSlackMessageId,
66
+ },
67
+ select: {
68
+ _id: true,
69
+ },
70
+ props: {
71
+ isRoot: true,
72
+ },
73
+ });
74
+
75
+ return existingNote !== null;
76
+ }
77
+
52
78
  @CaptureSpan()
53
79
  public override async onCreateSuccess(
54
80
  _onCreate: OnCreate<Model>,
@@ -162,6 +162,7 @@ ${(updatedItem.note || "") + attachmentsMarkdown}
162
162
  projectId: ObjectID;
163
163
  note: string;
164
164
  attachmentFileIds?: Array<ObjectID>;
165
+ postedFromSlackMessageId?: string;
165
166
  }): Promise<Model> {
166
167
  const publicNote: Model = new Model();
167
168
  publicNote.createdByUserId = data.userId;
@@ -170,6 +171,10 @@ ${(updatedItem.note || "") + attachmentsMarkdown}
170
171
  publicNote.note = data.note;
171
172
  publicNote.postedAt = OneUptimeDate.getCurrentDate();
172
173
 
174
+ if (data.postedFromSlackMessageId) {
175
+ publicNote.postedFromSlackMessageId = data.postedFromSlackMessageId;
176
+ }
177
+
173
178
  if (data.attachmentFileIds && data.attachmentFileIds.length > 0) {
174
179
  publicNote.attachments = data.attachmentFileIds.map(
175
180
  (fileId: ObjectID) => {
@@ -188,6 +193,27 @@ ${(updatedItem.note || "") + attachmentsMarkdown}
188
193
  });
189
194
  }
190
195
 
196
+ @CaptureSpan()
197
+ public async hasNoteFromSlackMessage(data: {
198
+ scheduledMaintenanceId: ObjectID;
199
+ postedFromSlackMessageId: string;
200
+ }): Promise<boolean> {
201
+ const existingNote: Model | null = await this.findOneBy({
202
+ query: {
203
+ scheduledMaintenanceId: data.scheduledMaintenanceId,
204
+ postedFromSlackMessageId: data.postedFromSlackMessageId,
205
+ },
206
+ select: {
207
+ _id: true,
208
+ },
209
+ props: {
210
+ isRoot: true,
211
+ },
212
+ });
213
+
214
+ return existingNote !== null;
215
+ }
216
+
191
217
  private async getAttachmentsMarkdown(
192
218
  modelId: ObjectID,
193
219
  attachmentApiPath: string,
@@ -1193,6 +1193,9 @@ export class Service extends DatabaseService<StatusPage> {
1193
1193
  },
1194
1194
  select: {
1195
1195
  statusPageGroupId: true,
1196
+ statusPageGroup: {
1197
+ name: true,
1198
+ },
1196
1199
  monitorId: true,
1197
1200
  displayTooltip: true,
1198
1201
  displayDescription: true,
@@ -40,6 +40,7 @@ export interface OneUptimeRequest extends express.Request {
40
40
  userGlobalAccessPermission?: UserGlobalAccessPermission;
41
41
  userTenantAccessPermission?: Dictionary<UserTenantAccessPermission>; // tenantId <-> UserTenantAccessPermission;
42
42
  rawFormUrlEncodedBody?: string;
43
+ rawBody?: string; // Raw body for signature verification (JSON or URL-encoded)
43
44
  }
44
45
 
45
46
  export interface OneUptimeResponse extends express.Response {
@@ -50,6 +50,10 @@ app.use(CookieParser());
50
50
  const jsonBodyParserMiddleware: RequestHandler = ExpressJson({
51
51
  limit: "50mb",
52
52
  extended: true,
53
+ verify: (req: ExpressRequest, _res: ExpressResponse, buf: Buffer) => {
54
+ (req as OneUptimeRequest).rawBody = buf.toString();
55
+ logger.debug(`Raw JSON Body for signature verification captured`);
56
+ },
53
57
  }); // 50 MB limit.
54
58
 
55
59
  const urlEncodedMiddleware: RequestHandler = ExpressUrlEncoded({
@@ -57,6 +61,7 @@ const urlEncodedMiddleware: RequestHandler = ExpressUrlEncoded({
57
61
  extended: true,
58
62
  verify: (req: ExpressRequest, _res: ExpressResponse, buf: Buffer) => {
59
63
  (req as OneUptimeRequest).rawFormUrlEncodedBody = buf.toString();
64
+ (req as OneUptimeRequest).rawBody = buf.toString(); // Also set rawBody for consistency
60
65
  logger.debug(
61
66
  `Raw Form Url Encoded Body: ${(req as OneUptimeRequest).rawFormUrlEncodedBody}`,
62
67
  );
@@ -0,0 +1,89 @@
1
+ import StatusPageResource from "../../Models/DatabaseModels/StatusPageResource";
2
+ import Dictionary from "../../Types/Dictionary";
3
+
4
+ export interface GetResourcesGroupedByGroupNameOptions {
5
+ resources: Array<StatusPageResource>;
6
+ defaultValue?: string;
7
+ }
8
+
9
+ export default class StatusPageResourceUtil {
10
+ /**
11
+ * Formats an array of StatusPageResource items into a string grouped by their resource group.
12
+ *
13
+ * If resources have no group or only one resource exists without a group, returns a simple comma-separated list.
14
+ * If resources are grouped, returns a formatted string like:
15
+ * "EU: Infrastructure, Website; UK: Infrastructure, API"
16
+ *
17
+ * @param resources - Array of StatusPageResource items with displayName, statusPageGroupId, and optionally statusPageGroup.name
18
+ * @param defaultValue - Value to return if no resources (defaults to "None")
19
+ * @returns Formatted string of resources grouped by their resource group
20
+ */
21
+ public static getResourcesGroupedByGroupName(
22
+ resources: Array<StatusPageResource>,
23
+ defaultValue: string = "",
24
+ ): string {
25
+ if (!resources || resources.length === 0) {
26
+ return defaultValue;
27
+ }
28
+
29
+ // Check if any resource has a group
30
+ const hasAnyGroup: boolean = resources.some((r: StatusPageResource) => {
31
+ return r.statusPageGroupId || r.statusPageGroup;
32
+ });
33
+
34
+ // If no resources have groups, return simple comma-separated list
35
+ if (!hasAnyGroup) {
36
+ return (
37
+ resources
38
+ .map((r: StatusPageResource) => {
39
+ return r.displayName;
40
+ })
41
+ .filter((name: string | undefined) => {
42
+ return name;
43
+ })
44
+ .join(", ") || ""
45
+ );
46
+ }
47
+
48
+ // Group resources by their group name
49
+ const resourcesByGroup: Dictionary<Array<string>> = {};
50
+ const ungroupedResources: Array<string> = [];
51
+
52
+ for (const resource of resources) {
53
+ const displayName: string | undefined = resource.displayName;
54
+ if (!displayName) {
55
+ continue;
56
+ }
57
+
58
+ const groupName: string | undefined =
59
+ resource.statusPageGroup?.name || undefined;
60
+
61
+ if (groupName) {
62
+ if (!resourcesByGroup[groupName]) {
63
+ resourcesByGroup[groupName] = [];
64
+ }
65
+ resourcesByGroup[groupName]!.push(displayName);
66
+ } else {
67
+ ungroupedResources.push(displayName);
68
+ }
69
+ }
70
+
71
+ // Build the formatted string
72
+ const formattedGroups: Array<string> = [];
73
+
74
+ // Add grouped resources
75
+ for (const groupName in resourcesByGroup) {
76
+ const groupResources: Array<string> = resourcesByGroup[groupName]!;
77
+ formattedGroups.push(`${groupName}: ${groupResources.join(", ")}`);
78
+ }
79
+
80
+ // Add ungrouped resources on separate lines (without "Other" label)
81
+ if (ungroupedResources.length > 0) {
82
+ for (const resourceName of ungroupedResources) {
83
+ formattedGroups.push(resourceName);
84
+ }
85
+ }
86
+
87
+ return formattedGroups.join("<br/>") || defaultValue;
88
+ }
89
+ }