@oneuptime/common 10.4.11 → 10.4.13

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 (117) hide show
  1. package/Models/DatabaseModels/Alert.ts +332 -0
  2. package/Models/DatabaseModels/Incident.ts +332 -0
  3. package/Models/DatabaseModels/RunbookAgent.ts +16 -2
  4. package/Server/EnvironmentConfig.ts +16 -0
  5. package/Server/Infrastructure/ClickhouseConfig.ts +14 -0
  6. package/Server/Infrastructure/ClickhouseDatabase.ts +20 -3
  7. package/Server/Infrastructure/InMemoryTTLCache.ts +61 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1779302536475-AttachKubernetesAndDockerToIncidentAndAlert.ts +253 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/1779303924241-AttachServiceToIncidentAndAlert.ts +60 -0
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
  11. package/Server/Middleware/TelemetryIngest.ts +6 -38
  12. package/Server/Middleware/UserAuthorization.ts +1 -11
  13. package/Server/Services/AnalyticsDatabaseService.ts +33 -1
  14. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +6 -0
  15. package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +1 -0
  16. package/Server/Services/OnCallDutyPolicyScheduleService.ts +17 -0
  17. package/Server/Services/TelemetryIngestionKeyService.ts +90 -1
  18. package/Server/Utils/Monitor/Criteria/DnssecMonitorCriteria.ts +108 -0
  19. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +13 -0
  20. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +25 -0
  21. package/Tests/Server/Middleware/UserAuthorization.test.ts +0 -7
  22. package/Types/Dashboard/DashboardComponentType.ts +0 -1
  23. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +2 -0
  24. package/Types/Dashboard/DashboardComponents/DashboardTableComponent.ts +74 -1
  25. package/Types/Dashboard/DashboardTemplates.ts +164 -51
  26. package/Types/Monitor/CriteriaFilter.ts +13 -0
  27. package/Types/Monitor/DnssecMonitor/DnssecMonitorResponse.ts +69 -0
  28. package/Types/Monitor/MonitorCriteriaInstance.ts +67 -0
  29. package/Types/Monitor/MonitorStep.ts +39 -0
  30. package/Types/Monitor/MonitorStepDnssecMonitor.ts +59 -0
  31. package/Types/Monitor/MonitorType.ts +18 -2
  32. package/Types/OnCallDutyPolicy/UserOverrideUtil.ts +36 -9
  33. package/Types/Probe/ProbeMonitorResponse.ts +2 -0
  34. package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +51 -0
  35. package/Utils/Dashboard/Components/DashboardTableComponent.ts +80 -17
  36. package/Utils/Dashboard/Components/Index.ts +0 -7
  37. package/Utils/Monitor/MonitorMetricType.ts +1 -0
  38. package/build/dist/Models/DatabaseModels/Alert.js +324 -0
  39. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  40. package/build/dist/Models/DatabaseModels/Incident.js +324 -0
  41. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  42. package/build/dist/Models/DatabaseModels/RunbookAgent.js +16 -2
  43. package/build/dist/Models/DatabaseModels/RunbookAgent.js.map +1 -1
  44. package/build/dist/Server/EnvironmentConfig.js +8 -0
  45. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  46. package/build/dist/Server/Infrastructure/ClickhouseConfig.js +9 -1
  47. package/build/dist/Server/Infrastructure/ClickhouseConfig.js.map +1 -1
  48. package/build/dist/Server/Infrastructure/ClickhouseDatabase.js +12 -3
  49. package/build/dist/Server/Infrastructure/ClickhouseDatabase.js.map +1 -1
  50. package/build/dist/Server/Infrastructure/InMemoryTTLCache.js +49 -0
  51. package/build/dist/Server/Infrastructure/InMemoryTTLCache.js.map +1 -0
  52. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779302536475-AttachKubernetesAndDockerToIncidentAndAlert.js +100 -0
  53. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779302536475-AttachKubernetesAndDockerToIncidentAndAlert.js.map +1 -0
  54. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779303924241-AttachServiceToIncidentAndAlert.js +28 -0
  55. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779303924241-AttachServiceToIncidentAndAlert.js.map +1 -0
  56. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
  57. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  58. package/build/dist/Server/Middleware/TelemetryIngest.js +2 -26
  59. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  60. package/build/dist/Server/Middleware/UserAuthorization.js +1 -7
  61. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  62. package/build/dist/Server/Services/AnalyticsDatabaseService.js +23 -2
  63. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  64. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +28 -24
  65. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  66. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +1 -1
  67. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
  68. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +18 -2
  69. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  70. package/build/dist/Server/Services/TelemetryIngestionKeyService.js +83 -0
  71. package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
  72. package/build/dist/Server/Utils/Monitor/Criteria/DnssecMonitorCriteria.js +94 -0
  73. package/build/dist/Server/Utils/Monitor/Criteria/DnssecMonitorCriteria.js.map +1 -0
  74. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +10 -0
  75. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  76. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +22 -3
  77. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  78. package/build/dist/Tests/Server/Middleware/UserAuthorization.test.js +0 -7
  79. package/build/dist/Tests/Server/Middleware/UserAuthorization.test.js.map +1 -1
  80. package/build/dist/Types/Dashboard/DashboardComponentType.js +0 -1
  81. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  82. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +2 -0
  83. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  84. package/build/dist/Types/Dashboard/DashboardComponents/DashboardTableComponent.js +13 -1
  85. package/build/dist/Types/Dashboard/DashboardComponents/DashboardTableComponent.js.map +1 -1
  86. package/build/dist/Types/Dashboard/DashboardTemplates.js +142 -42
  87. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  88. package/build/dist/Types/Monitor/CriteriaFilter.js +12 -0
  89. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  90. package/build/dist/Types/Monitor/DnssecMonitor/DnssecMonitorResponse.js +2 -0
  91. package/build/dist/Types/Monitor/DnssecMonitor/DnssecMonitorResponse.js.map +1 -0
  92. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +62 -0
  93. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  94. package/build/dist/Types/Monitor/MonitorStep.js +26 -0
  95. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  96. package/build/dist/Types/Monitor/MonitorStepDnssecMonitor.js +42 -0
  97. package/build/dist/Types/Monitor/MonitorStepDnssecMonitor.js.map +1 -0
  98. package/build/dist/Types/Monitor/MonitorType.js +16 -2
  99. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  100. package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js +27 -7
  101. package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js.map +1 -1
  102. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +47 -0
  103. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
  104. package/build/dist/Utils/Dashboard/Components/DashboardTableComponent.js +68 -16
  105. package/build/dist/Utils/Dashboard/Components/DashboardTableComponent.js.map +1 -1
  106. package/build/dist/Utils/Dashboard/Components/Index.js +0 -4
  107. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  108. package/build/dist/Utils/Monitor/MonitorMetricType.js +1 -0
  109. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
  110. package/package.json +1 -2
  111. package/Types/Dashboard/DashboardComponents/DashboardHostMetricChartComponent.ts +0 -27
  112. package/Typings/elkjs.d.ts +0 -30
  113. package/Utils/Dashboard/Components/DashboardHostMetricChartComponent.ts +0 -132
  114. package/build/dist/Types/Dashboard/DashboardComponents/DashboardHostMetricChartComponent.js +0 -11
  115. package/build/dist/Types/Dashboard/DashboardComponents/DashboardHostMetricChartComponent.js.map +0 -1
  116. package/build/dist/Utils/Dashboard/Components/DashboardHostMetricChartComponent.js +0 -113
  117. package/build/dist/Utils/Dashboard/Components/DashboardHostMetricChartComponent.js.map +0 -1
@@ -313,7 +313,14 @@ export default class RunbookAgent extends BaseModel {
313
313
  public key?: string = undefined;
314
314
 
315
315
  @ColumnAccessControl({
316
- create: [],
316
+ create: [
317
+ Permission.ProjectOwner,
318
+ Permission.ProjectAdmin,
319
+ Permission.ProjectMember,
320
+ Permission.RunbookAdmin,
321
+ Permission.RunbookMember,
322
+ Permission.CreateRunbookAgent,
323
+ ],
317
324
  read: [
318
325
  Permission.ProjectOwner,
319
326
  Permission.ProjectAdmin,
@@ -369,7 +376,14 @@ export default class RunbookAgent extends BaseModel {
369
376
  public lastAlive?: Date = undefined;
370
377
 
371
378
  @ColumnAccessControl({
372
- create: [],
379
+ create: [
380
+ Permission.ProjectOwner,
381
+ Permission.ProjectAdmin,
382
+ Permission.ProjectMember,
383
+ Permission.RunbookAdmin,
384
+ Permission.RunbookMember,
385
+ Permission.CreateRunbookAgent,
386
+ ],
373
387
  read: [
374
388
  Permission.ProjectOwner,
375
389
  Permission.ProjectAdmin,
@@ -285,6 +285,22 @@ export const ShouldClickhouseSslEnable: boolean = Boolean(
285
285
  ClickhouseTlsCa || (ClickhouseTlsCert && ClickhouseTlsKey),
286
286
  );
287
287
 
288
+ export const MaxClickhouseConnections: number = parseInt(
289
+ process.env["CLICKHOUSE_MAX_OPEN_CONNECTIONS"] || "100",
290
+ 10,
291
+ );
292
+
293
+ /*
294
+ * Ingest pool size. Falls back to MaxClickhouseConnections so single-knob
295
+ * setups still work; override only when the ingest pool needs to be sized
296
+ * independently from the query pool.
297
+ */
298
+ export const MaxClickhouseIngestConnections: number = parseInt(
299
+ process.env["CLICKHOUSE_INGEST_MAX_OPEN_CONNECTIONS"] ||
300
+ String(MaxClickhouseConnections),
301
+ 10,
302
+ );
303
+
288
304
  export const GitSha: string = process.env["GIT_SHA"] || "unknown";
289
305
 
290
306
  export const AppVersion: string = process.env["APP_VERSION"] || "unknown";
@@ -9,6 +9,8 @@ import {
9
9
  ClickhouseTlsCert,
10
10
  ClickhouseTlsKey,
11
11
  ClickhouseUsername,
12
+ MaxClickhouseConnections,
13
+ MaxClickhouseIngestConnections,
12
14
  ShouldClickhouseSslEnable,
13
15
  } from "../EnvironmentConfig";
14
16
  import Hostname from "../../Types/API/Hostname";
@@ -35,6 +37,13 @@ const options: ClickHouseClientConfigOptions = {
35
37
  * aggregation statements provides the hard server-side cap.
36
38
  */
37
39
  request_timeout: 58_000,
40
+ /*
41
+ * @clickhouse/client defaults max_open_connections to 10. Sized for the
42
+ * query pool (dashboard reads, DDL); ingest writes use a separate pool
43
+ * (see ingestDataSourceOptions) so a burst of inserts cannot starve
44
+ * user-facing queries of HTTP sockets.
45
+ */
46
+ max_open_connections: MaxClickhouseConnections,
38
47
  };
39
48
 
40
49
  if (ShouldClickhouseSslEnable && ClickhouseTlsCa) {
@@ -58,5 +67,10 @@ if (
58
67
 
59
68
  export const dataSourceOptions: ClickHouseClientConfigOptions = options;
60
69
 
70
+ export const ingestDataSourceOptions: ClickHouseClientConfigOptions = {
71
+ ...options,
72
+ max_open_connections: MaxClickhouseIngestConnections,
73
+ };
74
+
61
75
  export const testDataSourceOptions: ClickHouseClientConfigOptions =
62
76
  dataSourceOptions;
@@ -2,6 +2,7 @@ import logger from "../Utils/Logger";
2
2
  import {
3
3
  ClickHouseClientConfigOptions,
4
4
  dataSourceOptions,
5
+ ingestDataSourceOptions,
5
6
  testDataSourceOptions,
6
7
  } from "./ClickhouseConfig";
7
8
  import { PingResult, createClient, ClickHouseClient } from "@clickhouse/client";
@@ -18,9 +19,16 @@ export type ClickhouseClient = ClickHouseClient;
18
19
 
19
20
  export default class ClickhouseDatabase {
20
21
  private dataSource!: ClickhouseClient | null;
22
+ private options: ClickHouseClientConfigOptions;
23
+
24
+ public constructor(
25
+ options: ClickHouseClientConfigOptions = dataSourceOptions,
26
+ ) {
27
+ this.options = options;
28
+ }
21
29
 
22
30
  public getDatasourceOptions(): ClickHouseClientConfigOptions {
23
- return dataSourceOptions;
31
+ return this.options;
24
32
  }
25
33
 
26
34
  public getTestDatasourceOptions(): ClickHouseClientConfigOptions {
@@ -161,5 +169,14 @@ export default class ClickhouseDatabase {
161
169
  }
162
170
  }
163
171
 
164
- export const ClickhouseAppInstance: ClickhouseDatabase =
165
- new ClickhouseDatabase();
172
+ export const ClickhouseAppInstance: ClickhouseDatabase = new ClickhouseDatabase(
173
+ dataSourceOptions,
174
+ );
175
+
176
+ /*
177
+ * Separate pool for high-volume telemetry inserts. Reads/DDL keep using
178
+ * ClickhouseAppInstance so dashboard queries are not starved of HTTP
179
+ * sockets when ingest is bursting.
180
+ */
181
+ export const ClickhouseIngestInstance: ClickhouseDatabase =
182
+ new ClickhouseDatabase(ingestDataSourceOptions);
@@ -0,0 +1,61 @@
1
+ interface CacheEntry<T> {
2
+ value: T;
3
+ expiresAt: number;
4
+ }
5
+
6
+ /**
7
+ * Bounded, in-process TTL cache. Entries expire on read after their TTL and the
8
+ * oldest entry is evicted when capacity is reached (Map preserves insertion
9
+ * order, which we use as a coarse LRU on writes).
10
+ *
11
+ * Each process holds its own copy — there is no cross-process invalidation.
12
+ * Callers that need stronger consistency should pair the TTL with an explicit
13
+ * `delete()` on writes to the underlying data.
14
+ */
15
+ export default class InMemoryTTLCache<T> {
16
+ private store: Map<string, CacheEntry<T>> = new Map();
17
+ private maxEntries: number;
18
+
19
+ public constructor(maxEntries: number = 10_000) {
20
+ this.maxEntries = maxEntries;
21
+ }
22
+
23
+ public set(key: string, value: T, ttlMs: number): void {
24
+ if (this.store.size >= this.maxEntries && !this.store.has(key)) {
25
+ const oldest: string | undefined = this.store.keys().next().value;
26
+ if (oldest !== undefined) {
27
+ this.store.delete(oldest);
28
+ }
29
+ }
30
+ this.store.delete(key);
31
+ this.store.set(key, { value, expiresAt: Date.now() + ttlMs });
32
+ }
33
+
34
+ public get(key: string): T | undefined {
35
+ const entry: CacheEntry<T> | undefined = this.store.get(key);
36
+ if (!entry) {
37
+ return undefined;
38
+ }
39
+ if (Date.now() > entry.expiresAt) {
40
+ this.store.delete(key);
41
+ return undefined;
42
+ }
43
+ return entry.value;
44
+ }
45
+
46
+ public has(key: string): boolean {
47
+ return this.get(key) !== undefined;
48
+ }
49
+
50
+ public delete(key: string): void {
51
+ this.store.delete(key);
52
+ }
53
+
54
+ public clear(): void {
55
+ this.store.clear();
56
+ }
57
+
58
+ public size(): number {
59
+ return this.store.size;
60
+ }
61
+ }
@@ -0,0 +1,253 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class AttachKubernetesAndDockerToIncidentAndAlert1779302536475
4
+ implements MigrationInterface
5
+ {
6
+ public name: string =
7
+ "AttachKubernetesAndDockerToIncidentAndAlert1779302536475";
8
+
9
+ public async up(queryRunner: QueryRunner): Promise<void> {
10
+ // IncidentKubernetesCluster
11
+ await queryRunner.query(
12
+ `CREATE TABLE "IncidentKubernetesCluster" ("incidentId" uuid NOT NULL, "kubernetesClusterId" uuid NOT NULL, CONSTRAINT "PK_0706004605b87701df3fb2fc4fb" PRIMARY KEY ("incidentId", "kubernetesClusterId"))`,
13
+ );
14
+ await queryRunner.query(
15
+ `CREATE INDEX "IDX_4d49468cbea4ece4fe7e2ecf3f" ON "IncidentKubernetesCluster" ("incidentId") `,
16
+ );
17
+ await queryRunner.query(
18
+ `CREATE INDEX "IDX_cb313f51853d6178c1ea498405" ON "IncidentKubernetesCluster" ("kubernetesClusterId") `,
19
+ );
20
+ await queryRunner.query(
21
+ `ALTER TABLE "IncidentKubernetesCluster" ADD CONSTRAINT "FK_4d49468cbea4ece4fe7e2ecf3f8" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
22
+ );
23
+ await queryRunner.query(
24
+ `ALTER TABLE "IncidentKubernetesCluster" ADD CONSTRAINT "FK_cb313f51853d6178c1ea498405e" FOREIGN KEY ("kubernetesClusterId") REFERENCES "KubernetesCluster"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
25
+ );
26
+
27
+ // IncidentKubernetesResource
28
+ await queryRunner.query(
29
+ `CREATE TABLE "IncidentKubernetesResource" ("incidentId" uuid NOT NULL, "kubernetesResourceId" uuid NOT NULL, CONSTRAINT "PK_2d7d43459ccef0edddd433dab0f" PRIMARY KEY ("incidentId", "kubernetesResourceId"))`,
30
+ );
31
+ await queryRunner.query(
32
+ `CREATE INDEX "IDX_706dad5f9b04e57516310bb107" ON "IncidentKubernetesResource" ("incidentId") `,
33
+ );
34
+ await queryRunner.query(
35
+ `CREATE INDEX "IDX_bd41e6a5b7368685534190f8e8" ON "IncidentKubernetesResource" ("kubernetesResourceId") `,
36
+ );
37
+ await queryRunner.query(
38
+ `ALTER TABLE "IncidentKubernetesResource" ADD CONSTRAINT "FK_706dad5f9b04e57516310bb1076" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
39
+ );
40
+ await queryRunner.query(
41
+ `ALTER TABLE "IncidentKubernetesResource" ADD CONSTRAINT "FK_bd41e6a5b7368685534190f8e85" FOREIGN KEY ("kubernetesResourceId") REFERENCES "KubernetesResource"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
42
+ );
43
+
44
+ // IncidentKubernetesContainer
45
+ await queryRunner.query(
46
+ `CREATE TABLE "IncidentKubernetesContainer" ("incidentId" uuid NOT NULL, "kubernetesContainerId" uuid NOT NULL, CONSTRAINT "PK_96c823347cee097c4c99d60d472" PRIMARY KEY ("incidentId", "kubernetesContainerId"))`,
47
+ );
48
+ await queryRunner.query(
49
+ `CREATE INDEX "IDX_318c277a133ab782087eee5a93" ON "IncidentKubernetesContainer" ("incidentId") `,
50
+ );
51
+ await queryRunner.query(
52
+ `CREATE INDEX "IDX_411d29efab26561877b148bb21" ON "IncidentKubernetesContainer" ("kubernetesContainerId") `,
53
+ );
54
+ await queryRunner.query(
55
+ `ALTER TABLE "IncidentKubernetesContainer" ADD CONSTRAINT "FK_318c277a133ab782087eee5a93b" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
56
+ );
57
+ await queryRunner.query(
58
+ `ALTER TABLE "IncidentKubernetesContainer" ADD CONSTRAINT "FK_411d29efab26561877b148bb218" FOREIGN KEY ("kubernetesContainerId") REFERENCES "KubernetesContainer"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
59
+ );
60
+
61
+ // IncidentDockerHost
62
+ await queryRunner.query(
63
+ `CREATE TABLE "IncidentDockerHost" ("incidentId" uuid NOT NULL, "dockerHostId" uuid NOT NULL, CONSTRAINT "PK_56a970e60a6af0ae3bc03952a82" PRIMARY KEY ("incidentId", "dockerHostId"))`,
64
+ );
65
+ await queryRunner.query(
66
+ `CREATE INDEX "IDX_364b7b272015813b8ee02314c4" ON "IncidentDockerHost" ("incidentId") `,
67
+ );
68
+ await queryRunner.query(
69
+ `CREATE INDEX "IDX_9761ce8eb83f4d63d7fef00a55" ON "IncidentDockerHost" ("dockerHostId") `,
70
+ );
71
+ await queryRunner.query(
72
+ `ALTER TABLE "IncidentDockerHost" ADD CONSTRAINT "FK_364b7b272015813b8ee02314c45" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
73
+ );
74
+ await queryRunner.query(
75
+ `ALTER TABLE "IncidentDockerHost" ADD CONSTRAINT "FK_9761ce8eb83f4d63d7fef00a55c" FOREIGN KEY ("dockerHostId") REFERENCES "DockerHost"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
76
+ );
77
+
78
+ // IncidentDockerResource
79
+ await queryRunner.query(
80
+ `CREATE TABLE "IncidentDockerResource" ("incidentId" uuid NOT NULL, "dockerResourceId" uuid NOT NULL, CONSTRAINT "PK_5c1f59bafc8278da53767c2aeae" PRIMARY KEY ("incidentId", "dockerResourceId"))`,
81
+ );
82
+ await queryRunner.query(
83
+ `CREATE INDEX "IDX_5a1cf0cb50fec5135cfd715e2c" ON "IncidentDockerResource" ("incidentId") `,
84
+ );
85
+ await queryRunner.query(
86
+ `CREATE INDEX "IDX_c90832cd0bce96661ae3e3652c" ON "IncidentDockerResource" ("dockerResourceId") `,
87
+ );
88
+ await queryRunner.query(
89
+ `ALTER TABLE "IncidentDockerResource" ADD CONSTRAINT "FK_5a1cf0cb50fec5135cfd715e2cb" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
90
+ );
91
+ await queryRunner.query(
92
+ `ALTER TABLE "IncidentDockerResource" ADD CONSTRAINT "FK_c90832cd0bce96661ae3e3652cc" FOREIGN KEY ("dockerResourceId") REFERENCES "DockerResource"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
93
+ );
94
+
95
+ // AlertKubernetesCluster
96
+ await queryRunner.query(
97
+ `CREATE TABLE "AlertKubernetesCluster" ("alertId" uuid NOT NULL, "kubernetesClusterId" uuid NOT NULL, CONSTRAINT "PK_36951c4b963d30a51d49db2f185" PRIMARY KEY ("alertId", "kubernetesClusterId"))`,
98
+ );
99
+ await queryRunner.query(
100
+ `CREATE INDEX "IDX_9c59dd1fbaa2623c55147588fa" ON "AlertKubernetesCluster" ("alertId") `,
101
+ );
102
+ await queryRunner.query(
103
+ `CREATE INDEX "IDX_b880dd9641b488d37e9c4dbc96" ON "AlertKubernetesCluster" ("kubernetesClusterId") `,
104
+ );
105
+ await queryRunner.query(
106
+ `ALTER TABLE "AlertKubernetesCluster" ADD CONSTRAINT "FK_9c59dd1fbaa2623c55147588fa4" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
107
+ );
108
+ await queryRunner.query(
109
+ `ALTER TABLE "AlertKubernetesCluster" ADD CONSTRAINT "FK_b880dd9641b488d37e9c4dbc967" FOREIGN KEY ("kubernetesClusterId") REFERENCES "KubernetesCluster"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
110
+ );
111
+
112
+ // AlertKubernetesResource
113
+ await queryRunner.query(
114
+ `CREATE TABLE "AlertKubernetesResource" ("alertId" uuid NOT NULL, "kubernetesResourceId" uuid NOT NULL, CONSTRAINT "PK_55c136562d0b3ca986eedd20344" PRIMARY KEY ("alertId", "kubernetesResourceId"))`,
115
+ );
116
+ await queryRunner.query(
117
+ `CREATE INDEX "IDX_09847045f3b90d01b5d5116a27" ON "AlertKubernetesResource" ("alertId") `,
118
+ );
119
+ await queryRunner.query(
120
+ `CREATE INDEX "IDX_04479f7cd61764c417284364e4" ON "AlertKubernetesResource" ("kubernetesResourceId") `,
121
+ );
122
+ await queryRunner.query(
123
+ `ALTER TABLE "AlertKubernetesResource" ADD CONSTRAINT "FK_09847045f3b90d01b5d5116a278" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
124
+ );
125
+ await queryRunner.query(
126
+ `ALTER TABLE "AlertKubernetesResource" ADD CONSTRAINT "FK_04479f7cd61764c417284364e49" FOREIGN KEY ("kubernetesResourceId") REFERENCES "KubernetesResource"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
127
+ );
128
+
129
+ // AlertKubernetesContainer
130
+ await queryRunner.query(
131
+ `CREATE TABLE "AlertKubernetesContainer" ("alertId" uuid NOT NULL, "kubernetesContainerId" uuid NOT NULL, CONSTRAINT "PK_5004da87e6cee38c2cdce1c015b" PRIMARY KEY ("alertId", "kubernetesContainerId"))`,
132
+ );
133
+ await queryRunner.query(
134
+ `CREATE INDEX "IDX_e5e3b19d56842d98ad736f2451" ON "AlertKubernetesContainer" ("alertId") `,
135
+ );
136
+ await queryRunner.query(
137
+ `CREATE INDEX "IDX_cc7bd03e0d9fec67856319959b" ON "AlertKubernetesContainer" ("kubernetesContainerId") `,
138
+ );
139
+ await queryRunner.query(
140
+ `ALTER TABLE "AlertKubernetesContainer" ADD CONSTRAINT "FK_e5e3b19d56842d98ad736f2451e" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
141
+ );
142
+ await queryRunner.query(
143
+ `ALTER TABLE "AlertKubernetesContainer" ADD CONSTRAINT "FK_cc7bd03e0d9fec67856319959be" FOREIGN KEY ("kubernetesContainerId") REFERENCES "KubernetesContainer"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
144
+ );
145
+
146
+ // AlertDockerHost
147
+ await queryRunner.query(
148
+ `CREATE TABLE "AlertDockerHost" ("alertId" uuid NOT NULL, "dockerHostId" uuid NOT NULL, CONSTRAINT "PK_12c730ea1126a0cccde73ce819e" PRIMARY KEY ("alertId", "dockerHostId"))`,
149
+ );
150
+ await queryRunner.query(
151
+ `CREATE INDEX "IDX_2b33c4643132be69e65dc48653" ON "AlertDockerHost" ("alertId") `,
152
+ );
153
+ await queryRunner.query(
154
+ `CREATE INDEX "IDX_e98f39fecd1bc955015882ca34" ON "AlertDockerHost" ("dockerHostId") `,
155
+ );
156
+ await queryRunner.query(
157
+ `ALTER TABLE "AlertDockerHost" ADD CONSTRAINT "FK_2b33c4643132be69e65dc48653c" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
158
+ );
159
+ await queryRunner.query(
160
+ `ALTER TABLE "AlertDockerHost" ADD CONSTRAINT "FK_e98f39fecd1bc955015882ca34b" FOREIGN KEY ("dockerHostId") REFERENCES "DockerHost"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
161
+ );
162
+
163
+ // AlertDockerResource
164
+ await queryRunner.query(
165
+ `CREATE TABLE "AlertDockerResource" ("alertId" uuid NOT NULL, "dockerResourceId" uuid NOT NULL, CONSTRAINT "PK_60dbce6b63a1cac67178bbb3998" PRIMARY KEY ("alertId", "dockerResourceId"))`,
166
+ );
167
+ await queryRunner.query(
168
+ `CREATE INDEX "IDX_8843cfc9ef7118e39a40d32548" ON "AlertDockerResource" ("alertId") `,
169
+ );
170
+ await queryRunner.query(
171
+ `CREATE INDEX "IDX_c781b3411915ba016ea3fc30fd" ON "AlertDockerResource" ("dockerResourceId") `,
172
+ );
173
+ await queryRunner.query(
174
+ `ALTER TABLE "AlertDockerResource" ADD CONSTRAINT "FK_8843cfc9ef7118e39a40d325489" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
175
+ );
176
+ await queryRunner.query(
177
+ `ALTER TABLE "AlertDockerResource" ADD CONSTRAINT "FK_c781b3411915ba016ea3fc30fd3" FOREIGN KEY ("dockerResourceId") REFERENCES "DockerResource"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
178
+ );
179
+ }
180
+
181
+ public async down(queryRunner: QueryRunner): Promise<void> {
182
+ await queryRunner.query(
183
+ `ALTER TABLE "AlertDockerResource" DROP CONSTRAINT "FK_c781b3411915ba016ea3fc30fd3"`,
184
+ );
185
+ await queryRunner.query(
186
+ `ALTER TABLE "AlertDockerResource" DROP CONSTRAINT "FK_8843cfc9ef7118e39a40d325489"`,
187
+ );
188
+ await queryRunner.query(
189
+ `ALTER TABLE "AlertDockerHost" DROP CONSTRAINT "FK_e98f39fecd1bc955015882ca34b"`,
190
+ );
191
+ await queryRunner.query(
192
+ `ALTER TABLE "AlertDockerHost" DROP CONSTRAINT "FK_2b33c4643132be69e65dc48653c"`,
193
+ );
194
+ await queryRunner.query(
195
+ `ALTER TABLE "AlertKubernetesContainer" DROP CONSTRAINT "FK_cc7bd03e0d9fec67856319959be"`,
196
+ );
197
+ await queryRunner.query(
198
+ `ALTER TABLE "AlertKubernetesContainer" DROP CONSTRAINT "FK_e5e3b19d56842d98ad736f2451e"`,
199
+ );
200
+ await queryRunner.query(
201
+ `ALTER TABLE "AlertKubernetesResource" DROP CONSTRAINT "FK_04479f7cd61764c417284364e49"`,
202
+ );
203
+ await queryRunner.query(
204
+ `ALTER TABLE "AlertKubernetesResource" DROP CONSTRAINT "FK_09847045f3b90d01b5d5116a278"`,
205
+ );
206
+ await queryRunner.query(
207
+ `ALTER TABLE "AlertKubernetesCluster" DROP CONSTRAINT "FK_b880dd9641b488d37e9c4dbc967"`,
208
+ );
209
+ await queryRunner.query(
210
+ `ALTER TABLE "AlertKubernetesCluster" DROP CONSTRAINT "FK_9c59dd1fbaa2623c55147588fa4"`,
211
+ );
212
+ await queryRunner.query(
213
+ `ALTER TABLE "IncidentDockerResource" DROP CONSTRAINT "FK_c90832cd0bce96661ae3e3652cc"`,
214
+ );
215
+ await queryRunner.query(
216
+ `ALTER TABLE "IncidentDockerResource" DROP CONSTRAINT "FK_5a1cf0cb50fec5135cfd715e2cb"`,
217
+ );
218
+ await queryRunner.query(
219
+ `ALTER TABLE "IncidentDockerHost" DROP CONSTRAINT "FK_9761ce8eb83f4d63d7fef00a55c"`,
220
+ );
221
+ await queryRunner.query(
222
+ `ALTER TABLE "IncidentDockerHost" DROP CONSTRAINT "FK_364b7b272015813b8ee02314c45"`,
223
+ );
224
+ await queryRunner.query(
225
+ `ALTER TABLE "IncidentKubernetesContainer" DROP CONSTRAINT "FK_411d29efab26561877b148bb218"`,
226
+ );
227
+ await queryRunner.query(
228
+ `ALTER TABLE "IncidentKubernetesContainer" DROP CONSTRAINT "FK_318c277a133ab782087eee5a93b"`,
229
+ );
230
+ await queryRunner.query(
231
+ `ALTER TABLE "IncidentKubernetesResource" DROP CONSTRAINT "FK_bd41e6a5b7368685534190f8e85"`,
232
+ );
233
+ await queryRunner.query(
234
+ `ALTER TABLE "IncidentKubernetesResource" DROP CONSTRAINT "FK_706dad5f9b04e57516310bb1076"`,
235
+ );
236
+ await queryRunner.query(
237
+ `ALTER TABLE "IncidentKubernetesCluster" DROP CONSTRAINT "FK_cb313f51853d6178c1ea498405e"`,
238
+ );
239
+ await queryRunner.query(
240
+ `ALTER TABLE "IncidentKubernetesCluster" DROP CONSTRAINT "FK_4d49468cbea4ece4fe7e2ecf3f8"`,
241
+ );
242
+ await queryRunner.query(`DROP TABLE "AlertDockerResource"`);
243
+ await queryRunner.query(`DROP TABLE "AlertDockerHost"`);
244
+ await queryRunner.query(`DROP TABLE "AlertKubernetesContainer"`);
245
+ await queryRunner.query(`DROP TABLE "AlertKubernetesResource"`);
246
+ await queryRunner.query(`DROP TABLE "AlertKubernetesCluster"`);
247
+ await queryRunner.query(`DROP TABLE "IncidentDockerResource"`);
248
+ await queryRunner.query(`DROP TABLE "IncidentDockerHost"`);
249
+ await queryRunner.query(`DROP TABLE "IncidentKubernetesContainer"`);
250
+ await queryRunner.query(`DROP TABLE "IncidentKubernetesResource"`);
251
+ await queryRunner.query(`DROP TABLE "IncidentKubernetesCluster"`);
252
+ }
253
+ }
@@ -0,0 +1,60 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class AttachServiceToIncidentAndAlert1779303924241
4
+ implements MigrationInterface
5
+ {
6
+ public name: string = "AttachServiceToIncidentAndAlert1779303924241";
7
+
8
+ public async up(queryRunner: QueryRunner): Promise<void> {
9
+ // IncidentService
10
+ await queryRunner.query(
11
+ `CREATE TABLE "IncidentService" ("incidentId" uuid NOT NULL, "serviceId" uuid NOT NULL, CONSTRAINT "PK_f4278c4ad966e1388f6aa832b98" PRIMARY KEY ("incidentId", "serviceId"))`,
12
+ );
13
+ await queryRunner.query(
14
+ `CREATE INDEX "IDX_9b8061de368e0c38bf78fc1412" ON "IncidentService" ("incidentId") `,
15
+ );
16
+ await queryRunner.query(
17
+ `CREATE INDEX "IDX_780433e4b5ce2df00b7dc2b30b" ON "IncidentService" ("serviceId") `,
18
+ );
19
+ await queryRunner.query(
20
+ `ALTER TABLE "IncidentService" ADD CONSTRAINT "FK_9b8061de368e0c38bf78fc1412d" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
21
+ );
22
+ await queryRunner.query(
23
+ `ALTER TABLE "IncidentService" ADD CONSTRAINT "FK_780433e4b5ce2df00b7dc2b30b6" FOREIGN KEY ("serviceId") REFERENCES "Service"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
24
+ );
25
+
26
+ // AlertService
27
+ await queryRunner.query(
28
+ `CREATE TABLE "AlertService" ("alertId" uuid NOT NULL, "serviceId" uuid NOT NULL, CONSTRAINT "PK_eb1648d9ffb96bf6c38d90c4293" PRIMARY KEY ("alertId", "serviceId"))`,
29
+ );
30
+ await queryRunner.query(
31
+ `CREATE INDEX "IDX_f250e1b41b406c65d007cc08a9" ON "AlertService" ("alertId") `,
32
+ );
33
+ await queryRunner.query(
34
+ `CREATE INDEX "IDX_c93eaf768fb41804783e246b12" ON "AlertService" ("serviceId") `,
35
+ );
36
+ await queryRunner.query(
37
+ `ALTER TABLE "AlertService" ADD CONSTRAINT "FK_f250e1b41b406c65d007cc08a9c" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
38
+ );
39
+ await queryRunner.query(
40
+ `ALTER TABLE "AlertService" ADD CONSTRAINT "FK_c93eaf768fb41804783e246b129" FOREIGN KEY ("serviceId") REFERENCES "Service"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
41
+ );
42
+ }
43
+
44
+ public async down(queryRunner: QueryRunner): Promise<void> {
45
+ await queryRunner.query(
46
+ `ALTER TABLE "AlertService" DROP CONSTRAINT "FK_c93eaf768fb41804783e246b129"`,
47
+ );
48
+ await queryRunner.query(
49
+ `ALTER TABLE "AlertService" DROP CONSTRAINT "FK_f250e1b41b406c65d007cc08a9c"`,
50
+ );
51
+ await queryRunner.query(
52
+ `ALTER TABLE "IncidentService" DROP CONSTRAINT "FK_780433e4b5ce2df00b7dc2b30b6"`,
53
+ );
54
+ await queryRunner.query(
55
+ `ALTER TABLE "IncidentService" DROP CONSTRAINT "FK_9b8061de368e0c38bf78fc1412d"`,
56
+ );
57
+ await queryRunner.query(`DROP TABLE "AlertService"`);
58
+ await queryRunner.query(`DROP TABLE "IncidentService"`);
59
+ }
60
+ }
@@ -340,6 +340,8 @@ import { IncreaseSmtpUsernameLength1779125489830 } from "./1779125489830-Increas
340
340
  import { AddTelemetryRetentionConfig1779199346010 } from "./1779199346010-AddTelemetryRetentionConfig";
341
341
  import { DropServiceDependencyTable1779277271302 } from "./1779277271302-DropServiceDependencyTable";
342
342
  import { AddTelemetryRetentionToHostDockerKubernetes1779282769946 } from "./1779282769946-AddTelemetryRetentionToHostDockerKubernetes";
343
+ import { AttachKubernetesAndDockerToIncidentAndAlert1779302536475 } from "./1779302536475-AttachKubernetesAndDockerToIncidentAndAlert";
344
+ import { AttachServiceToIncidentAndAlert1779303924241 } from "./1779303924241-AttachServiceToIncidentAndAlert";
343
345
  export default [
344
346
  InitialMigration,
345
347
  MigrationName1717678334852,
@@ -683,4 +685,6 @@ export default [
683
685
  AddTelemetryRetentionConfig1779199346010,
684
686
  DropServiceDependencyTable1779277271302,
685
687
  AddTelemetryRetentionToHostDockerKubernetes1779282769946,
688
+ AttachKubernetesAndDockerToIncidentAndAlert1779302536475,
689
+ AttachServiceToIncidentAndAlert1779303924241,
686
690
  ];
@@ -7,7 +7,6 @@ import {
7
7
  NextFunction,
8
8
  } from "../../Server/Utils/Express";
9
9
  import TelemetryIngestionKeyService from "../../Server/Services/TelemetryIngestionKeyService";
10
- import TelemetryIngestionKey from "../../Models/DatabaseModels/TelemetryIngestionKey";
11
10
  import Response from "../Utils/Response";
12
11
  import logger, { getLogAttributesFromRequest } from "../Utils/Logger";
13
12
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
@@ -65,45 +64,14 @@ export default class TelemetryIngest {
65
64
  throw new BadRequestException("Missing header: x-oneuptime-token");
66
65
  }
67
66
 
68
- let projectId: ObjectID | undefined = undefined;
69
-
70
- const token: TelemetryIngestionKey | null =
71
- await TelemetryIngestionKeyService.findOneBy({
72
- query: {
73
- secretKey: new ObjectID(oneuptimeToken?.toString() || ""),
74
- },
75
- select: {
76
- projectId: true,
77
- },
78
- props: {
79
- isRoot: true,
80
- },
81
- });
82
-
83
- if (!token) {
84
- logger.error(
85
- "Invalid service token: " + oneuptimeToken,
86
- getLogAttributesFromRequest(req as any),
67
+ const projectId: ObjectID | null =
68
+ await TelemetryIngestionKeyService.getProjectIdFromSecretKey(
69
+ oneuptimeToken.toString(),
87
70
  );
88
71
 
89
- if (isOpenTelemetryAPI) {
90
- /*
91
- * then accept the response and return success.
92
- * do not return error because it causes Otel to retry the request.
93
- */
94
- return Response.sendEmptySuccessResponse(req, res);
95
- }
96
-
97
- throw new BadRequestException(
98
- "Invalid service token: " + oneuptimeToken,
99
- );
100
- }
101
-
102
- projectId = token.projectId as ObjectID;
103
-
104
72
  if (!projectId) {
105
73
  logger.error(
106
- "Project ID not found for service token: " + oneuptimeToken,
74
+ "Invalid service token: " + oneuptimeToken,
107
75
  getLogAttributesFromRequest(req as any),
108
76
  );
109
77
 
@@ -116,11 +84,11 @@ export default class TelemetryIngest {
116
84
  }
117
85
 
118
86
  throw new BadRequestException(
119
- "Project ID not found for service token: " + oneuptimeToken,
87
+ "Invalid service token: " + oneuptimeToken,
120
88
  );
121
89
  }
122
90
 
123
- (req as TelemetryRequest).projectId = projectId as ObjectID;
91
+ (req as TelemetryRequest).projectId = projectId;
124
92
 
125
93
  // Tag span with project context for telemetry ingestion observability
126
94
  SpanUtil.addAttributesToCurrentSpan({
@@ -277,7 +277,6 @@ export default class UserMiddleware {
277
277
  req,
278
278
  tenantId,
279
279
  userId: new ObjectID(userId),
280
- isGlobalLogin: oneuptimeRequest.userAuthorization.isGlobalLogin,
281
280
  });
282
281
 
283
282
  if (userTenantAccessPermission) {
@@ -466,9 +465,8 @@ export default class UserMiddleware {
466
465
  req: ExpressRequest;
467
466
  tenantId: ObjectID;
468
467
  userId: ObjectID;
469
- isGlobalLogin: boolean;
470
468
  }): Promise<UserTenantAccessPermission | null> {
471
- const { req, tenantId, userId, isGlobalLogin } = data;
469
+ const { req, tenantId, userId } = data;
472
470
 
473
471
  const project: Project | null = await ProjectService.findOneById({
474
472
  id: tenantId,
@@ -484,14 +482,6 @@ export default class UserMiddleware {
484
482
  throw new TenantNotFoundException("Invalid tenantId");
485
483
  }
486
484
 
487
- if (!isGlobalLogin) {
488
- if (!UserMiddleware.doesSsoTokenForProjectExist(req, tenantId, userId)) {
489
- throw new NotAuthenticatedException(
490
- "This project requires OneUptime authentication. Please login to access this project.",
491
- );
492
- }
493
- }
494
-
495
485
  if (
496
486
  project.requireSsoForLogin &&
497
487
  !UserMiddleware.doesSsoTokenForProjectExist(req, tenantId, userId)