@oneuptime/common 11.6.1 → 11.6.2
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/Index.ts +4 -0
- package/Models/AnalyticsModels/KubernetesCostAllocation.ts +842 -0
- package/Models/AnalyticsModels/NetworkFlow.ts +54 -0
- package/Models/AnalyticsModels/SloHistory.ts +240 -0
- package/Models/DatabaseModels/Index.ts +20 -0
- package/Models/DatabaseModels/NetworkDevice.ts +453 -6
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +7 -6
- package/Models/DatabaseModels/NetworkEndpoint.ts +753 -0
- package/Models/DatabaseModels/NetworkSite.ts +1155 -0
- package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +517 -0
- package/Models/DatabaseModels/NetworkSiteLink.ts +611 -0
- package/Models/DatabaseModels/NetworkSiteStatusTimeline.ts +520 -0
- package/Models/DatabaseModels/NetworkSiteType.ts +499 -0
- package/Models/DatabaseModels/ServiceLevelObjective.ts +1106 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +762 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.ts +444 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.ts +443 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.ts +359 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.ts +48 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.ts +65 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.ts +88 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.ts +391 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Services/AnalyticsDatabaseService.ts +25 -9
- package/Server/Services/Index.ts +24 -0
- package/Server/Services/KubernetesCostAllocationService.ts +14 -0
- package/Server/Services/MetricService.ts +21 -2
- package/Server/Services/MonitorService.ts +22 -0
- package/Server/Services/NetworkDeviceService.ts +438 -2
- package/Server/Services/NetworkEndpointService.ts +414 -0
- package/Server/Services/NetworkSiteAssignmentRuleService.ts +98 -0
- package/Server/Services/NetworkSiteLinkService.ts +10 -0
- package/Server/Services/NetworkSiteService.ts +1254 -0
- package/Server/Services/NetworkSiteStatusTimelineService.ts +10 -0
- package/Server/Services/NetworkSiteTypeService.ts +10 -0
- package/Server/Services/ProjectService.ts +122 -2
- package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +457 -0
- package/Server/Services/ServiceLevelObjectiveOwnerTeamService.ts +10 -0
- package/Server/Services/ServiceLevelObjectiveOwnerUserService.ts +10 -0
- package/Server/Services/ServiceLevelObjectiveService.ts +677 -0
- package/Server/Services/SloHistoryService.ts +101 -0
- package/Server/Services/UserNotificationSettingService.ts +37 -0
- package/Server/Types/AnalyticsDatabase/AggregateBy.ts +9 -0
- package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +15 -0
- package/Server/Utils/AnalyticsDatabase/Statement.ts +39 -3
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +87 -48
- package/Server/Utils/Memory.ts +9 -1
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +190 -12
- package/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
- package/Server/Utils/Monitor/DnsResolutionCache.ts +129 -0
- package/Server/Utils/Monitor/MonitorResource.ts +4 -30
- package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +214 -39
- package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +343 -0
- package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +251 -0
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +176 -142
- package/Server/Utils/Monitor/OuiLookupUtil.ts +49 -0
- package/Server/Utils/Monitor/SnmpInterfaceRateUtil.ts +17 -13
- package/Server/Utils/WhatsAppTemplateUtil.ts +7 -3
- package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +135 -0
- package/Tests/Models/NetworkSiteHierarchy.test.ts +134 -0
- package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +239 -0
- package/Tests/Server/Services/KubernetesCostAllocationAggregate.test.ts +338 -0
- package/Tests/Server/Services/MetricServiceAggregate.test.ts +142 -0
- package/Tests/Server/Services/NetworkDeviceSiteAssignment.test.ts +484 -0
- package/Tests/Server/Services/NetworkEndpointServiceUpsert.test.ts +686 -0
- package/Tests/Server/Services/NetworkSiteAssignmentRuleService.test.ts +185 -0
- package/Tests/Server/Services/NetworkSiteService.test.ts +1354 -0
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +1313 -0
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +1988 -0
- package/Tests/Server/Utils/AnalyticsDatabase/Statement.test.ts +22 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +404 -0
- package/Tests/Server/Utils/Encryption.test.ts +70 -0
- package/Tests/Server/Utils/FileAttachmentMarkdownUtil.test.ts +225 -0
- package/Tests/Server/Utils/JsonWebToken.test.ts +175 -0
- package/Tests/Server/Utils/LocalFile.test.ts +258 -0
- package/Tests/Server/Utils/Memory.test.ts +213 -0
- package/Tests/Server/Utils/Monitor/Criteria/LogMonitorCriteria.test.ts +30 -0
- package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +385 -0
- package/Tests/Server/Utils/Monitor/DnsResolutionCache.test.ts +194 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +155 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +600 -0
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +151 -124
- package/Tests/Server/Utils/Monitor/SnmpInterfaceRateUtil.test.ts +496 -0
- package/Tests/Server/Utils/MonitorCriteriaDataExtractor.test.ts +175 -0
- package/Tests/Server/Utils/MonitorCriteriaMessageFormatter.test.ts +282 -0
- package/Tests/Server/Utils/OuiLookupUtil.test.ts +59 -0
- package/Tests/Server/Utils/SeriesResourceLabels.test.ts +117 -0
- package/Tests/Server/Utils/StackTraceParser.test.ts +370 -0
- package/Tests/Server/Utils/Stream.test.ts +87 -0
- package/Tests/Server/Utils/ValidateGlobalProviderProjectTeams.test.ts +221 -0
- package/Tests/Server/Utils/WhatsAppTemplateUtil.test.ts +199 -0
- package/Tests/Types/Database/CompareOperatorWireSerialization.test.ts +33 -0
- package/Tests/Types/Email.test.ts +198 -0
- package/Tests/Types/Kubernetes/KubernetesObjectParser.test.ts +177 -0
- package/Tests/Types/Log/LogQueryToFilter.test.ts +111 -0
- package/Tests/Types/Monitor/MonitorStepNetworkDeviceMonitor.test.ts +141 -1
- package/Tests/Types/Monitor/MonitorType.test.ts +59 -1
- package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +97 -0
- package/Tests/Types/Monitor/SnmpEndpointDiscovery.test.ts +151 -0
- package/Tests/Types/Monitor/SnmpVendorTemplate.test.ts +110 -6
- package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +129 -0
- package/Tests/Types/SerializableObjectDictionary.test.ts +166 -0
- package/Tests/Types/Time/RangeStartAndEndDateTime.test.ts +98 -0
- package/Tests/Types/WebsiteRequest.test.ts +230 -0
- package/Tests/UI/Components/EntityFilterRoundTrip.test.tsx +103 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +612 -0
- package/Tests/UI/Components/ModelTable/FilterDataToQuery.test.ts +275 -0
- package/Tests/UI/Utils/LogExport.test.ts +159 -0
- package/Tests/UI/Utils/Navigation.test.ts +183 -0
- package/Tests/UI/Utils/TableFilterUrlState.test.ts +539 -0
- package/Tests/UI/Utils/TableViewUrlState.test.ts +272 -0
- package/Tests/Utils/Base64.test.ts +51 -0
- package/Tests/Utils/Boolean.test.ts +76 -0
- package/Tests/Utils/Crypto.test.ts +48 -0
- package/Tests/Utils/Dashboard/DashboardSloComponent.test.ts +259 -0
- package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +162 -0
- package/Tests/Utils/Enum.test.ts +54 -0
- package/Tests/Utils/IpCanonicalUtil.test.ts +85 -0
- package/Tests/Utils/Metrics/MetricSeriesFingerprint.test.ts +160 -0
- package/Tests/Utils/Monitor/EndpointAttachmentUtil.test.ts +836 -0
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +218 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +447 -0
- package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +440 -0
- package/Tests/Utils/NetworkSite/MaterializedPathUtil.test.ts +205 -0
- package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +221 -0
- package/Tests/Utils/NetworkSite/SiteUptimeUtil.test.ts +283 -0
- package/Tests/Utils/ObjectUtil.test.ts +30 -0
- package/Tests/Utils/Slo/SloStatusColor.test.ts +89 -0
- package/Tests/Utils/Slo/SloUtil.test.ts +1980 -0
- package/Tests/Utils/Slo/SloWidgetFormat.test.ts +605 -0
- package/Tests/Utils/TechStack.test.ts +50 -0
- package/Tests/Utils/Traces/CriticalPath.test.ts +178 -0
- package/Types/AnalyticsDatabase/AnalyticsTableName.ts +10 -0
- package/Types/BaseDatabase/EqualTo.ts +9 -1
- package/Types/BaseDatabase/EqualToOrNull.ts +9 -1
- package/Types/BaseDatabase/NotEqual.ts +9 -1
- package/Types/Dashboard/DashboardComponentType.ts +1 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardSloComponent.ts +42 -0
- package/Types/Dashboard/DashboardTemplates.ts +214 -0
- package/Types/Email/EmailTemplateType.ts +2 -0
- package/Types/Kubernetes/KubernetesCostIngest.ts +79 -0
- package/Types/Monitor/CriteriaFilter.ts +9 -0
- package/Types/Monitor/MonitorStep.ts +5 -8
- package/Types/Monitor/MonitorStepNetworkDeviceMonitor.ts +27 -5
- package/Types/Monitor/MonitorType.ts +15 -5
- package/Types/Monitor/SnmpMonitor/ArpEntry.ts +14 -0
- package/Types/Monitor/SnmpMonitor/FdbEntry.ts +18 -0
- package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +10 -3
- package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +31 -5
- package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +12 -0
- package/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.ts +231 -3
- package/Types/NetworkSite/DefaultNetworkSiteType.ts +20 -0
- package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
- package/Types/Permission.ts +449 -0
- package/Types/ServiceLevelObjective/SliType.ts +6 -0
- package/Types/ServiceLevelObjective/SloMultiMonitorMode.ts +6 -0
- package/Types/ServiceLevelObjective/SloStatus.ts +9 -0
- package/Types/ServiceLevelObjective/SloWindowType.ts +6 -0
- package/Types/Telemetry/ServiceType.ts +1 -0
- package/UI/Components/Filters/EntityFilter.tsx +16 -0
- package/UI/Components/Filters/FilterViewer.tsx +22 -5
- package/UI/Components/List/List.tsx +8 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +309 -106
- package/UI/Components/ModelTable/FilterDataToQuery.ts +172 -0
- package/UI/Components/Navbar/NavBar.tsx +16 -2
- package/UI/Components/Navbar/NavBarMenuModal.tsx +3 -3
- package/UI/Utils/Navigation.ts +10 -0
- package/UI/Utils/TableFilterUrlState.ts +204 -17
- package/UI/Utils/TableViewUrlState.ts +165 -0
- package/Utils/Dashboard/Components/DashboardSloComponent.ts +114 -0
- package/Utils/Dashboard/Components/Index.ts +7 -0
- package/Utils/IpCanonicalUtil.ts +134 -0
- package/Utils/Monitor/EndpointAttachmentUtil.ts +508 -0
- package/Utils/Monitor/NetworkTopologyUtil.ts +157 -5
- package/Utils/NetworkSite/CidrMatchUtil.ts +296 -0
- package/Utils/NetworkSite/MaterializedPathUtil.ts +115 -0
- package/Utils/NetworkSite/SiteStatusRollupUtil.ts +97 -0
- package/Utils/NetworkSite/SiteUptimeUtil.ts +111 -0
- package/Utils/Slo/SloStatusColor.ts +54 -0
- package/Utils/Slo/SloUtil.ts +637 -0
- package/Utils/Slo/SloWidgetFormat.ts +383 -0
- package/build/dist/Models/AnalyticsModels/Index.js +4 -0
- package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +713 -0
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -0
- package/build/dist/Models/AnalyticsModels/NetworkFlow.js +44 -0
- package/build/dist/Models/AnalyticsModels/NetworkFlow.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/SloHistory.js +215 -0
- package/build/dist/Models/AnalyticsModels/SloHistory.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Index.js +20 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +458 -6
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +0 -6
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkEndpoint.js +779 -0
- package/build/dist/Models/DatabaseModels/NetworkEndpoint.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSite.js +1180 -0
- package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +534 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteLink.js +629 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteLink.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js +538 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js +522 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +1124 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +769 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js +460 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js +459 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js +130 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js +31 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js +36 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js +49 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js +140 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +23 -6
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +24 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/KubernetesCostAllocationService.js +12 -0
- package/build/dist/Server/Services/KubernetesCostAllocationService.js.map +1 -0
- package/build/dist/Server/Services/MetricService.js +21 -3
- package/build/dist/Server/Services/MetricService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +19 -0
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +351 -1
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkEndpointService.js +319 -0
- package/build/dist/Server/Services/NetworkEndpointService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js +90 -0
- package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteLinkService.js +9 -0
- package/build/dist/Server/Services/NetworkSiteLinkService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteService.js +1038 -0
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js +9 -0
- package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteTypeService.js +9 -0
- package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -0
- package/build/dist/Server/Services/ProjectService.js +98 -2
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +358 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js +9 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js +9 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js +582 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -0
- package/build/dist/Server/Services/SloHistoryService.js +77 -0
- package/build/dist/Server/Services/SloHistoryService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationSettingService.js +20 -0
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +9 -0
- package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +15 -0
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +31 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +76 -48
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/Memory.js +9 -1
- package/build/dist/Server/Utils/Memory.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +132 -10
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
- package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js +77 -0
- package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +21 -41
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +152 -40
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +262 -0
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +201 -0
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +152 -120
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js +44 -0
- package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js +10 -10
- package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js.map +1 -1
- package/build/dist/Server/Utils/WhatsAppTemplateUtil.js +5 -0
- package/build/dist/Server/Utils/WhatsAppTemplateUtil.js.map +1 -1
- package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +10 -0
- package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
- package/build/dist/Types/BaseDatabase/EqualTo.js +9 -1
- package/build/dist/Types/BaseDatabase/EqualTo.js.map +1 -1
- package/build/dist/Types/BaseDatabase/EqualToOrNull.js +9 -1
- package/build/dist/Types/BaseDatabase/EqualToOrNull.js.map +1 -1
- package/build/dist/Types/BaseDatabase/NotEqual.js +9 -1
- package/build/dist/Types/BaseDatabase/NotEqual.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js +23 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js +205 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.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/Kubernetes/KubernetesCostIngest.js +21 -0
- package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js +1 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +5 -5
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js +8 -0
- package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorType.js +15 -5
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js +2 -0
- package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js.map +1 -0
- package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js +2 -0
- package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js.map +1 -0
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +9 -3
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js +217 -3
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js.map +1 -1
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js +21 -0
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js.map +1 -0
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
- package/build/dist/Types/Permission.js +409 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/ServiceLevelObjective/SliType.js +7 -0
- package/build/dist/Types/ServiceLevelObjective/SliType.js.map +1 -0
- package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js +7 -0
- package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js.map +1 -0
- package/build/dist/Types/ServiceLevelObjective/SloStatus.js +10 -0
- package/build/dist/Types/ServiceLevelObjective/SloStatus.js.map +1 -0
- package/build/dist/Types/ServiceLevelObjective/SloWindowType.js +7 -0
- package/build/dist/Types/ServiceLevelObjective/SloWindowType.js.map +1 -0
- package/build/dist/Types/Telemetry/ServiceType.js +1 -0
- package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
- package/build/dist/UI/Components/Filters/EntityFilter.js +15 -0
- package/build/dist/UI/Components/Filters/EntityFilter.js.map +1 -1
- package/build/dist/UI/Components/Filters/FilterViewer.js +19 -4
- package/build/dist/UI/Components/Filters/FilterViewer.js.map +1 -1
- package/build/dist/UI/Components/List/List.js +1 -1
- package/build/dist/UI/Components/List/List.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +235 -89
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js +96 -0
- package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js.map +1 -0
- package/build/dist/UI/Components/Navbar/NavBar.js +14 -2
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +3 -2
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +9 -0
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/UI/Utils/TableFilterUrlState.js +159 -15
- package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
- package/build/dist/UI/Utils/TableViewUrlState.js +103 -0
- package/build/dist/UI/Utils/TableViewUrlState.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js +93 -0
- package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/IpCanonicalUtil.js +110 -0
- package/build/dist/Utils/IpCanonicalUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js +311 -0
- package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +98 -5
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +222 -0
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js +89 -0
- package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +60 -0
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js +76 -0
- package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js.map +1 -0
- package/build/dist/Utils/Slo/SloStatusColor.js +18 -0
- package/build/dist/Utils/Slo/SloStatusColor.js.map +1 -0
- package/build/dist/Utils/Slo/SloUtil.js +393 -0
- package/build/dist/Utils/Slo/SloUtil.js.map +1 -0
- package/build/dist/Utils/Slo/SloWidgetFormat.js +174 -0
- package/build/dist/Utils/Slo/SloWidgetFormat.js.map +1 -0
- package/package.json +2 -2
- package/Types/Dashboard/DashboardComponents/Index.ts +0 -7
- package/build/dist/Types/Dashboard/DashboardComponents/Index.js +0 -8
- package/build/dist/Types/Dashboard/DashboardComponents/Index.js.map +0 -1
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
import DatabaseService from "./DatabaseService";
|
|
2
|
+
import Model from "../../Models/DatabaseModels/NetworkEndpoint";
|
|
3
|
+
import ColumnLength from "../../Types/Database/ColumnLength";
|
|
4
|
+
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
5
|
+
import ObjectID from "../../Types/ObjectID";
|
|
6
|
+
import EndpointAttachmentUtil, {
|
|
7
|
+
EndpointAttachment,
|
|
8
|
+
EndpointIncomingObservation,
|
|
9
|
+
EndpointIpBinding,
|
|
10
|
+
EndpointUpsertContext,
|
|
11
|
+
EndpointUpsertDecision,
|
|
12
|
+
} from "../../Utils/Monitor/EndpointAttachmentUtil";
|
|
13
|
+
import OuiLookupUtil from "../Utils/Monitor/OuiLookupUtil";
|
|
14
|
+
import QueryHelper from "../Types/Database/QueryHelper";
|
|
15
|
+
import logger from "../Utils/Logger";
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
* Rows written per statement. Endpoint rows are narrow (12 params each),
|
|
19
|
+
* so 500 keeps a chunk well under Postgres' parameter ceiling while
|
|
20
|
+
* turning a 4096-MAC switch into 9 round trips instead of 4096.
|
|
21
|
+
*/
|
|
22
|
+
const UPSERT_BATCH_SIZE: number = 500;
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* Hard ceiling on how many MACs one device walk may write. This is the
|
|
26
|
+
* findBy limit too — reading more than we can look up would silently
|
|
27
|
+
* treat known endpoints as new. A switch under a MAC-flood attack (or a
|
|
28
|
+
* misconfigured trunk dumping a whole campus into one FDB) is capped
|
|
29
|
+
* here and logged rather than allowed to monopolise the ingest thread.
|
|
30
|
+
*/
|
|
31
|
+
const MAX_ENDPOINTS_PER_WALK: number = LIMIT_MAX;
|
|
32
|
+
|
|
33
|
+
/*
|
|
34
|
+
* Column order used by the INSERT in upsertDiscoveredEndpoints. Keep
|
|
35
|
+
* this and the generated parameter tuples in perfect sync.
|
|
36
|
+
*/
|
|
37
|
+
const INSERT_COLUMNS: Array<string> = [
|
|
38
|
+
"projectId",
|
|
39
|
+
"macAddress",
|
|
40
|
+
"ipAddress",
|
|
41
|
+
"vendor",
|
|
42
|
+
"attachedNetworkDeviceId",
|
|
43
|
+
"attachedInterfaceIndex",
|
|
44
|
+
"attachedPortName",
|
|
45
|
+
"vlanId",
|
|
46
|
+
"siteId",
|
|
47
|
+
"firstSeenAt",
|
|
48
|
+
"lastSeenAt",
|
|
49
|
+
"version",
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
/*
|
|
53
|
+
* ShortText columns are 100 chars. Truncating BEFORE the decision is
|
|
54
|
+
* made (rather than at write time) matters twice over: one over-long
|
|
55
|
+
* value can never fail the whole chunk it rides in, and the
|
|
56
|
+
* unchanged-since-last-poll comparison compares what we would store
|
|
57
|
+
* against what is stored, not against the untruncated observation.
|
|
58
|
+
*/
|
|
59
|
+
function truncateShortText(value: string | undefined): string | undefined {
|
|
60
|
+
if (!value) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
return value.length > ColumnLength.ShortText
|
|
64
|
+
? value.substring(0, ColumnLength.ShortText)
|
|
65
|
+
: value;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export class Service extends DatabaseService<Model> {
|
|
69
|
+
public constructor() {
|
|
70
|
+
super(Model);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/*
|
|
74
|
+
* Applies one device walk's endpoint observations to the per-project
|
|
75
|
+
* endpoint inventory. Precedence between switch-FDB attachments and
|
|
76
|
+
* router-ARP sightings lives in EndpointAttachmentUtil.decideUpsert (pure,
|
|
77
|
+
* exhaustively tested); this method only batches the reads and applies
|
|
78
|
+
* the decisions:
|
|
79
|
+
*
|
|
80
|
+
* - one findBy for every observed MAC, then ONE INSERT per 500 new
|
|
81
|
+
* MACs and ONE UPDATE per 500 changed MACs — this runs inline on
|
|
82
|
+
* the probe-ingest request path, so per-MAC round trips are not an
|
|
83
|
+
* option at restaurant-chain scale (thousands of sites x thousands
|
|
84
|
+
* of L2 endpoints),
|
|
85
|
+
* - endpoints that have not moved since the last poll produce no
|
|
86
|
+
* write at all (see ENDPOINT_LAST_SEEN_REFRESH_MS), so a stable
|
|
87
|
+
* switch costs one SELECT and nothing else,
|
|
88
|
+
* - vendor is stamped from the MAC OUI on create only (user-correctable),
|
|
89
|
+
* - siteId follows the attaching device's site whenever an attachment is
|
|
90
|
+
* (re)written and the caller knows the site,
|
|
91
|
+
* - firstSeenAt is set on create, lastSeenAt on every touch that writes.
|
|
92
|
+
*/
|
|
93
|
+
public async upsertDiscoveredEndpoints(data: {
|
|
94
|
+
projectId: ObjectID;
|
|
95
|
+
deviceId: ObjectID;
|
|
96
|
+
deviceSiteId?: ObjectID | undefined;
|
|
97
|
+
attachments: Array<EndpointAttachment>;
|
|
98
|
+
ipBindings: Array<EndpointIpBinding>;
|
|
99
|
+
now: Date;
|
|
100
|
+
}): Promise<void> {
|
|
101
|
+
// Merge both observation kinds per MAC — an L3 switch yields both.
|
|
102
|
+
const incomingByMac: Map<string, EndpointIncomingObservation> = new Map();
|
|
103
|
+
|
|
104
|
+
for (const attachment of data.attachments) {
|
|
105
|
+
incomingByMac.set(attachment.macAddress, {
|
|
106
|
+
macAddress: attachment.macAddress,
|
|
107
|
+
deviceId: data.deviceId.toString(),
|
|
108
|
+
attachment: {
|
|
109
|
+
interfaceIndex: attachment.attachedInterfaceIndex,
|
|
110
|
+
portName: truncateShortText(attachment.attachedPortName),
|
|
111
|
+
vlanId: attachment.vlanId,
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
for (const binding of data.ipBindings) {
|
|
117
|
+
const existing: EndpointIncomingObservation | undefined =
|
|
118
|
+
incomingByMac.get(binding.macAddress);
|
|
119
|
+
const ipAddress: string | undefined = truncateShortText(
|
|
120
|
+
binding.ipAddress,
|
|
121
|
+
);
|
|
122
|
+
if (!ipAddress) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (existing) {
|
|
126
|
+
existing.ipBinding = {
|
|
127
|
+
ipAddress: ipAddress,
|
|
128
|
+
routerInterfaceIndex: binding.routerInterfaceIndex,
|
|
129
|
+
};
|
|
130
|
+
} else {
|
|
131
|
+
incomingByMac.set(binding.macAddress, {
|
|
132
|
+
macAddress: binding.macAddress,
|
|
133
|
+
deviceId: data.deviceId.toString(),
|
|
134
|
+
ipBinding: {
|
|
135
|
+
ipAddress: ipAddress,
|
|
136
|
+
routerInterfaceIndex: binding.routerInterfaceIndex,
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/*
|
|
143
|
+
* Deterministic order, capped so a pathological FDB dump (or a MAC
|
|
144
|
+
* flood attack on a customer switch) cannot write unbounded rows or
|
|
145
|
+
* exceed the findBy limit.
|
|
146
|
+
*/
|
|
147
|
+
const allMacs: Array<string> = Array.from(incomingByMac.keys()).sort();
|
|
148
|
+
const macs: Array<string> = allMacs.slice(0, MAX_ENDPOINTS_PER_WALK);
|
|
149
|
+
|
|
150
|
+
if (macs.length === 0) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (allMacs.length > macs.length) {
|
|
155
|
+
logger.warn(
|
|
156
|
+
`NetworkEndpointService: device ${data.deviceId.toString()} reported ${allMacs.length} endpoint MACs; capping this walk at ${MAX_ENDPOINTS_PER_WALK}.`,
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const existingRows: Array<Model> = await this.findBy({
|
|
161
|
+
query: {
|
|
162
|
+
projectId: data.projectId,
|
|
163
|
+
macAddress: QueryHelper.any(macs),
|
|
164
|
+
},
|
|
165
|
+
select: {
|
|
166
|
+
_id: true,
|
|
167
|
+
macAddress: true,
|
|
168
|
+
attachedNetworkDeviceId: true,
|
|
169
|
+
attachedInterfaceIndex: true,
|
|
170
|
+
attachedPortName: true,
|
|
171
|
+
vlanId: true,
|
|
172
|
+
ipAddress: true,
|
|
173
|
+
siteId: true,
|
|
174
|
+
firstSeenAt: true,
|
|
175
|
+
lastSeenAt: true,
|
|
176
|
+
},
|
|
177
|
+
limit: LIMIT_MAX,
|
|
178
|
+
skip: 0,
|
|
179
|
+
props: {
|
|
180
|
+
isRoot: true,
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const existingByMac: Map<string, Model> = new Map();
|
|
185
|
+
for (const row of existingRows) {
|
|
186
|
+
if (row.macAddress) {
|
|
187
|
+
existingByMac.set(row.macAddress, row);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const context: EndpointUpsertContext = {
|
|
192
|
+
now: data.now,
|
|
193
|
+
siteId: data.deviceSiteId?.toString(),
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const creates: Array<{ mac: string; decision: EndpointUpsertDecision }> =
|
|
197
|
+
[];
|
|
198
|
+
const updates: Array<{ mac: string; decision: EndpointUpsertDecision }> =
|
|
199
|
+
[];
|
|
200
|
+
|
|
201
|
+
for (const mac of macs) {
|
|
202
|
+
const incoming: EndpointIncomingObservation = incomingByMac.get(mac)!;
|
|
203
|
+
const existing: Model | undefined = existingByMac.get(mac);
|
|
204
|
+
|
|
205
|
+
const decision: EndpointUpsertDecision =
|
|
206
|
+
EndpointAttachmentUtil.decideUpsert(
|
|
207
|
+
existing
|
|
208
|
+
? {
|
|
209
|
+
attachedNetworkDeviceId:
|
|
210
|
+
existing.attachedNetworkDeviceId?.toString(),
|
|
211
|
+
attachedInterfaceIndex: existing.attachedInterfaceIndex,
|
|
212
|
+
attachedPortName: existing.attachedPortName,
|
|
213
|
+
vlanId: existing.vlanId,
|
|
214
|
+
ipAddress: existing.ipAddress,
|
|
215
|
+
siteId: existing.siteId?.toString(),
|
|
216
|
+
firstSeenAt: existing.firstSeenAt,
|
|
217
|
+
lastSeenAt: existing.lastSeenAt,
|
|
218
|
+
}
|
|
219
|
+
: null,
|
|
220
|
+
incoming,
|
|
221
|
+
context,
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
if (decision.action === "create") {
|
|
225
|
+
creates.push({ mac, decision });
|
|
226
|
+
} else if (decision.action === "update") {
|
|
227
|
+
updates.push({ mac, decision });
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
await this.bulkInsertEndpoints({
|
|
232
|
+
projectId: data.projectId,
|
|
233
|
+
deviceId: data.deviceId,
|
|
234
|
+
deviceSiteId: data.deviceSiteId,
|
|
235
|
+
now: data.now,
|
|
236
|
+
rows: creates,
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
await this.bulkUpdateEndpoints({
|
|
240
|
+
projectId: data.projectId,
|
|
241
|
+
deviceId: data.deviceId,
|
|
242
|
+
deviceSiteId: data.deviceSiteId,
|
|
243
|
+
now: data.now,
|
|
244
|
+
rows: updates,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/*
|
|
249
|
+
* New MACs. Every create-path decision has setAttachment === true (a
|
|
250
|
+
* row with no stored attachment can never be "attached elsewhere"), so
|
|
251
|
+
* the conflict branch can write the attachment unconditionally.
|
|
252
|
+
*
|
|
253
|
+
* ON CONFLICT names the partial unique index on
|
|
254
|
+
* (projectId, macAddress) WHERE "deletedAt" IS NULL — the predicate is
|
|
255
|
+
* required for index inference, and it is what keeps a soft-deleted
|
|
256
|
+
* row from colliding with a rediscovered MAC. The DO UPDATE branch
|
|
257
|
+
* only fires when a concurrent walk created the row between our findBy
|
|
258
|
+
* and this INSERT; it then applies the same semantics the UPDATE path
|
|
259
|
+
* would have, so the observation is never silently dropped.
|
|
260
|
+
*
|
|
261
|
+
* `vendor` is deliberately absent from DO UPDATE SET: it is stamped
|
|
262
|
+
* from the OUI on create and is user-correctable thereafter.
|
|
263
|
+
*/
|
|
264
|
+
private async bulkInsertEndpoints(data: {
|
|
265
|
+
projectId: ObjectID;
|
|
266
|
+
deviceId: ObjectID;
|
|
267
|
+
deviceSiteId?: ObjectID | undefined;
|
|
268
|
+
now: Date;
|
|
269
|
+
rows: Array<{ mac: string; decision: EndpointUpsertDecision }>;
|
|
270
|
+
}): Promise<void> {
|
|
271
|
+
if (data.rows.length === 0) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
for (let i: number = 0; i < data.rows.length; i += UPSERT_BATCH_SIZE) {
|
|
276
|
+
const chunk: Array<{ mac: string; decision: EndpointUpsertDecision }> =
|
|
277
|
+
data.rows.slice(i, i + UPSERT_BATCH_SIZE);
|
|
278
|
+
|
|
279
|
+
const valueFragments: Array<string> = [];
|
|
280
|
+
const params: Array<unknown> = [];
|
|
281
|
+
let paramIndex: number = 1;
|
|
282
|
+
|
|
283
|
+
for (const row of chunk) {
|
|
284
|
+
const placeholders: Array<string> = [];
|
|
285
|
+
for (let c: number = 0; c < INSERT_COLUMNS.length; c++) {
|
|
286
|
+
placeholders.push(`$${paramIndex++}`);
|
|
287
|
+
}
|
|
288
|
+
valueFragments.push(`(${placeholders.join(", ")})`);
|
|
289
|
+
|
|
290
|
+
params.push(
|
|
291
|
+
data.projectId.toString(),
|
|
292
|
+
row.mac,
|
|
293
|
+
row.decision.setIpAddress && row.decision.ipAddress
|
|
294
|
+
? row.decision.ipAddress
|
|
295
|
+
: null,
|
|
296
|
+
truncateShortText(OuiLookupUtil.lookupVendor(row.mac)) ?? null,
|
|
297
|
+
data.deviceId.toString(),
|
|
298
|
+
row.decision.attachedInterfaceIndex ?? null,
|
|
299
|
+
row.decision.attachedPortName ?? null,
|
|
300
|
+
row.decision.vlanId ?? null,
|
|
301
|
+
data.deviceSiteId?.toString() ?? null,
|
|
302
|
+
data.now,
|
|
303
|
+
data.now,
|
|
304
|
+
0, // version (BaseModel @VersionColumn)
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const sql: string = `
|
|
309
|
+
INSERT INTO "NetworkEndpoint" (
|
|
310
|
+
"projectId", "macAddress", "ipAddress", "vendor",
|
|
311
|
+
"attachedNetworkDeviceId", "attachedInterfaceIndex",
|
|
312
|
+
"attachedPortName", "vlanId", "siteId",
|
|
313
|
+
"firstSeenAt", "lastSeenAt", "version"
|
|
314
|
+
)
|
|
315
|
+
VALUES ${valueFragments.join(", ")}
|
|
316
|
+
ON CONFLICT ("projectId", "macAddress") WHERE "deletedAt" IS NULL
|
|
317
|
+
DO UPDATE SET
|
|
318
|
+
"attachedNetworkDeviceId" = EXCLUDED."attachedNetworkDeviceId",
|
|
319
|
+
"attachedInterfaceIndex" = COALESCE(EXCLUDED."attachedInterfaceIndex", "NetworkEndpoint"."attachedInterfaceIndex"),
|
|
320
|
+
"attachedPortName" = COALESCE(EXCLUDED."attachedPortName", "NetworkEndpoint"."attachedPortName"),
|
|
321
|
+
"vlanId" = COALESCE(EXCLUDED."vlanId", "NetworkEndpoint"."vlanId"),
|
|
322
|
+
"siteId" = COALESCE(EXCLUDED."siteId", "NetworkEndpoint"."siteId"),
|
|
323
|
+
"ipAddress" = COALESCE(EXCLUDED."ipAddress", "NetworkEndpoint"."ipAddress"),
|
|
324
|
+
"firstSeenAt" = COALESCE("NetworkEndpoint"."firstSeenAt", EXCLUDED."firstSeenAt"),
|
|
325
|
+
"lastSeenAt" = EXCLUDED."lastSeenAt",
|
|
326
|
+
"updatedAt" = now()
|
|
327
|
+
`;
|
|
328
|
+
|
|
329
|
+
await this.getRepository().manager.query(sql, params);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/*
|
|
334
|
+
* Known MACs whose observation actually changed something. One
|
|
335
|
+
* UPDATE ... FROM (VALUES ...) per chunk, joined on the same
|
|
336
|
+
* (projectId, macAddress) key the unique index covers, with
|
|
337
|
+
* "deletedAt" IS NULL so a soft-deleted row is never resurrected.
|
|
338
|
+
*
|
|
339
|
+
* Per-row conditionality rides in the VALUES tuple: `setAttachment`
|
|
340
|
+
* gates the whole attachment group, and NULL means "the walk did not
|
|
341
|
+
* report one" — COALESCE keeps whatever is stored, which is the
|
|
342
|
+
* "undefined never clears a stored value" rule from decideUpsert.
|
|
343
|
+
*/
|
|
344
|
+
private async bulkUpdateEndpoints(data: {
|
|
345
|
+
projectId: ObjectID;
|
|
346
|
+
deviceId: ObjectID;
|
|
347
|
+
deviceSiteId?: ObjectID | undefined;
|
|
348
|
+
now: Date;
|
|
349
|
+
rows: Array<{ mac: string; decision: EndpointUpsertDecision }>;
|
|
350
|
+
}): Promise<void> {
|
|
351
|
+
if (data.rows.length === 0) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
for (let i: number = 0; i < data.rows.length; i += UPSERT_BATCH_SIZE) {
|
|
356
|
+
const chunk: Array<{ mac: string; decision: EndpointUpsertDecision }> =
|
|
357
|
+
data.rows.slice(i, i + UPSERT_BATCH_SIZE);
|
|
358
|
+
|
|
359
|
+
const valueFragments: Array<string> = [];
|
|
360
|
+
const params: Array<unknown> = [data.projectId.toString()];
|
|
361
|
+
let paramIndex: number = 2;
|
|
362
|
+
|
|
363
|
+
for (const row of chunk) {
|
|
364
|
+
valueFragments.push(
|
|
365
|
+
`($${paramIndex++}::character varying, $${paramIndex++}::boolean, $${paramIndex++}::uuid, $${paramIndex++}::integer, $${paramIndex++}::character varying, $${paramIndex++}::integer, $${paramIndex++}::uuid, $${paramIndex++}::character varying, $${paramIndex++}::timestamptz)`,
|
|
366
|
+
);
|
|
367
|
+
|
|
368
|
+
params.push(
|
|
369
|
+
row.mac,
|
|
370
|
+
row.decision.setAttachment,
|
|
371
|
+
row.decision.setAttachment ? data.deviceId.toString() : null,
|
|
372
|
+
row.decision.setAttachment
|
|
373
|
+
? row.decision.attachedInterfaceIndex ?? null
|
|
374
|
+
: null,
|
|
375
|
+
row.decision.setAttachment
|
|
376
|
+
? row.decision.attachedPortName ?? null
|
|
377
|
+
: null,
|
|
378
|
+
row.decision.setAttachment ? row.decision.vlanId ?? null : null,
|
|
379
|
+
row.decision.setAttachment
|
|
380
|
+
? data.deviceSiteId?.toString() ?? null
|
|
381
|
+
: null,
|
|
382
|
+
row.decision.setIpAddress && row.decision.ipAddress
|
|
383
|
+
? row.decision.ipAddress
|
|
384
|
+
: null,
|
|
385
|
+
data.now,
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const sql: string = `
|
|
390
|
+
UPDATE "NetworkEndpoint" AS e
|
|
391
|
+
SET
|
|
392
|
+
"attachedNetworkDeviceId" = CASE WHEN v."setAttachment" THEN v."deviceId" ELSE e."attachedNetworkDeviceId" END,
|
|
393
|
+
"attachedInterfaceIndex" = CASE WHEN v."setAttachment" THEN COALESCE(v."attachedInterfaceIndex", e."attachedInterfaceIndex") ELSE e."attachedInterfaceIndex" END,
|
|
394
|
+
"attachedPortName" = CASE WHEN v."setAttachment" THEN COALESCE(v."attachedPortName", e."attachedPortName") ELSE e."attachedPortName" END,
|
|
395
|
+
"vlanId" = CASE WHEN v."setAttachment" THEN COALESCE(v."vlanId", e."vlanId") ELSE e."vlanId" END,
|
|
396
|
+
"siteId" = CASE WHEN v."setAttachment" THEN COALESCE(v."siteId", e."siteId") ELSE e."siteId" END,
|
|
397
|
+
"ipAddress" = COALESCE(v."ipAddress", e."ipAddress"),
|
|
398
|
+
"firstSeenAt" = COALESCE(e."firstSeenAt", v."lastSeenAt"),
|
|
399
|
+
"lastSeenAt" = v."lastSeenAt",
|
|
400
|
+
"updatedAt" = now()
|
|
401
|
+
FROM (VALUES ${valueFragments.join(", ")})
|
|
402
|
+
AS v("macAddress", "setAttachment", "deviceId", "attachedInterfaceIndex", "attachedPortName", "vlanId", "siteId", "ipAddress", "lastSeenAt")
|
|
403
|
+
WHERE
|
|
404
|
+
e."projectId" = $1
|
|
405
|
+
AND e."macAddress" = v."macAddress"
|
|
406
|
+
AND e."deletedAt" IS NULL
|
|
407
|
+
`;
|
|
408
|
+
|
|
409
|
+
await this.getRepository().manager.query(sql, params);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
export default new Service();
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import DatabaseService from "./DatabaseService";
|
|
2
|
+
import Model from "../../Models/DatabaseModels/NetworkSiteAssignmentRule";
|
|
3
|
+
import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
|
|
4
|
+
import CreateBy from "../Types/Database/CreateBy";
|
|
5
|
+
import UpdateBy from "../Types/Database/UpdateBy";
|
|
6
|
+
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
7
|
+
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
8
|
+
import BadDataException from "../../Types/Exception/BadDataException";
|
|
9
|
+
import CidrMatchUtil from "../../Utils/NetworkSite/CidrMatchUtil";
|
|
10
|
+
|
|
11
|
+
export class Service extends DatabaseService<Model> {
|
|
12
|
+
public constructor() {
|
|
13
|
+
super(Model);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/*
|
|
17
|
+
* A rule with neither criterion would match nothing (or, worse, read as
|
|
18
|
+
* "match everything" to a future maintainer) - reject it at write time.
|
|
19
|
+
*/
|
|
20
|
+
@CaptureSpan()
|
|
21
|
+
protected override async onBeforeCreate(
|
|
22
|
+
createBy: CreateBy<Model>,
|
|
23
|
+
): Promise<OnCreate<Model>> {
|
|
24
|
+
this.validateCriteria({
|
|
25
|
+
subnetCidr: createBy.data.subnetCidr,
|
|
26
|
+
hostnamePattern: createBy.data.hostnamePattern,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
return { createBy, carryForward: null };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@CaptureSpan()
|
|
33
|
+
protected override async onBeforeUpdate(
|
|
34
|
+
updateBy: UpdateBy<Model>,
|
|
35
|
+
): Promise<OnUpdate<Model>> {
|
|
36
|
+
const dataKeys: Array<string> = Object.keys(updateBy.data || {});
|
|
37
|
+
|
|
38
|
+
if (
|
|
39
|
+
!dataKeys.includes("subnetCidr") &&
|
|
40
|
+
!dataKeys.includes("hostnamePattern")
|
|
41
|
+
) {
|
|
42
|
+
return { updateBy, carryForward: null };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/*
|
|
46
|
+
* The update may clear one criterion while the other only exists on the
|
|
47
|
+
* stored row, so validate the RESULTING state of every matched row.
|
|
48
|
+
*/
|
|
49
|
+
const existingRules: Array<Model> = await this.findBy({
|
|
50
|
+
query: updateBy.query,
|
|
51
|
+
select: {
|
|
52
|
+
_id: true,
|
|
53
|
+
subnetCidr: true,
|
|
54
|
+
hostnamePattern: true,
|
|
55
|
+
},
|
|
56
|
+
limit: LIMIT_MAX,
|
|
57
|
+
skip: 0,
|
|
58
|
+
props: {
|
|
59
|
+
isRoot: true,
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
for (const existingRule of existingRules) {
|
|
64
|
+
this.validateCriteria({
|
|
65
|
+
subnetCidr: dataKeys.includes("subnetCidr")
|
|
66
|
+
? ((updateBy.data as any)["subnetCidr"] as string | null)
|
|
67
|
+
: existingRule.subnetCidr,
|
|
68
|
+
hostnamePattern: dataKeys.includes("hostnamePattern")
|
|
69
|
+
? ((updateBy.data as any)["hostnamePattern"] as string | null)
|
|
70
|
+
: existingRule.hostnamePattern,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return { updateBy, carryForward: null };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private validateCriteria(data: {
|
|
78
|
+
subnetCidr?: string | null | undefined;
|
|
79
|
+
hostnamePattern?: string | null | undefined;
|
|
80
|
+
}): void {
|
|
81
|
+
const subnetCidr: string = (data.subnetCidr || "").trim();
|
|
82
|
+
const hostnamePattern: string = (data.hostnamePattern || "").trim();
|
|
83
|
+
|
|
84
|
+
if (!subnetCidr && !hostnamePattern) {
|
|
85
|
+
throw new BadDataException(
|
|
86
|
+
"At least one of Subnet CIDR or Hostname Pattern is required.",
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (subnetCidr && !CidrMatchUtil.isValidCidr(subnetCidr)) {
|
|
91
|
+
throw new BadDataException(
|
|
92
|
+
`${subnetCidr} is not a valid IPv4 CIDR (expected e.g. 10.0.0.0/24).`,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export default new Service();
|