@oneuptime/common 12.0.32 → 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/EnterpriseLicense.ts +56 -0
- package/Models/DatabaseModels/Index.ts +10 -0
- package/Models/DatabaseModels/Monitor.ts +76 -0
- package/Models/DatabaseModels/NetworkAlertPolicy.ts +690 -0
- package/Models/DatabaseModels/NetworkDevice.ts +176 -1
- package/Models/DatabaseModels/NetworkSite.ts +201 -2
- package/Models/DatabaseModels/NetworkSiteType.ts +102 -3
- package/Models/DatabaseModels/NetworkSnmpCredentialProfile.ts +841 -0
- 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/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 +12 -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/EnterpriseLicenseInstanceService.ts +197 -0
- package/Server/Services/EnterpriseLicenseService.ts +55 -0
- package/Server/Services/Index.ts +10 -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/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 +105 -48
- 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 -25
- 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 +134 -33
- package/Tests/App/Dashboard/AskAiSuggestedPrompts.test.ts +279 -0
- package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +517 -0
- package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +26 -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/MonitorTypePicker.test.tsx +4 -2
- 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 +41 -5
- 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/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/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/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/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/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/ProjectServiceNetworkSiteTypeDefaults.test.ts +214 -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/UserNotificationSettingRollupRouting.test.ts +856 -0
- package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +102 -1
- 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/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/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/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/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +15 -0
- package/Tests/UI/Components/ProgressBar.test.tsx +38 -2
- package/Tests/UI/Components/SideMenuItem.test.tsx +226 -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/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/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/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/Telemetry/CaptureSpanExportGating.test.ts +145 -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/SqlConnectionConfig.ts +31 -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 +90 -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/CommandPalette/CommandPalette.tsx +2 -8
- package/UI/Components/EditionLabel/EditionLabel.tsx +4 -0
- package/UI/Components/Modal/Modal.tsx +2 -8
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +44 -0
- package/UI/Components/ProgressBar/ProgressBar.tsx +12 -1
- package/UI/Components/RadioButtons/BasicRadioButtons.tsx +37 -7
- package/UI/Components/SideMenu/SideMenu.tsx +123 -5
- package/UI/Components/SideMenu/SideMenuItem.tsx +76 -84
- package/UI/Components/SideMenu/SideMenuSection.tsx +55 -23
- 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/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +16 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +191 -11
- package/Utils/Monitor/MonitorMetricType.ts +153 -1
- package/Utils/Monitor/NetworkTopologyUtil.ts +23 -3
- package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +65 -14
- package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +43 -14
- 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/build/dist/Models/AnalyticsModels/Span.js +14 -0
- package/build/dist/Models/AnalyticsModels/Span.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/Index.js +10 -0
- package/build/dist/Models/DatabaseModels/Index.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/NetworkAlertPolicy.js +713 -0
- package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +180 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- 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/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/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 +12 -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/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 +10 -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/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 +66 -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 -20
- 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/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 +80 -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/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/MonitorTemplateVariables/TemplateVariablesCatalog.js +39 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.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/SideMenu.js +67 -5
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js +49 -53
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js +25 -7
- 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/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/NetworkTopologyUtil.js +8 -3
- 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/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/package.json +2 -2
|
@@ -1,10 +1,1226 @@
|
|
|
1
|
+
import CreateBy from "../Types/Database/CreateBy";
|
|
2
|
+
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
3
|
+
import DeleteBy from "../Types/Database/DeleteBy";
|
|
4
|
+
import DeleteOneBy from "../Types/Database/DeleteOneBy";
|
|
5
|
+
import Select from "../Types/Database/Select";
|
|
6
|
+
import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
|
|
7
|
+
import Query from "../Types/Database/Query";
|
|
8
|
+
import QueryHelper from "../Types/Database/QueryHelper";
|
|
9
|
+
import UpdateBy from "../Types/Database/UpdateBy";
|
|
10
|
+
import UpdateOneBy from "../Types/Database/UpdateOneBy";
|
|
1
11
|
import DatabaseService from "./DatabaseService";
|
|
12
|
+
import NetworkSiteService from "./NetworkSiteService";
|
|
13
|
+
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
14
|
+
import RelationIdUtil from "../Utils/Database/RelationIdUtil";
|
|
15
|
+
import NetworkSiteHierarchyLock from "../Utils/NetworkSite/NetworkSiteHierarchyLock";
|
|
2
16
|
import Model from "../../Models/DatabaseModels/NetworkSiteType";
|
|
17
|
+
import NetworkSite from "../../Models/DatabaseModels/NetworkSite";
|
|
18
|
+
import NetworkSiteTypeHierarchyUtil from "../../Utils/NetworkSite/TypeHierarchyUtil";
|
|
19
|
+
import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
20
|
+
import BadDataException from "../../Types/Exception/BadDataException";
|
|
21
|
+
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
22
|
+
import ObjectID from "../../Types/ObjectID";
|
|
23
|
+
import PositiveNumber from "../../Types/PositiveNumber";
|
|
24
|
+
|
|
25
|
+
const PARENT_NETWORK_SITE_TYPE_KEYS: Array<string> = [
|
|
26
|
+
"parentNetworkSiteTypeId",
|
|
27
|
+
"parentNetworkSiteType",
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const PROJECT_KEYS: Array<string> = ["projectId", "project"];
|
|
31
|
+
|
|
32
|
+
const EXISTING_SITES_DO_NOT_MATCH_MESSAGE: string =
|
|
33
|
+
"This site type's parent cannot be changed because existing sites do not match the proposed hierarchy. Create a new site type under the desired parent, then move and reassign the sites to it.";
|
|
34
|
+
|
|
35
|
+
const REFERENCE_VALIDATION_BATCH_SIZE: number = 1000;
|
|
36
|
+
|
|
37
|
+
const normalizeId: (id: ObjectID | string) => string = (
|
|
38
|
+
id: ObjectID | string,
|
|
39
|
+
): string => {
|
|
40
|
+
return id.toString().toLowerCase();
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const sameId: (left: ObjectID | string, right: ObjectID | string) => boolean = (
|
|
44
|
+
left: ObjectID | string,
|
|
45
|
+
right: ObjectID | string,
|
|
46
|
+
): boolean => {
|
|
47
|
+
return normalizeId(left) === normalizeId(right);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/*
|
|
51
|
+
* Model instances contain properties initialised to undefined. Those are
|
|
52
|
+
* omissions, not writes: TypeORM drops them before producing INSERT/SET.
|
|
53
|
+
* Null, on the other hand, is an explicit request to make this a root type.
|
|
54
|
+
*/
|
|
55
|
+
const isAnyKeyWritten: (
|
|
56
|
+
data: Record<string, unknown>,
|
|
57
|
+
keys: Array<string>,
|
|
58
|
+
) => boolean = (
|
|
59
|
+
data: Record<string, unknown>,
|
|
60
|
+
keys: Array<string>,
|
|
61
|
+
): boolean => {
|
|
62
|
+
return keys.some((key: string) => {
|
|
63
|
+
return key in data && data[key] !== undefined;
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const assertNoSqlExpression: (
|
|
68
|
+
data: Record<string, unknown>,
|
|
69
|
+
keys: Array<string>,
|
|
70
|
+
) => void = (data: Record<string, unknown>, keys: Array<string>): void => {
|
|
71
|
+
for (const key of keys) {
|
|
72
|
+
if (typeof data[key] === "function") {
|
|
73
|
+
throw new BadDataException(
|
|
74
|
+
`${key} cannot be set to a raw SQL expression because the site type hierarchy must be validated against an actual parent ID.`,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const assertIsUnitLevelIsNotSqlExpression: (
|
|
81
|
+
data: Record<string, unknown>,
|
|
82
|
+
) => void = (data: Record<string, unknown>): void => {
|
|
83
|
+
if (typeof data["isUnitLevel"] === "function") {
|
|
84
|
+
throw new BadDataException(
|
|
85
|
+
"isUnitLevel cannot be set to a raw SQL expression because unit-level leaf rules must be validated against an actual boolean value.",
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
3
89
|
|
|
4
90
|
export class Service extends DatabaseService<Model> {
|
|
5
91
|
public constructor() {
|
|
6
92
|
super(Model);
|
|
7
93
|
}
|
|
94
|
+
|
|
95
|
+
/*
|
|
96
|
+
* NetworkSite and NetworkSiteType validate one shared graph. Keep the Redis
|
|
97
|
+
* mutex around the complete DatabaseService mutation (before hooks, write,
|
|
98
|
+
* and success hooks), not inside an individual hook, so every error path
|
|
99
|
+
* releases it and a concurrent site/type request cannot validate stale
|
|
100
|
+
* project state.
|
|
101
|
+
*/
|
|
102
|
+
@CaptureSpan()
|
|
103
|
+
public override async create(createBy: CreateBy<Model>): Promise<Model> {
|
|
104
|
+
if (createBy.props.ignoreHooks) {
|
|
105
|
+
return await super.create(createBy);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const projectId: ObjectID | null =
|
|
109
|
+
createBy.props.tenantId ||
|
|
110
|
+
this.readProjectId(createBy.data as unknown as Record<string, unknown>) ||
|
|
111
|
+
null;
|
|
112
|
+
|
|
113
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
114
|
+
projectIds: projectId ? [projectId] : [],
|
|
115
|
+
operation: async (): Promise<Model> => {
|
|
116
|
+
return await super.create(createBy);
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@CaptureSpan()
|
|
122
|
+
public override async updateOneBy(
|
|
123
|
+
updateOneBy: UpdateOneBy<Model>,
|
|
124
|
+
): Promise<number> {
|
|
125
|
+
if (
|
|
126
|
+
updateOneBy.props.ignoreHooks ||
|
|
127
|
+
!this.updateTouchesHierarchy(updateOneBy.data)
|
|
128
|
+
) {
|
|
129
|
+
return await super.updateOneBy(updateOneBy);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const projectIds: Array<ObjectID | string> =
|
|
133
|
+
await this.findMutationProjectIds({
|
|
134
|
+
query: updateOneBy.query,
|
|
135
|
+
props: updateOneBy.props,
|
|
136
|
+
limit: 1,
|
|
137
|
+
skip: 0,
|
|
138
|
+
isDelete: false,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
142
|
+
projectIds,
|
|
143
|
+
operation: async (): Promise<number> => {
|
|
144
|
+
return await super.updateOneBy(updateOneBy);
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
@CaptureSpan()
|
|
150
|
+
public override async updateBy(updateBy: UpdateBy<Model>): Promise<number> {
|
|
151
|
+
if (
|
|
152
|
+
updateBy.props.ignoreHooks ||
|
|
153
|
+
!this.updateTouchesHierarchy(updateBy.data)
|
|
154
|
+
) {
|
|
155
|
+
return await super.updateBy(updateBy);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const projectIds: Array<ObjectID | string> =
|
|
159
|
+
await this.findMutationProjectIds({
|
|
160
|
+
query: updateBy.query,
|
|
161
|
+
props: updateBy.props,
|
|
162
|
+
limit: this.positiveNumberValue(updateBy.limit, LIMIT_MAX),
|
|
163
|
+
skip: this.positiveNumberValue(updateBy.skip, 0),
|
|
164
|
+
isDelete: false,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
168
|
+
projectIds,
|
|
169
|
+
operation: async (): Promise<number> => {
|
|
170
|
+
return await super.updateBy(updateBy);
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@CaptureSpan()
|
|
176
|
+
public override async deleteOneBy(
|
|
177
|
+
deleteOneBy: DeleteOneBy<Model>,
|
|
178
|
+
): Promise<number> {
|
|
179
|
+
if (deleteOneBy.props.ignoreHooks) {
|
|
180
|
+
return await super.deleteOneBy(deleteOneBy);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const projectIds: Array<ObjectID | string> =
|
|
184
|
+
await this.findMutationProjectIds({
|
|
185
|
+
query: deleteOneBy.query,
|
|
186
|
+
props: deleteOneBy.props,
|
|
187
|
+
limit: 1,
|
|
188
|
+
skip: 0,
|
|
189
|
+
isDelete: true,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
193
|
+
projectIds,
|
|
194
|
+
operation: async (): Promise<number> => {
|
|
195
|
+
return await super.deleteOneBy(deleteOneBy);
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
@CaptureSpan()
|
|
201
|
+
public override async deleteBy(deleteBy: DeleteBy<Model>): Promise<number> {
|
|
202
|
+
if (deleteBy.props.ignoreHooks) {
|
|
203
|
+
return await super.deleteBy(deleteBy);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const projectIds: Array<ObjectID | string> =
|
|
207
|
+
await this.findMutationProjectIds({
|
|
208
|
+
query: deleteBy.query,
|
|
209
|
+
props: deleteBy.props,
|
|
210
|
+
limit: this.positiveNumberValue(deleteBy.limit, LIMIT_MAX),
|
|
211
|
+
skip: this.positiveNumberValue(deleteBy.skip, 0),
|
|
212
|
+
isDelete: true,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
216
|
+
projectIds,
|
|
217
|
+
operation: async (): Promise<number> => {
|
|
218
|
+
return await super.deleteBy(deleteBy);
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
@CaptureSpan()
|
|
224
|
+
public override async hardDeleteBy(
|
|
225
|
+
deleteBy: DeleteBy<Model>,
|
|
226
|
+
): Promise<number> {
|
|
227
|
+
if (deleteBy.props.ignoreHooks) {
|
|
228
|
+
return await super.hardDeleteBy(deleteBy);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/*
|
|
232
|
+
* The retention cron uses one root deletedAt query across all projects.
|
|
233
|
+
* Convert it to a closed batch of unused leaf types before locking. A
|
|
234
|
+
* parent and child can therefore never be split by the batch limit; once
|
|
235
|
+
* leaves are removed, the cron's next iteration can work upward.
|
|
236
|
+
*/
|
|
237
|
+
if (
|
|
238
|
+
!NetworkSiteHierarchyLock.isSafeRootMutationScope({
|
|
239
|
+
query: deleteBy.query as unknown as Record<string, unknown>,
|
|
240
|
+
props: deleteBy.props,
|
|
241
|
+
tenantScopeIsClosed: true,
|
|
242
|
+
})
|
|
243
|
+
) {
|
|
244
|
+
return await this.hardDeleteClosedLeafBatch(deleteBy);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const projectIds: Array<ObjectID | string> =
|
|
248
|
+
await this.findMutationProjectIds({
|
|
249
|
+
query: deleteBy.query,
|
|
250
|
+
props: deleteBy.props,
|
|
251
|
+
limit: this.positiveNumberValue(deleteBy.limit, LIMIT_MAX),
|
|
252
|
+
skip: this.positiveNumberValue(deleteBy.skip, 0),
|
|
253
|
+
isDelete: true,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
257
|
+
projectIds,
|
|
258
|
+
operation: async (): Promise<number> => {
|
|
259
|
+
return await super.hardDeleteBy(deleteBy);
|
|
260
|
+
},
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
private updateTouchesHierarchy(data: UpdateOneBy<Model>["data"]): boolean {
|
|
265
|
+
const record: Record<string, unknown> = data as unknown as Record<
|
|
266
|
+
string,
|
|
267
|
+
unknown
|
|
268
|
+
>;
|
|
269
|
+
|
|
270
|
+
return (
|
|
271
|
+
isAnyKeyWritten(record, PARENT_NETWORK_SITE_TYPE_KEYS) ||
|
|
272
|
+
("isUnitLevel" in record && record["isUnitLevel"] !== undefined) ||
|
|
273
|
+
isAnyKeyWritten(record, PROJECT_KEYS)
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
private positiveNumberValue(
|
|
278
|
+
value: PositiveNumber | number | undefined,
|
|
279
|
+
fallback: number,
|
|
280
|
+
): number {
|
|
281
|
+
if (value instanceof PositiveNumber) {
|
|
282
|
+
return value.toNumber();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return value ?? fallback;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
private async hardDeleteClosedLeafBatch(
|
|
289
|
+
deleteBy: DeleteBy<Model>,
|
|
290
|
+
): Promise<number> {
|
|
291
|
+
const requestedLimit: number = this.positiveNumberValue(
|
|
292
|
+
deleteBy.limit,
|
|
293
|
+
LIMIT_MAX,
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
if (requestedLimit <= 0) {
|
|
297
|
+
return 0;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const scanPageSize: number = Math.min(
|
|
301
|
+
REFERENCE_VALIDATION_BATCH_SIZE,
|
|
302
|
+
requestedLimit,
|
|
303
|
+
);
|
|
304
|
+
const leafTypes: Array<Model> = [];
|
|
305
|
+
let scanSkip: number = this.positiveNumberValue(deleteBy.skip, 0);
|
|
306
|
+
|
|
307
|
+
while (leafTypes.length < requestedLimit) {
|
|
308
|
+
const candidates: Array<Model> = await this.findBy({
|
|
309
|
+
query: deleteBy.query,
|
|
310
|
+
select: { _id: true, projectId: true },
|
|
311
|
+
sort: { _id: SortOrder.Ascending },
|
|
312
|
+
limit: scanPageSize,
|
|
313
|
+
skip: scanSkip,
|
|
314
|
+
props: { isRoot: true },
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
if (candidates.length === 0) {
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const candidateIds: Array<ObjectID> = candidates
|
|
322
|
+
.map((candidate: Model): ObjectID | null => {
|
|
323
|
+
return candidate.id || null;
|
|
324
|
+
})
|
|
325
|
+
.filter((id: ObjectID | null): id is ObjectID => {
|
|
326
|
+
return Boolean(id);
|
|
327
|
+
});
|
|
328
|
+
const referencedTypeIds: Set<string> = new Set<string>();
|
|
329
|
+
|
|
330
|
+
for (
|
|
331
|
+
let candidateOffset: number = 0;
|
|
332
|
+
candidateOffset < candidateIds.length;
|
|
333
|
+
candidateOffset += REFERENCE_VALIDATION_BATCH_SIZE
|
|
334
|
+
) {
|
|
335
|
+
const candidateIdBatch: Array<ObjectID> = candidateIds.slice(
|
|
336
|
+
candidateOffset,
|
|
337
|
+
candidateOffset + REFERENCE_VALIDATION_BATCH_SIZE,
|
|
338
|
+
);
|
|
339
|
+
let childSkip: number = 0;
|
|
340
|
+
|
|
341
|
+
while (candidateIdBatch.length > 0) {
|
|
342
|
+
const childTypes: Array<Model> = await this.findBy({
|
|
343
|
+
query: {
|
|
344
|
+
parentNetworkSiteTypeId: QueryHelper.any(candidateIdBatch),
|
|
345
|
+
},
|
|
346
|
+
select: { parentNetworkSiteTypeId: true },
|
|
347
|
+
sort: { _id: SortOrder.Ascending },
|
|
348
|
+
limit: REFERENCE_VALIDATION_BATCH_SIZE,
|
|
349
|
+
skip: childSkip,
|
|
350
|
+
props: { isRoot: true },
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
for (const childType of childTypes) {
|
|
354
|
+
if (childType.parentNetworkSiteTypeId) {
|
|
355
|
+
referencedTypeIds.add(
|
|
356
|
+
normalizeId(childType.parentNetworkSiteTypeId),
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (childTypes.length < REFERENCE_VALIDATION_BATCH_SIZE) {
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
childSkip += childTypes.length;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
let siteSkip: number = 0;
|
|
369
|
+
|
|
370
|
+
while (candidateIdBatch.length > 0) {
|
|
371
|
+
const sites: Array<NetworkSite> = await NetworkSiteService.findBy({
|
|
372
|
+
query: {
|
|
373
|
+
networkSiteTypeId: QueryHelper.any(candidateIdBatch),
|
|
374
|
+
},
|
|
375
|
+
select: { networkSiteTypeId: true },
|
|
376
|
+
sort: { _id: SortOrder.Ascending },
|
|
377
|
+
limit: REFERENCE_VALIDATION_BATCH_SIZE,
|
|
378
|
+
skip: siteSkip,
|
|
379
|
+
props: { isRoot: true },
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
for (const site of sites) {
|
|
383
|
+
if (site.networkSiteTypeId) {
|
|
384
|
+
referencedTypeIds.add(normalizeId(site.networkSiteTypeId));
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (sites.length < REFERENCE_VALIDATION_BATCH_SIZE) {
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
siteSkip += sites.length;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
for (const candidate of candidates) {
|
|
397
|
+
if (
|
|
398
|
+
candidate.id &&
|
|
399
|
+
candidate.projectId &&
|
|
400
|
+
!referencedTypeIds.has(normalizeId(candidate.id))
|
|
401
|
+
) {
|
|
402
|
+
leafTypes.push(candidate);
|
|
403
|
+
|
|
404
|
+
if (leafTypes.length === requestedLimit) {
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
scanSkip += candidates.length;
|
|
411
|
+
|
|
412
|
+
if (candidates.length < scanPageSize) {
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (leafTypes.length === 0) {
|
|
418
|
+
return 0;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const leafTypeIds: Array<ObjectID> = leafTypes.map(
|
|
422
|
+
(networkSiteType: Model): ObjectID => {
|
|
423
|
+
return networkSiteType.id!;
|
|
424
|
+
},
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
428
|
+
projectIds: leafTypes.map((networkSiteType: Model): ObjectID => {
|
|
429
|
+
return networkSiteType.projectId!;
|
|
430
|
+
}),
|
|
431
|
+
operation: async (): Promise<number> => {
|
|
432
|
+
return await super.hardDeleteBy({
|
|
433
|
+
...deleteBy,
|
|
434
|
+
query: {
|
|
435
|
+
...deleteBy.query,
|
|
436
|
+
_id: QueryHelper.any(leafTypeIds),
|
|
437
|
+
},
|
|
438
|
+
limit: leafTypeIds.length,
|
|
439
|
+
skip: 0,
|
|
440
|
+
});
|
|
441
|
+
},
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
private async findMutationProjectIds(data: {
|
|
446
|
+
query: Query<Model>;
|
|
447
|
+
props: DatabaseCommonInteractionProps;
|
|
448
|
+
limit: number;
|
|
449
|
+
skip: number;
|
|
450
|
+
isDelete: boolean;
|
|
451
|
+
}): Promise<Array<ObjectID | string>> {
|
|
452
|
+
NetworkSiteHierarchyLock.assertSafeRootMutationScope({
|
|
453
|
+
query: data.query as unknown as Record<string, unknown>,
|
|
454
|
+
props: data.props,
|
|
455
|
+
tenantScopeIsClosed: data.isDelete,
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
const networkSiteTypes: Array<Model> = await this.findBy({
|
|
459
|
+
query: data.isDelete
|
|
460
|
+
? this.scopeDeleteQueryToCallerTenant(data.query, data.props)
|
|
461
|
+
: this.scopeQueryToCallerTenant(data.query, data.props),
|
|
462
|
+
select: { projectId: true },
|
|
463
|
+
limit: data.limit,
|
|
464
|
+
skip: data.skip,
|
|
465
|
+
props: { isRoot: true },
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
const projectIds: Array<ObjectID | string> = networkSiteTypes
|
|
469
|
+
.map((networkSiteType: Model): ObjectID | undefined => {
|
|
470
|
+
return networkSiteType.projectId;
|
|
471
|
+
})
|
|
472
|
+
.filter((projectId: ObjectID | undefined): projectId is ObjectID => {
|
|
473
|
+
return Boolean(projectId);
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
projectIds.push(
|
|
477
|
+
...NetworkSiteHierarchyLock.getExplicitProjectIds(
|
|
478
|
+
data.query as unknown as Record<string, unknown>,
|
|
479
|
+
),
|
|
480
|
+
);
|
|
481
|
+
|
|
482
|
+
if (projectIds.length === 0 && data.props.tenantId) {
|
|
483
|
+
projectIds.push(data.props.tenantId);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const seenProjectIds: Set<string> = new Set<string>();
|
|
487
|
+
|
|
488
|
+
return projectIds.filter((projectId: ObjectID | string): boolean => {
|
|
489
|
+
const normalizedProjectId: string = normalizeId(projectId);
|
|
490
|
+
|
|
491
|
+
if (seenProjectIds.has(normalizedProjectId)) {
|
|
492
|
+
return false;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
seenProjectIds.add(normalizedProjectId);
|
|
496
|
+
return true;
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
private scopeQueryToCallerTenant(
|
|
501
|
+
query: Query<Model>,
|
|
502
|
+
props: DatabaseCommonInteractionProps,
|
|
503
|
+
): Query<Model> {
|
|
504
|
+
if (props.isRoot || props.isMasterAdmin || !props.tenantId) {
|
|
505
|
+
return query;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
return {
|
|
509
|
+
...query,
|
|
510
|
+
projectId: props.tenantId,
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/*
|
|
515
|
+
* DeletePermission retains tenant scoping for root callers that provide a
|
|
516
|
+
* tenantId. The hierarchy preflight must select the identical window.
|
|
517
|
+
*/
|
|
518
|
+
private scopeDeleteQueryToCallerTenant(
|
|
519
|
+
query: Query<Model>,
|
|
520
|
+
props: DatabaseCommonInteractionProps,
|
|
521
|
+
): Query<Model> {
|
|
522
|
+
if (!props.tenantId || props.isMultiTenantRequest) {
|
|
523
|
+
return query;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
return {
|
|
527
|
+
...query,
|
|
528
|
+
projectId: props.tenantId,
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
private readProjectId(data: Record<string, unknown>): ObjectID | null {
|
|
533
|
+
for (const key of PROJECT_KEYS) {
|
|
534
|
+
const value: unknown = data[key];
|
|
535
|
+
const isExplicitClear: boolean = value === null || value === "";
|
|
536
|
+
|
|
537
|
+
if (typeof value === "function") {
|
|
538
|
+
throw new BadDataException(
|
|
539
|
+
`${key} cannot be set to a raw SQL expression because the Network Site Type project must be validated against an actual ID.`,
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
if (
|
|
544
|
+
value !== undefined &&
|
|
545
|
+
!isExplicitClear &&
|
|
546
|
+
!RelationIdUtil.read(data, [key])
|
|
547
|
+
) {
|
|
548
|
+
throw new BadDataException(`${key} must contain a valid Project ID.`);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
return RelationIdUtil.readConsistent(data, PROJECT_KEYS, "project");
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/*
|
|
556
|
+
* Dashboard entity pickers submit the relation object; services and
|
|
557
|
+
* migrations usually submit the scalar FK. Validate both, and refuse a
|
|
558
|
+
* contradictory pair rather than relying on ORM precedence for the shared
|
|
559
|
+
* join column.
|
|
560
|
+
*/
|
|
561
|
+
private readParentId(data: Record<string, unknown>): ObjectID | null {
|
|
562
|
+
assertNoSqlExpression(data, PARENT_NETWORK_SITE_TYPE_KEYS);
|
|
563
|
+
|
|
564
|
+
for (const key of PARENT_NETWORK_SITE_TYPE_KEYS) {
|
|
565
|
+
const value: unknown = data[key];
|
|
566
|
+
const isExplicitClear: boolean = value === null || value === "";
|
|
567
|
+
|
|
568
|
+
if (
|
|
569
|
+
value !== undefined &&
|
|
570
|
+
!isExplicitClear &&
|
|
571
|
+
!RelationIdUtil.read(data, [key])
|
|
572
|
+
) {
|
|
573
|
+
throw new BadDataException(
|
|
574
|
+
`${key} must contain a valid Network Site Type ID.`,
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
return RelationIdUtil.readConsistent(
|
|
580
|
+
data,
|
|
581
|
+
PARENT_NETWORK_SITE_TYPE_KEYS,
|
|
582
|
+
"parent Network Site Type",
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
private async getNextSiblingOrder(data: {
|
|
587
|
+
projectId: ObjectID;
|
|
588
|
+
parentNetworkSiteTypeId: ObjectID | null;
|
|
589
|
+
}): Promise<number> {
|
|
590
|
+
const siblings: Array<Model> = await this.findAllNetworkSiteTypes({
|
|
591
|
+
query: {
|
|
592
|
+
projectId: data.projectId,
|
|
593
|
+
parentNetworkSiteTypeId: data.parentNetworkSiteTypeId
|
|
594
|
+
? data.parentNetworkSiteTypeId
|
|
595
|
+
: QueryHelper.isNull(),
|
|
596
|
+
} as Query<Model>,
|
|
597
|
+
select: { order: true },
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
const maxOrder: number | null = siblings.reduce<number | null>(
|
|
601
|
+
(currentMax: number | null, sibling: Model) => {
|
|
602
|
+
return typeof sibling.order === "number"
|
|
603
|
+
? Math.max(currentMax ?? sibling.order, sibling.order)
|
|
604
|
+
: currentMax;
|
|
605
|
+
},
|
|
606
|
+
null,
|
|
607
|
+
);
|
|
608
|
+
|
|
609
|
+
return maxOrder === null ? 1 : maxOrder + 1;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
private async findAllNetworkSiteTypes(data: {
|
|
613
|
+
query: Query<Model>;
|
|
614
|
+
select: Select<Model>;
|
|
615
|
+
}): Promise<Array<Model>> {
|
|
616
|
+
const networkSiteTypes: Array<Model> = [];
|
|
617
|
+
let skip: number = 0;
|
|
618
|
+
|
|
619
|
+
while (true) {
|
|
620
|
+
const page: Array<Model> = await this.findBy({
|
|
621
|
+
query: data.query,
|
|
622
|
+
select: data.select,
|
|
623
|
+
sort: { _id: SortOrder.Ascending },
|
|
624
|
+
limit: LIMIT_MAX,
|
|
625
|
+
skip,
|
|
626
|
+
props: { isRoot: true },
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
networkSiteTypes.push(...page);
|
|
630
|
+
|
|
631
|
+
if (page.length < LIMIT_MAX) {
|
|
632
|
+
return networkSiteTypes;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
skip += page.length;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/*
|
|
640
|
+
* Network estates regularly exceed LIMIT_MAX. Every hierarchy invariant is
|
|
641
|
+
* universal ("all sites match"), so silently validating only the first page
|
|
642
|
+
* would make its result depend on row order. A stable id sort also prevents
|
|
643
|
+
* offset pages from overlapping while these read-only checks run.
|
|
644
|
+
*/
|
|
645
|
+
private async findAllNetworkSites(data: {
|
|
646
|
+
query: Query<NetworkSite>;
|
|
647
|
+
select: Select<NetworkSite>;
|
|
648
|
+
}): Promise<Array<NetworkSite>> {
|
|
649
|
+
const sites: Array<NetworkSite> = [];
|
|
650
|
+
let skip: number = 0;
|
|
651
|
+
|
|
652
|
+
while (true) {
|
|
653
|
+
const page: Array<NetworkSite> = await NetworkSiteService.findBy({
|
|
654
|
+
query: data.query,
|
|
655
|
+
select: data.select,
|
|
656
|
+
sort: { _id: SortOrder.Ascending },
|
|
657
|
+
limit: LIMIT_MAX,
|
|
658
|
+
skip,
|
|
659
|
+
props: { isRoot: true },
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
sites.push(...page);
|
|
663
|
+
|
|
664
|
+
if (page.length < LIMIT_MAX) {
|
|
665
|
+
return sites;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
skip += page.length;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
private async assertParentIsValid(data: {
|
|
673
|
+
networkSiteTypeId: ObjectID | null;
|
|
674
|
+
parentNetworkSiteTypeId: ObjectID;
|
|
675
|
+
projectId: ObjectID;
|
|
676
|
+
}): Promise<void> {
|
|
677
|
+
if (
|
|
678
|
+
data.networkSiteTypeId &&
|
|
679
|
+
sameId(data.networkSiteTypeId, data.parentNetworkSiteTypeId)
|
|
680
|
+
) {
|
|
681
|
+
throw new BadDataException(
|
|
682
|
+
"A Network Site Type cannot be its own parent.",
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
const parent: Model | null = await this.findOneById({
|
|
687
|
+
id: data.parentNetworkSiteTypeId,
|
|
688
|
+
select: {
|
|
689
|
+
_id: true,
|
|
690
|
+
projectId: true,
|
|
691
|
+
isUnitLevel: true,
|
|
692
|
+
},
|
|
693
|
+
props: { isRoot: true },
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
if (!parent) {
|
|
697
|
+
throw new BadDataException("Parent Network Site Type not found.");
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
if (!parent.projectId || !sameId(parent.projectId, data.projectId)) {
|
|
701
|
+
throw new BadDataException(
|
|
702
|
+
"Parent Network Site Type must belong to the same project.",
|
|
703
|
+
);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
if (parent.isUnitLevel === true) {
|
|
707
|
+
throw new BadDataException(
|
|
708
|
+
"A unit-level Network Site Type cannot have child types.",
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
if (!data.networkSiteTypeId) {
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
const networkSiteTypes: Array<Model> = await this.findAllNetworkSiteTypes({
|
|
717
|
+
query: { projectId: data.projectId },
|
|
718
|
+
select: {
|
|
719
|
+
_id: true,
|
|
720
|
+
parentNetworkSiteTypeId: true,
|
|
721
|
+
},
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
const movingType: Model = new Model();
|
|
725
|
+
movingType.id = data.networkSiteTypeId;
|
|
726
|
+
|
|
727
|
+
const parentIsDescendant: boolean =
|
|
728
|
+
NetworkSiteTypeHierarchyUtil.getDescendantNetworkSiteTypes({
|
|
729
|
+
networkSiteType: movingType,
|
|
730
|
+
networkSiteTypes,
|
|
731
|
+
}).some((descendant: Model) => {
|
|
732
|
+
return Boolean(
|
|
733
|
+
descendant.id && sameId(descendant.id, data.parentNetworkSiteTypeId),
|
|
734
|
+
);
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
if (parentIsDescendant) {
|
|
738
|
+
throw new BadDataException(
|
|
739
|
+
"A Network Site Type cannot be moved under one of its descendants.",
|
|
740
|
+
);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/*
|
|
745
|
+
* Changing a type definition must not retroactively make the concrete site
|
|
746
|
+
* tree invalid. A root type may only describe root sites; a child type may
|
|
747
|
+
* only describe sites whose actual parent has the declared parent type.
|
|
748
|
+
*/
|
|
749
|
+
private async assertExistingSitesMatchProposedParent(data: {
|
|
750
|
+
networkSiteTypeId: ObjectID;
|
|
751
|
+
proposedParentNetworkSiteTypeId: ObjectID | null;
|
|
752
|
+
}): Promise<void> {
|
|
753
|
+
const sites: Array<NetworkSite> = await this.findAllNetworkSites({
|
|
754
|
+
query: { networkSiteTypeId: data.networkSiteTypeId },
|
|
755
|
+
select: {
|
|
756
|
+
_id: true,
|
|
757
|
+
parentSiteId: true,
|
|
758
|
+
},
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
if (sites.length === 0) {
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
if (!data.proposedParentNetworkSiteTypeId) {
|
|
766
|
+
if (
|
|
767
|
+
sites.some((site: NetworkSite) => {
|
|
768
|
+
return Boolean(site.parentSiteId);
|
|
769
|
+
})
|
|
770
|
+
) {
|
|
771
|
+
throw new BadDataException(EXISTING_SITES_DO_NOT_MATCH_MESSAGE);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
const parentSiteIds: Array<ObjectID> = [];
|
|
778
|
+
const distinctParentSiteIds: Set<string> = new Set<string>();
|
|
779
|
+
|
|
780
|
+
for (const site of sites) {
|
|
781
|
+
if (!site.parentSiteId) {
|
|
782
|
+
throw new BadDataException(EXISTING_SITES_DO_NOT_MATCH_MESSAGE);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
const normalizedParentSiteId: string = normalizeId(site.parentSiteId);
|
|
786
|
+
if (!distinctParentSiteIds.has(normalizedParentSiteId)) {
|
|
787
|
+
distinctParentSiteIds.add(normalizedParentSiteId);
|
|
788
|
+
parentSiteIds.push(site.parentSiteId);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
const parentSites: Array<NetworkSite> = [];
|
|
793
|
+
|
|
794
|
+
for (
|
|
795
|
+
let offset: number = 0;
|
|
796
|
+
offset < parentSiteIds.length;
|
|
797
|
+
offset += LIMIT_MAX
|
|
798
|
+
) {
|
|
799
|
+
const parentSiteIdBatch: Array<ObjectID> = parentSiteIds.slice(
|
|
800
|
+
offset,
|
|
801
|
+
offset + LIMIT_MAX,
|
|
802
|
+
);
|
|
803
|
+
|
|
804
|
+
parentSites.push(
|
|
805
|
+
...(await this.findAllNetworkSites({
|
|
806
|
+
query: {
|
|
807
|
+
_id: QueryHelper.any(
|
|
808
|
+
parentSiteIdBatch.map((parentSiteId: ObjectID) => {
|
|
809
|
+
return parentSiteId.toString();
|
|
810
|
+
}),
|
|
811
|
+
),
|
|
812
|
+
},
|
|
813
|
+
select: {
|
|
814
|
+
_id: true,
|
|
815
|
+
networkSiteTypeId: true,
|
|
816
|
+
},
|
|
817
|
+
})),
|
|
818
|
+
);
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
const parentTypeBySiteId: Map<string, ObjectID> = new Map<
|
|
822
|
+
string,
|
|
823
|
+
ObjectID
|
|
824
|
+
>();
|
|
825
|
+
|
|
826
|
+
for (const parentSite of parentSites) {
|
|
827
|
+
if (parentSite.id && parentSite.networkSiteTypeId) {
|
|
828
|
+
parentTypeBySiteId.set(
|
|
829
|
+
normalizeId(parentSite.id),
|
|
830
|
+
parentSite.networkSiteTypeId,
|
|
831
|
+
);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
const hasMismatch: boolean = parentSiteIds.some(
|
|
836
|
+
(parentSiteId: ObjectID) => {
|
|
837
|
+
const actualParentTypeId: ObjectID | undefined = parentTypeBySiteId.get(
|
|
838
|
+
normalizeId(parentSiteId),
|
|
839
|
+
);
|
|
840
|
+
|
|
841
|
+
return (
|
|
842
|
+
!actualParentTypeId ||
|
|
843
|
+
!sameId(actualParentTypeId, data.proposedParentNetworkSiteTypeId!)
|
|
844
|
+
);
|
|
845
|
+
},
|
|
846
|
+
);
|
|
847
|
+
|
|
848
|
+
if (hasMismatch) {
|
|
849
|
+
throw new BadDataException(EXISTING_SITES_DO_NOT_MATCH_MESSAGE);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
private async assertTypesCanBecomeUnitLevel(
|
|
854
|
+
networkSiteTypes: Array<Model>,
|
|
855
|
+
): Promise<void> {
|
|
856
|
+
const networkSiteTypeIds: Array<ObjectID> = networkSiteTypes
|
|
857
|
+
.map((networkSiteType: Model) => {
|
|
858
|
+
return networkSiteType.id;
|
|
859
|
+
})
|
|
860
|
+
.filter((id: ObjectID | null): id is ObjectID => {
|
|
861
|
+
return Boolean(id);
|
|
862
|
+
});
|
|
863
|
+
|
|
864
|
+
if (networkSiteTypeIds.length === 0) {
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
const projectIds: Array<string> = [
|
|
869
|
+
...new Set<string>(
|
|
870
|
+
networkSiteTypes
|
|
871
|
+
.map((networkSiteType: Model) => {
|
|
872
|
+
return networkSiteType.projectId?.toString();
|
|
873
|
+
})
|
|
874
|
+
.filter((projectId: string | undefined): projectId is string => {
|
|
875
|
+
return Boolean(projectId);
|
|
876
|
+
}),
|
|
877
|
+
),
|
|
878
|
+
];
|
|
879
|
+
|
|
880
|
+
const child: Model | null = await this.findOneBy({
|
|
881
|
+
query: {
|
|
882
|
+
parentNetworkSiteTypeId: QueryHelper.any(
|
|
883
|
+
networkSiteTypeIds.map((id: ObjectID) => {
|
|
884
|
+
return id.toString();
|
|
885
|
+
}),
|
|
886
|
+
),
|
|
887
|
+
...(projectIds.length > 0
|
|
888
|
+
? { projectId: QueryHelper.any(projectIds) }
|
|
889
|
+
: {}),
|
|
890
|
+
},
|
|
891
|
+
select: { _id: true },
|
|
892
|
+
props: { isRoot: true },
|
|
893
|
+
});
|
|
894
|
+
|
|
895
|
+
if (child) {
|
|
896
|
+
throw new BadDataException(
|
|
897
|
+
"A Network Site Type with child types cannot be made unit-level.",
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
const sitesOfTypes: Array<NetworkSite> = await this.findAllNetworkSites({
|
|
902
|
+
query: {
|
|
903
|
+
networkSiteTypeId: QueryHelper.any(
|
|
904
|
+
networkSiteTypeIds.map((id: ObjectID) => {
|
|
905
|
+
return id.toString();
|
|
906
|
+
}),
|
|
907
|
+
),
|
|
908
|
+
},
|
|
909
|
+
select: { _id: true },
|
|
910
|
+
});
|
|
911
|
+
|
|
912
|
+
const siteIds: Array<string> = sitesOfTypes
|
|
913
|
+
.map((site: NetworkSite) => {
|
|
914
|
+
return site.id?.toString();
|
|
915
|
+
})
|
|
916
|
+
.filter((id: string | undefined): id is string => {
|
|
917
|
+
return Boolean(id);
|
|
918
|
+
});
|
|
919
|
+
|
|
920
|
+
if (siteIds.length === 0) {
|
|
921
|
+
return;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
for (
|
|
925
|
+
let offset: number = 0;
|
|
926
|
+
offset < siteIds.length;
|
|
927
|
+
offset += REFERENCE_VALIDATION_BATCH_SIZE
|
|
928
|
+
) {
|
|
929
|
+
const childSite: NetworkSite | null = await NetworkSiteService.findOneBy({
|
|
930
|
+
query: {
|
|
931
|
+
parentSiteId: QueryHelper.any(
|
|
932
|
+
siteIds.slice(offset, offset + REFERENCE_VALIDATION_BATCH_SIZE),
|
|
933
|
+
),
|
|
934
|
+
...(projectIds.length > 0
|
|
935
|
+
? { projectId: QueryHelper.any(projectIds) }
|
|
936
|
+
: {}),
|
|
937
|
+
},
|
|
938
|
+
select: { _id: true },
|
|
939
|
+
props: { isRoot: true },
|
|
940
|
+
});
|
|
941
|
+
|
|
942
|
+
if (childSite) {
|
|
943
|
+
throw new BadDataException(
|
|
944
|
+
"A Network Site Type whose sites have child sites cannot be made unit-level.",
|
|
945
|
+
);
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
@CaptureSpan()
|
|
951
|
+
protected override async onBeforeCreate(
|
|
952
|
+
createBy: CreateBy<Model>,
|
|
953
|
+
): Promise<OnCreate<Model>> {
|
|
954
|
+
const data: Record<string, unknown> = createBy.data as unknown as Record<
|
|
955
|
+
string,
|
|
956
|
+
unknown
|
|
957
|
+
>;
|
|
958
|
+
assertIsUnitLevelIsNotSqlExpression(data);
|
|
959
|
+
const parentNetworkSiteTypeId: ObjectID | null = this.readParentId(data);
|
|
960
|
+
const projectId: ObjectID | null =
|
|
961
|
+
createBy.props.tenantId || this.readProjectId(data) || null;
|
|
962
|
+
|
|
963
|
+
if (!projectId) {
|
|
964
|
+
throw new BadDataException("Project ID is required.");
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
if (parentNetworkSiteTypeId) {
|
|
968
|
+
await this.assertParentIsValid({
|
|
969
|
+
networkSiteTypeId: createBy.data.id,
|
|
970
|
+
parentNetworkSiteTypeId,
|
|
971
|
+
projectId,
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
if (createBy.data.order === undefined || createBy.data.order === null) {
|
|
976
|
+
createBy.data.order = await this.getNextSiblingOrder({
|
|
977
|
+
projectId,
|
|
978
|
+
parentNetworkSiteTypeId,
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
return { createBy, carryForward: null };
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
@CaptureSpan()
|
|
986
|
+
protected override async onBeforeUpdate(
|
|
987
|
+
updateBy: UpdateBy<Model>,
|
|
988
|
+
): Promise<OnUpdate<Model>> {
|
|
989
|
+
const data: Record<string, unknown> = (updateBy.data ||
|
|
990
|
+
{}) as unknown as Record<string, unknown>;
|
|
991
|
+
assertIsUnitLevelIsNotSqlExpression(data);
|
|
992
|
+
const isParentWritten: boolean = isAnyKeyWritten(
|
|
993
|
+
data,
|
|
994
|
+
PARENT_NETWORK_SITE_TYPE_KEYS,
|
|
995
|
+
);
|
|
996
|
+
const isBecomingUnitLevel: boolean = data["isUnitLevel"] === true;
|
|
997
|
+
const isProjectWritten: boolean = isAnyKeyWritten(data, PROJECT_KEYS);
|
|
998
|
+
const proposedProjectId: ObjectID | null = isProjectWritten
|
|
999
|
+
? this.readProjectId(data)
|
|
1000
|
+
: null;
|
|
1001
|
+
|
|
1002
|
+
if (!isParentWritten && !isBecomingUnitLevel && !isProjectWritten) {
|
|
1003
|
+
return { updateBy, carryForward: null };
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
if (isProjectWritten && !proposedProjectId) {
|
|
1007
|
+
throw new BadDataException(
|
|
1008
|
+
"A Network Site Type cannot be moved to another project.",
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
const proposedParentNetworkSiteTypeId: ObjectID | null = isParentWritten
|
|
1013
|
+
? this.readParentId(data)
|
|
1014
|
+
: null;
|
|
1015
|
+
|
|
1016
|
+
const updateLimit: number =
|
|
1017
|
+
updateBy.limit instanceof PositiveNumber
|
|
1018
|
+
? updateBy.limit.toNumber()
|
|
1019
|
+
: updateBy.limit || LIMIT_MAX;
|
|
1020
|
+
const updateSkip: number =
|
|
1021
|
+
updateBy.skip instanceof PositiveNumber
|
|
1022
|
+
? updateBy.skip.toNumber()
|
|
1023
|
+
: updateBy.skip || 0;
|
|
1024
|
+
|
|
1025
|
+
const networkSiteTypesBeingUpdated: Array<Model> = await this.findBy({
|
|
1026
|
+
query: this.scopeQueryToCallerTenant(updateBy.query, updateBy.props),
|
|
1027
|
+
select: {
|
|
1028
|
+
_id: true,
|
|
1029
|
+
projectId: true,
|
|
1030
|
+
parentNetworkSiteTypeId: true,
|
|
1031
|
+
isUnitLevel: true,
|
|
1032
|
+
},
|
|
1033
|
+
limit: updateLimit,
|
|
1034
|
+
skip: updateSkip,
|
|
1035
|
+
props: { isRoot: true },
|
|
1036
|
+
});
|
|
1037
|
+
|
|
1038
|
+
if (isProjectWritten) {
|
|
1039
|
+
for (const networkSiteType of networkSiteTypesBeingUpdated) {
|
|
1040
|
+
if (
|
|
1041
|
+
!networkSiteType.projectId ||
|
|
1042
|
+
!proposedProjectId ||
|
|
1043
|
+
!sameId(networkSiteType.projectId, proposedProjectId)
|
|
1044
|
+
) {
|
|
1045
|
+
throw new BadDataException(
|
|
1046
|
+
"A Network Site Type cannot be moved to another project.",
|
|
1047
|
+
);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
if (!isParentWritten && !isBecomingUnitLevel) {
|
|
1053
|
+
return { updateBy, carryForward: null };
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
if (isBecomingUnitLevel) {
|
|
1057
|
+
await this.assertTypesCanBecomeUnitLevel(
|
|
1058
|
+
networkSiteTypesBeingUpdated.filter((networkSiteType: Model) => {
|
|
1059
|
+
return networkSiteType.isUnitLevel !== true;
|
|
1060
|
+
}),
|
|
1061
|
+
);
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
if (isParentWritten) {
|
|
1065
|
+
for (const networkSiteType of networkSiteTypesBeingUpdated) {
|
|
1066
|
+
if (!networkSiteType.id || !networkSiteType.projectId) {
|
|
1067
|
+
continue;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
if (proposedParentNetworkSiteTypeId) {
|
|
1071
|
+
await this.assertParentIsValid({
|
|
1072
|
+
networkSiteTypeId: networkSiteType.id,
|
|
1073
|
+
parentNetworkSiteTypeId: proposedParentNetworkSiteTypeId,
|
|
1074
|
+
projectId: networkSiteType.projectId,
|
|
1075
|
+
});
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
const currentParentId: string | null =
|
|
1079
|
+
NetworkSiteTypeHierarchyUtil.getParentId(networkSiteType);
|
|
1080
|
+
const parentChanged: boolean = proposedParentNetworkSiteTypeId
|
|
1081
|
+
? !currentParentId ||
|
|
1082
|
+
!sameId(currentParentId, proposedParentNetworkSiteTypeId)
|
|
1083
|
+
: Boolean(currentParentId);
|
|
1084
|
+
|
|
1085
|
+
if (parentChanged) {
|
|
1086
|
+
await this.assertExistingSitesMatchProposedParent({
|
|
1087
|
+
networkSiteTypeId: networkSiteType.id,
|
|
1088
|
+
proposedParentNetworkSiteTypeId,
|
|
1089
|
+
});
|
|
1090
|
+
|
|
1091
|
+
if (
|
|
1092
|
+
networkSiteTypesBeingUpdated.length === 1 &&
|
|
1093
|
+
data["order"] === undefined
|
|
1094
|
+
) {
|
|
1095
|
+
updateBy.data.order = await this.getNextSiblingOrder({
|
|
1096
|
+
projectId: networkSiteType.projectId,
|
|
1097
|
+
parentNetworkSiteTypeId: proposedParentNetworkSiteTypeId,
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
return { updateBy, carryForward: null };
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
@CaptureSpan()
|
|
1108
|
+
protected override async onBeforeDelete(
|
|
1109
|
+
deleteBy: DeleteBy<Model>,
|
|
1110
|
+
): Promise<OnDelete<Model>> {
|
|
1111
|
+
const deleteLimit: number =
|
|
1112
|
+
deleteBy.limit instanceof PositiveNumber
|
|
1113
|
+
? deleteBy.limit.toNumber()
|
|
1114
|
+
: deleteBy.limit || LIMIT_MAX;
|
|
1115
|
+
const deleteSkip: number =
|
|
1116
|
+
deleteBy.skip instanceof PositiveNumber
|
|
1117
|
+
? deleteBy.skip.toNumber()
|
|
1118
|
+
: deleteBy.skip || 0;
|
|
1119
|
+
|
|
1120
|
+
const networkSiteTypesBeingDeleted: Array<Model> = await this.findBy({
|
|
1121
|
+
query: this.scopeDeleteQueryToCallerTenant(
|
|
1122
|
+
deleteBy.query,
|
|
1123
|
+
deleteBy.props,
|
|
1124
|
+
),
|
|
1125
|
+
select: { _id: true, projectId: true },
|
|
1126
|
+
limit: deleteLimit,
|
|
1127
|
+
skip: deleteSkip,
|
|
1128
|
+
props: { isRoot: true },
|
|
1129
|
+
});
|
|
1130
|
+
|
|
1131
|
+
const ids: Array<ObjectID> = networkSiteTypesBeingDeleted
|
|
1132
|
+
.map((networkSiteType: Model) => {
|
|
1133
|
+
return networkSiteType.id;
|
|
1134
|
+
})
|
|
1135
|
+
.filter((id: ObjectID | null): id is ObjectID => {
|
|
1136
|
+
return Boolean(id);
|
|
1137
|
+
});
|
|
1138
|
+
|
|
1139
|
+
if (ids.length === 0) {
|
|
1140
|
+
return { deleteBy, carryForward: null };
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
const idStrings: Array<string> = ids.map((id: ObjectID) => {
|
|
1144
|
+
return id.toString();
|
|
1145
|
+
});
|
|
1146
|
+
|
|
1147
|
+
const deletingIds: Set<string> = new Set<string>(
|
|
1148
|
+
idStrings.map((id: string) => {
|
|
1149
|
+
return normalizeId(id);
|
|
1150
|
+
}),
|
|
1151
|
+
);
|
|
1152
|
+
const projectIdStrings: Array<string> = [
|
|
1153
|
+
...new Set<string>(
|
|
1154
|
+
networkSiteTypesBeingDeleted
|
|
1155
|
+
.map((networkSiteType: Model) => {
|
|
1156
|
+
return networkSiteType.projectId?.toString();
|
|
1157
|
+
})
|
|
1158
|
+
.filter((projectId: string | undefined): projectId is string => {
|
|
1159
|
+
return Boolean(projectId);
|
|
1160
|
+
}),
|
|
1161
|
+
),
|
|
1162
|
+
];
|
|
1163
|
+
|
|
1164
|
+
for (
|
|
1165
|
+
let parentOffset: number = 0;
|
|
1166
|
+
parentOffset < idStrings.length;
|
|
1167
|
+
parentOffset += REFERENCE_VALIDATION_BATCH_SIZE
|
|
1168
|
+
) {
|
|
1169
|
+
const parentIdBatch: Array<string> = idStrings.slice(
|
|
1170
|
+
parentOffset,
|
|
1171
|
+
parentOffset + REFERENCE_VALIDATION_BATCH_SIZE,
|
|
1172
|
+
);
|
|
1173
|
+
let childSkip: number = 0;
|
|
1174
|
+
|
|
1175
|
+
while (true) {
|
|
1176
|
+
const childTypes: Array<Model> = await this.findBy({
|
|
1177
|
+
query: {
|
|
1178
|
+
parentNetworkSiteTypeId: QueryHelper.any(parentIdBatch),
|
|
1179
|
+
...(projectIdStrings.length > 0
|
|
1180
|
+
? { projectId: QueryHelper.any(projectIdStrings) }
|
|
1181
|
+
: {}),
|
|
1182
|
+
},
|
|
1183
|
+
select: { _id: true },
|
|
1184
|
+
sort: { _id: SortOrder.Ascending },
|
|
1185
|
+
limit: REFERENCE_VALIDATION_BATCH_SIZE,
|
|
1186
|
+
skip: childSkip,
|
|
1187
|
+
props: { isRoot: true },
|
|
1188
|
+
});
|
|
1189
|
+
|
|
1190
|
+
const hasSurvivingChild: boolean = childTypes.some((child: Model) => {
|
|
1191
|
+
return !child.id || !deletingIds.has(normalizeId(child.id));
|
|
1192
|
+
});
|
|
1193
|
+
|
|
1194
|
+
if (hasSurvivingChild) {
|
|
1195
|
+
throw new BadDataException(
|
|
1196
|
+
"A Network Site Type cannot be deleted while child types use it as their parent.",
|
|
1197
|
+
);
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
if (childTypes.length < REFERENCE_VALIDATION_BATCH_SIZE) {
|
|
1201
|
+
break;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
childSkip += childTypes.length;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
const site: NetworkSite | null = await NetworkSiteService.findOneBy({
|
|
1208
|
+
query: {
|
|
1209
|
+
networkSiteTypeId: QueryHelper.any(parentIdBatch),
|
|
1210
|
+
},
|
|
1211
|
+
select: { _id: true },
|
|
1212
|
+
props: { isRoot: true },
|
|
1213
|
+
});
|
|
1214
|
+
|
|
1215
|
+
if (site) {
|
|
1216
|
+
throw new BadDataException(
|
|
1217
|
+
"A Network Site Type cannot be deleted while Network Sites use it.",
|
|
1218
|
+
);
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
return { deleteBy, carryForward: null };
|
|
1223
|
+
}
|
|
8
1224
|
}
|
|
9
1225
|
|
|
10
1226
|
export default new Service();
|