@oneuptime/common 11.1.2 → 11.2.1

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 (155) 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/AlertService.ts +24 -3
  18. package/Server/Services/IncidentService.ts +24 -3
  19. package/Server/Services/IoTDeviceService.ts +356 -0
  20. package/Server/Services/IoTFleetLabelRuleEngineService.ts +198 -0
  21. package/Server/Services/IoTFleetLabelRuleService.ts +14 -0
  22. package/Server/Services/IoTFleetOwnerRuleEngineService.ts +216 -0
  23. package/Server/Services/IoTFleetOwnerRuleService.ts +14 -0
  24. package/Server/Services/IoTFleetOwnerTeamService.ts +10 -0
  25. package/Server/Services/IoTFleetOwnerUserService.ts +10 -0
  26. package/Server/Services/IoTFleetService.ts +376 -0
  27. package/Server/Services/OpenTelemetryIngestService.ts +16 -0
  28. package/Server/Services/StatusPageService.ts +69 -26
  29. package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +36 -0
  30. package/Server/Services/TelemetryUsageBillingService.ts +18 -0
  31. package/Server/Services/TraceAggregationService.ts +174 -0
  32. package/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.ts +1 -1
  33. package/Server/Utils/Monitor/MonitorAlert.ts +24 -4
  34. package/Server/Utils/Monitor/MonitorClusterContext.ts +26 -2
  35. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +4 -2
  36. package/Server/Utils/Monitor/MonitorIncident.ts +39 -5
  37. package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +14 -0
  38. package/Server/Utils/Monitor/SeriesResourceLabels.ts +22 -0
  39. package/Server/Utils/Telemetry/IoTSnapshotScan.ts +408 -0
  40. package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +36 -0
  41. package/Types/Icon/IconProp.ts +1 -0
  42. package/Types/Monitor/IotAlertTemplates.ts +593 -0
  43. package/Types/Monitor/IotMetricCatalog.ts +146 -0
  44. package/Types/Monitor/MonitorStep.ts +31 -0
  45. package/Types/Monitor/MonitorStepIoTMonitor.ts +65 -0
  46. package/Types/Monitor/MonitorType.ts +12 -1
  47. package/Types/Permission.ts +230 -0
  48. package/Types/StatusPage/StatusPageSubscriberNotificationEventType.ts +3 -0
  49. package/Types/Telemetry/ServiceType.ts +1 -0
  50. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +5 -5
  51. package/UI/Components/Icon/Icon.tsx +18 -2
  52. package/UI/Components/Page/Page.tsx +1 -2
  53. package/build/dist/Models/DatabaseModels/Alert.js +54 -0
  54. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  55. package/build/dist/Models/DatabaseModels/Incident.js +54 -0
  56. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  57. package/build/dist/Models/DatabaseModels/Index.js +12 -0
  58. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  59. package/build/dist/Models/DatabaseModels/IoTDevice.js +722 -0
  60. package/build/dist/Models/DatabaseModels/IoTDevice.js.map +1 -0
  61. package/build/dist/Models/DatabaseModels/IoTFleet.js +882 -0
  62. package/build/dist/Models/DatabaseModels/IoTFleet.js.map +1 -0
  63. package/build/dist/Models/DatabaseModels/IoTFleetLabelRule.js +522 -0
  64. package/build/dist/Models/DatabaseModels/IoTFleetLabelRule.js.map +1 -0
  65. package/build/dist/Models/DatabaseModels/IoTFleetOwnerRule.js +603 -0
  66. package/build/dist/Models/DatabaseModels/IoTFleetOwnerRule.js.map +1 -0
  67. package/build/dist/Models/DatabaseModels/IoTFleetOwnerTeam.js +503 -0
  68. package/build/dist/Models/DatabaseModels/IoTFleetOwnerTeam.js.map +1 -0
  69. package/build/dist/Models/DatabaseModels/IoTFleetOwnerUser.js +502 -0
  70. package/build/dist/Models/DatabaseModels/IoTFleetOwnerUser.js.map +1 -0
  71. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +54 -0
  72. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  73. package/build/dist/Server/API/IoTDeviceAPI.js +92 -0
  74. package/build/dist/Server/API/IoTDeviceAPI.js.map +1 -0
  75. package/build/dist/Server/API/TelemetryAPI.js +76 -27
  76. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  77. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1782900000000-AddIoTFleetAndDeviceTables.js +187 -0
  78. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1782900000000-AddIoTFleetAndDeviceTables.js.map +1 -0
  79. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783000000000-AddIoTFleetActivityJoinTables.js +48 -0
  80. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783000000000-AddIoTFleetActivityJoinTables.js.map +1 -0
  81. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783010000000-MigrationName.js +340 -0
  82. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1783010000000-MigrationName.js.map +1 -0
  83. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  84. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  85. package/build/dist/Server/Services/AlertService.js +22 -3
  86. package/build/dist/Server/Services/AlertService.js.map +1 -1
  87. package/build/dist/Server/Services/IncidentService.js +22 -3
  88. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  89. package/build/dist/Server/Services/IoTDeviceService.js +249 -0
  90. package/build/dist/Server/Services/IoTDeviceService.js.map +1 -0
  91. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js +166 -0
  92. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js.map +1 -0
  93. package/build/dist/Server/Services/IoTFleetLabelRuleService.js +13 -0
  94. package/build/dist/Server/Services/IoTFleetLabelRuleService.js.map +1 -0
  95. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +186 -0
  96. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -0
  97. package/build/dist/Server/Services/IoTFleetOwnerRuleService.js +13 -0
  98. package/build/dist/Server/Services/IoTFleetOwnerRuleService.js.map +1 -0
  99. package/build/dist/Server/Services/IoTFleetOwnerTeamService.js +9 -0
  100. package/build/dist/Server/Services/IoTFleetOwnerTeamService.js.map +1 -0
  101. package/build/dist/Server/Services/IoTFleetOwnerUserService.js +9 -0
  102. package/build/dist/Server/Services/IoTFleetOwnerUserService.js.map +1 -0
  103. package/build/dist/Server/Services/IoTFleetService.js +340 -0
  104. package/build/dist/Server/Services/IoTFleetService.js.map +1 -0
  105. package/build/dist/Server/Services/OpenTelemetryIngestService.js +26 -11
  106. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  107. package/build/dist/Server/Services/StatusPageService.js +57 -23
  108. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  109. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +34 -0
  110. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
  111. package/build/dist/Server/Services/TelemetryUsageBillingService.js +13 -0
  112. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  113. package/build/dist/Server/Services/TraceAggregationService.js +136 -0
  114. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  115. package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js +15 -15
  116. package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js.map +1 -1
  117. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +37 -19
  118. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  119. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +27 -4
  120. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +1 -1
  121. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +4 -2
  122. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  123. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +39 -11
  124. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  125. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +8 -0
  126. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
  127. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +17 -0
  128. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
  129. package/build/dist/Server/Utils/Telemetry/IoTSnapshotScan.js +300 -0
  130. package/build/dist/Server/Utils/Telemetry/IoTSnapshotScan.js.map +1 -0
  131. package/build/dist/Types/Icon/IconProp.js +1 -0
  132. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  133. package/build/dist/Types/Monitor/IotAlertTemplates.js +467 -0
  134. package/build/dist/Types/Monitor/IotAlertTemplates.js.map +1 -0
  135. package/build/dist/Types/Monitor/IotMetricCatalog.js +108 -0
  136. package/build/dist/Types/Monitor/IotMetricCatalog.js.map +1 -0
  137. package/build/dist/Types/Monitor/MonitorStep.js +23 -0
  138. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  139. package/build/dist/Types/Monitor/MonitorStepIoTMonitor.js +32 -0
  140. package/build/dist/Types/Monitor/MonitorStepIoTMonitor.js.map +1 -0
  141. package/build/dist/Types/Monitor/MonitorType.js +11 -1
  142. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  143. package/build/dist/Types/Permission.js +204 -0
  144. package/build/dist/Types/Permission.js.map +1 -1
  145. package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js +2 -0
  146. package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js.map +1 -1
  147. package/build/dist/Types/Telemetry/ServiceType.js +1 -0
  148. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  149. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +3 -3
  150. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  151. package/build/dist/UI/Components/Icon/Icon.js +12 -2
  152. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  153. package/build/dist/UI/Components/Page/Page.js +1 -2
  154. package/build/dist/UI/Components/Page/Page.js.map +1 -1
  155. package/package.json +1 -1
@@ -0,0 +1,249 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import DatabaseService from "./DatabaseService";
11
+ import Model from "../../Models/DatabaseModels/IoTDevice";
12
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
13
+ import OneUptimeDate from "../../Types/Date";
14
+ import logger from "../Utils/Logger";
15
+ const UPSERT_BATCH_SIZE = 500;
16
+ const STALE_DELETE_WARN_THRESHOLD = 100;
17
+ /*
18
+ * Column order used by bulkUpsert() and its generated parameter tuples.
19
+ * Keep this and the INSERT column list in perfect sync.
20
+ */
21
+ const UPSERT_COLUMNS = [
22
+ "projectId",
23
+ "iotFleetId",
24
+ "kind",
25
+ "externalId",
26
+ "name",
27
+ "deviceType",
28
+ "firmwareVersion",
29
+ "isUp",
30
+ "uptimeSeconds",
31
+ "lastSeenAt",
32
+ "version",
33
+ ];
34
+ export class Service extends DatabaseService {
35
+ constructor() {
36
+ super(Model);
37
+ }
38
+ /**
39
+ * Upsert a batch of parsed devices for a single (project, fleet)
40
+ * pair. Uses ON CONFLICT on the UNIQUE (projectId, iotFleetId,
41
+ * kind, externalId) index with a dominance guard on lastSeenAt so
42
+ * out-of-order ingest never regresses a newer snapshot.
43
+ *
44
+ * Identity/status columns COALESCE against the existing row (unlike
45
+ * the K8s upsert, which overwrites): an iot-exporter batch is usually
46
+ * a complete scrape, but a batch that happens to lack an info series
47
+ * (e.g. only iot_device_up made it through a pipeline filter) must
48
+ * not blank name/deviceType/firmwareVersion that an earlier batch
49
+ * already filled.
50
+ */
51
+ async bulkUpsert(data) {
52
+ if (data.devices.length === 0) {
53
+ return;
54
+ }
55
+ // Chunk to keep individual statement parameter counts reasonable.
56
+ for (let i = 0; i < data.devices.length; i += UPSERT_BATCH_SIZE) {
57
+ const chunk = data.devices.slice(i, i + UPSERT_BATCH_SIZE);
58
+ const valueFragments = [];
59
+ const params = [];
60
+ let paramIndex = 1;
61
+ for (const r of chunk) {
62
+ const placeholders = [];
63
+ for (let c = 0; c < UPSERT_COLUMNS.length; c++) {
64
+ placeholders.push(`$${paramIndex++}`);
65
+ }
66
+ valueFragments.push(`(${placeholders.join(", ")})`);
67
+ params.push(data.projectId.toString(), data.iotFleetId.toString(), r.kind, r.externalId, r.name, r.deviceType, r.firmwareVersion, r.isUp, r.uptimeSeconds !== null ? Math.trunc(r.uptimeSeconds) : null, r.lastSeenAt, 0);
68
+ }
69
+ const sql = `
70
+ INSERT INTO "IoTDevice" (
71
+ "projectId", "iotFleetId", "kind", "externalId",
72
+ "name", "deviceType", "firmwareVersion",
73
+ "isUp", "uptimeSeconds",
74
+ "lastSeenAt", "version"
75
+ )
76
+ VALUES ${valueFragments.join(", ")}
77
+ ON CONFLICT ("projectId", "iotFleetId", "kind", "externalId")
78
+ DO UPDATE SET
79
+ "name" = COALESCE(EXCLUDED."name", "IoTDevice"."name"),
80
+ "deviceType" = COALESCE(EXCLUDED."deviceType", "IoTDevice"."deviceType"),
81
+ "firmwareVersion" = COALESCE(EXCLUDED."firmwareVersion", "IoTDevice"."firmwareVersion"),
82
+ "isUp" = COALESCE(EXCLUDED."isUp", "IoTDevice"."isUp"),
83
+ "uptimeSeconds" = COALESCE(EXCLUDED."uptimeSeconds", "IoTDevice"."uptimeSeconds"),
84
+ "lastSeenAt" = EXCLUDED."lastSeenAt",
85
+ "updatedAt" = now()
86
+ WHERE EXCLUDED."lastSeenAt" >= "IoTDevice"."lastSeenAt"
87
+ `;
88
+ await this.getRepository().manager.query(sql, params);
89
+ }
90
+ }
91
+ /**
92
+ * Update the latest-metric mirror columns for a batch of devices.
93
+ * Plain UPDATE: in practice the row always exists because bulkUpsert
94
+ * runs in the same flush; if it somehow doesn't, the write is
95
+ * silently skipped and the next flush catches up.
96
+ *
97
+ * Guarded by metricsUpdatedAt so out-of-order points don't regress a
98
+ * newer observation. COALESCE keeps the existing value when a batch
99
+ * lacks a series — notably a battery/signal/temperature value stays
100
+ * at its last-known reading (never 0) when a device omits that series.
101
+ */
102
+ async bulkUpdateLatestMetrics(data) {
103
+ if (data.metrics.length === 0) {
104
+ return;
105
+ }
106
+ for (let i = 0; i < data.metrics.length; i += UPSERT_BATCH_SIZE) {
107
+ const chunk = data.metrics.slice(i, i + UPSERT_BATCH_SIZE);
108
+ const valueFragments = [];
109
+ const params = [
110
+ data.projectId.toString(),
111
+ data.iotFleetId.toString(),
112
+ ];
113
+ let paramIndex = 3;
114
+ for (const m of chunk) {
115
+ valueFragments.push(`($${paramIndex++}, $${paramIndex++}, $${paramIndex++}::numeric, $${paramIndex++}::bigint, $${paramIndex++}::bigint, $${paramIndex++}::numeric, $${paramIndex++}::numeric, $${paramIndex++}::numeric, $${paramIndex++}::timestamptz)`);
116
+ params.push(m.kind, m.externalId, m.cpuPercent !== null && m.cpuPercent !== undefined
117
+ ? m.cpuPercent
118
+ : null, m.memoryBytes !== null && m.memoryBytes !== undefined
119
+ ? Math.trunc(m.memoryBytes).toString()
120
+ : null, m.maxMemoryBytes !== null && m.maxMemoryBytes !== undefined
121
+ ? Math.trunc(m.maxMemoryBytes).toString()
122
+ : null, m.memoryPercent !== null && m.memoryPercent !== undefined
123
+ ? m.memoryPercent
124
+ : null, m.batteryPercent !== null && m.batteryPercent !== undefined
125
+ ? m.batteryPercent
126
+ : null, m.signalStrengthDbm !== null && m.signalStrengthDbm !== undefined
127
+ ? m.signalStrengthDbm
128
+ : null, m.temperatureCelsius !== null && m.temperatureCelsius !== undefined
129
+ ? m.temperatureCelsius
130
+ : null, m.observedAt);
131
+ }
132
+ const sql = `
133
+ UPDATE "IoTDevice" AS p
134
+ SET
135
+ "latestCpuPercent" = COALESCE(v."cpu", p."latestCpuPercent"),
136
+ "latestMemoryBytes" = COALESCE(v."mem", p."latestMemoryBytes"),
137
+ "maxMemoryBytes" = COALESCE(v."maxMem", p."maxMemoryBytes"),
138
+ "latestMemoryPercent" = COALESCE(v."memPct", p."latestMemoryPercent"),
139
+ "latestBatteryPercent" = COALESCE(v."battery", p."latestBatteryPercent"),
140
+ "latestSignalStrengthDbm" = COALESCE(v."signal", p."latestSignalStrengthDbm"),
141
+ "latestTemperatureCelsius" = COALESCE(v."temp", p."latestTemperatureCelsius"),
142
+ "metricsUpdatedAt" = v."observedAt",
143
+ "updatedAt" = now()
144
+ FROM (VALUES ${valueFragments.join(", ")})
145
+ AS v("kind", "externalId", "cpu", "mem", "maxMem", "memPct", "battery", "signal", "temp", "observedAt")
146
+ WHERE
147
+ p."projectId" = $1
148
+ AND p."iotFleetId" = $2
149
+ AND p."kind" = v."kind"
150
+ AND p."externalId" = v."externalId"
151
+ AND (p."metricsUpdatedAt" IS NULL OR v."observedAt" >= p."metricsUpdatedAt")
152
+ `;
153
+ await this.getRepository().manager.query(sql, params);
154
+ }
155
+ }
156
+ /**
157
+ * Hard-delete all devices in a fleet whose last scrape is older
158
+ * than olderThan. Returns the number of deleted rows. Only called by
159
+ * the cleanup worker for fleets that are still connected — a
160
+ * disconnected fleet keeps its last-known inventory.
161
+ */
162
+ async deleteStaleForFleet(data) {
163
+ const result = await this.getRepository().manager.query(`DELETE FROM "IoTDevice" WHERE "iotFleetId" = $1 AND "lastSeenAt" < $2`, [data.iotFleetId.toString(), data.olderThan]);
164
+ // Postgres driver returns [rows, affected] for DELETE — normalize.
165
+ let affected = 0;
166
+ if (Array.isArray(result) && result.length >= 2) {
167
+ const second = result[1];
168
+ if (typeof second === "number") {
169
+ affected = second;
170
+ }
171
+ }
172
+ if (affected > STALE_DELETE_WARN_THRESHOLD) {
173
+ logger.warn(`IoTDevice cleanup deleted ${affected} stale rows for fleet ${data.iotFleetId.toString()} — larger than expected; investigate agent health.`);
174
+ }
175
+ return affected;
176
+ }
177
+ /**
178
+ * Compute the sidebar/overview summary in Postgres: counts per kind
179
+ * plus the total and online device breakdowns, in a single round-trip.
180
+ */
181
+ async getInventorySummary(data) {
182
+ const rows = await this.getRepository().manager.query(`SELECT "kind",
183
+ COUNT(*)::text AS count,
184
+ COUNT(*) FILTER (WHERE "isUp" IS TRUE)::text AS "upCount"
185
+ FROM "IoTDevice"
186
+ WHERE "projectId" = $1 AND "iotFleetId" = $2 AND "deletedAt" IS NULL
187
+ GROUP BY "kind"`, [data.projectId.toString(), data.iotFleetId.toString()]);
188
+ const countsByKind = {};
189
+ let deviceCount = 0;
190
+ let onlineDeviceCount = 0;
191
+ for (const row of rows) {
192
+ const count = parseInt(row.count, 10) || 0;
193
+ const upCount = parseInt(row.upCount, 10) || 0;
194
+ countsByKind[row.kind] = count;
195
+ deviceCount += count;
196
+ onlineDeviceCount += upCount;
197
+ }
198
+ return {
199
+ deviceCount,
200
+ onlineDeviceCount,
201
+ countsByKind,
202
+ };
203
+ }
204
+ /**
205
+ * Helper for the cleanup worker: snapshot-interval aware cutoff.
206
+ * 3× the 5-minute scrape interval by default. Tune via
207
+ * IOT_INVENTORY_STALE_MINUTES (min 5).
208
+ */
209
+ getStaleThresholdDate(nowOverride) {
210
+ const minutes = this.getStaleThresholdMinutes();
211
+ return OneUptimeDate.addRemoveMinutes(nowOverride || OneUptimeDate.getCurrentDate(), -minutes);
212
+ }
213
+ getStaleThresholdMinutes() {
214
+ const raw = process.env["IOT_INVENTORY_STALE_MINUTES"];
215
+ if (raw) {
216
+ const parsed = parseInt(raw, 10);
217
+ if (!isNaN(parsed) && parsed >= 5) {
218
+ return parsed;
219
+ }
220
+ }
221
+ return 15;
222
+ }
223
+ }
224
+ __decorate([
225
+ CaptureSpan(),
226
+ __metadata("design:type", Function),
227
+ __metadata("design:paramtypes", [Object]),
228
+ __metadata("design:returntype", Promise)
229
+ ], Service.prototype, "bulkUpsert", null);
230
+ __decorate([
231
+ CaptureSpan(),
232
+ __metadata("design:type", Function),
233
+ __metadata("design:paramtypes", [Object]),
234
+ __metadata("design:returntype", Promise)
235
+ ], Service.prototype, "bulkUpdateLatestMetrics", null);
236
+ __decorate([
237
+ CaptureSpan(),
238
+ __metadata("design:type", Function),
239
+ __metadata("design:paramtypes", [Object]),
240
+ __metadata("design:returntype", Promise)
241
+ ], Service.prototype, "deleteStaleForFleet", null);
242
+ __decorate([
243
+ CaptureSpan(),
244
+ __metadata("design:type", Function),
245
+ __metadata("design:paramtypes", [Object]),
246
+ __metadata("design:returntype", Promise)
247
+ ], Service.prototype, "getInventorySummary", null);
248
+ export default new Service();
249
+ //# sourceMappingURL=IoTDeviceService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IoTDeviceService.js","sourceRoot":"","sources":["../../../../Server/Services/IoTDeviceService.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,eAAe,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,MAAM,uCAAuC,CAAC;AAC1D,OAAO,WAAW,MAAM,gCAAgC,CAAC;AAEzD,OAAO,aAAa,MAAM,kBAAkB,CAAC;AAC7C,OAAO,MAAM,MAAM,iBAAiB,CAAC;AAmDrC,MAAM,iBAAiB,GAAW,GAAG,CAAC;AACtC,MAAM,2BAA2B,GAAW,GAAG,CAAC;AAEhD;;;GAGG;AACH,MAAM,cAAc,GAAkB;IACpC,WAAW;IACX,YAAY;IACZ,MAAM;IACN,YAAY;IACZ,MAAM;IACN,YAAY;IACZ,iBAAiB;IACjB,MAAM;IACN,eAAe;IACf,YAAY;IACZ,SAAS;CACV,CAAC;AAEF,MAAM,OAAO,OAAQ,SAAQ,eAAsB;IACjD;QACE,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,CAAC;IAED;;;;;;;;;;;;OAYG;IAEU,AAAN,KAAK,CAAC,UAAU,CAAC,IAIvB;QACC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,kEAAkE;QAClE,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,iBAAiB,EAAE,CAAC;YACxE,MAAM,KAAK,GAA2B,IAAI,CAAC,OAAO,CAAC,KAAK,CACtD,CAAC,EACD,CAAC,GAAG,iBAAiB,CACtB,CAAC;YAEF,MAAM,cAAc,GAAkB,EAAE,CAAC;YACzC,MAAM,MAAM,GAAmB,EAAE,CAAC;YAClC,IAAI,UAAU,GAAW,CAAC,CAAC;YAE3B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;gBACtB,MAAM,YAAY,GAAkB,EAAE,CAAC;gBACvC,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACvD,YAAY,CAAC,IAAI,CAAC,IAAI,UAAU,EAAE,EAAE,CAAC,CAAC;gBACxC,CAAC;gBACD,cAAc,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAEpD,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,EACzB,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,EAC1B,CAAC,CAAC,IAAI,EACN,CAAC,CAAC,UAAU,EACZ,CAAC,CAAC,IAAI,EACN,CAAC,CAAC,UAAU,EACZ,CAAC,CAAC,eAAe,EACjB,CAAC,CAAC,IAAI,EACN,CAAC,CAAC,aAAa,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,EAC7D,CAAC,CAAC,UAAU,EACZ,CAAC,CACF,CAAC;YACJ,CAAC;YAED,MAAM,GAAG,GAAW;;;;;;;iBAOT,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;;;OAWnC,CAAC;YAEF,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED;;;;;;;;;;OAUG;IAEU,AAAN,KAAK,CAAC,uBAAuB,CAAC,IAIpC;QACC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,KAAK,IAAI,CAAC,GAAW,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,iBAAiB,EAAE,CAAC;YACxE,MAAM,KAAK,GAAiC,IAAI,CAAC,OAAO,CAAC,KAAK,CAC5D,CAAC,EACD,CAAC,GAAG,iBAAiB,CACtB,CAAC;YAEF,MAAM,cAAc,GAAkB,EAAE,CAAC;YACzC,MAAM,MAAM,GAAmB;gBAC7B,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE;gBACzB,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE;aAC3B,CAAC;YACF,IAAI,UAAU,GAAW,CAAC,CAAC;YAE3B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;gBACtB,cAAc,CAAC,IAAI,CACjB,KAAK,UAAU,EAAE,MAAM,UAAU,EAAE,MAAM,UAAU,EAAE,eAAe,UAAU,EAAE,cAAc,UAAU,EAAE,cAAc,UAAU,EAAE,eAAe,UAAU,EAAE,eAAe,UAAU,EAAE,eAAe,UAAU,EAAE,gBAAgB,CACtO,CAAC;gBACF,MAAM,CAAC,IAAI,CACT,CAAC,CAAC,IAAI,EACN,CAAC,CAAC,UAAU,EACZ,CAAC,CAAC,UAAU,KAAK,IAAI,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS;oBACjD,CAAC,CAAC,CAAC,CAAC,UAAU;oBACd,CAAC,CAAC,IAAI,EACR,CAAC,CAAC,WAAW,KAAK,IAAI,IAAI,CAAC,CAAC,WAAW,KAAK,SAAS;oBACnD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE;oBACtC,CAAC,CAAC,IAAI,EACR,CAAC,CAAC,cAAc,KAAK,IAAI,IAAI,CAAC,CAAC,cAAc,KAAK,SAAS;oBACzD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,QAAQ,EAAE;oBACzC,CAAC,CAAC,IAAI,EACR,CAAC,CAAC,aAAa,KAAK,IAAI,IAAI,CAAC,CAAC,aAAa,KAAK,SAAS;oBACvD,CAAC,CAAC,CAAC,CAAC,aAAa;oBACjB,CAAC,CAAC,IAAI,EACR,CAAC,CAAC,cAAc,KAAK,IAAI,IAAI,CAAC,CAAC,cAAc,KAAK,SAAS;oBACzD,CAAC,CAAC,CAAC,CAAC,cAAc;oBAClB,CAAC,CAAC,IAAI,EACR,CAAC,CAAC,iBAAiB,KAAK,IAAI,IAAI,CAAC,CAAC,iBAAiB,KAAK,SAAS;oBAC/D,CAAC,CAAC,CAAC,CAAC,iBAAiB;oBACrB,CAAC,CAAC,IAAI,EACR,CAAC,CAAC,kBAAkB,KAAK,IAAI,IAAI,CAAC,CAAC,kBAAkB,KAAK,SAAS;oBACjE,CAAC,CAAC,CAAC,CAAC,kBAAkB;oBACtB,CAAC,CAAC,IAAI,EACR,CAAC,CAAC,UAAU,CACb,CAAC;YACJ,CAAC;YAED,MAAM,GAAG,GAAW;;;;;;;;;;;;uBAYH,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;OAQzC,CAAC;YAEF,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED;;;;;OAKG;IAEU,AAAN,KAAK,CAAC,mBAAmB,CAAC,IAGhC;QACC,MAAM,MAAM,GACV,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,OAAO,CAAC,KAAK,CACtC,uEAAuE,EACvE,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAC7C,CAAC;QAEJ,mEAAmE;QACnE,IAAI,QAAQ,GAAW,CAAC,CAAC;QACzB,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YAChD,MAAM,MAAM,GAAa,MAAyB,CAAC,CAAC,CAAC,CAAC;YACtD,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAC/B,QAAQ,GAAG,MAAM,CAAC;YACpB,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,GAAG,2BAA2B,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CACT,6BAA6B,QAAQ,yBAAyB,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,oDAAoD,CAC7I,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;OAGG;IAEU,AAAN,KAAK,CAAC,mBAAmB,CAAC,IAGhC;QACC,MAAM,IAAI,GAIL,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,OAAO,CAAC,KAAK,CAC3C;;;;;uBAKiB,EACjB,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CACxD,CAAC;QAEF,MAAM,YAAY,GAA2B,EAAE,CAAC;QAChD,IAAI,WAAW,GAAW,CAAC,CAAC;QAC5B,IAAI,iBAAiB,GAAW,CAAC,CAAC;QAClC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,KAAK,GAAW,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;YACnD,MAAM,OAAO,GAAW,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;YACvD,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;YAC/B,WAAW,IAAI,KAAK,CAAC;YACrB,iBAAiB,IAAI,OAAO,CAAC;QAC/B,CAAC;QAED,OAAO;YACL,WAAW;YACX,iBAAiB;YACjB,YAAY;SACb,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACI,qBAAqB,CAAC,WAAkB;QAC7C,MAAM,OAAO,GAAW,IAAI,CAAC,wBAAwB,EAAE,CAAC;QACxD,OAAO,aAAa,CAAC,gBAAgB,CACnC,WAAW,IAAI,aAAa,CAAC,cAAc,EAAE,EAC7C,CAAC,OAAO,CACT,CAAC;IACJ,CAAC;IAEM,wBAAwB;QAC7B,MAAM,GAAG,GAAuB,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAC3E,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,MAAM,GAAW,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACzC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;gBAClC,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;CACF;AAjQc;IADZ,WAAW,EAAE;;;;yCAiEb;AAcY;IADZ,WAAW,EAAE;;;;sDA+Eb;AASY;IADZ,WAAW,EAAE;;;;kDA2Bb;AAOY;IADZ,WAAW,EAAE;;;;kDAmCb;AA2BH,eAAe,IAAI,OAAO,EAAE,CAAC"}
@@ -0,0 +1,166 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import Label from "../../Models/DatabaseModels/Label";
11
+ import IoTFleet from "../../Models/DatabaseModels/IoTFleet";
12
+ import IoTFleetLabelRuleService from "./IoTFleetLabelRuleService";
13
+ import IoTFleetService from "./IoTFleetService";
14
+ import ObjectID from "../../Types/ObjectID";
15
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
16
+ import logger from "../Utils/Logger";
17
+ class IoTFleetLabelRuleEngineServiceClass {
18
+ /**
19
+ * Evaluates IoTFleetLabelRule rows for the given IoT fleet and attaches matched
20
+ * labels to it. The union is deduped against labels already on the IoT fleet
21
+ * before insert to avoid PK conflicts on the join table.
22
+ */
23
+ async applyRulesToIoTFleet(iotFleet) {
24
+ var _a, _b;
25
+ if (!iotFleet.id || !iotFleet.projectId) {
26
+ return;
27
+ }
28
+ try {
29
+ const rules = await IoTFleetLabelRuleService.findBy({
30
+ query: {
31
+ projectId: iotFleet.projectId,
32
+ isEnabled: true,
33
+ },
34
+ props: { isRoot: true },
35
+ select: {
36
+ _id: true,
37
+ name: true,
38
+ iotFleetLabels: { _id: true },
39
+ iotFleetNamePattern: true,
40
+ iotFleetDescriptionPattern: true,
41
+ labelsToAdd: { _id: true },
42
+ },
43
+ limit: 100,
44
+ skip: 0,
45
+ });
46
+ if (rules.length === 0) {
47
+ return;
48
+ }
49
+ const iotFleetWithDetails = await IoTFleetService.findOneById({
50
+ id: iotFleet.id,
51
+ select: {
52
+ name: true,
53
+ description: true,
54
+ labels: { _id: true },
55
+ },
56
+ props: { isRoot: true },
57
+ });
58
+ if (!iotFleetWithDetails) {
59
+ return;
60
+ }
61
+ const labelIdsToAdd = new Set();
62
+ for (const rule of rules) {
63
+ const matches = this.doesIoTFleetMatchRule(iotFleetWithDetails, rule);
64
+ if (!matches) {
65
+ continue;
66
+ }
67
+ for (const label of rule.labelsToAdd || []) {
68
+ if (label.id) {
69
+ labelIdsToAdd.add(label.id.toString());
70
+ }
71
+ }
72
+ }
73
+ if (labelIdsToAdd.size === 0) {
74
+ return;
75
+ }
76
+ const existingLabelIds = new Set((iotFleetWithDetails.labels || [])
77
+ .map((l) => {
78
+ var _a;
79
+ return ((_a = l.id) === null || _a === void 0 ? void 0 : _a.toString()) || "";
80
+ })
81
+ .filter((id) => {
82
+ return id !== "";
83
+ }));
84
+ const newLabelIds = Array.from(labelIdsToAdd).filter((id) => {
85
+ return !existingLabelIds.has(id);
86
+ });
87
+ if (newLabelIds.length === 0) {
88
+ return;
89
+ }
90
+ await IoTFleetService.getRepository()
91
+ .createQueryBuilder()
92
+ .relation(IoTFleet, "labels")
93
+ .of(iotFleet.id.toString())
94
+ .add(newLabelIds);
95
+ /*
96
+ * Sync in-memory iotFleet.labels so a downstream owner-rule engine in
97
+ * the same onCreateSuccess chain can match on rule-added labels.
98
+ */
99
+ const mergedLabelIds = new Set([
100
+ ...existingLabelIds,
101
+ ...newLabelIds,
102
+ ]);
103
+ iotFleet.labels = Array.from(mergedLabelIds).map((id) => {
104
+ const label = new Label();
105
+ label.id = new ObjectID(id);
106
+ return label;
107
+ });
108
+ logger.debug(`IoTFleetLabelRuleEngine attached ${newLabelIds.length} labels to IoT fleet ${iotFleet.id}`, { projectId: iotFleet.projectId.toString() });
109
+ }
110
+ catch (error) {
111
+ logger.error(`Error applying IoT fleet label rules: ${error}`, {
112
+ projectId: (_a = iotFleet.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
113
+ iotFleetId: (_b = iotFleet.id) === null || _b === void 0 ? void 0 : _b.toString(),
114
+ });
115
+ }
116
+ }
117
+ doesIoTFleetMatchRule(iotFleet, rule) {
118
+ if (rule.iotFleetLabels && rule.iotFleetLabels.length > 0) {
119
+ if (!iotFleet.labels || iotFleet.labels.length === 0) {
120
+ return false;
121
+ }
122
+ const ruleLabelIds = rule.iotFleetLabels.map((l) => {
123
+ var _a;
124
+ return ((_a = l.id) === null || _a === void 0 ? void 0 : _a.toString()) || "";
125
+ });
126
+ const labelIds = iotFleet.labels.map((l) => {
127
+ var _a;
128
+ return ((_a = l.id) === null || _a === void 0 ? void 0 : _a.toString()) || "";
129
+ });
130
+ if (!ruleLabelIds.some((id) => {
131
+ return labelIds.includes(id);
132
+ })) {
133
+ return false;
134
+ }
135
+ }
136
+ if (rule.iotFleetNamePattern &&
137
+ (!iotFleet.name ||
138
+ !this.testRegex(rule.iotFleetNamePattern, iotFleet.name, rule))) {
139
+ return false;
140
+ }
141
+ if (rule.iotFleetDescriptionPattern &&
142
+ (!iotFleet.description ||
143
+ !this.testRegex(rule.iotFleetDescriptionPattern, iotFleet.description, rule))) {
144
+ return false;
145
+ }
146
+ return true;
147
+ }
148
+ testRegex(pattern, value, rule) {
149
+ try {
150
+ const regex = new RegExp(pattern, "i");
151
+ return regex.test(value);
152
+ }
153
+ catch (_a) {
154
+ logger.warn(`Invalid regex in IoT fleet label rule ${rule.id}: ${pattern}`);
155
+ return false;
156
+ }
157
+ }
158
+ }
159
+ __decorate([
160
+ CaptureSpan(),
161
+ __metadata("design:type", Function),
162
+ __metadata("design:paramtypes", [IoTFleet]),
163
+ __metadata("design:returntype", Promise)
164
+ ], IoTFleetLabelRuleEngineServiceClass.prototype, "applyRulesToIoTFleet", null);
165
+ export default new IoTFleetLabelRuleEngineServiceClass();
166
+ //# sourceMappingURL=IoTFleetLabelRuleEngineService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IoTFleetLabelRuleEngineService.js","sourceRoot":"","sources":["../../../../Server/Services/IoTFleetLabelRuleEngineService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/IoTFleetLabelRule";
3
+ import { IsBillingEnabled } from "../EnvironmentConfig";
4
+ export class Service extends DatabaseService {
5
+ constructor() {
6
+ super(Model);
7
+ if (IsBillingEnabled) {
8
+ this.hardDeleteItemsOlderThanInDays("createdAt", 3 * 365);
9
+ }
10
+ }
11
+ }
12
+ export default new Service();
13
+ //# sourceMappingURL=IoTFleetLabelRuleService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IoTFleetLabelRuleService.js","sourceRoot":"","sources":["../../../../Server/Services/IoTFleetLabelRuleService.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,MAAM,+CAA+C,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,OAAO,OAAQ,SAAQ,eAAsB;IACjD;QACE,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,gBAAgB,EAAE,CAAC;YACrB,IAAI,CAAC,8BAA8B,CAAC,WAAW,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;CACF;AAED,eAAe,IAAI,OAAO,EAAE,CAAC"}
@@ -0,0 +1,186 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import IoTFleet from "../../Models/DatabaseModels/IoTFleet";
11
+ import IoTFleetOwnerUser from "../../Models/DatabaseModels/IoTFleetOwnerUser";
12
+ import IoTFleetOwnerTeam from "../../Models/DatabaseModels/IoTFleetOwnerTeam";
13
+ import IoTFleetOwnerRuleService from "./IoTFleetOwnerRuleService";
14
+ import IoTFleetOwnerUserService from "./IoTFleetOwnerUserService";
15
+ import IoTFleetOwnerTeamService from "./IoTFleetOwnerTeamService";
16
+ import IoTFleetService from "./IoTFleetService";
17
+ import ObjectID from "../../Types/ObjectID";
18
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
19
+ import logger from "../Utils/Logger";
20
+ class IoTFleetOwnerRuleEngineServiceClass {
21
+ /**
22
+ * Evaluates IoTFleetOwnerRule rows for the given IoT fleet and adds matched
23
+ * owner users / teams via IoTFleetOwnerUserService / IoTFleetOwnerTeamService. Rules
24
+ * with notifyOwners set notify the added owners; rules with notifyOwners off
25
+ * add silently.
26
+ */
27
+ async applyRulesToIoTFleet(iotFleet) {
28
+ var _a, _b;
29
+ if (!iotFleet.id || !iotFleet.projectId) {
30
+ return;
31
+ }
32
+ try {
33
+ const rules = await IoTFleetOwnerRuleService.findBy({
34
+ query: {
35
+ projectId: iotFleet.projectId,
36
+ isEnabled: true,
37
+ },
38
+ props: { isRoot: true },
39
+ select: {
40
+ _id: true,
41
+ name: true,
42
+ notifyOwners: true,
43
+ iotFleetLabels: { _id: true },
44
+ iotFleetNamePattern: true,
45
+ iotFleetDescriptionPattern: true,
46
+ ownerUsers: { _id: true },
47
+ ownerTeams: { _id: true },
48
+ },
49
+ limit: 100,
50
+ skip: 0,
51
+ });
52
+ if (rules.length === 0) {
53
+ return;
54
+ }
55
+ const iotFleetWithDetails = await IoTFleetService.findOneById({
56
+ id: iotFleet.id,
57
+ select: {
58
+ name: true,
59
+ description: true,
60
+ labels: { _id: true },
61
+ },
62
+ props: { isRoot: true },
63
+ });
64
+ if (!iotFleetWithDetails) {
65
+ return;
66
+ }
67
+ const usersByNotify = new Map([
68
+ [true, new Set()],
69
+ [false, new Set()],
70
+ ]);
71
+ const teamsByNotify = new Map([
72
+ [true, new Set()],
73
+ [false, new Set()],
74
+ ]);
75
+ const matchedRules = [];
76
+ for (const rule of rules) {
77
+ const matches = this.doesIoTFleetMatchRule(iotFleetWithDetails, rule);
78
+ if (!matches) {
79
+ continue;
80
+ }
81
+ let ruleAddedAny = false;
82
+ const notify = rule.notifyOwners !== false;
83
+ for (const user of rule.ownerUsers || []) {
84
+ if (user.id) {
85
+ usersByNotify.get(notify).add(user.id.toString());
86
+ ruleAddedAny = true;
87
+ }
88
+ }
89
+ for (const team of rule.ownerTeams || []) {
90
+ if (team.id) {
91
+ teamsByNotify.get(notify).add(team.id.toString());
92
+ ruleAddedAny = true;
93
+ }
94
+ }
95
+ if (ruleAddedAny) {
96
+ matchedRules.push(rule);
97
+ }
98
+ }
99
+ if (matchedRules.length === 0) {
100
+ return;
101
+ }
102
+ for (const notify of [true, false]) {
103
+ const userIds = usersByNotify.get(notify);
104
+ const teamIds = teamsByNotify.get(notify);
105
+ for (const userId of userIds) {
106
+ const owner = new IoTFleetOwnerUser();
107
+ owner.iotFleetId = iotFleet.id;
108
+ owner.projectId = iotFleet.projectId;
109
+ owner.userId = new ObjectID(userId);
110
+ owner.isOwnerNotified = !notify;
111
+ await IoTFleetOwnerUserService.create({
112
+ data: owner,
113
+ props: { isRoot: true },
114
+ });
115
+ }
116
+ for (const teamId of teamIds) {
117
+ const owner = new IoTFleetOwnerTeam();
118
+ owner.iotFleetId = iotFleet.id;
119
+ owner.projectId = iotFleet.projectId;
120
+ owner.teamId = new ObjectID(teamId);
121
+ owner.isOwnerNotified = !notify;
122
+ await IoTFleetOwnerTeamService.create({
123
+ data: owner,
124
+ props: { isRoot: true },
125
+ });
126
+ }
127
+ }
128
+ logger.debug(`IoTFleetOwnerRuleEngine added owners to IoT fleet ${iotFleet.id}`, { projectId: iotFleet.projectId.toString() });
129
+ }
130
+ catch (error) {
131
+ logger.error(`Error applying IoT fleet owner rules: ${error}`, {
132
+ projectId: (_a = iotFleet.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
133
+ iotFleetId: (_b = iotFleet.id) === null || _b === void 0 ? void 0 : _b.toString(),
134
+ });
135
+ }
136
+ }
137
+ doesIoTFleetMatchRule(iotFleet, rule) {
138
+ if (rule.iotFleetLabels && rule.iotFleetLabels.length > 0) {
139
+ if (!iotFleet.labels || iotFleet.labels.length === 0) {
140
+ return false;
141
+ }
142
+ const ruleLabelIds = rule.iotFleetLabels.map((l) => {
143
+ var _a;
144
+ return ((_a = l.id) === null || _a === void 0 ? void 0 : _a.toString()) || "";
145
+ });
146
+ const labelIds = iotFleet.labels.map((l) => {
147
+ var _a;
148
+ return ((_a = l.id) === null || _a === void 0 ? void 0 : _a.toString()) || "";
149
+ });
150
+ if (!ruleLabelIds.some((id) => {
151
+ return labelIds.includes(id);
152
+ })) {
153
+ return false;
154
+ }
155
+ }
156
+ if (rule.iotFleetNamePattern &&
157
+ (!iotFleet.name ||
158
+ !this.testRegex(rule.iotFleetNamePattern, iotFleet.name, rule))) {
159
+ return false;
160
+ }
161
+ if (rule.iotFleetDescriptionPattern &&
162
+ (!iotFleet.description ||
163
+ !this.testRegex(rule.iotFleetDescriptionPattern, iotFleet.description, rule))) {
164
+ return false;
165
+ }
166
+ return true;
167
+ }
168
+ testRegex(pattern, value, rule) {
169
+ try {
170
+ const regex = new RegExp(pattern, "i");
171
+ return regex.test(value);
172
+ }
173
+ catch (_a) {
174
+ logger.warn(`Invalid regex in IoT fleet owner rule ${rule.id}: ${pattern}`);
175
+ return false;
176
+ }
177
+ }
178
+ }
179
+ __decorate([
180
+ CaptureSpan(),
181
+ __metadata("design:type", Function),
182
+ __metadata("design:paramtypes", [IoTFleet]),
183
+ __metadata("design:returntype", Promise)
184
+ ], IoTFleetOwnerRuleEngineServiceClass.prototype, "applyRulesToIoTFleet", null);
185
+ export default new IoTFleetOwnerRuleEngineServiceClass();
186
+ //# sourceMappingURL=IoTFleetOwnerRuleEngineService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IoTFleetOwnerRuleEngineService.js","sourceRoot":"","sources":["../../../../Server/Services/IoTFleetOwnerRuleEngineService.ts"],"names":[],"mappings":"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"}