@oneuptime/common 12.0.22 → 12.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/DetectionRule.ts +55 -0
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/NetworkDevice.ts +44 -0
- package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +584 -0
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +105 -0
- package/Models/DatabaseModels/Project.ts +68 -0
- package/Models/DatabaseModels/User.ts +68 -0
- package/Server/API/TelemetryAPI.ts +29 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddNetworkDeviceAutoImportRule.ts +60 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789200000000-AddSysObjectIdPatternToAutoImportRule.ts +26 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789300000000-AddAutoApplyVendorHealthTemplate.ts +26 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.ts +28 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.ts +49 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
- package/Server/Middleware/GzipRequestBody.ts +311 -0
- package/Server/Middleware/MultipartFormData.ts +87 -3
- package/Server/Services/DetectionRuleService.ts +73 -6
- package/Server/Services/Index.ts +207 -0
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +917 -0
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +181 -0
- package/Server/Services/NetworkDeviceDiscoveryScanService.ts +59 -0
- package/Server/Services/NetworkDeviceService.ts +148 -0
- package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +65 -0
- package/Server/Services/OnCallDutyPolicyFeedService.ts +1 -1
- package/Server/Services/ProjectService.ts +29 -19
- package/Server/Services/SecurityEventService.ts +90 -13
- package/Server/Services/StatusPageResourceService.ts +223 -0
- package/Server/Services/TelemetryAttributeService.ts +17 -0
- package/Server/Services/UserService.ts +4 -6
- package/Server/Types/Markdown.ts +161 -67
- package/Server/Utils/AI/Toolbox/OnCallTools.ts +12 -4
- package/Server/Utils/AnalyticsDatabase/Statement.ts +13 -1
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +297 -6
- package/Server/Utils/Attribution.ts +4 -0
- package/Server/Utils/Marketing/MarketingEventUtil.ts +45 -7
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +39 -1
- package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +55 -3
- package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +21 -0
- package/Server/Utils/StartServer.ts +12 -32
- package/Server/Utils/Telemetry/LlmCostBudgetEvaluator.ts +101 -4
- package/Server/Utils/Telemetry/LlmMetricSpend.ts +130 -0
- package/Server/Views/Partials/AnalyticsConsent.ejs +159 -102
- package/Server/Views/Partials/Head.ejs +2 -1
- package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +776 -38
- package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +359 -0
- package/Tests/App/Dashboard/CorrelateGraph.test.tsx +865 -0
- package/Tests/App/Dashboard/CorrelationGraph.test.ts +346 -0
- package/Tests/App/Dashboard/CriteriaFilterConditionDropdown.test.tsx +256 -0
- package/Tests/App/Dashboard/CriteriaFilterDefaults.test.ts +738 -0
- package/Tests/App/Dashboard/CriteriaFilterMonitorTypeChange.test.ts +1122 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +283 -0
- package/Tests/App/Dashboard/ExternalStatusPageCriteriaFilter.test.ts +407 -0
- package/Tests/App/Dashboard/MetricSeriesInvestigateMenu.test.tsx +5 -14
- package/Tests/App/Dashboard/MonitorCriteriaActionToggles.test.tsx +426 -0
- package/Tests/App/Dashboard/MonitorStepsCriteriaAlignmentWiring.test.tsx +352 -0
- package/Tests/App/Dashboard/OnCallLayerCardOverrides.test.tsx +278 -0
- package/Tests/App/Dashboard/OnCallLayerShiftPreviewOverrides.test.ts +237 -0
- package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +2 -2
- package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +460 -0
- package/Tests/App/Dashboard/SecurityEventAttributeUtil.test.ts +171 -0
- package/Tests/App/Dashboard/SecurityEventCorrelation.test.ts +857 -0
- package/Tests/App/Dashboard/SecurityEventDetailObservables.test.tsx +194 -0
- package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +124 -0
- package/Tests/App/Dashboard/SecurityEventsMonitorStepForm.test.tsx +79 -19
- package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +382 -0
- package/Tests/App/StatusPage/BulkAddStatusPageMonitors.test.ts +216 -0
- package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +590 -11
- package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +757 -0
- package/Tests/Models/DiscoveryScanNameColumn.test.ts +293 -0
- package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +564 -0
- package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +120 -4
- package/Tests/Server/Middleware/GzipRequestBody.test.ts +725 -0
- package/Tests/Server/Middleware/MultipartFormData.test.ts +298 -0
- package/Tests/Server/Services/AddDetectionRuleDistinctCountColumnsMigration.test.ts +311 -0
- package/Tests/Server/Services/AutoImportScanCredentialSelect.test.ts +205 -0
- package/Tests/Server/Services/DetectionRuleService.test.ts +134 -2
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +7 -1
- package/Tests/Server/Services/FeedRetentionConsistency.test.ts +131 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +933 -0
- package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +194 -0
- package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +800 -0
- package/Tests/Server/Services/OnCallScheduleAttachRosterRefresh.test.ts +244 -0
- package/Tests/Server/Services/SecurityEventService.test.ts +376 -0
- package/Tests/Server/Services/StatusPageResourceDuplicates.test.ts +703 -0
- package/Tests/Server/Services/TelemetryAttributeServiceSecurityEvent.test.ts +256 -0
- package/Tests/Server/Types/Workflow/Components/ComponentRegistryParity.test.ts +417 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorWhereOperators.test.ts +677 -0
- package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +43 -0
- package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +15 -11
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +97 -1
- package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +369 -8
- package/Tests/Server/Utils/SecurityEvent/SigmaClickhouseCompiler.test.ts +35 -0
- package/Tests/Server/Utils/Telemetry/LlmCostBudgetEvaluator.test.ts +368 -4
- package/Tests/Server/Utils/Telemetry/LlmMetricSpend.test.ts +245 -0
- package/Tests/Server/Views/AnalyticsConsentPartial.test.ts +48 -5
- package/Tests/Types/Code/YamlSyntax.test.ts +396 -0
- package/Tests/Types/Monitor/MetricAndProfileDefaultCriteria.test.ts +957 -0
- package/Tests/Types/Monitor/MonitorCriteriaActionValidation.test.ts +598 -0
- package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +49 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +6 -6
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +4 -4
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +4 -3
- package/Tests/Types/Telemetry/LlmMetricConventions.test.ts +193 -0
- package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +0 -12
- package/Tests/UI/Components/CardModelDetailEdit.test.tsx +1 -17
- package/Tests/UI/Components/CodeEditor.test.tsx +474 -10
- package/Tests/UI/Components/Detail/YamlField.test.tsx +105 -0
- package/Tests/UI/Components/EntityDropdownLabelsBulkAdd.test.tsx +319 -0
- package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +231 -0
- package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +1 -0
- package/Tests/UI/Components/Forms/ValidationYAML.test.ts +234 -0
- package/Tests/UI/Components/ModelTable/AttributeColumns.test.tsx +573 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableAttributeColumns.test.tsx +824 -0
- package/Tests/UI/Components/ModelTable/ColumnCustomizationModalAddableColumns.test.tsx +707 -0
- package/Tests/UI/Components/SideOver.test.tsx +1 -1
- package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +294 -0
- package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +436 -0
- package/Tests/UI/Components/TableBulkCsvExport.test.tsx +6 -2
- package/Tests/UI/Components/Toggle.test.tsx +25 -0
- package/Tests/UI/Components/YamlEditor.test.tsx +847 -0
- package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +252 -0
- package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +516 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +272 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +221 -0
- package/Tests/Utils/NetworkDiscovery/ScanNameUtil.test.ts +312 -0
- package/Tests/Utils/NetworkDiscovery/ScanTargetUtil.test.ts +164 -0
- package/Tests/Utils/StatusPage/ResourceExplorer.test.ts +468 -0
- package/Tests/Utils/Telemetry/LlmMetricQuery.test.ts +472 -0
- package/Types/Code/YamlSyntax.ts +396 -0
- package/Types/Exception/ExceptionCode.ts +1 -0
- package/Types/Exception/PayloadTooLargeException.ts +8 -0
- package/Types/Marketing/Attribution.ts +10 -0
- package/Types/Marketing/MarketingEvent.ts +4 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +116 -56
- package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +2 -1
- package/Types/NetworkAutomation/RuleRunResult.ts +84 -0
- package/Types/Permission.ts +47 -0
- package/Types/SecurityEvent/DetectionFindingConstants.ts +11 -0
- package/Types/Telemetry/LlmMetricConventions.ts +124 -0
- package/UI/Components/AutocompleteTextInput/AutocompleteTextInput.tsx +3 -0
- package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +10 -1
- package/UI/Components/CodeEditor/CodeEditor.tsx +241 -79
- package/UI/Components/CodeEditor/YamlEditor.tsx +369 -0
- package/UI/Components/Detail/Detail.tsx +10 -0
- package/UI/Components/EntityDropdown/EntityDropdown.tsx +33 -0
- package/UI/Components/Forms/Fields/FormField.tsx +31 -0
- package/UI/Components/Forms/Types/Field.ts +8 -0
- package/UI/Components/Forms/Types/FormFieldSchemaType.ts +1 -0
- package/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.ts +2 -0
- package/UI/Components/Forms/Validation.ts +46 -0
- package/UI/Components/Input/Input.tsx +3 -0
- package/UI/Components/ModelTable/AttributeColumns.tsx +321 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +263 -14
- package/UI/Components/ModelTable/Column.ts +8 -0
- package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +310 -0
- package/UI/Components/ModelTable/ColumnPreference.ts +13 -1
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.tsx +2 -2
- package/UI/Components/SideOver/SideOver.tsx +5 -5
- package/UI/Components/StatusPage/ResourceGrid.tsx +82 -2
- package/UI/Components/StatusPage/ResourceList.tsx +197 -38
- package/UI/Components/Toggle/Toggle.tsx +9 -1
- package/UI/Components/Types/FieldType.ts +1 -0
- package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +73 -1
- package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +257 -0
- package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +183 -0
- package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +95 -0
- package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +66 -0
- package/Utils/NetworkDiscovery/ScanNameUtil.ts +181 -0
- package/Utils/NetworkDiscovery/ScanTargetUtil.ts +82 -0
- package/Utils/StatusPage/ResourceExplorer.ts +258 -0
- package/Utils/Telemetry/LlmMetricQuery.ts +204 -0
- package/build/dist/Models/DatabaseModels/DetectionRule.js +57 -0
- package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +45 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +609 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +97 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +76 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/User.js +76 -0
- package/build/dist/Models/DatabaseModels/User.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +17 -0
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddNetworkDeviceAutoImportRule.js +35 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddNetworkDeviceAutoImportRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789200000000-AddSysObjectIdPatternToAutoImportRule.js +19 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789200000000-AddSysObjectIdPatternToAutoImportRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789300000000-AddAutoApplyVendorHealthTemplate.js +19 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789300000000-AddAutoApplyVendorHealthTemplate.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js +21 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js +42 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.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/Middleware/GzipRequestBody.js +224 -0
- package/build/dist/Server/Middleware/GzipRequestBody.js.map +1 -0
- package/build/dist/Server/Middleware/MultipartFormData.js +71 -2
- package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
- package/build/dist/Server/Services/DetectionRuleService.js +49 -4
- package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +206 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +711 -0
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +155 -0
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +50 -0
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +124 -0
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +68 -13
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +25 -45
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/SecurityEventService.js +57 -5
- package/build/dist/Server/Services/SecurityEventService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageResourceService.js +140 -0
- package/build/dist/Server/Services/StatusPageResourceService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryAttributeService.js +17 -0
- package/build/dist/Server/Services/TelemetryAttributeService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +2 -12
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Markdown.js +147 -61
- package/build/dist/Server/Types/Markdown.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +12 -4
- package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +12 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +246 -9
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/Attribution.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js +27 -7
- package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +26 -0
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +42 -7
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +18 -0
- package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +12 -21
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js +76 -5
- package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js +102 -0
- package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js.map +1 -0
- package/build/dist/Types/Code/YamlSyntax.js +212 -0
- package/build/dist/Types/Code/YamlSyntax.js.map +1 -0
- package/build/dist/Types/Exception/ExceptionCode.js +1 -0
- package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
- package/build/dist/Types/Exception/PayloadTooLargeException.js +8 -0
- package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -0
- package/build/dist/Types/Marketing/Attribution.js +10 -0
- package/build/dist/Types/Marketing/Attribution.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +112 -51
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +2 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -1
- package/build/dist/Types/NetworkAutomation/RuleRunResult.js +24 -0
- package/build/dist/Types/NetworkAutomation/RuleRunResult.js.map +1 -1
- package/build/dist/Types/Permission.js +41 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +9 -0
- package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
- package/build/dist/Types/Telemetry/LlmMetricConventions.js +98 -0
- package/build/dist/Types/Telemetry/LlmMetricConventions.js.map +1 -0
- package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js +1 -1
- package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js.map +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +5 -2
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js +206 -76
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/YamlEditor.js +201 -0
- package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -0
- package/build/dist/UI/Components/Detail/Detail.js +9 -0
- package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +16 -1
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +14 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Forms/Types/Field.js.map +1 -1
- package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js +1 -0
- package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js.map +1 -1
- package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js +2 -0
- package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js.map +1 -1
- package/build/dist/UI/Components/Forms/Validation.js +27 -0
- package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +1 -1
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/AttributeColumns.js +159 -0
- package/build/dist/UI/Components/ModelTable/AttributeColumns.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +179 -17
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +133 -2
- package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ColumnPreference.js +7 -1
- package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.js +2 -2
- package/build/dist/UI/Components/SideOver/SideOver.js +5 -5
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js +28 -2
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceList.js +87 -20
- package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
- package/build/dist/UI/Components/Toggle/Toggle.js +9 -1
- package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
- package/build/dist/UI/Components/Types/FieldType.js +1 -0
- package/build/dist/UI/Components/Types/FieldType.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +37 -1
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +149 -0
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +121 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +75 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +59 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js +120 -0
- package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +60 -0
- package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -1
- package/build/dist/Utils/StatusPage/ResourceExplorer.js +171 -0
- package/build/dist/Utils/StatusPage/ResourceExplorer.js.map +1 -1
- package/build/dist/Utils/Telemetry/LlmMetricQuery.js +119 -0
- package/build/dist/Utils/Telemetry/LlmMetricQuery.js.map +1 -0
- package/jest.config.json +2 -0
- package/package.json +1 -1
- package/tsconfig.json +2 -1
- package/Tests/UI/Components/Toast.test.tsx +0 -197
- package/Tests/UI/Components/ToastStacking.test.tsx +0 -198
- package/UI/Components/Toast/Toast.tsx +0 -189
- package/UI/Components/Toast/ToastInit.tsx +0 -110
- package/build/dist/UI/Components/Toast/Toast.js +0 -123
- package/build/dist/UI/Components/Toast/Toast.js.map +0 -1
- package/build/dist/UI/Components/Toast/ToastInit.js +0 -53
- package/build/dist/UI/Components/Toast/ToastInit.js.map +0 -1
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MAX_DEVICE_DESCRIPTION_LENGTH,
|
|
3
|
+
MAX_DEVICE_NAME_LENGTH,
|
|
4
|
+
buildDeviceName,
|
|
5
|
+
buildFallbackDeviceName,
|
|
6
|
+
buildNetworkDeviceFromDiscoveredHost,
|
|
7
|
+
DiscoveredDeviceScanSource,
|
|
8
|
+
} from "../../../Utils/NetworkDiscovery/DiscoveredDeviceBuilder";
|
|
9
|
+
import NetworkDevice from "../../../Models/DatabaseModels/NetworkDevice";
|
|
10
|
+
import { DiscoveredNetworkDevice } from "../../../Models/DatabaseModels/NetworkDeviceDiscoveryScan";
|
|
11
|
+
import NetworkDeviceMonitoringMethod from "../../../Types/NetworkDevice/NetworkDeviceMonitoringMethod";
|
|
12
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
13
|
+
import { describe, expect, it } from "@jest/globals";
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
* Contract under test — one discovered host maps to one NetworkDevice the
|
|
17
|
+
* SAME way everywhere. The builder is the shared recipe behind the
|
|
18
|
+
* dashboard's Review-dialog import and the server-side auto-import rule
|
|
19
|
+
* engine, so what these tests pin is the device both paths must agree on:
|
|
20
|
+
* which host field lands in which device column, which scan credentials ride
|
|
21
|
+
* along (and when they must NOT), and the length ceilings that keep a
|
|
22
|
+
* real-world 255-octet sysName from failing the create on the slug.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const PROJECT_ID: ObjectID = new ObjectID(
|
|
26
|
+
"22222222-2222-4222-8222-222222222222",
|
|
27
|
+
);
|
|
28
|
+
const PROBE_ID: ObjectID = new ObjectID("11111111-1111-4111-8111-111111111111");
|
|
29
|
+
|
|
30
|
+
function snmpHost(
|
|
31
|
+
overrides: Partial<DiscoveredNetworkDevice> = {},
|
|
32
|
+
): DiscoveredNetworkDevice {
|
|
33
|
+
return {
|
|
34
|
+
ipAddress: "10.0.0.5",
|
|
35
|
+
sysName: "core-switch-01",
|
|
36
|
+
sysDescr: "Cisco IOS Software, C2960X",
|
|
37
|
+
...overrides,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// A scan carrying every credential column the builder knows how to copy.
|
|
42
|
+
function fullScanSource(): DiscoveredDeviceScanSource {
|
|
43
|
+
return {
|
|
44
|
+
probeId: PROBE_ID,
|
|
45
|
+
snmpVersion: "V3",
|
|
46
|
+
snmpCommunityString: "public",
|
|
47
|
+
snmpPort: 1161,
|
|
48
|
+
snmpV3SecurityLevel: "authPriv",
|
|
49
|
+
snmpV3Username: "observer",
|
|
50
|
+
snmpV3AuthProtocol: "SHA",
|
|
51
|
+
snmpV3AuthKey: "auth-key-value",
|
|
52
|
+
snmpV3PrivProtocol: "AES",
|
|
53
|
+
snmpV3PrivKey: "priv-key-value",
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function build(data: {
|
|
58
|
+
host?: DiscoveredNetworkDevice | undefined;
|
|
59
|
+
scan?: DiscoveredDeviceScanSource | undefined;
|
|
60
|
+
name?: string | undefined;
|
|
61
|
+
}): NetworkDevice {
|
|
62
|
+
return buildNetworkDeviceFromDiscoveredHost({
|
|
63
|
+
projectId: PROJECT_ID,
|
|
64
|
+
host: data.host || snmpHost(),
|
|
65
|
+
scan: data.scan || fullScanSource(),
|
|
66
|
+
name: data.name,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
describe("buildNetworkDeviceFromDiscoveredHost - vendor template auto-apply flag", () => {
|
|
71
|
+
it("is off unless the caller asks for it", () => {
|
|
72
|
+
expect(build({}).autoApplyVendorHealthTemplate).toBeUndefined();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("is set on an SNMP host when the caller asks (the rule engine does)", () => {
|
|
76
|
+
const device: NetworkDevice = buildNetworkDeviceFromDiscoveredHost({
|
|
77
|
+
projectId: PROJECT_ID,
|
|
78
|
+
host: snmpHost(),
|
|
79
|
+
scan: fullScanSource(),
|
|
80
|
+
autoApplyVendorHealthTemplate: true,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
expect(device.autoApplyVendorHealthTemplate).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
/*
|
|
87
|
+
* A ping-only host is never SNMP-polled, so no poll can ever fingerprint
|
|
88
|
+
* its vendor — the flag would be a dead toggle that reads as a promise.
|
|
89
|
+
*/
|
|
90
|
+
it("stays off on a ping-only host even when requested", () => {
|
|
91
|
+
const device: NetworkDevice = buildNetworkDeviceFromDiscoveredHost({
|
|
92
|
+
projectId: PROJECT_ID,
|
|
93
|
+
host: snmpHost({ snmpReachable: false }),
|
|
94
|
+
scan: fullScanSource(),
|
|
95
|
+
autoApplyVendorHealthTemplate: true,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
expect(device.autoApplyVendorHealthTemplate).toBeUndefined();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe("buildNetworkDeviceFromDiscoveredHost - SNMP host", () => {
|
|
103
|
+
it("maps identity fields: sysName to name, address to hostname, sysDescr to description", () => {
|
|
104
|
+
const device: NetworkDevice = build({});
|
|
105
|
+
|
|
106
|
+
expect(device.projectId?.toString()).toBe(PROJECT_ID.toString());
|
|
107
|
+
expect(device.name).toBe("core-switch-01");
|
|
108
|
+
// The address is both the hostname and the registered-host dedup key.
|
|
109
|
+
expect(device.hostname).toBe("10.0.0.5");
|
|
110
|
+
expect(device.description).toBe("Cisco IOS Software, C2960X");
|
|
111
|
+
expect(device.monitoringMethod).toBe(NetworkDeviceMonitoringMethod.Snmp);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
/*
|
|
115
|
+
* Every credential the scan swept with must land on the device, or the
|
|
116
|
+
* imported device can never poll. The v3 block matters most: a v3 scan
|
|
117
|
+
* that imported as a credential-less device would sit unreachable with no
|
|
118
|
+
* error anywhere.
|
|
119
|
+
*/
|
|
120
|
+
it("copies the probe and every SNMP credential from the scan source", () => {
|
|
121
|
+
const device: NetworkDevice = build({});
|
|
122
|
+
|
|
123
|
+
expect(device.probeId?.toString()).toBe(PROBE_ID.toString());
|
|
124
|
+
expect(device.snmpVersion).toBe("V3");
|
|
125
|
+
expect(device.snmpCommunityString).toBe("public");
|
|
126
|
+
expect(device.snmpPort).toBe(1161);
|
|
127
|
+
expect(device.snmpV3SecurityLevel).toBe("authPriv");
|
|
128
|
+
expect(device.snmpV3Username).toBe("observer");
|
|
129
|
+
expect(device.snmpV3AuthProtocol).toBe("SHA");
|
|
130
|
+
expect(device.snmpV3AuthKey).toBe("auth-key-value");
|
|
131
|
+
expect(device.snmpV3PrivProtocol).toBe("AES");
|
|
132
|
+
expect(device.snmpV3PrivKey).toBe("priv-key-value");
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
/*
|
|
136
|
+
* The scan row may hold a serialized id rather than an ObjectID instance
|
|
137
|
+
* (the rule engine selects its scan itself); the builder re-wraps rather
|
|
138
|
+
* than trusting the shape.
|
|
139
|
+
*/
|
|
140
|
+
it("re-wraps the probe id so a serialized id still becomes an ObjectID", () => {
|
|
141
|
+
const device: NetworkDevice = build({
|
|
142
|
+
scan: {
|
|
143
|
+
...fullScanSource(),
|
|
144
|
+
probeId: PROBE_ID.toString() as unknown as ObjectID,
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
expect(device.probeId).toBeInstanceOf(ObjectID);
|
|
149
|
+
expect(device.probeId?.toString()).toBe(PROBE_ID.toString());
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe("buildNetworkDeviceFromDiscoveredHost - ping-only host", () => {
|
|
154
|
+
/*
|
|
155
|
+
* A ping-only host becomes a monitor-backed device: recorded so it can
|
|
156
|
+
* belong to a site and appear on the topology map, with binding a monitor
|
|
157
|
+
* to it a separate deliberate step. Credentials it never answered to must
|
|
158
|
+
* not ride along.
|
|
159
|
+
*/
|
|
160
|
+
it("builds a monitor-backed device with polling off and no credentials", () => {
|
|
161
|
+
const device: NetworkDevice = build({
|
|
162
|
+
host: snmpHost({ snmpReachable: false, sysName: undefined }),
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
expect(device.monitoringMethod).toBe(NetworkDeviceMonitoringMethod.Monitor);
|
|
166
|
+
expect(device.isPollingEnabled).toBe(false);
|
|
167
|
+
expect(device.probeId).toBeUndefined();
|
|
168
|
+
expect(device.snmpVersion).toBeUndefined();
|
|
169
|
+
expect(device.snmpCommunityString).toBeUndefined();
|
|
170
|
+
expect(device.snmpPort).toBeUndefined();
|
|
171
|
+
expect(device.snmpV3SecurityLevel).toBeUndefined();
|
|
172
|
+
expect(device.snmpV3Username).toBeUndefined();
|
|
173
|
+
expect(device.snmpV3AuthProtocol).toBeUndefined();
|
|
174
|
+
expect(device.snmpV3AuthKey).toBeUndefined();
|
|
175
|
+
expect(device.snmpV3PrivProtocol).toBeUndefined();
|
|
176
|
+
expect(device.snmpV3PrivKey).toBeUndefined();
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
describe("buildDeviceName", () => {
|
|
181
|
+
it("prefers the sysName", () => {
|
|
182
|
+
expect(buildDeviceName(snmpHost())).toBe("core-switch-01");
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// A ping-only host has no SNMP identity; the address is all there is.
|
|
186
|
+
it("falls back to the address when sysName is missing", () => {
|
|
187
|
+
expect(buildDeviceName(snmpHost({ sysName: undefined }))).toBe("10.0.0.5");
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("falls back to the address when sysName is whitespace", () => {
|
|
191
|
+
expect(buildDeviceName(snmpHost({ sysName: " " }))).toBe("10.0.0.5");
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
/*
|
|
195
|
+
* SNMP sysName is a DisplayString of up to 255 octets, so over-long names
|
|
196
|
+
* are routine on real gear — and the create path THROWS on an over-long
|
|
197
|
+
* name (via the slug ceiling) rather than truncating, so the clamp has to
|
|
198
|
+
* happen here.
|
|
199
|
+
*/
|
|
200
|
+
it("clamps a 255-character sysName to MAX_DEVICE_NAME_LENGTH", () => {
|
|
201
|
+
const longSysName: string = "x".repeat(255);
|
|
202
|
+
const name: string = buildDeviceName(snmpHost({ sysName: longSysName }));
|
|
203
|
+
|
|
204
|
+
expect(name.length).toBe(MAX_DEVICE_NAME_LENGTH);
|
|
205
|
+
expect(name).toBe(longSysName.substring(0, MAX_DEVICE_NAME_LENGTH));
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
describe("buildFallbackDeviceName", () => {
|
|
210
|
+
it("appends the address that tells name-twins apart", () => {
|
|
211
|
+
expect(buildFallbackDeviceName(snmpHost())).toBe(
|
|
212
|
+
"core-switch-01 (10.0.0.5)",
|
|
213
|
+
);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
/*
|
|
217
|
+
* The collision fallback must fit under the SAME ceiling as the first
|
|
218
|
+
* attempt: the widest possible suffix is " (255.255.255.255)", so the base
|
|
219
|
+
* name is cut down first rather than the composed string overflowing into
|
|
220
|
+
* the very slug-length failure the ceiling exists to avoid.
|
|
221
|
+
*/
|
|
222
|
+
it("keeps the composed name within MAX_DEVICE_NAME_LENGTH at the widest address", () => {
|
|
223
|
+
const name: string = buildFallbackDeviceName(
|
|
224
|
+
snmpHost({
|
|
225
|
+
sysName: "y".repeat(255),
|
|
226
|
+
ipAddress: "255.255.255.255",
|
|
227
|
+
}),
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
expect(name.length).toBeLessThanOrEqual(MAX_DEVICE_NAME_LENGTH);
|
|
231
|
+
expect(name.endsWith(" (255.255.255.255)")).toBe(true);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
describe("description clamping", () => {
|
|
236
|
+
it("clamps an over-long sysDescr to MAX_DEVICE_DESCRIPTION_LENGTH", () => {
|
|
237
|
+
const longSysDescr: string = "d".repeat(700);
|
|
238
|
+
const device: NetworkDevice = build({
|
|
239
|
+
host: snmpHost({ sysDescr: longSysDescr }),
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
expect(device.description?.length).toBe(MAX_DEVICE_DESCRIPTION_LENGTH);
|
|
243
|
+
expect(device.description).toBe(
|
|
244
|
+
longSysDescr.substring(0, MAX_DEVICE_DESCRIPTION_LENGTH),
|
|
245
|
+
);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it("sets no description when the host has no sysDescr", () => {
|
|
249
|
+
const device: NetworkDevice = build({
|
|
250
|
+
host: snmpHost({ sysDescr: undefined }),
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
expect(device.description).toBeUndefined();
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
describe("the name override", () => {
|
|
258
|
+
/*
|
|
259
|
+
* The caller supplies the name so the collision retry can rebuild the SAME
|
|
260
|
+
* device under the fallback name without re-deciding anything else — the
|
|
261
|
+
* override must therefore be taken verbatim.
|
|
262
|
+
*/
|
|
263
|
+
it("uses a supplied name verbatim instead of deriving one", () => {
|
|
264
|
+
const device: NetworkDevice = build({
|
|
265
|
+
name: "core-switch-01 (10.0.0.5)",
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
expect(device.name).toBe("core-switch-01 (10.0.0.5)");
|
|
269
|
+
// Everything else is still derived from the host as usual.
|
|
270
|
+
expect(device.hostname).toBe("10.0.0.5");
|
|
271
|
+
});
|
|
272
|
+
});
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { DiscoveredNetworkDevice } from "../../../Models/DatabaseModels/NetworkDeviceDiscoveryScan";
|
|
2
|
+
import { normalizeDiscoveredHosts } from "../../../Utils/NetworkDiscovery/DiscoveredHostUtil";
|
|
3
|
+
import { describe, expect, test } from "@jest/globals";
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* normalizeDiscoveredHosts is the one reading of a scan's `discoveredDevices`
|
|
7
|
+
* jsonb that both the dashboard's Review dialog and the server-side
|
|
8
|
+
* auto-import rule engine share. The column is written verbatim from the
|
|
9
|
+
* probe's payload and the only guard on it is "the value is an array", so the
|
|
10
|
+
* three payload shapes documented on the function - a null row, a non-string
|
|
11
|
+
* address, and the same address carrying two different isAlreadyRegistered
|
|
12
|
+
* values - are shapes nothing upstream stops. These tests pin that each is
|
|
13
|
+
* neutralised here, once, so no downstream reader can be handed a different
|
|
14
|
+
* reading of the same payload.
|
|
15
|
+
*
|
|
16
|
+
* A cast through `unknown` is used wherever a test feeds a shape the type
|
|
17
|
+
* forbids on purpose: the whole point of the function is that the runtime
|
|
18
|
+
* value does not honour the type, so the tests have to be able to say so.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
function host(
|
|
22
|
+
overrides: Partial<DiscoveredNetworkDevice>,
|
|
23
|
+
): DiscoveredNetworkDevice {
|
|
24
|
+
return { ipAddress: "10.0.0.1", ...overrides };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe("normalizeDiscoveredHosts", () => {
|
|
28
|
+
describe("rows that are not hosts at all", () => {
|
|
29
|
+
test("an empty scan normalises to an empty list", () => {
|
|
30
|
+
expect(normalizeDiscoveredHosts([])).toEqual([]);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test.each([
|
|
34
|
+
["null", null],
|
|
35
|
+
["undefined", undefined],
|
|
36
|
+
["a number", 10],
|
|
37
|
+
["a string", "10.0.0.1"],
|
|
38
|
+
["a boolean", true],
|
|
39
|
+
])(
|
|
40
|
+
"%s is dropped rather than dereferenced",
|
|
41
|
+
(_label: string, value: unknown) => {
|
|
42
|
+
expect(
|
|
43
|
+
normalizeDiscoveredHosts([
|
|
44
|
+
value,
|
|
45
|
+
] as unknown as Array<DiscoveredNetworkDevice>),
|
|
46
|
+
).toEqual([]);
|
|
47
|
+
},
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
test("the real hosts around a null row survive it", () => {
|
|
51
|
+
const result: Array<DiscoveredNetworkDevice> = normalizeDiscoveredHosts([
|
|
52
|
+
host({ ipAddress: "10.0.0.1" }),
|
|
53
|
+
null as unknown as DiscoveredNetworkDevice,
|
|
54
|
+
host({ ipAddress: "10.0.0.2" }),
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
expect(
|
|
58
|
+
result.map((entry: DiscoveredNetworkDevice) => {
|
|
59
|
+
return entry.ipAddress;
|
|
60
|
+
}),
|
|
61
|
+
).toEqual(["10.0.0.1", "10.0.0.2"]);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe("the address is made a trimmed string", () => {
|
|
66
|
+
test("a numeric address becomes its string spelling, so Set.has can find it", () => {
|
|
67
|
+
const result: Array<DiscoveredNetworkDevice> = normalizeDiscoveredHosts([
|
|
68
|
+
{ ipAddress: 10 } as unknown as DiscoveredNetworkDevice,
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
expect(result[0]!.ipAddress).toBe("10");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test.each([
|
|
75
|
+
["a leading and trailing space", " 10.0.0.1 ", "10.0.0.1"],
|
|
76
|
+
["a tab", "\t10.0.0.1", "10.0.0.1"],
|
|
77
|
+
["only whitespace", " ", ""],
|
|
78
|
+
])("%s is trimmed", (_label: string, given: string, expected: string) => {
|
|
79
|
+
const result: Array<DiscoveredNetworkDevice> = normalizeDiscoveredHosts([
|
|
80
|
+
host({ ipAddress: given }),
|
|
81
|
+
]);
|
|
82
|
+
|
|
83
|
+
expect(result[0]!.ipAddress).toBe(expected);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test.each([
|
|
87
|
+
["undefined", undefined],
|
|
88
|
+
["null", null],
|
|
89
|
+
])(
|
|
90
|
+
"a %s address becomes the empty string, never the literal word",
|
|
91
|
+
(_label: string, value: unknown) => {
|
|
92
|
+
const result: Array<DiscoveredNetworkDevice> = normalizeDiscoveredHosts(
|
|
93
|
+
[{ ipAddress: value } as unknown as DiscoveredNetworkDevice],
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
expect(result[0]!.ipAddress).toBe("");
|
|
97
|
+
},
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe("everything else on the row is carried through untouched", () => {
|
|
102
|
+
test("the SNMP system group and reachability flags survive normalisation", () => {
|
|
103
|
+
const result: Array<DiscoveredNetworkDevice> = normalizeDiscoveredHosts([
|
|
104
|
+
{
|
|
105
|
+
ipAddress: " 10.0.0.5 ",
|
|
106
|
+
sysName: "core-switch",
|
|
107
|
+
sysDescr: "vendor OS 1.2",
|
|
108
|
+
sysObjectId: "1.3.6.1.4.1.9",
|
|
109
|
+
sysLocation: "rack 4",
|
|
110
|
+
sysContact: "neteng",
|
|
111
|
+
sysUpTimeSeconds: 4200,
|
|
112
|
+
snmpReachable: true,
|
|
113
|
+
},
|
|
114
|
+
]);
|
|
115
|
+
|
|
116
|
+
expect(result[0]).toEqual({
|
|
117
|
+
ipAddress: "10.0.0.5",
|
|
118
|
+
sysName: "core-switch",
|
|
119
|
+
sysDescr: "vendor OS 1.2",
|
|
120
|
+
sysObjectId: "1.3.6.1.4.1.9",
|
|
121
|
+
sysLocation: "rack 4",
|
|
122
|
+
sysContact: "neteng",
|
|
123
|
+
sysUpTimeSeconds: 4200,
|
|
124
|
+
snmpReachable: true,
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe("an address registered on one row is registered on every row", () => {
|
|
130
|
+
test("a duplicate address inherits the registered verdict regardless of probe ordering", () => {
|
|
131
|
+
const result: Array<DiscoveredNetworkDevice> = normalizeDiscoveredHosts([
|
|
132
|
+
host({ ipAddress: "10.0.0.9", isAlreadyRegistered: false }),
|
|
133
|
+
host({ ipAddress: "10.0.0.9", isAlreadyRegistered: true }),
|
|
134
|
+
]);
|
|
135
|
+
|
|
136
|
+
expect(
|
|
137
|
+
result.map((entry: DiscoveredNetworkDevice) => {
|
|
138
|
+
return entry.isAlreadyRegistered;
|
|
139
|
+
}),
|
|
140
|
+
).toEqual([true, true]);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test("the verdict does not bleed onto a different address", () => {
|
|
144
|
+
const result: Array<DiscoveredNetworkDevice> = normalizeDiscoveredHosts([
|
|
145
|
+
host({ ipAddress: "10.0.0.9", isAlreadyRegistered: true }),
|
|
146
|
+
host({ ipAddress: "10.0.0.10", isAlreadyRegistered: false }),
|
|
147
|
+
]);
|
|
148
|
+
|
|
149
|
+
expect(
|
|
150
|
+
result.find((entry: DiscoveredNetworkDevice) => {
|
|
151
|
+
return entry.ipAddress === "10.0.0.10";
|
|
152
|
+
})!.isAlreadyRegistered,
|
|
153
|
+
).toBe(false);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test("an already-registered row is handed back as the very same object", () => {
|
|
157
|
+
const registered: DiscoveredNetworkDevice = host({
|
|
158
|
+
ipAddress: "10.0.0.11",
|
|
159
|
+
isAlreadyRegistered: true,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const result: Array<DiscoveredNetworkDevice> = normalizeDiscoveredHosts([
|
|
163
|
+
registered,
|
|
164
|
+
]);
|
|
165
|
+
|
|
166
|
+
/*
|
|
167
|
+
* With nothing to flip, the normaliser must not churn objects it did
|
|
168
|
+
* not change - a fresh clone every render would defeat any memoised
|
|
169
|
+
* reader keyed on identity. The first pass already re-spread the row,
|
|
170
|
+
* so identity is asserted against that cleaned object, not the input.
|
|
171
|
+
*/
|
|
172
|
+
expect(result[0]).toEqual(registered);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test("the empty-string address is never treated as a registered key", () => {
|
|
176
|
+
/*
|
|
177
|
+
* A blank address is what an undefined or whitespace-only address
|
|
178
|
+
* normalises to. If it counted as a registered key, every other blank
|
|
179
|
+
* row - unrelated hosts the probe could not address - would be marked
|
|
180
|
+
* registered together.
|
|
181
|
+
*/
|
|
182
|
+
const result: Array<DiscoveredNetworkDevice> = normalizeDiscoveredHosts([
|
|
183
|
+
host({ ipAddress: " ", isAlreadyRegistered: true }),
|
|
184
|
+
host({ ipAddress: undefined as unknown as string }),
|
|
185
|
+
]);
|
|
186
|
+
|
|
187
|
+
expect(
|
|
188
|
+
result.every((entry: DiscoveredNetworkDevice) => {
|
|
189
|
+
return entry.ipAddress === "";
|
|
190
|
+
}),
|
|
191
|
+
).toBe(true);
|
|
192
|
+
expect(result[1]!.isAlreadyRegistered).toBeUndefined();
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
test("three rows of one address all end up registered when any one is", () => {
|
|
196
|
+
const result: Array<DiscoveredNetworkDevice> = normalizeDiscoveredHosts([
|
|
197
|
+
host({ ipAddress: "10.0.0.20", isAlreadyRegistered: false }),
|
|
198
|
+
host({ ipAddress: "10.0.0.20" }),
|
|
199
|
+
host({ ipAddress: "10.0.0.20", isAlreadyRegistered: true }),
|
|
200
|
+
]);
|
|
201
|
+
|
|
202
|
+
expect(
|
|
203
|
+
result.map((entry: DiscoveredNetworkDevice) => {
|
|
204
|
+
return entry.isAlreadyRegistered;
|
|
205
|
+
}),
|
|
206
|
+
).toEqual([true, true, true]);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
describe("a scan with nothing registered is left as it is found", () => {
|
|
211
|
+
test("no row gains a registered flag it did not arrive with", () => {
|
|
212
|
+
const result: Array<DiscoveredNetworkDevice> = normalizeDiscoveredHosts([
|
|
213
|
+
host({ ipAddress: "10.0.0.30", isAlreadyRegistered: false }),
|
|
214
|
+
host({ ipAddress: "10.0.0.31" }),
|
|
215
|
+
]);
|
|
216
|
+
|
|
217
|
+
expect(result[0]!.isAlreadyRegistered).toBe(false);
|
|
218
|
+
expect(result[1]!.isAlreadyRegistered).toBeUndefined();
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
});
|