@oneuptime/common 8.0.5580 → 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 (137) 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/Response.ts +13 -0
  33. package/Types/File/MimeType.ts +18 -0
  34. package/UI/Components/AttachmentList/EventAttachmentList.tsx +121 -0
  35. package/UI/Components/EventItem/EventItem.tsx +22 -0
  36. package/UI/Components/Feed/FeedItem.tsx +9 -16
  37. package/UI/Components/FilePicker/FilePicker.tsx +441 -145
  38. package/UI/Components/Forms/Fields/FormField.tsx +32 -15
  39. package/UI/Components/Forms/FormSummary.tsx +168 -1
  40. package/UI/Components/Forms/ModelForm.tsx +46 -24
  41. package/UI/Components/Forms/Types/FormFieldSchemaType.ts +1 -0
  42. package/UI/Components/Icon/Icon.tsx +1 -1
  43. package/UI/Utils/API/RequestOptions.ts +2 -0
  44. package/UI/Utils/ModelAPI/ModelAPI.ts +18 -0
  45. package/UI/Utils/User.ts +8 -0
  46. package/Utils/API.ts +11 -1
  47. package/build/dist/Models/DatabaseModels/AlertInternalNote.js +49 -1
  48. package/build/dist/Models/DatabaseModels/AlertInternalNote.js.map +1 -1
  49. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +1 -0
  50. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
  51. package/build/dist/Models/DatabaseModels/File.js +1 -1
  52. package/build/dist/Models/DatabaseModels/File.js.map +1 -1
  53. package/build/dist/Models/DatabaseModels/IncidentInternalNote.js +49 -1
  54. package/build/dist/Models/DatabaseModels/IncidentInternalNote.js.map +1 -1
  55. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +49 -1
  56. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
  57. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceInternalNote.js +49 -1
  58. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceInternalNote.js.map +1 -1
  59. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +49 -1
  60. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
  61. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +48 -0
  62. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
  63. package/build/dist/Server/API/AlertInternalNoteAPI.js +68 -0
  64. package/build/dist/Server/API/AlertInternalNoteAPI.js.map +1 -0
  65. package/build/dist/Server/API/IncidentInternalNoteAPI.js +68 -0
  66. package/build/dist/Server/API/IncidentInternalNoteAPI.js.map +1 -0
  67. package/build/dist/Server/API/IncidentPublicNoteAPI.js +68 -0
  68. package/build/dist/Server/API/IncidentPublicNoteAPI.js.map +1 -0
  69. package/build/dist/Server/API/ScheduledMaintenanceInternalNoteAPI.js +68 -0
  70. package/build/dist/Server/API/ScheduledMaintenanceInternalNoteAPI.js.map +1 -0
  71. package/build/dist/Server/API/ScheduledMaintenancePublicNoteAPI.js +68 -0
  72. package/build/dist/Server/API/ScheduledMaintenancePublicNoteAPI.js.map +1 -0
  73. package/build/dist/Server/API/StatusPageAPI.js +488 -85
  74. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  75. package/build/dist/Server/API/StatusPageAnnouncementAPI.js +68 -0
  76. package/build/dist/Server/API/StatusPageAnnouncementAPI.js.map +1 -0
  77. package/build/dist/Server/API/UserAPI.js +66 -0
  78. package/build/dist/Server/API/UserAPI.js.map +1 -0
  79. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763471659817-MigrationName.js +34 -0
  80. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763471659817-MigrationName.js.map +1 -0
  81. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763477560906-MigrationName.js +34 -0
  82. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763477560906-MigrationName.js.map +1 -0
  83. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763480947474-MigrationName.js +34 -0
  84. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763480947474-MigrationName.js.map +1 -0
  85. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  86. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  87. package/build/dist/Server/Middleware/ProjectAuthorization.js +4 -1
  88. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  89. package/build/dist/Server/Services/AlertInternalNoteService.js +54 -2
  90. package/build/dist/Server/Services/AlertInternalNoteService.js.map +1 -1
  91. package/build/dist/Server/Services/IncidentInternalNoteService.js +54 -2
  92. package/build/dist/Server/Services/IncidentInternalNoteService.js.map +1 -1
  93. package/build/dist/Server/Services/IncidentPublicNoteService.js +54 -2
  94. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  95. package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js +54 -2
  96. package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js.map +1 -1
  97. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +54 -2
  98. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  99. package/build/dist/Server/Services/ScheduledMaintenanceService.js +6 -5
  100. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  101. package/build/dist/Server/Services/StatusPagePrivateUserService.js +6 -4
  102. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  103. package/build/dist/Server/Services/StatusPageService.js +7 -4
  104. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  105. package/build/dist/Server/Services/StatusPageSubscriberService.js +11 -7
  106. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  107. package/build/dist/Server/Utils/FileAttachmentMarkdownUtil.js +67 -0
  108. package/build/dist/Server/Utils/FileAttachmentMarkdownUtil.js.map +1 -0
  109. package/build/dist/Server/Utils/Response.js +8 -0
  110. package/build/dist/Server/Utils/Response.js.map +1 -1
  111. package/build/dist/Types/File/MimeType.js +18 -0
  112. package/build/dist/Types/File/MimeType.js.map +1 -1
  113. package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js +42 -0
  114. package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js.map +1 -0
  115. package/build/dist/UI/Components/EventItem/EventItem.js +5 -1
  116. package/build/dist/UI/Components/EventItem/EventItem.js.map +1 -1
  117. package/build/dist/UI/Components/Feed/FeedItem.js +6 -4
  118. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
  119. package/build/dist/UI/Components/FilePicker/FilePicker.js +262 -77
  120. package/build/dist/UI/Components/FilePicker/FilePicker.js.map +1 -1
  121. package/build/dist/UI/Components/Forms/Fields/FormField.js +24 -12
  122. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  123. package/build/dist/UI/Components/Forms/FormSummary.js +77 -1
  124. package/build/dist/UI/Components/Forms/FormSummary.js.map +1 -1
  125. package/build/dist/UI/Components/Forms/ModelForm.js +32 -18
  126. package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
  127. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js +1 -0
  128. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js.map +1 -1
  129. package/build/dist/UI/Components/Icon/Icon.js +1 -1
  130. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  131. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +30 -45
  132. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  133. package/build/dist/UI/Utils/User.js +7 -0
  134. package/build/dist/UI/Utils/User.js.map +1 -1
  135. package/build/dist/Utils/API.js +3 -0
  136. package/build/dist/Utils/API.js.map +1 -1
  137. package/package.json +6 -6
@@ -1,6 +1,7 @@
1
1
  import Alert from "./Alert";
2
2
  import Project from "./Project";
3
3
  import User from "./User";
4
+ import File from "./File";
4
5
  import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
5
6
  import Route from "../../Types/API/Route";
6
7
  import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
@@ -17,7 +18,15 @@ import TenantColumn from "../../Types/Database/TenantColumn";
17
18
  import IconProp from "../../Types/Icon/IconProp";
18
19
  import ObjectID from "../../Types/ObjectID";
19
20
  import Permission from "../../Types/Permission";
20
- import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
21
+ import {
22
+ Column,
23
+ Entity,
24
+ Index,
25
+ JoinColumn,
26
+ JoinTable,
27
+ ManyToMany,
28
+ ManyToOne,
29
+ } from "typeorm";
21
30
 
22
31
  @EnableDocumentation()
23
32
  @CanAccessIfCanReadOn("alert")
@@ -340,6 +349,54 @@ export default class AlertInternalNote extends BaseModel {
340
349
  })
341
350
  public note?: string = undefined;
342
351
 
352
+ @ColumnAccessControl({
353
+ create: [
354
+ Permission.ProjectOwner,
355
+ Permission.ProjectAdmin,
356
+ Permission.ProjectMember,
357
+ Permission.CreateAlertInternalNote,
358
+ ],
359
+ read: [
360
+ Permission.ProjectOwner,
361
+ Permission.ProjectAdmin,
362
+ Permission.ProjectMember,
363
+ Permission.ReadAlertInternalNote,
364
+ ],
365
+ update: [
366
+ Permission.ProjectOwner,
367
+ Permission.ProjectAdmin,
368
+ Permission.ProjectMember,
369
+ Permission.EditAlertInternalNote,
370
+ ],
371
+ })
372
+ @TableColumn({
373
+ type: TableColumnType.EntityArray,
374
+ modelType: File,
375
+ title: "Attachments",
376
+ description: "Files attached to this note",
377
+ required: false,
378
+ })
379
+ @ManyToMany(
380
+ () => {
381
+ return File;
382
+ },
383
+ {
384
+ eager: false,
385
+ },
386
+ )
387
+ @JoinTable({
388
+ name: "AlertInternalNoteFile",
389
+ joinColumn: {
390
+ name: "alertInternalNoteId",
391
+ referencedColumnName: "_id",
392
+ },
393
+ inverseJoinColumn: {
394
+ name: "fileId",
395
+ referencedColumnName: "_id",
396
+ },
397
+ })
398
+ public attachments?: Array<File> = undefined;
399
+
343
400
  @ColumnAccessControl({
344
401
  create: [],
345
402
  read: [
@@ -58,6 +58,7 @@ export default class DatabaseBaseModel extends BaseEntity {
58
58
  type: TableColumnType.ObjectID,
59
59
  description: "ID of this object",
60
60
  computed: true,
61
+ canReadOnRelationQuery: true,
61
62
  })
62
63
  @PrimaryGeneratedColumn("uuid")
63
64
  public _id?: string = undefined;
@@ -22,7 +22,7 @@ import { Entity } from "typeorm";
22
22
  @CrudApiEndpoint(new Route("/file"))
23
23
  @TableAccessControl({
24
24
  create: [Permission.CurrentUser, Permission.AuthenticatedRequest],
25
- read: [Permission.CurrentUser, Permission.AuthenticatedRequest],
25
+ read: [],
26
26
  delete: [],
27
27
  update: [],
28
28
  })
@@ -1,6 +1,7 @@
1
1
  import Incident from "./Incident";
2
2
  import Project from "./Project";
3
3
  import User from "./User";
4
+ import File from "./File";
4
5
  import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
5
6
  import Route from "../../Types/API/Route";
6
7
  import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
@@ -17,7 +18,15 @@ import TenantColumn from "../../Types/Database/TenantColumn";
17
18
  import IconProp from "../../Types/Icon/IconProp";
18
19
  import ObjectID from "../../Types/ObjectID";
19
20
  import Permission from "../../Types/Permission";
20
- import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
21
+ import {
22
+ Column,
23
+ Entity,
24
+ Index,
25
+ JoinColumn,
26
+ JoinTable,
27
+ ManyToMany,
28
+ ManyToOne,
29
+ } from "typeorm";
21
30
 
22
31
  @EnableDocumentation()
23
32
  @CanAccessIfCanReadOn("incident")
@@ -340,6 +349,54 @@ export default class IncidentInternalNote extends BaseModel {
340
349
  })
341
350
  public note?: string = undefined;
342
351
 
352
+ @ColumnAccessControl({
353
+ create: [
354
+ Permission.ProjectOwner,
355
+ Permission.ProjectAdmin,
356
+ Permission.ProjectMember,
357
+ Permission.CreateIncidentInternalNote,
358
+ ],
359
+ read: [
360
+ Permission.ProjectOwner,
361
+ Permission.ProjectAdmin,
362
+ Permission.ProjectMember,
363
+ Permission.ReadIncidentInternalNote,
364
+ ],
365
+ update: [
366
+ Permission.ProjectOwner,
367
+ Permission.ProjectAdmin,
368
+ Permission.ProjectMember,
369
+ Permission.EditIncidentInternalNote,
370
+ ],
371
+ })
372
+ @TableColumn({
373
+ type: TableColumnType.EntityArray,
374
+ modelType: File,
375
+ title: "Attachments",
376
+ description: "Files attached to this note",
377
+ required: false,
378
+ })
379
+ @ManyToMany(
380
+ () => {
381
+ return File;
382
+ },
383
+ {
384
+ eager: false,
385
+ },
386
+ )
387
+ @JoinTable({
388
+ name: "IncidentInternalNoteFile",
389
+ joinColumn: {
390
+ name: "incidentInternalNoteId",
391
+ referencedColumnName: "_id",
392
+ },
393
+ inverseJoinColumn: {
394
+ name: "fileId",
395
+ referencedColumnName: "_id",
396
+ },
397
+ })
398
+ public attachments?: Array<File> = undefined;
399
+
343
400
  @ColumnAccessControl({
344
401
  create: [],
345
402
  read: [
@@ -1,6 +1,7 @@
1
1
  import Incident from "./Incident";
2
2
  import Project from "./Project";
3
3
  import User from "./User";
4
+ import File from "./File";
4
5
  import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
5
6
  import Route from "../../Types/API/Route";
6
7
  import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
@@ -18,7 +19,15 @@ import IconProp from "../../Types/Icon/IconProp";
18
19
  import ObjectID from "../../Types/ObjectID";
19
20
  import Permission from "../../Types/Permission";
20
21
  import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
21
- import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
22
+ import {
23
+ Column,
24
+ Entity,
25
+ Index,
26
+ JoinColumn,
27
+ JoinTable,
28
+ ManyToMany,
29
+ ManyToOne,
30
+ } from "typeorm";
22
31
 
23
32
  @EnableDocumentation()
24
33
  @CanAccessIfCanReadOn("incident")
@@ -341,6 +350,54 @@ export default class IncidentPublicNote extends BaseModel {
341
350
  })
342
351
  public note?: string = undefined;
343
352
 
353
+ @ColumnAccessControl({
354
+ create: [
355
+ Permission.ProjectOwner,
356
+ Permission.ProjectAdmin,
357
+ Permission.ProjectMember,
358
+ Permission.CreateIncidentPublicNote,
359
+ ],
360
+ read: [
361
+ Permission.ProjectOwner,
362
+ Permission.ProjectAdmin,
363
+ Permission.ProjectMember,
364
+ Permission.ReadIncidentPublicNote,
365
+ ],
366
+ update: [
367
+ Permission.ProjectOwner,
368
+ Permission.ProjectAdmin,
369
+ Permission.ProjectMember,
370
+ Permission.EditIncidentPublicNote,
371
+ ],
372
+ })
373
+ @TableColumn({
374
+ type: TableColumnType.EntityArray,
375
+ modelType: File,
376
+ title: "Attachments",
377
+ description: "Files attached to this note",
378
+ required: false,
379
+ })
380
+ @ManyToMany(
381
+ () => {
382
+ return File;
383
+ },
384
+ {
385
+ eager: false,
386
+ },
387
+ )
388
+ @JoinTable({
389
+ name: "IncidentPublicNoteFile",
390
+ joinColumn: {
391
+ name: "incidentPublicNoteId",
392
+ referencedColumnName: "_id",
393
+ },
394
+ inverseJoinColumn: {
395
+ name: "fileId",
396
+ referencedColumnName: "_id",
397
+ },
398
+ })
399
+ public attachments?: Array<File> = undefined;
400
+
344
401
  @ColumnAccessControl({
345
402
  create: [
346
403
  Permission.ProjectOwner,
@@ -1,6 +1,7 @@
1
1
  import Project from "./Project";
2
2
  import ScheduledMaintenance from "./ScheduledMaintenance";
3
3
  import User from "./User";
4
+ import File from "./File";
4
5
  import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
5
6
  import Route from "../../Types/API/Route";
6
7
  import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
@@ -16,7 +17,15 @@ import TenantColumn from "../../Types/Database/TenantColumn";
16
17
  import IconProp from "../../Types/Icon/IconProp";
17
18
  import ObjectID from "../../Types/ObjectID";
18
19
  import Permission from "../../Types/Permission";
19
- import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
20
+ import {
21
+ Column,
22
+ Entity,
23
+ Index,
24
+ JoinColumn,
25
+ JoinTable,
26
+ ManyToMany,
27
+ ManyToOne,
28
+ } from "typeorm";
20
29
 
21
30
  @CanAccessIfCanReadOn("scheduledMaintenance")
22
31
  @TenantColumn("projectId")
@@ -340,6 +349,54 @@ export default class ScheduledMaintenanceInternalNote extends BaseModel {
340
349
  })
341
350
  public note?: string = undefined;
342
351
 
352
+ @ColumnAccessControl({
353
+ create: [
354
+ Permission.ProjectOwner,
355
+ Permission.ProjectAdmin,
356
+ Permission.ProjectMember,
357
+ Permission.CreateScheduledMaintenanceInternalNote,
358
+ ],
359
+ read: [
360
+ Permission.ProjectOwner,
361
+ Permission.ProjectAdmin,
362
+ Permission.ProjectMember,
363
+ Permission.ReadScheduledMaintenanceInternalNote,
364
+ ],
365
+ update: [
366
+ Permission.ProjectOwner,
367
+ Permission.ProjectAdmin,
368
+ Permission.ProjectMember,
369
+ Permission.EditScheduledMaintenanceInternalNote,
370
+ ],
371
+ })
372
+ @TableColumn({
373
+ type: TableColumnType.EntityArray,
374
+ modelType: File,
375
+ title: "Attachments",
376
+ description: "Files attached to this note",
377
+ required: false,
378
+ })
379
+ @ManyToMany(
380
+ () => {
381
+ return File;
382
+ },
383
+ {
384
+ eager: false,
385
+ },
386
+ )
387
+ @JoinTable({
388
+ name: "ScheduledMaintenanceInternalNoteFile",
389
+ joinColumn: {
390
+ name: "scheduledMaintenanceInternalNoteId",
391
+ referencedColumnName: "_id",
392
+ },
393
+ inverseJoinColumn: {
394
+ name: "fileId",
395
+ referencedColumnName: "_id",
396
+ },
397
+ })
398
+ public attachments?: Array<File> = undefined;
399
+
343
400
  @ColumnAccessControl({
344
401
  create: [],
345
402
  read: [
@@ -1,6 +1,7 @@
1
1
  import Project from "./Project";
2
2
  import ScheduledMaintenance from "./ScheduledMaintenance";
3
3
  import User from "./User";
4
+ import File from "./File";
4
5
  import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
5
6
  import Route from "../../Types/API/Route";
6
7
  import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
@@ -18,7 +19,15 @@ import IconProp from "../../Types/Icon/IconProp";
18
19
  import ObjectID from "../../Types/ObjectID";
19
20
  import Permission from "../../Types/Permission";
20
21
  import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
21
- import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
22
+ import {
23
+ Column,
24
+ Entity,
25
+ Index,
26
+ JoinColumn,
27
+ JoinTable,
28
+ ManyToMany,
29
+ ManyToOne,
30
+ } from "typeorm";
22
31
 
23
32
  @EnableDocumentation()
24
33
  @CanAccessIfCanReadOn("scheduledMaintenance")
@@ -342,6 +351,54 @@ export default class ScheduledMaintenancePublicNote extends BaseModel {
342
351
  })
343
352
  public note?: string = undefined;
344
353
 
354
+ @ColumnAccessControl({
355
+ create: [
356
+ Permission.ProjectOwner,
357
+ Permission.ProjectAdmin,
358
+ Permission.ProjectMember,
359
+ Permission.CreateScheduledMaintenancePublicNote,
360
+ ],
361
+ read: [
362
+ Permission.ProjectOwner,
363
+ Permission.ProjectAdmin,
364
+ Permission.ProjectMember,
365
+ Permission.ReadScheduledMaintenancePublicNote,
366
+ ],
367
+ update: [
368
+ Permission.ProjectOwner,
369
+ Permission.ProjectAdmin,
370
+ Permission.ProjectMember,
371
+ Permission.EditScheduledMaintenancePublicNote,
372
+ ],
373
+ })
374
+ @TableColumn({
375
+ type: TableColumnType.EntityArray,
376
+ modelType: File,
377
+ title: "Attachments",
378
+ description: "Files attached to this note",
379
+ required: false,
380
+ })
381
+ @ManyToMany(
382
+ () => {
383
+ return File;
384
+ },
385
+ {
386
+ eager: false,
387
+ },
388
+ )
389
+ @JoinTable({
390
+ name: "ScheduledMaintenancePublicNoteFile",
391
+ joinColumn: {
392
+ name: "scheduledMaintenancePublicNoteId",
393
+ referencedColumnName: "_id",
394
+ },
395
+ inverseJoinColumn: {
396
+ name: "fileId",
397
+ referencedColumnName: "_id",
398
+ },
399
+ })
400
+ public attachments?: Array<File> = undefined;
401
+
345
402
  @ColumnAccessControl({
346
403
  create: [
347
404
  Permission.ProjectOwner,
@@ -2,6 +2,7 @@ import Monitor from "./Monitor";
2
2
  import Project from "./Project";
3
3
  import StatusPage from "./StatusPage";
4
4
  import User from "./User";
5
+ import File from "./File";
5
6
  import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
6
7
  import Route from "../../Types/API/Route";
7
8
  import { PlanType } from "../../Types/Billing/SubscriptionPlan";
@@ -375,6 +376,54 @@ export default class StatusPageAnnouncement extends BaseModel {
375
376
  })
376
377
  public description?: string = undefined;
377
378
 
379
+ @ColumnAccessControl({
380
+ create: [
381
+ Permission.ProjectOwner,
382
+ Permission.ProjectAdmin,
383
+ Permission.ProjectMember,
384
+ Permission.CreateStatusPageAnnouncement,
385
+ ],
386
+ read: [
387
+ Permission.ProjectOwner,
388
+ Permission.ProjectAdmin,
389
+ Permission.ProjectMember,
390
+ Permission.ReadStatusPageAnnouncement,
391
+ ],
392
+ update: [
393
+ Permission.ProjectOwner,
394
+ Permission.ProjectAdmin,
395
+ Permission.ProjectMember,
396
+ Permission.EditStatusPageAnnouncement,
397
+ ],
398
+ })
399
+ @TableColumn({
400
+ type: TableColumnType.EntityArray,
401
+ modelType: File,
402
+ title: "Attachments",
403
+ description: "Files attached to this announcement",
404
+ required: false,
405
+ })
406
+ @ManyToMany(
407
+ () => {
408
+ return File;
409
+ },
410
+ {
411
+ eager: false,
412
+ },
413
+ )
414
+ @JoinTable({
415
+ name: "StatusPageAnnouncementFile",
416
+ joinColumn: {
417
+ name: "statusPageAnnouncementId",
418
+ referencedColumnName: "_id",
419
+ },
420
+ inverseJoinColumn: {
421
+ name: "fileId",
422
+ referencedColumnName: "_id",
423
+ },
424
+ })
425
+ public attachments?: Array<File> = undefined;
426
+
378
427
  @ColumnAccessControl({
379
428
  create: [
380
429
  Permission.ProjectOwner,
@@ -0,0 +1,96 @@
1
+ import AlertInternalNote from "../../Models/DatabaseModels/AlertInternalNote";
2
+ import File from "../../Models/DatabaseModels/File";
3
+ import NotFoundException from "../../Types/Exception/NotFoundException";
4
+ import ObjectID from "../../Types/ObjectID";
5
+ import AlertInternalNoteService, {
6
+ Service as AlertInternalNoteServiceType,
7
+ } from "../Services/AlertInternalNoteService";
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 AlertInternalNoteAPI extends BaseAPI<
20
+ AlertInternalNote,
21
+ AlertInternalNoteServiceType
22
+ > {
23
+ public constructor() {
24
+ super(AlertInternalNote, AlertInternalNoteService);
25
+
26
+ this.router.get(
27
+ `${new this.entityType().getCrudApiPath()?.toString()}/attachment/:projectId/:noteId/: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 noteIdParam: string | undefined = req.params["noteId"];
44
+ const fileIdParam: string | undefined = req.params["fileId"];
45
+
46
+ if (!noteIdParam || !fileIdParam) {
47
+ throw new NotFoundException("Attachment not found");
48
+ }
49
+
50
+ let noteId: ObjectID;
51
+ let fileId: ObjectID;
52
+
53
+ try {
54
+ noteId = new ObjectID(noteIdParam);
55
+ fileId = new ObjectID(fileIdParam);
56
+ } catch {
57
+ throw new NotFoundException("Attachment not found");
58
+ }
59
+
60
+ const props: DatabaseCommonInteractionProps =
61
+ await CommonAPI.getDatabaseCommonInteractionProps(req);
62
+
63
+ const note: AlertInternalNote | null = await this.service.findOneBy({
64
+ query: {
65
+ _id: noteId,
66
+ },
67
+ select: {
68
+ attachments: {
69
+ _id: true,
70
+ file: true,
71
+ fileType: true,
72
+ name: true,
73
+ },
74
+ },
75
+ props,
76
+ });
77
+
78
+ const attachment: File | undefined = note?.attachments?.find(
79
+ (file: File) => {
80
+ const attachmentId: string | null = file._id
81
+ ? file._id.toString()
82
+ : file.id
83
+ ? file.id.toString()
84
+ : null;
85
+ return attachmentId === fileId.toString();
86
+ },
87
+ );
88
+
89
+ if (!attachment || !attachment.file) {
90
+ throw new NotFoundException("Attachment not found");
91
+ }
92
+
93
+ Response.setNoCacheHeaders(res);
94
+ return Response.sendFileResponse(req, res, attachment);
95
+ }
96
+ }
@@ -0,0 +1,96 @@
1
+ import IncidentInternalNote from "../../Models/DatabaseModels/IncidentInternalNote";
2
+ import File from "../../Models/DatabaseModels/File";
3
+ import NotFoundException from "../../Types/Exception/NotFoundException";
4
+ import ObjectID from "../../Types/ObjectID";
5
+ import IncidentInternalNoteService, {
6
+ Service as IncidentInternalNoteServiceType,
7
+ } from "../Services/IncidentInternalNoteService";
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 IncidentInternalNoteAPI extends BaseAPI<
20
+ IncidentInternalNote,
21
+ IncidentInternalNoteServiceType
22
+ > {
23
+ public constructor() {
24
+ super(IncidentInternalNote, IncidentInternalNoteService);
25
+
26
+ this.router.get(
27
+ `${new this.entityType().getCrudApiPath()?.toString()}/attachment/:projectId/:noteId/: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 noteIdParam: string | undefined = req.params["noteId"];
44
+ const fileIdParam: string | undefined = req.params["fileId"];
45
+
46
+ if (!noteIdParam || !fileIdParam) {
47
+ throw new NotFoundException("Attachment not found");
48
+ }
49
+
50
+ let noteId: ObjectID;
51
+ let fileId: ObjectID;
52
+
53
+ try {
54
+ noteId = new ObjectID(noteIdParam);
55
+ fileId = new ObjectID(fileIdParam);
56
+ } catch {
57
+ throw new NotFoundException("Attachment not found");
58
+ }
59
+
60
+ const props: DatabaseCommonInteractionProps =
61
+ await CommonAPI.getDatabaseCommonInteractionProps(req);
62
+
63
+ const note: IncidentInternalNote | null = await this.service.findOneBy({
64
+ query: {
65
+ _id: noteId,
66
+ },
67
+ select: {
68
+ attachments: {
69
+ _id: true,
70
+ file: true,
71
+ fileType: true,
72
+ name: true,
73
+ },
74
+ },
75
+ props,
76
+ });
77
+
78
+ const attachment: File | undefined = note?.attachments?.find(
79
+ (file: File) => {
80
+ const attachmentId: string | null = file._id
81
+ ? file._id.toString()
82
+ : file.id
83
+ ? file.id.toString()
84
+ : null;
85
+ return attachmentId === fileId.toString();
86
+ },
87
+ );
88
+
89
+ if (!attachment || !attachment.file) {
90
+ throw new NotFoundException("Attachment not found");
91
+ }
92
+
93
+ Response.setNoCacheHeaders(res);
94
+ return Response.sendFileResponse(req, res, attachment);
95
+ }
96
+ }