@oneuptime/common 12.0.25 → 12.0.26
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 +2 -0
- package/Models/AnalyticsModels/ThreatIntelIndicator.ts +413 -0
- package/Models/DatabaseModels/AlertSeverity.ts +4 -1
- package/Models/DatabaseModels/CephClusterFeed.ts +625 -0
- package/Models/DatabaseModels/CloudResourceFeed.ts +625 -0
- package/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +13 -0
- package/Models/DatabaseModels/DetectionRule.ts +9 -3
- package/Models/DatabaseModels/DockerHostFeed.ts +625 -0
- package/Models/DatabaseModels/DockerSwarmClusterFeed.ts +628 -0
- package/Models/DatabaseModels/GoogleSecOpsConnection.ts +9 -3
- package/Models/DatabaseModels/HostFeed.ts +625 -0
- package/Models/DatabaseModels/IncidentSeverity.ts +4 -1
- package/Models/DatabaseModels/Index.ts +22 -0
- package/Models/DatabaseModels/KubernetesClusterFeed.ts +628 -0
- package/Models/DatabaseModels/Monitor.ts +87 -0
- package/Models/DatabaseModels/NetworkDevice.ts +96 -5
- package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +92 -6
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +301 -31
- package/Models/DatabaseModels/NetworkSite.ts +120 -0
- package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +1 -0
- package/Models/DatabaseModels/PodmanHostFeed.ts +625 -0
- package/Models/DatabaseModels/ProxmoxClusterFeed.ts +626 -0
- package/Models/DatabaseModels/ScheduledMaintenance.ts +67 -0
- package/Models/DatabaseModels/ServiceFeed.ts +625 -0
- package/Models/DatabaseModels/TelemetrySourceMap.ts +474 -0
- package/Models/DatabaseModels/ThreatIntelFeed.ts +758 -0
- package/Models/DatabaseModels/UserOnCallLog.ts +1 -0
- package/Models/DatabaseModels/UserTotpAuth.ts +1 -0
- package/Models/DatabaseModels/UserWebAuthn.ts +1 -0
- package/Server/API/AlertAPI.ts +23 -1
- package/Server/API/BaseAPI.ts +14 -3
- package/Server/API/IncidentAPI.ts +41 -1
- package/Server/API/IncidentEpisodeAPI.ts +23 -1
- package/Server/API/MicrosoftTeamsAPI.ts +31 -2
- package/Server/API/ScheduledMaintenanceAPI.ts +23 -1
- package/Server/API/SlackAPI.ts +48 -0
- package/Server/API/TelemetryAPI.ts +167 -42
- package/Server/API/UserOnCallLogTimelineAPI.ts +75 -61
- package/Server/API/UserTotpAuthAPI.ts +67 -1
- package/Server/API/UserWebAuthnAPI.ts +44 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787923136162-MigrationName.ts +57 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789600000000-AddAutoProvisionedNetworkDeviceMonitors.ts +49 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789700000000-AddNetworkScaleIndexes.ts +129 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789800000000-WidenSecurityEventLastErrorColumns.ts +54 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789900000000-AddNetworkSiteRollupPolicyAndMaintenance.ts +64 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790000000000-AddTelemetrySourceMap.ts +64 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790000000001-AddSnmpConfigsToNetworkDeviceDiscoveryScan.ts +72 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790003445000-AddSnmpEnabledToNetworkDeviceDiscoveryScan.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790100000000-AddResourceActivityFeeds.ts +489 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +18 -0
- package/Server/Middleware/IdentityRateLimit.ts +53 -3
- package/Server/Services/AIService.ts +181 -41
- package/Server/Services/CephClusterFeedService.ts +99 -0
- package/Server/Services/CephClusterLabelRuleEngineService.ts +29 -0
- package/Server/Services/CephClusterOwnerRuleEngineService.ts +23 -0
- package/Server/Services/CephClusterOwnerTeamService.ts +129 -0
- package/Server/Services/CephClusterOwnerUserService.ts +123 -0
- package/Server/Services/CephClusterService.ts +223 -2
- package/Server/Services/CloudResourceFeedService.ts +99 -0
- package/Server/Services/CloudResourceLabelRuleEngineService.ts +30 -0
- package/Server/Services/CloudResourceOwnerRuleEngineService.ts +33 -0
- package/Server/Services/CloudResourceOwnerTeamService.ts +129 -0
- package/Server/Services/CloudResourceOwnerUserService.ts +123 -0
- package/Server/Services/CloudResourceService.ts +227 -2
- package/Server/Services/DatabaseService.ts +265 -0
- package/Server/Services/DockerHostFeedService.ts +99 -0
- package/Server/Services/DockerHostLabelRuleEngineService.ts +29 -0
- package/Server/Services/DockerHostOwnerRuleEngineService.ts +23 -0
- package/Server/Services/DockerHostOwnerTeamService.ts +129 -0
- package/Server/Services/DockerHostOwnerUserService.ts +123 -0
- package/Server/Services/DockerHostService.ts +227 -2
- package/Server/Services/DockerSwarmClusterFeedService.ts +102 -0
- package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +30 -0
- package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +24 -0
- package/Server/Services/DockerSwarmClusterOwnerTeamService.ts +133 -0
- package/Server/Services/DockerSwarmClusterOwnerUserService.ts +127 -0
- package/Server/Services/DockerSwarmClusterService.ts +229 -2
- package/Server/Services/EnterpriseLicenseService.ts +15 -7
- package/Server/Services/ExceptionAggregationService.ts +12 -2
- package/Server/Services/HostFeedService.ts +99 -0
- package/Server/Services/HostLabelRuleEngineService.ts +29 -0
- package/Server/Services/HostOwnerRuleEngineService.ts +23 -0
- package/Server/Services/HostOwnerTeamService.ts +129 -0
- package/Server/Services/HostOwnerUserService.ts +123 -0
- package/Server/Services/HostService.ts +215 -2
- package/Server/Services/IncidentService.ts +11 -0
- package/Server/Services/Index.ts +24 -0
- package/Server/Services/KubernetesClusterFeedService.ts +99 -0
- package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +30 -0
- package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +24 -0
- package/Server/Services/KubernetesClusterOwnerTeamService.ts +133 -0
- package/Server/Services/KubernetesClusterOwnerUserService.ts +127 -0
- package/Server/Services/KubernetesClusterService.ts +231 -2
- package/Server/Services/LogAggregationService.ts +23 -280
- package/Server/Services/MetricAggregationService.ts +98 -1
- package/Server/Services/MonitorService.ts +177 -13
- package/Server/Services/MonitorTemplateService.ts +111 -0
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +777 -86
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +199 -16
- package/Server/Services/NetworkDeviceDiscoveryScanService.ts +1055 -14
- package/Server/Services/NetworkDeviceService.ts +750 -4
- package/Server/Services/NetworkInterfaceService.ts +415 -0
- package/Server/Services/NetworkSiteService.ts +485 -52
- package/Server/Services/PodmanHostFeedService.ts +99 -0
- package/Server/Services/PodmanHostLabelRuleEngineService.ts +29 -0
- package/Server/Services/PodmanHostOwnerRuleEngineService.ts +23 -0
- package/Server/Services/PodmanHostOwnerTeamService.ts +129 -0
- package/Server/Services/PodmanHostOwnerUserService.ts +123 -0
- package/Server/Services/PodmanHostService.ts +227 -2
- package/Server/Services/ProjectService.ts +16 -10
- package/Server/Services/ProxmoxClusterFeedService.ts +99 -0
- package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +30 -0
- package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +24 -0
- package/Server/Services/ProxmoxClusterOwnerTeamService.ts +131 -0
- package/Server/Services/ProxmoxClusterOwnerUserService.ts +124 -0
- package/Server/Services/ProxmoxClusterService.ts +225 -2
- package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +61 -0
- package/Server/Services/ServiceFeedService.ts +99 -0
- package/Server/Services/ServiceLabelRuleEngineService.ts +29 -0
- package/Server/Services/ServiceOwnerRuleEngineService.ts +26 -0
- package/Server/Services/ServiceOwnerTeamService.ts +129 -0
- package/Server/Services/ServiceOwnerUserService.ts +123 -0
- package/Server/Services/ServiceService.ts +227 -3
- package/Server/Services/StatusPageSubscriberService.ts +7 -0
- package/Server/Services/TelemetryAttributeService.ts +13 -3
- package/Server/Services/TelemetrySourceMapService.ts +307 -0
- package/Server/Services/ThreatIntelFeedService.ts +222 -0
- package/Server/Services/ThreatIntelIndicatorService.ts +428 -0
- package/Server/Services/TraceAggregationService.ts +101 -11
- package/Server/Services/UserService.ts +13 -6
- package/Server/Services/UserTwoFactorBackupCodeService.ts +127 -0
- package/Server/Services/UserWebhookService.ts +11 -2
- package/Server/Static/Brand/README.md +38 -0
- package/Server/Static/Brand/favicons/apple-touch-icon.png +0 -0
- package/Server/Static/Brand/favicons/favicon-16x16.png +0 -0
- package/Server/Static/Brand/favicons/favicon-32x32.png +0 -0
- package/Server/Static/Brand/favicons/favicon.ico +0 -0
- package/Server/Static/Brand/favicons/safari-pinned-tab.svg +31 -0
- package/Server/Static/Brand/hou-wb.svg +1 -0
- package/Server/Static/Brand/oneuptime-logo.svg +1 -0
- package/Server/Static/Brand/ou-wb.svg +1 -0
- package/Server/Static/Vendor/README.md +4 -0
- package/Server/Types/AnalyticsDatabase/ModelPermission.ts +13 -3
- package/Server/Types/Database/AggregateBy.ts +83 -0
- package/Server/Types/Database/AggregateResultUtil.ts +126 -0
- package/Server/Types/Database/JSONColumnQuery.ts +18 -0
- package/Server/Types/Database/QueryHelper.ts +40 -0
- package/Server/Types/Database/QueryUtil.ts +26 -0
- package/Server/Types/Workflow/Components/API/Utils.ts +10 -1
- package/Server/Types/Workflow/Components/JavaScript.ts +8 -0
- package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +9 -0
- package/Server/Utils/AI/SRE/InvestigationGrader.ts +18 -0
- package/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.ts +422 -0
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +176 -0
- package/Server/Utils/DataSource/HttpFetch.ts +18 -0
- package/Server/Utils/Database/RelationIdUtil.ts +42 -0
- package/Server/Utils/Marketing/MarketingEventUtil.ts +38 -9
- package/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.ts +34 -3
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +9 -1
- package/Server/Utils/Monitor/Criteria/SyntheticMonitor.ts +28 -10
- package/Server/Utils/Monitor/MonitorAlert.ts +541 -332
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +330 -64
- package/Server/Utils/Monitor/MonitorIncident.ts +640 -434
- package/Server/Utils/Monitor/MonitorResource.ts +226 -49
- package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +46 -3
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +23 -102
- package/Server/Utils/Monitor/PerEntityCriteriaFanOut.ts +329 -0
- package/Server/Utils/NetworkDevice/DeviceHealthAggregation.ts +427 -0
- package/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.ts +310 -0
- package/Server/Utils/OnCallNotificationContext.ts +686 -0
- package/Server/Utils/PrivateNetworkWebhookConfig.ts +549 -0
- package/Server/Utils/ResourceFeed/ResourceFeedUtil.ts +139 -0
- package/Server/Utils/Response.ts +11 -1
- package/Server/Utils/SSRFProtection.ts +230 -60
- package/Server/Utils/SecurityEvent/ConnectorErrorMessage.ts +106 -0
- package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +84 -284
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +47 -20
- package/Server/Utils/SecurityEvent/SecurityEventAlerting.ts +318 -0
- package/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.ts +199 -0
- package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.ts +252 -0
- package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.ts +739 -0
- package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.ts +533 -0
- package/Server/Utils/StartServer.ts +83 -56
- package/Server/Utils/StatusPageSubscriberWebhook.ts +3 -0
- package/Server/Utils/Telemetry/SourceMapResolver.ts +480 -0
- package/Server/Utils/TwoFactorBackupCodeNotification.ts +106 -0
- package/Server/Utils/VM/VMAPI.ts +3 -0
- package/Server/Utils/VM/VMRunner.ts +27 -1
- package/Server/Utils/VendorAssets.ts +42 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +136 -6
- package/Server/Views/AcknowledgeUserOnCallNotification.ejs +11 -9
- package/Server/Views/Partials/Head.ejs +9 -9
- package/Server/Views/Partials/OnCallNotificationDetails.ejs +48 -0
- package/Server/Views/ViewMessage.ejs +11 -9
- package/Tests/App/Accounts/LoginTwoFactorRecovery.test.tsx +972 -0
- package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +401 -0
- package/Tests/App/Dashboard/DiscoveryScanEditForm.test.tsx +707 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +1908 -18
- package/Tests/App/Dashboard/ResourceFeed.test.tsx +230 -0
- package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +216 -0
- package/Tests/App/Dashboard/TopologyAddToMonitoring.test.tsx +192 -0
- package/Tests/App/Dashboard/WorkspaceNotificationRuleConditions.test.tsx +439 -0
- package/Tests/Models/DatabaseModels/DateColumnDeserialization.test.ts +182 -0
- package/Tests/Models/DatabaseModels/RelationColumnModelTypeCoverage.test.ts +82 -0
- package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +398 -0
- package/Tests/Models/DiscoveryScanNameColumn.test.ts +151 -16
- package/Tests/Models/DiscoveryScanSnmpEnabledColumn.test.ts +593 -0
- package/Tests/Models/NetworkDeviceCreateContract.test.ts +102 -0
- package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +607 -0
- package/Tests/Server/API/AIGenerationRequestBudget.test.ts +355 -0
- package/Tests/Server/API/AIKillSwitchBackstop.test.ts +602 -0
- package/Tests/Server/API/BaseAPIUpdateDateColumns.test.ts +154 -0
- package/Tests/Server/API/MicrosoftTeamsBotTestEndpoint.test.ts +335 -0
- package/Tests/Server/API/UserOnCallLogTimelineAcknowledgePage.test.ts +611 -0
- package/Tests/Server/API/UserTotpAuthAPI.test.ts +498 -4
- package/Tests/Server/API/UserWebAuthnBackupCodeMinting.test.ts +682 -0
- package/Tests/Server/Infrastructure/ExampleDockerfiles.test.ts +595 -0
- package/Tests/Server/Services/AIServiceDailyBudget.test.ts +9 -0
- package/Tests/Server/Services/AIServiceProjectAccess.test.ts +6 -0
- package/Tests/Server/Services/AutoImportScanCredentialSelect.test.ts +18 -0
- package/Tests/Server/Services/DatabaseServiceAggregateBy.test.ts +590 -0
- package/Tests/Server/Services/DatabaseServiceUpdateWriteRouting.test.ts +12 -0
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +162 -26
- package/Tests/Server/Services/EnterpriseLicenseServiceCreate.test.ts +292 -0
- package/Tests/Server/Services/FeedRetentionConsistency.test.ts +119 -12
- package/Tests/Server/Services/LogAggregationAttributeOperators.test.ts +109 -0
- package/Tests/Server/Services/MetricAggregationAttributeOperators.test.ts +170 -0
- package/Tests/Server/Services/MonitorTemplateServiceNetworkDeviceSync.test.ts +383 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +997 -3
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +830 -0
- package/Tests/Server/Services/NetworkDeviceAutoMonitorLifecycle.test.ts +528 -0
- package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +3141 -1
- package/Tests/Server/Services/NetworkDeviceRegisteredHostnames.test.ts +1023 -0
- package/Tests/Server/Services/NetworkDeviceSiteAssignmentRuleSkip.test.ts +728 -0
- package/Tests/Server/Services/NetworkInterfaceServiceUpsert.test.ts +795 -0
- package/Tests/Server/Services/NetworkSiteRollupPolicyAndMaintenance.test.ts +903 -0
- package/Tests/Server/Services/NetworkSiteService.test.ts +165 -24
- package/Tests/Server/Services/ProjectServiceChangePlan.test.ts +5 -3
- package/Tests/Server/Services/ProjectServiceCreateSubscriptionStarted.test.ts +5 -2
- package/Tests/Server/Services/ResourceCreationFeedWrites.test.ts +304 -0
- package/Tests/Server/Services/ResourceFeedServices.test.ts +269 -0
- package/Tests/Server/Services/ResourceOwnerFeedWrites.test.ts +245 -0
- package/Tests/Server/Services/SecurityEventLastErrorColumnWidth.test.ts +792 -0
- package/Tests/Server/Services/TelemetrySourceMapService.test.ts +483 -0
- package/Tests/Server/Services/ThreatIntelFeedService.test.ts +351 -0
- package/Tests/Server/Services/ThreatIntelIndicatorService.test.ts +366 -0
- package/Tests/Server/Services/TraceAggregationAttributeOperators.test.ts +507 -0
- package/Tests/Server/Services/UserTwoFactorBackupCodeGenerateIfNone.test.ts +705 -0
- package/Tests/Server/Services/WorkspaceNotificationRuleOnCallDutyPolicy.test.ts +306 -0
- package/Tests/Server/Types/Database/AggregateResultUtil.test.ts +386 -0
- package/Tests/Server/Types/Database/Permissions/SelectRejectionMessageContract.test.ts +424 -0
- package/Tests/Server/Types/Database/QueryHelperWildcard.test.ts +142 -0
- package/Tests/Server/Types/Workflow/Components/ApiComponentPrivateNetwork.test.ts +163 -0
- package/Tests/Server/Types/Workflow/Components/JavaScriptPrivateNetwork.test.ts +124 -0
- package/Tests/Server/Utils/AI/CodeFixAgentCompletion.test.ts +5 -0
- package/Tests/Server/Utils/AI/InvestigationGrader.test.ts +39 -1
- package/Tests/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.test.ts +338 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorWildcard.test.ts +383 -0
- package/Tests/Server/Utils/Marketing/EmittedMarketingEvent.ts +23 -0
- package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +51 -0
- package/Tests/Server/Utils/Monitor/Criteria/SyntheticMonitorCriteria.test.ts +259 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPerSeriesFanout.test.ts +557 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +12 -2
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkLogWritePath.test.ts +404 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +8 -2
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +125 -98
- package/Tests/Server/Utils/Monitor/PerEntityCriteriaFanOut.test.ts +444 -0
- package/Tests/Server/Utils/Monitor/PerSeriesSecondEntityAlerting.test.ts +1112 -0
- package/Tests/Server/Utils/NetworkDevice/DeviceHealthAggregation.test.ts +717 -0
- package/Tests/Server/Utils/NetworkDevice/RulePatternValidator.test.ts +78 -0
- package/Tests/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.test.ts +363 -0
- package/Tests/Server/Utils/OfflineAssetHygiene.test.ts +35 -0
- package/Tests/Server/Utils/OnCallNotificationContext.test.ts +908 -0
- package/Tests/Server/Utils/PrivateNetworkWebhookConfig.test.ts +423 -0
- package/Tests/Server/Utils/ResourceFeed/ResourceFeedUtil.test.ts +191 -0
- package/Tests/Server/Utils/SSRFProtectionPrivateNetwork.test.ts +597 -0
- package/Tests/Server/Utils/SecurityEvent/ConnectorErrorMessage.test.ts +819 -0
- package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +381 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +417 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +819 -0
- package/Tests/Server/Utils/SecurityEvent/SecurityEventAlerting.test.ts +246 -0
- package/Tests/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.test.ts +282 -0
- package/Tests/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.test.ts +312 -0
- package/Tests/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.test.ts +854 -0
- package/Tests/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.test.ts +437 -0
- package/Tests/Server/Utils/StartServerErrorStatus.test.ts +225 -0
- package/Tests/Server/Utils/StatusPage/MonitorRulePatternValidator.test.ts +62 -0
- package/Tests/Server/Utils/StatusPageSubscriberWebhookPrivateNetwork.test.ts +119 -0
- package/Tests/Server/Utils/Telemetry/SourceMapResolver.test.ts +542 -0
- package/Tests/Server/Utils/TwoFactorBackupCodeNotification.test.ts +272 -0
- package/Tests/Server/Utils/VM/VMRunnerPrivateNetworkWiring.test.ts +111 -0
- package/Tests/Server/Utils/VendorAssets.test.ts +117 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +101 -4
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsInstallStateDiagnostics.test.ts +922 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsRosterDiagnosticMessages.test.ts +642 -0
- package/Tests/Server/Views/OnCallAcknowledgePage.test.ts +430 -0
- package/Tests/Types/API/URLQueryString.test.ts +472 -0
- package/Tests/Types/BaseDatabase/Wildcard.test.ts +163 -0
- package/Tests/Types/BaseDatabase/WildcardPattern.test.ts +149 -0
- package/Tests/Types/Database/DateColumnValue.test.ts +265 -0
- package/Tests/Types/DateToIsoStringOrNull.test.ts +67 -0
- package/Tests/Types/Log/LogQueryToFilter.test.ts +218 -43
- package/Tests/Types/Monitor/KubernetesTemplateGroupByKeys.test.ts +225 -0
- package/Tests/Types/Monitor/TemplateGroupByKeys.test.ts +296 -0
- package/Tests/Types/NetworkAutomation/RuleRunResult.test.ts +102 -0
- package/Tests/Types/NetworkAutomation/RuleRunResultDescribe.test.ts +145 -0
- package/Tests/Types/NetworkSite/SiteHealthRollupPolicy.test.ts +58 -0
- package/Tests/Types/SerializableObjectDictionaryImportCycle.test.ts +15 -0
- package/Tests/Types/Telemetry/TelemetrySearchQuery.test.ts +620 -0
- package/Tests/Types/WhatsApp/WhatsAppTemplates.test.ts +110 -0
- package/Tests/Types/Workspace/NotificationRuleConditionUtil.test.ts +76 -6
- package/Tests/Types/Workspace/NotificationRules/NotificationRuleCondition.test.ts +16 -4
- package/Tests/Types/Workspace/NotificationRules/OnCallDutyPolicyConditions.test.ts +669 -0
- package/Tests/UI/Components/DictionaryFilterOperatorWildcard.test.ts +175 -0
- package/Tests/UI/Components/IconOpticalSize.test.tsx +377 -0
- package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardInstallGuidance.test.tsx +332 -0
- package/Tests/UI/MicrosoftTeams/MicrosoftTeamsInstallGuidanceContent.test.tsx +643 -0
- package/Tests/Utils/Monitor/InterfaceInventoryUtil.test.ts +824 -0
- package/Tests/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.test.ts +626 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +718 -0
- package/Tests/Utils/NetworkDevice/DeviceHealthStateUtil.test.ts +59 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +287 -2
- package/Tests/Utils/NetworkDiscovery/DiscoveryImportEligibility.test.ts +73 -0
- package/Tests/Utils/NetworkDiscovery/PingMonitorBuilder.test.ts +317 -0
- package/Tests/Utils/NetworkDiscovery/RescanIntervalUtil.test.ts +262 -0
- package/Tests/Utils/NetworkDiscovery/ScanModeUtil.test.ts +474 -0
- package/Tests/Utils/NetworkDiscovery/SnmpScanConfigUtil.test.ts +2442 -0
- package/Tests/Utils/NetworkSite/SiteMaintenanceUtil.test.ts +188 -0
- package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +522 -0
- package/Tests/Utils/NetworkSite/SiteUptimeUtil.test.ts +694 -0
- package/Tests/Utils/SecurityEvent/ThreatIntel/StixPatternParser.test.ts +281 -0
- package/Tests/Utils/Telemetry/CrossSignalScope.test.ts +87 -67
- package/Types/API/URL.ts +45 -10
- package/Types/AnalyticsDatabase/AnalyticsTableName.ts +8 -0
- package/Types/BaseDatabase/NotWildcard.ts +86 -0
- package/Types/BaseDatabase/Wildcard.ts +89 -0
- package/Types/BaseDatabase/WildcardPattern.ts +176 -0
- package/Types/Database/DateColumnValue.ts +184 -0
- package/Types/Database/TableColumn.ts +40 -5
- package/Types/Date.ts +37 -0
- package/Types/Email/EmailTemplateType.ts +1 -0
- package/Types/JSON.ts +8 -0
- package/Types/Log/LogQueryToFilter.ts +167 -129
- package/Types/Monitor/DockerAlertTemplates.ts +43 -12
- package/Types/Monitor/HostAlertTemplates.ts +31 -3
- package/Types/Monitor/KubernetesAlertTemplates.ts +98 -0
- package/Types/Monitor/MonitorStep.ts +49 -0
- package/Types/Monitor/PodmanAlertTemplates.ts +39 -12
- package/Types/Monitor/SnmpMonitor/CdpNeighbor.ts +14 -0
- package/Types/Monitor/SnmpMonitor/LldpNeighbor.ts +11 -0
- package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +11 -4
- package/Types/NetworkAutomation/RuleRunResult.ts +191 -2
- package/Types/NetworkSite/SiteHealthRollupPolicy.ts +96 -0
- package/Types/Permission.ts +411 -0
- package/Types/Probe/ProbeApiIngestResponse.ts +42 -0
- package/Types/SecurityEvent/ThreatIntelConstants.ts +118 -0
- package/Types/SerializableObjectDictionary.ts +8 -0
- package/Types/Telemetry/SourceMap.ts +56 -0
- package/Types/Telemetry/TelemetrySearchQuery.ts +949 -0
- package/Types/Workspace/NotificationRules/NotificationRuleCondition.ts +12 -1
- package/UI/Components/Dictionary/DictionaryFilterOperator.ts +83 -0
- package/UI/Components/Icon/Icon.tsx +28 -1
- package/UI/Components/LogsViewer/components/LogSearchBar.tsx +26 -4
- package/UI/Components/LogsViewer/components/LogSearchHelp.tsx +34 -16
- package/UI/Components/TelemetryViewer/components/TelemetrySearchBar.tsx +15 -2
- package/Utils/Metrics/MetricExplorerUrl.ts +77 -15
- package/Utils/Monitor/InterfaceInventoryUtil.ts +251 -0
- package/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.ts +333 -0
- package/Utils/Monitor/NetworkTopologyUtil.ts +249 -28
- package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +14 -6
- package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +2 -0
- package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +49 -18
- package/Utils/NetworkDiscovery/PingMonitorBuilder.ts +215 -0
- package/Utils/NetworkDiscovery/RescanIntervalUtil.ts +148 -0
- package/Utils/NetworkDiscovery/ScanModeUtil.ts +105 -0
- package/Utils/NetworkDiscovery/SnmpScanConfigUtil.ts +827 -0
- package/Utils/NetworkSite/SiteMaintenanceUtil.ts +110 -0
- package/Utils/NetworkSite/SiteStatusRollupUtil.ts +350 -19
- package/Utils/NetworkSite/SiteUptimeUtil.ts +422 -21
- package/Utils/SecurityEvent/ThreatIntel/StixPatternParser.ts +383 -0
- package/Utils/Telemetry/CrossSignalScope.ts +37 -39
- package/build/dist/Models/AnalyticsModels/Index.js +2 -0
- package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js +325 -0
- package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js.map +1 -0
- package/build/dist/Models/DatabaseModels/AlertSeverity.js +4 -1
- package/build/dist/Models/DatabaseModels/AlertSeverity.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephClusterFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/CephClusterFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/CloudResourceFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/CloudResourceFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +11 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DetectionRule.js +9 -3
- package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHostFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/DockerHostFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +9 -3
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +1 -1
- package/build/dist/Models/DatabaseModels/HostFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/HostFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncidentSeverity.js +4 -1
- package/build/dist/Models/DatabaseModels/IncidentSeverity.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +22 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesClusterFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/KubernetesClusterFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Monitor.js +81 -0
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +103 -7
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +91 -6
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +276 -31
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSite.js +124 -1
- package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +1 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/PodmanHostFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/PodmanHostFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ProxmoxClusterFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/ProxmoxClusterFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +66 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/ServiceFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/TelemetrySourceMap.js +496 -0
- package/build/dist/Models/DatabaseModels/TelemetrySourceMap.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js +800 -0
- package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js +1 -0
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserTotpAuth.js +1 -0
- package/build/dist/Models/DatabaseModels/UserTotpAuth.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWebAuthn.js +1 -0
- package/build/dist/Models/DatabaseModels/UserWebAuthn.js.map +1 -1
- package/build/dist/Server/API/AlertAPI.js +18 -1
- package/build/dist/Server/API/AlertAPI.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +8 -1
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentAPI.js +35 -1
- package/build/dist/Server/API/IncidentAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentEpisodeAPI.js +18 -1
- package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +30 -2
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js +18 -1
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
- package/build/dist/Server/API/SlackAPI.js +45 -0
- package/build/dist/Server/API/SlackAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +100 -35
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/API/UserOnCallLogTimelineAPI.js +64 -59
- package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
- package/build/dist/Server/API/UserTotpAuthAPI.js +65 -1
- package/build/dist/Server/API/UserTotpAuthAPI.js.map +1 -1
- package/build/dist/Server/API/UserWebAuthnAPI.js +42 -1
- package/build/dist/Server/API/UserWebAuthnAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787923136162-MigrationName.js +26 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787923136162-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789600000000-AddAutoProvisionedNetworkDeviceMonitors.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789600000000-AddAutoProvisionedNetworkDeviceMonitors.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789700000000-AddNetworkScaleIndexes.js +88 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789700000000-AddNetworkScaleIndexes.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789800000000-WidenSecurityEventLastErrorColumns.js +39 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789800000000-WidenSecurityEventLastErrorColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789900000000-AddNetworkSiteRollupPolicyAndMaintenance.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789900000000-AddNetworkSiteRollupPolicyAndMaintenance.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000000-AddTelemetrySourceMap.js +32 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000000-AddTelemetrySourceMap.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000001-AddSnmpConfigsToNetworkDeviceDiscoveryScan.js +61 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000001-AddSnmpConfigsToNetworkDeviceDiscoveryScan.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790003445000-AddSnmpEnabledToNetworkDeviceDiscoveryScan.js +23 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790003445000-AddSnmpEnabledToNetworkDeviceDiscoveryScan.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790100000000-AddResourceActivityFeeds.js +179 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790100000000-AddResourceActivityFeeds.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/IdentityRateLimit.js +40 -3
- package/build/dist/Server/Middleware/IdentityRateLimit.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +177 -30
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterFeedService.js +89 -0
- package/build/dist/Server/Services/CephClusterFeedService.js.map +1 -0
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/CephClusterOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterOwnerUserService.js +113 -0
- package/build/dist/Server/Services/CephClusterOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterService.js +175 -1
- package/build/dist/Server/Services/CephClusterService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceFeedService.js +89 -0
- package/build/dist/Server/Services/CloudResourceFeedService.js.map +1 -0
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +28 -3
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/CloudResourceOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceOwnerUserService.js +113 -0
- package/build/dist/Server/Services/CloudResourceOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceService.js +177 -1
- package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +201 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostFeedService.js +89 -0
- package/build/dist/Server/Services/DockerHostFeedService.js.map +1 -0
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/DockerHostOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostOwnerUserService.js +113 -0
- package/build/dist/Server/Services/DockerHostOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +177 -1
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterFeedService.js +90 -0
- package/build/dist/Server/Services/DockerSwarmClusterFeedService.js.map +1 -0
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/DockerSwarmClusterOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterOwnerUserService.js +113 -0
- package/build/dist/Server/Services/DockerSwarmClusterOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js +175 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseService.js +40 -30
- package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
- package/build/dist/Server/Services/ExceptionAggregationService.js +8 -2
- package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
- package/build/dist/Server/Services/HostFeedService.js +89 -0
- package/build/dist/Server/Services/HostFeedService.js.map +1 -0
- package/build/dist/Server/Services/HostLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/HostOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/HostOwnerUserService.js +113 -0
- package/build/dist/Server/Services/HostOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +175 -1
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +10 -0
- package/build/dist/Server/Services/IncidentService.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/KubernetesClusterFeedService.js +89 -0
- package/build/dist/Server/Services/KubernetesClusterFeedService.js.map +1 -0
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/KubernetesClusterOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterOwnerUserService.js +113 -0
- package/build/dist/Server/Services/KubernetesClusterOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterService.js +177 -1
- package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +19 -196
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricAggregationService.js +59 -0
- package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +115 -13
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +86 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +561 -67
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +130 -16
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +850 -8
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +594 -5
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkInterfaceService.js +306 -0
- package/build/dist/Server/Services/NetworkInterfaceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +408 -47
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostFeedService.js +89 -0
- package/build/dist/Server/Services/PodmanHostFeedService.js.map +1 -0
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/PodmanHostOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostOwnerUserService.js +113 -0
- package/build/dist/Server/Services/PodmanHostOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostService.js +177 -1
- package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +40 -30
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterFeedService.js +89 -0
- package/build/dist/Server/Services/ProxmoxClusterFeedService.js.map +1 -0
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js +113 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js +175 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +56 -0
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceFeedService.js +89 -0
- package/build/dist/Server/Services/ServiceFeedService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +27 -3
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +24 -0
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceOwnerTeamService.js +120 -0
- package/build/dist/Server/Services/ServiceOwnerTeamService.js.map +1 -1
- package/build/dist/Server/Services/ServiceOwnerUserService.js +113 -0
- package/build/dist/Server/Services/ServiceOwnerUserService.js.map +1 -1
- package/build/dist/Server/Services/ServiceService.js +173 -2
- package/build/dist/Server/Services/ServiceService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberService.js +7 -0
- package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryAttributeService.js +9 -3
- package/build/dist/Server/Services/TelemetryAttributeService.js.map +1 -1
- package/build/dist/Server/Services/TelemetrySourceMapService.js +265 -0
- package/build/dist/Server/Services/TelemetrySourceMapService.js.map +1 -0
- package/build/dist/Server/Services/ThreatIntelFeedService.js +157 -0
- package/build/dist/Server/Services/ThreatIntelFeedService.js.map +1 -0
- package/build/dist/Server/Services/ThreatIntelIndicatorService.js +276 -0
- package/build/dist/Server/Services/ThreatIntelIndicatorService.js.map +1 -0
- package/build/dist/Server/Services/TraceAggregationService.js +62 -6
- package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +22 -13
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Services/UserTwoFactorBackupCodeService.js +120 -0
- package/build/dist/Server/Services/UserTwoFactorBackupCodeService.js.map +1 -1
- package/build/dist/Server/Services/UserWebhookService.js +11 -2
- package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js +12 -1
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/AggregateBy.js +2 -0
- package/build/dist/Server/Types/Database/AggregateBy.js.map +1 -0
- package/build/dist/Server/Types/Database/AggregateResultUtil.js +90 -0
- package/build/dist/Server/Types/Database/AggregateResultUtil.js.map +1 -0
- package/build/dist/Server/Types/Database/JSONColumnQuery.js +14 -0
- package/build/dist/Server/Types/Database/JSONColumnQuery.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +42 -0
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryUtil.js +18 -0
- package/build/dist/Server/Types/Database/QueryUtil.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js +10 -1
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/JavaScript.js +8 -0
- package/build/dist/Server/Types/Workflow/Components/JavaScript.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js +8 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +15 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.js +266 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.js.map +1 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +134 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/DataSource/HttpFetch.js +8 -0
- package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
- package/build/dist/Server/Utils/Database/RelationIdUtil.js +31 -0
- package/build/dist/Server/Utils/Database/RelationIdUtil.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js +26 -8
- package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js +42 -17
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +9 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SyntheticMonitor.js +15 -2
- package/build/dist/Server/Utils/Monitor/Criteria/SyntheticMonitor.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +386 -271
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +278 -64
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +469 -350
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +183 -44
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +46 -3
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +18 -91
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/PerEntityCriteriaFanOut.js +194 -0
- package/build/dist/Server/Utils/Monitor/PerEntityCriteriaFanOut.js.map +1 -0
- package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js +332 -0
- package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js.map +1 -0
- package/build/dist/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.js +279 -0
- package/build/dist/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.js.map +1 -0
- package/build/dist/Server/Utils/OnCallNotificationContext.js +415 -0
- package/build/dist/Server/Utils/OnCallNotificationContext.js.map +1 -0
- package/build/dist/Server/Utils/PrivateNetworkWebhookConfig.js +424 -0
- package/build/dist/Server/Utils/PrivateNetworkWebhookConfig.js.map +1 -0
- package/build/dist/Server/Utils/ResourceFeed/ResourceFeedUtil.js +108 -0
- package/build/dist/Server/Utils/ResourceFeed/ResourceFeedUtil.js.map +1 -0
- package/build/dist/Server/Utils/Response.js +12 -1
- package/build/dist/Server/Utils/Response.js.map +1 -1
- package/build/dist/Server/Utils/SSRFProtection.js +160 -58
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js +89 -0
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +75 -234
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +41 -16
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/SecurityEventAlerting.js +217 -0
- package/build/dist/Server/Utils/SecurityEvent/SecurityEventAlerting.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.js +103 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.js +168 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js +527 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js +376 -0
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js.map +1 -0
- package/build/dist/Server/Utils/StartServer.js +70 -44
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js +3 -0
- package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js +327 -0
- package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js.map +1 -0
- package/build/dist/Server/Utils/TwoFactorBackupCodeNotification.js +84 -0
- package/build/dist/Server/Utils/TwoFactorBackupCodeNotification.js.map +1 -0
- package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMRunner.js +10 -1
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Server/Utils/VendorAssets.js +29 -0
- package/build/dist/Server/Utils/VendorAssets.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +121 -6
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/API/URL.js +40 -10
- package/build/dist/Types/API/URL.js.map +1 -1
- package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +8 -0
- package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
- package/build/dist/Types/BaseDatabase/NotWildcard.js +72 -0
- package/build/dist/Types/BaseDatabase/NotWildcard.js.map +1 -0
- package/build/dist/Types/BaseDatabase/Wildcard.js +75 -0
- package/build/dist/Types/BaseDatabase/Wildcard.js.map +1 -0
- package/build/dist/Types/BaseDatabase/WildcardPattern.js +137 -0
- package/build/dist/Types/BaseDatabase/WildcardPattern.js.map +1 -0
- package/build/dist/Types/Database/DateColumnValue.js +125 -0
- package/build/dist/Types/Database/DateColumnValue.js.map +1 -0
- package/build/dist/Types/Database/TableColumn.js +18 -2
- package/build/dist/Types/Database/TableColumn.js.map +1 -1
- package/build/dist/Types/Date.js +31 -0
- package/build/dist/Types/Date.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/JSON.js +2 -0
- package/build/dist/Types/JSON.js.map +1 -1
- package/build/dist/Types/Log/LogQueryToFilter.js +111 -108
- package/build/dist/Types/Log/LogQueryToFilter.js.map +1 -1
- package/build/dist/Types/Monitor/DockerAlertTemplates.js +40 -16
- package/build/dist/Types/Monitor/DockerAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/HostAlertTemplates.js +29 -7
- package/build/dist/Types/Monitor/HostAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +98 -4
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +40 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/PodmanAlertTemplates.js +36 -16
- package/build/dist/Types/Monitor/PodmanAlertTemplates.js.map +1 -1
- package/build/dist/Types/NetworkAutomation/RuleRunResult.js +90 -0
- package/build/dist/Types/NetworkAutomation/RuleRunResult.js.map +1 -1
- package/build/dist/Types/NetworkSite/SiteHealthRollupPolicy.js +84 -0
- package/build/dist/Types/NetworkSite/SiteHealthRollupPolicy.js.map +1 -0
- package/build/dist/Types/Permission.js +354 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js +100 -0
- package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js.map +1 -0
- package/build/dist/Types/SerializableObjectDictionary.js +8 -0
- package/build/dist/Types/SerializableObjectDictionary.js.map +1 -1
- package/build/dist/Types/Telemetry/SourceMap.js +9 -0
- package/build/dist/Types/Telemetry/SourceMap.js.map +1 -0
- package/build/dist/Types/Telemetry/TelemetrySearchQuery.js +661 -0
- package/build/dist/Types/Telemetry/TelemetrySearchQuery.js.map +1 -0
- package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js +12 -1
- package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js.map +1 -1
- package/build/dist/UI/Components/Dictionary/DictionaryFilterOperator.js +67 -0
- package/build/dist/UI/Components/Dictionary/DictionaryFilterOperator.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +28 -1
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogSearchBar.js +25 -4
- package/build/dist/UI/Components/LogsViewer/components/LogSearchBar.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogSearchHelp.js +36 -16
- package/build/dist/UI/Components/LogsViewer/components/LogSearchHelp.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js +14 -2
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js.map +1 -1
- package/build/dist/Utils/Metrics/MetricExplorerUrl.js +54 -9
- package/build/dist/Utils/Metrics/MetricExplorerUrl.js.map +1 -1
- package/build/dist/Utils/Monitor/InterfaceInventoryUtil.js +128 -0
- package/build/dist/Utils/Monitor/InterfaceInventoryUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js +190 -0
- package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +206 -28
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js +14 -7
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +34 -18
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js +163 -0
- package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/RescanIntervalUtil.js +99 -0
- package/build/dist/Utils/NetworkDiscovery/RescanIntervalUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ScanModeUtil.js +85 -0
- package/build/dist/Utils/NetworkDiscovery/ScanModeUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/SnmpScanConfigUtil.js +560 -0
- package/build/dist/Utils/NetworkDiscovery/SnmpScanConfigUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/SiteMaintenanceUtil.js +56 -0
- package/build/dist/Utils/NetworkSite/SiteMaintenanceUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +185 -10
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
- package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js +248 -21
- package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js.map +1 -1
- package/build/dist/Utils/SecurityEvent/ThreatIntel/StixPatternParser.js +255 -0
- package/build/dist/Utils/SecurityEvent/ThreatIntel/StixPatternParser.js.map +1 -0
- package/build/dist/Utils/Telemetry/CrossSignalScope.js +27 -30
- package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -1
- package/package.json +2 -1
- package/Tests/Types/Log/LogQueryParser.test.ts +0 -186
- package/Types/Log/LogQueryParser.ts +0 -252
- package/build/dist/Types/Log/LogQueryParser.js +0 -200
- package/build/dist/Types/Log/LogQueryParser.js.map +0 -1
|
@@ -0,0 +1,972 @@
|
|
|
1
|
+
import "@testing-library/jest-dom";
|
|
2
|
+
import {
|
|
3
|
+
afterEach,
|
|
4
|
+
beforeEach,
|
|
5
|
+
describe,
|
|
6
|
+
expect,
|
|
7
|
+
jest,
|
|
8
|
+
test,
|
|
9
|
+
} from "@jest/globals";
|
|
10
|
+
import { act, cleanup, render, screen, waitFor } from "@testing-library/react";
|
|
11
|
+
import userEvent from "@testing-library/user-event";
|
|
12
|
+
import { UserEvent } from "@testing-library/user-event/dist/types/setup/setup";
|
|
13
|
+
import * as React from "react";
|
|
14
|
+
import { MemoryRouter } from "react-router-dom";
|
|
15
|
+
|
|
16
|
+
/*
|
|
17
|
+
* OneUptime issue #3382 -- "No MFA recovery path".
|
|
18
|
+
*
|
|
19
|
+
* The bug shipped TWICE, and the reason it shipped twice is that every test
|
|
20
|
+
* this feature had was a grep over source text. Backup codes existed, the
|
|
21
|
+
* endpoint existed, the locale strings existed, and a source-text test could
|
|
22
|
+
* see all three -- but nothing in the product ever minted a code, so
|
|
23
|
+
* `backupCodeCount` was 0 for essentially every account, and the one recovery
|
|
24
|
+
* affordance on the sign-in page was gated on `backupCodeCount > 0`. A user
|
|
25
|
+
* who had lost their authenticator saw a list of one method they could not
|
|
26
|
+
* use and NOTHING else. Indistinguishable, on screen, from a build where the
|
|
27
|
+
* feature had never been written.
|
|
28
|
+
*
|
|
29
|
+
* So this file renders the real sign-in page and asserts what a locked-out
|
|
30
|
+
* person can actually see and click. Every test below is a screen the reporter
|
|
31
|
+
* was looking at.
|
|
32
|
+
*
|
|
33
|
+
* WHY THE REAL TRANSLATIONS. The page's entire user-visible surface comes out
|
|
34
|
+
* of `t()`, so a passthrough `t` that echoes its key would let this suite pass
|
|
35
|
+
* against a build whose locale files never gained the new strings -- the user
|
|
36
|
+
* would read "login.twoFactor.lostAccess" and the assertions would be happy.
|
|
37
|
+
* The Accounts feature set's own i18n module is imported instead (its language
|
|
38
|
+
* detector is stubbed to English by Common's jest config), and the assertions
|
|
39
|
+
* are on the English sentences from Locales/en.json. A missing or renamed key
|
|
40
|
+
* therefore fails here rather than rendering as a dotted path in production.
|
|
41
|
+
*
|
|
42
|
+
* WHY THE FORM IS DRIVEN, NOT STUBBED. The two factor state is entered from
|
|
43
|
+
* the login ModelForm's `onSuccess`, so the form is filled in and submitted
|
|
44
|
+
* like a person would, with ModelAPI.createOrUpdate standing in for the
|
|
45
|
+
* network. That keeps the branch order in `onSuccess` (enrolment before
|
|
46
|
+
* method lists before plain login) under test as well as the screens.
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
import ModelAPI, {
|
|
50
|
+
ModelAPIHttpResponse,
|
|
51
|
+
} from "../../../UI/Utils/ModelAPI/ModelAPI";
|
|
52
|
+
import API from "../../../UI/Utils/API/API";
|
|
53
|
+
import HTTPResponse from "../../../Types/API/HTTPResponse";
|
|
54
|
+
import LoginUtil from "../../../UI/Utils/Login";
|
|
55
|
+
import Navigation from "../../../UI/Utils/Navigation";
|
|
56
|
+
import UserUtil from "../../../UI/Utils/User";
|
|
57
|
+
import UiAnalytics from "../../../UI/Utils/Analytics";
|
|
58
|
+
import User from "../../../Models/DatabaseModels/User";
|
|
59
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
60
|
+
|
|
61
|
+
/*
|
|
62
|
+
* The edition pill fetches the instance's global config on mount. It is page
|
|
63
|
+
* chrome with nothing to do with recovery, and stubbing the component is a
|
|
64
|
+
* smaller lie than stubbing the fetch it makes.
|
|
65
|
+
*/
|
|
66
|
+
jest.mock("../../../UI/Components/EditionLabel/EditionLabel", () => {
|
|
67
|
+
return {
|
|
68
|
+
__esModule: true,
|
|
69
|
+
default: (): null => {
|
|
70
|
+
return null;
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Registers the Accounts locale resources on the shared i18next instance.
|
|
76
|
+
import "../../../../App/FeatureSet/Accounts/src/Utils/i18n";
|
|
77
|
+
import LoginPage from "../../../../App/FeatureSet/Accounts/src/Pages/Login";
|
|
78
|
+
|
|
79
|
+
const USER_ID: string = "33333333-3333-4333-8333-333333333333";
|
|
80
|
+
const USER_EMAIL: string = "ada@analytical-engine.example.com";
|
|
81
|
+
const TOTP_ID: string = "11111111-1111-4111-8111-111111111111";
|
|
82
|
+
const WEBAUTHN_ID: string = "22222222-2222-4222-8222-222222222222";
|
|
83
|
+
|
|
84
|
+
const PASSWORD: string = "correct-horse-battery";
|
|
85
|
+
|
|
86
|
+
/* Straight out of en.json, so a dropped key is a failure rather than a pass. */
|
|
87
|
+
const LOST_ACCESS: string = "Lost access to your authenticator?";
|
|
88
|
+
|
|
89
|
+
/*
|
|
90
|
+
* The security-key screen asks the question about the right object. "Lost
|
|
91
|
+
* access to your authenticator?" is the wrong noun for somebody whose hardware
|
|
92
|
+
* key is what is gone, and an affordance a locked-out user does not recognise
|
|
93
|
+
* as addressed to them is the same failure the whole issue was filed about.
|
|
94
|
+
*/
|
|
95
|
+
const LOST_ACCESS_SECURITY_KEY: string = "Lost access to your security key?";
|
|
96
|
+
const BACK_TO_PICKER: string =
|
|
97
|
+
"Select a different two factor authentication method";
|
|
98
|
+
const SKIP_FOR_NOW: string = "Skip for now";
|
|
99
|
+
const REGISTER_LINK: string = "Register.";
|
|
100
|
+
const ADMIN_RESET: string = "reset two factor authentication on your account";
|
|
101
|
+
|
|
102
|
+
type LoginMockCall = { user?: unknown; token?: unknown };
|
|
103
|
+
|
|
104
|
+
let loginCalls: Array<LoginMockCall> = [];
|
|
105
|
+
let postedUrls: Array<string> = [];
|
|
106
|
+
|
|
107
|
+
/*
|
|
108
|
+
* What the mocked /login answers with. Set per test, read when the form is
|
|
109
|
+
* submitted.
|
|
110
|
+
*/
|
|
111
|
+
let loginMiscData: JSONObject = {};
|
|
112
|
+
|
|
113
|
+
/* What the mocked second-step endpoints answer with. */
|
|
114
|
+
let secondStepMiscData: JSONObject = {};
|
|
115
|
+
|
|
116
|
+
/* What the mocked /user-two-factor-backup-code/generate answers with. */
|
|
117
|
+
let generatedCodes: Array<string> = [];
|
|
118
|
+
|
|
119
|
+
/*
|
|
120
|
+
* Which account is signing in. Variable rather than a constant because the
|
|
121
|
+
* "skip for now" snooze is keyed on it, and the test that matters most about
|
|
122
|
+
* that keying is the one where a SECOND account signs in on the same browser
|
|
123
|
+
* and must still be asked.
|
|
124
|
+
*/
|
|
125
|
+
let signedInUserId: string = USER_ID;
|
|
126
|
+
|
|
127
|
+
type UserJsonFunction = () => JSONObject;
|
|
128
|
+
|
|
129
|
+
const userJson: UserJsonFunction = (): JSONObject => {
|
|
130
|
+
return {
|
|
131
|
+
_id: signedInUserId,
|
|
132
|
+
email: USER_EMAIL,
|
|
133
|
+
name: "Ada Lovelace",
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
type TotpJsonFunction = (name: string) => JSONObject;
|
|
138
|
+
|
|
139
|
+
const totpJson: TotpJsonFunction = (name: string): JSONObject => {
|
|
140
|
+
return { _id: TOTP_ID, name: name };
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
type WebAuthnJsonFunction = (name: string) => JSONObject;
|
|
144
|
+
|
|
145
|
+
const webAuthnJson: WebAuthnJsonFunction = (name: string): JSONObject => {
|
|
146
|
+
return { _id: WEBAUTHN_ID, name: name };
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
type SetupUserFunction = () => UserEvent;
|
|
150
|
+
|
|
151
|
+
/*
|
|
152
|
+
* No inter-keystroke delay: Input mirrors its value onto the DOM node from an
|
|
153
|
+
* effect, so a keystroke that lands before React has committed the previous
|
|
154
|
+
* one is overwritten and lost. See the same note in BasicForm.test.tsx.
|
|
155
|
+
*/
|
|
156
|
+
const setupUser: SetupUserFunction = (): UserEvent => {
|
|
157
|
+
return userEvent.setup({ delay: null });
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
type RenderPageFunction = () => void;
|
|
161
|
+
|
|
162
|
+
const renderPage: RenderPageFunction = (): void => {
|
|
163
|
+
render(
|
|
164
|
+
<MemoryRouter>
|
|
165
|
+
<LoginPage />
|
|
166
|
+
</MemoryRouter>,
|
|
167
|
+
);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
type SubmitPasswordFunction = () => Promise<void>;
|
|
171
|
+
|
|
172
|
+
// The first step, typed in as a person types it.
|
|
173
|
+
const submitPassword: SubmitPasswordFunction = async (): Promise<void> => {
|
|
174
|
+
const user: UserEvent = setupUser();
|
|
175
|
+
|
|
176
|
+
/*
|
|
177
|
+
* ModelForm assembles its field list in an async effect, so the boxes do
|
|
178
|
+
* not exist on the first paint.
|
|
179
|
+
*/
|
|
180
|
+
await user.type(await screen.findByTestId("email"), USER_EMAIL);
|
|
181
|
+
await user.type(screen.getByTestId("password"), PASSWORD);
|
|
182
|
+
|
|
183
|
+
/*
|
|
184
|
+
* The submit handler keeps running after the click returns, and the state
|
|
185
|
+
* it sets on the way out lands outside React's act() scope unless the whole
|
|
186
|
+
* awaited click is inside one.
|
|
187
|
+
*/
|
|
188
|
+
await act(async () => {
|
|
189
|
+
await user.click(screen.getByTestId("Login"));
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
type TwoFactorChallengeOptions = {
|
|
194
|
+
totpNames?: Array<string>;
|
|
195
|
+
webAuthnNames?: Array<string>;
|
|
196
|
+
/*
|
|
197
|
+
* `null` reproduces a /login that could NOT count the account's codes and
|
|
198
|
+
* therefore omitted the key. That is not the same wire shape as zero, and
|
|
199
|
+
* the page is required to tell them apart -- see the "unknown" tests below.
|
|
200
|
+
*/
|
|
201
|
+
backupCodeCount: number | null;
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
type StartTwoFactorChallengeFunction = (
|
|
205
|
+
options: TwoFactorChallengeOptions,
|
|
206
|
+
) => Promise<void>;
|
|
207
|
+
|
|
208
|
+
/*
|
|
209
|
+
* Sign in with a password on an account that has a second factor, and stop on
|
|
210
|
+
* whichever two factor screen that produces.
|
|
211
|
+
*/
|
|
212
|
+
const startTwoFactorChallenge: StartTwoFactorChallengeFunction = async (
|
|
213
|
+
options: TwoFactorChallengeOptions,
|
|
214
|
+
): Promise<void> => {
|
|
215
|
+
loginMiscData = {
|
|
216
|
+
totpAuthList: (options.totpNames || []).map(totpJson),
|
|
217
|
+
webAuthnList: (options.webAuthnNames || []).map(webAuthnJson),
|
|
218
|
+
...(options.backupCodeCount === null
|
|
219
|
+
? {}
|
|
220
|
+
: { backupCodeCount: options.backupCodeCount }),
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
renderPage();
|
|
224
|
+
await submitPassword();
|
|
225
|
+
|
|
226
|
+
await screen.findByText("Two Factor Authentication");
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
type StartForcedEnrolmentFunction = () => Promise<void>;
|
|
230
|
+
|
|
231
|
+
/*
|
|
232
|
+
* The other way onto a second factor: an administrator has mandated two factor
|
|
233
|
+
* auth (or just reset it for somebody who was locked out), so /login answers a
|
|
234
|
+
* correct password with a QR code and no session at all.
|
|
235
|
+
*/
|
|
236
|
+
const startForcedEnrolment: StartForcedEnrolmentFunction =
|
|
237
|
+
async (): Promise<void> => {
|
|
238
|
+
loginMiscData = {
|
|
239
|
+
twoFactorEnrolmentRequired: true,
|
|
240
|
+
twoFactorAuthId: TOTP_ID,
|
|
241
|
+
twoFactorOtpUrl: "otpauth://totp/OneUptime:ada?secret=ABCDEFGH",
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
renderPage();
|
|
245
|
+
await submitPassword();
|
|
246
|
+
|
|
247
|
+
await screen.findByText("Set Up Two Factor Authentication");
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
type SubmitEnrolmentCodeFunction = () => Promise<void>;
|
|
251
|
+
|
|
252
|
+
const submitEnrolmentCode: SubmitEnrolmentCodeFunction =
|
|
253
|
+
async (): Promise<void> => {
|
|
254
|
+
const user: UserEvent = setupUser();
|
|
255
|
+
|
|
256
|
+
await user.type(await screen.findByTestId("enrolment-code"), "123456");
|
|
257
|
+
|
|
258
|
+
await act(async () => {
|
|
259
|
+
await user.click(screen.getByTestId("Verify and Sign In"));
|
|
260
|
+
});
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
type EnterTotpCodeFunction = () => Promise<void>;
|
|
264
|
+
|
|
265
|
+
// The second step: pick the authenticator app and type its code.
|
|
266
|
+
const enterTotpCode: EnterTotpCodeFunction = async (): Promise<void> => {
|
|
267
|
+
const user: UserEvent = setupUser();
|
|
268
|
+
|
|
269
|
+
await user.click(screen.getByText("Authenticator App"));
|
|
270
|
+
await user.type(await screen.findByTestId("code"), "123456");
|
|
271
|
+
|
|
272
|
+
await act(async () => {
|
|
273
|
+
await user.click(screen.getByTestId("Login"));
|
|
274
|
+
});
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
type InstallMocksFunction = () => void;
|
|
278
|
+
|
|
279
|
+
/*
|
|
280
|
+
* Everything the page would otherwise reach for. The redirect in particular:
|
|
281
|
+
* every "was the user let through?" assertion below is really "was
|
|
282
|
+
* LoginUtil.login called?", and the real one navigates away from the only
|
|
283
|
+
* copy of the recovery codes that will ever exist.
|
|
284
|
+
*/
|
|
285
|
+
const installMocks: InstallMocksFunction = (): void => {
|
|
286
|
+
/*
|
|
287
|
+
* "Skip for now" is now REMEMBERED -- it writes a timestamp to local storage
|
|
288
|
+
* keyed by user id so an account with no codes is not stopped on every
|
|
289
|
+
* sign-in for the rest of its life. jsdom keeps one storage for the whole
|
|
290
|
+
* file, so without this a test that skips silences the offer for every later
|
|
291
|
+
* test that signs the same user in, and they fail asserting on a screen that
|
|
292
|
+
* was deliberately suppressed.
|
|
293
|
+
*/
|
|
294
|
+
try {
|
|
295
|
+
window.localStorage.clear();
|
|
296
|
+
} catch {
|
|
297
|
+
/* Nothing to clear is not a failure. */
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
signedInUserId = USER_ID;
|
|
301
|
+
loginCalls = [];
|
|
302
|
+
postedUrls = [];
|
|
303
|
+
loginMiscData = {};
|
|
304
|
+
secondStepMiscData = { token: "session-token" };
|
|
305
|
+
generatedCodes = [];
|
|
306
|
+
|
|
307
|
+
jest.spyOn(UserUtil, "isLoggedIn").mockReturnValue(false);
|
|
308
|
+
jest.spyOn(Navigation, "navigate").mockImplementation(() => {});
|
|
309
|
+
jest.spyOn(Navigation, "getQueryStringByName").mockReturnValue("");
|
|
310
|
+
jest.spyOn(UiAnalytics, "userAuth").mockImplementation(() => {});
|
|
311
|
+
jest.spyOn(UiAnalytics, "capture").mockImplementation(() => {});
|
|
312
|
+
|
|
313
|
+
jest.spyOn(LoginUtil, "login").mockImplementation((value: JSONObject) => {
|
|
314
|
+
loginCalls.push(value as LoginMockCall);
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
// The /login call the ModelForm makes.
|
|
318
|
+
jest
|
|
319
|
+
.spyOn(ModelAPI, "createOrUpdate")
|
|
320
|
+
.mockImplementation(async (): Promise<ModelAPIHttpResponse<User>> => {
|
|
321
|
+
const response: ModelAPIHttpResponse<User> =
|
|
322
|
+
new ModelAPIHttpResponse<User>(200, userJson(), {});
|
|
323
|
+
|
|
324
|
+
response.miscData = loginMiscData;
|
|
325
|
+
|
|
326
|
+
return response;
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// Every second-step call the page makes directly, routed by URL.
|
|
330
|
+
jest
|
|
331
|
+
.spyOn(API, "post")
|
|
332
|
+
.mockImplementation(
|
|
333
|
+
async (options: {
|
|
334
|
+
url?: { toString: () => string } | undefined;
|
|
335
|
+
}): Promise<HTTPResponse<JSONObject>> => {
|
|
336
|
+
const url: string = options.url?.toString() || "";
|
|
337
|
+
|
|
338
|
+
postedUrls.push(url);
|
|
339
|
+
|
|
340
|
+
if (url.includes("/user-two-factor-backup-code/generate")) {
|
|
341
|
+
return new HTTPResponse<JSONObject>(
|
|
342
|
+
200,
|
|
343
|
+
{ codes: generatedCodes },
|
|
344
|
+
{},
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/*
|
|
349
|
+
* Security keys do not exist in jsdom. The page has to survive that
|
|
350
|
+
* and keep the recovery link on screen -- which is precisely the
|
|
351
|
+
* screen somebody with a broken key is standing on.
|
|
352
|
+
*/
|
|
353
|
+
if (url.includes("/user-webauthn/generate-authentication-options")) {
|
|
354
|
+
throw new Error("No authenticator is available on this device.");
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return new HTTPResponse<JSONObject>(
|
|
358
|
+
200,
|
|
359
|
+
{ ...userJson(), _miscData: secondStepMiscData },
|
|
360
|
+
{},
|
|
361
|
+
);
|
|
362
|
+
},
|
|
363
|
+
);
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
describe("Two factor sign-in always offers a way out", () => {
|
|
367
|
+
beforeEach(() => {
|
|
368
|
+
installMocks();
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
afterEach(() => {
|
|
372
|
+
cleanup();
|
|
373
|
+
jest.restoreAllMocks();
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
/*
|
|
377
|
+
* THE REPORTED BUG, at its smallest.
|
|
378
|
+
*
|
|
379
|
+
* `backupCodeCount` is 0 here because that is what it was for essentially
|
|
380
|
+
* every real account: nothing in the product minted codes at setup time.
|
|
381
|
+
* The old page gated the recovery link on that count, so this screen had a
|
|
382
|
+
* list of methods and nothing else on it.
|
|
383
|
+
*/
|
|
384
|
+
test("the lost-access link is on the method picker even with no codes", async () => {
|
|
385
|
+
await startTwoFactorChallenge({
|
|
386
|
+
totpNames: ["Ada's phone"],
|
|
387
|
+
webAuthnNames: ["YubiKey"],
|
|
388
|
+
backupCodeCount: 0,
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
expect(screen.getByText(LOST_ACCESS)).toBeInTheDocument();
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
/*
|
|
395
|
+
* The screen the issue actually named. The old link lived INSIDE the method
|
|
396
|
+
* picker, so choosing a method took it away: the user was left staring at a
|
|
397
|
+
* box asking for a code they cannot produce, with "select a different
|
|
398
|
+
* method" as the only exit -- back to a list of methods they already told us
|
|
399
|
+
* they cannot use.
|
|
400
|
+
*/
|
|
401
|
+
test("the lost-access link is on the code-entry screen the issue named", async () => {
|
|
402
|
+
await startTwoFactorChallenge({
|
|
403
|
+
totpNames: ["Ada's phone"],
|
|
404
|
+
backupCodeCount: 0,
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
const user: UserEvent = setupUser();
|
|
408
|
+
await user.click(screen.getByText("Authenticator App"));
|
|
409
|
+
|
|
410
|
+
expect(await screen.findByTestId("code")).toBeInTheDocument();
|
|
411
|
+
expect(screen.getByText(LOST_ACCESS)).toBeInTheDocument();
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
test("the lost-access link is on the security-key screen too", async () => {
|
|
415
|
+
await startTwoFactorChallenge({
|
|
416
|
+
webAuthnNames: ["YubiKey"],
|
|
417
|
+
backupCodeCount: 0,
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
const user: UserEvent = setupUser();
|
|
421
|
+
await user.click(screen.getByText("Security Key"));
|
|
422
|
+
|
|
423
|
+
await screen.findByText("Authenticating with Security Key");
|
|
424
|
+
|
|
425
|
+
await waitFor(() => {
|
|
426
|
+
expect(screen.getByText(LOST_ACCESS_SECURITY_KEY)).toBeInTheDocument();
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
/* And it does not ask about an authenticator app they may not own. */
|
|
430
|
+
expect(screen.queryByText(LOST_ACCESS)).not.toBeInTheDocument();
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
/*
|
|
434
|
+
* Until the link above existed, "Don't have an account? Register." was the
|
|
435
|
+
* only other thing on a two factor screen -- an offer to make a second
|
|
436
|
+
* account, made to somebody who is locked out of the one they have.
|
|
437
|
+
*/
|
|
438
|
+
test("a locked-out user is not offered the registration link instead", async () => {
|
|
439
|
+
await startTwoFactorChallenge({
|
|
440
|
+
totpNames: ["Ada's phone"],
|
|
441
|
+
backupCodeCount: 0,
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
expect(screen.queryByText(REGISTER_LINK)).not.toBeInTheDocument();
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
/*
|
|
448
|
+
* What is behind the link for the population the issue was about. Not a
|
|
449
|
+
* form that would refuse every code they typed: the sentence naming who can
|
|
450
|
+
* reset their two factor auth, which is the only true answer to their
|
|
451
|
+
* question and one nothing in the product used to give.
|
|
452
|
+
*/
|
|
453
|
+
test("with no codes, the link explains the administrator reset", async () => {
|
|
454
|
+
await startTwoFactorChallenge({
|
|
455
|
+
totpNames: ["Ada's phone"],
|
|
456
|
+
backupCodeCount: 0,
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
const user: UserEvent = setupUser();
|
|
460
|
+
await user.click(screen.getByText(LOST_ACCESS));
|
|
461
|
+
|
|
462
|
+
const guidance: HTMLElement = await screen.findByTestId("no-backup-codes");
|
|
463
|
+
|
|
464
|
+
expect(guidance).toHaveTextContent("You have no backup codes.");
|
|
465
|
+
expect(guidance).toHaveTextContent(ADMIN_RESET);
|
|
466
|
+
|
|
467
|
+
/*
|
|
468
|
+
* And no code box. Offering one to an account with no codes is offering a
|
|
469
|
+
* form that can only ever say "invalid" -- which reads as "you typed it
|
|
470
|
+
* wrong", not "there was never a code to type".
|
|
471
|
+
*/
|
|
472
|
+
expect(screen.queryByTestId("backup-code")).not.toBeInTheDocument();
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
test("with codes, the link opens the backup code form and not the guidance", async () => {
|
|
476
|
+
await startTwoFactorChallenge({
|
|
477
|
+
totpNames: ["Ada's phone"],
|
|
478
|
+
backupCodeCount: 8,
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
const user: UserEvent = setupUser();
|
|
482
|
+
await user.click(screen.getByText(LOST_ACCESS));
|
|
483
|
+
|
|
484
|
+
expect(await screen.findByTestId("backup-code")).toBeInTheDocument();
|
|
485
|
+
expect(screen.queryByTestId("no-backup-codes")).not.toBeInTheDocument();
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
/*
|
|
489
|
+
* Opening recovery by mistake must not be a trap. The "go back" link clears
|
|
490
|
+
* `isUsingBackupCode` as well as the two selections, because the picker is
|
|
491
|
+
* hidden while that flag is set -- without it, the link would appear to do
|
|
492
|
+
* nothing at all.
|
|
493
|
+
*/
|
|
494
|
+
/*
|
|
495
|
+
* "UNKNOWN" IS NOT "NONE".
|
|
496
|
+
*
|
|
497
|
+
* /login omits `backupCodeCount` entirely when it could not read it -- one
|
|
498
|
+
* bad index, one exhausted connection pool -- rather than reporting zero,
|
|
499
|
+
* because zero is a CLAIM and the page acts on it by telling the user they
|
|
500
|
+
* have nothing and should go and find an administrator. Said to somebody
|
|
501
|
+
* holding ten printed codes during a transient fault, that is both false and
|
|
502
|
+
* unrecoverable advice: they would stop trying the thing that works.
|
|
503
|
+
*
|
|
504
|
+
* Absent therefore has to behave like "there may be codes", which means the
|
|
505
|
+
* form.
|
|
506
|
+
*/
|
|
507
|
+
test("a count the server could not read still offers the code form", async () => {
|
|
508
|
+
await startTwoFactorChallenge({
|
|
509
|
+
totpNames: ["Ada's phone"],
|
|
510
|
+
backupCodeCount: null,
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
const user: UserEvent = setupUser();
|
|
514
|
+
await user.click(screen.getByText(LOST_ACCESS));
|
|
515
|
+
|
|
516
|
+
expect(await screen.findByTestId("backup-code")).toBeInTheDocument();
|
|
517
|
+
expect(screen.queryByTestId("no-backup-codes")).not.toBeInTheDocument();
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
test("the user can get back to the method picker from recovery", async () => {
|
|
521
|
+
await startTwoFactorChallenge({
|
|
522
|
+
totpNames: ["Ada's phone"],
|
|
523
|
+
webAuthnNames: ["YubiKey"],
|
|
524
|
+
backupCodeCount: 0,
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
const user: UserEvent = setupUser();
|
|
528
|
+
await user.click(screen.getByText(LOST_ACCESS));
|
|
529
|
+
await screen.findByTestId("no-backup-codes");
|
|
530
|
+
|
|
531
|
+
await user.click(screen.getByText(BACK_TO_PICKER));
|
|
532
|
+
|
|
533
|
+
expect(await screen.findByText("Authenticator App")).toBeInTheDocument();
|
|
534
|
+
expect(screen.getByText("Security Key")).toBeInTheDocument();
|
|
535
|
+
expect(screen.queryByTestId("no-backup-codes")).not.toBeInTheDocument();
|
|
536
|
+
});
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
describe("Finishing a two factor sign-in offers the codes that were missing", () => {
|
|
540
|
+
beforeEach(() => {
|
|
541
|
+
installMocks();
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
afterEach(() => {
|
|
545
|
+
cleanup();
|
|
546
|
+
jest.restoreAllMocks();
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
/*
|
|
550
|
+
* The population the whole issue was about: everybody who set two factor
|
|
551
|
+
* auth up before recovery codes existed. They are signed in at this point --
|
|
552
|
+
* the server has already set the session cookie -- and the ONLY moment the
|
|
553
|
+
* product has ever had their attention on their second factor is right now.
|
|
554
|
+
*
|
|
555
|
+
* The assertion that matters is the negative one: the redirect has not
|
|
556
|
+
* happened. An offer made after the navigation is an offer made to an empty
|
|
557
|
+
* page.
|
|
558
|
+
*/
|
|
559
|
+
test("an account with no codes is offered a set instead of being redirected", async () => {
|
|
560
|
+
await startTwoFactorChallenge({
|
|
561
|
+
totpNames: ["Ada's phone"],
|
|
562
|
+
backupCodeCount: 0,
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
await enterTotpCode();
|
|
566
|
+
|
|
567
|
+
expect(await screen.findByTestId("generate-backup-codes")).toBeVisible();
|
|
568
|
+
expect(loginCalls).toHaveLength(0);
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
/*
|
|
572
|
+
* ...and the offer can always be refused. A prompt that could wedge a
|
|
573
|
+
* sign-in the server has already completed would be a worse bug than the one
|
|
574
|
+
* being fixed.
|
|
575
|
+
*/
|
|
576
|
+
test("'Skip for now' lets the completed sign-in through", async () => {
|
|
577
|
+
await startTwoFactorChallenge({
|
|
578
|
+
totpNames: ["Ada's phone"],
|
|
579
|
+
backupCodeCount: 0,
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
await enterTotpCode();
|
|
583
|
+
await screen.findByTestId("generate-backup-codes");
|
|
584
|
+
|
|
585
|
+
const user: UserEvent = setupUser();
|
|
586
|
+
await user.click(screen.getByText(SKIP_FOR_NOW));
|
|
587
|
+
|
|
588
|
+
await waitFor(() => {
|
|
589
|
+
expect(loginCalls).toHaveLength(1);
|
|
590
|
+
});
|
|
591
|
+
expect(loginCalls[0]?.token).toBe("session-token");
|
|
592
|
+
});
|
|
593
|
+
|
|
594
|
+
test("accepting the offer shows the codes it minted", async () => {
|
|
595
|
+
generatedCodes = ["AAAAA-11111", "BBBBB-22222"];
|
|
596
|
+
|
|
597
|
+
await startTwoFactorChallenge({
|
|
598
|
+
totpNames: ["Ada's phone"],
|
|
599
|
+
backupCodeCount: 0,
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
await enterTotpCode();
|
|
603
|
+
|
|
604
|
+
const user: UserEvent = setupUser();
|
|
605
|
+
const generateButton: HTMLElement = await screen.findByTestId(
|
|
606
|
+
"generate-backup-codes",
|
|
607
|
+
);
|
|
608
|
+
|
|
609
|
+
await act(async () => {
|
|
610
|
+
await user.click(generateButton);
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
const shown: Array<HTMLElement> =
|
|
614
|
+
await screen.findAllByTestId("backup-code-value");
|
|
615
|
+
|
|
616
|
+
expect(
|
|
617
|
+
shown.map((element: HTMLElement): string => {
|
|
618
|
+
return element.textContent || "";
|
|
619
|
+
}),
|
|
620
|
+
).toEqual(generatedCodes);
|
|
621
|
+
|
|
622
|
+
// Still not signed through -- these have not been acknowledged yet.
|
|
623
|
+
expect(loginCalls).toHaveLength(0);
|
|
624
|
+
expect(
|
|
625
|
+
postedUrls.some((url: string): boolean => {
|
|
626
|
+
return url.includes("/user-two-factor-backup-code/generate");
|
|
627
|
+
}),
|
|
628
|
+
).toBe(true);
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
/*
|
|
632
|
+
* THE SHOW-ONCE GUARANTEE.
|
|
633
|
+
*
|
|
634
|
+
* The server keeps only keyed digests, so the plaintext in this response is
|
|
635
|
+
* the only copy that will ever exist. A redirect that fires before the user
|
|
636
|
+
* has said "I have these" destroys them silently -- the account keeps ten
|
|
637
|
+
* codes nobody has ever seen, which is the original bug wearing a different
|
|
638
|
+
* hat.
|
|
639
|
+
*/
|
|
640
|
+
test("server-minted codes are all shown, and the redirect waits for the tick", async () => {
|
|
641
|
+
const minted: Array<string> = [
|
|
642
|
+
"AAAAA-11111",
|
|
643
|
+
"BBBBB-22222",
|
|
644
|
+
"CCCCC-33333",
|
|
645
|
+
"DDDDD-44444",
|
|
646
|
+
];
|
|
647
|
+
|
|
648
|
+
secondStepMiscData = { token: "session-token", backupCodes: minted };
|
|
649
|
+
|
|
650
|
+
await startTwoFactorChallenge({
|
|
651
|
+
totpNames: ["Ada's phone"],
|
|
652
|
+
backupCodeCount: 0,
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
await enterTotpCode();
|
|
656
|
+
|
|
657
|
+
const shown: Array<HTMLElement> =
|
|
658
|
+
await screen.findAllByTestId("backup-code-value");
|
|
659
|
+
|
|
660
|
+
// Every one of them, not just the first row of the grid.
|
|
661
|
+
expect(
|
|
662
|
+
shown.map((element: HTMLElement): string => {
|
|
663
|
+
return element.textContent || "";
|
|
664
|
+
}),
|
|
665
|
+
).toEqual(minted);
|
|
666
|
+
|
|
667
|
+
const continueButton: HTMLElement = screen.getByTestId(
|
|
668
|
+
"backup-codes-continue",
|
|
669
|
+
);
|
|
670
|
+
|
|
671
|
+
expect(continueButton).toBeDisabled();
|
|
672
|
+
|
|
673
|
+
const user: UserEvent = setupUser();
|
|
674
|
+
|
|
675
|
+
// Pressing it before acknowledging must do nothing at all.
|
|
676
|
+
await user.click(continueButton);
|
|
677
|
+
expect(loginCalls).toHaveLength(0);
|
|
678
|
+
|
|
679
|
+
await user.click(screen.getByTestId("backup-codes-saved-checkbox"));
|
|
680
|
+
|
|
681
|
+
await waitFor(() => {
|
|
682
|
+
expect(screen.getByTestId("backup-codes-continue")).toBeEnabled();
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
await user.click(screen.getByTestId("backup-codes-continue"));
|
|
686
|
+
|
|
687
|
+
await waitFor(() => {
|
|
688
|
+
expect(loginCalls).toHaveLength(1);
|
|
689
|
+
});
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
/*
|
|
693
|
+
* The account that already has codes and was not given new ones is not
|
|
694
|
+
* stopped for anything. Nothing has been lost and nothing is being handed
|
|
695
|
+
* over, so a screen here would be pure friction on every single sign-in.
|
|
696
|
+
*/
|
|
697
|
+
test("an account that already has codes is signed straight in", async () => {
|
|
698
|
+
await startTwoFactorChallenge({
|
|
699
|
+
totpNames: ["Ada's phone"],
|
|
700
|
+
backupCodeCount: 8,
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
await enterTotpCode();
|
|
704
|
+
|
|
705
|
+
await waitFor(() => {
|
|
706
|
+
expect(loginCalls).toHaveLength(1);
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
expect(
|
|
710
|
+
screen.queryByTestId("generate-backup-codes"),
|
|
711
|
+
).not.toBeInTheDocument();
|
|
712
|
+
expect(screen.queryByTestId("backup-codes-list")).not.toBeInTheDocument();
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
/*
|
|
716
|
+
* The same "unknown is not none" rule, on the way out rather than the way
|
|
717
|
+
* in. A database that cannot count backup codes for a minute would otherwise
|
|
718
|
+
* put a "you have no backup codes" screen in front of every two factor
|
|
719
|
+
* sign-in on the instance -- an outage turned into a product-wide nag.
|
|
720
|
+
*/
|
|
721
|
+
test("a count the server could not read does not interrupt the sign-in", async () => {
|
|
722
|
+
await startTwoFactorChallenge({
|
|
723
|
+
totpNames: ["Ada's phone"],
|
|
724
|
+
backupCodeCount: null,
|
|
725
|
+
});
|
|
726
|
+
|
|
727
|
+
await enterTotpCode();
|
|
728
|
+
|
|
729
|
+
await waitFor(() => {
|
|
730
|
+
expect(loginCalls).toHaveLength(1);
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
expect(
|
|
734
|
+
screen.queryByTestId("generate-backup-codes"),
|
|
735
|
+
).not.toBeInTheDocument();
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
/*
|
|
739
|
+
* FORCED ENROLMENT -- the path with the strongest claim on this feature.
|
|
740
|
+
*
|
|
741
|
+
* An account reaches it in one of two ways: an admin has mandated two factor
|
|
742
|
+
* auth on somebody who had none, or an admin has just RESET it for somebody
|
|
743
|
+
* who was locked out (which deletes their codes). Both used to end with the
|
|
744
|
+
* user signed in, a fresh authenticator app, and no recovery route at all --
|
|
745
|
+
* the user who had just been rescued was the one most certain to need
|
|
746
|
+
* rescuing again.
|
|
747
|
+
*
|
|
748
|
+
* The handler used to throw the response's misc bag away with a literal
|
|
749
|
+
* `{}`, so even once the server started minting here, the only copy of the
|
|
750
|
+
* plaintext went in the bin.
|
|
751
|
+
*/
|
|
752
|
+
test("codes minted behind a forced enrolment are shown before the redirect", async () => {
|
|
753
|
+
const minted: Array<string> = ["AAAAA-11111", "BBBBB-22222"];
|
|
754
|
+
|
|
755
|
+
secondStepMiscData = { token: "session-token", backupCodes: minted };
|
|
756
|
+
|
|
757
|
+
await startForcedEnrolment();
|
|
758
|
+
await submitEnrolmentCode();
|
|
759
|
+
|
|
760
|
+
const shown: Array<HTMLElement> =
|
|
761
|
+
await screen.findAllByTestId("backup-code-value");
|
|
762
|
+
|
|
763
|
+
expect(
|
|
764
|
+
shown.map((element: HTMLElement): string => {
|
|
765
|
+
return element.textContent || "";
|
|
766
|
+
}),
|
|
767
|
+
).toEqual(minted);
|
|
768
|
+
|
|
769
|
+
expect(loginCalls).toHaveLength(0);
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
/*
|
|
773
|
+
* ...and the enrolment that minted nothing BECAUSE the account already had a
|
|
774
|
+
* set must not be treated as an account with none. The profile card lets a
|
|
775
|
+
* user generate codes before turning two factor auth on, so somebody can be
|
|
776
|
+
* holding a printed set when an admin mandates a factor. There is no count
|
|
777
|
+
* on this path -- /login answered with a QR code, not a factor list -- so the
|
|
778
|
+
* server says it outright with `hasBackupCodes`. Ignoring that would tell
|
|
779
|
+
* that user they have no codes and offer to make some, which would replace
|
|
780
|
+
* the very set they printed.
|
|
781
|
+
*/
|
|
782
|
+
test("an enrolment on an account that already had codes is not offered more", async () => {
|
|
783
|
+
secondStepMiscData = { token: "session-token", hasBackupCodes: true };
|
|
784
|
+
|
|
785
|
+
await startForcedEnrolment();
|
|
786
|
+
await submitEnrolmentCode();
|
|
787
|
+
|
|
788
|
+
await waitFor(() => {
|
|
789
|
+
expect(loginCalls).toHaveLength(1);
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
expect(
|
|
793
|
+
screen.queryByTestId("generate-backup-codes"),
|
|
794
|
+
).not.toBeInTheDocument();
|
|
795
|
+
expect(screen.queryByTestId("backup-codes-list")).not.toBeInTheDocument();
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
/*
|
|
799
|
+
* And the offer must not leak onto accounts with no second factor at all.
|
|
800
|
+
* There is no lock for these recovery codes to open, so asking for them
|
|
801
|
+
* would put a screen in front of every password-only sign-in in the product
|
|
802
|
+
* -- an unrelated regression that this fix is one `if` away from causing.
|
|
803
|
+
*/
|
|
804
|
+
test("a password-only account is never prompted for backup codes", async () => {
|
|
805
|
+
loginMiscData = { token: "session-token" };
|
|
806
|
+
|
|
807
|
+
renderPage();
|
|
808
|
+
await submitPassword();
|
|
809
|
+
|
|
810
|
+
await waitFor(() => {
|
|
811
|
+
expect(loginCalls).toHaveLength(1);
|
|
812
|
+
});
|
|
813
|
+
|
|
814
|
+
expect(
|
|
815
|
+
screen.queryByTestId("generate-backup-codes"),
|
|
816
|
+
).not.toBeInTheDocument();
|
|
817
|
+
expect(screen.queryByTestId("backup-codes-list")).not.toBeInTheDocument();
|
|
818
|
+
expect(screen.queryByText(LOST_ACCESS)).not.toBeInTheDocument();
|
|
819
|
+
});
|
|
820
|
+
|
|
821
|
+
/*
|
|
822
|
+
* SPENDING THE LAST CODE.
|
|
823
|
+
*
|
|
824
|
+
* The one user in the product who has just PROVED they needed a recovery
|
|
825
|
+
* route, and who now has none. The count on the challenge response was taken
|
|
826
|
+
* before the code was spent, so it is one too high by the time this runs --
|
|
827
|
+
* and this screen is only reachable when it was above zero, which means the
|
|
828
|
+
* obvious "is the count zero" test is false here forever. Nothing else on
|
|
829
|
+
* the response says so: the identity route's remaining-code count is
|
|
830
|
+
* computed on a detached promise that must never fail the login, so it
|
|
831
|
+
* cannot be waited on to put it in the body.
|
|
832
|
+
*
|
|
833
|
+
* Without the decrement this user is redirected into the dashboard and the
|
|
834
|
+
* product never mentions it again, which is precisely the state issue #3382
|
|
835
|
+
* was filed about, reached by the one path that is supposed to prevent it.
|
|
836
|
+
*/
|
|
837
|
+
test("spending the last backup code offers a fresh set", async () => {
|
|
838
|
+
await startTwoFactorChallenge({
|
|
839
|
+
totpNames: ["Ada's phone"],
|
|
840
|
+
backupCodeCount: 1,
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
const user: UserEvent = setupUser();
|
|
844
|
+
await user.click(screen.getByText(LOST_ACCESS));
|
|
845
|
+
await user.type(await screen.findByTestId("backup-code"), "ABCDE-12345");
|
|
846
|
+
|
|
847
|
+
await act(async () => {
|
|
848
|
+
await user.click(screen.getByTestId("Login"));
|
|
849
|
+
});
|
|
850
|
+
|
|
851
|
+
expect(
|
|
852
|
+
await screen.findByTestId("generate-backup-codes"),
|
|
853
|
+
).toBeInTheDocument();
|
|
854
|
+
|
|
855
|
+
/* Held, not redirected -- the offer is the point. */
|
|
856
|
+
expect(loginCalls).toHaveLength(0);
|
|
857
|
+
});
|
|
858
|
+
|
|
859
|
+
/*
|
|
860
|
+
* And the same sign-in with codes still to spare goes straight through. A
|
|
861
|
+
* decrement applied too eagerly would stop every recovery sign-in with an
|
|
862
|
+
* offer the user does not need, on the screen they reached because they were
|
|
863
|
+
* already having a bad day.
|
|
864
|
+
*/
|
|
865
|
+
test("spending a backup code with others left does not interrupt", async () => {
|
|
866
|
+
await startTwoFactorChallenge({
|
|
867
|
+
totpNames: ["Ada's phone"],
|
|
868
|
+
backupCodeCount: 4,
|
|
869
|
+
});
|
|
870
|
+
|
|
871
|
+
const user: UserEvent = setupUser();
|
|
872
|
+
await user.click(screen.getByText(LOST_ACCESS));
|
|
873
|
+
await user.type(await screen.findByTestId("backup-code"), "ABCDE-12345");
|
|
874
|
+
|
|
875
|
+
await act(async () => {
|
|
876
|
+
await user.click(screen.getByTestId("Login"));
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
await waitFor(() => {
|
|
880
|
+
expect(loginCalls).toHaveLength(1);
|
|
881
|
+
});
|
|
882
|
+
expect(
|
|
883
|
+
screen.queryByTestId("generate-backup-codes"),
|
|
884
|
+
).not.toBeInTheDocument();
|
|
885
|
+
});
|
|
886
|
+
|
|
887
|
+
/*
|
|
888
|
+
* "SKIP FOR NOW" HAS TO MEAN SOMETHING.
|
|
889
|
+
*
|
|
890
|
+
* The offer interrupts a sign-in that has already succeeded. Made once, that
|
|
891
|
+
* is a security prompt; made on every sign-in for the life of the account it
|
|
892
|
+
* is a toll, and it is worst on an instance where the generate route is
|
|
893
|
+
* failing -- a button that cannot work and a link that says "later", every
|
|
894
|
+
* time, with no way to mean it.
|
|
895
|
+
*
|
|
896
|
+
* Bounded rather than permanent, and keyed to the user id so a shared
|
|
897
|
+
* machine does not silence the prompt for the next person to sign in on it.
|
|
898
|
+
*/
|
|
899
|
+
test("skipping the offer suppresses it on the next sign-in", async () => {
|
|
900
|
+
await startTwoFactorChallenge({
|
|
901
|
+
totpNames: ["Ada's phone"],
|
|
902
|
+
backupCodeCount: 0,
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
await enterTotpCode();
|
|
906
|
+
await screen.findByTestId("generate-backup-codes");
|
|
907
|
+
|
|
908
|
+
const user: UserEvent = setupUser();
|
|
909
|
+
await user.click(screen.getByText(SKIP_FOR_NOW));
|
|
910
|
+
|
|
911
|
+
await waitFor(() => {
|
|
912
|
+
expect(loginCalls).toHaveLength(1);
|
|
913
|
+
});
|
|
914
|
+
|
|
915
|
+
/* Sign in again on the same browser, same account, still no codes. */
|
|
916
|
+
cleanup();
|
|
917
|
+
loginCalls = [];
|
|
918
|
+
|
|
919
|
+
await startTwoFactorChallenge({
|
|
920
|
+
totpNames: ["Ada's phone"],
|
|
921
|
+
backupCodeCount: 0,
|
|
922
|
+
});
|
|
923
|
+
await enterTotpCode();
|
|
924
|
+
|
|
925
|
+
await waitFor(() => {
|
|
926
|
+
expect(loginCalls).toHaveLength(1);
|
|
927
|
+
});
|
|
928
|
+
expect(
|
|
929
|
+
screen.queryByTestId("generate-backup-codes"),
|
|
930
|
+
).not.toBeInTheDocument();
|
|
931
|
+
});
|
|
932
|
+
|
|
933
|
+
/*
|
|
934
|
+
* A DIFFERENT ACCOUNT ON THE SAME BROWSER IS STILL ASKED.
|
|
935
|
+
*
|
|
936
|
+
* Scoping the snooze to the user id is what stops one person's "later" from
|
|
937
|
+
* hiding a security prompt from somebody who never dismissed it -- which on
|
|
938
|
+
* a shared or handed-down machine is somebody who then has no recovery route
|
|
939
|
+
* and was never told.
|
|
940
|
+
*/
|
|
941
|
+
test("skipping for one account does not silence the offer for another", async () => {
|
|
942
|
+
await startTwoFactorChallenge({
|
|
943
|
+
totpNames: ["Ada's phone"],
|
|
944
|
+
backupCodeCount: 0,
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
await enterTotpCode();
|
|
948
|
+
await screen.findByTestId("generate-backup-codes");
|
|
949
|
+
|
|
950
|
+
const user: UserEvent = setupUser();
|
|
951
|
+
await user.click(screen.getByText(SKIP_FOR_NOW));
|
|
952
|
+
|
|
953
|
+
await waitFor(() => {
|
|
954
|
+
expect(loginCalls).toHaveLength(1);
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
cleanup();
|
|
958
|
+
loginCalls = [];
|
|
959
|
+
signedInUserId = "22222222-2222-4222-8222-222222222222";
|
|
960
|
+
|
|
961
|
+
await startTwoFactorChallenge({
|
|
962
|
+
totpNames: ["Grace's phone"],
|
|
963
|
+
backupCodeCount: 0,
|
|
964
|
+
});
|
|
965
|
+
await enterTotpCode();
|
|
966
|
+
|
|
967
|
+
expect(
|
|
968
|
+
await screen.findByTestId("generate-backup-codes"),
|
|
969
|
+
).toBeInTheDocument();
|
|
970
|
+
expect(loginCalls).toHaveLength(0);
|
|
971
|
+
});
|
|
972
|
+
});
|