@oneuptime/common 8.0.5579 → 8.0.5581

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 (181) hide show
  1. package/Models/DatabaseModels/AlertInternalNote.ts +58 -1
  2. package/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +1 -0
  3. package/Models/DatabaseModels/File.ts +1 -1
  4. package/Models/DatabaseModels/IncidentInternalNote.ts +58 -1
  5. package/Models/DatabaseModels/IncidentPublicNote.ts +58 -1
  6. package/Models/DatabaseModels/ScheduledMaintenanceInternalNote.ts +58 -1
  7. package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +58 -1
  8. package/Models/DatabaseModels/StatusPageAnnouncement.ts +49 -0
  9. package/Server/API/AlertInternalNoteAPI.ts +96 -0
  10. package/Server/API/IncidentInternalNoteAPI.ts +96 -0
  11. package/Server/API/IncidentPublicNoteAPI.ts +96 -0
  12. package/Server/API/ScheduledMaintenanceInternalNoteAPI.ts +100 -0
  13. package/Server/API/ScheduledMaintenancePublicNoteAPI.ts +100 -0
  14. package/Server/API/StatusPageAPI.ts +585 -59
  15. package/Server/API/StatusPageAnnouncementAPI.ts +98 -0
  16. package/Server/API/UserAPI.ts +95 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1763471659817-MigrationName.ts +79 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1763477560906-MigrationName.ts +81 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/1763480947474-MigrationName.ts +79 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  21. package/Server/Middleware/ProjectAuthorization.ts +3 -1
  22. package/Server/Services/AlertInternalNoteService.ts +75 -2
  23. package/Server/Services/IncidentInternalNoteService.ts +76 -2
  24. package/Server/Services/IncidentPublicNoteService.ts +76 -2
  25. package/Server/Services/ScheduledMaintenanceInternalNoteService.ts +76 -2
  26. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +76 -2
  27. package/Server/Services/ScheduledMaintenanceService.ts +10 -7
  28. package/Server/Services/StatusPagePrivateUserService.ts +10 -7
  29. package/Server/Services/StatusPageService.ts +12 -7
  30. package/Server/Services/StatusPageSubscriberService.ts +19 -13
  31. package/Server/Utils/FileAttachmentMarkdownUtil.ts +98 -0
  32. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +9 -1
  33. package/Server/Utils/Monitor/Criteria/ExceptionMonitorCriteria.ts +34 -0
  34. package/Server/Utils/Monitor/DataToProcess.ts +3 -1
  35. package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +13 -0
  36. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +13 -0
  37. package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +20 -0
  38. package/Server/Utils/Monitor/MonitorResource.ts +18 -0
  39. package/Server/Utils/Response.ts +13 -0
  40. package/Server/Utils/Telemetry.ts +15 -0
  41. package/Types/File/MimeType.ts +18 -0
  42. package/Types/Monitor/CriteriaFilter.ts +3 -0
  43. package/Types/Monitor/ExceptionMonitor/ExceptionMonitorResponse.ts +12 -0
  44. package/Types/Monitor/MonitorCriteriaInstance.ts +67 -0
  45. package/Types/Monitor/MonitorStep.ts +30 -0
  46. package/Types/Monitor/MonitorStepExceptionMonitor.ts +94 -0
  47. package/Types/Monitor/MonitorType.ts +10 -1
  48. package/Types/Telemetry/TelemetryQuery.ts +2 -1
  49. package/Types/Telemetry/TelemetryType.ts +1 -0
  50. package/UI/Components/AttachmentList/EventAttachmentList.tsx +121 -0
  51. package/UI/Components/EventItem/EventItem.tsx +22 -0
  52. package/UI/Components/Feed/FeedItem.tsx +9 -16
  53. package/UI/Components/FilePicker/FilePicker.tsx +441 -145
  54. package/UI/Components/Forms/Fields/FormField.tsx +32 -15
  55. package/UI/Components/Forms/FormSummary.tsx +168 -1
  56. package/UI/Components/Forms/ModelForm.tsx +46 -24
  57. package/UI/Components/Forms/Types/FormFieldSchemaType.ts +1 -0
  58. package/UI/Components/Icon/Icon.tsx +1 -1
  59. package/UI/Utils/API/RequestOptions.ts +2 -0
  60. package/UI/Utils/ModelAPI/ModelAPI.ts +18 -0
  61. package/UI/Utils/User.ts +8 -0
  62. package/Utils/API.ts +11 -1
  63. package/build/dist/Models/DatabaseModels/AlertInternalNote.js +49 -1
  64. package/build/dist/Models/DatabaseModels/AlertInternalNote.js.map +1 -1
  65. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +1 -0
  66. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
  67. package/build/dist/Models/DatabaseModels/File.js +1 -1
  68. package/build/dist/Models/DatabaseModels/File.js.map +1 -1
  69. package/build/dist/Models/DatabaseModels/IncidentInternalNote.js +49 -1
  70. package/build/dist/Models/DatabaseModels/IncidentInternalNote.js.map +1 -1
  71. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +49 -1
  72. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
  73. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceInternalNote.js +49 -1
  74. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceInternalNote.js.map +1 -1
  75. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +49 -1
  76. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
  77. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +48 -0
  78. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
  79. package/build/dist/Server/API/AlertInternalNoteAPI.js +68 -0
  80. package/build/dist/Server/API/AlertInternalNoteAPI.js.map +1 -0
  81. package/build/dist/Server/API/IncidentInternalNoteAPI.js +68 -0
  82. package/build/dist/Server/API/IncidentInternalNoteAPI.js.map +1 -0
  83. package/build/dist/Server/API/IncidentPublicNoteAPI.js +68 -0
  84. package/build/dist/Server/API/IncidentPublicNoteAPI.js.map +1 -0
  85. package/build/dist/Server/API/ScheduledMaintenanceInternalNoteAPI.js +68 -0
  86. package/build/dist/Server/API/ScheduledMaintenanceInternalNoteAPI.js.map +1 -0
  87. package/build/dist/Server/API/ScheduledMaintenancePublicNoteAPI.js +68 -0
  88. package/build/dist/Server/API/ScheduledMaintenancePublicNoteAPI.js.map +1 -0
  89. package/build/dist/Server/API/StatusPageAPI.js +488 -85
  90. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  91. package/build/dist/Server/API/StatusPageAnnouncementAPI.js +68 -0
  92. package/build/dist/Server/API/StatusPageAnnouncementAPI.js.map +1 -0
  93. package/build/dist/Server/API/UserAPI.js +66 -0
  94. package/build/dist/Server/API/UserAPI.js.map +1 -0
  95. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763471659817-MigrationName.js +34 -0
  96. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763471659817-MigrationName.js.map +1 -0
  97. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763477560906-MigrationName.js +34 -0
  98. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763477560906-MigrationName.js.map +1 -0
  99. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763480947474-MigrationName.js +34 -0
  100. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763480947474-MigrationName.js.map +1 -0
  101. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  102. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  103. package/build/dist/Server/Middleware/ProjectAuthorization.js +4 -1
  104. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  105. package/build/dist/Server/Services/AlertInternalNoteService.js +54 -2
  106. package/build/dist/Server/Services/AlertInternalNoteService.js.map +1 -1
  107. package/build/dist/Server/Services/IncidentInternalNoteService.js +54 -2
  108. package/build/dist/Server/Services/IncidentInternalNoteService.js.map +1 -1
  109. package/build/dist/Server/Services/IncidentPublicNoteService.js +54 -2
  110. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  111. package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js +54 -2
  112. package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js.map +1 -1
  113. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +54 -2
  114. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  115. package/build/dist/Server/Services/ScheduledMaintenanceService.js +6 -5
  116. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  117. package/build/dist/Server/Services/StatusPagePrivateUserService.js +6 -4
  118. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  119. package/build/dist/Server/Services/StatusPageService.js +7 -4
  120. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  121. package/build/dist/Server/Services/StatusPageSubscriberService.js +11 -7
  122. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  123. package/build/dist/Server/Utils/FileAttachmentMarkdownUtil.js +67 -0
  124. package/build/dist/Server/Utils/FileAttachmentMarkdownUtil.js.map +1 -0
  125. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +6 -1
  126. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
  127. package/build/dist/Server/Utils/Monitor/Criteria/ExceptionMonitorCriteria.js +34 -0
  128. package/build/dist/Server/Utils/Monitor/Criteria/ExceptionMonitorCriteria.js.map +1 -0
  129. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js +6 -0
  130. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js.map +1 -1
  131. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +10 -0
  132. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  133. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +9 -0
  134. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
  135. package/build/dist/Server/Utils/Monitor/MonitorResource.js +10 -0
  136. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  137. package/build/dist/Server/Utils/Response.js +8 -0
  138. package/build/dist/Server/Utils/Response.js.map +1 -1
  139. package/build/dist/Server/Utils/Telemetry.js +8 -1
  140. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  141. package/build/dist/Types/File/MimeType.js +18 -0
  142. package/build/dist/Types/File/MimeType.js.map +1 -1
  143. package/build/dist/Types/Monitor/CriteriaFilter.js +2 -0
  144. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  145. package/build/dist/Types/Monitor/ExceptionMonitor/ExceptionMonitorResponse.js +2 -0
  146. package/build/dist/Types/Monitor/ExceptionMonitor/ExceptionMonitorResponse.js.map +1 -0
  147. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +62 -0
  148. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  149. package/build/dist/Types/Monitor/MonitorStep.js +20 -1
  150. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  151. package/build/dist/Types/Monitor/MonitorStepExceptionMonitor.js +58 -0
  152. package/build/dist/Types/Monitor/MonitorStepExceptionMonitor.js.map +1 -0
  153. package/build/dist/Types/Monitor/MonitorType.js +9 -1
  154. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  155. package/build/dist/Types/Telemetry/TelemetryType.js +1 -0
  156. package/build/dist/Types/Telemetry/TelemetryType.js.map +1 -1
  157. package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js +42 -0
  158. package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js.map +1 -0
  159. package/build/dist/UI/Components/EventItem/EventItem.js +5 -1
  160. package/build/dist/UI/Components/EventItem/EventItem.js.map +1 -1
  161. package/build/dist/UI/Components/Feed/FeedItem.js +6 -4
  162. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
  163. package/build/dist/UI/Components/FilePicker/FilePicker.js +262 -77
  164. package/build/dist/UI/Components/FilePicker/FilePicker.js.map +1 -1
  165. package/build/dist/UI/Components/Forms/Fields/FormField.js +24 -12
  166. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  167. package/build/dist/UI/Components/Forms/FormSummary.js +77 -1
  168. package/build/dist/UI/Components/Forms/FormSummary.js.map +1 -1
  169. package/build/dist/UI/Components/Forms/ModelForm.js +32 -18
  170. package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
  171. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js +1 -0
  172. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js.map +1 -1
  173. package/build/dist/UI/Components/Icon/Icon.js +1 -1
  174. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  175. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +30 -45
  176. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  177. package/build/dist/UI/Utils/User.js +7 -0
  178. package/build/dist/UI/Utils/User.js.map +1 -1
  179. package/build/dist/Utils/API.js +3 -0
  180. package/build/dist/Utils/API.js.map +1 -1
  181. package/package.json +6 -6
@@ -0,0 +1,98 @@
1
+ import StatusPageAnnouncement from "../../Models/DatabaseModels/StatusPageAnnouncement";
2
+ import File from "../../Models/DatabaseModels/File";
3
+ import NotFoundException from "../../Types/Exception/NotFoundException";
4
+ import ObjectID from "../../Types/ObjectID";
5
+ import StatusPageAnnouncementService, {
6
+ Service as StatusPageAnnouncementServiceType,
7
+ } from "../Services/StatusPageAnnouncementService";
8
+ import Response from "../Utils/Response";
9
+ import BaseAPI from "./BaseAPI";
10
+ import UserMiddleware from "../Middleware/UserAuthorization";
11
+ import CommonAPI from "./CommonAPI";
12
+ import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
13
+ import {
14
+ ExpressRequest,
15
+ ExpressResponse,
16
+ NextFunction,
17
+ } from "../Utils/Express";
18
+
19
+ export default class StatusPageAnnouncementAPI extends BaseAPI<
20
+ StatusPageAnnouncement,
21
+ StatusPageAnnouncementServiceType
22
+ > {
23
+ public constructor() {
24
+ super(StatusPageAnnouncement, StatusPageAnnouncementService);
25
+
26
+ this.router.get(
27
+ `${new this.entityType().getCrudApiPath()?.toString()}/attachment/:projectId/:announcementId/:fileId`,
28
+ UserMiddleware.getUserMiddleware,
29
+ async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
30
+ try {
31
+ await this.getAttachment(req, res);
32
+ } catch (err) {
33
+ next(err);
34
+ }
35
+ },
36
+ );
37
+ }
38
+
39
+ private async getAttachment(
40
+ req: ExpressRequest,
41
+ res: ExpressResponse,
42
+ ): Promise<void> {
43
+ const announcementIdParam: string | undefined =
44
+ req.params["announcementId"];
45
+ const fileIdParam: string | undefined = req.params["fileId"];
46
+
47
+ if (!announcementIdParam || !fileIdParam) {
48
+ throw new NotFoundException("Attachment not found");
49
+ }
50
+
51
+ let announcementId: ObjectID;
52
+ let fileId: ObjectID;
53
+
54
+ try {
55
+ announcementId = new ObjectID(announcementIdParam);
56
+ fileId = new ObjectID(fileIdParam);
57
+ } catch {
58
+ throw new NotFoundException("Attachment not found");
59
+ }
60
+
61
+ const props: DatabaseCommonInteractionProps =
62
+ await CommonAPI.getDatabaseCommonInteractionProps(req);
63
+
64
+ const announcement: StatusPageAnnouncement | null =
65
+ await this.service.findOneBy({
66
+ query: {
67
+ _id: announcementId,
68
+ },
69
+ select: {
70
+ attachments: {
71
+ _id: true,
72
+ file: true,
73
+ fileType: true,
74
+ name: true,
75
+ },
76
+ },
77
+ props,
78
+ });
79
+
80
+ const attachment: File | undefined = announcement?.attachments?.find(
81
+ (file: File) => {
82
+ const attachmentId: string | null = file._id
83
+ ? file._id.toString()
84
+ : file.id
85
+ ? file.id.toString()
86
+ : null;
87
+ return attachmentId === fileId.toString();
88
+ },
89
+ );
90
+
91
+ if (!attachment || !attachment.file) {
92
+ throw new NotFoundException("Attachment not found");
93
+ }
94
+
95
+ Response.setNoCacheHeaders(res);
96
+ return Response.sendFileResponse(req, res, attachment);
97
+ }
98
+ }
@@ -0,0 +1,95 @@
1
+ import User from "../../Models/DatabaseModels/User";
2
+ import NotFoundException from "../../Types/Exception/NotFoundException";
3
+ import ObjectID from "../../Types/ObjectID";
4
+ import UserService, {
5
+ Service as UserServiceType,
6
+ } from "../Services/UserService";
7
+ import { ExpressRequest, ExpressResponse } from "../Utils/Express";
8
+ import logger from "../Utils/Logger";
9
+ import Response from "../Utils/Response";
10
+ import BaseAPI from "./BaseAPI";
11
+
12
+ const BLANK_PROFILE_PICTURE_PATH: string =
13
+ "/usr/src/Common/UI/Images/users/blank-profile.svg";
14
+
15
+ export default class UserAPI extends BaseAPI<User, UserServiceType> {
16
+ public constructor() {
17
+ super(User, UserService);
18
+
19
+ this.router.get(
20
+ `${new this.entityType().getCrudApiPath()?.toString()}/profile-picture/:userId`,
21
+ async (req: ExpressRequest, res: ExpressResponse) => {
22
+ const userIdParam: string | undefined = req.params["userId"];
23
+
24
+ if (!userIdParam) {
25
+ return this.sendBlankProfile(req, res);
26
+ }
27
+
28
+ let userId: ObjectID;
29
+
30
+ try {
31
+ userId = new ObjectID(userIdParam);
32
+ } catch {
33
+ return this.sendBlankProfile(req, res);
34
+ }
35
+
36
+ try {
37
+ const profilePictureSelect: {
38
+ profilePictureFile: {
39
+ _id: boolean;
40
+ file: boolean;
41
+ fileType: boolean;
42
+ name: boolean;
43
+ };
44
+ } = {
45
+ profilePictureFile: {
46
+ _id: true,
47
+ file: true,
48
+ fileType: true,
49
+ name: true,
50
+ },
51
+ };
52
+
53
+ const userById: User | null = await UserService.findOneBy({
54
+ query: {
55
+ _id: userId,
56
+ },
57
+ select: profilePictureSelect,
58
+ props: {
59
+ isRoot: true,
60
+ },
61
+ });
62
+
63
+ if (userById && userById.profilePictureFile) {
64
+ Response.setNoCacheHeaders(res);
65
+ return Response.sendFileResponse(
66
+ req,
67
+ res,
68
+ userById.profilePictureFile,
69
+ );
70
+ }
71
+
72
+ return this.sendBlankProfile(req, res);
73
+ } catch (error) {
74
+ logger.error(error);
75
+ return this.sendBlankProfile(req, res);
76
+ }
77
+ },
78
+ );
79
+ }
80
+
81
+ private sendBlankProfile(req: ExpressRequest, res: ExpressResponse): void {
82
+ Response.setNoCacheHeaders(res);
83
+
84
+ try {
85
+ Response.sendFileByPath(req, res, BLANK_PROFILE_PICTURE_PATH);
86
+ } catch (error) {
87
+ logger.error(error);
88
+ Response.sendErrorResponse(
89
+ req,
90
+ res,
91
+ new NotFoundException("User profile picture not found"),
92
+ );
93
+ }
94
+ }
95
+ }
@@ -0,0 +1,79 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class MigrationName1763471659817 implements MigrationInterface {
4
+ public name = "MigrationName1763471659817";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `CREATE TABLE "IncidentInternalNoteFile" ("incidentInternalNoteId" uuid NOT NULL, "fileId" uuid NOT NULL, CONSTRAINT "PK_1e97a749db84f9dc65ee162dd6b" PRIMARY KEY ("incidentInternalNoteId", "fileId"))`,
9
+ );
10
+ await queryRunner.query(
11
+ `CREATE INDEX "IDX_0edb0291ff3e97197269d77dc4" ON "IncidentInternalNoteFile" ("incidentInternalNoteId") `,
12
+ );
13
+ await queryRunner.query(
14
+ `CREATE INDEX "IDX_b30b49d21a553c06bd0ff3acf5" ON "IncidentInternalNoteFile" ("fileId") `,
15
+ );
16
+ await queryRunner.query(
17
+ `CREATE TABLE "IncidentPublicNoteFile" ("incidentPublicNoteId" uuid NOT NULL, "fileId" uuid NOT NULL, CONSTRAINT "PK_42d2fe75b663f8fa20421f31e78" PRIMARY KEY ("incidentPublicNoteId", "fileId"))`,
18
+ );
19
+ await queryRunner.query(
20
+ `CREATE INDEX "IDX_e5c4a5671b2bb51a9918f1f203" ON "IncidentPublicNoteFile" ("incidentPublicNoteId") `,
21
+ );
22
+ await queryRunner.query(
23
+ `CREATE INDEX "IDX_81a5bc92f59cb5577746ee51ba" ON "IncidentPublicNoteFile" ("fileId") `,
24
+ );
25
+ await queryRunner.query(
26
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
27
+ );
28
+ await queryRunner.query(
29
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
30
+ );
31
+ await queryRunner.query(
32
+ `ALTER TABLE "IncidentInternalNoteFile" ADD CONSTRAINT "FK_0edb0291ff3e97197269d77dc48" FOREIGN KEY ("incidentInternalNoteId") REFERENCES "IncidentInternalNote"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
33
+ );
34
+ await queryRunner.query(
35
+ `ALTER TABLE "IncidentInternalNoteFile" ADD CONSTRAINT "FK_b30b49d21a553c06bd0ff3acf5f" FOREIGN KEY ("fileId") REFERENCES "File"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
36
+ );
37
+ await queryRunner.query(
38
+ `ALTER TABLE "IncidentPublicNoteFile" ADD CONSTRAINT "FK_e5c4a5671b2bb51a9918f1f203d" FOREIGN KEY ("incidentPublicNoteId") REFERENCES "IncidentPublicNote"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
39
+ );
40
+ await queryRunner.query(
41
+ `ALTER TABLE "IncidentPublicNoteFile" ADD CONSTRAINT "FK_81a5bc92f59cb5577746ee51baf" FOREIGN KEY ("fileId") REFERENCES "File"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
42
+ );
43
+ }
44
+
45
+ public async down(queryRunner: QueryRunner): Promise<void> {
46
+ await queryRunner.query(
47
+ `ALTER TABLE "IncidentPublicNoteFile" DROP CONSTRAINT "FK_81a5bc92f59cb5577746ee51baf"`,
48
+ );
49
+ await queryRunner.query(
50
+ `ALTER TABLE "IncidentPublicNoteFile" DROP CONSTRAINT "FK_e5c4a5671b2bb51a9918f1f203d"`,
51
+ );
52
+ await queryRunner.query(
53
+ `ALTER TABLE "IncidentInternalNoteFile" DROP CONSTRAINT "FK_b30b49d21a553c06bd0ff3acf5f"`,
54
+ );
55
+ await queryRunner.query(
56
+ `ALTER TABLE "IncidentInternalNoteFile" DROP CONSTRAINT "FK_0edb0291ff3e97197269d77dc48"`,
57
+ );
58
+ await queryRunner.query(
59
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
60
+ );
61
+ await queryRunner.query(
62
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
63
+ );
64
+ await queryRunner.query(
65
+ `DROP INDEX "public"."IDX_81a5bc92f59cb5577746ee51ba"`,
66
+ );
67
+ await queryRunner.query(
68
+ `DROP INDEX "public"."IDX_e5c4a5671b2bb51a9918f1f203"`,
69
+ );
70
+ await queryRunner.query(`DROP TABLE "IncidentPublicNoteFile"`);
71
+ await queryRunner.query(
72
+ `DROP INDEX "public"."IDX_b30b49d21a553c06bd0ff3acf5"`,
73
+ );
74
+ await queryRunner.query(
75
+ `DROP INDEX "public"."IDX_0edb0291ff3e97197269d77dc4"`,
76
+ );
77
+ await queryRunner.query(`DROP TABLE "IncidentInternalNoteFile"`);
78
+ }
79
+ }
@@ -0,0 +1,81 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class MigrationName1763477560906 implements MigrationInterface {
4
+ public name = "MigrationName1763477560906";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `CREATE TABLE "ScheduledMaintenanceInternalNoteFile" ("scheduledMaintenanceInternalNoteId" uuid NOT NULL, "fileId" uuid NOT NULL, CONSTRAINT "PK_fddb744dc7cf400724befe5ba91" PRIMARY KEY ("scheduledMaintenanceInternalNoteId", "fileId"))`,
9
+ );
10
+ await queryRunner.query(
11
+ `CREATE INDEX "IDX_ac92a60535a6d598c9619fd199" ON "ScheduledMaintenanceInternalNoteFile" ("scheduledMaintenanceInternalNoteId") `,
12
+ );
13
+ await queryRunner.query(
14
+ `CREATE INDEX "IDX_daee340befeece208b507a4242" ON "ScheduledMaintenanceInternalNoteFile" ("fileId") `,
15
+ );
16
+ await queryRunner.query(
17
+ `CREATE TABLE "ScheduledMaintenancePublicNoteFile" ("scheduledMaintenancePublicNoteId" uuid NOT NULL, "fileId" uuid NOT NULL, CONSTRAINT "PK_373f78b83aa76e5250df8ebaed7" PRIMARY KEY ("scheduledMaintenancePublicNoteId", "fileId"))`,
18
+ );
19
+ await queryRunner.query(
20
+ `CREATE INDEX "IDX_af6905f89ca8108ed0f478fd37" ON "ScheduledMaintenancePublicNoteFile" ("scheduledMaintenancePublicNoteId") `,
21
+ );
22
+ await queryRunner.query(
23
+ `CREATE INDEX "IDX_f09af6332e0b89f134472f0442" ON "ScheduledMaintenancePublicNoteFile" ("fileId") `,
24
+ );
25
+ await queryRunner.query(
26
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
27
+ );
28
+ await queryRunner.query(
29
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
30
+ );
31
+ await queryRunner.query(
32
+ `ALTER TABLE "ScheduledMaintenanceInternalNoteFile" ADD CONSTRAINT "FK_ac92a60535a6d598c9619fd1999" FOREIGN KEY ("scheduledMaintenanceInternalNoteId") REFERENCES "ScheduledMaintenanceInternalNote"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
33
+ );
34
+ await queryRunner.query(
35
+ `ALTER TABLE "ScheduledMaintenanceInternalNoteFile" ADD CONSTRAINT "FK_daee340befeece208b507a42423" FOREIGN KEY ("fileId") REFERENCES "File"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
36
+ );
37
+ await queryRunner.query(
38
+ `ALTER TABLE "ScheduledMaintenancePublicNoteFile" ADD CONSTRAINT "FK_af6905f89ca8108ed0f478fd376" FOREIGN KEY ("scheduledMaintenancePublicNoteId") REFERENCES "ScheduledMaintenancePublicNote"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
39
+ );
40
+ await queryRunner.query(
41
+ `ALTER TABLE "ScheduledMaintenancePublicNoteFile" ADD CONSTRAINT "FK_f09af6332e0b89f134472f0442a" FOREIGN KEY ("fileId") REFERENCES "File"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
42
+ );
43
+ }
44
+
45
+ public async down(queryRunner: QueryRunner): Promise<void> {
46
+ await queryRunner.query(
47
+ `ALTER TABLE "ScheduledMaintenancePublicNoteFile" DROP CONSTRAINT "FK_f09af6332e0b89f134472f0442a"`,
48
+ );
49
+ await queryRunner.query(
50
+ `ALTER TABLE "ScheduledMaintenancePublicNoteFile" DROP CONSTRAINT "FK_af6905f89ca8108ed0f478fd376"`,
51
+ );
52
+ await queryRunner.query(
53
+ `ALTER TABLE "ScheduledMaintenanceInternalNoteFile" DROP CONSTRAINT "FK_daee340befeece208b507a42423"`,
54
+ );
55
+ await queryRunner.query(
56
+ `ALTER TABLE "ScheduledMaintenanceInternalNoteFile" DROP CONSTRAINT "FK_ac92a60535a6d598c9619fd1999"`,
57
+ );
58
+ await queryRunner.query(
59
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
60
+ );
61
+ await queryRunner.query(
62
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
63
+ );
64
+ await queryRunner.query(
65
+ `DROP INDEX "public"."IDX_f09af6332e0b89f134472f0442"`,
66
+ );
67
+ await queryRunner.query(
68
+ `DROP INDEX "public"."IDX_af6905f89ca8108ed0f478fd37"`,
69
+ );
70
+ await queryRunner.query(`DROP TABLE "ScheduledMaintenancePublicNoteFile"`);
71
+ await queryRunner.query(
72
+ `DROP INDEX "public"."IDX_daee340befeece208b507a4242"`,
73
+ );
74
+ await queryRunner.query(
75
+ `DROP INDEX "public"."IDX_ac92a60535a6d598c9619fd199"`,
76
+ );
77
+ await queryRunner.query(
78
+ `DROP TABLE "ScheduledMaintenanceInternalNoteFile"`,
79
+ );
80
+ }
81
+ }
@@ -0,0 +1,79 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class MigrationName1763480947474 implements MigrationInterface {
4
+ public name = "MigrationName1763480947474";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `CREATE TABLE "StatusPageAnnouncementFile" ("statusPageAnnouncementId" uuid NOT NULL, "fileId" uuid NOT NULL, CONSTRAINT "PK_1323a0215e608ece58a96816134" PRIMARY KEY ("statusPageAnnouncementId", "fileId"))`,
9
+ );
10
+ await queryRunner.query(
11
+ `CREATE INDEX "IDX_b152a77a26a67d2e76160ba15e" ON "StatusPageAnnouncementFile" ("statusPageAnnouncementId") `,
12
+ );
13
+ await queryRunner.query(
14
+ `CREATE INDEX "IDX_2f78e2d073bf58013c962ce482" ON "StatusPageAnnouncementFile" ("fileId") `,
15
+ );
16
+ await queryRunner.query(
17
+ `CREATE TABLE "AlertInternalNoteFile" ("alertInternalNoteId" uuid NOT NULL, "fileId" uuid NOT NULL, CONSTRAINT "PK_a5370c68590b3db5c3635d364aa" PRIMARY KEY ("alertInternalNoteId", "fileId"))`,
18
+ );
19
+ await queryRunner.query(
20
+ `CREATE INDEX "IDX_09507cdab877a482edcc4c0593" ON "AlertInternalNoteFile" ("alertInternalNoteId") `,
21
+ );
22
+ await queryRunner.query(
23
+ `CREATE INDEX "IDX_77dc8a31bd4ebb0882450abdde" ON "AlertInternalNoteFile" ("fileId") `,
24
+ );
25
+ await queryRunner.query(
26
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
27
+ );
28
+ await queryRunner.query(
29
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
30
+ );
31
+ await queryRunner.query(
32
+ `ALTER TABLE "StatusPageAnnouncementFile" ADD CONSTRAINT "FK_b152a77a26a67d2e76160ba15e3" FOREIGN KEY ("statusPageAnnouncementId") REFERENCES "StatusPageAnnouncement"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
33
+ );
34
+ await queryRunner.query(
35
+ `ALTER TABLE "StatusPageAnnouncementFile" ADD CONSTRAINT "FK_2f78e2d073bf58013c962ce4827" FOREIGN KEY ("fileId") REFERENCES "File"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
36
+ );
37
+ await queryRunner.query(
38
+ `ALTER TABLE "AlertInternalNoteFile" ADD CONSTRAINT "FK_09507cdab877a482edcc4c05933" FOREIGN KEY ("alertInternalNoteId") REFERENCES "AlertInternalNote"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
39
+ );
40
+ await queryRunner.query(
41
+ `ALTER TABLE "AlertInternalNoteFile" ADD CONSTRAINT "FK_77dc8a31bd4ebb0882450abdde9" FOREIGN KEY ("fileId") REFERENCES "File"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
42
+ );
43
+ }
44
+
45
+ public async down(queryRunner: QueryRunner): Promise<void> {
46
+ await queryRunner.query(
47
+ `ALTER TABLE "AlertInternalNoteFile" DROP CONSTRAINT "FK_77dc8a31bd4ebb0882450abdde9"`,
48
+ );
49
+ await queryRunner.query(
50
+ `ALTER TABLE "AlertInternalNoteFile" DROP CONSTRAINT "FK_09507cdab877a482edcc4c05933"`,
51
+ );
52
+ await queryRunner.query(
53
+ `ALTER TABLE "StatusPageAnnouncementFile" DROP CONSTRAINT "FK_2f78e2d073bf58013c962ce4827"`,
54
+ );
55
+ await queryRunner.query(
56
+ `ALTER TABLE "StatusPageAnnouncementFile" DROP CONSTRAINT "FK_b152a77a26a67d2e76160ba15e3"`,
57
+ );
58
+ await queryRunner.query(
59
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
60
+ );
61
+ await queryRunner.query(
62
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
63
+ );
64
+ await queryRunner.query(
65
+ `DROP INDEX "public"."IDX_77dc8a31bd4ebb0882450abdde"`,
66
+ );
67
+ await queryRunner.query(
68
+ `DROP INDEX "public"."IDX_09507cdab877a482edcc4c0593"`,
69
+ );
70
+ await queryRunner.query(`DROP TABLE "AlertInternalNoteFile"`);
71
+ await queryRunner.query(
72
+ `DROP INDEX "public"."IDX_2f78e2d073bf58013c962ce482"`,
73
+ );
74
+ await queryRunner.query(
75
+ `DROP INDEX "public"."IDX_b152a77a26a67d2e76160ba15e"`,
76
+ );
77
+ await queryRunner.query(`DROP TABLE "StatusPageAnnouncementFile"`);
78
+ }
79
+ }
@@ -182,6 +182,9 @@ import { MigrationName1761834523183 } from "./1761834523183-MigrationName";
182
182
  import { MigrationName1762181014879 } from "./1762181014879-MigrationName";
183
183
  import { MigrationName1762554602716 } from "./1762554602716-MigrationName";
184
184
  import { MigrationName1762890441920 } from "./1762890441920-MigrationName";
185
+ import { MigrationName1763471659817 } from "./1763471659817-MigrationName";
186
+ import { MigrationName1763477560906 } from "./1763477560906-MigrationName";
187
+ import { MigrationName1763480947474 } from "./1763480947474-MigrationName";
185
188
 
186
189
  export default [
187
190
  InitialMigration,
@@ -368,4 +371,7 @@ export default [
368
371
  MigrationName1762181014879,
369
372
  MigrationName1762554602716,
370
373
  MigrationName1762890441920,
374
+ MigrationName1763471659817,
375
+ MigrationName1763477560906,
376
+ MigrationName1763480947474,
371
377
  ];
@@ -24,7 +24,9 @@ export default class ProjectMiddleware {
24
24
  @CaptureSpan()
25
25
  public static getProjectId(req: ExpressRequest): ObjectID | null {
26
26
  let projectId: ObjectID | null = null;
27
- if (req.params && req.params["tenantid"]) {
27
+ if (req.params && req.params["projectId"]) {
28
+ projectId = new ObjectID(req.params["projectId"]);
29
+ } else if (req.params && req.params["tenantid"]) {
28
30
  projectId = new ObjectID(req.params["tenantid"]);
29
31
  } else if (req.query && req.query["tenantid"]) {
30
32
  projectId = new ObjectID(req.query["tenantid"] as string);
@@ -9,6 +9,8 @@ import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
9
9
  import Alert from "../../Models/DatabaseModels/Alert";
10
10
  import AlertService from "./AlertService";
11
11
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
12
+ import File from "../../Models/DatabaseModels/File";
13
+ import FileAttachmentMarkdownUtil from "../Utils/FileAttachmentMarkdownUtil";
12
14
 
13
15
  export class Service extends DatabaseService<Model> {
14
16
  public constructor() {
@@ -21,6 +23,7 @@ export class Service extends DatabaseService<Model> {
21
23
  alertId: ObjectID;
22
24
  projectId: ObjectID;
23
25
  note: string;
26
+ attachmentFileIds?: Array<ObjectID>;
24
27
  }): Promise<Model> {
25
28
  const internalNote: Model = new Model();
26
29
  internalNote.createdByUserId = data.userId;
@@ -28,6 +31,16 @@ export class Service extends DatabaseService<Model> {
28
31
  internalNote.projectId = data.projectId;
29
32
  internalNote.note = data.note;
30
33
 
34
+ if (data.attachmentFileIds && data.attachmentFileIds.length > 0) {
35
+ internalNote.attachments = data.attachmentFileIds.map(
36
+ (fileId: ObjectID) => {
37
+ const file: File = new File();
38
+ file.id = fileId;
39
+ return file;
40
+ },
41
+ );
42
+ }
43
+
31
44
  return this.create({
32
45
  data: internalNote,
33
46
  props: {
@@ -50,6 +63,11 @@ export class Service extends DatabaseService<Model> {
50
63
  alertId: alertId,
51
64
  });
52
65
 
66
+ const attachmentsMarkdown: string = await this.getAttachmentsMarkdown(
67
+ createdItem.id!,
68
+ "/alert-internal-note/attachment",
69
+ );
70
+
53
71
  await AlertFeedService.createAlertFeedItem({
54
72
  alertId: createdItem.alertId!,
55
73
  projectId: createdItem.projectId!,
@@ -59,7 +77,7 @@ export class Service extends DatabaseService<Model> {
59
77
 
60
78
  feedInfoInMarkdown: `📄 posted **private note** for this [Alert ${alertNumber}](${(await AlertService.getAlertLinkInDashboard(createdItem.projectId!, alertId)).toString()}):
61
79
 
62
- ${createdItem.note}
80
+ ${(createdItem.note || "") + attachmentsMarkdown}
63
81
  `,
64
82
  workspaceNotification: {
65
83
  sendWorkspaceNotification: true,
@@ -104,6 +122,10 @@ ${createdItem.note}
104
122
 
105
123
  for (const updatedItem of updatedItems) {
106
124
  const alert: Alert = updatedItem.alert!;
125
+ const attachmentsMarkdown: string = await this.getAttachmentsMarkdown(
126
+ updatedItem.id!,
127
+ "/alert-internal-note/attachment",
128
+ );
107
129
  await AlertFeedService.createAlertFeedItem({
108
130
  alertId: updatedItem.alertId!,
109
131
  projectId: updatedItem.projectId!,
@@ -113,7 +135,7 @@ ${createdItem.note}
113
135
 
114
136
  feedInfoInMarkdown: `📄 updated **Private Note** for this [Alert ${alert.alertNumber}](${(await AlertService.getAlertLinkInDashboard(alert.projectId!, alert.id!)).toString()})
115
137
 
116
- ${updatedItem.note}
138
+ ${(updatedItem.note || "") + attachmentsMarkdown}
117
139
  `,
118
140
  workspaceNotification: {
119
141
  sendWorkspaceNotification: true,
@@ -124,6 +146,57 @@ ${updatedItem.note}
124
146
  }
125
147
  return onUpdate;
126
148
  }
149
+
150
+ private async getAttachmentsMarkdown(
151
+ modelId: ObjectID,
152
+ attachmentApiPath: string,
153
+ ): Promise<string> {
154
+ if (!modelId) {
155
+ return "";
156
+ }
157
+
158
+ const noteWithAttachments: Model | null = await this.findOneById({
159
+ id: modelId,
160
+ select: {
161
+ attachments: {
162
+ _id: true,
163
+ },
164
+ },
165
+ props: {
166
+ isRoot: true,
167
+ },
168
+ });
169
+
170
+ if (!noteWithAttachments || !noteWithAttachments.attachments) {
171
+ return "";
172
+ }
173
+
174
+ const attachmentIds: Array<ObjectID> = noteWithAttachments.attachments
175
+ .map((file: File) => {
176
+ if (file.id) {
177
+ return file.id;
178
+ }
179
+
180
+ if (file._id) {
181
+ return new ObjectID(file._id);
182
+ }
183
+
184
+ return null;
185
+ })
186
+ .filter((id: ObjectID | null): id is ObjectID => {
187
+ return Boolean(id);
188
+ });
189
+
190
+ if (!attachmentIds.length) {
191
+ return "";
192
+ }
193
+
194
+ return await FileAttachmentMarkdownUtil.buildAttachmentMarkdown({
195
+ modelId,
196
+ attachmentIds,
197
+ attachmentApiPath,
198
+ });
199
+ }
127
200
  }
128
201
 
129
202
  export default new Service();