@oneuptime/common 11.1.1 → 11.2.0

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 (149) hide show
  1. package/Models/DatabaseModels/Alert.ts +55 -0
  2. package/Models/DatabaseModels/Incident.ts +55 -0
  3. package/Models/DatabaseModels/Index.ts +12 -0
  4. package/Models/DatabaseModels/IoTDevice.ts +690 -0
  5. package/Models/DatabaseModels/IoTFleet.ts +862 -0
  6. package/Models/DatabaseModels/IoTFleetLabelRule.ts +514 -0
  7. package/Models/DatabaseModels/IoTFleetOwnerRule.ts +596 -0
  8. package/Models/DatabaseModels/IoTFleetOwnerTeam.ts +485 -0
  9. package/Models/DatabaseModels/IoTFleetOwnerUser.ts +484 -0
  10. package/Models/DatabaseModels/ScheduledMaintenance.ts +55 -0
  11. package/Server/API/IoTDeviceAPI.ts +128 -0
  12. package/Server/API/TelemetryAPI.ts +104 -35
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1782900000000-AddIoTFleetAndDeviceTables.ts +399 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1783000000000-AddIoTFleetActivityJoinTables.ts +97 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/1783010000000-MigrationName.ts +979 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  17. package/Server/Services/IoTDeviceService.ts +356 -0
  18. package/Server/Services/IoTFleetLabelRuleEngineService.ts +198 -0
  19. package/Server/Services/IoTFleetLabelRuleService.ts +14 -0
  20. package/Server/Services/IoTFleetOwnerRuleEngineService.ts +216 -0
  21. package/Server/Services/IoTFleetOwnerRuleService.ts +14 -0
  22. package/Server/Services/IoTFleetOwnerTeamService.ts +10 -0
  23. package/Server/Services/IoTFleetOwnerUserService.ts +10 -0
  24. package/Server/Services/IoTFleetService.ts +376 -0
  25. package/Server/Services/OpenTelemetryIngestService.ts +16 -0
  26. package/Server/Services/StatusPageService.ts +69 -26
  27. package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +36 -0
  28. package/Server/Services/TelemetryUsageBillingService.ts +18 -0
  29. package/Server/Services/TraceAggregationService.ts +174 -0
  30. package/Server/Utils/Monitor/MonitorAlert.ts +24 -4
  31. package/Server/Utils/Monitor/MonitorClusterContext.ts +26 -2
  32. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +4 -2
  33. package/Server/Utils/Monitor/MonitorIncident.ts +39 -5
  34. package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +14 -0
  35. package/Server/Utils/Monitor/SeriesResourceLabels.ts +22 -0
  36. package/Server/Utils/Telemetry/IoTSnapshotScan.ts +408 -0
  37. package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +36 -0
  38. package/Types/Icon/IconProp.ts +1 -0
  39. package/Types/Monitor/IotAlertTemplates.ts +593 -0
  40. package/Types/Monitor/IotMetricCatalog.ts +146 -0
  41. package/Types/Monitor/MonitorCriteriaInstance.ts +12 -2
  42. package/Types/Monitor/MonitorStep.ts +31 -0
  43. package/Types/Monitor/MonitorStepIoTMonitor.ts +65 -0
  44. package/Types/Monitor/MonitorType.ts +12 -1
  45. package/Types/Permission.ts +230 -0
  46. package/Types/StatusPage/StatusPageSubscriberNotificationEventType.ts +3 -0
  47. package/Types/Telemetry/ServiceType.ts +1 -0
  48. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +5 -5
  49. package/UI/Components/Icon/Icon.tsx +18 -2
  50. package/UI/Components/Page/Page.tsx +1 -2
  51. package/build/dist/Models/DatabaseModels/Alert.js +54 -0
  52. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  53. package/build/dist/Models/DatabaseModels/Incident.js +54 -0
  54. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  55. package/build/dist/Models/DatabaseModels/Index.js +12 -0
  56. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  57. package/build/dist/Models/DatabaseModels/IoTDevice.js +722 -0
  58. package/build/dist/Models/DatabaseModels/IoTDevice.js.map +1 -0
  59. package/build/dist/Models/DatabaseModels/IoTFleet.js +882 -0
  60. package/build/dist/Models/DatabaseModels/IoTFleet.js.map +1 -0
  61. package/build/dist/Models/DatabaseModels/IoTFleetLabelRule.js +522 -0
  62. package/build/dist/Models/DatabaseModels/IoTFleetLabelRule.js.map +1 -0
  63. package/build/dist/Models/DatabaseModels/IoTFleetOwnerRule.js +603 -0
  64. package/build/dist/Models/DatabaseModels/IoTFleetOwnerRule.js.map +1 -0
  65. package/build/dist/Models/DatabaseModels/IoTFleetOwnerTeam.js +503 -0
  66. package/build/dist/Models/DatabaseModels/IoTFleetOwnerTeam.js.map +1 -0
  67. package/build/dist/Models/DatabaseModels/IoTFleetOwnerUser.js +502 -0
  68. package/build/dist/Models/DatabaseModels/IoTFleetOwnerUser.js.map +1 -0
  69. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +54 -0
  70. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  71. package/build/dist/Server/API/IoTDeviceAPI.js +92 -0
  72. package/build/dist/Server/API/IoTDeviceAPI.js.map +1 -0
  73. package/build/dist/Server/API/TelemetryAPI.js +76 -27
  74. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  75. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1782900000000-AddIoTFleetAndDeviceTables.js +187 -0
  76. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1782900000000-AddIoTFleetAndDeviceTables.js.map +1 -0
  77. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783000000000-AddIoTFleetActivityJoinTables.js +48 -0
  78. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783000000000-AddIoTFleetActivityJoinTables.js.map +1 -0
  79. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783010000000-MigrationName.js +340 -0
  80. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783010000000-MigrationName.js.map +1 -0
  81. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  82. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  83. package/build/dist/Server/Services/IoTDeviceService.js +249 -0
  84. package/build/dist/Server/Services/IoTDeviceService.js.map +1 -0
  85. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js +166 -0
  86. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js.map +1 -0
  87. package/build/dist/Server/Services/IoTFleetLabelRuleService.js +13 -0
  88. package/build/dist/Server/Services/IoTFleetLabelRuleService.js.map +1 -0
  89. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +186 -0
  90. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -0
  91. package/build/dist/Server/Services/IoTFleetOwnerRuleService.js +13 -0
  92. package/build/dist/Server/Services/IoTFleetOwnerRuleService.js.map +1 -0
  93. package/build/dist/Server/Services/IoTFleetOwnerTeamService.js +9 -0
  94. package/build/dist/Server/Services/IoTFleetOwnerTeamService.js.map +1 -0
  95. package/build/dist/Server/Services/IoTFleetOwnerUserService.js +9 -0
  96. package/build/dist/Server/Services/IoTFleetOwnerUserService.js.map +1 -0
  97. package/build/dist/Server/Services/IoTFleetService.js +340 -0
  98. package/build/dist/Server/Services/IoTFleetService.js.map +1 -0
  99. package/build/dist/Server/Services/OpenTelemetryIngestService.js +26 -11
  100. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  101. package/build/dist/Server/Services/StatusPageService.js +57 -23
  102. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  103. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +34 -0
  104. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
  105. package/build/dist/Server/Services/TelemetryUsageBillingService.js +13 -0
  106. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  107. package/build/dist/Server/Services/TraceAggregationService.js +136 -0
  108. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  109. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +37 -19
  110. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  111. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +27 -4
  112. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +1 -1
  113. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +4 -2
  114. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  115. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +39 -11
  116. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  117. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +8 -0
  118. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
  119. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +17 -0
  120. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
  121. package/build/dist/Server/Utils/Telemetry/IoTSnapshotScan.js +300 -0
  122. package/build/dist/Server/Utils/Telemetry/IoTSnapshotScan.js.map +1 -0
  123. package/build/dist/Types/Icon/IconProp.js +1 -0
  124. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  125. package/build/dist/Types/Monitor/IotAlertTemplates.js +467 -0
  126. package/build/dist/Types/Monitor/IotAlertTemplates.js.map +1 -0
  127. package/build/dist/Types/Monitor/IotMetricCatalog.js +108 -0
  128. package/build/dist/Types/Monitor/IotMetricCatalog.js.map +1 -0
  129. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +12 -2
  130. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  131. package/build/dist/Types/Monitor/MonitorStep.js +23 -0
  132. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  133. package/build/dist/Types/Monitor/MonitorStepIoTMonitor.js +32 -0
  134. package/build/dist/Types/Monitor/MonitorStepIoTMonitor.js.map +1 -0
  135. package/build/dist/Types/Monitor/MonitorType.js +11 -1
  136. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  137. package/build/dist/Types/Permission.js +204 -0
  138. package/build/dist/Types/Permission.js.map +1 -1
  139. package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js +2 -0
  140. package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js.map +1 -1
  141. package/build/dist/Types/Telemetry/ServiceType.js +1 -0
  142. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  143. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +3 -3
  144. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  145. package/build/dist/UI/Components/Icon/Icon.js +12 -2
  146. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  147. package/build/dist/UI/Components/Page/Page.js +1 -2
  148. package/build/dist/UI/Components/Page/Page.js.map +1 -1
  149. package/package.json +1 -1
@@ -0,0 +1,484 @@
1
+ import IoTFleet from "./IoTFleet";
2
+ import Project from "./Project";
3
+ import User from "./User";
4
+ import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
5
+ import Route from "../../Types/API/Route";
6
+ import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
7
+ import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
8
+ import ColumnType from "../../Types/Database/ColumnType";
9
+ import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
10
+ import EnableDocumentation from "../../Types/Database/EnableDocumentation";
11
+ import EnableWorkflow from "../../Types/Database/EnableWorkflow";
12
+ import TableColumn from "../../Types/Database/TableColumn";
13
+ import TableColumnType from "../../Types/Database/TableColumnType";
14
+ import TableMetadata from "../../Types/Database/TableMetadata";
15
+ import TenantColumn from "../../Types/Database/TenantColumn";
16
+ import IconProp from "../../Types/Icon/IconProp";
17
+ import ObjectID from "../../Types/ObjectID";
18
+ import Permission from "../../Types/Permission";
19
+ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
20
+
21
+ @EnableDocumentation()
22
+ @TenantColumn("projectId")
23
+ @TableAccessControl({
24
+ create: [
25
+ Permission.ProjectOwner,
26
+ Permission.ProjectAdmin,
27
+ Permission.ProjectMember,
28
+ Permission.SettingsAdmin,
29
+ Permission.SettingsMember,
30
+ Permission.CreateIoTFleetOwnerUser,
31
+ ],
32
+ read: [
33
+ Permission.ProjectOwner,
34
+ Permission.ProjectAdmin,
35
+ Permission.ProjectMember,
36
+ Permission.Viewer,
37
+ Permission.SettingsAdmin,
38
+ Permission.SettingsMember,
39
+ Permission.SettingsViewer,
40
+ Permission.ReadIoTFleetOwnerUser,
41
+ ],
42
+ delete: [
43
+ Permission.ProjectOwner,
44
+ Permission.ProjectAdmin,
45
+ Permission.ProjectMember,
46
+ Permission.SettingsAdmin,
47
+ Permission.SettingsMember,
48
+ Permission.DeleteIoTFleetOwnerUser,
49
+ ],
50
+ update: [
51
+ Permission.ProjectOwner,
52
+ Permission.ProjectAdmin,
53
+ Permission.ProjectMember,
54
+ Permission.SettingsAdmin,
55
+ Permission.SettingsMember,
56
+ Permission.EditIoTFleetOwnerUser,
57
+ ],
58
+ })
59
+ @EnableWorkflow({
60
+ create: true,
61
+ delete: true,
62
+ update: true,
63
+ read: true,
64
+ })
65
+ @CrudApiEndpoint(new Route("/iot-fleet-owner-user"))
66
+ @TableMetadata({
67
+ tableName: "IoTFleetOwnerUser",
68
+ singularName: "IoT Fleet User Owner",
69
+ pluralName: "IoT Fleet User Owners",
70
+ icon: IconProp.Cube,
71
+ tableDescription: "Add users as owners to your IoT fleets.",
72
+ })
73
+ @Entity({
74
+ name: "IoTFleetOwnerUser",
75
+ })
76
+ export default class IoTFleetOwnerUser extends BaseModel {
77
+ @ColumnAccessControl({
78
+ create: [
79
+ Permission.ProjectOwner,
80
+ Permission.ProjectAdmin,
81
+ Permission.ProjectMember,
82
+ Permission.SettingsAdmin,
83
+ Permission.SettingsMember,
84
+ Permission.CreateIoTFleetOwnerUser,
85
+ ],
86
+ read: [
87
+ Permission.ProjectOwner,
88
+ Permission.ProjectAdmin,
89
+ Permission.ProjectMember,
90
+ Permission.Viewer,
91
+ Permission.SettingsAdmin,
92
+ Permission.SettingsMember,
93
+ Permission.SettingsViewer,
94
+ Permission.ReadIoTFleetOwnerUser,
95
+ ],
96
+ update: [],
97
+ })
98
+ @TableColumn({
99
+ manyToOneRelationColumn: "projectId",
100
+ type: TableColumnType.Entity,
101
+ modelType: Project,
102
+ title: "Project",
103
+ description: "Relation to Project Resource in which this object belongs",
104
+ })
105
+ @ManyToOne(
106
+ () => {
107
+ return Project;
108
+ },
109
+ {
110
+ eager: false,
111
+ nullable: false,
112
+ onDelete: "CASCADE",
113
+ orphanedRowAction: "nullify",
114
+ },
115
+ )
116
+ @JoinColumn({ name: "projectId" })
117
+ public project?: Project = undefined;
118
+
119
+ @ColumnAccessControl({
120
+ create: [
121
+ Permission.ProjectOwner,
122
+ Permission.ProjectAdmin,
123
+ Permission.ProjectMember,
124
+ Permission.SettingsAdmin,
125
+ Permission.SettingsMember,
126
+ Permission.CreateIoTFleetOwnerUser,
127
+ ],
128
+ read: [
129
+ Permission.ProjectOwner,
130
+ Permission.ProjectAdmin,
131
+ Permission.ProjectMember,
132
+ Permission.Viewer,
133
+ Permission.SettingsAdmin,
134
+ Permission.SettingsMember,
135
+ Permission.SettingsViewer,
136
+ Permission.ReadIoTFleetOwnerUser,
137
+ ],
138
+ update: [],
139
+ })
140
+ @Index()
141
+ @TableColumn({
142
+ type: TableColumnType.ObjectID,
143
+ required: true,
144
+ canReadOnRelationQuery: true,
145
+ title: "Project ID",
146
+ description: "ID of your OneUptime Project in which this object belongs",
147
+ })
148
+ @Column({
149
+ type: ColumnType.ObjectID,
150
+ nullable: false,
151
+ transformer: ObjectID.getDatabaseTransformer(),
152
+ })
153
+ public projectId?: ObjectID = undefined;
154
+
155
+ @ColumnAccessControl({
156
+ create: [
157
+ Permission.ProjectOwner,
158
+ Permission.ProjectAdmin,
159
+ Permission.ProjectMember,
160
+ Permission.SettingsAdmin,
161
+ Permission.SettingsMember,
162
+ Permission.CreateIoTFleetOwnerUser,
163
+ ],
164
+ read: [
165
+ Permission.ProjectOwner,
166
+ Permission.ProjectAdmin,
167
+ Permission.ProjectMember,
168
+ Permission.Viewer,
169
+ Permission.SettingsAdmin,
170
+ Permission.SettingsMember,
171
+ Permission.SettingsViewer,
172
+ Permission.ReadIoTFleetOwnerUser,
173
+ ],
174
+ update: [],
175
+ })
176
+ @TableColumn({
177
+ manyToOneRelationColumn: "userId",
178
+ type: TableColumnType.Entity,
179
+ modelType: User,
180
+ title: "User",
181
+ description:
182
+ "User that is the owner. This user will receive notifications. ",
183
+ })
184
+ @ManyToOne(
185
+ () => {
186
+ return User;
187
+ },
188
+ {
189
+ eager: false,
190
+ nullable: true,
191
+ onDelete: "CASCADE",
192
+ orphanedRowAction: "nullify",
193
+ },
194
+ )
195
+ @JoinColumn({ name: "userId" })
196
+ public user?: User = undefined;
197
+
198
+ @ColumnAccessControl({
199
+ create: [
200
+ Permission.ProjectOwner,
201
+ Permission.ProjectAdmin,
202
+ Permission.ProjectMember,
203
+ Permission.SettingsAdmin,
204
+ Permission.SettingsMember,
205
+ Permission.CreateIoTFleetOwnerUser,
206
+ ],
207
+ read: [
208
+ Permission.ProjectOwner,
209
+ Permission.ProjectAdmin,
210
+ Permission.ProjectMember,
211
+ Permission.Viewer,
212
+ Permission.SettingsAdmin,
213
+ Permission.SettingsMember,
214
+ Permission.SettingsViewer,
215
+ Permission.ReadIoTFleetOwnerUser,
216
+ ],
217
+ update: [],
218
+ })
219
+ @Index()
220
+ @TableColumn({
221
+ type: TableColumnType.ObjectID,
222
+ required: true,
223
+ canReadOnRelationQuery: true,
224
+ title: "User ID",
225
+ description: "ID of your OneUptime User in which this object belongs",
226
+ })
227
+ @Column({
228
+ type: ColumnType.ObjectID,
229
+ nullable: false,
230
+ transformer: ObjectID.getDatabaseTransformer(),
231
+ })
232
+ public userId?: ObjectID = undefined;
233
+
234
+ @ColumnAccessControl({
235
+ create: [
236
+ Permission.ProjectOwner,
237
+ Permission.ProjectAdmin,
238
+ Permission.ProjectMember,
239
+ Permission.SettingsAdmin,
240
+ Permission.SettingsMember,
241
+ Permission.CreateIoTFleetOwnerUser,
242
+ ],
243
+ read: [
244
+ Permission.ProjectOwner,
245
+ Permission.ProjectAdmin,
246
+ Permission.ProjectMember,
247
+ Permission.Viewer,
248
+ Permission.SettingsAdmin,
249
+ Permission.SettingsMember,
250
+ Permission.SettingsViewer,
251
+ Permission.ReadIoTFleetOwnerUser,
252
+ ],
253
+ update: [],
254
+ })
255
+ @TableColumn({
256
+ manyToOneRelationColumn: "iotFleetId",
257
+ type: TableColumnType.Entity,
258
+ modelType: IoTFleet,
259
+ title: "IoT Fleet",
260
+ description: "Relation to IoT Fleet Resource in which this object belongs",
261
+ })
262
+ @ManyToOne(
263
+ () => {
264
+ return IoTFleet;
265
+ },
266
+ {
267
+ eager: false,
268
+ nullable: true,
269
+ onDelete: "CASCADE",
270
+ orphanedRowAction: "nullify",
271
+ },
272
+ )
273
+ @JoinColumn({ name: "iotFleetId" })
274
+ public iotFleet?: IoTFleet = undefined;
275
+
276
+ @ColumnAccessControl({
277
+ create: [
278
+ Permission.ProjectOwner,
279
+ Permission.ProjectAdmin,
280
+ Permission.ProjectMember,
281
+ Permission.SettingsAdmin,
282
+ Permission.SettingsMember,
283
+ Permission.CreateIoTFleetOwnerUser,
284
+ ],
285
+ read: [
286
+ Permission.ProjectOwner,
287
+ Permission.ProjectAdmin,
288
+ Permission.ProjectMember,
289
+ Permission.Viewer,
290
+ Permission.SettingsAdmin,
291
+ Permission.SettingsMember,
292
+ Permission.SettingsViewer,
293
+ Permission.ReadIoTFleetOwnerUser,
294
+ ],
295
+ update: [],
296
+ })
297
+ @Index()
298
+ @TableColumn({
299
+ type: TableColumnType.ObjectID,
300
+ required: true,
301
+ canReadOnRelationQuery: true,
302
+ title: "IoT Fleet ID",
303
+ description: "ID of your OneUptime IoT Fleet in which this object belongs",
304
+ })
305
+ @Column({
306
+ type: ColumnType.ObjectID,
307
+ nullable: false,
308
+ transformer: ObjectID.getDatabaseTransformer(),
309
+ })
310
+ public iotFleetId?: ObjectID = undefined;
311
+
312
+ @ColumnAccessControl({
313
+ create: [
314
+ Permission.ProjectOwner,
315
+ Permission.ProjectAdmin,
316
+ Permission.ProjectMember,
317
+ Permission.SettingsAdmin,
318
+ Permission.SettingsMember,
319
+ Permission.CreateIoTFleetOwnerUser,
320
+ ],
321
+ read: [
322
+ Permission.ProjectOwner,
323
+ Permission.ProjectAdmin,
324
+ Permission.ProjectMember,
325
+ Permission.Viewer,
326
+ Permission.SettingsAdmin,
327
+ Permission.SettingsMember,
328
+ Permission.SettingsViewer,
329
+ Permission.ReadIoTFleetOwnerUser,
330
+ ],
331
+ update: [],
332
+ })
333
+ @TableColumn({
334
+ manyToOneRelationColumn: "createdByUserId",
335
+ type: TableColumnType.Entity,
336
+ modelType: User,
337
+ title: "Created by User",
338
+ description:
339
+ "Relation to User who created this object (if this object was created by a User)",
340
+ })
341
+ @ManyToOne(
342
+ () => {
343
+ return User;
344
+ },
345
+ {
346
+ eager: false,
347
+ nullable: true,
348
+ onDelete: "SET NULL",
349
+ orphanedRowAction: "nullify",
350
+ },
351
+ )
352
+ @JoinColumn({ name: "createdByUserId" })
353
+ public createdByUser?: User = undefined;
354
+
355
+ @ColumnAccessControl({
356
+ create: [
357
+ Permission.ProjectOwner,
358
+ Permission.ProjectAdmin,
359
+ Permission.ProjectMember,
360
+ Permission.SettingsAdmin,
361
+ Permission.SettingsMember,
362
+ Permission.CreateIoTFleetOwnerUser,
363
+ ],
364
+ read: [
365
+ Permission.ProjectOwner,
366
+ Permission.ProjectAdmin,
367
+ Permission.ProjectMember,
368
+ Permission.Viewer,
369
+ Permission.SettingsAdmin,
370
+ Permission.SettingsMember,
371
+ Permission.SettingsViewer,
372
+ Permission.ReadIoTFleetOwnerUser,
373
+ ],
374
+ update: [],
375
+ })
376
+ @TableColumn({
377
+ type: TableColumnType.ObjectID,
378
+ title: "Created by User ID",
379
+ description:
380
+ "User ID who created this object (if this object was created by a User)",
381
+ })
382
+ @Column({
383
+ type: ColumnType.ObjectID,
384
+ nullable: true,
385
+ transformer: ObjectID.getDatabaseTransformer(),
386
+ })
387
+ public createdByUserId?: ObjectID = undefined;
388
+
389
+ @ColumnAccessControl({
390
+ create: [],
391
+ read: [
392
+ Permission.ProjectOwner,
393
+ Permission.ProjectAdmin,
394
+ Permission.ProjectMember,
395
+ Permission.Viewer,
396
+ Permission.SettingsAdmin,
397
+ Permission.SettingsMember,
398
+ Permission.SettingsViewer,
399
+ Permission.ReadIoTFleetOwnerUser,
400
+ ],
401
+ update: [],
402
+ })
403
+ @TableColumn({
404
+ manyToOneRelationColumn: "deletedByUserId",
405
+ type: TableColumnType.Entity,
406
+ title: "Deleted by User",
407
+ modelType: User,
408
+ description:
409
+ "Relation to User who deleted this object (if this object was deleted by a User)",
410
+ })
411
+ @ManyToOne(
412
+ () => {
413
+ return User;
414
+ },
415
+ {
416
+ cascade: false,
417
+ eager: false,
418
+ nullable: true,
419
+ onDelete: "SET NULL",
420
+ orphanedRowAction: "nullify",
421
+ },
422
+ )
423
+ @JoinColumn({ name: "deletedByUserId" })
424
+ public deletedByUser?: User = undefined;
425
+
426
+ @ColumnAccessControl({
427
+ create: [],
428
+ read: [
429
+ Permission.ProjectOwner,
430
+ Permission.ProjectAdmin,
431
+ Permission.ProjectMember,
432
+ Permission.Viewer,
433
+ Permission.SettingsAdmin,
434
+ Permission.SettingsMember,
435
+ Permission.SettingsViewer,
436
+ Permission.ReadIoTFleetOwnerUser,
437
+ ],
438
+ update: [],
439
+ })
440
+ @TableColumn({
441
+ type: TableColumnType.ObjectID,
442
+ title: "Deleted by User ID",
443
+ description:
444
+ "User ID who deleted this object (if this object was deleted by a User)",
445
+ })
446
+ @Column({
447
+ type: ColumnType.ObjectID,
448
+ nullable: true,
449
+ transformer: ObjectID.getDatabaseTransformer(),
450
+ })
451
+ public deletedByUserId?: ObjectID = undefined;
452
+
453
+ @ColumnAccessControl({
454
+ create: [],
455
+ read: [
456
+ Permission.ProjectOwner,
457
+ Permission.ProjectAdmin,
458
+ Permission.ProjectMember,
459
+ Permission.Viewer,
460
+ Permission.SettingsAdmin,
461
+ Permission.SettingsMember,
462
+ Permission.SettingsViewer,
463
+ Permission.ReadIoTFleetOwnerUser,
464
+ ],
465
+ update: [],
466
+ })
467
+ @Index()
468
+ @TableColumn({
469
+ type: TableColumnType.Boolean,
470
+ computed: true,
471
+ hideColumnInDocumentation: true,
472
+ required: true,
473
+ isDefaultValueColumn: true,
474
+ title: "Are Owners Notified",
475
+ description: "Are owners notified of this resource ownership?",
476
+ defaultValue: false,
477
+ })
478
+ @Column({
479
+ type: ColumnType.Boolean,
480
+ nullable: false,
481
+ default: false,
482
+ })
483
+ public isOwnerNotified?: boolean = undefined;
484
+ }
@@ -8,6 +8,7 @@ import Monitor from "./Monitor";
8
8
  import MonitorStatus from "./MonitorStatus";
9
9
  import Project from "./Project";
10
10
  import ProxmoxCluster from "./ProxmoxCluster";
11
+ import IoTFleet from "./IoTFleet";
11
12
  import DockerSwarmCluster from "./DockerSwarmCluster";
12
13
  import ScheduledMaintenanceState from "./ScheduledMaintenanceState";
13
14
  import Service from "./Service";
@@ -764,6 +765,60 @@ export default class ScheduledMaintenance extends BaseModel {
764
765
  })
765
766
  public proxmoxClusters?: Array<ProxmoxCluster> = undefined;
766
767
 
768
+ @ColumnAccessControl({
769
+ create: [
770
+ Permission.ProjectOwner,
771
+ Permission.ProjectAdmin,
772
+ Permission.ProjectMember,
773
+ Permission.ScheduledMaintenanceAdmin,
774
+ Permission.ScheduledMaintenanceMember,
775
+ Permission.CreateProjectScheduledMaintenance,
776
+ ],
777
+ read: [
778
+ Permission.ProjectOwner,
779
+ Permission.ProjectAdmin,
780
+ Permission.ProjectMember,
781
+ Permission.Viewer,
782
+ Permission.ScheduledMaintenanceAdmin,
783
+ Permission.ScheduledMaintenanceMember,
784
+ Permission.ScheduledMaintenanceViewer,
785
+ Permission.ReadProjectScheduledMaintenance,
786
+ ],
787
+ update: [
788
+ Permission.ProjectOwner,
789
+ Permission.ProjectAdmin,
790
+ Permission.ProjectMember,
791
+ Permission.ScheduledMaintenanceAdmin,
792
+ Permission.ScheduledMaintenanceMember,
793
+ Permission.EditProjectScheduledMaintenance,
794
+ ],
795
+ })
796
+ @TableColumn({
797
+ required: false,
798
+ type: TableColumnType.EntityArray,
799
+ modelType: IoTFleet,
800
+ title: "IoT Fleets",
801
+ description: "List of IoT fleets affected by this event.",
802
+ })
803
+ @ManyToMany(
804
+ () => {
805
+ return IoTFleet;
806
+ },
807
+ { eager: false },
808
+ )
809
+ @JoinTable({
810
+ name: "ScheduledMaintenanceIoTFleet",
811
+ inverseJoinColumn: {
812
+ name: "iotFleetId",
813
+ referencedColumnName: "_id",
814
+ },
815
+ joinColumn: {
816
+ name: "scheduledMaintenanceId",
817
+ referencedColumnName: "_id",
818
+ },
819
+ })
820
+ public iotFleets?: Array<IoTFleet> = undefined;
821
+
767
822
  @ColumnAccessControl({
768
823
  create: [
769
824
  Permission.ProjectOwner,
@@ -0,0 +1,128 @@
1
+ import IoTDevice from "../../Models/DatabaseModels/IoTDevice";
2
+ import IoTFleet from "../../Models/DatabaseModels/IoTFleet";
3
+ import BadDataException from "../../Types/Exception/BadDataException";
4
+ import ObjectID from "../../Types/ObjectID";
5
+ import IoTDeviceService, {
6
+ IoTInventorySummary,
7
+ Service as IoTDeviceServiceType,
8
+ } from "../Services/IoTDeviceService";
9
+ import IoTFleetService from "../Services/IoTFleetService";
10
+ import UserMiddleware from "../Middleware/UserAuthorization";
11
+ import Response from "../Utils/Response";
12
+ import BaseAPI from "./BaseAPI";
13
+ import {
14
+ ExpressRequest,
15
+ ExpressResponse,
16
+ NextFunction,
17
+ } from "../Utils/Express";
18
+ import CommonAPI from "./CommonAPI";
19
+ import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
20
+ import NotFoundException from "../../Types/Exception/NotFoundException";
21
+ import { JSONObject } from "../../Types/JSON";
22
+
23
+ /*
24
+ * ------------------------------------------------------------------
25
+ * IoTDeviceAPI
26
+ *
27
+ * Augments the auto-generated CRUD router with a single custom
28
+ * endpoint the IoT layout/overview pages use to fetch sidebar
29
+ * badge counts in one round-trip:
30
+ *
31
+ * POST /iot-device/inventory-summary/:fleetId
32
+ *
33
+ * The standard CRUD endpoints (list / get) are still registered by
34
+ * BaseAPI; the UI uses them via ModelAPI for list/detail reads.
35
+ * Write endpoints reject (@TableAccessControl create/update/delete
36
+ * = []); ingest writes go through IoTDeviceService as root.
37
+ * ------------------------------------------------------------------
38
+ */
39
+ export default class IoTDeviceAPI extends BaseAPI<
40
+ IoTDevice,
41
+ IoTDeviceServiceType
42
+ > {
43
+ public constructor() {
44
+ super(IoTDevice, IoTDeviceService);
45
+
46
+ this.router.post(
47
+ `${new this.entityType()
48
+ .getCrudApiPath()
49
+ ?.toString()}/inventory-summary/:fleetId`,
50
+ UserMiddleware.getUserMiddleware,
51
+ async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
52
+ try {
53
+ await this.getInventorySummary(req, res);
54
+ } catch (err) {
55
+ next(err);
56
+ }
57
+ },
58
+ );
59
+ }
60
+
61
+ /*
62
+ * Fleet + auth resolution for the fleet-scoped sub-route.
63
+ * Returns the (projectId, iotFleetId) tuple after enforcing
64
+ * the standard ACL chain. Throws NotFound when the fleet is
65
+ * missing or the caller lacks read access (indistinguishable on
66
+ * purpose).
67
+ */
68
+ private async resolveFleetForRequest(req: ExpressRequest): Promise<{
69
+ projectId: ObjectID;
70
+ iotFleetId: ObjectID;
71
+ }> {
72
+ const fleetIdParam: string | undefined = req.params["fleetId"];
73
+ if (!fleetIdParam) {
74
+ throw new BadDataException("Fleet ID is required");
75
+ }
76
+
77
+ let iotFleetId: ObjectID;
78
+ try {
79
+ iotFleetId = new ObjectID(fleetIdParam);
80
+ } catch {
81
+ throw new BadDataException("Invalid Fleet ID");
82
+ }
83
+
84
+ const props: DatabaseCommonInteractionProps =
85
+ await CommonAPI.getDatabaseCommonInteractionProps(req);
86
+
87
+ const fleet: IoTFleet | null = await IoTFleetService.findOneById({
88
+ id: iotFleetId,
89
+ select: {
90
+ _id: true,
91
+ projectId: true,
92
+ },
93
+ props,
94
+ });
95
+
96
+ if (!fleet || !fleet.projectId) {
97
+ throw new NotFoundException("IoT Fleet not found");
98
+ }
99
+
100
+ return {
101
+ projectId: fleet.projectId,
102
+ iotFleetId,
103
+ };
104
+ }
105
+
106
+ private async getInventorySummary(
107
+ req: ExpressRequest,
108
+ res: ExpressResponse,
109
+ ): Promise<void> {
110
+ const { projectId, iotFleetId } = await this.resolveFleetForRequest(req);
111
+
112
+ const summary: IoTInventorySummary = await this.service.getInventorySummary(
113
+ {
114
+ projectId,
115
+ iotFleetId,
116
+ },
117
+ );
118
+
119
+ const responseBody: JSONObject = {
120
+ countsByKind: summary.countsByKind as unknown as JSONObject,
121
+ // Convenience fields so the UI doesn't have to repeat COALESCE:
122
+ deviceCount: summary.deviceCount,
123
+ onlineDeviceCount: summary.onlineDeviceCount,
124
+ };
125
+
126
+ return Response.sendJsonObjectResponse(req, res, responseBody);
127
+ }
128
+ }