@oneuptime/common 12.0.3 → 12.0.5
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/AIRun.ts +38 -1
- package/Models/DatabaseModels/AlertFeed.ts +30 -0
- package/Models/DatabaseModels/CephCluster.ts +14 -0
- package/Models/DatabaseModels/CodeRepository.ts +14 -6
- package/Models/DatabaseModels/Dashboard.ts +28 -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/Incident.ts +2 -0
- package/Models/DatabaseModels/IncidentEpisode.ts +1 -0
- package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +1 -0
- package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
- package/Models/DatabaseModels/IncidentFeed.ts +30 -0
- package/Models/DatabaseModels/IncidentPublicNote.ts +1 -0
- package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
- package/Models/DatabaseModels/IoTFleet.ts +14 -0
- package/Models/DatabaseModels/KubernetesCluster.ts +14 -0
- package/Models/DatabaseModels/LogSavedView.ts +33 -0
- package/Models/DatabaseModels/NetworkDevice.ts +14 -0
- package/Models/DatabaseModels/NetworkInterface.ts +18 -0
- package/Models/DatabaseModels/Project.ts +247 -11
- package/Models/DatabaseModels/ProxmoxCluster.ts +14 -0
- package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.ts +4 -4
- package/Models/DatabaseModels/Service.ts +30 -0
- package/Models/DatabaseModels/StatusPage.ts +28 -0
- package/Models/DatabaseModels/StatusPageAnnouncement.ts +1 -0
- package/Models/DatabaseModels/StatusPagePrivateUser.ts +30 -0
- package/Models/DatabaseModels/User.ts +30 -0
- package/Server/API/AIAgentDataAPI.ts +75 -55
- package/Server/API/AIInvestigationAPI.ts +175 -17
- package/Server/API/DashboardAPI.ts +429 -22
- package/Server/API/GitHubAPI.ts +119 -283
- package/Server/API/StatusPageAPI.ts +38 -19
- package/Server/API/UserAPI.ts +263 -1
- package/Server/EnvironmentConfig.ts +23 -3
- package/Server/Infrastructure/ClickhouseConfig.ts +15 -1
- package/Server/Infrastructure/ClickhouseDatabase.ts +1 -1
- package/Server/Infrastructure/GlobalCache.ts +37 -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/1786096660558-AddTimeRangeToLogSavedView.ts +27 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.ts +100 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.ts +89 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.ts +27 -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/1786400000000-AddMasterPasswordSalt.ts +40 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.ts +26 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +20 -0
- package/Server/Services/AIRunService.ts +78 -10
- package/Server/Services/AIService.ts +94 -22
- package/Server/Services/AlertFeedService.ts +5 -0
- package/Server/Services/AnalyticsDatabaseService.ts +101 -1
- package/Server/Services/CodeRepositoryService.ts +105 -2
- package/Server/Services/DatabaseService.ts +227 -3
- package/Server/Services/IncidentFeedService.ts +5 -0
- package/Server/Services/LlmLogService.ts +46 -2
- package/Server/Services/OpenTelemetryIngestService.ts +230 -26
- package/Server/Services/UserService.ts +184 -0
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +6 -0
- package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +4 -0
- package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +8 -5
- package/Server/Utils/AI/CodeFix/FixRunBudget.ts +90 -16
- package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +2 -0
- package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +2 -0
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +223 -22
- package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +25 -24
- package/Server/Utils/AI/SRE/ConfidenceSignal.ts +182 -71
- package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +252 -43
- package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +25 -24
- package/Server/Utils/AI/SRE/InstrumentationTaskTrigger.ts +47 -13
- package/Server/Utils/AI/SRE/InvestigationGrader.ts +9 -5
- package/Server/Utils/AI/SRE/InvestigationQueue.ts +141 -24
- package/Server/Utils/AI/SRE/InvestigationSubjectLock.ts +66 -0
- package/Server/Utils/AI/SRE/PostedRootCause.ts +94 -3
- package/Server/Utils/AI/SRE/README.md +1 -1
- package/Server/Utils/AI/SRE/SubjectCodeFixRun.ts +132 -10
- package/Server/Utils/AI/Toolbox/CodeTools.ts +45 -4
- package/Server/Utils/AnalyticsDatabase/ClusterConfig.ts +24 -0
- 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/Monitor/Criteria/APIRequestCriteria.ts +29 -0
- package/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.ts +56 -0
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +46 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +1 -0
- package/Server/Utils/PasswordHash.ts +330 -0
- package/Tests/App/Dashboard/AIInvestigationHeaderStatus.test.tsx +251 -0
- package/Tests/App/Dashboard/EventStatusPanel.test.tsx +747 -0
- package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +480 -0
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1184 -0
- package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +500 -0
- package/Tests/App/Dashboard/OverviewCustomFields.test.tsx +333 -0
- package/Tests/App/Dashboard/PortMonitorCriteriaFilter.test.ts +93 -0
- package/Tests/App/Dashboard/UserCustomFields.test.tsx +392 -0
- package/Tests/App/StatusPage/PublicStatusPageAPIErrorHandling.test.ts +117 -0
- package/Tests/App/StatusPage/StatusPageModelAPIPolymorphism.test.ts +223 -0
- package/Tests/Models/DatabaseModels/PermissionCatalogueCoverage.test.ts +243 -0
- package/Tests/Server/API/AIAgentDataFixFromIncidentContext.test.ts +266 -0
- package/Tests/Server/API/AIAgentDataRepositoryToken.test.ts +381 -0
- package/Tests/Server/API/AIInvestigationAPI.test.ts +594 -0
- package/Tests/Server/API/AIInvestigationCreateFixTask.test.ts +80 -0
- package/Tests/Server/API/DashboardMasterPasswordAPI.test.ts +172 -1
- package/Tests/Server/API/DashboardPublicAttributeValuesAPI.test.ts +943 -0
- package/Tests/Server/API/DashboardPublicMetricsAggregateAPI.test.ts +1296 -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/StatusPageMasterPasswordAPI.test.ts +335 -0
- package/Tests/Server/API/UserProjectsAPI.test.ts +852 -0
- package/Tests/Server/Infrastructure/GlobalCache.test.ts +128 -0
- package/Tests/Server/Infrastructure/SemaphoreMutex.test.ts +215 -0
- package/Tests/Server/Services/AIRunCodeFixClaim.test.ts +59 -5
- package/Tests/Server/Services/AIRunHumanVerdict.test.ts +127 -58
- package/Tests/Server/Services/AIServiceDailyBudget.test.ts +396 -20
- package/Tests/Server/Services/AddMasterPasswordSaltMigration.test.ts +283 -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 +30 -1
- 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 +880 -0
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsWithoutHooks.test.ts +54 -0
- package/Tests/Server/Services/FeedAIRunAssociation.test.ts +125 -0
- package/Tests/Server/Services/FixFromIncidentTaskTrigger.test.ts +418 -57
- package/Tests/Server/Services/InstrumentationTaskTrigger.test.ts +173 -14
- package/Tests/Server/Services/MasterPasswordScrypt.test.ts +567 -0
- package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +568 -0
- package/Tests/Server/Services/RestoreDroppedUniqueIndexesMigration.test.ts +386 -0
- package/Tests/Server/Services/RestoreServiceLowerNameIndexMigration.test.ts +240 -0
- package/Tests/Server/Services/SeparateIncidentAlertAiSettingsMigration.test.ts +194 -0
- package/Tests/Server/Services/UserServiceFirstMasterAdminElection.test.ts +885 -0
- package/Tests/Server/Services/WidenHashedStringColumnsForScryptMigration.test.ts +220 -0
- package/Tests/Server/Utils/AI/AIAlertGating.test.ts +37 -4
- package/Tests/Server/Utils/AI/AIConfidenceSignal.test.ts +330 -29
- package/Tests/Server/Utils/AI/AIIncidentGating.test.ts +25 -0
- package/Tests/Server/Utils/AI/AIInvestigationQueue.test.ts +293 -5
- package/Tests/Server/Utils/AI/CodeFixAgentCompletion.test.ts +59 -1
- package/Tests/Server/Utils/AI/CodeTools.test.ts +47 -1
- package/Tests/Server/Utils/AI/CodeWriteTools.test.ts +10 -0
- package/Tests/Server/Utils/AI/FixFromIncidentAutoTrigger.test.ts +342 -19
- package/Tests/Server/Utils/AI/FixRunBudget.test.ts +214 -30
- package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +2 -0
- package/Tests/Server/Utils/AI/InvestigationGrader.test.ts +65 -17
- package/Tests/Server/Utils/AI/InvestigationQueueRemediationExecution.test.ts +3 -0
- package/Tests/Server/Utils/AI/InvestigationSettlement.test.ts +313 -20
- package/Tests/Server/Utils/AI/PostedRootCause.test.ts +254 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +4 -0
- package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +2 -0
- package/Tests/Server/Utils/AI/SubjectCodeFixRunDedupe.test.ts +44 -0
- package/Tests/Server/Utils/AnalyticsDatabase/ClusterAwareSchema.test.ts +30 -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/GitHubInstallationOwnershipVerification.test.ts +340 -0
- package/Tests/Server/Utils/GitHubWebhookAndTreeCacheIsolation.test.ts +250 -0
- package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaPortTimings.test.ts +212 -0
- package/Tests/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.test.ts +401 -0
- package/Tests/Server/Utils/Monitor/MonitorMetricUtilPortTimings.test.ts +243 -0
- package/Tests/Server/Utils/PasswordHash.test.ts +585 -0
- package/Tests/Types/Dashboard/DashboardTemplates.test.ts +111 -0
- package/Tests/Types/Database/ColumnLength.test.ts +7 -1
- package/Tests/Types/HashedStringPerUserSalt.test.ts +476 -0
- package/Tests/Types/Monitor/CephMetricCatalog.test.ts +104 -0
- package/Tests/Types/Monitor/CriteriaFilter.test.ts +4 -0
- package/Tests/Types/Monitor/DockerAlertTemplates.test.ts +293 -0
- package/Tests/Types/Monitor/DockerMetricCatalog.test.ts +109 -0
- package/Tests/Types/Monitor/DockerSwarmMetricCatalog.test.ts +118 -0
- package/Tests/Types/Monitor/HostAlertTemplates.test.ts +249 -0
- package/Tests/Types/Monitor/HostMetricCatalog.test.ts +104 -0
- package/Tests/Types/Monitor/IotAlertTemplates.test.ts +320 -0
- package/Tests/Types/Monitor/IotMetricCatalog.test.ts +104 -0
- package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +118 -0
- package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +42 -0
- package/Tests/Types/Monitor/MonitorStep.test.ts +38 -0
- package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +75 -0
- package/Tests/Types/Monitor/PodmanAlertTemplates.test.ts +271 -0
- package/Tests/Types/Monitor/PodmanMetricCatalog.test.ts +109 -0
- package/Tests/Types/Monitor/ProxmoxMetricCatalog.test.ts +107 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.test.ts +151 -0
- package/Tests/Types/Permission.test.ts +137 -0
- package/Tests/Types/Rum/SessionReplayMaskingMode.test.ts +101 -0
- package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +5 -5
- package/Tests/UI/Components/CardModelDetailEdit.test.tsx +3 -5
- package/Tests/UI/Components/CustomFields/CustomFieldsDetail.test.tsx +696 -0
- package/Tests/UI/Components/ErrorBoundary.test.tsx +158 -0
- package/Tests/UI/Components/FeedItemSafeMode.test.tsx +74 -0
- package/Tests/UI/Components/MoreMenu.test.tsx +756 -0
- package/Tests/UI/Components/StatusPage/ResourceGroupSection.test.tsx +62 -0
- package/Tests/UI/Monitor/PortMonitorView.test.tsx +237 -0
- package/Tests/UI/Telemetry/TelemetrySnapshotWindowAlert.test.tsx +91 -0
- package/Tests/UI/Utils/DownloadFile.test.ts +103 -0
- package/Tests/UI/Utils/ErrorSupportBundle.test.ts +582 -0
- package/Tests/UI/Utils/Project.test.ts +31 -0
- package/Tests/UI/Utils/StatusPageModelAPIInjection.test.ts +245 -0
- package/Tests/UI/Utils/UseDashboardGridDnd.test.tsx +820 -0
- package/Tests/UI/Utils/UserProjectsModelAPI.test.ts +714 -0
- package/Tests/Utils/Dashboard/DashboardViewConfig.test.ts +329 -0
- package/Tests/Utils/Dashboard/GridLayout.test.ts +951 -0
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +117 -0
- package/Tests/Utils/RecordingRuleExpression.test.ts +327 -0
- package/Tests/Utils/StatusPage/GroupNestingLayout.test.ts +186 -0
- package/Tests/Utils/StatusPage/GroupTree.test.ts +456 -0
- package/Tests/Utils/StatusPage/OverviewGroupHierarchyVisibility.test.ts +588 -0
- package/Tests/Utils/TeamMembersByProject.test.ts +655 -0
- package/Tests/Utils/Telemetry/SavedViewTimeRange.test.ts +244 -0
- package/Tests/Utils/Telemetry/TelemetryQueryTimeRange.test.ts +825 -0
- package/Types/AI/AIRunCodeFixRecommendation.ts +17 -0
- package/Types/AI/CodeFixTaskContext.ts +63 -3
- package/Types/AI/CodeFixTaskType.ts +3 -3
- package/Types/Database/ColumnLength.ts +9 -1
- package/Types/Database/TableColumn.ts +11 -0
- package/Types/Database/UnsynchronizedIndex.ts +48 -0
- package/Types/HashedString.ts +140 -4
- package/Types/Monitor/CriteriaFilter.ts +4 -0
- package/Types/Monitor/DomainMonitor/DomainLookupMethod.ts +23 -0
- package/Types/Monitor/DomainMonitor/DomainMonitorResponse.ts +7 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +24 -7
- package/Types/Monitor/MonitorMetricType.ts +8 -0
- package/Types/Monitor/MonitorStep.ts +10 -1
- package/Types/Monitor/MonitorStepDomainMonitor.ts +21 -0
- package/Types/Monitor/PortMonitor/PortMonitorTimings.ts +10 -0
- package/Types/Permission.ts +23 -175
- package/Types/Probe/ProbeMonitorResponse.ts +6 -0
- package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +2 -3
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +85 -11
- package/UI/Components/ErrorBoundary.tsx +138 -11
- package/UI/Components/Feed/FeedItem.tsx +9 -2
- package/UI/Components/ModelDetail/CardModelDetail.tsx +0 -12
- package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +12 -2
- package/UI/Components/MoreMenu/MoreMenu.tsx +285 -97
- package/UI/Components/MoreMenu/MoreMenuItem.tsx +8 -5
- package/UI/Components/Navbar/NavBar.tsx +12 -2
- package/UI/Components/Navbar/NavBarMenuModal.tsx +19 -7
- package/UI/Utils/DownloadFile.ts +16 -8
- package/UI/Utils/ErrorSupportBundle.ts +805 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +19 -8
- package/UI/Utils/ModelAPI/UserProjectsModelAPI.ts +257 -0
- package/UI/Utils/Project.ts +4 -0
- package/UI/Utils/StatusPage.ts +8 -2
- package/UI/Utils/UseDashboardGridDnd.ts +917 -0
- package/Utils/Dashboard/DashboardViewConfig.ts +80 -36
- package/Utils/Dashboard/GridLayout.ts +523 -0
- package/Utils/Metrics/RecordingRuleExpression.ts +19 -17
- package/Utils/Monitor/MonitorMetricType.ts +44 -2
- package/Utils/StatusPage/GroupNestingLayout.ts +69 -0
- package/Utils/StatusPage/GroupTree.ts +157 -66
- package/Utils/StatusPage/ResourceUptime.ts +37 -2
- package/Utils/TeamMembersByProject.ts +237 -0
- package/Utils/Telemetry/SavedViewTimeRange.ts +114 -0
- package/Utils/Telemetry/TelemetryQueryTimeRange.ts +334 -0
- package/build/dist/Models/DatabaseModels/AIRun.js +39 -1
- package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertFeed.js +32 -0
- package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
- 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/Dashboard.js +29 -0
- package/build/dist/Models/DatabaseModels/Dashboard.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/Incident.js +2 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentFeed.js +32 -0
- package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.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/LogSavedView.js +33 -0
- package/build/dist/Models/DatabaseModels/LogSavedView.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 +257 -13
- 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/ScheduledMaintenance.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.js +4 -4
- package/build/dist/Models/DatabaseModels/Service.js +28 -1
- package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +29 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +1 -0
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js +32 -0
- package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.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 +49 -48
- package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +111 -11
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +312 -15
- 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/StatusPageAPI.js +29 -11
- package/build/dist/Server/API/StatusPageAPI.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 +21 -3
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseConfig.js +12 -1
- package/build/dist/Server/Infrastructure/ClickhouseConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseDatabase.js +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseDatabase.js.map +1 -1
- package/build/dist/Server/Infrastructure/GlobalCache.js +29 -0
- package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
- 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/1786096660558-AddTimeRangeToLogSavedView.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.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/1786101798351-MigrationName.js +36 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.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/1786400000000-AddMasterPasswordSalt.js +19 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.js +19 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AIRunService.js +58 -12
- package/build/dist/Server/Services/AIRunService.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +74 -21
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertFeedService.js +3 -0
- package/build/dist/Server/Services/AlertFeedService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +86 -2
- package/build/dist/Server/Services/AnalyticsDatabaseService.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 +180 -3
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentFeedService.js +3 -0
- package/build/dist/Server/Services/IncidentFeedService.js.map +1 -1
- package/build/dist/Server/Services/LlmLogService.js +22 -1
- package/build/dist/Server/Services/LlmLogService.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/UserService.js +165 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +3 -0
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js +4 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +8 -5
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +63 -24
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +2 -0
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +2 -0
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +156 -28
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +21 -19
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js +128 -49
- package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js +170 -31
- package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +21 -19
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js +33 -9
- package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +9 -5
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +121 -41
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationSubjectLock.js +46 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationSubjectLock.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js +61 -14
- package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js +79 -1
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.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/ClusterConfig.js +21 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/ClusterConfig.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/Monitor/Criteria/APIRequestCriteria.js +20 -3
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js +43 -0
- package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +33 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/PasswordHash.js +258 -0
- package/build/dist/Server/Utils/PasswordHash.js.map +1 -0
- package/build/dist/Types/AI/AIRunCodeFixRecommendation.js +18 -0
- package/build/dist/Types/AI/AIRunCodeFixRecommendation.js.map +1 -0
- package/build/dist/Types/AI/CodeFixTaskContext.js +23 -3
- package/build/dist/Types/AI/CodeFixTaskContext.js.map +1 -1
- package/build/dist/Types/AI/CodeFixTaskType.js +3 -3
- package/build/dist/Types/Database/ColumnLength.js +9 -1
- package/build/dist/Types/Database/ColumnLength.js.map +1 -1
- 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/HashedString.js +96 -5
- package/build/dist/Types/HashedString.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +4 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/DomainMonitor/DomainLookupMethod.js +24 -0
- package/build/dist/Types/Monitor/DomainMonitor/DomainLookupMethod.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +24 -7
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorMetricType.js +7 -0
- package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +6 -1
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js +15 -0
- package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/PortMonitor/PortMonitorTimings.js +2 -0
- package/build/dist/Types/Monitor/PortMonitor/PortMonitorTimings.js.map +1 -0
- package/build/dist/Types/Permission.js +23 -155
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +2 -5
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.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/ErrorBoundary.js +67 -8
- package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
- package/build/dist/UI/Components/Feed/FeedItem.js +2 -2
- package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +0 -12
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +12 -2
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +193 -65
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
- 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/DownloadFile.js +15 -8
- package/build/dist/UI/Utils/DownloadFile.js.map +1 -1
- package/build/dist/UI/Utils/ErrorSupportBundle.js +476 -0
- package/build/dist/UI/Utils/ErrorSupportBundle.js.map +1 -0
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -8
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.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/UI/Utils/Project.js +3 -0
- package/build/dist/UI/Utils/Project.js.map +1 -1
- package/build/dist/UI/Utils/StatusPage.js +4 -4
- package/build/dist/UI/Utils/StatusPage.js.map +1 -1
- package/build/dist/UI/Utils/UseDashboardGridDnd.js +551 -0
- package/build/dist/UI/Utils/UseDashboardGridDnd.js.map +1 -0
- package/build/dist/Utils/Dashboard/DashboardViewConfig.js +42 -26
- package/build/dist/Utils/Dashboard/DashboardViewConfig.js.map +1 -1
- package/build/dist/Utils/Dashboard/GridLayout.js +338 -0
- package/build/dist/Utils/Dashboard/GridLayout.js.map +1 -0
- package/build/dist/Utils/Metrics/RecordingRuleExpression.js +19 -17
- package/build/dist/Utils/Metrics/RecordingRuleExpression.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +38 -6
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/StatusPage/GroupNestingLayout.js +46 -0
- package/build/dist/Utils/StatusPage/GroupNestingLayout.js.map +1 -1
- package/build/dist/Utils/StatusPage/GroupTree.js +79 -34
- package/build/dist/Utils/StatusPage/GroupTree.js.map +1 -1
- package/build/dist/Utils/StatusPage/ResourceUptime.js +22 -1
- package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
- package/build/dist/Utils/TeamMembersByProject.js +145 -0
- package/build/dist/Utils/TeamMembersByProject.js.map +1 -0
- package/build/dist/Utils/Telemetry/SavedViewTimeRange.js +79 -0
- package/build/dist/Utils/Telemetry/SavedViewTimeRange.js.map +1 -0
- package/build/dist/Utils/Telemetry/TelemetryQueryTimeRange.js +236 -0
- package/build/dist/Utils/Telemetry/TelemetryQueryTimeRange.js.map +1 -0
- package/package.json +1 -1
|
@@ -15,11 +15,9 @@ import Response from "../Utils/Response";
|
|
|
15
15
|
import BaseAPI from "./BaseAPI";
|
|
16
16
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
17
17
|
import NotFoundException from "../../Types/Exception/NotFoundException";
|
|
18
|
-
import HashedString from "../../Types/HashedString";
|
|
19
18
|
import ObjectID from "../../Types/ObjectID";
|
|
20
19
|
import Dashboard from "../../Models/DatabaseModels/Dashboard";
|
|
21
20
|
import DashboardDomain from "../../Models/DatabaseModels/DashboardDomain";
|
|
22
|
-
import { EncryptionSecret } from "../EnvironmentConfig";
|
|
23
21
|
import { DASHBOARD_MASTER_PASSWORD_INVALID_MESSAGE } from "../../Types/Dashboard/MasterPassword";
|
|
24
22
|
import NotAuthenticatedException from "../../Types/Exception/NotAuthenticatedException";
|
|
25
23
|
import ForbiddenException from "../../Types/Exception/ForbiddenException";
|
|
@@ -69,6 +67,7 @@ import NetworkSiteService from "../Services/NetworkSiteService";
|
|
|
69
67
|
import SpanService from "../Services/SpanService";
|
|
70
68
|
import LogService from "../Services/LogService";
|
|
71
69
|
import DashboardComponentType from "../../Types/Dashboard/DashboardComponentType";
|
|
70
|
+
import { DashboardVariableType } from "../../Types/Dashboard/DashboardVariable";
|
|
72
71
|
import Includes from "../../Types/BaseDatabase/Includes";
|
|
73
72
|
|
|
74
73
|
/*
|
|
@@ -994,6 +993,14 @@ export default class DashboardAPI extends BaseAPI<
|
|
|
994
993
|
* the behaviour here scoped to the dashboard's owning projectId.
|
|
995
994
|
* Authorization reuses DashboardService.hasReadAccess (public flag, IP
|
|
996
995
|
* whitelist, master password) — never falls back to project-wide read.
|
|
996
|
+
*
|
|
997
|
+
* The requested attribute key is additionally allowlisted against the
|
|
998
|
+
* keys this dashboard's own variables bind to. Project scoping alone is
|
|
999
|
+
* not enough here: the underlying query is a SELECT DISTINCT over the
|
|
1000
|
+
* attribute map of every log, span, metric and exception in the project,
|
|
1001
|
+
* so an unrestricted key would let anyone holding a public dashboard id
|
|
1002
|
+
* read `user.email`, `db.statement`, `http.url`, ... out of telemetry the
|
|
1003
|
+
* dashboard never renders (GHSA-w332-x78m-vf3v).
|
|
997
1004
|
*/
|
|
998
1005
|
this.router.post(
|
|
999
1006
|
`${new this.entityType()
|
|
@@ -1021,10 +1028,11 @@ export default class DashboardAPI extends BaseAPI<
|
|
|
1021
1028
|
);
|
|
1022
1029
|
}
|
|
1023
1030
|
|
|
1024
|
-
const attributeKey:
|
|
1025
|
-
|
|
1031
|
+
const attributeKey: unknown = req.body
|
|
1032
|
+
? req.body["attributeKey"]
|
|
1033
|
+
: undefined;
|
|
1026
1034
|
|
|
1027
|
-
if (
|
|
1035
|
+
if (typeof attributeKey !== "string" || !attributeKey.trim()) {
|
|
1028
1036
|
throw new BadDataException("attributeKey is required.");
|
|
1029
1037
|
}
|
|
1030
1038
|
|
|
@@ -1048,6 +1056,7 @@ export default class DashboardAPI extends BaseAPI<
|
|
|
1048
1056
|
select: {
|
|
1049
1057
|
_id: true,
|
|
1050
1058
|
projectId: true,
|
|
1059
|
+
dashboardViewConfig: true,
|
|
1051
1060
|
},
|
|
1052
1061
|
props: {
|
|
1053
1062
|
isRoot: true,
|
|
@@ -1058,11 +1067,32 @@ export default class DashboardAPI extends BaseAPI<
|
|
|
1058
1067
|
throw new NotFoundException("Dashboard not found");
|
|
1059
1068
|
}
|
|
1060
1069
|
|
|
1070
|
+
/*
|
|
1071
|
+
* Only the attribute keys this dashboard's own variable dropdowns
|
|
1072
|
+
* offer may be read. Variable interpolation only ever substitutes
|
|
1073
|
+
* a variable's VALUE into a widget filter — never its key — so the
|
|
1074
|
+
* stored view config is an exact allowlist. A dashboard with no
|
|
1075
|
+
* telemetry-attribute variables has nothing to look up and is
|
|
1076
|
+
* refused outright.
|
|
1077
|
+
*/
|
|
1078
|
+
const requestedAttributeKey: string = attributeKey.trim();
|
|
1079
|
+
|
|
1080
|
+
const allowedAttributeKeys: Set<string> =
|
|
1081
|
+
DashboardAPI.collectDashboardVariableAttributeKeys(
|
|
1082
|
+
dashboard.dashboardViewConfig,
|
|
1083
|
+
);
|
|
1084
|
+
|
|
1085
|
+
if (!allowedAttributeKeys.has(requestedAttributeKey)) {
|
|
1086
|
+
throw new BadDataException(
|
|
1087
|
+
"This attribute is not part of this dashboard.",
|
|
1088
|
+
);
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1061
1091
|
const values: Array<string> =
|
|
1062
1092
|
await TelemetryAttributeService.fetchAttributeValues({
|
|
1063
1093
|
projectId: dashboard.projectId,
|
|
1064
1094
|
telemetryType,
|
|
1065
|
-
attributeKey:
|
|
1095
|
+
attributeKey: requestedAttributeKey,
|
|
1066
1096
|
});
|
|
1067
1097
|
|
|
1068
1098
|
return Response.sendJsonObjectResponse(req, res, {
|
|
@@ -1265,9 +1295,25 @@ export default class DashboardAPI extends BaseAPI<
|
|
|
1265
1295
|
DashboardAPI.collectDashboardMetricNames(
|
|
1266
1296
|
dashboard.dashboardViewConfig,
|
|
1267
1297
|
);
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1298
|
+
|
|
1299
|
+
/*
|
|
1300
|
+
* Read the query through an OWN-properties copy. JSON.parse turns a
|
|
1301
|
+
* literal "__proto__" member into a real own key and
|
|
1302
|
+
* JSONFunctions.deserialize copies it with `newVal[key] = ...`,
|
|
1303
|
+
* which fires Object.prototype's __proto__ setter — so a plain
|
|
1304
|
+
* `query["name"]` lookup walks the prototype chain and sees a name
|
|
1305
|
+
* that a later own-properties spread would silently drop, leaving
|
|
1306
|
+
* the aggregation with no metric predicate at all. The check and
|
|
1307
|
+
* the object that reaches the database must read the same keys.
|
|
1308
|
+
*/
|
|
1309
|
+
const requestedQuery: Record<string, unknown> =
|
|
1310
|
+
aggregateBy.query &&
|
|
1311
|
+
typeof aggregateBy.query === "object" &&
|
|
1312
|
+
!Array.isArray(aggregateBy.query)
|
|
1313
|
+
? { ...(aggregateBy.query as Record<string, unknown>) }
|
|
1314
|
+
: {};
|
|
1315
|
+
|
|
1316
|
+
const requestedMetricName: unknown = requestedQuery["name"];
|
|
1271
1317
|
|
|
1272
1318
|
if (
|
|
1273
1319
|
typeof requestedMetricName !== "string" ||
|
|
@@ -1279,14 +1325,156 @@ export default class DashboardAPI extends BaseAPI<
|
|
|
1279
1325
|
}
|
|
1280
1326
|
|
|
1281
1327
|
/*
|
|
1282
|
-
*
|
|
1283
|
-
*
|
|
1284
|
-
*
|
|
1328
|
+
* Pinning the metric name is not enough on its own: a grouped
|
|
1329
|
+
* aggregation echoes each group's key back in the result rows, so
|
|
1330
|
+
* `groupByAttributeKeys: ["enduser.id"]` — or the blunter
|
|
1331
|
+
* `groupBy: { attributes: true }`, which returns the WHOLE
|
|
1332
|
+
* attribute map — turns an allowlisted metric into a reader for
|
|
1333
|
+
* attribute values the widget never renders. Both grouping
|
|
1334
|
+
* dimensions are therefore allowlisted against the stored view
|
|
1335
|
+
* config as well; interpolation never rewrites either of them.
|
|
1336
|
+
*/
|
|
1337
|
+
const allowedGroupByAttributeKeys: Set<string> =
|
|
1338
|
+
DashboardAPI.collectDashboardGroupByAttributeKeys(
|
|
1339
|
+
dashboard.dashboardViewConfig,
|
|
1340
|
+
);
|
|
1341
|
+
const requestedGroupByAttributeKeys: unknown =
|
|
1342
|
+
aggregateBy.groupByAttributeKeys;
|
|
1343
|
+
|
|
1344
|
+
/*
|
|
1345
|
+
* `null` means "not grouped" here: JSONFunctions.serialize drops
|
|
1346
|
+
* undefined but preserves null, and both downstream sinks already
|
|
1347
|
+
* treat a null grouping as absent.
|
|
1348
|
+
*/
|
|
1349
|
+
if (
|
|
1350
|
+
requestedGroupByAttributeKeys !== undefined &&
|
|
1351
|
+
requestedGroupByAttributeKeys !== null
|
|
1352
|
+
) {
|
|
1353
|
+
if (!Array.isArray(requestedGroupByAttributeKeys)) {
|
|
1354
|
+
throw new BadDataException(
|
|
1355
|
+
"groupByAttributeKeys must be an array of attribute keys.",
|
|
1356
|
+
);
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
for (const requestedKey of requestedGroupByAttributeKeys) {
|
|
1360
|
+
if (
|
|
1361
|
+
typeof requestedKey !== "string" ||
|
|
1362
|
+
!allowedGroupByAttributeKeys.has(requestedKey)
|
|
1363
|
+
) {
|
|
1364
|
+
throw new BadDataException(
|
|
1365
|
+
"This attribute is not part of this dashboard.",
|
|
1366
|
+
);
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
const allowedGroupByColumns: Set<string> =
|
|
1372
|
+
DashboardAPI.collectDashboardGroupByColumns(
|
|
1373
|
+
dashboard.dashboardViewConfig,
|
|
1374
|
+
);
|
|
1375
|
+
const requestedGroupBy: unknown = aggregateBy.groupBy;
|
|
1376
|
+
|
|
1377
|
+
if (requestedGroupBy !== undefined && requestedGroupBy !== null) {
|
|
1378
|
+
if (
|
|
1379
|
+
typeof requestedGroupBy !== "object" ||
|
|
1380
|
+
Array.isArray(requestedGroupBy)
|
|
1381
|
+
) {
|
|
1382
|
+
throw new BadDataException("groupBy must be an object.");
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
for (const requestedColumn of Object.keys(requestedGroupBy)) {
|
|
1386
|
+
if (!allowedGroupByColumns.has(requestedColumn)) {
|
|
1387
|
+
throw new BadDataException(
|
|
1388
|
+
"This grouping is not part of this dashboard.",
|
|
1389
|
+
);
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
/*
|
|
1394
|
+
* Hand the SQL builder the same keys this guard validated. The
|
|
1395
|
+
* guard reads Object.keys but the GROUP BY builder walks the
|
|
1396
|
+
* object with for...in, so an inherited key would otherwise
|
|
1397
|
+
* reach the query without ever being checked.
|
|
1398
|
+
*/
|
|
1399
|
+
aggregateBy.groupBy = {
|
|
1400
|
+
...(requestedGroupBy as Record<string, unknown>),
|
|
1401
|
+
} as typeof aggregateBy.groupBy;
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
/*
|
|
1405
|
+
* The client never chooses what is aggregated over what: every
|
|
1406
|
+
* widget aggregates `value` over `time`. Left open, an anonymous
|
|
1407
|
+
* caller could aggregate `attributes` instead — `max(attributes)`
|
|
1408
|
+
* returns the whole map and the row mapper passes non-numeric
|
|
1409
|
+
* aggregates through untouched, handing back a full attribute map
|
|
1410
|
+
* per time bucket.
|
|
1411
|
+
*/
|
|
1412
|
+
if (aggregateBy.aggregateColumnName !== "value") {
|
|
1413
|
+
throw new BadDataException("Invalid aggregateColumnName.");
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
if (aggregateBy.aggregationTimestampColumnName !== "time") {
|
|
1417
|
+
throw new BadDataException(
|
|
1418
|
+
"Invalid aggregationTimestampColumnName.",
|
|
1419
|
+
);
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
// Never let an anonymous caller choose an unbounded page.
|
|
1423
|
+
aggregateBy.limit = Math.min(
|
|
1424
|
+
Math.max(Number(aggregateBy.limit) || LIMIT_PER_PROJECT, 1),
|
|
1425
|
+
LIMIT_PER_PROJECT,
|
|
1426
|
+
);
|
|
1427
|
+
aggregateBy.skip = Math.max(Number(aggregateBy.skip) || 0, 0);
|
|
1428
|
+
|
|
1429
|
+
/*
|
|
1430
|
+
* Security: the client does not get to choose what is filtered on a
|
|
1431
|
+
* public, unauthenticated endpoint. Rebuild the query from the
|
|
1432
|
+
* fields the dashboard's own widgets legitimately send — the
|
|
1433
|
+
* allowlisted metric name, the time window, and attribute filters
|
|
1434
|
+
* on keys those widgets already filter by — and pin the project.
|
|
1435
|
+
* Everything else the client sent is dropped rather than merged: a
|
|
1436
|
+
* foreign projectId, a filter on an arbitrary attribute key used as
|
|
1437
|
+
* a blind ILIKE oracle, a key smuggled in on the prototype
|
|
1438
|
+
* (GHSA-w332-x78m-vf3v).
|
|
1285
1439
|
*/
|
|
1440
|
+
const allowedFilterAttributeKeys: Set<string> =
|
|
1441
|
+
DashboardAPI.collectDashboardFilterAttributeKeys(
|
|
1442
|
+
dashboard.dashboardViewConfig,
|
|
1443
|
+
);
|
|
1444
|
+
|
|
1445
|
+
const sanitizedAttributes: Record<string, unknown> = {};
|
|
1446
|
+
const requestedAttributes: unknown = requestedQuery["attributes"];
|
|
1447
|
+
|
|
1448
|
+
if (
|
|
1449
|
+
requestedAttributes &&
|
|
1450
|
+
typeof requestedAttributes === "object" &&
|
|
1451
|
+
!Array.isArray(requestedAttributes)
|
|
1452
|
+
) {
|
|
1453
|
+
for (const requestedAttributeKey of Object.keys(
|
|
1454
|
+
requestedAttributes as Record<string, unknown>,
|
|
1455
|
+
)) {
|
|
1456
|
+
if (!allowedFilterAttributeKeys.has(requestedAttributeKey)) {
|
|
1457
|
+
throw new BadDataException(
|
|
1458
|
+
"This attribute is not part of this dashboard.",
|
|
1459
|
+
);
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
sanitizedAttributes[requestedAttributeKey] = (
|
|
1463
|
+
requestedAttributes as Record<string, unknown>
|
|
1464
|
+
)[requestedAttributeKey];
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1286
1468
|
aggregateBy.query = {
|
|
1287
|
-
|
|
1469
|
+
name: requestedMetricName,
|
|
1470
|
+
...(requestedQuery["time"] !== undefined
|
|
1471
|
+
? { time: requestedQuery["time"] }
|
|
1472
|
+
: {}),
|
|
1473
|
+
...(Object.keys(sanitizedAttributes).length > 0
|
|
1474
|
+
? { attributes: sanitizedAttributes }
|
|
1475
|
+
: {}),
|
|
1288
1476
|
projectId: dashboard.projectId,
|
|
1289
|
-
};
|
|
1477
|
+
} as unknown as typeof aggregateBy.query;
|
|
1290
1478
|
|
|
1291
1479
|
const aggregateResult: AggregatedResult =
|
|
1292
1480
|
await MetricService.aggregateBy(aggregateBy);
|
|
@@ -1351,10 +1539,9 @@ export default class DashboardAPI extends BaseAPI<
|
|
|
1351
1539
|
req.params["dashboardId"] as string,
|
|
1352
1540
|
);
|
|
1353
1541
|
|
|
1354
|
-
const password:
|
|
1355
|
-
req.body && (req.body["password"] as string);
|
|
1542
|
+
const password: unknown = req.body && req.body["password"];
|
|
1356
1543
|
|
|
1357
|
-
if (!password) {
|
|
1544
|
+
if (typeof password !== "string" || !password) {
|
|
1358
1545
|
throw new BadDataException("Master password is required.");
|
|
1359
1546
|
}
|
|
1360
1547
|
|
|
@@ -1366,6 +1553,7 @@ export default class DashboardAPI extends BaseAPI<
|
|
|
1366
1553
|
projectId: true,
|
|
1367
1554
|
enableMasterPassword: true,
|
|
1368
1555
|
masterPassword: true,
|
|
1556
|
+
masterPasswordSalt: true,
|
|
1369
1557
|
isPublicDashboard: true,
|
|
1370
1558
|
},
|
|
1371
1559
|
props: {
|
|
@@ -1389,12 +1577,14 @@ export default class DashboardAPI extends BaseAPI<
|
|
|
1389
1577
|
);
|
|
1390
1578
|
}
|
|
1391
1579
|
|
|
1392
|
-
const
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1580
|
+
const isMasterPasswordValid: boolean =
|
|
1581
|
+
await DashboardService.verifyHashedColumnValue({
|
|
1582
|
+
item: dashboard,
|
|
1583
|
+
columnName: "masterPassword",
|
|
1584
|
+
plainValue: password,
|
|
1585
|
+
});
|
|
1396
1586
|
|
|
1397
|
-
if (
|
|
1587
|
+
if (!isMasterPasswordValid) {
|
|
1398
1588
|
throw new BadDataException(
|
|
1399
1589
|
DASHBOARD_MASTER_PASSWORD_INVALID_MESSAGE,
|
|
1400
1590
|
);
|
|
@@ -1518,6 +1708,223 @@ export default class DashboardAPI extends BaseAPI<
|
|
|
1518
1708
|
return metricNames;
|
|
1519
1709
|
}
|
|
1520
1710
|
|
|
1711
|
+
/*
|
|
1712
|
+
* Walk a stored dashboard view config and collect every OpenTelemetry
|
|
1713
|
+
* attribute key its variables bind to (a `Telemetry Attribute` variable
|
|
1714
|
+
* carries the key its dropdown lists values for). Used as the allowlist
|
|
1715
|
+
* for the public attribute-values endpoint, so an anonymous viewer can
|
|
1716
|
+
* only read the values behind this dashboard's own variable pickers and
|
|
1717
|
+
* not every attribute in the owning project.
|
|
1718
|
+
*/
|
|
1719
|
+
private static collectDashboardVariableAttributeKeys(
|
|
1720
|
+
dashboardViewConfig: unknown,
|
|
1721
|
+
): Set<string> {
|
|
1722
|
+
const attributeKeys: Set<string> = new Set<string>();
|
|
1723
|
+
|
|
1724
|
+
const walk: (node: unknown) => void = (node: unknown): void => {
|
|
1725
|
+
if (!node || typeof node !== "object") {
|
|
1726
|
+
return;
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
if (Array.isArray(node)) {
|
|
1730
|
+
for (const item of node) {
|
|
1731
|
+
walk(item);
|
|
1732
|
+
}
|
|
1733
|
+
return;
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
const obj: Record<string, unknown> = node as Record<string, unknown>;
|
|
1737
|
+
|
|
1738
|
+
if (obj["type"] === DashboardVariableType.TelemetryAttribute) {
|
|
1739
|
+
const attributeKey: unknown = obj["attributeKey"];
|
|
1740
|
+
|
|
1741
|
+
if (
|
|
1742
|
+
typeof attributeKey === "string" &&
|
|
1743
|
+
attributeKey.trim().length > 0
|
|
1744
|
+
) {
|
|
1745
|
+
attributeKeys.add(attributeKey.trim());
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
for (const key of Object.keys(obj)) {
|
|
1750
|
+
walk(obj[key]);
|
|
1751
|
+
}
|
|
1752
|
+
};
|
|
1753
|
+
|
|
1754
|
+
walk(dashboardViewConfig);
|
|
1755
|
+
|
|
1756
|
+
return attributeKeys;
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
/*
|
|
1760
|
+
* Walk a stored dashboard view config and collect every OpenTelemetry
|
|
1761
|
+
* attribute key its metric widgets group by — `groupByAttributeKeys`
|
|
1762
|
+
* (chart / value / gauge / legacy table queries) and `groupByAttributes`
|
|
1763
|
+
* (the table widget's richer per-key form). Used as the allowlist for the
|
|
1764
|
+
* public metric-aggregate endpoint, whose grouped results echo each
|
|
1765
|
+
* group's key values back to the caller.
|
|
1766
|
+
*/
|
|
1767
|
+
private static collectDashboardGroupByAttributeKeys(
|
|
1768
|
+
dashboardViewConfig: unknown,
|
|
1769
|
+
): Set<string> {
|
|
1770
|
+
const attributeKeys: Set<string> = new Set<string>();
|
|
1771
|
+
|
|
1772
|
+
const addKey: (value: unknown) => void = (value: unknown): void => {
|
|
1773
|
+
if (typeof value === "string" && value.length > 0) {
|
|
1774
|
+
attributeKeys.add(value);
|
|
1775
|
+
}
|
|
1776
|
+
};
|
|
1777
|
+
|
|
1778
|
+
const walk: (node: unknown) => void = (node: unknown): void => {
|
|
1779
|
+
if (!node || typeof node !== "object") {
|
|
1780
|
+
return;
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
if (Array.isArray(node)) {
|
|
1784
|
+
for (const item of node) {
|
|
1785
|
+
walk(item);
|
|
1786
|
+
}
|
|
1787
|
+
return;
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
const obj: Record<string, unknown> = node as Record<string, unknown>;
|
|
1791
|
+
|
|
1792
|
+
const groupByAttributeKeys: unknown = obj["groupByAttributeKeys"];
|
|
1793
|
+
if (Array.isArray(groupByAttributeKeys)) {
|
|
1794
|
+
for (const key of groupByAttributeKeys) {
|
|
1795
|
+
addKey(key);
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
const groupByAttributes: unknown = obj["groupByAttributes"];
|
|
1800
|
+
if (Array.isArray(groupByAttributes)) {
|
|
1801
|
+
for (const groupByAttribute of groupByAttributes) {
|
|
1802
|
+
if (groupByAttribute && typeof groupByAttribute === "object") {
|
|
1803
|
+
addKey((groupByAttribute as Record<string, unknown>)["key"]);
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
for (const key of Object.keys(obj)) {
|
|
1809
|
+
walk(obj[key]);
|
|
1810
|
+
}
|
|
1811
|
+
};
|
|
1812
|
+
|
|
1813
|
+
walk(dashboardViewConfig);
|
|
1814
|
+
|
|
1815
|
+
return attributeKeys;
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
/*
|
|
1819
|
+
* Attribute keys a public metric aggregation may FILTER on.
|
|
1820
|
+
*
|
|
1821
|
+
* Two sources, and both are needed:
|
|
1822
|
+
*
|
|
1823
|
+
* - Keys the widgets themselves persist — `filterData.attributes` on a
|
|
1824
|
+
* chart/value/gauge query, and the table widget's widget-level
|
|
1825
|
+
* `attributeFilters`.
|
|
1826
|
+
* - Keys the dashboard's `Telemetry Attribute` variables bind to. The
|
|
1827
|
+
* shipped templates store `filterData: { metricName, aggegationType }`
|
|
1828
|
+
* and no attributes at all; the filter on e.g.
|
|
1829
|
+
* `resource.k8s.cluster.name` only appears once the viewer picks a value
|
|
1830
|
+
* and DashboardVariableInterpolation injects it at render time. An
|
|
1831
|
+
* allowlist built from stored filters alone would refuse every real
|
|
1832
|
+
* templated dashboard the moment its variable is used.
|
|
1833
|
+
*/
|
|
1834
|
+
private static collectDashboardFilterAttributeKeys(
|
|
1835
|
+
dashboardViewConfig: unknown,
|
|
1836
|
+
): Set<string> {
|
|
1837
|
+
const attributeKeys: Set<string> =
|
|
1838
|
+
DashboardAPI.collectDashboardVariableAttributeKeys(dashboardViewConfig);
|
|
1839
|
+
|
|
1840
|
+
const addKeysOf: (value: unknown) => void = (value: unknown): void => {
|
|
1841
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
for (const key of Object.keys(value as Record<string, unknown>)) {
|
|
1846
|
+
if (key.length > 0) {
|
|
1847
|
+
attributeKeys.add(key);
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
};
|
|
1851
|
+
|
|
1852
|
+
const walk: (node: unknown) => void = (node: unknown): void => {
|
|
1853
|
+
if (!node || typeof node !== "object") {
|
|
1854
|
+
return;
|
|
1855
|
+
}
|
|
1856
|
+
|
|
1857
|
+
if (Array.isArray(node)) {
|
|
1858
|
+
for (const item of node) {
|
|
1859
|
+
walk(item);
|
|
1860
|
+
}
|
|
1861
|
+
return;
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
const obj: Record<string, unknown> = node as Record<string, unknown>;
|
|
1865
|
+
|
|
1866
|
+
const filterData: unknown = obj["filterData"];
|
|
1867
|
+
if (filterData && typeof filterData === "object") {
|
|
1868
|
+
addKeysOf((filterData as Record<string, unknown>)["attributes"]);
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
addKeysOf(obj["attributeFilters"]);
|
|
1872
|
+
|
|
1873
|
+
for (const key of Object.keys(obj)) {
|
|
1874
|
+
walk(obj[key]);
|
|
1875
|
+
}
|
|
1876
|
+
};
|
|
1877
|
+
|
|
1878
|
+
walk(dashboardViewConfig);
|
|
1879
|
+
|
|
1880
|
+
return attributeKeys;
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
/*
|
|
1884
|
+
* Walk a stored dashboard view config and collect every model column its
|
|
1885
|
+
* widgets group by. Used as the allowlist for the public metric-aggregate
|
|
1886
|
+
* endpoint: grouping echoes the grouped column back in every result row,
|
|
1887
|
+
* so `groupBy: { attributes: true }` would hand an anonymous viewer the
|
|
1888
|
+
* entire attribute map of an allowlisted metric.
|
|
1889
|
+
*/
|
|
1890
|
+
private static collectDashboardGroupByColumns(
|
|
1891
|
+
dashboardViewConfig: unknown,
|
|
1892
|
+
): Set<string> {
|
|
1893
|
+
const groupByColumns: Set<string> = new Set<string>();
|
|
1894
|
+
|
|
1895
|
+
const walk: (node: unknown) => void = (node: unknown): void => {
|
|
1896
|
+
if (!node || typeof node !== "object") {
|
|
1897
|
+
return;
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
if (Array.isArray(node)) {
|
|
1901
|
+
for (const item of node) {
|
|
1902
|
+
walk(item);
|
|
1903
|
+
}
|
|
1904
|
+
return;
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
const obj: Record<string, unknown> = node as Record<string, unknown>;
|
|
1908
|
+
|
|
1909
|
+
const groupBy: unknown = obj["groupBy"];
|
|
1910
|
+
if (groupBy && typeof groupBy === "object" && !Array.isArray(groupBy)) {
|
|
1911
|
+
for (const column of Object.keys(groupBy as Record<string, unknown>)) {
|
|
1912
|
+
if ((groupBy as Record<string, unknown>)[column]) {
|
|
1913
|
+
groupByColumns.add(column);
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
for (const key of Object.keys(obj)) {
|
|
1919
|
+
walk(obj[key]);
|
|
1920
|
+
}
|
|
1921
|
+
};
|
|
1922
|
+
|
|
1923
|
+
walk(dashboardViewConfig);
|
|
1924
|
+
|
|
1925
|
+
return groupByColumns;
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1521
1928
|
/*
|
|
1522
1929
|
* Walk a stored dashboard view config and collect every widget type it
|
|
1523
1930
|
* renders. Used to build an allowlist for the public resource-list
|