@oneuptime/common 12.0.2 → 12.0.4
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.
- package/Models/DatabaseModels/CephCluster.ts +14 -0
- package/Models/DatabaseModels/CodeRepository.ts +14 -6
- package/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +14 -0
- package/Models/DatabaseModels/DockerHost.ts +14 -0
- package/Models/DatabaseModels/GlobalOidcProject.ts +18 -0
- package/Models/DatabaseModels/GlobalSsoProject.ts +18 -0
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/IoTFleet.ts +14 -0
- package/Models/DatabaseModels/KubernetesCluster.ts +14 -0
- package/Models/DatabaseModels/LogDropFilter.ts +9 -20
- package/Models/DatabaseModels/NetworkDevice.ts +14 -0
- package/Models/DatabaseModels/NetworkInterface.ts +18 -0
- package/Models/DatabaseModels/Project.ts +16 -2
- package/Models/DatabaseModels/ProxmoxCluster.ts +14 -0
- package/Models/DatabaseModels/Service.ts +30 -0
- package/Models/DatabaseModels/StatusPageMonitorRule.ts +911 -0
- package/Models/DatabaseModels/StatusPagePrivateUser.ts +30 -0
- package/Models/DatabaseModels/StatusPageResource.ts +73 -0
- package/Models/DatabaseModels/TraceDropFilter.ts +9 -20
- package/Models/DatabaseModels/User.ts +30 -0
- package/Server/API/AIAgentDataAPI.ts +31 -0
- package/Server/API/BaseAPI.ts +13 -2
- package/Server/API/DashboardAPI.ts +458 -12
- package/Server/API/GitHubAPI.ts +119 -283
- package/Server/API/UserAPI.ts +263 -1
- package/Server/EnvironmentConfig.ts +38 -4
- package/Server/Infrastructure/GlobalCache.ts +152 -0
- package/Server/Infrastructure/Postgres/DataSourceOptions.ts +16 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786005052769-AddStatusPageMonitorRule.ts +123 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786018109307-AddPerUserPasswordSalt.ts +21 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786023262402-WidenHashedStringColumnsForScrypt.ts +68 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.ts +100 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786200000000-RestoreDroppedUniqueIndexes.ts +214 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786300000000-QuarantineUnboundGitHubInstallations.ts +69 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
- package/Server/Services/AlertStateTimelineService.ts +20 -0
- package/Server/Services/AnalyticsDatabaseService.ts +72 -1
- package/Server/Services/CephClusterService.ts +26 -86
- package/Server/Services/CloudResourceService.ts +23 -83
- package/Server/Services/CodeRepositoryService.ts +105 -2
- package/Server/Services/DatabaseService.ts +296 -2
- package/Server/Services/DockerHostService.ts +19 -79
- package/Server/Services/DockerSwarmClusterService.ts +27 -88
- package/Server/Services/HostService.ts +46 -99
- package/Server/Services/IncidentStateTimelineService.ts +20 -0
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/IoTFleetService.ts +19 -79
- package/Server/Services/KubernetesClusterService.ts +17 -78
- package/Server/Services/LabelService.ts +57 -10
- package/Server/Services/MetricTypeService.ts +84 -0
- package/Server/Services/MonitorService.ts +89 -14
- package/Server/Services/MonitorStatusTimelineService.ts +29 -0
- package/Server/Services/MonitorTemplateService.ts +65 -0
- package/Server/Services/OpenTelemetryIngestService.ts +230 -26
- package/Server/Services/PodmanHostService.ts +19 -79
- package/Server/Services/ProxmoxClusterService.ts +23 -83
- package/Server/Services/RumApplicationService.ts +19 -80
- package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +21 -0
- package/Server/Services/ServerlessFunctionService.ts +24 -85
- package/Server/Services/ServiceService.ts +299 -73
- package/Server/Services/StatusPageMonitorRuleEngineService.ts +752 -0
- package/Server/Services/StatusPageMonitorRuleService.ts +471 -0
- package/Server/Services/TelemetryEntityRelationshipService.ts +1 -0
- package/Server/Services/TelemetryEntityService.ts +1 -0
- package/Server/Services/UserService.ts +184 -0
- package/Server/Utils/AI/Toolbox/CodeTools.ts +45 -4
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +13 -0
- package/Server/Utils/CodeRepository/GitHub/GitHub.ts +157 -4
- package/Server/Utils/CodeRepository/GitHub/GitHubInstallationBinding.ts +130 -0
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +170 -39
- package/Server/Utils/Monitor/MonitorResource.ts +63 -36
- package/Server/Utils/Monitor/MonitorStatusTimeline.ts +36 -0
- package/Server/Utils/Monitor/MonitorStepsProjectValidator.ts +148 -127
- package/Server/Utils/Monitor/MonitorStepsReferenceExtractor.ts +434 -0
- package/Server/Utils/PasswordHash.ts +306 -0
- package/Server/Utils/SingleFlight.ts +83 -0
- package/Server/Utils/StatusPage/MonitorRulePatternValidator.ts +46 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +107 -26
- package/Server/Utils/Telemetry/ResourceHeartbeat.ts +314 -0
- package/Server/Utils/Telemetry/Telemetry.ts +351 -122
- package/Tests/App/Dashboard/OverviewCustomFields.test.tsx +333 -0
- package/Tests/App/Dashboard/UserCustomFields.test.tsx +392 -0
- package/Tests/App/Dashboard/WidgetCatalog.test.ts +2 -0
- package/Tests/Models/DatabaseModels/ColumnTransformerInvariants.test.ts +306 -0
- package/Tests/Models/DatabaseModels/NumberColumnDeserialization.test.ts +333 -0
- package/Tests/Models/DatabaseModels/StatusPageMonitorRuleModel.test.ts +190 -0
- package/Tests/Server/API/AIAgentDataRepositoryToken.test.ts +381 -0
- package/Tests/Server/API/DashboardPublicAttributeValuesAPI.test.ts +943 -0
- package/Tests/Server/API/DashboardPublicMetricsAggregateAPI.test.ts +1296 -0
- package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +26 -0
- package/Tests/Server/API/DashboardPublicTemplatePayloads.test.ts +598 -0
- package/Tests/Server/API/GitHubAppInstallationBindingAPI.test.ts +539 -0
- package/Tests/Server/API/Helpers.ts +6 -1
- package/Tests/Server/API/UserProjectsAPI.test.ts +852 -0
- package/Tests/Server/Infrastructure/GlobalCache.test.ts +354 -0
- package/Tests/Server/Infrastructure/PostgresLockTimeoutOptions.test.ts +181 -0
- package/Tests/Server/Infrastructure/SemaphoreMutex.test.ts +215 -0
- package/Tests/Server/Services/AddPerUserPasswordSaltMigration.test.ts +178 -0
- package/Tests/Server/Services/AnalyticsDatabasePaginationStability.test.ts +582 -0
- package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +5 -0
- package/Tests/Server/Services/CodeRepositoryInstallationBinding.test.ts +305 -0
- package/Tests/Server/Services/CodeRepositoryResolutionBinding.test.ts +147 -0
- package/Tests/Server/Services/DatabaseServicePerUserPasswordSalt.test.ts +870 -0
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlocked.test.ts +342 -0
- package/Tests/Server/Services/DropFilterSaveValidation.test.ts +245 -0
- package/Tests/Server/Services/HostServiceUpdateLastSeen.test.ts +163 -15
- package/Tests/Server/Services/MetricTypeAttachServices.test.ts +222 -0
- package/Tests/Server/Services/MissingReferenceWriteGuard.test.ts +614 -0
- package/Tests/Server/Services/MonitorStatusTimelineFastPath.test.ts +23 -0
- package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +568 -0
- package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +305 -56
- package/Tests/Server/Services/RestoreDroppedUniqueIndexesMigration.test.ts +386 -0
- package/Tests/Server/Services/RestoreServiceLowerNameIndexMigration.test.ts +240 -0
- package/Tests/Server/Services/ServiceUpdateLastSeenSplitGates.test.ts +705 -0
- package/Tests/Server/Services/StatusPageMonitorRuleEngineService.test.ts +1719 -0
- package/Tests/Server/Services/StatusPageMonitorRuleHooks.test.ts +1212 -0
- package/Tests/Server/Services/StatusPageMonitorRuleMonitorCreateHook.test.ts +228 -0
- package/Tests/Server/Services/UserServiceFirstMasterAdminElection.test.ts +885 -0
- package/Tests/Server/Services/WidenHashedStringColumnsForScryptMigration.test.ts +220 -0
- package/Tests/Server/Utils/AI/CodeTools.test.ts +47 -1
- package/Tests/Server/Utils/AI/CodeWriteTools.test.ts +10 -0
- package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +267 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +120 -0
- package/Tests/Server/Utils/CodeRepository/GitHubInstallationBinding.test.ts +292 -0
- package/Tests/Server/Utils/Database/ProjectScopedReferenceValidator.test.ts +260 -13
- package/Tests/Server/Utils/EntityRegistryRowFence.test.ts +302 -0
- package/Tests/Server/Utils/GitHubInstallationOwnershipVerification.test.ts +340 -0
- package/Tests/Server/Utils/GitHubWebhookAndTreeCacheIsolation.test.ts +250 -0
- package/Tests/Server/Utils/MetricTypeIndexConvergence.test.ts +598 -0
- package/Tests/Server/Utils/Monitor/MonitorStatusTimelineUnusableStatus.test.ts +154 -0
- package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidator.test.ts +638 -92
- package/Tests/Server/Utils/Monitor/MonitorStepsReferenceExtractor.test.ts +724 -0
- package/Tests/Server/Utils/PasswordHash.test.ts +555 -0
- package/Tests/Server/Utils/SingleFlight.test.ts +221 -0
- package/Tests/Types/Dashboard/NetworkDashboardTemplate.test.ts +793 -0
- package/Tests/Types/Database/BigIntColumnTransformer.test.ts +147 -0
- package/Tests/Types/Database/ColumnLength.test.ts +7 -1
- package/Tests/Types/Database/DatabasePropertyTransformer.test.ts +140 -0
- package/Tests/Types/Database/NumericColumnValue.test.ts +127 -0
- package/Tests/Types/Decimal.test.ts +37 -0
- package/Tests/Types/HashedStringPerUserSalt.test.ts +476 -0
- package/Tests/Types/Monitor/DockerAlertTemplates.test.ts +293 -0
- package/Tests/Types/Monitor/HostAlertTemplates.test.ts +249 -0
- package/Tests/Types/Monitor/IotAlertTemplates.test.ts +320 -0
- package/Tests/Types/Monitor/PodmanAlertTemplates.test.ts +271 -0
- package/Tests/Types/Monitor/SnmpVersionParsing.test.ts +152 -0
- package/Tests/Types/Port.test.ts +38 -0
- package/Tests/UI/Components/CustomFields/CustomFieldsDetail.test.tsx +696 -0
- package/Tests/UI/Components/LogsHistogram.test.tsx +276 -0
- package/Tests/UI/Components/UseLiveLogsRefresh.test.tsx +489 -0
- package/Tests/UI/Components/UseLogsHistogram.test.tsx +500 -0
- package/Tests/UI/Utils/UserProjectsModelAPI.test.ts +714 -0
- package/Tests/Utils/Dashboard/Components/DashboardComponentsUtil.test.ts +120 -0
- package/Tests/Utils/Dashboard/DashboardNetworkMapComponent.test.ts +327 -0
- package/Tests/Utils/TeamMembersByProject.test.ts +655 -0
- package/Types/Dashboard/DashboardComponentType.ts +1 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardNetworkMapComponent.ts +40 -0
- package/Types/Dashboard/DashboardTemplates.ts +397 -0
- package/Types/Database/BigIntColumnTransformer.ts +74 -0
- package/Types/Database/ColumnLength.ts +9 -1
- package/Types/Database/DatabaseProperty.ts +26 -0
- package/Types/Database/NumericColumnValue.ts +128 -0
- package/Types/Database/TableColumn.ts +11 -0
- package/Types/Database/UnsynchronizedIndex.ts +48 -0
- package/Types/Decimal.ts +16 -4
- package/Types/HashedString.ts +139 -4
- package/Types/Permission.ts +48 -0
- package/Types/Port.ts +16 -4
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +85 -11
- package/UI/Components/LogsViewer/useLiveLogsRefresh.ts +86 -0
- package/UI/Components/LogsViewer/useLogsHistogram.ts +113 -0
- package/UI/Components/Navbar/NavBar.tsx +12 -2
- package/UI/Components/Navbar/NavBarMenuModal.tsx +19 -7
- package/UI/Utils/ModelAPI/UserProjectsModelAPI.ts +257 -0
- package/Utils/Dashboard/Components/DashboardNetworkMapComponent.ts +136 -0
- package/Utils/Dashboard/Components/Index.ts +7 -0
- package/Utils/TeamMembersByProject.ts +237 -0
- package/build/dist/Models/DatabaseModels/CephCluster.js +16 -1
- package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CodeRepository.js +14 -6
- package/build/dist/Models/DatabaseModels/CodeRepository.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +12 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHost.js +16 -1
- package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalOidcProject.js +16 -1
- package/build/dist/Models/DatabaseModels/GlobalOidcProject.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalSsoProject.js +16 -1
- package/build/dist/Models/DatabaseModels/GlobalSsoProject.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IoTFleet.js +16 -1
- package/build/dist/Models/DatabaseModels/IoTFleet.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js +16 -1
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/LogDropFilter.js +9 -20
- package/build/dist/Models/DatabaseModels/LogDropFilter.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +16 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkInterface.js +16 -1
- package/build/dist/Models/DatabaseModels/NetworkInterface.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +16 -2
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +16 -1
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Service.js +28 -1
- package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageMonitorRule.js +925 -0
- package/build/dist/Models/DatabaseModels/StatusPageMonitorRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js +32 -0
- package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageResource.js +72 -0
- package/build/dist/Models/DatabaseModels/StatusPageResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js +9 -20
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js.map +1 -1
- package/build/dist/Models/DatabaseModels/User.js +32 -0
- package/build/dist/Models/DatabaseModels/User.js.map +1 -1
- package/build/dist/Server/API/AIAgentDataAPI.js +21 -2
- package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +11 -1
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +343 -10
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/GitHubAPI.js +94 -167
- package/build/dist/Server/API/GitHubAPI.js.map +1 -1
- package/build/dist/Server/API/UserAPI.js +187 -2
- package/build/dist/Server/API/UserAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +34 -4
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/GlobalCache.js +120 -0
- package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js +5 -3
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786005052769-AddStatusPageMonitorRule.js +48 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786005052769-AddStatusPageMonitorRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786018109307-AddPerUserPasswordSalt.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786018109307-AddPerUserPasswordSalt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786023262402-WidenHashedStringColumnsForScrypt.js +59 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786023262402-WidenHashedStringColumnsForScrypt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.js +93 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786200000000-RestoreDroppedUniqueIndexes.js +101 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786200000000-RestoreDroppedUniqueIndexes.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786300000000-QuarantineUnboundGitHubInstallations.js +66 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786300000000-QuarantineUnboundGitHubInstallations.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AlertStateTimelineService.js +19 -0
- package/build/dist/Server/Services/AlertStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +57 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterService.js +26 -76
- package/build/dist/Server/Services/CephClusterService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceService.js +23 -73
- package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
- package/build/dist/Server/Services/CodeRepositoryService.js +90 -2
- package/build/dist/Server/Services/CodeRepositoryService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +246 -2
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +19 -69
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js +27 -78
- package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +58 -102
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/IncidentStateTimelineService.js +19 -0
- package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetService.js +19 -69
- package/build/dist/Server/Services/IoTFleetService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterService.js +17 -68
- package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
- package/build/dist/Server/Services/LabelService.js +42 -7
- package/build/dist/Server/Services/LabelService.js.map +1 -1
- package/build/dist/Server/Services/MetricTypeService.js +74 -0
- package/build/dist/Server/Services/MetricTypeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +81 -9
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusTimelineService.js +28 -0
- package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +60 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +155 -25
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostService.js +19 -69
- package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js +23 -73
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationService.js +19 -70
- package/build/dist/Server/Services/RumApplicationService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +20 -0
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionService.js +24 -75
- package/build/dist/Server/Services/ServerlessFunctionService.js.map +1 -1
- package/build/dist/Server/Services/ServiceService.js +236 -61
- package/build/dist/Server/Services/ServiceService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js +603 -0
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/StatusPageMonitorRuleService.js +401 -0
- package/build/dist/Server/Services/StatusPageMonitorRuleService.js.map +1 -0
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js +1 -0
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryEntityService.js +1 -0
- package/build/dist/Server/Services/TelemetryEntityService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +165 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/CodeTools.js +31 -1
- package/build/dist/Server/Utils/AI/Toolbox/CodeTools.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +13 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +126 -4
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubInstallationBinding.js +136 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubInstallationBinding.js.map +1 -0
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +105 -29
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +56 -32
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js +30 -3
- package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js +110 -98
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepsReferenceExtractor.js +312 -0
- package/build/dist/Server/Utils/Monitor/MonitorStepsReferenceExtractor.js.map +1 -0
- package/build/dist/Server/Utils/PasswordHash.js +237 -0
- package/build/dist/Server/Utils/PasswordHash.js.map +1 -0
- package/build/dist/Server/Utils/SingleFlight.js +76 -0
- package/build/dist/Server/Utils/SingleFlight.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js +29 -0
- package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +78 -19
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js +160 -0
- package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/Telemetry.js +279 -104
- package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardNetworkMapComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardNetworkMapComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js +368 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Database/BigIntColumnTransformer.js +66 -0
- package/build/dist/Types/Database/BigIntColumnTransformer.js.map +1 -0
- package/build/dist/Types/Database/ColumnLength.js +9 -1
- package/build/dist/Types/Database/ColumnLength.js.map +1 -1
- package/build/dist/Types/Database/DatabaseProperty.js +25 -0
- package/build/dist/Types/Database/DatabaseProperty.js.map +1 -1
- package/build/dist/Types/Database/NumericColumnValue.js +97 -0
- package/build/dist/Types/Database/NumericColumnValue.js.map +1 -0
- package/build/dist/Types/Database/TableColumn.js.map +1 -1
- package/build/dist/Types/Database/UnsynchronizedIndex.js +46 -0
- package/build/dist/Types/Database/UnsynchronizedIndex.js.map +1 -0
- package/build/dist/Types/Decimal.js +14 -3
- package/build/dist/Types/Decimal.js.map +1 -1
- package/build/dist/Types/HashedString.js +95 -5
- package/build/dist/Types/HashedString.js.map +1 -1
- package/build/dist/Types/Permission.js +42 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Port.js +15 -5
- package/build/dist/Types/Port.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +51 -10
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/useLiveLogsRefresh.js +44 -0
- package/build/dist/UI/Components/LogsViewer/useLiveLogsRefresh.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/useLogsHistogram.js +75 -0
- package/build/dist/UI/Components/LogsViewer/useLogsHistogram.js.map +1 -0
- package/build/dist/UI/Components/Navbar/NavBar.js +3 -1
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +19 -7
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/UserProjectsModelAPI.js +156 -0
- package/build/dist/UI/Utils/ModelAPI/UserProjectsModelAPI.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardNetworkMapComponent.js +114 -0
- package/build/dist/Utils/Dashboard/Components/DashboardNetworkMapComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/TeamMembersByProject.js +145 -0
- package/build/dist/Utils/TeamMembersByProject.js.map +1 -0
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ import Model from "../../Models/DatabaseModels/CephCluster";
|
|
|
5
5
|
import Label from "../../Models/DatabaseModels/Label";
|
|
6
6
|
import { OnCreate } from "../Types/Database/Hooks";
|
|
7
7
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
8
|
+
import ResourceHeartbeat from "../Utils/Telemetry/ResourceHeartbeat";
|
|
8
9
|
import ObjectID from "../../Types/ObjectID";
|
|
9
10
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
10
11
|
import OneUptimeDate from "../../Types/Date";
|
|
@@ -181,7 +182,6 @@ export class Service extends DatabaseService<Model> {
|
|
|
181
182
|
capacityUsedPercent?: number | undefined;
|
|
182
183
|
},
|
|
183
184
|
): Promise<void> {
|
|
184
|
-
const cacheKey: string = clusterId.toString();
|
|
185
185
|
const extrasFingerprint: string = crypto
|
|
186
186
|
.createHash("sha1")
|
|
187
187
|
.update(
|
|
@@ -200,34 +200,6 @@ export class Service extends DatabaseService<Model> {
|
|
|
200
200
|
)
|
|
201
201
|
.digest("hex");
|
|
202
202
|
|
|
203
|
-
let cached: string | null = null;
|
|
204
|
-
try {
|
|
205
|
-
cached = await GlobalCache.getString(LAST_SEEN_CACHE_NAMESPACE, cacheKey);
|
|
206
|
-
} catch {
|
|
207
|
-
/*
|
|
208
|
-
* Cache unavailable — fail open and refresh lastSeenAt anyway. A
|
|
209
|
-
* cache error must never skip the DB write below, otherwise the
|
|
210
|
-
* resource is wrongly marked "disconnected" while telemetry is
|
|
211
|
-
* still flowing. Mirrors shouldRunMaintenance's fail-open stance.
|
|
212
|
-
*/
|
|
213
|
-
cached = null;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (cached === extrasFingerprint) {
|
|
217
|
-
return; // same data was written recently
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
try {
|
|
221
|
-
await GlobalCache.setString(
|
|
222
|
-
LAST_SEEN_CACHE_NAMESPACE,
|
|
223
|
-
cacheKey,
|
|
224
|
-
extrasFingerprint,
|
|
225
|
-
{ expiresInSeconds: LAST_SEEN_THROTTLE_SECONDS },
|
|
226
|
-
);
|
|
227
|
-
} catch {
|
|
228
|
-
// Best-effort throttle write; proceed with the DB update regardless.
|
|
229
|
-
}
|
|
230
|
-
|
|
231
203
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
232
204
|
const liveness: any = {
|
|
233
205
|
lastSeenAt: OneUptimeDate.getCurrentDate(),
|
|
@@ -235,91 +207,59 @@ export class Service extends DatabaseService<Model> {
|
|
|
235
207
|
};
|
|
236
208
|
|
|
237
209
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
238
|
-
const
|
|
210
|
+
const metadata: any = {};
|
|
239
211
|
|
|
240
212
|
if (extra?.cephVersion) {
|
|
241
|
-
|
|
213
|
+
metadata.cephVersion = extra.cephVersion;
|
|
242
214
|
}
|
|
243
215
|
if (extra?.fsid) {
|
|
244
|
-
|
|
216
|
+
metadata.fsid = extra.fsid;
|
|
245
217
|
}
|
|
246
218
|
if (extra?.agentVersion) {
|
|
247
|
-
|
|
219
|
+
metadata.agentVersion = extra.agentVersion;
|
|
248
220
|
}
|
|
249
221
|
/*
|
|
250
222
|
* Counts and health: 0 is a legitimate value (healthStatus 0 = OK,
|
|
251
223
|
* osdUpCount 0 = every OSD down) — gate on undefined, not falsiness.
|
|
252
224
|
*/
|
|
253
225
|
if (extra?.monCount !== undefined) {
|
|
254
|
-
|
|
226
|
+
metadata.monCount = extra.monCount;
|
|
255
227
|
}
|
|
256
228
|
if (extra?.osdCount !== undefined) {
|
|
257
|
-
|
|
229
|
+
metadata.osdCount = extra.osdCount;
|
|
258
230
|
}
|
|
259
231
|
if (extra?.osdUpCount !== undefined) {
|
|
260
|
-
|
|
232
|
+
metadata.osdUpCount = extra.osdUpCount;
|
|
261
233
|
}
|
|
262
234
|
if (extra?.osdInCount !== undefined) {
|
|
263
|
-
|
|
235
|
+
metadata.osdInCount = extra.osdInCount;
|
|
264
236
|
}
|
|
265
237
|
if (extra?.poolCount !== undefined) {
|
|
266
|
-
|
|
238
|
+
metadata.poolCount = extra.poolCount;
|
|
267
239
|
}
|
|
268
240
|
if (extra?.healthStatus !== undefined) {
|
|
269
|
-
|
|
241
|
+
metadata.healthStatus = extra.healthStatus;
|
|
270
242
|
}
|
|
271
243
|
if (extra?.capacityUsedPercent !== undefined) {
|
|
272
|
-
|
|
244
|
+
metadata.capacityUsedPercent = extra.capacityUsedPercent;
|
|
273
245
|
}
|
|
274
246
|
|
|
275
247
|
/*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
* Collector-supplied strings are clamped to their declared column
|
|
281
|
-
* widths inside updateColumnsByIdWithoutHooks — see
|
|
282
|
-
* DatabaseService.truncateStringColumnsToMaxLength.
|
|
248
|
+
* One gated, non-blocking heartbeat write. The gates, the fail-open /
|
|
249
|
+
* fail-closed split and the liveness-only fallback all live in
|
|
250
|
+
* ResourceHeartbeat — see there for why this row's throttle used to
|
|
251
|
+
* provide no throttling at all.
|
|
283
252
|
*/
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
* reject the statement, lastSeenAt silently stops advancing and
|
|
295
|
-
* markDisconnectedClusters flips a perfectly healthy Ceph cluster to
|
|
296
|
-
* "disconnected" 15 minutes later — with telemetry still arriving the
|
|
297
|
-
* whole time. That was issue #3006 on the Host path (a host.ip list
|
|
298
|
-
* longer than the then-varchar(500) column). Retry with liveness only
|
|
299
|
-
* so the enrichment is what gets dropped, never the heartbeat.
|
|
300
|
-
*/
|
|
301
|
-
logger.warn(
|
|
302
|
-
`CephClusterService.updateLastSeen: metadata write failed for Ceph cluster ${clusterId.toString()}, falling back to a liveness-only update: ${
|
|
303
|
-
err instanceof Error ? err.message : String(err)
|
|
304
|
-
}`,
|
|
305
|
-
);
|
|
306
|
-
|
|
307
|
-
/*
|
|
308
|
-
* The throttle fingerprint was already stored, so without this the
|
|
309
|
-
* next batch would short-circuit on a cache hit and skip the retry
|
|
310
|
-
* for the rest of the window.
|
|
311
|
-
*/
|
|
312
|
-
try {
|
|
313
|
-
await GlobalCache.deleteKey(LAST_SEEN_CACHE_NAMESPACE, cacheKey);
|
|
314
|
-
} catch {
|
|
315
|
-
// Best-effort; the fallback write below is what actually matters.
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
await this.updateColumnsByIdWithoutHooks({
|
|
319
|
-
id: clusterId,
|
|
320
|
-
data: liveness,
|
|
321
|
-
});
|
|
322
|
-
}
|
|
253
|
+
await ResourceHeartbeat.write({
|
|
254
|
+
service: this,
|
|
255
|
+
id: clusterId,
|
|
256
|
+
cacheNamespace: LAST_SEEN_CACHE_NAMESPACE,
|
|
257
|
+
throttleInSeconds: LAST_SEEN_THROTTLE_SECONDS,
|
|
258
|
+
liveness: liveness,
|
|
259
|
+
metadata: metadata,
|
|
260
|
+
fingerprint: extrasFingerprint,
|
|
261
|
+
describe: `ceph cluster ${clusterId.toString()}`,
|
|
262
|
+
});
|
|
323
263
|
}
|
|
324
264
|
|
|
325
265
|
/**
|
|
@@ -2,6 +2,7 @@ import DatabaseService from "./DatabaseService";
|
|
|
2
2
|
import Model from "../../Models/DatabaseModels/CloudResource";
|
|
3
3
|
import Label from "../../Models/DatabaseModels/Label";
|
|
4
4
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
5
|
+
import ResourceHeartbeat from "../Utils/Telemetry/ResourceHeartbeat";
|
|
5
6
|
import ObjectID from "../../Types/ObjectID";
|
|
6
7
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
7
8
|
import OneUptimeDate from "../../Types/Date";
|
|
@@ -154,7 +155,6 @@ export class Service extends DatabaseService<Model> {
|
|
|
154
155
|
runtimeVersion?: string | undefined;
|
|
155
156
|
},
|
|
156
157
|
): Promise<void> {
|
|
157
|
-
const cacheKey: string = cloudResourceId.toString();
|
|
158
158
|
const extrasFingerprint: string = crypto
|
|
159
159
|
.createHash("sha1")
|
|
160
160
|
.update(
|
|
@@ -170,34 +170,6 @@ export class Service extends DatabaseService<Model> {
|
|
|
170
170
|
)
|
|
171
171
|
.digest("hex");
|
|
172
172
|
|
|
173
|
-
let cached: string | null = null;
|
|
174
|
-
try {
|
|
175
|
-
cached = await GlobalCache.getString(LAST_SEEN_CACHE_NAMESPACE, cacheKey);
|
|
176
|
-
} catch {
|
|
177
|
-
/*
|
|
178
|
-
* Cache unavailable — fail open and refresh lastSeenAt anyway. A
|
|
179
|
-
* cache error must never skip the DB write below, otherwise the
|
|
180
|
-
* resource is wrongly marked "disconnected" while telemetry is
|
|
181
|
-
* still flowing. Mirrors shouldRunMaintenance's fail-open stance.
|
|
182
|
-
*/
|
|
183
|
-
cached = null;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (cached === extrasFingerprint) {
|
|
187
|
-
return; // same data was written recently
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
try {
|
|
191
|
-
await GlobalCache.setString(
|
|
192
|
-
LAST_SEEN_CACHE_NAMESPACE,
|
|
193
|
-
cacheKey,
|
|
194
|
-
extrasFingerprint,
|
|
195
|
-
{ expiresInSeconds: LAST_SEEN_THROTTLE_SECONDS },
|
|
196
|
-
);
|
|
197
|
-
} catch {
|
|
198
|
-
// Best-effort throttle write; proceed with the DB update regardless.
|
|
199
|
-
}
|
|
200
|
-
|
|
201
173
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
202
174
|
const liveness: any = {
|
|
203
175
|
lastSeenAt: OneUptimeDate.getCurrentDate(),
|
|
@@ -205,78 +177,46 @@ export class Service extends DatabaseService<Model> {
|
|
|
205
177
|
};
|
|
206
178
|
|
|
207
179
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
208
|
-
const
|
|
180
|
+
const metadata: any = {};
|
|
209
181
|
|
|
210
182
|
if (extra?.agentVersion) {
|
|
211
|
-
|
|
183
|
+
metadata.agentVersion = extra.agentVersion;
|
|
212
184
|
}
|
|
213
185
|
if (extra?.cloudPlatform) {
|
|
214
|
-
|
|
186
|
+
metadata.cloudPlatform = extra.cloudPlatform;
|
|
215
187
|
}
|
|
216
188
|
if (extra?.cloudProvider) {
|
|
217
|
-
|
|
189
|
+
metadata.cloudProvider = extra.cloudProvider;
|
|
218
190
|
}
|
|
219
191
|
if (extra?.cloudRegion) {
|
|
220
|
-
|
|
192
|
+
metadata.cloudRegion = extra.cloudRegion;
|
|
221
193
|
}
|
|
222
194
|
if (extra?.cloudAccountId) {
|
|
223
|
-
|
|
195
|
+
metadata.cloudAccountId = extra.cloudAccountId;
|
|
224
196
|
}
|
|
225
197
|
if (extra?.runtimeName) {
|
|
226
|
-
|
|
198
|
+
metadata.runtimeName = extra.runtimeName;
|
|
227
199
|
}
|
|
228
200
|
if (extra?.runtimeVersion) {
|
|
229
|
-
|
|
201
|
+
metadata.runtimeVersion = extra.runtimeVersion;
|
|
230
202
|
}
|
|
231
203
|
|
|
232
204
|
/*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
* Collector-supplied strings are clamped to their declared column
|
|
238
|
-
* widths inside updateColumnsByIdWithoutHooks — see
|
|
239
|
-
* DatabaseService.truncateStringColumnsToMaxLength.
|
|
205
|
+
* One gated, non-blocking heartbeat write. The gates, the fail-open /
|
|
206
|
+
* fail-closed split and the liveness-only fallback all live in
|
|
207
|
+
* ResourceHeartbeat — see there for why this row's throttle used to
|
|
208
|
+
* provide no throttling at all.
|
|
240
209
|
*/
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
* reject the statement, lastSeenAt silently stops advancing and
|
|
252
|
-
* markDisconnectedResources flips a perfectly healthy cloud resource
|
|
253
|
-
* to "disconnected" 15 minutes later — with telemetry still arriving
|
|
254
|
-
* the whole time. That was issue #3006 on the Host path (a host.ip
|
|
255
|
-
* list longer than the then-varchar(500) column). Retry with liveness
|
|
256
|
-
* only so the enrichment is what gets dropped, never the heartbeat.
|
|
257
|
-
*/
|
|
258
|
-
logger.warn(
|
|
259
|
-
`CloudResourceService.updateLastSeen: metadata write failed for cloud resource ${cloudResourceId.toString()}, falling back to a liveness-only update: ${
|
|
260
|
-
err instanceof Error ? err.message : String(err)
|
|
261
|
-
}`,
|
|
262
|
-
);
|
|
263
|
-
|
|
264
|
-
/*
|
|
265
|
-
* The throttle fingerprint was already stored, so without this the
|
|
266
|
-
* next batch would short-circuit on a cache hit and skip the retry
|
|
267
|
-
* for the rest of the window.
|
|
268
|
-
*/
|
|
269
|
-
try {
|
|
270
|
-
await GlobalCache.deleteKey(LAST_SEEN_CACHE_NAMESPACE, cacheKey);
|
|
271
|
-
} catch {
|
|
272
|
-
// Best-effort; the fallback write below is what actually matters.
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
await this.updateColumnsByIdWithoutHooks({
|
|
276
|
-
id: cloudResourceId,
|
|
277
|
-
data: liveness,
|
|
278
|
-
});
|
|
279
|
-
}
|
|
210
|
+
await ResourceHeartbeat.write({
|
|
211
|
+
service: this,
|
|
212
|
+
id: cloudResourceId,
|
|
213
|
+
cacheNamespace: LAST_SEEN_CACHE_NAMESPACE,
|
|
214
|
+
throttleInSeconds: LAST_SEEN_THROTTLE_SECONDS,
|
|
215
|
+
liveness: liveness,
|
|
216
|
+
metadata: metadata,
|
|
217
|
+
fingerprint: extrasFingerprint,
|
|
218
|
+
describe: `cloud resource ${cloudResourceId.toString()}`,
|
|
219
|
+
});
|
|
280
220
|
}
|
|
281
221
|
|
|
282
222
|
@CaptureSpan()
|
|
@@ -14,6 +14,11 @@ import {
|
|
|
14
14
|
import GitHubUtil, {
|
|
15
15
|
GitHubRepository,
|
|
16
16
|
} from "../Utils/CodeRepository/GitHub/GitHub";
|
|
17
|
+
import GitHubInstallationBinding from "../Utils/CodeRepository/GitHub/GitHubInstallationBinding";
|
|
18
|
+
import BadDataException from "../../Types/Exception/BadDataException";
|
|
19
|
+
import CreateBy from "../Types/Database/CreateBy";
|
|
20
|
+
import UpdateBy from "../Types/Database/UpdateBy";
|
|
21
|
+
import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
|
|
17
22
|
|
|
18
23
|
export interface ImportReposFromInstallationResult {
|
|
19
24
|
imported: number;
|
|
@@ -25,6 +30,93 @@ export class Service extends DatabaseService<Model> {
|
|
|
25
30
|
super(Model);
|
|
26
31
|
}
|
|
27
32
|
|
|
33
|
+
/*
|
|
34
|
+
* Last line of defence for the installation-to-project binding.
|
|
35
|
+
*
|
|
36
|
+
* gitHubAppInstallationId is already closed to API callers at the column
|
|
37
|
+
* level, but that only stops requests that go through permission checks —
|
|
38
|
+
* every write here is made with `props: { isRoot: true }`, which skips them
|
|
39
|
+
* entirely. This hook runs regardless of isRoot, so any route (including one
|
|
40
|
+
* added later) that writes a row carrying another tenant's installation ID
|
|
41
|
+
* is refused at the service boundary rather than at the token endpoint.
|
|
42
|
+
*
|
|
43
|
+
* The legitimate writer is importReposFromInstallation, which the install
|
|
44
|
+
* callback and the installation webhooks only ever call for a project the
|
|
45
|
+
* installation is already bound to — so this check passes for them.
|
|
46
|
+
*/
|
|
47
|
+
@CaptureSpan()
|
|
48
|
+
protected override async onBeforeCreate(
|
|
49
|
+
createBy: CreateBy<Model>,
|
|
50
|
+
): Promise<OnCreate<Model>> {
|
|
51
|
+
const installationId: string | undefined =
|
|
52
|
+
createBy.data.gitHubAppInstallationId;
|
|
53
|
+
|
|
54
|
+
if (installationId) {
|
|
55
|
+
const projectId: ObjectID | undefined =
|
|
56
|
+
createBy.data.projectId || createBy.props.tenantId;
|
|
57
|
+
|
|
58
|
+
if (!projectId) {
|
|
59
|
+
throw new BadDataException(
|
|
60
|
+
"A project is required to connect a GitHub App installation to a repository.",
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
await GitHubInstallationBinding.assertInstallationBoundToProject({
|
|
65
|
+
projectId: projectId,
|
|
66
|
+
installationId: installationId,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return { createBy, carryForward: null };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/*
|
|
74
|
+
* Same rule on the update path. Clearing the installation ID is always
|
|
75
|
+
* allowed — that is how the `installation.deleted` webhook tears a
|
|
76
|
+
* disconnected installation out of the database.
|
|
77
|
+
*/
|
|
78
|
+
@CaptureSpan()
|
|
79
|
+
protected override async onBeforeUpdate(
|
|
80
|
+
updateBy: UpdateBy<Model>,
|
|
81
|
+
): Promise<OnUpdate<Model>> {
|
|
82
|
+
const installationId: string | undefined = updateBy.data
|
|
83
|
+
.gitHubAppInstallationId as string | undefined;
|
|
84
|
+
|
|
85
|
+
if (installationId) {
|
|
86
|
+
/*
|
|
87
|
+
* updateBy matches by query rather than by id, so check every row the
|
|
88
|
+
* write would touch: one unbound row is enough to leak a token.
|
|
89
|
+
*/
|
|
90
|
+
const repositories: Array<Model> = await this.findBy({
|
|
91
|
+
query: updateBy.query,
|
|
92
|
+
select: {
|
|
93
|
+
_id: true,
|
|
94
|
+
projectId: true,
|
|
95
|
+
},
|
|
96
|
+
limit: LIMIT_MAX,
|
|
97
|
+
skip: 0,
|
|
98
|
+
props: {
|
|
99
|
+
isRoot: true,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
for (const repository of repositories) {
|
|
104
|
+
if (!repository.projectId) {
|
|
105
|
+
throw new BadDataException(
|
|
106
|
+
"A project is required to connect a GitHub App installation to a repository.",
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
await GitHubInstallationBinding.assertInstallationBoundToProject({
|
|
111
|
+
projectId: repository.projectId,
|
|
112
|
+
installationId: installationId,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return { updateBy, carryForward: null };
|
|
118
|
+
}
|
|
119
|
+
|
|
28
120
|
/*
|
|
29
121
|
* Imports all repositories accessible to a GitHub App installation into a
|
|
30
122
|
* project. Repositories that already exist for the project (matched on
|
|
@@ -174,13 +266,24 @@ export class Service extends DatabaseService<Model> {
|
|
|
174
266
|
},
|
|
175
267
|
});
|
|
176
268
|
|
|
177
|
-
|
|
269
|
+
/*
|
|
270
|
+
* Only GitHub-App-connected repos can be cloned/pushed by the agent — and
|
|
271
|
+
* only ones whose installation this project actually owns. Resolution
|
|
272
|
+
* probes EVERY candidate's file tree, so an unbound row here would have
|
|
273
|
+
* the server read another tenant's private repository on its own
|
|
274
|
+
* initiative (GHSA-xx95-gmcf-7q86).
|
|
275
|
+
*/
|
|
276
|
+
const boundInstallationId: string | null =
|
|
277
|
+
await GitHubInstallationBinding.getBoundInstallationId(data.projectId);
|
|
278
|
+
|
|
178
279
|
const resolvable: Array<ResolvableRepository> = repositories
|
|
179
280
|
.filter((repository: Model) => {
|
|
180
281
|
return (
|
|
181
282
|
repository.repositoryHostedAt === CodeRepositoryType.GitHub &&
|
|
182
283
|
Boolean(repository.gitHubAppInstallationId) &&
|
|
183
|
-
Boolean(repository.id)
|
|
284
|
+
Boolean(repository.id) &&
|
|
285
|
+
Boolean(boundInstallationId) &&
|
|
286
|
+
repository.gitHubAppInstallationId === boundInstallationId
|
|
184
287
|
);
|
|
185
288
|
})
|
|
186
289
|
.map((repository: Model) => {
|