@oneuptime/common 12.0.31 → 12.0.33
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/AnalyticsModels/Span.ts +14 -0
- package/Models/DatabaseModels/AlertState.ts +0 -2
- package/Models/DatabaseModels/Domain.ts +1 -1
- package/Models/DatabaseModels/EnterpriseLicense.ts +56 -0
- package/Models/DatabaseModels/Incident.ts +1 -1
- package/Models/DatabaseModels/IncidentTemplate.ts +1 -1
- package/Models/DatabaseModels/Index.ts +12 -0
- package/Models/DatabaseModels/MetricType.ts +0 -2
- package/Models/DatabaseModels/Monitor.ts +76 -0
- package/Models/DatabaseModels/MonitorStatusTimeline.ts +0 -2
- package/Models/DatabaseModels/MonitorTest.ts +0 -2
- package/Models/DatabaseModels/NetworkAlertPolicy.ts +690 -0
- package/Models/DatabaseModels/NetworkDevice.ts +297 -3
- package/Models/DatabaseModels/NetworkDeviceOidTemplate.ts +3 -1
- package/Models/DatabaseModels/NetworkDeviceRole.ts +648 -0
- package/Models/DatabaseModels/NetworkSite.ts +201 -2
- package/Models/DatabaseModels/NetworkSiteType.ts +102 -3
- package/Models/DatabaseModels/NetworkSnmpCredentialProfile.ts +841 -0
- package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -1
- package/Models/DatabaseModels/ScheduledMaintenanceTemplate.ts +1 -1
- package/Models/DatabaseModels/StatusPageAnnouncement.ts +0 -2
- package/Models/DatabaseModels/StatusPageAnnouncementTemplate.ts +0 -2
- package/Models/DatabaseModels/StatusPagePrivateUser.ts +0 -2
- package/Models/DatabaseModels/StatusPageResource.ts +0 -2
- package/Models/DatabaseModels/StatusPageSubscriber.ts +0 -2
- package/Models/DatabaseModels/TelemetryException.ts +119 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupBatch.ts +334 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupItem.ts +370 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupSetting.ts +282 -0
- package/Server/API/EnterpriseLicenseAPI.ts +391 -64
- package/Server/API/LlmProviderAPI.ts +137 -22
- package/Server/EnvironmentConfig.ts +14 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.ts +55 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790800000000-AddNetworkDeviceRoleTable.ts +72 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.ts +124 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.ts +132 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.ts +79 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.ts +191 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +14 -0
- package/Server/Infrastructure/QueueWorker.ts +38 -8
- package/Server/Middleware/BearerTokenAuthorization.ts +12 -0
- package/Server/Middleware/ProjectAuthorization.ts +11 -0
- package/Server/Middleware/SCIMAuthorization.ts +12 -0
- package/Server/Middleware/TelemetryIngest.ts +11 -0
- package/Server/Services/AIBillingService.ts +101 -27
- package/Server/Services/DatabaseService.ts +39 -9
- package/Server/Services/EnterpriseLicenseInstanceService.ts +197 -0
- package/Server/Services/EnterpriseLicenseService.ts +55 -0
- package/Server/Services/Index.ts +12 -0
- package/Server/Services/MonitorService.ts +143 -21
- package/Server/Services/MonitorStatusTimelineService.ts +150 -8
- package/Server/Services/MonitorTemplateService.ts +217 -1
- package/Server/Services/NetworkAlertPolicyEngineService.ts +2159 -0
- package/Server/Services/NetworkAlertPolicyService.ts +944 -0
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +9 -10
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +60 -15
- package/Server/Services/NetworkDeviceRoleService.ts +90 -0
- package/Server/Services/NetworkDeviceService.ts +1032 -73
- package/Server/Services/NetworkSiteService.ts +1502 -129
- package/Server/Services/NetworkSiteTypeService.ts +1216 -0
- package/Server/Services/NetworkSnmpCredentialProfileService.ts +238 -0
- package/Server/Services/NotificationService.ts +118 -28
- package/Server/Services/ProjectService.ts +186 -44
- package/Server/Services/StatusPagePrivateUserService.ts +103 -3
- package/Server/Services/UserNotificationEmailRollupBatchService.ts +78 -0
- package/Server/Services/UserNotificationEmailRollupItemService.ts +79 -0
- package/Server/Services/UserNotificationEmailRollupSettingService.ts +113 -0
- package/Server/Services/UserNotificationSettingService.ts +62 -31
- package/Server/Services/UserService.ts +95 -0
- package/Server/Types/Database/QueryHelper.ts +2 -2
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +14 -3
- package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +10 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +10 -0
- package/Server/Utils/AI/SRE/Insights/InsightTriageRunner.ts +62 -1
- package/Server/Utils/AI/Toolbox/AlertTools.ts +15 -1
- package/Server/Utils/Billing/BillingFailureNoticeThrottle.ts +80 -0
- package/Server/Utils/DataSource/HttpFetch.ts +9 -2
- package/Server/Utils/EmailRollup/EmailRollupConstants.ts +98 -0
- package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +872 -0
- package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +781 -0
- package/Server/Utils/EmailRollup/EmailRollupWriter.ts +368 -0
- package/Server/Utils/LLM/LLMService.ts +78 -0
- package/Server/Utils/LogRedaction.ts +8 -0
- package/Server/Utils/Logger.ts +79 -1
- package/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.ts +190 -0
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +9 -2
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +61 -1
- package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +14 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +49 -0
- package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +255 -4
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +41 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +43 -0
- package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +499 -19
- package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +66 -10
- package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +238 -44
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +146 -39
- package/Server/Utils/NetworkDevice/DeviceHealthAggregation.ts +31 -18
- package/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.ts +213 -0
- package/Server/Utils/OutboundUserAgent.ts +152 -0
- package/Server/Utils/StartServer.ts +51 -19
- package/Server/Utils/Telemetry/CaptureSpan.ts +32 -8
- package/Server/Utils/Telemetry/ErrorClassResolver.ts +120 -0
- package/Server/Utils/Telemetry/SpanUtil.ts +33 -0
- package/Server/Utils/Telemetry.ts +198 -51
- package/Server/Views/Partials/SensitiveUrlToken.ejs +140 -0
- package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +158 -27
- package/Tests/App/Dashboard/AskAiSuggestedPrompts.test.ts +279 -0
- package/Tests/App/Dashboard/DashboardChartWidgetZoom.test.tsx +35 -8
- package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +107 -3
- package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +517 -0
- package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +26 -0
- package/Tests/App/Dashboard/DashboardWideChartZoom.test.tsx +401 -0
- package/Tests/App/Dashboard/DeviceStatusHero.test.tsx +588 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +18 -9
- package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +632 -0
- package/Tests/App/Dashboard/MonitorRecommendationCreateProgress.test.tsx +682 -0
- package/Tests/App/Dashboard/MonitorTemplateColumnAndFacet.test.tsx +318 -0
- package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +4 -2
- package/Tests/App/Dashboard/NetworkDeviceBulkDelete.test.tsx +357 -0
- package/Tests/App/Dashboard/NetworkDeviceCreateFormMonitorBinding.test.tsx +676 -0
- package/Tests/App/Dashboard/NetworkDeviceCreateFormPingMonitor.test.tsx +791 -0
- package/Tests/App/Dashboard/NetworkDeviceCreateFormProbeAndSnmp.test.tsx +833 -0
- package/Tests/App/Dashboard/NetworkDeviceCriteriaFilter.test.ts +161 -0
- package/Tests/App/Dashboard/NetworkDeviceSettingsMonitoringSection.test.tsx +458 -0
- package/Tests/App/Dashboard/NetworkSideMenu.test.tsx +626 -0
- package/Tests/App/Dashboard/PingMonitorProvisioning.test.ts +368 -0
- package/Tests/App/Dashboard/RecommendationCard.test.tsx +796 -0
- package/Tests/App/Dashboard/RecommendationToolbar.test.tsx +519 -0
- package/Tests/App/Dashboard/RecommendationsList.test.tsx +661 -0
- package/Tests/App/Dashboard/SideMenuHarness.tsx +11 -3
- package/Tests/App/Dashboard/UseBulkCreatePingMonitors.test.tsx +899 -0
- package/Tests/App/Dashboard/UseBulkSnmpCredentialProfileActions.test.tsx +732 -0
- package/Tests/App/SensitiveUrlTokenBootstrap.test.ts +256 -0
- package/Tests/App/StatusPage/StatusPageIndexPageRobotsMeta.test.ts +11 -1
- package/Tests/App/StatusPage/StatusPageLoginCodeBootstrap.test.ts +9 -4
- package/Tests/Models/DatabaseModels/ModelRegistryInvariants.test.ts +115 -41
- package/Tests/Models/NetworkSiteHierarchy.test.ts +41 -4
- package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +951 -7
- package/Tests/Server/API/LlmProviderConnectionTest.test.ts +522 -0
- package/Tests/Server/Infrastructure/Postgres/NetworkDeviceRoleTableMigration.test.ts +476 -0
- package/Tests/Server/Infrastructure/Postgres/NetworkSnmpCredentialProfilesAndAlertPoliciesMigration.test.ts +854 -0
- package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +18 -0
- package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupTableMigration.test.ts +535 -0
- package/Tests/Server/Services/AIChatPrivacyPin.test.ts +560 -0
- package/Tests/Server/Services/BillingRechargeOwnerEmailGuards.test.ts +783 -0
- package/Tests/Server/Services/DatabaseServiceGenerateSlug.test.ts +215 -0
- package/Tests/Server/Services/EnterpriseLicenseInstanceServiceDeletionUsage.test.ts +707 -0
- package/Tests/Server/Services/EnterpriseLicenseServiceUsageAggregationLock.test.ts +329 -0
- package/Tests/Server/Services/MonitorServiceDeleteNetworkDeviceCleanup.test.ts +294 -0
- package/Tests/Server/Services/MonitorStatusBridgeProbePath.test.ts +802 -0
- package/Tests/Server/Services/MonitorStatusTimelineService.test.ts +72 -2
- package/Tests/Server/Services/NetworkAlertPolicyEngineHooks.test.ts +752 -0
- package/Tests/Server/Services/NetworkAlertPolicyEngineService.test.ts +1849 -0
- package/Tests/Server/Services/NetworkAlertPolicyModel.test.ts +1793 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +47 -4
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +97 -12
- package/Tests/Server/Services/NetworkDeviceAutoMonitorLifecycle.test.ts +148 -3
- package/Tests/Server/Services/NetworkDeviceMonitorBindingUpdateGuard.test.ts +514 -0
- package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +447 -58
- package/Tests/Server/Services/NetworkDeviceMonitoringMethodTransition.test.ts +739 -0
- package/Tests/Server/Services/NetworkDevicePollingTenancy.test.ts +501 -0
- package/Tests/Server/Services/NetworkDeviceRoleModel.test.ts +672 -0
- package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +1 -1
- package/Tests/Server/Services/NetworkDeviceSiteDefaultProbe.test.ts +432 -0
- package/Tests/Server/Services/NetworkSiteMonitoringDefaults.test.ts +498 -0
- package/Tests/Server/Services/NetworkSiteRollupPolicyAndMaintenance.test.ts +337 -55
- package/Tests/Server/Services/NetworkSiteService.test.ts +1868 -131
- package/Tests/Server/Services/NetworkSiteTypeService.test.ts +1109 -0
- package/Tests/Server/Services/NetworkSnmpCredentialProfileModel.test.ts +926 -0
- package/Tests/Server/Services/NetworkSnmpCredentialProfileService.test.ts +796 -0
- package/Tests/Server/Services/ProjectServiceCreateSubscriptionStarted.test.ts +67 -4
- package/Tests/Server/Services/ProjectServiceNetworkSiteTypeDefaults.test.ts +214 -0
- package/Tests/Server/Services/ScheduledMaintenanceSubscriberEndTime.test.ts +369 -0
- package/Tests/Server/Services/StatusPagePrivateUserEmailChangePasswordResetExpiry.test.ts +269 -0
- package/Tests/Server/Services/UserEmailChangePasswordResetExpiry.test.ts +472 -0
- package/Tests/Server/Services/UserNotificationEmailRollupModels.test.ts +569 -0
- package/Tests/Server/Services/UserNotificationEmailRollupSettingModel.test.ts +314 -0
- package/Tests/Server/Services/UserNotificationEmailRollupSettingService.test.ts +409 -0
- package/Tests/Server/Services/UserNotificationSettingMonitorDefaults.test.ts +248 -0
- package/Tests/Server/Services/UserNotificationSettingRollupRouting.test.ts +856 -0
- package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +145 -3
- package/Tests/Server/Types/Database/Permissions/DashboardAccessPermission.test.ts +321 -0
- package/Tests/Server/Types/Database/QueryHelperOperators.test.ts +17 -0
- package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +124 -0
- package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +208 -0
- package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +235 -0
- package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +253 -0
- package/Tests/Server/Utils/BasicCron.test.ts +283 -0
- package/Tests/Server/Utils/Captcha.test.ts +422 -0
- package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +96 -2
- package/Tests/Server/Utils/Database/MigrationFailureLog.test.ts +466 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerBehaviour.test.ts +1096 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerClaim.test.ts +466 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +1428 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +752 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupWriter.test.ts +864 -0
- package/Tests/Server/Utils/IncomingCallPhoneNumber.test.ts +174 -0
- package/Tests/Server/Utils/LoggerFaultDemotion.test.ts +346 -0
- package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +633 -0
- package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +196 -0
- package/Tests/Server/Utils/Monitor/DatabaseMetricWrite.test.ts +367 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +100 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +5 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +512 -31
- package/Tests/Server/Utils/Monitor/NetworkDeviceMetricUtil.test.ts +252 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +479 -42
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +351 -5
- package/Tests/Server/Utils/NetworkDevice/DeviceHealthAggregation.test.ts +136 -12
- package/Tests/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.test.ts +306 -0
- package/Tests/Server/Utils/OutboundUserAgent.test.ts +266 -0
- package/Tests/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClientUserAgent.test.ts +141 -0
- package/Tests/Server/Utils/Telemetry/ErrorClassResolver.test.ts +298 -0
- package/Tests/Server/Utils/Telemetry.test.ts +456 -66
- package/Tests/Types/Monitor/DatabaseMetricCatalog.test.ts +388 -0
- package/Tests/Types/Monitor/MonitorStepDatabaseMonitor.test.ts +243 -0
- package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorType.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +16 -7
- package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +60 -0
- package/Tests/Types/NetworkDevice/DefaultNetworkDeviceRole.test.ts +417 -0
- package/Tests/Types/NetworkDevice/NetworkAlertPolicyScope.test.ts +655 -0
- package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +115 -26
- package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +39 -0
- package/Tests/Types/NotificationSetting/NotificationEmailRollupPolicy.test.ts +299 -0
- package/Tests/Types/Telemetry/ErrorClass.test.ts +483 -0
- package/Tests/UI/Components/BasicRadioButtons.test.tsx +336 -0
- package/Tests/UI/Components/Charts/ChartClickDoubleClickDisambiguation.test.tsx +221 -0
- package/Tests/UI/Components/Charts/ChartDoubleClickReset.test.tsx +220 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +751 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +475 -43
- package/Tests/UI/Components/ModelTable/ColumnPreference.test.ts +89 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +15 -0
- package/Tests/UI/Components/NavBarCommandKGating.test.tsx +103 -8
- package/Tests/UI/Components/ProgressBar.test.tsx +38 -2
- package/Tests/UI/Components/SideMenuItem.test.tsx +256 -4
- package/Tests/UI/Components/SideMenuSection.test.tsx +310 -0
- package/Tests/UI/Components/SideOverSubmitState.test.tsx +335 -0
- package/Tests/UI/Utils/PageScrollLock.test.tsx +377 -0
- package/Tests/UI/Utils/PermissionGate.test.ts +78 -0
- package/Tests/UI/Utils/SensitiveUrlToken.test.ts +140 -0
- package/Tests/UI/Utils/TableColumnsToCsv.test.ts +30 -0
- package/Tests/UI/Utils/UseDashboardTimeRangeZoom.test.tsx +187 -0
- package/Tests/Utils/Dashboard/DashboardResourceListSharedArgs.test.ts +302 -0
- package/Tests/Utils/Dashboard/DashboardTimeRangeZoom.test.ts +242 -0
- package/Tests/Utils/EnterpriseLicenseSeats.test.ts +69 -0
- package/Tests/Utils/EnterpriseLicenseSync.test.ts +7 -1
- package/Tests/Utils/EnterpriseLicenseUsage.test.ts +433 -2
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +280 -1
- package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +1 -0
- package/Tests/Utils/Monitor/NetworkDeviceRoleCatalog.test.ts +981 -0
- package/Tests/Utils/Monitor/NetworkTopologyRoleCatalog.test.ts +865 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +38 -0
- package/Tests/Utils/NetworkDevice/DeviceHealthStateUtil.test.ts +284 -23
- package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +177 -0
- package/Tests/Utils/NetworkDevice/DeviceRoleKeyUtil.test.ts +538 -0
- package/Tests/Utils/NetworkDevice/MonitoringMethodThreadedClassifiers.test.ts +992 -0
- package/Tests/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.test.ts +427 -0
- package/Tests/Utils/NetworkDevice/ReachabilityStampConsistency.test.ts +185 -0
- package/Tests/Utils/NetworkDevice/SnmpCredentialUtil.test.ts +268 -0
- package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +55 -5
- package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +98 -21
- package/Tests/Utils/NetworkDiscovery/DiscoveryImportEligibility.test.ts +98 -20
- package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +8 -7
- package/Tests/Utils/NetworkDiscovery/PingMonitorBuilderForAddress.test.ts +274 -0
- package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +230 -51
- package/Tests/Utils/NetworkSite/TypeHierarchyUtil.test.ts +209 -0
- package/Tests/Utils/Slo/SloEvaluation.test.ts +171 -0
- package/Tests/Utils/Slug.test.ts +61 -1
- package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +145 -0
- package/Tests/jest.setup.ts +19 -0
- package/Types/AI/ExceptionAIClassification.ts +10 -24
- package/Types/Email/EmailTemplateType.ts +2 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +5 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.ts +13 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.ts +6 -0
- package/Types/Exception/ApiException.ts +10 -0
- package/Types/Exception/BadDataException.ts +11 -0
- package/Types/Exception/BadRequestException.ts +11 -0
- package/Types/Exception/Exception.ts +65 -0
- package/Types/Exception/ForbiddenException.ts +10 -0
- package/Types/Exception/NotAuthenticatedException.ts +10 -0
- package/Types/Exception/NotAuthorizedException.ts +10 -0
- package/Types/Exception/NotFoundException.ts +11 -0
- package/Types/Exception/PayloadTooLargeException.ts +11 -0
- package/Types/Exception/PaymentRequiredException.ts +10 -0
- package/Types/Exception/ServiceUnavailableException.ts +10 -0
- package/Types/Exception/SsoAuthorizationException.ts +10 -0
- package/Types/Exception/TenantNotFoundException.ts +11 -0
- package/Types/Exception/TimeoutException.ts +10 -0
- package/Types/Exception/TooManyRequestsException.ts +10 -0
- package/Types/Exception/UnableToReachServer.ts +10 -0
- package/Types/Exception/WebsiteRequestException.ts +10 -0
- package/Types/Monitor/CriteriaFilter.ts +60 -2
- package/Types/Monitor/DatabaseMetricCatalog.ts +693 -0
- package/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.ts +83 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +76 -0
- package/Types/Monitor/MonitorMetricType.ts +71 -0
- package/Types/Monitor/MonitorStep.ts +76 -0
- package/Types/Monitor/MonitorStepDatabaseMonitor.ts +171 -0
- package/Types/Monitor/MonitorStepSqlMonitor.ts +2 -20
- package/Types/Monitor/MonitorType.ts +47 -1
- package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +22 -1
- package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +61 -0
- package/Types/Monitor/SqlConnectionConfig.ts +31 -0
- package/Types/NetworkDevice/DefaultNetworkDeviceRole.ts +145 -0
- package/Types/NetworkDevice/NetworkAlertPolicyScope.ts +343 -0
- package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +42 -22
- package/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.ts +30 -0
- package/Types/NotificationSetting/NotificationEmailRollupCategory.ts +255 -0
- package/Types/NotificationSetting/NotificationEmailRollupPolicy.ts +104 -0
- package/Types/Permission.ts +135 -0
- package/Types/Probe/ProbeMonitorResponse.ts +16 -0
- package/Types/Telemetry/ErrorClass.ts +274 -0
- package/Types/Telemetry/UnitOfWork.ts +59 -0
- package/UI/Components/Charts/Area/AreaChart.tsx +7 -0
- package/UI/Components/Charts/Bar/BarChart.tsx +6 -0
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +9 -1
- package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +97 -35
- package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +14 -0
- package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +97 -35
- package/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.ts +13 -0
- package/UI/Components/Charts/Line/LineChart.tsx +7 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +2 -8
- package/UI/Components/EditionLabel/EditionLabel.tsx +4 -0
- package/UI/Components/Modal/Modal.tsx +2 -8
- package/UI/Components/ModelTable/BaseModelTable.tsx +50 -15
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +44 -0
- package/UI/Components/Navbar/NavBar.tsx +62 -13
- package/UI/Components/Navbar/NavBarMenuModal.tsx +7 -2
- package/UI/Components/ProgressBar/ProgressBar.tsx +12 -1
- package/UI/Components/RadioButtons/BasicRadioButtons.tsx +37 -7
- package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +2 -0
- package/UI/Components/SideMenu/SideMenu.tsx +135 -7
- package/UI/Components/SideMenu/SideMenuItem.tsx +80 -85
- package/UI/Components/SideMenu/SideMenuSection.tsx +69 -25
- package/UI/Components/SideOver/SideOver.tsx +21 -20
- package/UI/Utils/PageScrollLock.ts +79 -3
- package/UI/Utils/PermissionGate.ts +61 -0
- package/UI/Utils/SensitiveUrlToken.ts +112 -0
- package/UI/Utils/TestLLMProvider.ts +11 -0
- package/UI/Utils/UseDashboardTimeRangeZoom.ts +77 -0
- package/Utils/Dashboard/DashboardTimeRangeZoom.ts +118 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +16 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +191 -11
- package/Utils/Monitor/MonitorMetricType.ts +153 -1
- package/Utils/Monitor/NetworkDeviceRoleCatalog.ts +232 -0
- package/Utils/Monitor/NetworkDeviceRoleUtil.ts +2 -1
- package/Utils/Monitor/NetworkTopologyUtil.ts +139 -36
- package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +65 -14
- package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +43 -14
- package/Utils/NetworkDevice/DeviceRoleKeyUtil.ts +137 -0
- package/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.ts +247 -0
- package/Utils/NetworkDevice/SnmpCredentialUtil.ts +68 -0
- package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +15 -7
- package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +52 -17
- package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +55 -23
- package/Utils/NetworkDiscovery/PingMonitorBuilder.ts +115 -13
- package/Utils/NetworkSite/SiteStatusRollupUtil.ts +66 -20
- package/Utils/NetworkSite/TypeHierarchyUtil.ts +313 -0
- package/Utils/Rules/RulePatternMatchUtil.ts +1 -1
- package/Utils/Slug.ts +34 -1
- package/build/dist/Models/AnalyticsModels/Span.js +14 -0
- package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertState.js +0 -2
- package/build/dist/Models/DatabaseModels/AlertState.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Domain.js +1 -1
- package/build/dist/Models/DatabaseModels/Domain.js.map +1 -1
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +59 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js +1 -1
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +12 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MetricType.js +0 -2
- package/build/dist/Models/DatabaseModels/MetricType.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +75 -0
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js +0 -2
- package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorTest.js +0 -2
- package/build/dist/Models/DatabaseModels/MonitorTest.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js +713 -0
- package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +304 -4
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js +3 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceRole.js +677 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceRole.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSite.js +200 -2
- package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js +102 -3
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js +878 -0
- package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +0 -2
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncementTemplate.js +0 -2
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncementTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js +0 -2
- package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageResource.js +0 -2
- package/build/dist/Models/DatabaseModels/StatusPageResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js +0 -2
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryException.js +123 -0
- package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js +363 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js +402 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js +296 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js.map +1 -0
- package/build/dist/Server/API/EnterpriseLicenseAPI.js +273 -60
- package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
- package/build/dist/Server/API/LlmProviderAPI.js +108 -13
- package/build/dist/Server/API/LlmProviderAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +12 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790800000000-AddNetworkDeviceRoleTable.js +39 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790800000000-AddNetworkDeviceRoleTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js +111 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js +77 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js +50 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js +83 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/QueueWorker.js +33 -5
- package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
- package/build/dist/Server/Middleware/BearerTokenAuthorization.js +12 -0
- package/build/dist/Server/Middleware/BearerTokenAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/ProjectAuthorization.js +11 -0
- package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/SCIMAuthorization.js +12 -0
- package/build/dist/Server/Middleware/SCIMAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +11 -0
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AIBillingService.js +70 -16
- package/build/dist/Server/Services/AIBillingService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +31 -5
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js +167 -0
- package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseService.js +39 -0
- package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +12 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +119 -21
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusTimelineService.js +127 -8
- package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +162 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js +1683 -0
- package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js.map +1 -0
- package/build/dist/Server/Services/NetworkAlertPolicyService.js +732 -0
- package/build/dist/Server/Services/NetworkAlertPolicyService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +10 -9
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +54 -11
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceRoleService.js +70 -0
- package/build/dist/Server/Services/NetworkDeviceRoleService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceService.js +841 -70
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +1145 -107
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteTypeService.js +863 -0
- package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js +217 -0
- package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js.map +1 -0
- package/build/dist/Server/Services/NotificationService.js +80 -17
- package/build/dist/Server/Services/NotificationService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +131 -30
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserService.js +92 -2
- package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js +76 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js +77 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js +111 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationSettingService.js +46 -21
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +90 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +14 -3
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +10 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +10 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js +54 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +18 -4
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
- package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js +59 -0
- package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/HttpFetch.js +2 -1
- package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js +91 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +691 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +497 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js +257 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js.map +1 -0
- package/build/dist/Server/Utils/LLM/LLMService.js +64 -1
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/LogRedaction.js +8 -0
- package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
- package/build/dist/Server/Utils/Logger.js +63 -1
- package/build/dist/Server/Utils/Logger.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js +141 -0
- package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +51 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js +7 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +37 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +158 -6
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.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 +32 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +330 -21
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +55 -10
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +178 -49
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +119 -29
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js +30 -17
- package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js.map +1 -1
- package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js +158 -0
- package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js.map +1 -0
- package/build/dist/Server/Utils/OutboundUserAgent.js +123 -0
- package/build/dist/Server/Utils/OutboundUserAgent.js.map +1 -0
- package/build/dist/Server/Utils/StartServer.js +38 -14
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/CaptureSpan.js +28 -8
- package/build/dist/Server/Utils/Telemetry/CaptureSpan.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js +95 -0
- package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/SpanUtil.js +29 -0
- package/build/dist/Server/Utils/Telemetry/SpanUtil.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry.js +162 -46
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Types/AI/ExceptionAIClassification.js +10 -24
- package/build/dist/Types/AI/ExceptionAIClassification.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js +2 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js.map +1 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js +7 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js.map +1 -0
- package/build/dist/Types/Exception/ApiException.js +9 -0
- package/build/dist/Types/Exception/ApiException.js.map +1 -1
- package/build/dist/Types/Exception/BadDataException.js +10 -0
- package/build/dist/Types/Exception/BadDataException.js.map +1 -1
- package/build/dist/Types/Exception/BadRequestException.js +10 -0
- package/build/dist/Types/Exception/BadRequestException.js.map +1 -1
- package/build/dist/Types/Exception/Exception.js +56 -0
- package/build/dist/Types/Exception/Exception.js.map +1 -1
- package/build/dist/Types/Exception/ForbiddenException.js +9 -0
- package/build/dist/Types/Exception/ForbiddenException.js.map +1 -1
- package/build/dist/Types/Exception/NotAuthenticatedException.js +9 -0
- package/build/dist/Types/Exception/NotAuthenticatedException.js.map +1 -1
- package/build/dist/Types/Exception/NotAuthorizedException.js +9 -0
- package/build/dist/Types/Exception/NotAuthorizedException.js.map +1 -1
- package/build/dist/Types/Exception/NotFoundException.js +10 -0
- package/build/dist/Types/Exception/NotFoundException.js.map +1 -1
- package/build/dist/Types/Exception/PayloadTooLargeException.js +10 -0
- package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -1
- package/build/dist/Types/Exception/PaymentRequiredException.js +9 -0
- package/build/dist/Types/Exception/PaymentRequiredException.js.map +1 -1
- package/build/dist/Types/Exception/ServiceUnavailableException.js +9 -0
- package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -1
- package/build/dist/Types/Exception/SsoAuthorizationException.js +9 -0
- package/build/dist/Types/Exception/SsoAuthorizationException.js.map +1 -1
- package/build/dist/Types/Exception/TenantNotFoundException.js +10 -0
- package/build/dist/Types/Exception/TenantNotFoundException.js.map +1 -1
- package/build/dist/Types/Exception/TimeoutException.js +9 -0
- package/build/dist/Types/Exception/TimeoutException.js.map +1 -1
- package/build/dist/Types/Exception/TooManyRequestsException.js +9 -0
- package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -1
- package/build/dist/Types/Exception/UnableToReachServer.js +9 -0
- package/build/dist/Types/Exception/UnableToReachServer.js.map +1 -1
- package/build/dist/Types/Exception/WebsiteRequestException.js +9 -0
- package/build/dist/Types/Exception/WebsiteRequestException.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +45 -2
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/DatabaseMetricCatalog.js +594 -0
- package/build/dist/Types/Monitor/DatabaseMetricCatalog.js.map +1 -0
- package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js +21 -0
- package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +70 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorMetricType.js +61 -0
- package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +54 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js +122 -0
- package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorType.js +45 -1
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +21 -1
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
- package/build/dist/Types/Monitor/SqlConnectionConfig.js +2 -0
- package/build/dist/Types/Monitor/SqlConnectionConfig.js.map +1 -0
- package/build/dist/Types/NetworkDevice/DefaultNetworkDeviceRole.js +105 -0
- package/build/dist/Types/NetworkDevice/DefaultNetworkDeviceRole.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js +172 -0
- package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +40 -22
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -1
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js +26 -0
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js.map +1 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js +186 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js.map +1 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js +87 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js.map +1 -0
- package/build/dist/Types/Permission.js +120 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Telemetry/ErrorClass.js +216 -0
- package/build/dist/Types/Telemetry/ErrorClass.js.map +1 -0
- package/build/dist/Types/Telemetry/UnitOfWork.js +59 -0
- package/build/dist/Types/Telemetry/UnitOfWork.js.map +1 -0
- package/build/dist/UI/Components/Charts/Area/AreaChart.js +1 -1
- package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +6 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +79 -31
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +7 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +79 -31
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js +14 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js.map +1 -0
- 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 +2 -7
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +3 -0
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +2 -7
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +39 -13
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +39 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +44 -9
- 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/ProgressBar/ProgressBar.js +12 -1
- package/build/dist/UI/Components/ProgressBar/ProgressBar.js.map +1 -1
- package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js +6 -6
- package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js +1 -1
- package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js +76 -11
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js +50 -54
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js +32 -9
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js.map +1 -1
- package/build/dist/UI/Components/SideOver/SideOver.js +5 -20
- package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
- package/build/dist/UI/Utils/PageScrollLock.js +31 -3
- package/build/dist/UI/Utils/PageScrollLock.js.map +1 -1
- package/build/dist/UI/Utils/PermissionGate.js +42 -1
- package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
- package/build/dist/UI/Utils/SensitiveUrlToken.js +97 -0
- package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -0
- package/build/dist/UI/Utils/TestLLMProvider.js +4 -5
- package/build/dist/UI/Utils/TestLLMProvider.js.map +1 -1
- package/build/dist/UI/Utils/UseDashboardTimeRangeZoom.js +42 -0
- package/build/dist/UI/Utils/UseDashboardTimeRangeZoom.js.map +1 -0
- package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js +74 -0
- package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js.map +1 -0
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +15 -0
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +111 -9
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +109 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkDeviceRoleCatalog.js +126 -0
- package/build/dist/Utils/Monitor/NetworkDeviceRoleCatalog.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js +2 -1
- package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +75 -35
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js +27 -7
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +7 -5
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceRoleKeyUtil.js +114 -0
- package/build/dist/Utils/NetworkDevice/DeviceRoleKeyUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js +180 -0
- package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js +12 -0
- package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +15 -5
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +44 -15
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +52 -23
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js +85 -13
- package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +30 -15
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js +191 -0
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js.map +1 -0
- package/build/dist/Utils/Rules/RulePatternMatchUtil.js +1 -1
- package/build/dist/Utils/Slug.js +31 -1
- package/build/dist/Utils/Slug.js.map +1 -1
- package/package.json +2 -2
|
@@ -15,6 +15,9 @@ import MonitorService from "./MonitorService";
|
|
|
15
15
|
import MonitorStatusService from "./MonitorStatusService";
|
|
16
16
|
import NetworkDeviceService from "./NetworkDeviceService";
|
|
17
17
|
import NetworkSiteStatusTimelineService from "./NetworkSiteStatusTimelineService";
|
|
18
|
+
import NetworkSiteTypeService from "./NetworkSiteTypeService";
|
|
19
|
+
import NetworkSnmpCredentialProfileService from "./NetworkSnmpCredentialProfileService";
|
|
20
|
+
import ProbeService from "./ProbeService";
|
|
18
21
|
import Model from "../../Models/DatabaseModels/NetworkSite";
|
|
19
22
|
import Alert from "../../Models/DatabaseModels/Alert";
|
|
20
23
|
import AlertStateTimeline from "../../Models/DatabaseModels/AlertStateTimeline";
|
|
@@ -25,11 +28,13 @@ import QueryHelper from "../Types/Database/QueryHelper";
|
|
|
25
28
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
26
29
|
import NetworkDeviceHydrationUtil from "../Utils/Monitor/NetworkDeviceHydrationUtil";
|
|
27
30
|
import logger from "../Utils/Logger";
|
|
31
|
+
import { NetworkDeviceMonitoringMethodUtil } from "../../Types/NetworkDevice/NetworkDeviceMonitoringMethod";
|
|
28
32
|
import LIMIT_MAX, { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
29
33
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
30
34
|
import MonitorType from "../../Types/Monitor/MonitorType";
|
|
31
35
|
import ObjectID from "../../Types/ObjectID";
|
|
32
36
|
import OneUptimeDate from "../../Types/Date";
|
|
37
|
+
import PositiveNumber from "../../Types/PositiveNumber";
|
|
33
38
|
import Text from "../../Types/Text";
|
|
34
39
|
import { Raw } from "typeorm";
|
|
35
40
|
import RelationIdUtil from "../Utils/Database/RelationIdUtil";
|
|
@@ -37,6 +42,7 @@ import MaterializedPathUtil from "../../Utils/NetworkSite/MaterializedPathUtil";
|
|
|
37
42
|
import SiteStatusRollupUtil from "../../Utils/NetworkSite/SiteStatusRollupUtil";
|
|
38
43
|
import { parseSiteHealthRollupPolicy } from "../../Types/NetworkSite/SiteHealthRollupPolicy";
|
|
39
44
|
import NetworkSiteMaintenanceSuppression from "../Utils/NetworkSite/NetworkSiteMaintenanceSuppression";
|
|
45
|
+
import NetworkSiteHierarchyLock from "../Utils/NetworkSite/NetworkSiteHierarchyLock";
|
|
40
46
|
import AggregateResultUtil from "../Types/Database/AggregateResultUtil";
|
|
41
47
|
import { deviceRollupStateForGroup, } from "../Utils/NetworkDevice/DeviceHealthAggregation";
|
|
42
48
|
/*
|
|
@@ -47,10 +53,354 @@ import { deviceRollupStateForGroup, } from "../Utils/NetworkDevice/DeviceHealthA
|
|
|
47
53
|
* path rebase entirely. See RelationIdUtil.
|
|
48
54
|
*/
|
|
49
55
|
const PARENT_SITE_KEYS = ["parentSiteId", "parentSite"];
|
|
56
|
+
/*
|
|
57
|
+
* Like parentSite, the site's type can be written either as its FK or as the
|
|
58
|
+
* serialised relation produced by dashboard forms. Hierarchy validation must
|
|
59
|
+
* inspect both spellings because TypeORM has not resolved the relation when
|
|
60
|
+
* the before hooks run.
|
|
61
|
+
*/
|
|
62
|
+
const NETWORK_SITE_TYPE_KEYS = [
|
|
63
|
+
"networkSiteTypeId",
|
|
64
|
+
"networkSiteType",
|
|
65
|
+
];
|
|
66
|
+
const PROJECT_KEYS = ["projectId", "project"];
|
|
67
|
+
/*
|
|
68
|
+
* Both spellings of the site's two monitoring defaults: the probe that polls
|
|
69
|
+
* devices here, and the SNMP credentials they are walked with.
|
|
70
|
+
*
|
|
71
|
+
* Both are references that a device INHERITS - the probe copied onto the
|
|
72
|
+
* device at write (see NetworkDeviceService), the credentials read live at
|
|
73
|
+
* poll time (see NetworkDeviceHydrationUtil.resolveSnmpCredentials). So a
|
|
74
|
+
* cross-project value here is not a cosmetic error on one row: it reaches
|
|
75
|
+
* every device in the subtree. Watching only the FK spelling would leave the
|
|
76
|
+
* dashboard's site form - which posts the relation - unguarded, which is the
|
|
77
|
+
* bug RelationIdUtil exists to document.
|
|
78
|
+
*/
|
|
79
|
+
const PROBE_KEYS = ["probeId", "probe"];
|
|
80
|
+
const SNMP_CREDENTIAL_PROFILE_KEYS = [
|
|
81
|
+
"snmpCredentialProfileId",
|
|
82
|
+
"snmpCredentialProfile",
|
|
83
|
+
];
|
|
84
|
+
const MATERIALIZED_HIERARCHY_KEYS = [
|
|
85
|
+
"materializedPath",
|
|
86
|
+
"depth",
|
|
87
|
+
];
|
|
88
|
+
/*
|
|
89
|
+
* Type edits have to inspect every direct child. Keep each read bounded and
|
|
90
|
+
* page until exhaustion so a very wide site cannot hide invalid edges beyond
|
|
91
|
+
* DatabaseService's single-query limit.
|
|
92
|
+
*/
|
|
93
|
+
const DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE = 1000;
|
|
94
|
+
/*
|
|
95
|
+
* Rebase large subtrees in bounded pages. Each successful rewrite removes the
|
|
96
|
+
* row from the old path prefix, so every page must start at offset zero.
|
|
97
|
+
*/
|
|
98
|
+
const SUBTREE_REBASE_PAGE_SIZE = 1000;
|
|
99
|
+
/*
|
|
100
|
+
* Model instances initialise optional fields to undefined. Those properties
|
|
101
|
+
* are omissions, not requests to clear a relation; null is the explicit
|
|
102
|
+
* clear value and must still run validation.
|
|
103
|
+
*/
|
|
104
|
+
function isRelationWritten(data, keys) {
|
|
105
|
+
return keys.some((key) => {
|
|
106
|
+
return key in data && data[key] !== undefined;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
function normalizeId(id) {
|
|
110
|
+
return id.toString().toLowerCase();
|
|
111
|
+
}
|
|
112
|
+
function sameId(left, right) {
|
|
113
|
+
return normalizeId(left) === normalizeId(right);
|
|
114
|
+
}
|
|
115
|
+
/*
|
|
116
|
+
* RelationIdUtil intentionally returns null for anything it cannot resolve.
|
|
117
|
+
* In a hierarchy hook, however, an unresolvable NON-null value cannot mean
|
|
118
|
+
* "clear": TypeORM may still interpret a raw expression or relation-shaped
|
|
119
|
+
* object during the eventual write. Require each supplied spelling to be an
|
|
120
|
+
* explicit clear or a concrete ID before checking cross-spelling agreement.
|
|
121
|
+
*/
|
|
122
|
+
function readStrictRelationId(data) {
|
|
123
|
+
for (const key of data.keys) {
|
|
124
|
+
const value = data.payload[key];
|
|
125
|
+
if (typeof value === "function") {
|
|
126
|
+
throw new BadDataException(`${key} cannot be set to a raw SQL expression because the network site hierarchy must be validated against an actual ID.`);
|
|
127
|
+
}
|
|
128
|
+
const isExplicitClear = value === null || value === "";
|
|
129
|
+
if (value !== undefined &&
|
|
130
|
+
!isExplicitClear &&
|
|
131
|
+
!RelationIdUtil.read(data.payload, [key])) {
|
|
132
|
+
throw new BadDataException(`${key} must contain a valid ${data.relationTitle} ID.`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return RelationIdUtil.readConsistent(data.payload, data.keys, data.relationTitle);
|
|
136
|
+
}
|
|
50
137
|
export class Service extends DatabaseService {
|
|
51
138
|
constructor() {
|
|
52
139
|
super(Model);
|
|
53
140
|
}
|
|
141
|
+
/*
|
|
142
|
+
* Parent/type validation and the eventual write must observe one serialized
|
|
143
|
+
* project hierarchy. The same distributed lock is used by
|
|
144
|
+
* NetworkSiteTypeService, because changing either table can invalidate the
|
|
145
|
+
* other. It surrounds the whole DatabaseService mutation so success-hook
|
|
146
|
+
* subtree maintenance is protected too and finally always releases it.
|
|
147
|
+
*/
|
|
148
|
+
async create(createBy) {
|
|
149
|
+
if (createBy.props.ignoreHooks) {
|
|
150
|
+
return await super.create(createBy);
|
|
151
|
+
}
|
|
152
|
+
const rawData = createBy.data;
|
|
153
|
+
const projectId = createBy.props.tenantId ||
|
|
154
|
+
RelationIdUtil.readConsistent(rawData, ["projectId", "project"], "Project") ||
|
|
155
|
+
null;
|
|
156
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
157
|
+
projectIds: projectId ? [projectId] : [],
|
|
158
|
+
operation: async () => {
|
|
159
|
+
return await super.create(createBy);
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
async updateOneBy(updateOneBy) {
|
|
164
|
+
if (updateOneBy.props.ignoreHooks ||
|
|
165
|
+
!this.updateTouchesHierarchy(updateOneBy.data)) {
|
|
166
|
+
return await super.updateOneBy(updateOneBy);
|
|
167
|
+
}
|
|
168
|
+
const projectIds = await this.findMutationProjectIds({
|
|
169
|
+
query: updateOneBy.query,
|
|
170
|
+
props: updateOneBy.props,
|
|
171
|
+
limit: 1,
|
|
172
|
+
skip: 0,
|
|
173
|
+
isDelete: false,
|
|
174
|
+
});
|
|
175
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
176
|
+
projectIds,
|
|
177
|
+
operation: async () => {
|
|
178
|
+
return await super.updateOneBy(updateOneBy);
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
async updateBy(updateBy) {
|
|
183
|
+
if (updateBy.props.ignoreHooks ||
|
|
184
|
+
!this.updateTouchesHierarchy(updateBy.data)) {
|
|
185
|
+
return await super.updateBy(updateBy);
|
|
186
|
+
}
|
|
187
|
+
const projectIds = await this.findMutationProjectIds({
|
|
188
|
+
query: updateBy.query,
|
|
189
|
+
props: updateBy.props,
|
|
190
|
+
limit: this.positiveNumberValue(updateBy.limit, LIMIT_MAX),
|
|
191
|
+
skip: this.positiveNumberValue(updateBy.skip, 0),
|
|
192
|
+
isDelete: false,
|
|
193
|
+
});
|
|
194
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
195
|
+
projectIds,
|
|
196
|
+
operation: async () => {
|
|
197
|
+
return await super.updateBy(updateBy);
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
async deleteOneBy(deleteOneBy) {
|
|
202
|
+
if (deleteOneBy.props.ignoreHooks) {
|
|
203
|
+
return await super.deleteOneBy(deleteOneBy);
|
|
204
|
+
}
|
|
205
|
+
const projectIds = await this.findMutationProjectIds({
|
|
206
|
+
query: deleteOneBy.query,
|
|
207
|
+
props: deleteOneBy.props,
|
|
208
|
+
limit: 1,
|
|
209
|
+
skip: 0,
|
|
210
|
+
isDelete: true,
|
|
211
|
+
});
|
|
212
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
213
|
+
projectIds,
|
|
214
|
+
operation: async () => {
|
|
215
|
+
return await super.deleteOneBy(deleteOneBy);
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
async deleteBy(deleteBy) {
|
|
220
|
+
if (deleteBy.props.ignoreHooks) {
|
|
221
|
+
return await super.deleteBy(deleteBy);
|
|
222
|
+
}
|
|
223
|
+
const projectIds = await this.findMutationProjectIds({
|
|
224
|
+
query: deleteBy.query,
|
|
225
|
+
props: deleteBy.props,
|
|
226
|
+
limit: this.positiveNumberValue(deleteBy.limit, LIMIT_MAX),
|
|
227
|
+
skip: this.positiveNumberValue(deleteBy.skip, 0),
|
|
228
|
+
isDelete: true,
|
|
229
|
+
});
|
|
230
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
231
|
+
projectIds,
|
|
232
|
+
operation: async () => {
|
|
233
|
+
return await super.deleteBy(deleteBy);
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
async hardDeleteBy(deleteBy) {
|
|
238
|
+
if (deleteBy.props.ignoreHooks) {
|
|
239
|
+
return await super.hardDeleteBy(deleteBy);
|
|
240
|
+
}
|
|
241
|
+
/*
|
|
242
|
+
* The generic retention cron intentionally queries every tenant at once
|
|
243
|
+
* by deletedAt. Resolve that open-ended query to a closed set of leaf IDs
|
|
244
|
+
* before locking and deleting. Deleting leaves only means a limit can
|
|
245
|
+
* never split a parent from a surviving child; the cron's next iteration
|
|
246
|
+
* naturally works upward through the tree.
|
|
247
|
+
*/
|
|
248
|
+
if (!NetworkSiteHierarchyLock.isSafeRootMutationScope({
|
|
249
|
+
query: deleteBy.query,
|
|
250
|
+
props: deleteBy.props,
|
|
251
|
+
tenantScopeIsClosed: true,
|
|
252
|
+
})) {
|
|
253
|
+
return await this.hardDeleteClosedLeafBatch(deleteBy);
|
|
254
|
+
}
|
|
255
|
+
const projectIds = await this.findMutationProjectIds({
|
|
256
|
+
query: deleteBy.query,
|
|
257
|
+
props: deleteBy.props,
|
|
258
|
+
limit: this.positiveNumberValue(deleteBy.limit, LIMIT_MAX),
|
|
259
|
+
skip: this.positiveNumberValue(deleteBy.skip, 0),
|
|
260
|
+
isDelete: true,
|
|
261
|
+
});
|
|
262
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
263
|
+
projectIds,
|
|
264
|
+
operation: async () => {
|
|
265
|
+
return await super.hardDeleteBy(deleteBy);
|
|
266
|
+
},
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
updateTouchesHierarchy(data) {
|
|
270
|
+
const record = data;
|
|
271
|
+
return (isRelationWritten(record, PARENT_SITE_KEYS) ||
|
|
272
|
+
isRelationWritten(record, NETWORK_SITE_TYPE_KEYS) ||
|
|
273
|
+
isRelationWritten(record, PROJECT_KEYS) ||
|
|
274
|
+
isRelationWritten(record, MATERIALIZED_HIERARCHY_KEYS));
|
|
275
|
+
}
|
|
276
|
+
positiveNumberValue(value, fallback) {
|
|
277
|
+
if (value instanceof PositiveNumber) {
|
|
278
|
+
return value.toNumber();
|
|
279
|
+
}
|
|
280
|
+
return value !== null && value !== void 0 ? value : fallback;
|
|
281
|
+
}
|
|
282
|
+
async hardDeleteClosedLeafBatch(deleteBy) {
|
|
283
|
+
const requestedLimit = this.positiveNumberValue(deleteBy.limit, LIMIT_MAX);
|
|
284
|
+
if (requestedLimit <= 0) {
|
|
285
|
+
return 0;
|
|
286
|
+
}
|
|
287
|
+
const scanPageSize = Math.min(DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE, requestedLimit);
|
|
288
|
+
const leafSites = [];
|
|
289
|
+
let scanSkip = this.positiveNumberValue(deleteBy.skip, 0);
|
|
290
|
+
while (leafSites.length < requestedLimit) {
|
|
291
|
+
const candidates = await this.findBy({
|
|
292
|
+
query: deleteBy.query,
|
|
293
|
+
select: {
|
|
294
|
+
_id: true,
|
|
295
|
+
projectId: true,
|
|
296
|
+
},
|
|
297
|
+
sort: { _id: SortOrder.Ascending },
|
|
298
|
+
limit: scanPageSize,
|
|
299
|
+
skip: scanSkip,
|
|
300
|
+
props: { isRoot: true },
|
|
301
|
+
});
|
|
302
|
+
if (candidates.length === 0) {
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
const candidateIds = candidates
|
|
306
|
+
.map((candidate) => {
|
|
307
|
+
return candidate.id || null;
|
|
308
|
+
})
|
|
309
|
+
.filter((id) => {
|
|
310
|
+
return Boolean(id);
|
|
311
|
+
});
|
|
312
|
+
const parentIdsWithChildren = new Set();
|
|
313
|
+
for (let parentOffset = 0; parentOffset < candidateIds.length; parentOffset += DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE) {
|
|
314
|
+
const parentIdBatch = candidateIds.slice(parentOffset, parentOffset + DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE);
|
|
315
|
+
let childSkip = 0;
|
|
316
|
+
while (parentIdBatch.length > 0) {
|
|
317
|
+
const children = await this.findBy({
|
|
318
|
+
query: {
|
|
319
|
+
parentSiteId: QueryHelper.any(parentIdBatch),
|
|
320
|
+
},
|
|
321
|
+
select: { parentSiteId: true },
|
|
322
|
+
sort: { _id: SortOrder.Ascending },
|
|
323
|
+
limit: DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE,
|
|
324
|
+
skip: childSkip,
|
|
325
|
+
props: { isRoot: true },
|
|
326
|
+
});
|
|
327
|
+
for (const child of children) {
|
|
328
|
+
if (child.parentSiteId) {
|
|
329
|
+
parentIdsWithChildren.add(normalizeId(child.parentSiteId));
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (children.length < DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE) {
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
childSkip += children.length;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
for (const candidate of candidates) {
|
|
339
|
+
if (candidate.id &&
|
|
340
|
+
candidate.projectId &&
|
|
341
|
+
!parentIdsWithChildren.has(normalizeId(candidate.id))) {
|
|
342
|
+
leafSites.push(candidate);
|
|
343
|
+
if (leafSites.length === requestedLimit) {
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
scanSkip += candidates.length;
|
|
349
|
+
if (candidates.length < scanPageSize) {
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
if (leafSites.length === 0) {
|
|
354
|
+
return 0;
|
|
355
|
+
}
|
|
356
|
+
const leafIds = leafSites.map((site) => {
|
|
357
|
+
return site.id;
|
|
358
|
+
});
|
|
359
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
360
|
+
projectIds: leafSites.map((site) => {
|
|
361
|
+
return site.projectId;
|
|
362
|
+
}),
|
|
363
|
+
operation: async () => {
|
|
364
|
+
return await super.hardDeleteBy(Object.assign(Object.assign({}, deleteBy), { query: Object.assign(Object.assign({}, deleteBy.query), { _id: QueryHelper.any(leafIds) }), limit: leafIds.length, skip: 0 }));
|
|
365
|
+
},
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
async findMutationProjectIds(data) {
|
|
369
|
+
NetworkSiteHierarchyLock.assertSafeRootMutationScope({
|
|
370
|
+
query: data.query,
|
|
371
|
+
props: data.props,
|
|
372
|
+
tenantScopeIsClosed: data.isDelete,
|
|
373
|
+
});
|
|
374
|
+
const sites = await this.findBy({
|
|
375
|
+
query: data.isDelete
|
|
376
|
+
? this.scopeDeleteQueryToCallerTenant(data.query, data.props)
|
|
377
|
+
: this.scopeQueryToCallerTenant(data.query, data.props),
|
|
378
|
+
select: { projectId: true },
|
|
379
|
+
limit: data.limit,
|
|
380
|
+
skip: data.skip,
|
|
381
|
+
props: { isRoot: true },
|
|
382
|
+
});
|
|
383
|
+
const projectIds = sites
|
|
384
|
+
.map((site) => {
|
|
385
|
+
return site.projectId;
|
|
386
|
+
})
|
|
387
|
+
.filter((projectId) => {
|
|
388
|
+
return Boolean(projectId);
|
|
389
|
+
});
|
|
390
|
+
projectIds.push(...NetworkSiteHierarchyLock.getExplicitProjectIds(data.query));
|
|
391
|
+
if (projectIds.length === 0 && data.props.tenantId) {
|
|
392
|
+
projectIds.push(data.props.tenantId);
|
|
393
|
+
}
|
|
394
|
+
const seenProjectIds = new Set();
|
|
395
|
+
return projectIds.filter((projectId) => {
|
|
396
|
+
const normalizedProjectId = normalizeId(projectId);
|
|
397
|
+
if (seenProjectIds.has(normalizedProjectId)) {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
seenProjectIds.add(normalizedProjectId);
|
|
401
|
+
return true;
|
|
402
|
+
});
|
|
403
|
+
}
|
|
54
404
|
/**
|
|
55
405
|
* How many sites sit under each rolled-up MonitorStatus, counted in the
|
|
56
406
|
* database.
|
|
@@ -102,7 +452,18 @@ export class Service extends DatabaseService {
|
|
|
102
452
|
* never see, let alone rewrite, a row outside the caller's project.
|
|
103
453
|
*/
|
|
104
454
|
scopeQueryToCallerTenant(query, props) {
|
|
105
|
-
if (props.isRoot || !props.tenantId) {
|
|
455
|
+
if (props.isRoot || props.isMasterAdmin || !props.tenantId) {
|
|
456
|
+
return query;
|
|
457
|
+
}
|
|
458
|
+
return Object.assign(Object.assign({}, query), { projectId: props.tenantId });
|
|
459
|
+
}
|
|
460
|
+
/*
|
|
461
|
+
* Root deletes are also tenant-scoped by DeletePermission when tenantId is
|
|
462
|
+
* present. Mirror that exact rule in the preflight read so limit/skip guard
|
|
463
|
+
* the same rows the eventual delete can select.
|
|
464
|
+
*/
|
|
465
|
+
scopeDeleteQueryToCallerTenant(query, props) {
|
|
466
|
+
if (!props.tenantId || props.isMultiTenantRequest) {
|
|
106
467
|
return query;
|
|
107
468
|
}
|
|
108
469
|
return Object.assign(Object.assign({}, query), { projectId: props.tenantId });
|
|
@@ -148,10 +509,10 @@ export class Service extends DatabaseService {
|
|
|
148
509
|
/*
|
|
149
510
|
* A stored path is trustworthy only when it agrees with parentSiteId: it
|
|
150
511
|
* must end with the site's own id, and the segment before it must be the
|
|
151
|
-
* parent (nothing before it for a root). A delete that
|
|
152
|
-
* or a half-applied move, leaves the two disagreeing - and a
|
|
153
|
-
* silently corrupts every prefix query built from it, so treat
|
|
154
|
-
* missing and let the caller rebuild.
|
|
512
|
+
* parent (nothing before it for a root). A legacy delete that nullified
|
|
513
|
+
* parentSiteId, or a half-applied move, leaves the two disagreeing - and a
|
|
514
|
+
* stale path silently corrupts every prefix query built from it, so treat
|
|
515
|
+
* it as missing and let the caller rebuild.
|
|
155
516
|
*/
|
|
156
517
|
isPathConsistent(site) {
|
|
157
518
|
if (!site.id) {
|
|
@@ -170,32 +531,329 @@ export class Service extends DatabaseService {
|
|
|
170
531
|
: null;
|
|
171
532
|
return parentSegment === parentId;
|
|
172
533
|
}
|
|
534
|
+
/*
|
|
535
|
+
* Resolve a site type with tenant information and its configured direct
|
|
536
|
+
* parent type. The lookup deliberately runs as root: hook validation occurs
|
|
537
|
+
* before DatabaseService applies the caller's permission-scoped query, so
|
|
538
|
+
* the service must see the referenced row and perform the project check
|
|
539
|
+
* explicitly rather than confuse "foreign" with "missing".
|
|
540
|
+
*/
|
|
541
|
+
async getNetworkSiteTypeForHierarchy(networkSiteTypeId, cache) {
|
|
542
|
+
const key = normalizeId(networkSiteTypeId);
|
|
543
|
+
const cached = cache.get(key);
|
|
544
|
+
if (cached) {
|
|
545
|
+
return cached;
|
|
546
|
+
}
|
|
547
|
+
const networkSiteType = await NetworkSiteTypeService.findOneById({
|
|
548
|
+
id: networkSiteTypeId,
|
|
549
|
+
select: {
|
|
550
|
+
_id: true,
|
|
551
|
+
projectId: true,
|
|
552
|
+
parentNetworkSiteTypeId: true,
|
|
553
|
+
},
|
|
554
|
+
props: {
|
|
555
|
+
isRoot: true,
|
|
556
|
+
},
|
|
557
|
+
});
|
|
558
|
+
if (!networkSiteType) {
|
|
559
|
+
throw new BadDataException("Network site type not found.");
|
|
560
|
+
}
|
|
561
|
+
cache.set(key, networkSiteType);
|
|
562
|
+
return networkSiteType;
|
|
563
|
+
}
|
|
564
|
+
/*
|
|
565
|
+
* Assert one proposed site edge against the type hierarchy. Untyped legacy
|
|
566
|
+
* root rows remain readable/editable, but as soon as a site has a type its
|
|
567
|
+
* placement is exact: a root type has no parent, and a non-root type has a
|
|
568
|
+
* parent site whose type is precisely the configured direct parent type.
|
|
569
|
+
*/
|
|
570
|
+
async validateSiteTypeEdge(data) {
|
|
571
|
+
if (!data.networkSiteTypeId) {
|
|
572
|
+
if (data.parentSite) {
|
|
573
|
+
throw new BadDataException("A network site with a parent must have a network site type.");
|
|
574
|
+
}
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
const networkSiteType = await this.getNetworkSiteTypeForHierarchy(data.networkSiteTypeId, data.typeCache);
|
|
578
|
+
if (data.projectId &&
|
|
579
|
+
networkSiteType.projectId &&
|
|
580
|
+
!sameId(networkSiteType.projectId, data.projectId)) {
|
|
581
|
+
throw new BadDataException("Network site type must belong to the same project.");
|
|
582
|
+
}
|
|
583
|
+
const requiredParentTypeId = networkSiteType.parentNetworkSiteTypeId || null;
|
|
584
|
+
if (!requiredParentTypeId) {
|
|
585
|
+
if (data.parentSite) {
|
|
586
|
+
throw new BadDataException("A site with a root network site type cannot have a parent site.");
|
|
587
|
+
}
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
if (!data.parentSite) {
|
|
591
|
+
throw new BadDataException("This network site type requires a parent site.");
|
|
592
|
+
}
|
|
593
|
+
if (!data.parentSite.networkSiteTypeId ||
|
|
594
|
+
!sameId(data.parentSite.networkSiteTypeId, requiredParentTypeId)) {
|
|
595
|
+
throw new BadDataException("Parent site must use the configured parent network site type.");
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
/*
|
|
599
|
+
* Changing a site's type also changes what every direct child's type must
|
|
600
|
+
* point at. Validate those reverse edges before the update so one edit
|
|
601
|
+
* cannot strand a previously valid subtree.
|
|
602
|
+
*/
|
|
603
|
+
async validateDirectChildrenForTypeChange(data) {
|
|
604
|
+
if (!data.site.id || !data.site.projectId) {
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
const proposedParent = {
|
|
608
|
+
id: data.site.id,
|
|
609
|
+
projectId: data.site.projectId,
|
|
610
|
+
networkSiteTypeId: data.proposedNetworkSiteTypeId || undefined,
|
|
611
|
+
};
|
|
612
|
+
let skip = 0;
|
|
613
|
+
while (true) {
|
|
614
|
+
const children = await this.findBy({
|
|
615
|
+
query: {
|
|
616
|
+
projectId: data.site.projectId,
|
|
617
|
+
parentSiteId: data.site.id,
|
|
618
|
+
},
|
|
619
|
+
select: {
|
|
620
|
+
_id: true,
|
|
621
|
+
projectId: true,
|
|
622
|
+
networkSiteTypeId: true,
|
|
623
|
+
},
|
|
624
|
+
sort: {
|
|
625
|
+
_id: SortOrder.Ascending,
|
|
626
|
+
},
|
|
627
|
+
limit: DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE,
|
|
628
|
+
skip: skip,
|
|
629
|
+
props: {
|
|
630
|
+
isRoot: true,
|
|
631
|
+
},
|
|
632
|
+
});
|
|
633
|
+
for (const child of children) {
|
|
634
|
+
await this.validateSiteTypeEdge({
|
|
635
|
+
networkSiteTypeId: child.networkSiteTypeId || null,
|
|
636
|
+
parentSite: proposedParent,
|
|
637
|
+
projectId: child.projectId || data.site.projectId,
|
|
638
|
+
typeCache: data.typeCache,
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
if (children.length < DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE) {
|
|
642
|
+
break;
|
|
643
|
+
}
|
|
644
|
+
skip += children.length;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
/*
|
|
648
|
+
* The FK behind `probeId` only requires the Probe row to exist. It does
|
|
649
|
+
* NOT require it to belong to this project, and probe ids reach the server
|
|
650
|
+
* from the browser (the site form's dropdown posts one), so without this
|
|
651
|
+
* check an operator could name another project's probe as this site's
|
|
652
|
+
* default - and NetworkDeviceService would then copy it onto every device
|
|
653
|
+
* created into the site, handing that project's probe a target list inside
|
|
654
|
+
* this one.
|
|
655
|
+
*
|
|
656
|
+
* A GLOBAL probe has no project and is attachable anywhere, which is why
|
|
657
|
+
* this delegates to ProbeService rather than comparing projectIds: the
|
|
658
|
+
* same predicate that decides which probes a monitor may use decides which
|
|
659
|
+
* probe a site may default to.
|
|
660
|
+
*/
|
|
661
|
+
async assertProbeIsAttachableToProject(data) {
|
|
662
|
+
if (!data.projectId) {
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
const isAttachable = await ProbeService.isProbeAttachableToProject({
|
|
666
|
+
probeId: data.probeId,
|
|
667
|
+
projectId: data.projectId,
|
|
668
|
+
});
|
|
669
|
+
if (!isAttachable) {
|
|
670
|
+
throw new BadDataException("Probe not found or it does not belong to this project.");
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
/*
|
|
674
|
+
* Same hole as the probe above, and the consequence is worse: a site's
|
|
675
|
+
* credential profile is read LIVE at poll time for every device in the
|
|
676
|
+
* site that has no credentials of its own
|
|
677
|
+
* (NetworkDeviceHydrationUtil.resolveSnmpCredentials), so a cross-project
|
|
678
|
+
* reference here would put another project's community string on this
|
|
679
|
+
* project's probe's wire. The resolver drops such a reference as a
|
|
680
|
+
* backstop; this is the half that stops it being written at all.
|
|
681
|
+
*/
|
|
682
|
+
async assertSnmpCredentialProfileBelongsToProject(data) {
|
|
683
|
+
if (!data.projectId) {
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
686
|
+
const profile = await NetworkSnmpCredentialProfileService.findOneById({
|
|
687
|
+
id: data.snmpCredentialProfileId,
|
|
688
|
+
select: {
|
|
689
|
+
_id: true,
|
|
690
|
+
projectId: true,
|
|
691
|
+
},
|
|
692
|
+
props: {
|
|
693
|
+
isRoot: true,
|
|
694
|
+
},
|
|
695
|
+
});
|
|
696
|
+
if (!profile) {
|
|
697
|
+
throw new BadDataException("SNMP Credential Profile not found.");
|
|
698
|
+
}
|
|
699
|
+
if (profile.projectId && !sameId(profile.projectId, data.projectId)) {
|
|
700
|
+
throw new BadDataException("SNMP Credential Profile must belong to the same project.");
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
/*
|
|
704
|
+
* The site's default probe, inherited: this site's own `probeId`, or the
|
|
705
|
+
* nearest ancestor that has one.
|
|
706
|
+
*
|
|
707
|
+
* Copy-at-write, not read-through — NetworkDeviceService calls this once,
|
|
708
|
+
* when a device is created into or moved to a site with no probe of its
|
|
709
|
+
* own, and stamps the answer on the device. That is what makes editing a
|
|
710
|
+
* site's default a decision about FUTURE devices only: nothing re-reads
|
|
711
|
+
* this, so no site edit can silently re-point a fleet that is already
|
|
712
|
+
* polling.
|
|
713
|
+
*
|
|
714
|
+
* Nearest ancestor wins, so a Region's probe covers every Market under it
|
|
715
|
+
* while a Market that names its own overrides it for its own subtree.
|
|
716
|
+
* `getAncestorIds` returns root-first, hence the reverse walk.
|
|
717
|
+
*/
|
|
718
|
+
async resolveDefaultProbeIdForSite(siteId) {
|
|
719
|
+
const site = await this.findOneById({
|
|
720
|
+
id: siteId,
|
|
721
|
+
select: {
|
|
722
|
+
_id: true,
|
|
723
|
+
probeId: true,
|
|
724
|
+
parentSiteId: true,
|
|
725
|
+
},
|
|
726
|
+
props: {
|
|
727
|
+
isRoot: true,
|
|
728
|
+
},
|
|
729
|
+
});
|
|
730
|
+
if (!site) {
|
|
731
|
+
return null;
|
|
732
|
+
}
|
|
733
|
+
if (site.probeId) {
|
|
734
|
+
return site.probeId;
|
|
735
|
+
}
|
|
736
|
+
/*
|
|
737
|
+
* A root site has no ancestors, so there is nothing above it to inherit
|
|
738
|
+
* from. Short-circuited here rather than left to getAncestorIds because
|
|
739
|
+
* that call is not free: it resolves — and, for a row whose path is
|
|
740
|
+
* missing or stale, REBUILDS AND PERSISTS — the materialized path. This
|
|
741
|
+
* runs on the device create path, where most sites are roots and no
|
|
742
|
+
* device write should be paying for hierarchy maintenance it cannot use.
|
|
743
|
+
*/
|
|
744
|
+
if (!site.parentSiteId) {
|
|
745
|
+
return null;
|
|
746
|
+
}
|
|
747
|
+
const ancestorIds = await this.getAncestorIds(siteId);
|
|
748
|
+
if (ancestorIds.length === 0) {
|
|
749
|
+
return null;
|
|
750
|
+
}
|
|
751
|
+
const ancestors = await this.findBy({
|
|
752
|
+
query: {
|
|
753
|
+
_id: QueryHelper.any(ancestorIds.map((ancestorId) => {
|
|
754
|
+
return ancestorId.toString();
|
|
755
|
+
})),
|
|
756
|
+
},
|
|
757
|
+
select: {
|
|
758
|
+
_id: true,
|
|
759
|
+
probeId: true,
|
|
760
|
+
},
|
|
761
|
+
limit: LIMIT_MAX,
|
|
762
|
+
skip: 0,
|
|
763
|
+
props: {
|
|
764
|
+
isRoot: true,
|
|
765
|
+
},
|
|
766
|
+
});
|
|
767
|
+
const probeIdBySiteId = new Map();
|
|
768
|
+
for (const ancestor of ancestors) {
|
|
769
|
+
if (ancestor.id && ancestor.probeId) {
|
|
770
|
+
probeIdBySiteId.set(ancestor.id.toString(), ancestor.probeId);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
for (let index = ancestorIds.length - 1; index >= 0; index--) {
|
|
774
|
+
const probeId = probeIdBySiteId.get(ancestorIds[index].toString());
|
|
775
|
+
if (probeId) {
|
|
776
|
+
return probeId;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
return null;
|
|
780
|
+
}
|
|
173
781
|
async onBeforeCreate(createBy) {
|
|
174
782
|
let parentPath = null;
|
|
783
|
+
let parentSite = null;
|
|
784
|
+
const rawData = createBy.data;
|
|
785
|
+
const projectId = createBy.props.tenantId ||
|
|
786
|
+
RelationIdUtil.readConsistent(rawData, ["projectId", "project"], "Project") ||
|
|
787
|
+
undefined;
|
|
175
788
|
/*
|
|
176
789
|
* Both spellings: the dashboard's site form posts the `parentSite`
|
|
177
790
|
* relation, not the `parentSiteId` column. See RelationIdUtil.
|
|
178
791
|
*/
|
|
179
|
-
const parentSiteId =
|
|
792
|
+
const parentSiteId = readStrictRelationId({
|
|
793
|
+
payload: rawData,
|
|
794
|
+
keys: PARENT_SITE_KEYS,
|
|
795
|
+
relationTitle: "Parent Site",
|
|
796
|
+
});
|
|
797
|
+
const networkSiteTypeId = readStrictRelationId({
|
|
798
|
+
payload: rawData,
|
|
799
|
+
keys: NETWORK_SITE_TYPE_KEYS,
|
|
800
|
+
relationTitle: "Network Site Type",
|
|
801
|
+
});
|
|
180
802
|
if (parentSiteId) {
|
|
181
|
-
|
|
803
|
+
parentSite = await this.findOneById({
|
|
182
804
|
id: parentSiteId,
|
|
183
805
|
select: {
|
|
184
806
|
_id: true,
|
|
185
807
|
projectId: true,
|
|
808
|
+
networkSiteTypeId: true,
|
|
186
809
|
},
|
|
187
810
|
props: {
|
|
188
811
|
isRoot: true,
|
|
189
812
|
},
|
|
190
813
|
});
|
|
191
|
-
if (!
|
|
814
|
+
if (!parentSite) {
|
|
192
815
|
throw new BadDataException("Parent site not found.");
|
|
193
816
|
}
|
|
194
|
-
if (
|
|
195
|
-
|
|
196
|
-
|
|
817
|
+
if (projectId &&
|
|
818
|
+
parentSite.projectId &&
|
|
819
|
+
!sameId(parentSite.projectId, projectId)) {
|
|
197
820
|
throw new BadDataException("Parent site must belong to the same project.");
|
|
198
821
|
}
|
|
822
|
+
}
|
|
823
|
+
await this.validateSiteTypeEdge({
|
|
824
|
+
networkSiteTypeId: networkSiteTypeId,
|
|
825
|
+
parentSite: parentSite,
|
|
826
|
+
projectId: projectId,
|
|
827
|
+
typeCache: new Map(),
|
|
828
|
+
});
|
|
829
|
+
/*
|
|
830
|
+
* The monitoring defaults are tenant-checked on the way in, in both
|
|
831
|
+
* spellings. See the constants for why a bad value here is not confined
|
|
832
|
+
* to this row.
|
|
833
|
+
*/
|
|
834
|
+
const probeId = readStrictRelationId({
|
|
835
|
+
payload: rawData,
|
|
836
|
+
keys: PROBE_KEYS,
|
|
837
|
+
relationTitle: "Probe",
|
|
838
|
+
});
|
|
839
|
+
if (probeId) {
|
|
840
|
+
await this.assertProbeIsAttachableToProject({
|
|
841
|
+
probeId: probeId,
|
|
842
|
+
projectId: projectId,
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
const snmpCredentialProfileId = readStrictRelationId({
|
|
846
|
+
payload: rawData,
|
|
847
|
+
keys: SNMP_CREDENTIAL_PROFILE_KEYS,
|
|
848
|
+
relationTitle: "SNMP Credential Profile",
|
|
849
|
+
});
|
|
850
|
+
if (snmpCredentialProfileId) {
|
|
851
|
+
await this.assertSnmpCredentialProfileBelongsToProject({
|
|
852
|
+
snmpCredentialProfileId: snmpCredentialProfileId,
|
|
853
|
+
projectId: projectId,
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
if (parentSiteId) {
|
|
199
857
|
parentPath = await this.getMaterializedPathForSite(parentSiteId);
|
|
200
858
|
}
|
|
201
859
|
return {
|
|
@@ -224,25 +882,85 @@ export class Service extends DatabaseService {
|
|
|
224
882
|
return createdItem;
|
|
225
883
|
}
|
|
226
884
|
async onBeforeUpdate(updateBy) {
|
|
227
|
-
const
|
|
228
|
-
|
|
885
|
+
const rawData = updateBy.data;
|
|
886
|
+
const touchesParent = isRelationWritten(rawData, PARENT_SITE_KEYS);
|
|
887
|
+
const touchesNetworkSiteType = isRelationWritten(rawData, NETWORK_SITE_TYPE_KEYS);
|
|
888
|
+
const touchesProject = isRelationWritten(rawData, PROJECT_KEYS);
|
|
889
|
+
const touchesMaterializedHierarchy = isRelationWritten(rawData, MATERIALIZED_HIERARCHY_KEYS);
|
|
890
|
+
/*
|
|
891
|
+
* These two have to be named in the early return, and that is the whole
|
|
892
|
+
* reason they are here. Setting a site's default probe or credential
|
|
893
|
+
* profile touches neither the parent nor the type, so a tenancy guard
|
|
894
|
+
* placed below the return would be dead code on exactly the write it
|
|
895
|
+
* exists for — the shape the site settings form actually posts.
|
|
896
|
+
*/
|
|
897
|
+
const touchesProbe = isRelationWritten(rawData, PROBE_KEYS);
|
|
898
|
+
const touchesSnmpCredentialProfile = isRelationWritten(rawData, SNMP_CREDENTIAL_PROFILE_KEYS);
|
|
899
|
+
if (!touchesParent &&
|
|
900
|
+
!touchesNetworkSiteType &&
|
|
901
|
+
!touchesProject &&
|
|
902
|
+
!touchesMaterializedHierarchy &&
|
|
903
|
+
!touchesProbe &&
|
|
904
|
+
!touchesSnmpCredentialProfile) {
|
|
229
905
|
return { updateBy, carryForward: null };
|
|
230
906
|
}
|
|
231
|
-
|
|
907
|
+
if (touchesMaterializedHierarchy) {
|
|
908
|
+
throw new BadDataException("materializedPath and depth are managed by the Network Site hierarchy and cannot be updated directly.");
|
|
909
|
+
}
|
|
910
|
+
const proposedProjectId = touchesProject
|
|
911
|
+
? readStrictRelationId({
|
|
912
|
+
payload: rawData,
|
|
913
|
+
keys: PROJECT_KEYS,
|
|
914
|
+
relationTitle: "Project",
|
|
915
|
+
})
|
|
916
|
+
: null;
|
|
917
|
+
if (touchesProject && !proposedProjectId) {
|
|
918
|
+
throw new BadDataException("A Network Site cannot be moved to another project.");
|
|
919
|
+
}
|
|
920
|
+
const newParentId = touchesParent
|
|
921
|
+
? readStrictRelationId({
|
|
922
|
+
payload: rawData,
|
|
923
|
+
keys: PARENT_SITE_KEYS,
|
|
924
|
+
relationTitle: "Parent Site",
|
|
925
|
+
})
|
|
926
|
+
: null;
|
|
927
|
+
const newNetworkSiteTypeId = touchesNetworkSiteType
|
|
928
|
+
? readStrictRelationId({
|
|
929
|
+
payload: rawData,
|
|
930
|
+
keys: NETWORK_SITE_TYPE_KEYS,
|
|
931
|
+
relationTitle: "Network Site Type",
|
|
932
|
+
})
|
|
933
|
+
: null;
|
|
934
|
+
const updateLimit = updateBy.limit instanceof PositiveNumber
|
|
935
|
+
? updateBy.limit.toNumber()
|
|
936
|
+
: updateBy.limit || LIMIT_MAX;
|
|
937
|
+
const updateSkip = updateBy.skip instanceof PositiveNumber
|
|
938
|
+
? updateBy.skip.toNumber()
|
|
939
|
+
: updateBy.skip || 0;
|
|
232
940
|
const previousItems = await this.findBy({
|
|
233
941
|
query: this.scopeQueryToCallerTenant(updateBy.query, updateBy.props),
|
|
234
942
|
select: {
|
|
235
943
|
_id: true,
|
|
236
944
|
projectId: true,
|
|
237
945
|
parentSiteId: true,
|
|
946
|
+
networkSiteTypeId: true,
|
|
238
947
|
materializedPath: true,
|
|
239
948
|
},
|
|
240
|
-
limit:
|
|
241
|
-
skip:
|
|
949
|
+
limit: updateLimit,
|
|
950
|
+
skip: updateSkip,
|
|
242
951
|
props: {
|
|
243
952
|
isRoot: true,
|
|
244
953
|
},
|
|
245
954
|
});
|
|
955
|
+
if (touchesProject) {
|
|
956
|
+
for (const item of previousItems) {
|
|
957
|
+
if (!item.projectId ||
|
|
958
|
+
!proposedProjectId ||
|
|
959
|
+
!sameId(item.projectId, proposedProjectId)) {
|
|
960
|
+
throw new BadDataException("A Network Site cannot be moved to another project.");
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
}
|
|
246
964
|
/*
|
|
247
965
|
* Same-project assertion for EVERY parentSiteId write, including the
|
|
248
966
|
* detach case (parentSiteId: null) which has no parent to compare
|
|
@@ -252,33 +970,84 @@ export class Service extends DatabaseService {
|
|
|
252
970
|
if (updateBy.props.tenantId) {
|
|
253
971
|
for (const item of previousItems) {
|
|
254
972
|
if (item.projectId &&
|
|
255
|
-
item.projectId
|
|
973
|
+
!sameId(item.projectId, updateBy.props.tenantId)) {
|
|
256
974
|
throw new BadDataException("Network site must belong to the same project.");
|
|
257
975
|
}
|
|
258
976
|
}
|
|
259
977
|
}
|
|
978
|
+
/*
|
|
979
|
+
* One check per DISTINCT project in the matched set, because a single
|
|
980
|
+
* updateBy can span more than one project when a root caller issues it,
|
|
981
|
+
* and the payload names one probe / one profile for all of them. Reading
|
|
982
|
+
* the ids here (rather than above the previousItems read) keeps a
|
|
983
|
+
* conflicting-spelling payload refused on every write shape.
|
|
984
|
+
*/
|
|
985
|
+
if (touchesProbe || touchesSnmpCredentialProfile) {
|
|
986
|
+
const newProbeId = touchesProbe
|
|
987
|
+
? readStrictRelationId({
|
|
988
|
+
payload: rawData,
|
|
989
|
+
keys: PROBE_KEYS,
|
|
990
|
+
relationTitle: "Probe",
|
|
991
|
+
})
|
|
992
|
+
: null;
|
|
993
|
+
const newSnmpCredentialProfileId = touchesSnmpCredentialProfile
|
|
994
|
+
? readStrictRelationId({
|
|
995
|
+
payload: rawData,
|
|
996
|
+
keys: SNMP_CREDENTIAL_PROFILE_KEYS,
|
|
997
|
+
relationTitle: "SNMP Credential Profile",
|
|
998
|
+
})
|
|
999
|
+
: null;
|
|
1000
|
+
// A clear (null) points at nothing and has nothing to check.
|
|
1001
|
+
if (newProbeId || newSnmpCredentialProfileId) {
|
|
1002
|
+
const checkedProjectIds = new Set();
|
|
1003
|
+
for (const item of previousItems) {
|
|
1004
|
+
if (!item.projectId ||
|
|
1005
|
+
checkedProjectIds.has(normalizeId(item.projectId))) {
|
|
1006
|
+
continue;
|
|
1007
|
+
}
|
|
1008
|
+
checkedProjectIds.add(normalizeId(item.projectId));
|
|
1009
|
+
if (newProbeId) {
|
|
1010
|
+
await this.assertProbeIsAttachableToProject({
|
|
1011
|
+
probeId: newProbeId,
|
|
1012
|
+
projectId: item.projectId,
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
if (newSnmpCredentialProfileId) {
|
|
1016
|
+
await this.assertSnmpCredentialProfileBelongsToProject({
|
|
1017
|
+
snmpCredentialProfileId: newSnmpCredentialProfileId,
|
|
1018
|
+
projectId: item.projectId,
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
if (!touchesParent && !touchesNetworkSiteType) {
|
|
1025
|
+
return { updateBy, carryForward: null };
|
|
1026
|
+
}
|
|
260
1027
|
let newParentPath = null;
|
|
261
|
-
|
|
262
|
-
|
|
1028
|
+
let newParent = null;
|
|
1029
|
+
if (touchesParent && newParentId) {
|
|
1030
|
+
newParent = await this.findOneById({
|
|
263
1031
|
id: newParentId,
|
|
264
1032
|
select: {
|
|
265
1033
|
_id: true,
|
|
266
1034
|
projectId: true,
|
|
1035
|
+
networkSiteTypeId: true,
|
|
267
1036
|
},
|
|
268
1037
|
props: {
|
|
269
1038
|
isRoot: true,
|
|
270
1039
|
},
|
|
271
1040
|
});
|
|
272
|
-
if (!
|
|
1041
|
+
if (!newParent) {
|
|
273
1042
|
throw new BadDataException("Parent site not found.");
|
|
274
1043
|
}
|
|
275
1044
|
for (const item of previousItems) {
|
|
276
|
-
if (item.id && item.id
|
|
1045
|
+
if (item.id && sameId(item.id, newParentId)) {
|
|
277
1046
|
throw new BadDataException("A site cannot be its own parent.");
|
|
278
1047
|
}
|
|
279
1048
|
if (item.projectId &&
|
|
280
|
-
|
|
281
|
-
item.projectId
|
|
1049
|
+
newParent.projectId &&
|
|
1050
|
+
!sameId(item.projectId, newParent.projectId)) {
|
|
282
1051
|
throw new BadDataException("Parent site must belong to the same project.");
|
|
283
1052
|
}
|
|
284
1053
|
}
|
|
@@ -290,6 +1059,66 @@ export class Service extends DatabaseService {
|
|
|
290
1059
|
}
|
|
291
1060
|
}
|
|
292
1061
|
}
|
|
1062
|
+
const typeCache = new Map();
|
|
1063
|
+
const existingParents = new Map();
|
|
1064
|
+
for (const item of previousItems) {
|
|
1065
|
+
let proposedParent = null;
|
|
1066
|
+
if (touchesParent) {
|
|
1067
|
+
proposedParent = newParent;
|
|
1068
|
+
}
|
|
1069
|
+
else if (item.parentSiteId) {
|
|
1070
|
+
const currentParentId = normalizeId(item.parentSiteId);
|
|
1071
|
+
proposedParent = existingParents.get(currentParentId) || null;
|
|
1072
|
+
if (!proposedParent) {
|
|
1073
|
+
proposedParent = await this.findOneById({
|
|
1074
|
+
id: item.parentSiteId,
|
|
1075
|
+
select: {
|
|
1076
|
+
_id: true,
|
|
1077
|
+
projectId: true,
|
|
1078
|
+
networkSiteTypeId: true,
|
|
1079
|
+
},
|
|
1080
|
+
props: {
|
|
1081
|
+
isRoot: true,
|
|
1082
|
+
},
|
|
1083
|
+
});
|
|
1084
|
+
if (!proposedParent) {
|
|
1085
|
+
throw new BadDataException("Parent site not found.");
|
|
1086
|
+
}
|
|
1087
|
+
existingParents.set(currentParentId, proposedParent);
|
|
1088
|
+
}
|
|
1089
|
+
if (item.projectId &&
|
|
1090
|
+
proposedParent.projectId &&
|
|
1091
|
+
!sameId(item.projectId, proposedParent.projectId)) {
|
|
1092
|
+
throw new BadDataException("Parent site must belong to the same project.");
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
const proposedNetworkSiteTypeId = touchesNetworkSiteType
|
|
1096
|
+
? newNetworkSiteTypeId
|
|
1097
|
+
: item.networkSiteTypeId || null;
|
|
1098
|
+
await this.validateSiteTypeEdge({
|
|
1099
|
+
networkSiteTypeId: proposedNetworkSiteTypeId,
|
|
1100
|
+
parentSite: proposedParent,
|
|
1101
|
+
projectId: item.projectId,
|
|
1102
|
+
typeCache: typeCache,
|
|
1103
|
+
});
|
|
1104
|
+
const previousNetworkSiteTypeId = item.networkSiteTypeId
|
|
1105
|
+
? normalizeId(item.networkSiteTypeId)
|
|
1106
|
+
: null;
|
|
1107
|
+
const proposedNetworkSiteTypeIdString = proposedNetworkSiteTypeId
|
|
1108
|
+
? normalizeId(proposedNetworkSiteTypeId)
|
|
1109
|
+
: null;
|
|
1110
|
+
if (touchesNetworkSiteType &&
|
|
1111
|
+
previousNetworkSiteTypeId !== proposedNetworkSiteTypeIdString) {
|
|
1112
|
+
await this.validateDirectChildrenForTypeChange({
|
|
1113
|
+
site: item,
|
|
1114
|
+
proposedNetworkSiteTypeId: proposedNetworkSiteTypeId,
|
|
1115
|
+
typeCache: typeCache,
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
if (!touchesParent) {
|
|
1120
|
+
return { updateBy, carryForward: null };
|
|
1121
|
+
}
|
|
293
1122
|
const carryForward = {
|
|
294
1123
|
previousItems: previousItems,
|
|
295
1124
|
newParentId: newParentId,
|
|
@@ -339,7 +1168,19 @@ export class Service extends DatabaseService {
|
|
|
339
1168
|
const updatedIds = new Set(updatedItemIds.map((id) => {
|
|
340
1169
|
return id.toString();
|
|
341
1170
|
}));
|
|
342
|
-
|
|
1171
|
+
/*
|
|
1172
|
+
* A bulk update can include both an ancestor and one of its descendants.
|
|
1173
|
+
* Move the deepest roots first; otherwise rebasing the ancestor changes
|
|
1174
|
+
* the descendant branch away from the latter's old prefix before its own
|
|
1175
|
+
* subtree has been processed.
|
|
1176
|
+
*/
|
|
1177
|
+
const previousItemsDeepestFirst = [
|
|
1178
|
+
...parentChange.previousItems,
|
|
1179
|
+
].sort((left, right) => {
|
|
1180
|
+
return (MaterializedPathUtil.segmentsOf(right.materializedPath).length -
|
|
1181
|
+
MaterializedPathUtil.segmentsOf(left.materializedPath).length);
|
|
1182
|
+
});
|
|
1183
|
+
for (const previousItem of previousItemsDeepestFirst) {
|
|
343
1184
|
if (!previousItem.id || !updatedIds.has(previousItem.id.toString())) {
|
|
344
1185
|
continue;
|
|
345
1186
|
}
|
|
@@ -358,35 +1199,43 @@ export class Service extends DatabaseService {
|
|
|
358
1199
|
});
|
|
359
1200
|
// ...then its entire subtree in one prefix query.
|
|
360
1201
|
if (oldPath) {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
!descendant.materializedPath ||
|
|
379
|
-
descendant.id.toString() === previousItem.id.toString()) {
|
|
380
|
-
continue;
|
|
381
|
-
}
|
|
382
|
-
const rebasedPath = MaterializedPathUtil.rebasePaths(oldPath, newPath, [descendant.materializedPath])[0];
|
|
383
|
-
await this.updateColumnsByIdWithoutHooks({
|
|
384
|
-
id: descendant.id,
|
|
385
|
-
data: {
|
|
386
|
-
materializedPath: rebasedPath,
|
|
387
|
-
depth: MaterializedPathUtil.depthOf(rebasedPath),
|
|
1202
|
+
while (true) {
|
|
1203
|
+
const descendants = await this.findBy({
|
|
1204
|
+
query: {
|
|
1205
|
+
projectId: previousItem.projectId,
|
|
1206
|
+
materializedPath: this.pathStartsWith(oldPath),
|
|
1207
|
+
},
|
|
1208
|
+
select: {
|
|
1209
|
+
_id: true,
|
|
1210
|
+
materializedPath: true,
|
|
1211
|
+
},
|
|
1212
|
+
sort: {
|
|
1213
|
+
_id: SortOrder.Ascending,
|
|
1214
|
+
},
|
|
1215
|
+
limit: SUBTREE_REBASE_PAGE_SIZE,
|
|
1216
|
+
skip: 0,
|
|
1217
|
+
props: {
|
|
1218
|
+
isRoot: true,
|
|
388
1219
|
},
|
|
389
1220
|
});
|
|
1221
|
+
for (const descendant of descendants) {
|
|
1222
|
+
if (!descendant.id ||
|
|
1223
|
+
!descendant.materializedPath ||
|
|
1224
|
+
descendant.id.toString() === previousItem.id.toString()) {
|
|
1225
|
+
continue;
|
|
1226
|
+
}
|
|
1227
|
+
const rebasedPath = MaterializedPathUtil.rebasePaths(oldPath, newPath, [descendant.materializedPath])[0];
|
|
1228
|
+
await this.updateColumnsByIdWithoutHooks({
|
|
1229
|
+
id: descendant.id,
|
|
1230
|
+
data: {
|
|
1231
|
+
materializedPath: rebasedPath,
|
|
1232
|
+
depth: MaterializedPathUtil.depthOf(rebasedPath),
|
|
1233
|
+
},
|
|
1234
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
if (descendants.length < SUBTREE_REBASE_PAGE_SIZE) {
|
|
1237
|
+
break;
|
|
1238
|
+
}
|
|
390
1239
|
}
|
|
391
1240
|
}
|
|
392
1241
|
/*
|
|
@@ -417,35 +1266,97 @@ export class Service extends DatabaseService {
|
|
|
417
1266
|
* checked.
|
|
418
1267
|
*/
|
|
419
1268
|
async onBeforeDelete(deleteBy) {
|
|
1269
|
+
const deleteLimit = deleteBy.limit instanceof PositiveNumber
|
|
1270
|
+
? deleteBy.limit.toNumber()
|
|
1271
|
+
: deleteBy.limit || LIMIT_MAX;
|
|
1272
|
+
const deleteSkip = deleteBy.skip instanceof PositiveNumber
|
|
1273
|
+
? deleteBy.skip.toNumber()
|
|
1274
|
+
: deleteBy.skip || 0;
|
|
420
1275
|
const sitesToDelete = await this.findBy({
|
|
421
|
-
query: this.
|
|
1276
|
+
query: this.scopeDeleteQueryToCallerTenant(deleteBy.query, deleteBy.props),
|
|
422
1277
|
select: {
|
|
423
1278
|
_id: true,
|
|
424
1279
|
projectId: true,
|
|
425
1280
|
parentSiteId: true,
|
|
426
1281
|
materializedPath: true,
|
|
427
1282
|
},
|
|
428
|
-
limit:
|
|
429
|
-
skip:
|
|
1283
|
+
limit: deleteLimit,
|
|
1284
|
+
skip: deleteSkip,
|
|
430
1285
|
props: {
|
|
431
1286
|
isRoot: true,
|
|
432
1287
|
},
|
|
433
1288
|
});
|
|
1289
|
+
const deletingSiteIds = new Set(sitesToDelete
|
|
1290
|
+
.map((site) => {
|
|
1291
|
+
return site.id ? normalizeId(site.id) : null;
|
|
1292
|
+
})
|
|
1293
|
+
.filter((siteId) => {
|
|
1294
|
+
return Boolean(siteId);
|
|
1295
|
+
}));
|
|
1296
|
+
const deletingSiteIdList = Array.from(deletingSiteIds);
|
|
1297
|
+
const deletingProjectIdList = Array.from(new Set(sitesToDelete
|
|
1298
|
+
.map((site) => {
|
|
1299
|
+
return site.projectId ? normalizeId(site.projectId) : null;
|
|
1300
|
+
})
|
|
1301
|
+
.filter((projectId) => {
|
|
1302
|
+
return Boolean(projectId);
|
|
1303
|
+
})));
|
|
1304
|
+
/*
|
|
1305
|
+
* A valid child type explicitly names the deleted site's type as its
|
|
1306
|
+
* required direct parent type. Legacy SET NULL/orphan-repair behaviour
|
|
1307
|
+
* therefore cannot produce a valid edge: promoting the child to root or
|
|
1308
|
+
* attaching it to the grandparent both violate its type. Reject the
|
|
1309
|
+
* delete unless every direct child is part of this same bulk delete.
|
|
1310
|
+
*
|
|
1311
|
+
* Parent ids and result rows are both batched so neither a wide delete nor
|
|
1312
|
+
* a wide site is silently truncated at a service query limit.
|
|
1313
|
+
*/
|
|
1314
|
+
for (let parentIdOffset = 0; parentIdOffset < deletingSiteIdList.length; parentIdOffset += DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE) {
|
|
1315
|
+
const parentIdBatch = deletingSiteIdList.slice(parentIdOffset, parentIdOffset + DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE);
|
|
1316
|
+
let childSkip = 0;
|
|
1317
|
+
while (true) {
|
|
1318
|
+
const directChildren = await this.findBy({
|
|
1319
|
+
query: {
|
|
1320
|
+
projectId: QueryHelper.any(deletingProjectIdList),
|
|
1321
|
+
parentSiteId: QueryHelper.any(parentIdBatch),
|
|
1322
|
+
},
|
|
1323
|
+
select: {
|
|
1324
|
+
_id: true,
|
|
1325
|
+
parentSiteId: true,
|
|
1326
|
+
},
|
|
1327
|
+
sort: {
|
|
1328
|
+
_id: SortOrder.Ascending,
|
|
1329
|
+
},
|
|
1330
|
+
limit: DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE,
|
|
1331
|
+
skip: childSkip,
|
|
1332
|
+
props: {
|
|
1333
|
+
isRoot: true,
|
|
1334
|
+
},
|
|
1335
|
+
});
|
|
1336
|
+
const hasSurvivingChild = directChildren.some((child) => {
|
|
1337
|
+
return !child.id || !deletingSiteIds.has(normalizeId(child.id));
|
|
1338
|
+
});
|
|
1339
|
+
if (hasSurvivingChild) {
|
|
1340
|
+
throw new BadDataException("A network site with child sites cannot be deleted. Move or delete its child sites first.");
|
|
1341
|
+
}
|
|
1342
|
+
if (directChildren.length < DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE) {
|
|
1343
|
+
break;
|
|
1344
|
+
}
|
|
1345
|
+
childSkip += directChildren.length;
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
434
1348
|
const carryForward = {
|
|
435
1349
|
sitesToDelete: sitesToDelete,
|
|
436
1350
|
};
|
|
437
1351
|
return { deleteBy, carryForward };
|
|
438
1352
|
}
|
|
439
1353
|
/*
|
|
440
|
-
*
|
|
441
|
-
*
|
|
442
|
-
*
|
|
443
|
-
*
|
|
444
|
-
*
|
|
445
|
-
* materializedPath
|
|
446
|
-
* counting every outage. Re-attach the orphans to the deleted site's own
|
|
447
|
-
* parent - NULL when it was a root, which is exactly what the FK did - and
|
|
448
|
-
* rebase the subtree paths so both readers agree again.
|
|
1354
|
+
* New schemas use a non-nullifying foreign key and onBeforeDelete rejects
|
|
1355
|
+
* surviving children, so this repair is normally a no-op. Keep it as a
|
|
1356
|
+
* defensive bridge for a database that has not applied the FK migration
|
|
1357
|
+
* yet, or for a legacy write already in flight during an upgrade: reattach
|
|
1358
|
+
* any detached children and rebase their subtree paths so parentSiteId and
|
|
1359
|
+
* materializedPath agree.
|
|
449
1360
|
*/
|
|
450
1361
|
async onDeleteSuccess(onDelete, itemIdsBeforeDelete) {
|
|
451
1362
|
const carryForward = onDelete.carryForward || null;
|
|
@@ -493,47 +1404,55 @@ export class Service extends DatabaseService {
|
|
|
493
1404
|
? await this.getMaterializedPathForSite(deletedSite.parentSiteId)
|
|
494
1405
|
: null;
|
|
495
1406
|
const deletedDepth = MaterializedPathUtil.segmentsOf(oldPath).length;
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
1407
|
+
while (true) {
|
|
1408
|
+
const descendants = await this.findBy({
|
|
1409
|
+
query: {
|
|
1410
|
+
projectId: deletedSite.projectId,
|
|
1411
|
+
materializedPath: this.pathStartsWith(oldPath),
|
|
1412
|
+
},
|
|
1413
|
+
select: {
|
|
1414
|
+
_id: true,
|
|
1415
|
+
materializedPath: true,
|
|
1416
|
+
},
|
|
1417
|
+
sort: {
|
|
1418
|
+
_id: SortOrder.Ascending,
|
|
1419
|
+
},
|
|
1420
|
+
limit: SUBTREE_REBASE_PAGE_SIZE,
|
|
1421
|
+
skip: 0,
|
|
1422
|
+
props: {
|
|
1423
|
+
isRoot: true,
|
|
1424
|
+
},
|
|
1425
|
+
});
|
|
1426
|
+
for (const descendant of descendants) {
|
|
1427
|
+
if (!descendant.id ||
|
|
1428
|
+
!descendant.materializedPath ||
|
|
1429
|
+
descendant.id.toString() === deletedSite.id.toString()) {
|
|
1430
|
+
continue;
|
|
1431
|
+
}
|
|
1432
|
+
const tailSegments = MaterializedPathUtil.segmentsOf(descendant.materializedPath).slice(deletedDepth);
|
|
1433
|
+
if (tailSegments.length === 0) {
|
|
1434
|
+
continue;
|
|
1435
|
+
}
|
|
1436
|
+
let rebasedPath = parentPath;
|
|
1437
|
+
for (const segment of tailSegments) {
|
|
1438
|
+
rebasedPath = MaterializedPathUtil.buildPath(rebasedPath, segment);
|
|
1439
|
+
}
|
|
1440
|
+
const updateData = {
|
|
1441
|
+
materializedPath: rebasedPath,
|
|
1442
|
+
depth: MaterializedPathUtil.depthOf(rebasedPath),
|
|
1443
|
+
};
|
|
1444
|
+
// A direct child is the one the FK just detached - give it a parent back.
|
|
1445
|
+
if (tailSegments.length === 1) {
|
|
1446
|
+
updateData["parentSiteId"] = deletedSite.parentSiteId || null;
|
|
1447
|
+
}
|
|
1448
|
+
await this.updateColumnsByIdWithoutHooks({
|
|
1449
|
+
id: descendant.id,
|
|
1450
|
+
data: updateData,
|
|
1451
|
+
});
|
|
524
1452
|
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
depth: MaterializedPathUtil.depthOf(rebasedPath),
|
|
528
|
-
};
|
|
529
|
-
// A direct child is the one the FK just detached - give it a parent back.
|
|
530
|
-
if (tailSegments.length === 1) {
|
|
531
|
-
data["parentSiteId"] = deletedSite.parentSiteId || null;
|
|
1453
|
+
if (descendants.length < SUBTREE_REBASE_PAGE_SIZE) {
|
|
1454
|
+
break;
|
|
532
1455
|
}
|
|
533
|
-
await this.updateColumnsByIdWithoutHooks({
|
|
534
|
-
id: descendant.id,
|
|
535
|
-
data: data,
|
|
536
|
-
});
|
|
537
1456
|
}
|
|
538
1457
|
/*
|
|
539
1458
|
* The deleted site's own devices were detached by their FK too, so the
|
|
@@ -1243,8 +2162,11 @@ export class Service extends DatabaseService {
|
|
|
1243
2162
|
* ------------------------------------------------------------------
|
|
1244
2163
|
*/
|
|
1245
2164
|
/*
|
|
1246
|
-
* Called
|
|
1247
|
-
*
|
|
2165
|
+
* Called after a monitor's current status persists - from
|
|
2166
|
+
* MonitorStatusTimelineService.onCreateSuccess / onDeleteSuccess (the one
|
|
2167
|
+
* path every status change, probe-driven or manual, passes through) and
|
|
2168
|
+
* from MonitorService.refreshMonitorCurrentStatus when a repair moves the
|
|
2169
|
+
* id. Resolves which NetworkDevices these monitors report on, stamps those
|
|
1248
2170
|
* devices' currentMonitorStatusId, then recomputes the rollup for every
|
|
1249
2171
|
* affected site chain. Never throws - a rollup failure must never break a
|
|
1250
2172
|
* monitor status change.
|
|
@@ -1258,6 +2180,26 @@ export class Service extends DatabaseService {
|
|
|
1258
2180
|
* monitor-backed path (monitoringMethod "Monitor") for gear that does
|
|
1259
2181
|
* not speak SNMP, so ANY monitor type qualifies — a Ping monitor on an
|
|
1260
2182
|
* access point is the whole point of it.
|
|
2183
|
+
*
|
|
2184
|
+
* What gets stamped depends on how the device is monitored:
|
|
2185
|
+
*
|
|
2186
|
+
* - every device gets currentMonitorStatusId, which the pill, the site
|
|
2187
|
+
* rollup and the topology node read.
|
|
2188
|
+
* - a MONITOR-BACKED device also gets isReachable, derived from the
|
|
2189
|
+
* status row (`!isOfflineState`, the same offline-end reading
|
|
2190
|
+
* DeviceReachabilityUtil uses). Nothing polls such a device, so the
|
|
2191
|
+
* column is NULL forever otherwise - and the device list's summary
|
|
2192
|
+
* tiles and its Status filter count and filter on isReachable in SQL,
|
|
2193
|
+
* which is why a bound ping-only device sat under "Pending" there while
|
|
2194
|
+
* its own pill said Up. The server keeps the two in sync so the list
|
|
2195
|
+
* agrees with itself.
|
|
2196
|
+
* - an SNMP device's isReachable is left alone: the walk owns it
|
|
2197
|
+
* (NetworkInventoryUtil.updateFromWalk), and a Network Device monitor
|
|
2198
|
+
* going Degraded must not overwrite what the probe actually found.
|
|
2199
|
+
*
|
|
2200
|
+
* The status row is read at most once per call, and only when at least one
|
|
2201
|
+
* collected device is monitor-backed, so an all-SNMP estate costs no extra
|
|
2202
|
+
* query.
|
|
1261
2203
|
*/
|
|
1262
2204
|
async onMonitorStatusChanged(data) {
|
|
1263
2205
|
try {
|
|
@@ -1306,6 +2248,8 @@ export class Service extends DatabaseService {
|
|
|
1306
2248
|
select: {
|
|
1307
2249
|
_id: true,
|
|
1308
2250
|
siteId: true,
|
|
2251
|
+
// Decides whether isReachable is stamped alongside the status.
|
|
2252
|
+
monitoringMethod: true,
|
|
1309
2253
|
},
|
|
1310
2254
|
limit: LIMIT_MAX,
|
|
1311
2255
|
skip: 0,
|
|
@@ -1322,6 +2266,8 @@ export class Service extends DatabaseService {
|
|
|
1322
2266
|
select: {
|
|
1323
2267
|
_id: true,
|
|
1324
2268
|
siteId: true,
|
|
2269
|
+
// Decides whether isReachable is stamped alongside the status.
|
|
2270
|
+
monitoringMethod: true,
|
|
1325
2271
|
},
|
|
1326
2272
|
limit: LIMIT_MAX,
|
|
1327
2273
|
skip: 0,
|
|
@@ -1333,15 +2279,65 @@ export class Service extends DatabaseService {
|
|
|
1333
2279
|
if (devices.length === 0) {
|
|
1334
2280
|
return;
|
|
1335
2281
|
}
|
|
2282
|
+
/*
|
|
2283
|
+
* Resolve the status row lazily - once, and only if a monitor-backed
|
|
2284
|
+
* device is in the set - because it is only needed to derive
|
|
2285
|
+
* isReachable, and the SNMP-only case must stay one query cheaper.
|
|
2286
|
+
*
|
|
2287
|
+
* `undefined` afterwards means "do not touch isReachable": either no
|
|
2288
|
+
* device needs it, or the row could not be found in this project (a
|
|
2289
|
+
* status deleted between the timeline write and this call, or one
|
|
2290
|
+
* from another tenant). The id is still stamped in that case so the
|
|
2291
|
+
* pill keeps moving; a stale reachability is the lesser harm next to
|
|
2292
|
+
* a device that stops reporting altogether.
|
|
2293
|
+
*/
|
|
2294
|
+
const hasMonitorBackedDevice = devices.some((device) => {
|
|
2295
|
+
return NetworkDeviceMonitoringMethodUtil.isMonitorBacked(device.monitoringMethod);
|
|
2296
|
+
});
|
|
2297
|
+
let monitorBackedIsReachable = undefined;
|
|
2298
|
+
if (hasMonitorBackedDevice) {
|
|
2299
|
+
const status = await MonitorStatusService.findOneBy({
|
|
2300
|
+
query: {
|
|
2301
|
+
_id: data.monitorStatusId,
|
|
2302
|
+
projectId: data.projectId,
|
|
2303
|
+
},
|
|
2304
|
+
select: {
|
|
2305
|
+
_id: true,
|
|
2306
|
+
isOfflineState: true,
|
|
2307
|
+
},
|
|
2308
|
+
props: {
|
|
2309
|
+
isRoot: true,
|
|
2310
|
+
},
|
|
2311
|
+
});
|
|
2312
|
+
if (status) {
|
|
2313
|
+
monitorBackedIsReachable = !status.isOfflineState;
|
|
2314
|
+
}
|
|
2315
|
+
else {
|
|
2316
|
+
logger.warn(`NetworkSiteService.onMonitorStatusChanged: monitor status ${data.monitorStatusId.toString()} was not found in project ${data.projectId.toString()}; stamping the status id on the bound network devices but leaving isReachable unchanged.`, {
|
|
2317
|
+
projectId: data.projectId.toString(),
|
|
2318
|
+
monitorStatusId: data.monitorStatusId.toString(),
|
|
2319
|
+
});
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
1336
2322
|
for (const device of devices) {
|
|
1337
2323
|
if (!device.id) {
|
|
1338
2324
|
continue;
|
|
1339
2325
|
}
|
|
2326
|
+
const stamp = {
|
|
2327
|
+
currentMonitorStatusId: data.monitorStatusId,
|
|
2328
|
+
};
|
|
2329
|
+
/*
|
|
2330
|
+
* Only a monitor-backed device gets isReachable from here. The key
|
|
2331
|
+
* is left OUT of the payload for an SNMP device rather than set to
|
|
2332
|
+
* undefined, so the walk's verdict is provably untouched.
|
|
2333
|
+
*/
|
|
2334
|
+
if (monitorBackedIsReachable !== undefined &&
|
|
2335
|
+
NetworkDeviceMonitoringMethodUtil.isMonitorBacked(device.monitoringMethod)) {
|
|
2336
|
+
stamp.isReachable = monitorBackedIsReachable;
|
|
2337
|
+
}
|
|
1340
2338
|
await NetworkDeviceService.updateColumnsByIdWithoutHooks({
|
|
1341
2339
|
id: device.id,
|
|
1342
|
-
data:
|
|
1343
|
-
currentMonitorStatusId: data.monitorStatusId,
|
|
1344
|
-
},
|
|
2340
|
+
data: stamp,
|
|
1345
2341
|
});
|
|
1346
2342
|
}
|
|
1347
2343
|
const distinctSiteIds = new Map();
|
|
@@ -1362,12 +2358,54 @@ export class Service extends DatabaseService {
|
|
|
1362
2358
|
}
|
|
1363
2359
|
}
|
|
1364
2360
|
}
|
|
2361
|
+
__decorate([
|
|
2362
|
+
CaptureSpan(),
|
|
2363
|
+
__metadata("design:type", Function),
|
|
2364
|
+
__metadata("design:paramtypes", [Object]),
|
|
2365
|
+
__metadata("design:returntype", Promise)
|
|
2366
|
+
], Service.prototype, "create", null);
|
|
2367
|
+
__decorate([
|
|
2368
|
+
CaptureSpan(),
|
|
2369
|
+
__metadata("design:type", Function),
|
|
2370
|
+
__metadata("design:paramtypes", [Object]),
|
|
2371
|
+
__metadata("design:returntype", Promise)
|
|
2372
|
+
], Service.prototype, "updateOneBy", null);
|
|
2373
|
+
__decorate([
|
|
2374
|
+
CaptureSpan(),
|
|
2375
|
+
__metadata("design:type", Function),
|
|
2376
|
+
__metadata("design:paramtypes", [Object]),
|
|
2377
|
+
__metadata("design:returntype", Promise)
|
|
2378
|
+
], Service.prototype, "updateBy", null);
|
|
2379
|
+
__decorate([
|
|
2380
|
+
CaptureSpan(),
|
|
2381
|
+
__metadata("design:type", Function),
|
|
2382
|
+
__metadata("design:paramtypes", [Object]),
|
|
2383
|
+
__metadata("design:returntype", Promise)
|
|
2384
|
+
], Service.prototype, "deleteOneBy", null);
|
|
2385
|
+
__decorate([
|
|
2386
|
+
CaptureSpan(),
|
|
2387
|
+
__metadata("design:type", Function),
|
|
2388
|
+
__metadata("design:paramtypes", [Object]),
|
|
2389
|
+
__metadata("design:returntype", Promise)
|
|
2390
|
+
], Service.prototype, "deleteBy", null);
|
|
2391
|
+
__decorate([
|
|
2392
|
+
CaptureSpan(),
|
|
2393
|
+
__metadata("design:type", Function),
|
|
2394
|
+
__metadata("design:paramtypes", [Object]),
|
|
2395
|
+
__metadata("design:returntype", Promise)
|
|
2396
|
+
], Service.prototype, "hardDeleteBy", null);
|
|
1365
2397
|
__decorate([
|
|
1366
2398
|
CaptureSpan(),
|
|
1367
2399
|
__metadata("design:type", Function),
|
|
1368
2400
|
__metadata("design:paramtypes", [Object]),
|
|
1369
2401
|
__metadata("design:returntype", Promise)
|
|
1370
2402
|
], Service.prototype, "getStatusCounts", null);
|
|
2403
|
+
__decorate([
|
|
2404
|
+
CaptureSpan(),
|
|
2405
|
+
__metadata("design:type", Function),
|
|
2406
|
+
__metadata("design:paramtypes", [ObjectID]),
|
|
2407
|
+
__metadata("design:returntype", Promise)
|
|
2408
|
+
], Service.prototype, "resolveDefaultProbeIdForSite", null);
|
|
1371
2409
|
__decorate([
|
|
1372
2410
|
CaptureSpan(),
|
|
1373
2411
|
__metadata("design:type", Function),
|