@oneuptime/common 14.0.3 → 14.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/Alert.ts +55 -0
- package/Models/DatabaseModels/DatabaseServer.ts +1650 -0
- package/Models/DatabaseModels/DatabaseServerEndpoint.ts +540 -0
- package/Models/DatabaseModels/DatabaseServerFeed.ts +625 -0
- package/Models/DatabaseModels/DatabaseServerLabelRule.ts +514 -0
- package/Models/DatabaseModels/DatabaseServerOwnerRule.ts +596 -0
- package/Models/DatabaseModels/DatabaseServerOwnerTeam.ts +491 -0
- package/Models/DatabaseModels/DatabaseServerOwnerUser.ts +490 -0
- package/Models/DatabaseModels/Incident.ts +55 -0
- package/Models/DatabaseModels/Index.ts +16 -0
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +26 -0
- package/Models/DatabaseModels/ScheduledMaintenance.ts +55 -0
- package/Models/DatabaseModels/TelemetryException.ts +2 -0
- package/Models/DatabaseModels/UserProjectSsoConsent.ts +146 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.ts +673 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.ts +51 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Middleware/MultipartFormData.ts +1 -1
- package/Server/Middleware/TelemetryIngest.ts +15 -8
- package/Server/Services/AlertReminderRuleService.ts +100 -24
- package/Server/Services/DatabaseServerEndpointService.ts +895 -0
- package/Server/Services/DatabaseServerFeedService.ts +128 -0
- package/Server/Services/DatabaseServerLabelRuleEngineService.ts +340 -0
- package/Server/Services/DatabaseServerLabelRuleService.ts +14 -0
- package/Server/Services/DatabaseServerOwnerRuleEngineService.ts +425 -0
- package/Server/Services/DatabaseServerOwnerRuleService.ts +14 -0
- package/Server/Services/DatabaseServerOwnerTeamService.ts +180 -0
- package/Server/Services/DatabaseServerOwnerUserService.ts +173 -0
- package/Server/Services/DatabaseServerService.ts +4546 -0
- package/Server/Services/DatabaseService.ts +14 -8
- package/Server/Services/DockerResourceService.ts +43 -2
- package/Server/Services/IncidentReminderRuleService.ts +103 -23
- package/Server/Services/Index.ts +16 -0
- package/Server/Services/InventoryItemService.ts +113 -5
- package/Server/Services/IoTDeviceService.ts +145 -37
- package/Server/Services/OpenTelemetryIngestService.ts +19 -0
- package/Server/Services/PodmanResourceService.ts +43 -2
- package/Server/Services/ScheduledMaintenanceReminderRuleService.ts +107 -23
- package/Server/Services/ServiceService.ts +1 -1
- package/Server/Services/TelemetryUsageBillingService.ts +29 -2
- package/Server/Services/UserProjectSsoConsentService.ts +74 -0
- package/Server/Services/UserService.ts +14 -1
- package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +18 -0
- package/Server/Types/Database/QueryHelper.ts +30 -1
- package/Server/Utils/AI/Toolbox/ResourceTools.ts +69 -1
- package/Server/Utils/Database/AffectedResourceRelations.ts +6 -0
- package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +188 -6
- package/Server/Utils/Monitor/MonitorAlert.ts +28 -1
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +2262 -755
- package/Server/Utils/Monitor/MonitorIncident.ts +28 -1
- package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +268 -6
- package/Server/Utils/Monitor/MonitorResource.ts +47 -11
- package/Server/Utils/Monitor/MonitorResourceContext.ts +1 -0
- package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +239 -21
- package/Server/Utils/Monitor/PerSeriesResolutionRootCause.ts +43 -0
- package/Server/Utils/Monitor/SeriesResourceLabels.ts +291 -0
- package/Server/Utils/Monitor/SeriesResourceLinker.ts +111 -12
- package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +25 -0
- package/Server/Utils/StartServer.ts +26 -6
- package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +2 -0
- package/Server/Utils/Telemetry/DatabaseEndpointDiscovery.ts +688 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +5 -1
- package/Server/Utils/Telemetry/LogExceptionExtractor.ts +18 -1
- package/Server/Utils/Telemetry/ResourceEntityFilter.ts +175 -12
- package/Server/Utils/Telemetry/ResourceFacetResolver.ts +12 -0
- package/Server/Utils/Telemetry/ServiceDependencyDiscovery.ts +606 -36
- package/Server/Utils/Telemetry/Telemetry.ts +16 -0
- package/Server/Utils/Telemetry/TelemetryEntity.ts +22 -22
- package/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.ts +16 -10
- package/Tests/App/Accounts/SignedInRedirect.test.tsx +241 -0
- package/Tests/App/AdminDashboard/AdminHeaderSmallScreens.test.tsx +221 -4
- package/Tests/App/Dashboard/AIInsightsResourcePageContext.test.ts +42 -0
- package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +100 -0
- package/Tests/App/Dashboard/AffectedResourcesPicker.test.tsx +86 -0
- package/Tests/App/Dashboard/AffectedResourcesPickerHiddenTypes.test.tsx +2 -0
- package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +19 -0
- package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +14 -0
- package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +26 -1
- package/Tests/App/Dashboard/DashboardAppSsoError.test.tsx +501 -0
- package/Tests/App/Dashboard/DashboardHeaderRequests.test.tsx +64 -1
- package/Tests/App/Dashboard/DashboardHeaderSmallScreens.test.tsx +178 -18
- package/Tests/App/Dashboard/DashboardMasterPageSsoRedirect.test.tsx +444 -0
- package/Tests/App/Dashboard/DashboardNavBarForeignHiddenRule.test.tsx +573 -0
- package/Tests/App/Dashboard/DatabaseChartAxes.test.tsx +431 -0
- package/Tests/App/Dashboard/DatabaseContainerDetailBadge.test.tsx +249 -0
- package/Tests/App/Dashboard/DatabaseDashboardE2EFixes.test.ts +681 -0
- package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +1801 -0
- package/Tests/App/Dashboard/DatabaseFleetSummaryRefresh.test.tsx +280 -0
- package/Tests/App/Dashboard/DatabaseFormHelpers.test.tsx +321 -0
- package/Tests/App/Dashboard/DatabaseMetricMonitorLink.test.tsx +795 -0
- package/Tests/App/Dashboard/DatabaseOverviewHeader.test.tsx +580 -0
- package/Tests/App/Dashboard/DatabaseRecommendationsEngineMetrics.test.ts +270 -0
- package/Tests/App/Dashboard/DatabaseServerComponents.test.tsx +1486 -0
- package/Tests/App/Dashboard/DatabaseServerEngineMetricsFilter.test.ts +223 -0
- package/Tests/App/Dashboard/DatabaseServerPresentation.test.ts +435 -0
- package/Tests/App/Dashboard/DatabaseServerSummary.test.ts +186 -0
- package/Tests/App/Dashboard/DatabaseServerTelemetryQueries.test.ts +1553 -0
- package/Tests/App/Dashboard/DatabaseTableTruncation.test.tsx +326 -0
- package/Tests/App/Dashboard/DatabaseTelemetryScope.test.ts +512 -0
- package/Tests/App/Dashboard/DatabaseTelemetryTabs.test.tsx +774 -0
- package/Tests/App/Dashboard/DatabaseViewLayout.test.tsx +233 -0
- package/Tests/App/Dashboard/DatabaseWorkloadBadge.test.tsx +972 -0
- package/Tests/App/Dashboard/DiscoveryReviewInventoryRefresh.test.tsx +5 -0
- package/Tests/App/Dashboard/DiscoveryReviewUnnamedHostHint.test.tsx +1061 -0
- package/Tests/App/Dashboard/EventOverlayScope.test.ts +147 -0
- package/Tests/App/Dashboard/EventOverlayScopeHook.test.tsx +1 -0
- package/Tests/App/Dashboard/LogsResourceFacetChips.test.tsx +1 -0
- package/Tests/App/Dashboard/MetricsViewerDrillDown.test.tsx +310 -0
- package/Tests/App/Dashboard/MetricsViewerEntityScopedRows.test.tsx +495 -0
- package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +132 -1
- package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +5 -0
- package/Tests/App/Dashboard/ProductOrientation.test.tsx +4 -3
- package/Tests/App/Dashboard/RecommendationsLoadedContext.test.tsx +349 -0
- package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +62 -0
- package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +8 -1
- package/Tests/App/Dashboard/ResourceFeedPagesFilterSort.test.tsx +14 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +2 -0
- package/Tests/App/Dashboard/ServiceMapDatabaseLink.test.tsx +1085 -0
- package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +10 -0
- package/Tests/App/Dashboard/TracesResourceFacets.test.tsx +2 -1
- package/Tests/App/StatusPage/StatusPageHeaderForeignHiddenRule.test.tsx +284 -0
- package/Tests/ClassStrings.ts +178 -0
- package/Tests/Fixtures/MobilePasskeyUser.json +1 -2
- package/Tests/ForeignHiddenRuleGuard.ts +2152 -0
- package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +2250 -0
- package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +24 -5
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
- package/Tests/RenderedMarkup.ts +518 -0
- package/Tests/ResponsiveVisibility.test.ts +490 -4
- package/Tests/ResponsiveVisibility.ts +505 -52
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
- package/Tests/Server/Infrastructure/Postgres/AddDatabaseServerTablesMigration.test.ts +541 -0
- package/Tests/Server/Infrastructure/Postgres/AddUserProjectSsoConsentMigration.test.ts +234 -0
- package/Tests/Server/Services/ContainerSnapshotUpsertPostgres.test.ts +319 -0
- package/Tests/Server/Services/CrossProjectRelationWriteGuard.test.ts +13 -0
- package/Tests/Server/Services/DatabaseServerEndpointService.test.ts +2033 -0
- package/Tests/Server/Services/DatabaseServerFeedAndOwnerServices.test.ts +529 -0
- package/Tests/Server/Services/DatabaseServerLifecycle.test.ts +3302 -0
- package/Tests/Server/Services/DatabaseServerRegistries.test.ts +603 -0
- package/Tests/Server/Services/DatabaseServerRuleEngines.test.ts +754 -0
- package/Tests/Server/Services/DatabaseServerService.test.ts +3558 -0
- package/Tests/Server/Services/DatabaseServerSqlPostgres.test.ts +2045 -0
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlockedPostgres.test.ts +362 -0
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlockedReply.test.ts +210 -0
- package/Tests/Server/Services/HookFreeWriteLengthClamp.test.ts +18 -0
- package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +2 -0
- package/Tests/Server/Services/IncomingCallPolicyEscalationRuleTarget.test.ts +225 -0
- package/Tests/Server/Services/InventoryItemDisplayName.test.ts +280 -2
- package/Tests/Server/Services/InventoryUpsertSchemaParity.test.ts +8 -2
- package/Tests/Server/Services/IoTDeviceLatestMetricsPostgres.test.ts +689 -0
- package/Tests/Server/Services/IoTDeviceService.test.ts +379 -0
- package/Tests/Server/Services/LatestMetricsValuesShape.test.ts +360 -0
- package/Tests/Server/Services/LlmModelPriceService.test.ts +402 -0
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +7 -1
- package/Tests/Server/Services/OwnerRowUniqueness.test.ts +61 -9
- package/Tests/Server/Services/ReminderRuleLookupPostgres.test.ts +2250 -0
- package/Tests/Server/Services/ReminderRuleRefreshOpenSubjectsPaging.test.ts +653 -0
- package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +68 -20
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +3 -3
- package/Tests/Server/Services/TelemetryResourceFacetCounting.test.ts +9 -0
- package/Tests/Server/Services/UserProjectSsoConsentPostgres.test.ts +153 -0
- package/Tests/Server/Services/UserProjectSsoConsentService.test.ts +192 -0
- package/Tests/Server/Services/UserServiceFirstMasterAdminElection.test.ts +71 -0
- package/Tests/Server/Services/UserSignupIdTakeoverPostgres.test.ts +238 -0
- package/Tests/Server/Services/WorkspaceNotificationSummaryHelpers.test.ts +592 -0
- package/Tests/Server/Types/Billing/PayAsYouGoMeteredAuthorization.test.ts +3 -0
- package/Tests/Server/Types/Database/EventOverlayScopePostgres.test.ts +1 -0
- package/Tests/Server/Types/Database/FeedEventTypeFilterQuery.test.ts +11 -0
- package/Tests/Server/Types/Database/Permissions/InfrastructureOwnershipScope.test.ts +8 -0
- package/Tests/Server/Types/Database/QueryHelperBooleanForCriteriaBackedRule.test.ts +1094 -0
- package/Tests/Server/Utils/AI/ResourceTools.test.ts +134 -0
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.ts +41 -0
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +279 -9
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaDisplayContext.test.ts +933 -0
- package/Tests/Server/Utils/Monitor/DatabaseMaintenanceSuppression.test.ts +582 -0
- package/Tests/Server/Utils/Monitor/DatabaseServerMonitorLinking.test.ts +753 -0
- package/Tests/Server/Utils/Monitor/MonitorActionTimestamps.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertCriteriaReferences.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +119 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +60 -25
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorAffectedResourceEdgeCases.test.ts +1719 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorKubernetesAffectedResources.test.ts +1447 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorKubernetesRatioEmail.test.ts +352 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformMetricUnits.test.ts +717 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformRawScan.test.ts +2125 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformSeriesAffectedResources.test.ts +1288 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorIncidentCriteriaReferences.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorIncidentMemberRoleMembership.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +88 -0
- package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +205 -0
- package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +62 -0
- package/Tests/Server/Utils/Monitor/MonitorResourceDatabaseMaintenance.test.ts +803 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +133 -3
- package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/PerSeriesRecoveryResolution.test.ts +472 -1
- package/Tests/Server/Utils/Monitor/PerSeriesSecondEntityAlerting.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +236 -2
- package/Tests/Server/Utils/SeriesResourceLabels.test.ts +70 -0
- package/Tests/Server/Utils/StartServerProtobufContentType.test.ts +54 -0
- package/Tests/Server/Utils/Telemetry/DatabaseEndpointDiscovery.test.ts +1895 -0
- package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +7 -0
- package/Tests/Server/Utils/Telemetry/LogExceptionExtractorSeverityGate.test.ts +90 -0
- package/Tests/Server/Utils/Telemetry/ResourceEntityFilter.test.ts +570 -0
- package/Tests/Server/Utils/Telemetry/ResourceFacetResolver.test.ts +97 -2
- package/Tests/Server/Utils/Telemetry/ServiceDependencyDiscovery.test.ts +1337 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +295 -0
- package/Tests/Types/AI/AIResourceContext.test.ts +30 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerClassifier.test.ts +3644 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerCommand.test.ts +340 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerCommandCorpus.ts +826 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerCommandPostgres.test.ts +150 -0
- package/Tests/Types/DatabaseServer/DatabaseEndpoint.test.ts +2657 -0
- package/Tests/Types/DatabaseServer/DatabaseServerDiscoverySource.test.ts +64 -0
- package/Tests/Types/DatabaseServer/DatabaseServerEntityKeys.test.ts +952 -0
- package/Tests/Types/DatabaseServer/DatabaseServerMetricCatalog.test.ts +1161 -0
- package/Tests/Types/DatabaseServer/DatabaseSystem.test.ts +1514 -0
- package/Tests/Types/DatabaseServer/DatabaseTelemetryResolver.test.ts +1558 -0
- package/Tests/Types/Monitor/CephAlertTemplates.test.ts +255 -6
- package/Tests/Types/Monitor/DatabaseAlertTemplates.test.ts +2254 -0
- package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +298 -0
- package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +271 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +253 -9
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +13 -5
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +4 -2
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +111 -2
- package/Tests/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.test.ts +61 -0
- package/Tests/Types/Monitor/SeriesContext/SeriesLabelDisplay.test.ts +114 -0
- package/Tests/Types/Monitor/Utils/KubernetesAgentEmittedMetrics.ts +181 -0
- package/Tests/Types/NetworkDevice/DiscoveredHostNamingStatus.test.ts +401 -0
- package/Tests/Types/Telemetry/ResourceEntityFacet.test.ts +4 -1
- package/Tests/Types/Telemetry/ResourceFacetCatalog.test.ts +24 -2
- package/Tests/UI/Components/Card.test.tsx +93 -2
- package/Tests/UI/Components/FeedOptions.test.ts +6 -0
- package/Tests/UI/Components/FeedOptionsButton.test.tsx +8 -1
- package/Tests/UI/Components/ForeignHiddenRuleResilience.test.tsx +1147 -0
- package/Tests/UI/Components/HeaderRightRail.test.tsx +41 -1
- package/Tests/UI/Components/LogsEntityNames.test.ts +16 -1
- package/Tests/UI/Components/LogsFacetSidebarHiddenFacets.test.tsx +7 -3
- package/Tests/UI/Components/ResourceFacetConfigs.test.ts +2 -1
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
- package/Tests/UI/Components/SrOnlyForeignRule.test.tsx +994 -0
- package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +34 -1
- package/Tests/UI/Components/TelemetryFacetSidebarHiddenFacets.test.tsx +4 -1
- package/Tests/UI/ForeignHiddenRuleGuard.test.ts +1951 -0
- package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +19 -1
- package/Tests/UI/Rum/ReplayTabSwitcher.test.tsx +19 -1
- package/Tests/UI/TailwindPlayCdnForeignHiddenRule.test.ts +1005 -0
- package/Tests/UI/ThemeGroupHoverReveal.test.ts +847 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +70 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +21 -0
- package/Tests/UI/Utils/ModelAPISsoRedirect.test.ts +127 -0
- package/Tests/UI/Utils/Navigation.test.ts +102 -0
- package/Tests/UI/Utils/Telemetry/TelemetryEntityNames.test.ts +23 -0
- package/Tests/Utils/LabelRuleImportExport.test.ts +5 -0
- package/Tests/Utils/MetricUnitUtil.test.ts +227 -2
- package/Tests/Utils/Monitor/MetricValueFormatter.test.ts +288 -2
- package/Tests/Utils/Monitor/PlatformResourceIdentityAndUnits.test.ts +1559 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.test.ts +2546 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +315 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +336 -1
- package/Tests/Utils/NetworkDiscovery/NetbiosNameUtil.test.ts +244 -0
- package/Tests/Utils/ValueFormatter.test.ts +50 -0
- package/Tests/tsconfig.json +16 -0
- package/Types/AI/AIResourceContext.ts +7 -0
- package/Types/Dashboard/DashboardTemplates.ts +2 -1
- package/Types/DatabaseServer/DatabaseConnectionSpan.ts +77 -0
- package/Types/DatabaseServer/DatabaseContainerClassifier.ts +2068 -0
- package/Types/DatabaseServer/DatabaseContainerCommand.ts +801 -0
- package/Types/DatabaseServer/DatabaseEndpoint.ts +1943 -0
- package/Types/DatabaseServer/DatabaseServerDiscoverySource.ts +68 -0
- package/Types/DatabaseServer/DatabaseServerMetricCatalog.ts +966 -0
- package/Types/DatabaseServer/DatabaseSystem.ts +2124 -0
- package/Types/DatabaseServer/DatabaseTelemetryResolver.ts +555 -0
- package/Types/Email/EmailTemplateType.ts +1 -0
- package/Types/Monitor/CephAlertTemplates.ts +18 -0
- package/Types/Monitor/DatabaseAlertTemplates.ts +2020 -0
- package/Types/Monitor/KubernetesAlertTemplates.ts +64 -24
- package/Types/Monitor/KubernetesMetricCatalog.ts +118 -19
- package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +14 -0
- package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +93 -10
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +109 -8
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +36 -7
- package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +43 -2
- package/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.ts +41 -6
- package/Types/Monitor/SeriesContext/SeriesLabelDisplay.ts +26 -0
- package/Types/NetworkDevice/DiscoveredHostNamingStatus.ts +147 -0
- package/Types/Permission.ts +267 -0
- package/Types/Probe/ProbeApiIngestResponse.ts +8 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +10 -0
- package/Types/Rules/RuleRun.ts +12 -0
- package/Types/Telemetry/EntityType.ts +23 -0
- package/Types/Telemetry/ResourceFacetCatalog.ts +14 -0
- package/Types/Telemetry/ServiceType.ts +8 -0
- package/UI/Components/Banner/Banner.tsx +1 -1
- package/UI/Components/Card/Card.tsx +1 -1
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +2 -2
- package/UI/Components/Charts/Line/LineChart.tsx +7 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +1 -1
- package/UI/Components/Date/StartAndEndDate.tsx +5 -5
- package/UI/Components/Diagram/HorizontalStepChain.tsx +1 -1
- package/UI/Components/Feed/FeedOptionsButton.tsx +1 -1
- package/UI/Components/Forms/BasicForm.tsx +1 -1
- package/UI/Components/Header/Header.tsx +1 -1
- package/UI/Components/Header/HeaderIconDropdownButton.tsx +1 -1
- package/UI/Components/HeaderAlert/HeaderAlert.tsx +1 -1
- package/UI/Components/LogsViewer/components/FacetValueRow.tsx +1 -1
- package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +1 -1
- package/UI/Components/Modal/ModalFooter.tsx +1 -1
- package/UI/Components/ModelDetail/CardModelDetail.tsx +2 -2
- package/UI/Components/ModelTable/BaseModelTable.tsx +4 -4
- package/UI/Components/Navbar/NavBar.tsx +9 -2
- package/UI/Components/Navbar/NavBarMenuModal.tsx +2 -2
- package/UI/Components/Page/Page.tsx +1 -1
- package/UI/Components/Pagination/Pagination.tsx +3 -3
- package/UI/Components/ProgressButtons/ProgressButtonItem.tsx +1 -1
- package/UI/Components/SideMenu/SideMenu.tsx +4 -1
- package/UI/Components/StatusPage/ResourceGroupNavigator.tsx +4 -2
- package/UI/Components/StatusPage/ResourceList.tsx +6 -6
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +1 -1
- package/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.tsx +1 -1
- package/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.tsx +1 -1
- package/UI/Components/Workflow/ComponentsModal.tsx +2 -2
- package/UI/Components/Workflow/StepTraceViewer.tsx +1 -1
- package/UI/Styles/Theme.css +8 -1
- package/UI/Utils/Navigation.ts +89 -42
- package/UI/Utils/Telemetry/TelemetryEntityNames.ts +7 -0
- package/UI/Utils/TelemetryService.ts +4 -3
- package/Utils/LabelRuleImportExport.ts +2 -0
- package/Utils/MetricUnitUtil.ts +103 -11
- package/Utils/Monitor/MetricValueFormatter.ts +66 -13
- package/Utils/Monitor/PlatformMetricUnitUtil.ts +215 -0
- package/Utils/Monitor/PlatformResourceIdentity.ts +514 -0
- package/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.ts +425 -0
- package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +32 -0
- package/Utils/NetworkDiscovery/NetbiosNameUtil.ts +73 -0
- package/Utils/Telemetry/DatabaseServerEntityKeys.ts +275 -0
- package/Utils/Telemetry/EntityKey.ts +176 -0
- package/Utils/ValueFormatter.ts +16 -0
- package/build/dist/Models/DatabaseModels/Alert.js +54 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseServer.js +1683 -0
- package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerEndpoint.js +559 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerEndpoint.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerLabelRule.js +522 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerRule.js +603 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerTeam.js +506 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerUser.js +505 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Incident.js +54 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +16 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +54 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryException.js +2 -0
- package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserProjectSsoConsent.js +162 -0
- package/build/dist/Models/DatabaseModels/UserProjectSsoConsent.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.js +240 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.js +26 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/MultipartFormData.js +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +15 -8
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AlertReminderRuleService.js +72 -23
- package/build/dist/Server/Services/AlertReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseServerEndpointService.js +694 -0
- package/build/dist/Server/Services/DatabaseServerEndpointService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerFeedService.js +110 -0
- package/build/dist/Server/Services/DatabaseServerFeedService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleEngineService.js +272 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleService.js +13 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleEngineService.js +340 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleService.js +13 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerTeamService.js +160 -0
- package/build/dist/Server/Services/DatabaseServerOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerUserService.js +153 -0
- package/build/dist/Server/Services/DatabaseServerOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerService.js +3272 -0
- package/build/dist/Server/Services/DatabaseServerService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseService.js +8 -4
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerResourceService.js +30 -3
- package/build/dist/Server/Services/DockerResourceService.js.map +1 -1
- package/build/dist/Server/Services/IncidentReminderRuleService.js +73 -23
- package/build/dist/Server/Services/IncidentReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +16 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/InventoryItemService.js +88 -5
- package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
- package/build/dist/Server/Services/IoTDeviceService.js +111 -24
- package/build/dist/Server/Services/IoTDeviceService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +24 -9
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/PodmanResourceService.js +30 -3
- package/build/dist/Server/Services/PodmanResourceService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js +75 -23
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServiceService.js +1 -1
- package/build/dist/Server/Services/ServiceService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +23 -2
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/UserProjectSsoConsentService.js +79 -0
- package/build/dist/Server/Services/UserProjectSsoConsentService.js.map +1 -0
- package/build/dist/Server/Services/UserService.js +13 -1
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +18 -0
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +26 -1
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js +46 -0
- package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js.map +1 -1
- package/build/dist/Server/Utils/Database/AffectedResourceRelations.js +6 -0
- package/build/dist/Server/Utils/Database/AffectedResourceRelations.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +134 -13
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +22 -6
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +1489 -524
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +22 -6
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +196 -6
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +36 -9
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +175 -17
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/PerSeriesResolutionRootCause.js +29 -0
- package/build/dist/Server/Utils/Monitor/PerSeriesResolutionRootCause.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +211 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +82 -10
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +25 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +20 -4
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +2 -0
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/DatabaseEndpointDiscovery.js +442 -0
- package/build/dist/Server/Utils/Telemetry/DatabaseEndpointDiscovery.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +5 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js +15 -1
- package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +121 -5
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js +12 -0
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js +438 -36
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/Telemetry.js +12 -0
- package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +17 -18
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js +16 -10
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js.map +1 -1
- package/build/dist/Types/AI/AIResourceContext.js +7 -0
- package/build/dist/Types/AI/AIResourceContext.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js +2 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/DatabaseServer/DatabaseConnectionSpan.js +71 -0
- package/build/dist/Types/DatabaseServer/DatabaseConnectionSpan.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerClassifier.js +1462 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerClassifier.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerCommand.js +691 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerCommand.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseEndpoint.js +1407 -0
- package/build/dist/Types/DatabaseServer/DatabaseEndpoint.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerDiscoverySource.js +60 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerDiscoverySource.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerMetricCatalog.js +804 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerMetricCatalog.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseSystem.js +1860 -0
- package/build/dist/Types/DatabaseServer/DatabaseSystem.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseTelemetryResolver.js +406 -0
- package/build/dist/Types/DatabaseServer/DatabaseTelemetryResolver.js.map +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Monitor/CephAlertTemplates.js +18 -0
- package/build/dist/Types/Monitor/CephAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/DatabaseAlertTemplates.js +1518 -0
- package/build/dist/Types/Monitor/DatabaseAlertTemplates.js.map +1 -0
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +57 -24
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/KubernetesMetricCatalog.js +104 -18
- package/build/dist/Types/Monitor/KubernetesMetricCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +80 -3
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +10 -3
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +29 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js +21 -6
- package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js.map +1 -1
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js +25 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js.map +1 -1
- package/build/dist/Types/NetworkDevice/DiscoveredHostNamingStatus.js +136 -0
- package/build/dist/Types/NetworkDevice/DiscoveredHostNamingStatus.js.map +1 -0
- package/build/dist/Types/Permission.js +234 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +10 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rules/RuleRun.js +4 -0
- package/build/dist/Types/Rules/RuleRun.js.map +1 -1
- package/build/dist/Types/Telemetry/EntityType.js +23 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js +14 -0
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js.map +1 -1
- package/build/dist/Types/Telemetry/ServiceType.js +8 -0
- package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
- package/build/dist/UI/Components/Banner/Banner.js +1 -1
- package/build/dist/UI/Components/Banner/Banner.js.map +1 -1
- package/build/dist/UI/Components/Card/Card.js +1 -1
- package/build/dist/UI/Components/Card/Card.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +2 -2
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js +1 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js +1 -1
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
- package/build/dist/UI/Components/Date/StartAndEndDate.js +5 -5
- package/build/dist/UI/Components/Date/StartAndEndDate.js.map +1 -1
- package/build/dist/UI/Components/Diagram/HorizontalStepChain.js +1 -1
- package/build/dist/UI/Components/Diagram/HorizontalStepChain.js.map +1 -1
- package/build/dist/UI/Components/Feed/FeedOptionsButton.js +1 -1
- package/build/dist/UI/Components/Feed/FeedOptionsButton.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
- package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js +1 -1
- package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js +1 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +2 -2
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +4 -4
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +9 -2
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +2 -2
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Components/Page/Page.js +1 -1
- package/build/dist/UI/Components/Page/Page.js.map +1 -1
- package/build/dist/UI/Components/Pagination/Pagination.js +3 -3
- package/build/dist/UI/Components/Pagination/Pagination.js.map +1 -1
- package/build/dist/UI/Components/ProgressButtons/ProgressButtonItem.js +1 -1
- package/build/dist/UI/Components/ProgressButtons/ProgressButtonItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js +4 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js +3 -1
- package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceList.js +6 -6
- package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.js +1 -1
- package/build/dist/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentsModal.js +2 -2
- package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js +1 -1
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +66 -33
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js +7 -0
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js.map +1 -1
- package/build/dist/UI/Utils/TelemetryService.js +3 -2
- package/build/dist/UI/Utils/TelemetryService.js.map +1 -1
- package/build/dist/Utils/LabelRuleImportExport.js +2 -0
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
- package/build/dist/Utils/MetricUnitUtil.js +77 -13
- package/build/dist/Utils/MetricUnitUtil.js.map +1 -1
- package/build/dist/Utils/Monitor/MetricValueFormatter.js +58 -13
- package/build/dist/Utils/Monitor/MetricValueFormatter.js.map +1 -1
- package/build/dist/Utils/Monitor/PlatformMetricUnitUtil.js +161 -0
- package/build/dist/Utils/Monitor/PlatformMetricUnitUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/PlatformResourceIdentity.js +323 -0
- package/build/dist/Utils/Monitor/PlatformResourceIdentity.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.js +270 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +23 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js +61 -0
- package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js.map +1 -1
- package/build/dist/Utils/Telemetry/DatabaseServerEntityKeys.js +178 -0
- package/build/dist/Utils/Telemetry/DatabaseServerEntityKeys.js.map +1 -0
- package/build/dist/Utils/Telemetry/EntityKey.js +133 -0
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- package/build/dist/Utils/ValueFormatter.js +15 -0
- package/build/dist/Utils/ValueFormatter.js.map +1 -1
- package/package.json +1 -1
- package/tsconfig.tests.json +7 -5
|
@@ -20,6 +20,7 @@ jest.mock("../../../Server/Utils/PasswordHash", () => {
|
|
|
20
20
|
|
|
21
21
|
import CephClusterService from "../../../Server/Services/CephClusterService";
|
|
22
22
|
import CloudResourceService from "../../../Server/Services/CloudResourceService";
|
|
23
|
+
import DatabaseServerService from "../../../Server/Services/DatabaseServerService";
|
|
23
24
|
import DockerHostService from "../../../Server/Services/DockerHostService";
|
|
24
25
|
import DockerSwarmClusterService from "../../../Server/Services/DockerSwarmClusterService";
|
|
25
26
|
import GlobalCache from "../../../Server/Infrastructure/GlobalCache";
|
|
@@ -46,9 +47,10 @@ import {
|
|
|
46
47
|
/*
|
|
47
48
|
* Every resource type's liveness heartbeat, pinned together.
|
|
48
49
|
*
|
|
49
|
-
*
|
|
50
|
-
* otelCollectorStatus
|
|
51
|
-
* OpenTelemetry resource attributes, and
|
|
50
|
+
* Thirteen services write the same two liveness columns (lastSeenAt +
|
|
51
|
+
* otelCollectorStatus; a database adds collectorLastSeenAt) alongside
|
|
52
|
+
* optional columns harvested from OpenTelemetry resource attributes, and
|
|
53
|
+
* each has its own markDisconnected*
|
|
52
54
|
* job that flips the resource to "disconnected" 15 minutes after lastSeenAt
|
|
53
55
|
* stops advancing. They now share one implementation — ResourceHeartbeat —
|
|
54
56
|
* because eleven hand-copied versions meant eleven copies of the same defect
|
|
@@ -109,11 +111,49 @@ type ServiceCase = {
|
|
|
109
111
|
* These are what defeated the old throttle — see the header.
|
|
110
112
|
*/
|
|
111
113
|
churningExtras?: Array<Record<string, unknown>>;
|
|
114
|
+
/**
|
|
115
|
+
* The columns every heartbeat writes, when not just lastSeenAt +
|
|
116
|
+
* otelCollectorStatus. A database also stamps collectorLastSeenAt: an
|
|
117
|
+
* application querying it moves lastSeenAt too, so only that column says
|
|
118
|
+
* the COLLECTOR is alive.
|
|
119
|
+
*/
|
|
120
|
+
livenessColumns?: Array<string>;
|
|
112
121
|
};
|
|
113
122
|
|
|
114
123
|
/** Longer than any bounded column on any of these models. */
|
|
115
124
|
const OVERSIZED: string = "x".repeat(5000);
|
|
116
125
|
|
|
126
|
+
const DEFAULT_LIVENESS_COLUMNS: Array<string> = [
|
|
127
|
+
"lastSeenAt",
|
|
128
|
+
"otelCollectorStatus",
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
/*
|
|
132
|
+
* The database heartbeat is recordCollectorHeartbeat (a CLIENT span calling
|
|
133
|
+
* the database is a separate, sighting-only heartbeat). This view of the real
|
|
134
|
+
* service gives it the updateLastSeen shape the table drives - `this` stays
|
|
135
|
+
* the view, so the write spies below still see every UPDATE - and answers
|
|
136
|
+
* the one read the heartbeat makes afterwards (the auto-archive restore
|
|
137
|
+
* check) with "no row", so the suite still never reaches Postgres.
|
|
138
|
+
*/
|
|
139
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
140
|
+
const databaseServerHeartbeat: any = Object.assign(
|
|
141
|
+
Object.create(DatabaseServerService),
|
|
142
|
+
{
|
|
143
|
+
updateLastSeen: function (
|
|
144
|
+
this: typeof DatabaseServerService,
|
|
145
|
+
id: ObjectID,
|
|
146
|
+
extra?: { agentVersion?: string; dbVersion?: string },
|
|
147
|
+
): Promise<void> {
|
|
148
|
+
return this.recordCollectorHeartbeat(id, extra);
|
|
149
|
+
},
|
|
150
|
+
findOneById: async (): Promise<null> => {
|
|
151
|
+
return null;
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
);
|
|
155
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
156
|
+
|
|
117
157
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
118
158
|
const SERVICE_CASES: Array<ServiceCase> = [
|
|
119
159
|
{
|
|
@@ -257,6 +297,19 @@ const SERVICE_CASES: Array<ServiceCase> = [
|
|
|
257
297
|
{ osType: "linux", processCount: 413, totalMemoryBytes: 17179869184 },
|
|
258
298
|
],
|
|
259
299
|
},
|
|
300
|
+
{
|
|
301
|
+
name: "DatabaseServerService",
|
|
302
|
+
service: databaseServerHeartbeat,
|
|
303
|
+
namespace: "database-server-last-seen",
|
|
304
|
+
extra: { agentVersion: "0.118.0" },
|
|
305
|
+
otherExtra: { agentVersion: "0.119.0" },
|
|
306
|
+
oversizedExtra: { dbVersion: OVERSIZED },
|
|
307
|
+
livenessColumns: [
|
|
308
|
+
"collectorLastSeenAt",
|
|
309
|
+
"lastSeenAt",
|
|
310
|
+
"otelCollectorStatus",
|
|
311
|
+
],
|
|
312
|
+
},
|
|
260
313
|
];
|
|
261
314
|
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
262
315
|
|
|
@@ -269,7 +322,11 @@ describe.each(SERVICE_CASES)(
|
|
|
269
322
|
otherExtra,
|
|
270
323
|
oversizedExtra,
|
|
271
324
|
churningExtras,
|
|
325
|
+
livenessColumns,
|
|
272
326
|
}: ServiceCase) => {
|
|
327
|
+
const liveness: Array<string> = [
|
|
328
|
+
...(livenessColumns || DEFAULT_LIVENESS_COLUMNS),
|
|
329
|
+
].sort();
|
|
273
330
|
let writes: Array<WriteCall>;
|
|
274
331
|
let cache: Map<string, string>;
|
|
275
332
|
let deletedCacheKeys: Array<string>;
|
|
@@ -329,8 +386,8 @@ describe.each(SERVICE_CASES)(
|
|
|
329
386
|
}
|
|
330
387
|
|
|
331
388
|
/**
|
|
332
|
-
* Fails any write carrying more than the
|
|
333
|
-
*
|
|
389
|
+
* Fails any write carrying more than the liveness columns — the shape
|
|
390
|
+
* of a Postgres rejection caused by one bad optional column.
|
|
334
391
|
*/
|
|
335
392
|
function mockEnrichedWriteFailing(): void {
|
|
336
393
|
jest
|
|
@@ -340,7 +397,7 @@ describe.each(SERVICE_CASES)(
|
|
|
340
397
|
...(input.data as Record<string, unknown>),
|
|
341
398
|
};
|
|
342
399
|
writes.push({ id: input.id, data: data });
|
|
343
|
-
if (Object.keys(data).length >
|
|
400
|
+
if (Object.keys(data).length > liveness.length) {
|
|
344
401
|
throw new Error("value too long for type character varying(100)");
|
|
345
402
|
}
|
|
346
403
|
return true;
|
|
@@ -505,10 +562,7 @@ describe.each(SERVICE_CASES)(
|
|
|
505
562
|
await service.updateLastSeen(RESOURCE_ID, oversizedExtra as never);
|
|
506
563
|
|
|
507
564
|
expect(writes).toHaveLength(2);
|
|
508
|
-
expect(Object.keys(lastWrite()).sort()).toEqual(
|
|
509
|
-
"lastSeenAt",
|
|
510
|
-
"otelCollectorStatus",
|
|
511
|
-
]);
|
|
565
|
+
expect(Object.keys(lastWrite()).sort()).toEqual(liveness);
|
|
512
566
|
expect(lastWrite()["otelCollectorStatus"]).toBe("connected");
|
|
513
567
|
expect(lastWrite()["lastSeenAt"]).toBeInstanceOf(Date);
|
|
514
568
|
});
|
|
@@ -553,10 +607,7 @@ describe.each(SERVICE_CASES)(
|
|
|
553
607
|
|
|
554
608
|
await service.updateLastSeen(RESOURCE_ID, oversizedExtra as never);
|
|
555
609
|
|
|
556
|
-
expect(Object.keys(lastWrite()).sort()).toEqual(
|
|
557
|
-
"lastSeenAt",
|
|
558
|
-
"otelCollectorStatus",
|
|
559
|
-
]);
|
|
610
|
+
expect(Object.keys(lastWrite()).sort()).toEqual(liveness);
|
|
560
611
|
});
|
|
561
612
|
|
|
562
613
|
test("surfaces a genuinely broken database instead of hiding it", async () => {
|
|
@@ -617,10 +668,7 @@ describe.each(SERVICE_CASES)(
|
|
|
617
668
|
await service.updateLastSeen(RESOURCE_ID, extra as never);
|
|
618
669
|
|
|
619
670
|
expect(writes).toHaveLength(1);
|
|
620
|
-
expect(Object.keys(lastWrite()).sort()).toEqual(
|
|
621
|
-
"lastSeenAt",
|
|
622
|
-
"otelCollectorStatus",
|
|
623
|
-
]);
|
|
671
|
+
expect(Object.keys(lastWrite()).sort()).toEqual(liveness);
|
|
624
672
|
});
|
|
625
673
|
});
|
|
626
674
|
|
|
@@ -668,11 +716,11 @@ describe.each(SERVICE_CASES)(
|
|
|
668
716
|
describe("liveness fallback coverage", () => {
|
|
669
717
|
test("covers every service that writes liveness on the hook-free path", () => {
|
|
670
718
|
/*
|
|
671
|
-
* If a
|
|
719
|
+
* If a fourteenth resource type grows an updateLastSeen, it belongs in
|
|
672
720
|
* SERVICE_CASES — that is the whole point of this suite. Bumping this
|
|
673
721
|
* number without adding the case defeats it.
|
|
674
722
|
*/
|
|
675
|
-
expect(SERVICE_CASES).toHaveLength(
|
|
723
|
+
expect(SERVICE_CASES).toHaveLength(13);
|
|
676
724
|
});
|
|
677
725
|
|
|
678
726
|
test("no service is listed twice", () => {
|
|
@@ -196,9 +196,9 @@ describe("static rule criteria runtime coverage", () => {
|
|
|
196
196
|
discoverStaticRuleForms();
|
|
197
197
|
const inheritedRuleModelNames: Array<string> = getInheritedRuleModelNames();
|
|
198
198
|
|
|
199
|
-
test("all
|
|
200
|
-
expect(formFiles).toHaveLength(
|
|
201
|
-
expect(formsByModel.size).toBe(
|
|
199
|
+
test("all 66 static match-criteria forms route their 78 rule models through ModelForm", () => {
|
|
200
|
+
expect(formFiles).toHaveLength(66);
|
|
201
|
+
expect(formsByModel.size).toBe(78);
|
|
202
202
|
expect([...formsByModel.keys()].sort()).toEqual(inheritedRuleModelNames);
|
|
203
203
|
expect(Object.keys(RULE_CRITERIA_FIELDS_BY_MODEL).sort()).toEqual(
|
|
204
204
|
inheritedRuleModelNames,
|
|
@@ -109,6 +109,15 @@ describe("resource facet counting covers the whole catalog", () => {
|
|
|
109
109
|
);
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
+
test("databaseServerId is counted under DatabaseServer — the receiver batches primary-keyed on the row", () => {
|
|
113
|
+
const statement: Statement = service.build({
|
|
114
|
+
facetKey: "databaseServerId",
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
expect(paramValues(statement)).toContain(ServiceType.DatabaseServer);
|
|
118
|
+
expect(statement.query).not.toContain("mapContains(attributes");
|
|
119
|
+
});
|
|
120
|
+
|
|
112
121
|
test("iotFleetId is counted under IoTDevice — ingest stamps the fleet id with that type", () => {
|
|
113
122
|
const statement: Statement = service.build({ facetKey: "iotFleetId" });
|
|
114
123
|
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import Entities from "../../../Models/DatabaseModels/Index";
|
|
2
|
+
import PostgresAppInstance from "../../../Server/Infrastructure/PostgresDatabase";
|
|
3
|
+
import UserProjectSsoConsentService from "../../../Server/Services/UserProjectSsoConsentService";
|
|
4
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
5
|
+
import { DataSource } from "typeorm";
|
|
6
|
+
|
|
7
|
+
jest.mock("../../../Server/Middleware/UserAuthorization", () => {
|
|
8
|
+
return { getUserMiddleware: jest.fn() };
|
|
9
|
+
});
|
|
10
|
+
jest.mock("../../../Server/Services/ProjectService", () => {
|
|
11
|
+
return { getCurrentPlan: jest.fn() };
|
|
12
|
+
});
|
|
13
|
+
jest.mock("../../../Server/Infrastructure/Postgres/DataSourceOptions", () => {
|
|
14
|
+
return {};
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
* The consent record against a real, migrated database.
|
|
19
|
+
*
|
|
20
|
+
* UserProjectSsoConsentService.test.ts pins the service's logic with the
|
|
21
|
+
* database faked. What only a database can show is the guarantee that logic
|
|
22
|
+
* leans on: the unique index turns a second, racing insert for the same
|
|
23
|
+
* (user, project) into an error rather than a duplicate row, so two clicks on
|
|
24
|
+
* one confirmation link -- or two links for one project -- end with exactly
|
|
25
|
+
* one consent, and the second click still succeeds.
|
|
26
|
+
*
|
|
27
|
+
* Opt in with RUN_POSTGRES_SSO_CONSENT_TESTS=true and config.env; point it at
|
|
28
|
+
* a migrated database with SSO_CONSENT_TEST_DATABASE_HOST/PORT/NAME
|
|
29
|
+
* (default localhost:5400; the Postgres Schema Drift job runs it). Only the table definition is copied from public, into an
|
|
30
|
+
* isolated schema that is dropped afterwards; every row is synthetic.
|
|
31
|
+
*/
|
|
32
|
+
const describePostgres: typeof describe =
|
|
33
|
+
process.env["RUN_POSTGRES_SSO_CONSENT_TESTS"] === "true"
|
|
34
|
+
? describe
|
|
35
|
+
: describe.skip;
|
|
36
|
+
|
|
37
|
+
describePostgres("UserProjectSsoConsent against Postgres", () => {
|
|
38
|
+
const schema: string = `sso_consent_test_${ObjectID.generate().toString().replace(/-/g, "")}`;
|
|
39
|
+
let database: DataSource;
|
|
40
|
+
|
|
41
|
+
const countRows: (
|
|
42
|
+
userId: ObjectID,
|
|
43
|
+
projectId: ObjectID,
|
|
44
|
+
) => Promise<number> = async (
|
|
45
|
+
userId: ObjectID,
|
|
46
|
+
projectId: ObjectID,
|
|
47
|
+
): Promise<number> => {
|
|
48
|
+
const rows: Array<{ count: string }> = await database.query(
|
|
49
|
+
`SELECT COUNT(*)::text AS count FROM "${schema}"."UserProjectSsoConsent" WHERE "userId" = $1 AND "projectId" = $2`,
|
|
50
|
+
[userId.toString(), projectId.toString()],
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
return Number(rows[0]!.count);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
beforeAll(async () => {
|
|
57
|
+
database = new DataSource({
|
|
58
|
+
type: "postgres",
|
|
59
|
+
host: process.env["SSO_CONSENT_TEST_DATABASE_HOST"] || "localhost",
|
|
60
|
+
port: Number(process.env["SSO_CONSENT_TEST_DATABASE_PORT"] || "5400"),
|
|
61
|
+
username: process.env["DATABASE_USERNAME"] || "postgres",
|
|
62
|
+
password: process.env["DATABASE_PASSWORD"] || "password",
|
|
63
|
+
database:
|
|
64
|
+
process.env["SSO_CONSENT_TEST_DATABASE_NAME"] ||
|
|
65
|
+
process.env["DATABASE_NAME"] ||
|
|
66
|
+
"oneuptimedb",
|
|
67
|
+
entities: Entities,
|
|
68
|
+
schema,
|
|
69
|
+
synchronize: false,
|
|
70
|
+
extra: { options: `-c search_path=${schema},public` },
|
|
71
|
+
});
|
|
72
|
+
await database.initialize();
|
|
73
|
+
await database.query(`CREATE SCHEMA "${schema}"`);
|
|
74
|
+
await database.query(
|
|
75
|
+
`CREATE TABLE "${schema}"."UserProjectSsoConsent" (LIKE public."UserProjectSsoConsent" INCLUDING ALL)`,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
jest.spyOn(PostgresAppInstance, "isConnected").mockReturnValue(true);
|
|
79
|
+
jest.spyOn(PostgresAppInstance, "getDataSource").mockReturnValue(database);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
afterAll(async () => {
|
|
83
|
+
if (database?.isInitialized) {
|
|
84
|
+
await database.query(`DROP SCHEMA IF EXISTS "${schema}" CASCADE`);
|
|
85
|
+
await database.destroy();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
jest.restoreAllMocks();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("records consent once, and finds it for that project only", async () => {
|
|
92
|
+
const userId: ObjectID = ObjectID.generate();
|
|
93
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
94
|
+
const otherProjectId: ObjectID = ObjectID.generate();
|
|
95
|
+
|
|
96
|
+
expect(
|
|
97
|
+
await UserProjectSsoConsentService.hasConsent({ userId, projectId }),
|
|
98
|
+
).toBe(false);
|
|
99
|
+
|
|
100
|
+
await UserProjectSsoConsentService.recordConsent({ userId, projectId });
|
|
101
|
+
|
|
102
|
+
expect(
|
|
103
|
+
await UserProjectSsoConsentService.hasConsent({ userId, projectId }),
|
|
104
|
+
).toBe(true);
|
|
105
|
+
expect(
|
|
106
|
+
await UserProjectSsoConsentService.hasConsent({
|
|
107
|
+
userId,
|
|
108
|
+
projectId: otherProjectId,
|
|
109
|
+
}),
|
|
110
|
+
).toBe(false);
|
|
111
|
+
expect(
|
|
112
|
+
await UserProjectSsoConsentService.hasConsent({
|
|
113
|
+
userId: ObjectID.generate(),
|
|
114
|
+
projectId,
|
|
115
|
+
}),
|
|
116
|
+
).toBe(false);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("a second confirmation neither fails nor duplicates the row", async () => {
|
|
120
|
+
const userId: ObjectID = ObjectID.generate();
|
|
121
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
122
|
+
|
|
123
|
+
await UserProjectSsoConsentService.recordConsent({ userId, projectId });
|
|
124
|
+
await UserProjectSsoConsentService.recordConsent({ userId, projectId });
|
|
125
|
+
|
|
126
|
+
expect(await countRows(userId, projectId)).toBe(1);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test("two confirmations racing each other end with exactly one row", async () => {
|
|
130
|
+
const userId: ObjectID = ObjectID.generate();
|
|
131
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
132
|
+
|
|
133
|
+
await Promise.all([
|
|
134
|
+
UserProjectSsoConsentService.recordConsent({ userId, projectId }),
|
|
135
|
+
UserProjectSsoConsentService.recordConsent({ userId, projectId }),
|
|
136
|
+
UserProjectSsoConsentService.recordConsent({ userId, projectId }),
|
|
137
|
+
]);
|
|
138
|
+
|
|
139
|
+
expect(await countRows(userId, projectId)).toBe(1);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("the database itself refuses a duplicate live consent", async () => {
|
|
143
|
+
const userId: ObjectID = ObjectID.generate();
|
|
144
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
145
|
+
const insert: string = `INSERT INTO "${schema}"."UserProjectSsoConsent" ("userId", "projectId", "version") VALUES ($1, $2, 1)`;
|
|
146
|
+
|
|
147
|
+
await database.query(insert, [userId.toString(), projectId.toString()]);
|
|
148
|
+
|
|
149
|
+
await expect(
|
|
150
|
+
database.query(insert, [userId.toString(), projectId.toString()]),
|
|
151
|
+
).rejects.toThrow(/duplicate key value/);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import UserProjectSsoConsent from "../../../Models/DatabaseModels/UserProjectSsoConsent";
|
|
2
|
+
import UserProjectSsoConsentService from "../../../Server/Services/UserProjectSsoConsentService";
|
|
3
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
4
|
+
import PositiveNumber from "../../../Types/PositiveNumber";
|
|
5
|
+
import { afterEach, describe, expect, jest, test } from "@jest/globals";
|
|
6
|
+
import { getMetadataArgsStorage } from "typeorm";
|
|
7
|
+
import { IndexMetadataArgs } from "typeorm/metadata-args/IndexMetadataArgs";
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* The record that an account's owner agreed, from their mailbox, that a
|
|
11
|
+
* project's single sign-on may sign them in. Read on every hosted project-SSO
|
|
12
|
+
* sign-in; written only by the confirmation link.
|
|
13
|
+
*
|
|
14
|
+
* What has to hold:
|
|
15
|
+
*
|
|
16
|
+
* - consent is per (user, project): the query is scoped to both, so one
|
|
17
|
+
* project's consent can never let another project's IdP in;
|
|
18
|
+
* - recording is idempotent, because the same person can press the button
|
|
19
|
+
* twice, or confirm two emails for the same project, and the second must
|
|
20
|
+
* neither fail nor duplicate the row;
|
|
21
|
+
* - a lost race with a concurrent insert is absorbed, but a real failure is
|
|
22
|
+
* not swallowed.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const USER_ID: ObjectID = new ObjectID("88888888-8888-4888-8888-888888888888");
|
|
26
|
+
const PROJECT_ID: ObjectID = new ObjectID(
|
|
27
|
+
"99999999-9999-4999-8999-999999999999",
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
* Spy handles are held through this rather than a SpiedFunction/SpyInstance
|
|
32
|
+
* type: two such declarations are in scope in this project (the global jest
|
|
33
|
+
* namespace's and @jest/globals'), jest.spyOn returns the latter, and naming
|
|
34
|
+
* the wrong one passes the jest run and fails only in compile-common. These
|
|
35
|
+
* tests read exactly one thing off a spy, so that is all this names.
|
|
36
|
+
*/
|
|
37
|
+
interface SpyCalls {
|
|
38
|
+
mock: { calls: Array<Array<unknown>> };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
jest.restoreAllMocks();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe("UserProjectSsoConsentService.hasConsent", () => {
|
|
46
|
+
test("asks about this user in this project, as root", async () => {
|
|
47
|
+
const countBy: SpyCalls = jest
|
|
48
|
+
.spyOn(UserProjectSsoConsentService, "countBy")
|
|
49
|
+
.mockResolvedValue(new PositiveNumber(1)) as unknown as SpyCalls;
|
|
50
|
+
|
|
51
|
+
await expect(
|
|
52
|
+
UserProjectSsoConsentService.hasConsent({
|
|
53
|
+
userId: USER_ID,
|
|
54
|
+
projectId: PROJECT_ID,
|
|
55
|
+
}),
|
|
56
|
+
).resolves.toBe(true);
|
|
57
|
+
|
|
58
|
+
const call: Record<string, any> = countBy.mock.calls[0]![0] as Record<
|
|
59
|
+
string,
|
|
60
|
+
any
|
|
61
|
+
>;
|
|
62
|
+
|
|
63
|
+
expect(call["query"]["userId"].toString()).toBe(USER_ID.toString());
|
|
64
|
+
expect(call["query"]["projectId"].toString()).toBe(PROJECT_ID.toString());
|
|
65
|
+
expect(call["props"]["isRoot"]).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("is false when there is no row", async () => {
|
|
69
|
+
jest
|
|
70
|
+
.spyOn(UserProjectSsoConsentService, "countBy")
|
|
71
|
+
.mockResolvedValue(new PositiveNumber(0));
|
|
72
|
+
|
|
73
|
+
await expect(
|
|
74
|
+
UserProjectSsoConsentService.hasConsent({
|
|
75
|
+
userId: USER_ID,
|
|
76
|
+
projectId: PROJECT_ID,
|
|
77
|
+
}),
|
|
78
|
+
).resolves.toBe(false);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe("UserProjectSsoConsentService.recordConsent", () => {
|
|
83
|
+
test("writes one row for this user and project", async () => {
|
|
84
|
+
jest
|
|
85
|
+
.spyOn(UserProjectSsoConsentService, "countBy")
|
|
86
|
+
.mockResolvedValue(new PositiveNumber(0));
|
|
87
|
+
const create: SpyCalls = jest
|
|
88
|
+
.spyOn(UserProjectSsoConsentService, "create")
|
|
89
|
+
.mockResolvedValue(new UserProjectSsoConsent()) as unknown as SpyCalls;
|
|
90
|
+
|
|
91
|
+
await UserProjectSsoConsentService.recordConsent({
|
|
92
|
+
userId: USER_ID,
|
|
93
|
+
projectId: PROJECT_ID,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
expect(create.mock.calls).toHaveLength(1);
|
|
97
|
+
|
|
98
|
+
const call: Record<string, any> = create.mock.calls[0]![0] as Record<
|
|
99
|
+
string,
|
|
100
|
+
any
|
|
101
|
+
>;
|
|
102
|
+
|
|
103
|
+
expect(call["data"]).toBeInstanceOf(UserProjectSsoConsent);
|
|
104
|
+
expect(call["data"]["userId"].toString()).toBe(USER_ID.toString());
|
|
105
|
+
expect(call["data"]["projectId"].toString()).toBe(PROJECT_ID.toString());
|
|
106
|
+
expect(call["props"]["isRoot"]).toBe(true);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("writes nothing when consent is already on record", async () => {
|
|
110
|
+
jest
|
|
111
|
+
.spyOn(UserProjectSsoConsentService, "countBy")
|
|
112
|
+
.mockResolvedValue(new PositiveNumber(1));
|
|
113
|
+
const create: SpyCalls = jest.spyOn(
|
|
114
|
+
UserProjectSsoConsentService,
|
|
115
|
+
"create",
|
|
116
|
+
) as unknown as SpyCalls;
|
|
117
|
+
|
|
118
|
+
await UserProjectSsoConsentService.recordConsent({
|
|
119
|
+
userId: USER_ID,
|
|
120
|
+
projectId: PROJECT_ID,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
expect(create.mock.calls).toHaveLength(0);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("absorbs losing an insert race to a concurrent click", async () => {
|
|
127
|
+
// Absent when checked, present by the time the insert was turned away.
|
|
128
|
+
jest
|
|
129
|
+
.spyOn(UserProjectSsoConsentService, "countBy")
|
|
130
|
+
.mockResolvedValueOnce(new PositiveNumber(0))
|
|
131
|
+
.mockResolvedValueOnce(new PositiveNumber(1));
|
|
132
|
+
jest
|
|
133
|
+
.spyOn(UserProjectSsoConsentService, "create")
|
|
134
|
+
.mockRejectedValue(
|
|
135
|
+
new Error("duplicate key value violates unique constraint"),
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
await expect(
|
|
139
|
+
UserProjectSsoConsentService.recordConsent({
|
|
140
|
+
userId: USER_ID,
|
|
141
|
+
projectId: PROJECT_ID,
|
|
142
|
+
}),
|
|
143
|
+
).resolves.toBeUndefined();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test("does not swallow a write that failed for any other reason", async () => {
|
|
147
|
+
jest
|
|
148
|
+
.spyOn(UserProjectSsoConsentService, "countBy")
|
|
149
|
+
.mockResolvedValue(new PositiveNumber(0));
|
|
150
|
+
jest
|
|
151
|
+
.spyOn(UserProjectSsoConsentService, "create")
|
|
152
|
+
.mockRejectedValue(new Error("connection terminated"));
|
|
153
|
+
|
|
154
|
+
await expect(
|
|
155
|
+
UserProjectSsoConsentService.recordConsent({
|
|
156
|
+
userId: USER_ID,
|
|
157
|
+
projectId: PROJECT_ID,
|
|
158
|
+
}),
|
|
159
|
+
).rejects.toThrow("connection terminated");
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
describe("UserProjectSsoConsent model", () => {
|
|
164
|
+
test("has no API: nobody but the server reads or writes it", () => {
|
|
165
|
+
const model: UserProjectSsoConsent = new UserProjectSsoConsent();
|
|
166
|
+
|
|
167
|
+
expect(model.createRecordPermissions).toEqual([]);
|
|
168
|
+
expect(model.readRecordPermissions).toEqual([]);
|
|
169
|
+
expect(model.updateRecordPermissions).toEqual([]);
|
|
170
|
+
expect(model.deleteRecordPermissions).toEqual([]);
|
|
171
|
+
expect(model.crudApiPath).toBeFalsy();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("is one live row per user and project, enforced by the database", () => {
|
|
175
|
+
/*
|
|
176
|
+
* The unique index is what turns a concurrent second insert into the
|
|
177
|
+
* error recordConsent absorbs, instead of a duplicate row.
|
|
178
|
+
*/
|
|
179
|
+
const index: IndexMetadataArgs | undefined = getMetadataArgsStorage()
|
|
180
|
+
.indices.filter((candidate: IndexMetadataArgs) => {
|
|
181
|
+
return candidate.target === UserProjectSsoConsent;
|
|
182
|
+
})
|
|
183
|
+
.find((candidate: IndexMetadataArgs) => {
|
|
184
|
+
return candidate.name === "IDX_UserProjectSsoConsent_userId_projectId";
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
expect(index).toBeDefined();
|
|
188
|
+
expect(index!.unique).toBe(true);
|
|
189
|
+
expect(index!.columns).toEqual(["userId", "projectId"]);
|
|
190
|
+
expect(index!.where).toBe('"deletedAt" IS NULL');
|
|
191
|
+
});
|
|
192
|
+
});
|
|
@@ -684,6 +684,77 @@ describe("UserService.createUserOnSignup -- first Master Admin election", () =>
|
|
|
684
684
|
});
|
|
685
685
|
});
|
|
686
686
|
|
|
687
|
+
describe("a signup that names an existing row", () => {
|
|
688
|
+
/*
|
|
689
|
+
* TypeORM's save() UPDATEs the row an entity's `_id` names, and this create
|
|
690
|
+
* runs as root, which DatabaseService.create exempts from its supplied-id
|
|
691
|
+
* check. A signup carrying a victim's id therefore rewrote the victim's
|
|
692
|
+
* email and password in place (UserSignupIdTakeoverPostgres.test.ts shows
|
|
693
|
+
* it against a real table). Refused before anything is read or written.
|
|
694
|
+
*/
|
|
695
|
+
const VICTIM_ID: string = "33333333-3333-4333-8333-333333333333";
|
|
696
|
+
|
|
697
|
+
type BuildUserWithIdFunction = (modules: LoadedModules) => any;
|
|
698
|
+
|
|
699
|
+
const buildUserWithId: BuildUserWithIdFunction = (
|
|
700
|
+
modules: LoadedModules,
|
|
701
|
+
): any => {
|
|
702
|
+
const user: any = buildUser({ modules, email: "attacker@example.com" });
|
|
703
|
+
user._id = VICTIM_ID;
|
|
704
|
+
return user;
|
|
705
|
+
};
|
|
706
|
+
|
|
707
|
+
test("self-hosted: refuses it without taking the lock or touching a row", async () => {
|
|
708
|
+
userRows.push({ email: "victim@example.com" });
|
|
709
|
+
|
|
710
|
+
await expect(
|
|
711
|
+
selfHosted.userService.createUserOnSignup({
|
|
712
|
+
user: buildUserWithId(selfHosted),
|
|
713
|
+
props: { isRoot: true },
|
|
714
|
+
}),
|
|
715
|
+
).rejects.toThrow("An id cannot be supplied when signing up.");
|
|
716
|
+
|
|
717
|
+
expect(events).toEqual([]);
|
|
718
|
+
expect(selfHosted.userService.create).not.toHaveBeenCalled();
|
|
719
|
+
expect(selfHosted.semaphore.lock).not.toHaveBeenCalled();
|
|
720
|
+
expect(userRows).toHaveLength(1);
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
test("self-hosted: refuses it on an empty instance, so the id cannot win the election either", async () => {
|
|
724
|
+
await expect(
|
|
725
|
+
selfHosted.userService.createUserOnSignup({
|
|
726
|
+
user: buildUserWithId(selfHosted),
|
|
727
|
+
props: { isRoot: true },
|
|
728
|
+
}),
|
|
729
|
+
).rejects.toThrow("An id cannot be supplied when signing up.");
|
|
730
|
+
|
|
731
|
+
expect(selfHosted.userService.create).not.toHaveBeenCalled();
|
|
732
|
+
expect(userRows).toHaveLength(0);
|
|
733
|
+
});
|
|
734
|
+
|
|
735
|
+
test("hosted: refuses it without touching a row", async () => {
|
|
736
|
+
await expect(
|
|
737
|
+
hosted.userService.createUserOnSignup({
|
|
738
|
+
user: buildUserWithId(hosted),
|
|
739
|
+
props: { isRoot: true },
|
|
740
|
+
}),
|
|
741
|
+
).rejects.toThrow("An id cannot be supplied when signing up.");
|
|
742
|
+
|
|
743
|
+
expect(events).toEqual([]);
|
|
744
|
+
expect(hosted.userService.create).not.toHaveBeenCalled();
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
test("a user with no id is still created", async () => {
|
|
748
|
+
const created: any = await hosted.userService.createUserOnSignup({
|
|
749
|
+
user: buildUser({ modules: hosted, email: "new@example.com" }),
|
|
750
|
+
props: { isRoot: true },
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
expect(created).toBeTruthy();
|
|
754
|
+
expect(hosted.userService.create).toHaveBeenCalledTimes(1);
|
|
755
|
+
});
|
|
756
|
+
});
|
|
757
|
+
|
|
687
758
|
describe("the race itself", () => {
|
|
688
759
|
test("two simultaneous signups produce exactly one Master Admin", async () => {
|
|
689
760
|
const [first, second]: Array<any> = await Promise.all([
|