@oneuptime/common 12.0.1 → 12.0.2

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 (205) hide show
  1. package/Models/DatabaseModels/Host.ts +12 -4
  2. package/Models/DatabaseModels/KubernetesContainer.ts +5 -4
  3. package/Models/DatabaseModels/KubernetesResource.ts +8 -7
  4. package/Models/DatabaseModels/PodmanResource.ts +6 -6
  5. package/Models/DatabaseModels/ServiceLevelObjective.ts +91 -0
  6. package/Models/DatabaseModels/StatusPage.ts +95 -0
  7. package/Server/API/TeamMemberAPI.ts +85 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1785900000000-AddSloMonitorLabelRule.ts +84 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/1785915638551-IncreaseHostIpAddressesLength.ts +40 -0
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/1785930000000-WidenInventoryResourceNameColumns.ts +131 -0
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/1785930709405-AddStatusPageReportPeriod.ts +25 -0
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  13. package/Server/Middleware/ProjectAuthorization.ts +66 -4
  14. package/Server/Services/BillingService.ts +600 -51
  15. package/Server/Services/CephClusterService.ts +47 -5
  16. package/Server/Services/CephResourceService.ts +43 -4
  17. package/Server/Services/CloudResourceService.ts +47 -5
  18. package/Server/Services/DatabaseService.ts +87 -6
  19. package/Server/Services/DockerHostService.ts +47 -5
  20. package/Server/Services/DockerResourceService.ts +62 -8
  21. package/Server/Services/DockerSwarmClusterService.ts +48 -5
  22. package/Server/Services/DockerSwarmResourceService.ts +53 -4
  23. package/Server/Services/HostService.ts +48 -5
  24. package/Server/Services/IoTDeviceService.ts +1 -17
  25. package/Server/Services/IoTFleetService.ts +47 -5
  26. package/Server/Services/KubernetesClusterService.ts +48 -5
  27. package/Server/Services/KubernetesContainerService.ts +50 -9
  28. package/Server/Services/KubernetesResourceService.ts +53 -7
  29. package/Server/Services/LabelService.ts +106 -1
  30. package/Server/Services/MonitorService.ts +57 -0
  31. package/Server/Services/PodmanHostService.ts +47 -5
  32. package/Server/Services/PodmanResourceService.ts +62 -8
  33. package/Server/Services/ProjectService.ts +165 -35
  34. package/Server/Services/ProxmoxClusterService.ts +47 -5
  35. package/Server/Services/ProxmoxResourceService.ts +43 -4
  36. package/Server/Services/RumApplicationService.ts +48 -5
  37. package/Server/Services/ServerlessFunctionService.ts +48 -5
  38. package/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.ts +426 -0
  39. package/Server/Services/ServiceLevelObjectiveService.ts +39 -0
  40. package/Server/Services/StatusPageService.ts +95 -36
  41. package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +18 -1
  42. package/Server/Services/StatusPageSubscriberService.ts +3 -0
  43. package/Server/Types/Database/JSONColumnQuery.ts +621 -0
  44. package/Server/Types/Database/Permissions/PublicPermission.ts +9 -2
  45. package/Server/Types/Database/QueryHelper.ts +17 -32
  46. package/Server/Utils/Database/TruncateColumnValue.ts +84 -0
  47. package/Tests/App/Dashboard/UsersTableGroupsByPerson.test.tsx +448 -0
  48. package/Tests/Server/API/BaseAPIApiKeyAuth.test.ts +704 -0
  49. package/Tests/Server/API/TeamMemberRemoveUserFromProjectAPI.test.ts +303 -0
  50. package/Tests/Server/Middleware/MasterAdminAuthorization.test.ts +350 -0
  51. package/Tests/Server/Middleware/ProjectAuthorizationApiKeyHeader.test.ts +362 -0
  52. package/Tests/Server/Middleware/ProjectAuthorizationApiKeyMiddleware.test.ts +687 -0
  53. package/Tests/Server/Services/BillingService.test.ts +78 -3
  54. package/Tests/Server/Services/BillingServiceChangePlanCancel.test.ts +645 -0
  55. package/Tests/Server/Services/BillingServiceTrialPlanChange.test.ts +1005 -0
  56. package/Tests/Server/Services/HookFreeWriteLengthClamp.test.ts +503 -0
  57. package/Tests/Server/Services/HostIpAddressesColumnWidth.test.ts +198 -0
  58. package/Tests/Server/Services/HostServiceUpdateLastSeen.test.ts +510 -0
  59. package/Tests/Server/Services/InventoryResourceNameColumnWidth.test.ts +500 -0
  60. package/Tests/Server/Services/InventoryUpsertSchemaParity.test.ts +586 -0
  61. package/Tests/Server/Services/InventoryUpsertTruncationGuard.test.ts +1242 -0
  62. package/Tests/Server/Services/ProjectServiceChangePlan.test.ts +650 -0
  63. package/Tests/Server/Services/ProjectServiceExtendTrial.test.ts +1 -0
  64. package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +387 -0
  65. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.test.ts +770 -0
  66. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +130 -0
  67. package/Tests/Server/Services/SloMonitorLabelRuleHooks.test.ts +352 -0
  68. package/Tests/Server/Services/StatusPageSubscriberReport.test.ts +29 -13
  69. package/Tests/Server/TestingUtils/Services/BillingServiceHelper.ts +69 -8
  70. package/Tests/Server/Types/Database/JSONColumnQuery.test.ts +593 -0
  71. package/Tests/Server/Types/Database/Permissions/PublicPermission.test.ts +495 -0
  72. package/Tests/Server/Types/Database/QueryUtil.test.ts +113 -0
  73. package/Tests/Server/Utils/Database/TruncateColumnValue.test.ts +179 -0
  74. package/Tests/Types/Events/Recurring.test.ts +157 -0
  75. package/Tests/UI/Components/ModelTable/ModelTableGroupsProjectUsers.test.tsx +375 -0
  76. package/Tests/UI/Components/ModelTable/useCustomFieldColumns.test.tsx +196 -0
  77. package/Tests/UI/Utils/ProjectUsersModelAPI.test.ts +739 -0
  78. package/Tests/UI/Utils/TeamMembersByUser.test.ts +633 -0
  79. package/Tests/Utils/StatusPage/ReportPeriod.test.ts +218 -0
  80. package/Tests/Utils/Telemetry/HostIpAddresses.test.ts +291 -0
  81. package/Types/CustomField/CustomFieldDefinition.ts +24 -0
  82. package/Types/Date.ts +112 -0
  83. package/Types/Events/Recurring.ts +99 -1
  84. package/Types/StatusPage/StatusPageReport.ts +11 -0
  85. package/Types/StatusPage/StatusPageReportPeriodType.ts +21 -0
  86. package/UI/Components/ModelTable/CustomFieldColumns.tsx +2 -6
  87. package/UI/Components/ModelTable/useCustomFieldColumns.ts +21 -2
  88. package/UI/Utils/ModelAPI/ProjectUsersModelAPI.ts +305 -0
  89. package/UI/Utils/TeamMembersByUser.ts +302 -0
  90. package/Utils/StatusPage/ReportPeriod.ts +236 -0
  91. package/Utils/Telemetry/HostIpAddresses.ts +98 -0
  92. package/build/dist/Models/DatabaseModels/Host.js +12 -4
  93. package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
  94. package/build/dist/Models/DatabaseModels/KubernetesContainer.js +4 -4
  95. package/build/dist/Models/DatabaseModels/KubernetesContainer.js.map +1 -1
  96. package/build/dist/Models/DatabaseModels/KubernetesResource.js +7 -7
  97. package/build/dist/Models/DatabaseModels/KubernetesResource.js.map +1 -1
  98. package/build/dist/Models/DatabaseModels/PodmanResource.js +6 -6
  99. package/build/dist/Models/DatabaseModels/PodmanResource.js.map +1 -1
  100. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +87 -0
  101. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -1
  102. package/build/dist/Models/DatabaseModels/StatusPage.js +98 -0
  103. package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
  104. package/build/dist/Server/API/TeamMemberAPI.js +57 -2
  105. package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
  106. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785900000000-AddSloMonitorLabelRule.js +45 -0
  107. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785900000000-AddSloMonitorLabelRule.js.map +1 -0
  108. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785915638551-IncreaseHostIpAddressesLength.js +31 -0
  109. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785915638551-IncreaseHostIpAddressesLength.js.map +1 -0
  110. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785930000000-WidenInventoryResourceNameColumns.js +90 -0
  111. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785930000000-WidenInventoryResourceNameColumns.js.map +1 -0
  112. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785930709405-AddStatusPageReportPeriod.js +14 -0
  113. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785930709405-AddStatusPageReportPeriod.js.map +1 -0
  114. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  115. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  116. package/build/dist/Server/Middleware/ProjectAuthorization.js +59 -4
  117. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  118. package/build/dist/Server/Services/BillingService.js +466 -36
  119. package/build/dist/Server/Services/BillingService.js.map +1 -1
  120. package/build/dist/Server/Services/CephClusterService.js +42 -5
  121. package/build/dist/Server/Services/CephClusterService.js.map +1 -1
  122. package/build/dist/Server/Services/CephResourceService.js +28 -3
  123. package/build/dist/Server/Services/CephResourceService.js.map +1 -1
  124. package/build/dist/Server/Services/CloudResourceService.js +42 -5
  125. package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
  126. package/build/dist/Server/Services/DatabaseService.js +69 -2
  127. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  128. package/build/dist/Server/Services/DockerHostService.js +42 -5
  129. package/build/dist/Server/Services/DockerHostService.js.map +1 -1
  130. package/build/dist/Server/Services/DockerResourceService.js +34 -4
  131. package/build/dist/Server/Services/DockerResourceService.js.map +1 -1
  132. package/build/dist/Server/Services/DockerSwarmClusterService.js +43 -5
  133. package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
  134. package/build/dist/Server/Services/DockerSwarmResourceService.js +28 -3
  135. package/build/dist/Server/Services/DockerSwarmResourceService.js.map +1 -1
  136. package/build/dist/Server/Services/HostService.js +43 -5
  137. package/build/dist/Server/Services/HostService.js.map +1 -1
  138. package/build/dist/Server/Services/IoTDeviceService.js +1 -8
  139. package/build/dist/Server/Services/IoTDeviceService.js.map +1 -1
  140. package/build/dist/Server/Services/IoTFleetService.js +42 -5
  141. package/build/dist/Server/Services/IoTFleetService.js.map +1 -1
  142. package/build/dist/Server/Services/KubernetesClusterService.js +43 -5
  143. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  144. package/build/dist/Server/Services/KubernetesContainerService.js +29 -3
  145. package/build/dist/Server/Services/KubernetesContainerService.js.map +1 -1
  146. package/build/dist/Server/Services/KubernetesResourceService.js +32 -4
  147. package/build/dist/Server/Services/KubernetesResourceService.js.map +1 -1
  148. package/build/dist/Server/Services/LabelService.js +92 -0
  149. package/build/dist/Server/Services/LabelService.js.map +1 -1
  150. package/build/dist/Server/Services/MonitorService.js +47 -0
  151. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  152. package/build/dist/Server/Services/PodmanHostService.js +42 -5
  153. package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
  154. package/build/dist/Server/Services/PodmanResourceService.js +34 -4
  155. package/build/dist/Server/Services/PodmanResourceService.js.map +1 -1
  156. package/build/dist/Server/Services/ProjectService.js +135 -21
  157. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  158. package/build/dist/Server/Services/ProxmoxClusterService.js +42 -5
  159. package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
  160. package/build/dist/Server/Services/ProxmoxResourceService.js +28 -3
  161. package/build/dist/Server/Services/ProxmoxResourceService.js.map +1 -1
  162. package/build/dist/Server/Services/RumApplicationService.js +43 -5
  163. package/build/dist/Server/Services/RumApplicationService.js.map +1 -1
  164. package/build/dist/Server/Services/ServerlessFunctionService.js +43 -5
  165. package/build/dist/Server/Services/ServerlessFunctionService.js.map +1 -1
  166. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js +347 -0
  167. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js.map +1 -0
  168. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +33 -1
  169. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
  170. package/build/dist/Server/Services/StatusPageService.js +69 -46
  171. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  172. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +17 -1
  173. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
  174. package/build/dist/Server/Services/StatusPageSubscriberService.js +3 -0
  175. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  176. package/build/dist/Server/Types/Database/JSONColumnQuery.js +402 -0
  177. package/build/dist/Server/Types/Database/JSONColumnQuery.js.map +1 -0
  178. package/build/dist/Server/Types/Database/Permissions/PublicPermission.js +9 -2
  179. package/build/dist/Server/Types/Database/Permissions/PublicPermission.js.map +1 -1
  180. package/build/dist/Server/Types/Database/QueryHelper.js +17 -27
  181. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  182. package/build/dist/Server/Utils/Database/TruncateColumnValue.js +32 -0
  183. package/build/dist/Server/Utils/Database/TruncateColumnValue.js.map +1 -0
  184. package/build/dist/Types/CustomField/CustomFieldDefinition.js +2 -0
  185. package/build/dist/Types/CustomField/CustomFieldDefinition.js.map +1 -0
  186. package/build/dist/Types/Date.js +68 -0
  187. package/build/dist/Types/Date.js.map +1 -1
  188. package/build/dist/Types/Events/Recurring.js +63 -0
  189. package/build/dist/Types/Events/Recurring.js.map +1 -1
  190. package/build/dist/Types/StatusPage/StatusPageReportPeriodType.js +22 -0
  191. package/build/dist/Types/StatusPage/StatusPageReportPeriodType.js.map +1 -0
  192. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -1
  193. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +18 -2
  194. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -1
  195. package/build/dist/UI/Utils/ModelAPI/ProjectUsersModelAPI.js +213 -0
  196. package/build/dist/UI/Utils/ModelAPI/ProjectUsersModelAPI.js.map +1 -0
  197. package/build/dist/UI/Utils/TeamMembersByUser.js +195 -0
  198. package/build/dist/UI/Utils/TeamMembersByUser.js.map +1 -0
  199. package/build/dist/Utils/StatusPage/ReportPeriod.js +131 -0
  200. package/build/dist/Utils/StatusPage/ReportPeriod.js.map +1 -0
  201. package/build/dist/Utils/Telemetry/HostIpAddresses.js +82 -0
  202. package/build/dist/Utils/Telemetry/HostIpAddresses.js.map +1 -0
  203. package/jest.config.json +2 -0
  204. package/package.json +1 -1
  205. package/tsconfig.json +12 -1
@@ -0,0 +1,131 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class WidenInventoryResourceNameColumns1785930000000
4
+ implements MigrationInterface
5
+ {
6
+ public name = "WidenInventoryResourceNameColumns1785930000000";
7
+
8
+ /*
9
+ * Same overflow class as WidenDockerResourceImageColumns1782800000000,
10
+ * on the Podman and Kubernetes inventory tables. These services build
11
+ * `INSERT ... ON CONFLICT` strings by hand and flush them in chunks of
12
+ * 500 rows, so ONE value over varchar(100) raises "value too long for
13
+ * type character varying(100)" (22001) and aborts the ENTIRE multi-row
14
+ * INSERT — up to 500 inventory rows silently dropped per flush.
15
+ *
16
+ * The offenders, all previously varchar(100):
17
+ * - PodmanResource."name" / "imageName": full image references
18
+ * (registry host + org + repo + tag) routinely exceed 100 chars.
19
+ * - KubernetesResource."name" and KubernetesContainer."podName":
20
+ * Kubernetes DNS-subdomain names go up to 253 characters, and
21
+ * generated pod names (deployment + replicaset hash + pod hash)
22
+ * commonly clear 100.
23
+ * - KubernetesResource."controllerDeploymentName": written from the
24
+ * `k8s.deployment.name` resource attribute, same bound.
25
+ *
26
+ * 500 (ColumnLength.LongText) clears the 253-char Kubernetes ceiling
27
+ * with room to spare and matches what DockerResource already uses.
28
+ *
29
+ * COST: raising a varchar length cap is binary-coercible, so Postgres
30
+ * skips the table rewrite — but ALTER COLUMN TYPE still rebuilds every
31
+ * index on the altered column ("any indexes on the affected columns
32
+ * must still be rebuilt"). Three of these five columns are members of
33
+ * composite UNIQUE indexes:
34
+ * - PodmanResource."name" -> IDX_772c02b6419beb57fa47ccae1b
35
+ * - KubernetesResource."name" -> IDX_3ae20a0d4346958dff73ba7fda
36
+ * - KubernetesContainer."podName" -> IDX_1dcb8fed322a9bddfabb60cbc7
37
+ * Those three rebuild under ACCESS EXCLUSIVE, so on a large inventory
38
+ * table this is not free: ingest for the affected tables blocks for
39
+ * the duration, and TypeORM runs all pending migrations in one
40
+ * transaction, so the locks are held until the whole batch commits.
41
+ * "imageName" and "controllerDeploymentName" are in no index and are
42
+ * genuinely metadata-only.
43
+ */
44
+ public async up(queryRunner: QueryRunner): Promise<void> {
45
+ await queryRunner.query(
46
+ `ALTER TABLE "PodmanResource" ALTER COLUMN "name" TYPE character varying(500)`,
47
+ );
48
+ await queryRunner.query(
49
+ `ALTER TABLE "PodmanResource" ALTER COLUMN "imageName" TYPE character varying(500)`,
50
+ );
51
+ await queryRunner.query(
52
+ `ALTER TABLE "KubernetesResource" ALTER COLUMN "name" TYPE character varying(500)`,
53
+ );
54
+ await queryRunner.query(
55
+ `ALTER TABLE "KubernetesResource" ALTER COLUMN "controllerDeploymentName" TYPE character varying(500)`,
56
+ );
57
+ await queryRunner.query(
58
+ `ALTER TABLE "KubernetesContainer" ALTER COLUMN "podName" TYPE character varying(500)`,
59
+ );
60
+ }
61
+
62
+ public async down(queryRunner: QueryRunner): Promise<void> {
63
+ /*
64
+ * Narrowing back to varchar(100) fails outright if any row written
65
+ * since up() exceeds 100 chars, so clip first. "name" / "podName"
66
+ * are part of UNIQUE indexes: clipping two rows onto the same
67
+ * truncated key would violate them, so the revert deletes rows
68
+ * whose identity would collide after clipping instead of letting
69
+ * the ALTER blow up. Inventory rows are a projection of what the
70
+ * agent is reporting — the next snapshot re-creates them.
71
+ */
72
+ await queryRunner.query(
73
+ `DELETE FROM "PodmanResource" a USING "PodmanResource" b
74
+ WHERE a."projectId" = b."projectId"
75
+ AND a."podmanHostId" = b."podmanHostId"
76
+ AND a."kind" = b."kind"
77
+ AND LEFT(a."name", 100) = LEFT(b."name", 100)
78
+ AND a."_id" > b."_id"`,
79
+ );
80
+ await queryRunner.query(
81
+ `DELETE FROM "KubernetesResource" a USING "KubernetesResource" b
82
+ WHERE a."projectId" = b."projectId"
83
+ AND a."kubernetesClusterId" = b."kubernetesClusterId"
84
+ AND a."kind" = b."kind"
85
+ AND a."namespaceKey" = b."namespaceKey"
86
+ AND LEFT(a."name", 100) = LEFT(b."name", 100)
87
+ AND a."_id" > b."_id"`,
88
+ );
89
+ await queryRunner.query(
90
+ `DELETE FROM "KubernetesContainer" a USING "KubernetesContainer" b
91
+ WHERE a."projectId" = b."projectId"
92
+ AND a."kubernetesClusterId" = b."kubernetesClusterId"
93
+ AND a."podNamespaceKey" = b."podNamespaceKey"
94
+ AND LEFT(a."podName", 100) = LEFT(b."podName", 100)
95
+ AND a."name" = b."name"
96
+ AND a."_id" > b."_id"`,
97
+ );
98
+
99
+ await queryRunner.query(
100
+ `UPDATE "PodmanResource" SET "name" = LEFT("name", 100) WHERE LENGTH("name") > 100`,
101
+ );
102
+ await queryRunner.query(
103
+ `UPDATE "PodmanResource" SET "imageName" = LEFT("imageName", 100) WHERE "imageName" IS NOT NULL AND LENGTH("imageName") > 100`,
104
+ );
105
+ await queryRunner.query(
106
+ `UPDATE "KubernetesResource" SET "name" = LEFT("name", 100) WHERE LENGTH("name") > 100`,
107
+ );
108
+ await queryRunner.query(
109
+ `UPDATE "KubernetesResource" SET "controllerDeploymentName" = LEFT("controllerDeploymentName", 100) WHERE "controllerDeploymentName" IS NOT NULL AND LENGTH("controllerDeploymentName") > 100`,
110
+ );
111
+ await queryRunner.query(
112
+ `UPDATE "KubernetesContainer" SET "podName" = LEFT("podName", 100) WHERE LENGTH("podName") > 100`,
113
+ );
114
+
115
+ await queryRunner.query(
116
+ `ALTER TABLE "PodmanResource" ALTER COLUMN "name" TYPE character varying(100)`,
117
+ );
118
+ await queryRunner.query(
119
+ `ALTER TABLE "PodmanResource" ALTER COLUMN "imageName" TYPE character varying(100)`,
120
+ );
121
+ await queryRunner.query(
122
+ `ALTER TABLE "KubernetesResource" ALTER COLUMN "name" TYPE character varying(100)`,
123
+ );
124
+ await queryRunner.query(
125
+ `ALTER TABLE "KubernetesResource" ALTER COLUMN "controllerDeploymentName" TYPE character varying(100)`,
126
+ );
127
+ await queryRunner.query(
128
+ `ALTER TABLE "KubernetesContainer" ALTER COLUMN "podName" TYPE character varying(100)`,
129
+ );
130
+ }
131
+ }
@@ -0,0 +1,25 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class AddStatusPageReportPeriod1785930709405
4
+ implements MigrationInterface
5
+ {
6
+ public name = "AddStatusPageReportPeriod1785930709405";
7
+
8
+ public async up(queryRunner: QueryRunner): Promise<void> {
9
+ await queryRunner.query(
10
+ `ALTER TABLE "StatusPage" ADD "reportPeriodType" character varying DEFAULT 'Rolling'`,
11
+ );
12
+ await queryRunner.query(
13
+ `ALTER TABLE "StatusPage" ADD "reportTimezone" character varying DEFAULT 'UTC'`,
14
+ );
15
+ }
16
+
17
+ public async down(queryRunner: QueryRunner): Promise<void> {
18
+ await queryRunner.query(
19
+ `ALTER TABLE "StatusPage" DROP COLUMN "reportTimezone"`,
20
+ );
21
+ await queryRunner.query(
22
+ `ALTER TABLE "StatusPage" DROP COLUMN "reportPeriodType"`,
23
+ );
24
+ }
25
+ }
@@ -492,6 +492,10 @@ import { SessionReplayDefaultToSensitiveInputMasking1785860000000 } from "./1785
492
492
  import { AddAiCommandRemediation1785870000000 } from "./1785870000000-AddAiCommandRemediation";
493
493
  import { AlignRunnerSchemaWithEntities1785880000000 } from "./1785880000000-AlignRunnerSchemaWithEntities";
494
494
  import { AddFixVerificationAndAutomaticCodeFixes1785890000000 } from "./1785890000000-AddFixVerificationAndAutomaticCodeFixes";
495
+ import { AddSloMonitorLabelRule1785900000000 } from "./1785900000000-AddSloMonitorLabelRule";
496
+ import { IncreaseHostIpAddressesLength1785915638551 } from "./1785915638551-IncreaseHostIpAddressesLength";
497
+ import { WidenInventoryResourceNameColumns1785930000000 } from "./1785930000000-WidenInventoryResourceNameColumns";
498
+ import { AddStatusPageReportPeriod1785930709405 } from "./1785930709405-AddStatusPageReportPeriod";
495
499
  import { AddIncidentInvestigationGating1785790000000 } from "./1785790000000-AddIncidentInvestigationGating";
496
500
  import { AddRemediationVerification1785768089408 } from "./1785768089408-AddRemediationVerification";
497
501
 
@@ -992,4 +996,8 @@ export default [
992
996
  AddAiCommandRemediation1785870000000,
993
997
  AlignRunnerSchemaWithEntities1785880000000,
994
998
  AddFixVerificationAndAutomaticCodeFixes1785890000000,
999
+ AddSloMonitorLabelRule1785900000000,
1000
+ IncreaseHostIpAddressesLength1785915638551,
1001
+ WidenInventoryResourceNameColumns1785930000000,
1002
+ AddStatusPageReportPeriod1785930709405,
995
1003
  ];
@@ -41,18 +41,69 @@ export default class ProjectMiddleware {
41
41
  return projectId;
42
42
  }
43
43
 
44
+ /*
45
+ * The `apikey` header exactly as it arrived, or null when it was never
46
+ * sent at all. Node lower-cases header names, and a caller that sends the
47
+ * header twice arrives here as one comma-joined string — never a usable
48
+ * key, but unmistakably a caller who meant to authenticate by key.
49
+ *
50
+ * An empty or whitespace-only value is a header that WAS sent. Keeping that
51
+ * distinct from "absent" is the whole point of this helper; see hasApiKey.
52
+ */
53
+ private static getRawApiKeyHeader(req: ExpressRequest): string | null {
54
+ const rawHeader: string | Array<string> | undefined =
55
+ req.headers?.["apikey"];
56
+
57
+ if (rawHeader === undefined) {
58
+ return null;
59
+ }
60
+
61
+ return Array.isArray(rawHeader) ? rawHeader.join(",") : rawHeader;
62
+ }
63
+
44
64
  @CaptureSpan()
45
65
  public static getApiKey(req: ExpressRequest): ObjectID | null {
46
- if (req.headers && req.headers["apikey"]) {
47
- return new ObjectID(req.headers["apikey"] as string);
66
+ const rawHeader: string | null = ProjectMiddleware.getRawApiKeyHeader(req);
67
+
68
+ if (rawHeader === null) {
69
+ return null;
48
70
  }
49
71
 
50
- return null;
72
+ const apiKey: string = rawHeader.trim();
73
+
74
+ /*
75
+ * `ApiKey.apiKey` is a Postgres `uuid` column, so a non-UUID value makes
76
+ * the lookup raise "invalid input syntax for type uuid" down in the query
77
+ * layer. A raw QueryFailedError is not a OneUptime Exception, so it slips
78
+ * past the error translator and answers 500 to what is really a malformed
79
+ * request. Reject the shape here and let the caller get `Invalid API Key`.
80
+ */
81
+ if (!ObjectID.isValidUUID(apiKey)) {
82
+ return null;
83
+ }
84
+
85
+ return new ObjectID(apiKey);
51
86
  }
52
87
 
88
+ /*
89
+ * Presence, not usability — deliberately NOT `Boolean(this.getApiKey(req))`.
90
+ *
91
+ * A request carrying an empty or malformed `ApiKey` header is a caller
92
+ * trying to authenticate by key and getting it wrong. Answering false here
93
+ * routed it down the anonymous path, where it failed much later with
94
+ * "A user should be logged in to <op> record of <Model>." — an error about
95
+ * session auth, raised against a caller who never attempted session auth,
96
+ * naming a model as though the model were what went wrong. It reads as an
97
+ * RBAC bug in whichever resource happened to be asked for, and has been
98
+ * reported as one more than once (issues #1754, #3004). An unset shell
99
+ * variable, a client that sends the header blank, and our own CLI's
100
+ * partial-credential path all land here.
101
+ *
102
+ * Claim the request instead, so it fails as `Invalid API Key`.
103
+ */
53
104
  @CaptureSpan()
54
105
  public static hasApiKey(req: ExpressRequest): boolean {
55
- return Boolean(this.getApiKey(req));
106
+ return ProjectMiddleware.getRawApiKeyHeader(req) !== null;
56
107
  }
57
108
 
58
109
  @CaptureSpan()
@@ -118,6 +169,17 @@ export default class ProjectMiddleware {
118
169
  }
119
170
 
120
171
  if (!apiKey) {
172
+ /*
173
+ * Separate "no header at all" from "header sent, but unusable".
174
+ * getUserMiddleware only routes here once the header is present, so
175
+ * in practice it is always the second: an empty value from an unset
176
+ * variable, a non-UUID string, or duplicate headers that Node joined
177
+ * into a comma-separated list.
178
+ */
179
+ if (ProjectMiddleware.hasApiKey(req)) {
180
+ throw new BadDataException("Invalid API Key");
181
+ }
182
+
121
183
  throw new BadDataException(
122
184
  "API Key not found in the request header. Please provide a valid API Key in the request header.",
123
185
  );