@oneuptime/common 12.0.13 → 12.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/GlobalOidc.ts +20 -0
- package/Models/DatabaseModels/GlobalSso.ts +20 -0
- package/Models/DatabaseModels/MarketingConversion.ts +19 -9
- package/Models/DatabaseModels/NetworkDeviceLinkRule.ts +46 -0
- package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +14 -0
- package/Models/DatabaseModels/StatusPage.ts +7 -4
- package/Models/DatabaseModels/UserCall.ts +94 -3
- package/Models/DatabaseModels/UserEmail.ts +94 -3
- package/Models/DatabaseModels/UserIncomingCallNumber.ts +94 -3
- package/Models/DatabaseModels/UserPush.ts +37 -0
- package/Models/DatabaseModels/UserSMS.ts +94 -3
- package/Models/DatabaseModels/UserWhatsApp.ts +93 -2
- package/Server/API/BaseAPI.ts +79 -14
- package/Server/API/StatusPageAPI.ts +29 -4
- package/Server/API/UserCallAPI.ts +53 -45
- package/Server/API/UserEmailAPI.ts +53 -44
- package/Server/API/UserIncomingCallNumberAPI.ts +48 -38
- package/Server/API/UserNotificationMethodAdminAPI.ts +481 -0
- package/Server/API/UserPushAPI.ts +126 -2
- package/Server/API/UserSmsAPI.ts +53 -44
- package/Server/API/UserWhatsAppAPI.ts +53 -50
- package/Server/EnvironmentConfig.ts +7 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.ts +154 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.ts +17 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.ts +45 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787800000000-AddScopeToNetworkDeviceLinkRule.ts +19 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787900000000-AddRestrictToAttachedProjectsToGlobalSso.ts +40 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Middleware/SlackAuthorization.ts +43 -6
- package/Server/Middleware/UserAuthorization.ts +236 -26
- package/Server/Middleware/VerificationCodeRateLimit.ts +586 -0
- package/Server/Middleware/WhatsAppAuthorization.ts +43 -3
- package/Server/Services/AnalyticsDatabaseService.ts +169 -0
- package/Server/Services/DatabaseService.ts +101 -0
- package/Server/Services/GlobalOidcProjectService.ts +126 -1
- package/Server/Services/GlobalOidcService.ts +132 -0
- package/Server/Services/GlobalSsoProjectService.ts +126 -1
- package/Server/Services/GlobalSsoService.ts +132 -0
- package/Server/Services/LogAggregationService.ts +5 -0
- package/Server/Services/PushNotificationService.ts +127 -12
- package/Server/Services/TeamMemberService.ts +53 -13
- package/Server/Services/UserCallService.ts +55 -24
- package/Server/Services/UserEmailService.ts +83 -17
- package/Server/Services/UserIncomingCallNumberService.ts +49 -85
- package/Server/Services/UserNotificationMethodAdminService.ts +1527 -0
- package/Server/Services/UserNotificationRuleService.ts +26 -0
- package/Server/Services/UserPushService.ts +89 -0
- package/Server/Services/UserSmsService.ts +50 -17
- package/Server/Services/UserWhatsAppService.ts +48 -15
- package/Server/Types/Database/QueryHelper.ts +30 -0
- package/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.ts +59 -0
- package/Server/Utils/ChannelVerification.ts +510 -0
- package/Server/Utils/CronTab.ts +73 -0
- package/Server/Utils/GlobalSsoAuthorization.ts +175 -0
- package/Server/Utils/Marketing/ConversionUploadProvider.ts +35 -5
- package/Server/Utils/Marketing/Providers/GoogleAds.ts +1 -1
- package/Server/Utils/Marketing/Providers/LinkedIn.ts +1 -1
- package/Server/Utils/Marketing/Providers/Meta.ts +1 -1
- package/Server/Utils/Marketing/Providers/MicrosoftAds.ts +1 -1
- package/Server/Utils/Marketing/Providers/Reddit.ts +1 -1
- package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +48 -33
- package/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.ts +35 -30
- package/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.ts +33 -28
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +475 -47
- package/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.ts +35 -30
- package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +47 -44
- package/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.ts +33 -28
- package/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.ts +69 -40
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +35 -29
- package/Server/Utils/Monitor/MonitorAlert.ts +24 -21
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +8 -0
- package/Server/Utils/Monitor/MonitorIncident.ts +21 -18
- package/Server/Utils/Monitor/MonitorResource.ts +161 -21
- package/Server/Utils/Monitor/MonitorResourceContext.ts +107 -0
- package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +442 -0
- package/Server/Utils/Monitor/SeriesResourceLabels.ts +3 -3
- package/Server/Utils/Monitor/SeriesResourceLinker.ts +96 -28
- package/Server/Utils/StatusPageContentSecurityPolicy.ts +56 -0
- package/Server/Utils/StatusPageCustomizationAccess.ts +117 -0
- package/Server/Utils/TotpAuth.ts +137 -9
- package/Server/Utils/UserRegistrationToken.ts +182 -0
- package/Server/Utils/VerificationCode.ts +134 -0
- package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +173 -94
- package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +1151 -0
- package/Tests/App/Dashboard/AdminUserOnCallPages.test.tsx +905 -0
- package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +338 -0
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1 -1
- package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +28 -0
- package/Tests/Models/UserPushCriticalAlertColumn.test.ts +172 -0
- package/Tests/Server/API/BaseAPIGetListParallel.test.ts +519 -0
- package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +543 -0
- package/Tests/Server/API/StatusPageCustomizationOrigin.test.ts +348 -0
- package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +108 -18
- package/Tests/Server/API/UserNotificationMethodAdminAPI.test.ts +963 -0
- package/Tests/Server/API/UserPushCriticalAlertsApi.test.ts +114 -0
- package/Tests/Server/API/UserSmsApi.test.ts +107 -14
- package/Tests/Server/API/UserTotpAuthAPI.test.ts +427 -0
- package/Tests/Server/Infrastructure/Postgres/FixTotpOtpUrlAlgorithmMigration.test.ts +265 -0
- package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +227 -0
- package/Tests/Server/Middleware/SlackAuthorization.test.ts +149 -0
- package/Tests/Server/Middleware/UserAuthorization.test.ts +27 -13
- package/Tests/Server/Middleware/UserAuthorizationGlobalSsoGovernance.test.ts +1455 -0
- package/Tests/Server/Middleware/UserAuthorizationSSOProvider.test.ts +91 -2
- package/Tests/Server/Middleware/VerificationCodeRateLimit.test.ts +775 -0
- package/Tests/Server/Middleware/WhatsAppAuthorization.test.ts +233 -0
- package/Tests/Server/Services/AddNetworkDeviceReachabilityColumnsMigration.test.ts +10 -62
- package/Tests/Server/Services/AnalyticsDatabasePaginationStability.test.ts +33 -13
- package/Tests/Server/Services/AnalyticsDatabaseSortKeyBoundary.test.ts +658 -0
- package/Tests/Server/Services/CriticalOnCallAlertDelivery.test.ts +458 -0
- package/Tests/Server/Services/CriticalPushAlertPayload.test.ts +301 -0
- package/Tests/Server/Services/DatabaseServiceAtomicIncrement.test.ts +143 -0
- package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1 -0
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +21 -8
- package/Tests/Server/Services/GlobalSsoProviderAuthorization.test.ts +1242 -0
- package/Tests/Server/Services/LogAggregationScanMemory.test.ts +421 -0
- package/Tests/Server/Services/LogAggregationService.test.ts +2 -2
- package/Tests/Server/Services/MonitorResourceProbeAgreementHydration.test.ts +459 -0
- package/Tests/Server/Services/MonitorResourceProbeAgreementReuse.test.ts +10 -0
- package/Tests/Server/Services/NotificationChannelCodeIssuance.test.ts +401 -0
- package/Tests/Server/Services/PushNotificationDeliveryOptions.test.ts +204 -0
- package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +21 -1
- package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +290 -0
- package/Tests/Server/Services/UserNotificationMethodAdminService.test.ts +948 -0
- package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1 -0
- package/Tests/Server/Services/UserPushCriticalAlertToggle.test.ts +255 -0
- package/Tests/Server/Services/UserTotpAuthEnrolment.test.ts +218 -0
- package/Tests/Server/TestingUtils/AuthenticatorApp.ts +248 -0
- package/Tests/Server/Types/AnalyticsDatabase/AggregateUtilBucketTimestamp.test.ts +416 -0
- package/Tests/Server/Types/Database/Permissions/NotificationChannelVerificationColumns.test.ts +135 -0
- package/Tests/Server/Types/Database/Permissions/OnCallScheduleRelationSelect.test.ts +504 -0
- package/Tests/Server/Types/Database/QueryHelperFindWithSameTextAnyOf.test.ts +91 -0
- package/Tests/Server/Types/Database/QueryHelperManyToManyAndEmptyValues.test.ts +551 -0
- package/Tests/Server/Types/Database/SelectUtil.test.ts +348 -0
- package/Tests/Server/Types/Workflow/Components/JsonToText.test.ts +384 -0
- package/Tests/Server/Types/Workflow/Components/MergeJson.test.ts +403 -0
- package/Tests/Server/Utils/Browser.test.ts +162 -0
- package/Tests/Server/Utils/ChannelVerification.test.ts +689 -0
- package/Tests/Server/Utils/CronTab.test.ts +116 -0
- package/Tests/Server/Utils/Express.test.ts +371 -0
- package/Tests/Server/Utils/GlobalSSOToken.test.ts +581 -0
- package/Tests/Server/Utils/GlobalSsoAuthorization.test.ts +1401 -0
- package/Tests/Server/Utils/Marketing/AdUploadableConversionTypes.test.ts +254 -0
- package/Tests/Server/Utils/Marketing/ConversionUploadProvider.test.ts +1 -1
- package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaEvaluateOverTime.test.ts +508 -0
- package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaPortTimings.test.ts +30 -9
- package/Tests/Server/Utils/Monitor/Criteria/CustomCodeMonitorCriteria.test.ts +707 -0
- package/Tests/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.test.ts +698 -0
- package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +987 -0
- package/Tests/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.test.ts +916 -0
- package/Tests/Server/Utils/Monitor/Criteria/IncomingEmailBodyCriteria.test.ts +243 -0
- package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestBodyCriteria.test.ts +278 -0
- package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +382 -0
- package/Tests/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.test.ts +1219 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +160 -20
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +13 -8
- package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +162 -18
- package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +349 -0
- package/Tests/Server/Utils/Monitor/MonitorResourceIngestedStepSelection.test.ts +86 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +690 -0
- package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +7 -2
- package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +92 -18
- package/Tests/Server/Utils/PushNotificationUtilCreators.test.ts +267 -0
- package/Tests/Server/Utils/StatusPageContentSecurityPolicy.test.ts +136 -0
- package/Tests/Server/Utils/StatusPageCustomizationAccess.test.ts +223 -0
- package/Tests/Server/Utils/Telemetry/OneuptimeLabel.test.ts +439 -0
- package/Tests/Server/Utils/TotpAuth.test.ts +719 -0
- package/Tests/Server/Utils/UserRegistrationToken.test.ts +322 -0
- package/Tests/Server/Utils/VerificationCode.test.ts +296 -0
- package/Tests/Types/AutoRemediation/AutoRemediationSuggestionStatus.test.ts +192 -0
- package/Tests/Types/Call/CallRequest.test.ts +189 -0
- package/Tests/Types/Dashboard/DashboardSize.test.ts +226 -0
- package/Tests/Types/Incident/IncidentSlaStatus.test.ts +191 -0
- package/Tests/Types/Metrics/MetricDashboardMetricType.test.ts +278 -0
- package/Tests/Types/Metrics/MetricPipelineRuleType.test.ts +517 -0
- package/Tests/Types/Monitor/IncomingMonitorDefaultCriteria.test.ts +470 -0
- package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +6 -4
- package/Tests/Types/Monitor/MonitorStepConfigHelpers.test.ts +165 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +262 -5
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +1 -1
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +1 -1
- package/Tests/Types/Monitor/ServiceAlertTemplates.test.ts +905 -0
- package/Tests/Types/NetworkDevice/NetworkDeviceLinkRuleScope.test.ts +215 -0
- package/Tests/Types/Service/ServiceLanguage.test.ts +255 -0
- package/Tests/Types/TextRandomGeneration.test.ts +211 -0
- package/Tests/UI/Components/Button.test.tsx +175 -1
- package/Tests/UI/Components/CodeBlockLanguages.test.tsx +236 -0
- package/Tests/UI/Components/CommandPalette/CommandPalette.test.tsx +568 -0
- package/Tests/UI/Components/CommandPalette/CommandPaletteKeyboard.test.tsx +239 -0
- package/Tests/UI/Components/CommandPalette/CommandPaletteProviders.test.tsx +400 -0
- package/Tests/UI/Components/CommandPalette/PaletteFilter.test.ts +234 -0
- package/Tests/UI/Components/CommandPalette/RecentCommands.test.ts +97 -0
- package/Tests/UI/Components/CountModelSideMenuItemGuard.test.tsx +198 -0
- package/Tests/UI/Components/FeedItemSafeMode.test.tsx +1 -1
- package/Tests/UI/Components/Forms/FormSubmitAnalytics.test.tsx +206 -0
- package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +267 -0
- package/Tests/UI/Components/List.test.tsx +9 -2
- package/Tests/UI/Components/ListLoadingStates.test.tsx +173 -0
- package/Tests/UI/Components/MarkdownLazy.test.tsx +113 -0
- package/Tests/UI/Components/MarkdownMermaidRetry.test.tsx +110 -0
- package/Tests/UI/Components/ModelTable/useCustomFieldColumns.test.tsx +8 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +692 -0
- package/Tests/UI/Components/MoreMenuMotion.test.tsx +118 -0
- package/Tests/UI/Components/NavBarCommandKGating.test.tsx +178 -0
- package/Tests/UI/Components/OrderedStatesList.test.tsx +19 -2
- package/Tests/UI/Components/SideOverMotion.test.tsx +109 -0
- package/Tests/UI/Components/Skeleton.test.tsx +71 -0
- package/Tests/UI/Components/TableLoadingStates.test.tsx +279 -0
- package/Tests/UI/Components/Tabs.test.tsx +24 -0
- package/Tests/UI/Components/Toast.test.tsx +130 -7
- package/Tests/UI/Components/ToastStacking.test.tsx +198 -0
- package/Tests/UI/Utils/AIChatExport/ConversationMarkdown.test.ts +774 -0
- package/Tests/UI/Utils/AIChatExport/MarkdownBlocks.test.ts +791 -0
- package/Tests/UI/Utils/AIChatExport/MarkdownSafety.test.ts +544 -0
- package/Tests/UI/Utils/Dropdown.test.ts +423 -0
- package/Tests/UI/Utils/ModelAPITenantHeader.test.ts +122 -0
- package/Tests/UI/Utils/ModelListCache.test.ts +338 -0
- package/Tests/UI/Utils/ProjectListCacheInvalidation.test.ts +225 -0
- package/Tests/Utils/API.test.ts +16 -2
- package/Tests/Utils/Analytics.test.ts +187 -0
- package/Tests/Utils/Dashboard/Components/DashboardKubernetesResourceListShared.test.ts +347 -0
- package/Tests/Utils/Dashboard/Components/DashboardListSharedArgs.test.ts +259 -0
- package/Tests/Utils/Dashboard/Components/DashboardMonitorListComponent.test.ts +466 -0
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +80 -0
- package/Tests/Utils/Monitor/NetworkDeviceLinkRuleUtil.test.ts +1291 -0
- package/Tests/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.test.ts +214 -0
- package/Tests/Utils/Rum/UrlScrubberSegments.test.ts +362 -0
- package/Types/Email/EmailTemplateType.ts +1 -0
- package/Types/Marketing/MarketingConversion.ts +12 -0
- package/Types/Monitor/CriteriaFilter.ts +9 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +41 -20
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +131 -8
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +48 -8
- package/Types/Monitor/ServiceAlertTemplates.ts +1352 -0
- package/Types/NetworkDevice/NetworkDeviceLinkRuleScope.ts +51 -0
- package/Types/Permission.ts +35 -0
- package/Types/PushNotification/AndroidNotificationChannel.ts +26 -0
- package/Types/PushNotification/PushNotificationMessage.ts +15 -0
- package/Types/PushNotification/PushNotificationRequest.ts +8 -16
- package/Types/Service/ServiceLanguage.ts +144 -0
- package/Types/Text.ts +111 -19
- package/UI/Components/Button/Button.tsx +27 -14
- package/UI/Components/CodeBlock/CodeBlock.tsx +54 -7
- package/UI/Components/CodeBlock/LanguageRegistry.ts +103 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +790 -0
- package/UI/Components/CommandPalette/PaletteFilter.ts +196 -0
- package/UI/Components/CommandPalette/PaletteRow.tsx +173 -0
- package/UI/Components/CommandPalette/RecentCommands.ts +57 -0
- package/UI/Components/CommandPalette/Types.ts +49 -0
- package/UI/Components/CommandPalette/UseProviderSearch.ts +129 -0
- package/UI/Components/Dropdown/Dropdown.tsx +6 -1
- package/UI/Components/Feed/FeedItem.tsx +1 -1
- package/UI/Components/FormModal/BasicFormModal.tsx +12 -0
- package/UI/Components/Forms/BasicForm.tsx +13 -1
- package/UI/Components/Forms/BasicModelForm.tsx +2 -1
- package/UI/Components/Forms/ModelForm.tsx +10 -1
- package/UI/Components/Forms/Utils/FormAnalyticsName.ts +39 -0
- package/UI/Components/List/List.tsx +37 -5
- package/UI/Components/List/ListSkeleton.tsx +54 -0
- package/UI/Components/Markdown.tsx/LazyMarkdownViewer.tsx +6 -1
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +71 -26
- package/UI/Components/Modal/Modal.tsx +2 -2
- package/UI/Components/ModelFormModal/ModelFormModal.tsx +6 -1
- package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
- package/UI/Components/ModelTable/useCustomFieldColumns.ts +11 -5
- package/UI/Components/MoreMenu/MoreMenu.tsx +39 -1
- package/UI/Components/Navbar/NavBar.tsx +14 -1
- package/UI/Components/OrderedStatesList/OrderedStatesList.tsx +50 -5
- package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +40 -1
- package/UI/Components/SideOver/SideOver.tsx +37 -2
- package/UI/Components/Skeleton/Skeleton.tsx +53 -0
- package/UI/Components/Table/Table.tsx +74 -44
- package/UI/Components/Table/TableSkeletonRows.tsx +141 -0
- package/UI/Components/Tabs/Tab.tsx +1 -1
- package/UI/Components/Toast/Toast.tsx +118 -53
- package/UI/Components/Toast/ToastInit.tsx +82 -32
- package/UI/Styles/Theme.css +40 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +20 -10
- package/UI/Utils/ModelListCache.ts +188 -0
- package/UI/Utils/Project.ts +29 -0
- package/Utils/API.ts +6 -1
- package/Utils/Analytics.ts +55 -2
- package/Utils/Monitor/MonitorMetricType.ts +40 -0
- package/Utils/Monitor/NetworkDeviceLinkRuleUtil.ts +587 -37
- package/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.ts +115 -0
- package/build/dist/Models/DatabaseModels/GlobalOidc.js +21 -0
- package/build/dist/Models/DatabaseModels/GlobalOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalSso.js +21 -0
- package/build/dist/Models/DatabaseModels/GlobalSso.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MarketingConversion.js +20 -10
- package/build/dist/Models/DatabaseModels/MarketingConversion.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js +47 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +14 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +4 -4
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserCall.js +101 -3
- package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserEmail.js +101 -3
- package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js +101 -3
- package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserPush.js +38 -0
- package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserSMS.js +101 -3
- package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js +100 -2
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +69 -13
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +25 -4
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/UserCallAPI.js +42 -38
- package/build/dist/Server/API/UserCallAPI.js.map +1 -1
- package/build/dist/Server/API/UserEmailAPI.js +42 -38
- package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js +37 -32
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
- package/build/dist/Server/API/UserNotificationMethodAdminAPI.js +341 -0
- package/build/dist/Server/API/UserNotificationMethodAdminAPI.js.map +1 -0
- package/build/dist/Server/API/UserPushAPI.js +95 -2
- package/build/dist/Server/API/UserPushAPI.js.map +1 -1
- package/build/dist/Server/API/UserSmsAPI.js +42 -38
- package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
- package/build/dist/Server/API/UserWhatsAppAPI.js +42 -40
- package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +6 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js +89 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787800000000-AddScopeToNetworkDeviceLinkRule.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787800000000-AddScopeToNetworkDeviceLinkRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787900000000-AddRestrictToAttachedProjectsToGlobalSso.js +29 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787900000000-AddRestrictToAttachedProjectsToGlobalSso.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/SlackAuthorization.js +28 -4
- package/build/dist/Server/Middleware/SlackAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +197 -22
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/VerificationCodeRateLimit.js +393 -0
- package/build/dist/Server/Middleware/VerificationCodeRateLimit.js.map +1 -0
- package/build/dist/Server/Middleware/WhatsAppAuthorization.js +32 -2
- package/build/dist/Server/Middleware/WhatsAppAuthorization.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +136 -0
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +74 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/GlobalOidcProjectService.js +105 -0
- package/build/dist/Server/Services/GlobalOidcProjectService.js.map +1 -1
- package/build/dist/Server/Services/GlobalOidcService.js +127 -0
- package/build/dist/Server/Services/GlobalOidcService.js.map +1 -1
- package/build/dist/Server/Services/GlobalSsoProjectService.js +105 -0
- package/build/dist/Server/Services/GlobalSsoProjectService.js.map +1 -1
- package/build/dist/Server/Services/GlobalSsoService.js +127 -0
- package/build/dist/Server/Services/GlobalSsoService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +5 -0
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/PushNotificationService.js +69 -30
- package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +43 -7
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/UserCallService.js +54 -22
- package/build/dist/Server/Services/UserCallService.js.map +1 -1
- package/build/dist/Server/Services/UserEmailService.js +78 -17
- package/build/dist/Server/Services/UserEmailService.js.map +1 -1
- package/build/dist/Server/Services/UserIncomingCallNumberService.js +45 -74
- package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationMethodAdminService.js +1117 -0
- package/build/dist/Server/Services/UserNotificationMethodAdminService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationRuleService.js +20 -0
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserPushService.js +77 -0
- package/build/dist/Server/Services/UserPushService.js.map +1 -1
- package/build/dist/Server/Services/UserSmsService.js +50 -17
- package/build/dist/Server/Services/UserSmsService.js.map +1 -1
- package/build/dist/Server/Services/UserWhatsAppService.js +48 -15
- package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +27 -0
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js +46 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js.map +1 -1
- package/build/dist/Server/Utils/ChannelVerification.js +348 -0
- package/build/dist/Server/Utils/ChannelVerification.js.map +1 -0
- package/build/dist/Server/Utils/CronTab.js +66 -0
- package/build/dist/Server/Utils/CronTab.js.map +1 -1
- package/build/dist/Server/Utils/GlobalSsoAuthorization.js +112 -0
- package/build/dist/Server/Utils/GlobalSsoAuthorization.js.map +1 -0
- package/build/dist/Server/Utils/Marketing/ConversionUploadProvider.js +17 -1
- package/build/dist/Server/Utils/Marketing/ConversionUploadProvider.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/GoogleAds.js +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/GoogleAds.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/LinkedIn.js +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/LinkedIn.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/Meta.js +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/Meta.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/MicrosoftAds.js +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/MicrosoftAds.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/Reddit.js +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/Reddit.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +37 -35
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.js +21 -25
- package/build/dist/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js +20 -22
- package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +370 -42
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.js +21 -25
- package/build/dist/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +34 -37
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js +21 -25
- package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js +64 -52
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +25 -29
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +20 -17
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +8 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +17 -14
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +123 -23
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +95 -0
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +313 -0
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +3 -3
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +67 -26
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
- package/build/dist/Server/Utils/StatusPageContentSecurityPolicy.js +39 -0
- package/build/dist/Server/Utils/StatusPageContentSecurityPolicy.js.map +1 -0
- package/build/dist/Server/Utils/StatusPageCustomizationAccess.js +85 -0
- package/build/dist/Server/Utils/StatusPageCustomizationAccess.js.map +1 -0
- package/build/dist/Server/Utils/TotpAuth.js +127 -8
- package/build/dist/Server/Utils/TotpAuth.js.map +1 -1
- package/build/dist/Server/Utils/UserRegistrationToken.js +170 -0
- package/build/dist/Server/Utils/UserRegistrationToken.js.map +1 -0
- package/build/dist/Server/Utils/VerificationCode.js +120 -0
- package/build/dist/Server/Utils/VerificationCode.js.map +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Marketing/MarketingConversion.js +10 -0
- package/build/dist/Types/Marketing/MarketingConversion.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +1 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +42 -21
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +77 -5
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +18 -6
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/ServiceAlertTemplates.js +1028 -0
- package/build/dist/Types/Monitor/ServiceAlertTemplates.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceLinkRuleScope.js +46 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceLinkRuleScope.js.map +1 -0
- package/build/dist/Types/Permission.js +33 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/PushNotification/AndroidNotificationChannel.js +27 -0
- package/build/dist/Types/PushNotification/AndroidNotificationChannel.js.map +1 -0
- package/build/dist/Types/Service/ServiceLanguage.js +96 -0
- package/build/dist/Types/Service/ServiceLanguage.js.map +1 -0
- package/build/dist/Types/Text.js +82 -17
- package/build/dist/Types/Text.js.map +1 -1
- package/build/dist/UI/Components/Button/Button.js +22 -14
- package/build/dist/UI/Components/Button/Button.js.map +1 -1
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js +35 -3
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
- package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js +57 -0
- package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js +439 -0
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/PaletteFilter.js +135 -0
- package/build/dist/UI/Components/CommandPalette/PaletteFilter.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/PaletteRow.js +83 -0
- package/build/dist/UI/Components/CommandPalette/PaletteRow.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/RecentCommands.js +47 -0
- package/build/dist/UI/Components/CommandPalette/RecentCommands.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/Types.js +2 -0
- package/build/dist/UI/Components/CommandPalette/Types.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js +88 -0
- package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js.map +1 -0
- package/build/dist/UI/Components/Dropdown/Dropdown.js +6 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/Feed/FeedItem.js +1 -1
- package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
- package/build/dist/UI/Components/FormModal/BasicFormModal.js +2 -1
- package/build/dist/UI/Components/FormModal/BasicFormModal.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js +10 -1
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicModelForm.js +2 -1
- package/build/dist/UI/Components/Forms/BasicModelForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/ModelForm.js +4 -1
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/Utils/FormAnalyticsName.js +33 -0
- package/build/dist/UI/Components/Forms/Utils/FormAnalyticsName.js.map +1 -0
- package/build/dist/UI/Components/List/List.js +19 -5
- package/build/dist/UI/Components/List/List.js.map +1 -1
- package/build/dist/UI/Components/List/ListSkeleton.js +21 -0
- package/build/dist/UI/Components/List/ListSkeleton.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +52 -25
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +2 -2
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js +2 -1
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +9 -2
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +32 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +5 -1
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js +29 -5
- package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js +23 -1
- package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideOver/SideOver.js +23 -2
- package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
- package/build/dist/UI/Components/Skeleton/Skeleton.js +23 -0
- package/build/dist/UI/Components/Skeleton/Skeleton.js.map +1 -0
- package/build/dist/UI/Components/Table/Table.js +35 -24
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableSkeletonRows.js +52 -0
- package/build/dist/UI/Components/Table/TableSkeletonRows.js.map +1 -0
- package/build/dist/UI/Components/Tabs/Tab.js +1 -1
- package/build/dist/UI/Components/Tabs/Tab.js.map +1 -1
- package/build/dist/UI/Components/Toast/Toast.js +77 -23
- package/build/dist/UI/Components/Toast/Toast.js.map +1 -1
- package/build/dist/UI/Components/Toast/ToastInit.js +37 -15
- package/build/dist/UI/Components/Toast/ToastInit.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -9
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/ModelListCache.js +126 -0
- package/build/dist/UI/Utils/ModelListCache.js.map +1 -0
- package/build/dist/UI/Utils/Project.js +24 -1
- package/build/dist/UI/Utils/Project.js.map +1 -1
- package/build/dist/Utils/API.js +6 -1
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/Analytics.js +50 -2
- package/build/dist/Utils/Analytics.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +37 -0
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js +318 -37
- package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.js +87 -0
- package/build/dist/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.js.map +1 -0
- package/jest.config.json +1 -1
- package/package.json +2 -3
- package/Server/Utils/Monitor/MonitorClusterContext.ts +0 -182
- package/Tests/__mocks__/otpauth.js +0 -30
- package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +0 -141
- package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +0 -1
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import NetworkDeviceLinkRuleScope, {
|
|
2
|
+
NetworkDeviceLinkRuleScopeUtil,
|
|
3
|
+
} from "../../../Types/NetworkDevice/NetworkDeviceLinkRuleScope";
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* `scope` was added to a table that already had rules in it, so every rule
|
|
7
|
+
* written before the column existed holds NULL — and each of those rules is
|
|
8
|
+
* currently drawing a topology somebody has already looked at and trusted.
|
|
9
|
+
* NULL therefore has to read as Project, because Project is exactly what
|
|
10
|
+
* those rules have always meant: one parent across whatever device set the
|
|
11
|
+
* query handed the resolver. Read NULL as Site instead and every legacy rule
|
|
12
|
+
* quietly starts asking a different question, re-pointing cables on maps
|
|
13
|
+
* nobody re-opened. That is why the default lives in `parse` rather than in a
|
|
14
|
+
* `=== "Site"` comparison scattered over the call sites: one place to be
|
|
15
|
+
* right, and it is pinned here.
|
|
16
|
+
*
|
|
17
|
+
* The mirror of the same worry is the unrecognised value. The column is free
|
|
18
|
+
* text (the NetworkDeviceMonitoringMethod precedent), so a typo, an older
|
|
19
|
+
* client, or a future scope name that this build has never heard of can all
|
|
20
|
+
* land in it. Every one of them has to fall back to the behaviour that was
|
|
21
|
+
* already on screen rather than to the new one.
|
|
22
|
+
*/
|
|
23
|
+
describe("NetworkDeviceLinkRuleScope enum", () => {
|
|
24
|
+
/*
|
|
25
|
+
* These strings are persisted values, not display labels. Renaming one is
|
|
26
|
+
* a silent data migration: every row already holding the old spelling stops
|
|
27
|
+
* being recognised and — by the fallback above — quietly reverts to
|
|
28
|
+
* Project, with no error anywhere to say so. Change these only alongside a
|
|
29
|
+
* migration that rewrites the column.
|
|
30
|
+
*/
|
|
31
|
+
test("Project is persisted as the string Project", () => {
|
|
32
|
+
expect(NetworkDeviceLinkRuleScope.Project).toBe("Project");
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("Site is persisted as the string Site", () => {
|
|
36
|
+
expect(NetworkDeviceLinkRuleScope.Site).toBe("Site");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("has exactly the two known scopes", () => {
|
|
40
|
+
expect(Object.values(NetworkDeviceLinkRuleScope).sort()).toEqual([
|
|
41
|
+
"Project",
|
|
42
|
+
"Site",
|
|
43
|
+
]);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/*
|
|
48
|
+
* One table, two consumers. `parse` and `isSiteScoped` are asserted against
|
|
49
|
+
* the same rows further down so the pair cannot drift apart: a caller that
|
|
50
|
+
* branches on `isSiteScoped` and a caller that switches on `parse` must never
|
|
51
|
+
* disagree about the same stored string.
|
|
52
|
+
*/
|
|
53
|
+
const PROJECT_INPUTS: Array<string | null | undefined> = [
|
|
54
|
+
// The pre-column rows, and the shapes an empty form field arrives as.
|
|
55
|
+
undefined,
|
|
56
|
+
null,
|
|
57
|
+
"",
|
|
58
|
+
" ",
|
|
59
|
+
// The value written by anything that does set the column explicitly.
|
|
60
|
+
"Project",
|
|
61
|
+
"project",
|
|
62
|
+
"PROJECT",
|
|
63
|
+
" Project ",
|
|
64
|
+
/*
|
|
65
|
+
* Near-misses that must NOT be read as site scope. "Sites" and
|
|
66
|
+
* "site-scoped" are the plausible typo and the plausible rename; matching
|
|
67
|
+
* them loosely would turn a mistyped rule into one that silently redraws.
|
|
68
|
+
*/
|
|
69
|
+
"Sites",
|
|
70
|
+
"site-scoped",
|
|
71
|
+
"anything",
|
|
72
|
+
// Falsy-looking text is still just unrecognised text, not a flag.
|
|
73
|
+
"0",
|
|
74
|
+
"false",
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
const SITE_INPUTS: Array<string> = [
|
|
78
|
+
"Site",
|
|
79
|
+
"site",
|
|
80
|
+
"SITE",
|
|
81
|
+
" site ",
|
|
82
|
+
" SiTe ",
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
interface ScopeCase {
|
|
86
|
+
value: string | null | undefined;
|
|
87
|
+
expected: NetworkDeviceLinkRuleScope;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const ALL_CASES: Array<ScopeCase> = [
|
|
91
|
+
...PROJECT_INPUTS.map((value: string | null | undefined): ScopeCase => {
|
|
92
|
+
return { value: value, expected: NetworkDeviceLinkRuleScope.Project };
|
|
93
|
+
}),
|
|
94
|
+
...SITE_INPUTS.map((value: string): ScopeCase => {
|
|
95
|
+
return { value: value, expected: NetworkDeviceLinkRuleScope.Site };
|
|
96
|
+
}),
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
describe("NetworkDeviceLinkRuleScopeUtil.parse", () => {
|
|
100
|
+
test.each(PROJECT_INPUTS)(
|
|
101
|
+
"reads %p as Project",
|
|
102
|
+
(value: string | null | undefined) => {
|
|
103
|
+
expect(NetworkDeviceLinkRuleScopeUtil.parse(value)).toBe(
|
|
104
|
+
NetworkDeviceLinkRuleScope.Project,
|
|
105
|
+
);
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
test.each(SITE_INPUTS)(
|
|
110
|
+
"reads %p as Site, case- and whitespace-insensitively",
|
|
111
|
+
(value: string) => {
|
|
112
|
+
expect(NetworkDeviceLinkRuleScopeUtil.parse(value)).toBe(
|
|
113
|
+
NetworkDeviceLinkRuleScope.Site,
|
|
114
|
+
);
|
|
115
|
+
},
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
/*
|
|
119
|
+
* Only an exact (trimmed, lowercased) "site" opts in. Substring matching
|
|
120
|
+
* would make "not site" or "site (deprecated)" flip the rule's meaning,
|
|
121
|
+
* which is the one direction of mistake this type refuses to make.
|
|
122
|
+
*/
|
|
123
|
+
test("does not treat a string merely containing 'site' as site-scoped", () => {
|
|
124
|
+
expect(NetworkDeviceLinkRuleScopeUtil.parse("per site")).toBe(
|
|
125
|
+
NetworkDeviceLinkRuleScope.Project,
|
|
126
|
+
);
|
|
127
|
+
expect(NetworkDeviceLinkRuleScopeUtil.parse("not site")).toBe(
|
|
128
|
+
NetworkDeviceLinkRuleScope.Project,
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
/*
|
|
133
|
+
* The return value is always one of the two enum members — never the raw
|
|
134
|
+
* column text passed straight back. Callers switch on it, and a passthrough
|
|
135
|
+
* would send an unrecognised spelling into a branch that does not exist.
|
|
136
|
+
*/
|
|
137
|
+
test("returns an enum member for every case in the table, never the raw input", () => {
|
|
138
|
+
for (const testCase of ALL_CASES) {
|
|
139
|
+
const parsed: NetworkDeviceLinkRuleScope =
|
|
140
|
+
NetworkDeviceLinkRuleScopeUtil.parse(testCase.value);
|
|
141
|
+
|
|
142
|
+
expect(Object.values(NetworkDeviceLinkRuleScope)).toContain(parsed);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
/*
|
|
147
|
+
* The parser sits in the middle of rendering a topology map: throwing here
|
|
148
|
+
* would take out the whole map over one bad cell, when the safe answer
|
|
149
|
+
* (Project, what the rule drew yesterday) is right there. So nothing in the
|
|
150
|
+
* declared signature may throw — and neither may the falsy non-string
|
|
151
|
+
* shapes a loosely typed caller or a hand-rolled JSON body can smuggle past
|
|
152
|
+
* TypeScript, which the `|| ""` guard absorbs.
|
|
153
|
+
*/
|
|
154
|
+
test("never throws for any value in or near its declared signature", () => {
|
|
155
|
+
const inputs: Array<string | null | undefined> = [
|
|
156
|
+
...ALL_CASES.map((testCase: ScopeCase): string | null | undefined => {
|
|
157
|
+
return testCase.value;
|
|
158
|
+
}),
|
|
159
|
+
"\tSITE\n",
|
|
160
|
+
"\n project \t",
|
|
161
|
+
"Site\u0000",
|
|
162
|
+
"🙂",
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
for (const input of inputs) {
|
|
166
|
+
expect((): NetworkDeviceLinkRuleScope => {
|
|
167
|
+
return NetworkDeviceLinkRuleScopeUtil.parse(input);
|
|
168
|
+
}).not.toThrow();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/*
|
|
172
|
+
* Not strings at all. 0/false/NaN are what a JSON body or a permissive
|
|
173
|
+
* ORM can hand over in place of "no scope set", and they have to land on
|
|
174
|
+
* the same safe default rather than blow up.
|
|
175
|
+
*/
|
|
176
|
+
const nonStrings: Array<unknown> = [0, false, NaN];
|
|
177
|
+
|
|
178
|
+
for (const input of nonStrings) {
|
|
179
|
+
expect(
|
|
180
|
+
NetworkDeviceLinkRuleScopeUtil.parse(input as unknown as string),
|
|
181
|
+
).toBe(NetworkDeviceLinkRuleScope.Project);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe("NetworkDeviceLinkRuleScopeUtil.isSiteScoped", () => {
|
|
187
|
+
test.each(SITE_INPUTS)("is true for %p", (value: string) => {
|
|
188
|
+
expect(NetworkDeviceLinkRuleScopeUtil.isSiteScoped(value)).toBe(true);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test.each(PROJECT_INPUTS)(
|
|
192
|
+
"is false for %p",
|
|
193
|
+
(value: string | null | undefined) => {
|
|
194
|
+
expect(NetworkDeviceLinkRuleScopeUtil.isSiteScoped(value)).toBe(false);
|
|
195
|
+
},
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
/*
|
|
199
|
+
* The two entry points are asserted against the same table in the same
|
|
200
|
+
* loop, so neither can be extended (a new alias, a new scope) without the
|
|
201
|
+
* other. `NetworkDeviceLinkRuleUtil` branches on `isSiteScoped` while the
|
|
202
|
+
* dashboard's rule list renders off it too — if they ever disagreed, a rule
|
|
203
|
+
* would be labelled one way and resolved the other.
|
|
204
|
+
*/
|
|
205
|
+
test("agrees with parse on every case in the table", () => {
|
|
206
|
+
for (const testCase of ALL_CASES) {
|
|
207
|
+
expect(NetworkDeviceLinkRuleScopeUtil.parse(testCase.value)).toBe(
|
|
208
|
+
testCase.expected,
|
|
209
|
+
);
|
|
210
|
+
expect(NetworkDeviceLinkRuleScopeUtil.isSiteScoped(testCase.value)).toBe(
|
|
211
|
+
testCase.expected === NetworkDeviceLinkRuleScope.Site,
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
});
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SERVICE_LANGUAGE_DISPLAY_NAMES,
|
|
3
|
+
ServiceLanguage,
|
|
4
|
+
detectServiceLanguage,
|
|
5
|
+
} from "../../../Types/Service/ServiceLanguage";
|
|
6
|
+
import TechStack from "../../../Types/Service/TechStack";
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Which runtime a service is written in, decided from three sources of
|
|
10
|
+
* evidence of decreasing trustworthiness.
|
|
11
|
+
*
|
|
12
|
+
* This used to only pick which charts to draw on the service overview, where
|
|
13
|
+
* a wrong answer is a chart with no data in it. It now also picks which
|
|
14
|
+
* monitors OneUptime recommends, where a wrong answer is a monitor that
|
|
15
|
+
* queries a metric the service never emits and therefore never fires — a
|
|
16
|
+
* silent gap that reads as coverage. Every case below is about the difference
|
|
17
|
+
* between "we know" and "we are guessing".
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const ALL_LANGUAGES: Array<ServiceLanguage> = Object.keys(
|
|
21
|
+
SERVICE_LANGUAGE_DISPLAY_NAMES,
|
|
22
|
+
) as Array<ServiceLanguage>;
|
|
23
|
+
|
|
24
|
+
describe("detectServiceLanguage", () => {
|
|
25
|
+
describe("precedence between the three sources", () => {
|
|
26
|
+
/*
|
|
27
|
+
* The order is not arbitrary. `telemetry.sdk.language` is stamped by the
|
|
28
|
+
* SDK inside the process, so it describes what the process actually runs
|
|
29
|
+
* on. `process.runtime.name` is the same information one hop later.
|
|
30
|
+
* The tech stack is a human's answer typed into a form, which can be
|
|
31
|
+
* months out of date. Each test below sets up a deliberate disagreement
|
|
32
|
+
* so the winner is unambiguous.
|
|
33
|
+
*/
|
|
34
|
+
it("prefers the SDK language over the runtime name", () => {
|
|
35
|
+
expect(
|
|
36
|
+
detectServiceLanguage({
|
|
37
|
+
telemetrySdkLanguage: "go",
|
|
38
|
+
runtimeName: "OpenJDK Runtime Environment",
|
|
39
|
+
}),
|
|
40
|
+
).toBe("go");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("prefers the SDK language over the tech stack", () => {
|
|
44
|
+
expect(
|
|
45
|
+
detectServiceLanguage({
|
|
46
|
+
telemetrySdkLanguage: "python",
|
|
47
|
+
techStack: [TechStack.Java],
|
|
48
|
+
}),
|
|
49
|
+
).toBe("python");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("prefers the runtime name over the tech stack", () => {
|
|
53
|
+
expect(
|
|
54
|
+
detectServiceLanguage({
|
|
55
|
+
runtimeName: "node",
|
|
56
|
+
techStack: [TechStack.Java],
|
|
57
|
+
}),
|
|
58
|
+
).toBe("nodejs");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("falls through to the tech stack when telemetry says nothing", () => {
|
|
62
|
+
expect(
|
|
63
|
+
detectServiceLanguage({
|
|
64
|
+
techStack: [TechStack.Rust],
|
|
65
|
+
}),
|
|
66
|
+
).toBe("rust");
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe("the SDK language attribute", () => {
|
|
71
|
+
it.each(ALL_LANGUAGES)("recognises %s", (language: ServiceLanguage) => {
|
|
72
|
+
expect(detectServiceLanguage({ telemetrySdkLanguage: language })).toBe(
|
|
73
|
+
language,
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("is matched case-insensitively and ignores surrounding whitespace", () => {
|
|
78
|
+
expect(
|
|
79
|
+
detectServiceLanguage({ telemetrySdkLanguage: " DotNet " }),
|
|
80
|
+
).toBe("dotnet");
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
/*
|
|
84
|
+
* The important negative case. An unrecognised value must NOT be returned
|
|
85
|
+
* verbatim — it would be a string that looks like a `ServiceLanguage` to
|
|
86
|
+
* every consumer and matches no template set, so the recommendations page
|
|
87
|
+
* would show nothing at all rather than the language-agnostic set.
|
|
88
|
+
*/
|
|
89
|
+
it("does not pass an unrecognised SDK language through", () => {
|
|
90
|
+
expect(
|
|
91
|
+
detectServiceLanguage({ telemetrySdkLanguage: "cobol" }),
|
|
92
|
+
).toBeNull();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("falls through to the other sources when the SDK language is unknown", () => {
|
|
96
|
+
expect(
|
|
97
|
+
detectServiceLanguage({
|
|
98
|
+
telemetrySdkLanguage: "cobol",
|
|
99
|
+
techStack: [TechStack.Go],
|
|
100
|
+
}),
|
|
101
|
+
).toBe("go");
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe("the runtime name markers", () => {
|
|
106
|
+
it.each([
|
|
107
|
+
["OpenJDK 64-Bit Server VM", "java"],
|
|
108
|
+
["GraalVM CE", "java"],
|
|
109
|
+
["Java HotSpot(TM) 64-Bit Server VM", "java"],
|
|
110
|
+
[".NET 9.0.0", "dotnet"],
|
|
111
|
+
["dotnet", "dotnet"],
|
|
112
|
+
["node", "nodejs"],
|
|
113
|
+
["Deno", "nodejs"],
|
|
114
|
+
["bun", "nodejs"],
|
|
115
|
+
["CPython", "python"],
|
|
116
|
+
["PyPy", "python"],
|
|
117
|
+
["BEAM", "erlang"],
|
|
118
|
+
["Erlang/OTP 26", "erlang"],
|
|
119
|
+
["ruby", "ruby"],
|
|
120
|
+
["PHP 8.3", "php"],
|
|
121
|
+
["rustc", "rust"],
|
|
122
|
+
["swift", "swift"],
|
|
123
|
+
["go", "go"],
|
|
124
|
+
])(
|
|
125
|
+
"maps runtime name %s to %s",
|
|
126
|
+
(runtimeName: string, expected: string) => {
|
|
127
|
+
expect(detectServiceLanguage({ runtimeName: runtimeName })).toBe(
|
|
128
|
+
expected,
|
|
129
|
+
);
|
|
130
|
+
},
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
/*
|
|
134
|
+
* `go` is a two-letter substring, so it appears inside plenty of words —
|
|
135
|
+
* "GraalVM" does not contain it, but the ordering still matters and this
|
|
136
|
+
* pins it: the JVM markers are checked first, so a runtime string that
|
|
137
|
+
* contains both loses to the more specific one.
|
|
138
|
+
*/
|
|
139
|
+
it("checks specific markers before the two-letter go marker", () => {
|
|
140
|
+
expect(
|
|
141
|
+
detectServiceLanguage({ runtimeName: "GraalVM for Go interop" }),
|
|
142
|
+
).toBe("java");
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("returns null for a runtime name it does not recognise", () => {
|
|
146
|
+
expect(detectServiceLanguage({ runtimeName: "SomeVM 1.0" })).toBeNull();
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
describe("the tech stack fallback", () => {
|
|
151
|
+
it("maps Kotlin to java, because the runtime is what matters", () => {
|
|
152
|
+
expect(detectServiceLanguage({ techStack: [TechStack.Kotlin] })).toBe(
|
|
153
|
+
"java",
|
|
154
|
+
);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("maps C# to dotnet", () => {
|
|
158
|
+
expect(detectServiceLanguage({ techStack: [TechStack.CSharp] })).toBe(
|
|
159
|
+
"dotnet",
|
|
160
|
+
);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it.each([TechStack.TypeScript, TechStack.JavaScript, TechStack.NodeJS])(
|
|
164
|
+
"maps %s to nodejs",
|
|
165
|
+
(techStack: TechStack) => {
|
|
166
|
+
expect(detectServiceLanguage({ techStack: [techStack] })).toBe(
|
|
167
|
+
"nodejs",
|
|
168
|
+
);
|
|
169
|
+
},
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
it("maps React to webjs rather than to nodejs", () => {
|
|
173
|
+
expect(detectServiceLanguage({ techStack: [TechStack.React] })).toBe(
|
|
174
|
+
"webjs",
|
|
175
|
+
);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("takes the first entry that maps to a runtime", () => {
|
|
179
|
+
expect(
|
|
180
|
+
detectServiceLanguage({
|
|
181
|
+
techStack: [TechStack.Shell, TechStack.Markdown, TechStack.Go],
|
|
182
|
+
}),
|
|
183
|
+
).toBe("go");
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it.each([TechStack.Shell, TechStack.Markdown, TechStack.Other])(
|
|
187
|
+
"does not invent a runtime for %s",
|
|
188
|
+
(techStack: TechStack) => {
|
|
189
|
+
expect(detectServiceLanguage({ techStack: [techStack] })).toBeNull();
|
|
190
|
+
},
|
|
191
|
+
);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
describe("when nothing identifies the runtime", () => {
|
|
195
|
+
/*
|
|
196
|
+
* Null, never a default. A default would hand every unidentified service
|
|
197
|
+
* one language's recommendations — monitors on metrics it does not emit,
|
|
198
|
+
* presented as if OneUptime had established what it runs on.
|
|
199
|
+
*/
|
|
200
|
+
it("returns null for no input at all", () => {
|
|
201
|
+
expect(detectServiceLanguage({})).toBeNull();
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("returns null for empty strings and an empty tech stack", () => {
|
|
205
|
+
expect(
|
|
206
|
+
detectServiceLanguage({
|
|
207
|
+
telemetrySdkLanguage: "",
|
|
208
|
+
runtimeName: "",
|
|
209
|
+
techStack: [],
|
|
210
|
+
}),
|
|
211
|
+
).toBeNull();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it("returns null for whitespace-only telemetry values", () => {
|
|
215
|
+
expect(
|
|
216
|
+
detectServiceLanguage({
|
|
217
|
+
telemetrySdkLanguage: " ",
|
|
218
|
+
runtimeName: " ",
|
|
219
|
+
}),
|
|
220
|
+
).toBeNull();
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("returns null for explicitly undefined fields", () => {
|
|
224
|
+
expect(
|
|
225
|
+
detectServiceLanguage({
|
|
226
|
+
telemetrySdkLanguage: undefined,
|
|
227
|
+
runtimeName: undefined,
|
|
228
|
+
techStack: undefined,
|
|
229
|
+
}),
|
|
230
|
+
).toBeNull();
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
describe("SERVICE_LANGUAGE_DISPLAY_NAMES", () => {
|
|
236
|
+
it("names every language, non-blank", () => {
|
|
237
|
+
expect(ALL_LANGUAGES.length).toBeGreaterThan(0);
|
|
238
|
+
|
|
239
|
+
for (const language of ALL_LANGUAGES) {
|
|
240
|
+
expect(
|
|
241
|
+
SERVICE_LANGUAGE_DISPLAY_NAMES[language].trim().length,
|
|
242
|
+
).toBeGreaterThan(0);
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it("gives each language a distinct display name", () => {
|
|
247
|
+
const names: Array<string> = ALL_LANGUAGES.map(
|
|
248
|
+
(language: ServiceLanguage) => {
|
|
249
|
+
return SERVICE_LANGUAGE_DISPLAY_NAMES[language];
|
|
250
|
+
},
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
expect(new Set<string>(names).size).toBe(names.length);
|
|
254
|
+
});
|
|
255
|
+
});
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import Text from "../../Types/Text";
|
|
2
|
+
import { describe, expect, it } from "@jest/globals";
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* GHSA-5cr8-vph4-3hrf, CWE-330.
|
|
6
|
+
*
|
|
7
|
+
* Text.generateRandomNumber is what mints notification-channel verification
|
|
8
|
+
* codes. It used to draw from the literal string "12134567890" using
|
|
9
|
+
* Math.random, which is wrong twice over: the alphabet has "1" in it twice so
|
|
10
|
+
* the digits are not equally likely, and Math.random is a non-cryptographic
|
|
11
|
+
* PRNG whose state is recoverable from its own output.
|
|
12
|
+
*
|
|
13
|
+
* Neither property can be observed by looking at one value, which is why they
|
|
14
|
+
* survived. The tests below observe them the only ways available: by counting
|
|
15
|
+
* a large sample for bias, and by watching which source the generator actually
|
|
16
|
+
* pulls from.
|
|
17
|
+
*/
|
|
18
|
+
describe("Text random generation", () => {
|
|
19
|
+
describe("generateRandomNumber", () => {
|
|
20
|
+
it("emits only digits, at the requested length", () => {
|
|
21
|
+
for (let length: number = 1; length <= 12; length++) {
|
|
22
|
+
const value: string = Text.generateRandomNumber(length);
|
|
23
|
+
|
|
24
|
+
expect(value).toHaveLength(length);
|
|
25
|
+
expect(value).toMatch(/^[0-9]+$/);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("defaults to ten characters", () => {
|
|
30
|
+
expect(Text.generateRandomNumber()).toHaveLength(10);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
/*
|
|
34
|
+
* The direct regression. With the old alphabet the digit "1" appeared
|
|
35
|
+
* twice in an eleven-character string, so it came up 2/11 of the time
|
|
36
|
+
* against 1/11 for every other digit — and "8" appeared once, like the
|
|
37
|
+
* rest, only because the typo happened to leave it in.
|
|
38
|
+
*
|
|
39
|
+
* 60,000 digits puts the expected count per digit at 6,000 with a
|
|
40
|
+
* standard deviation of about 73. The old generator produced ~10,909 ones
|
|
41
|
+
* and ~5,454 of everything else, so the bound below is enormously loose
|
|
42
|
+
* for a fair generator and enormously tight for the broken one.
|
|
43
|
+
*/
|
|
44
|
+
it("draws every digit with equal probability", () => {
|
|
45
|
+
const sampleSize: number = 10000;
|
|
46
|
+
const digitsPerSample: number = 6;
|
|
47
|
+
const counts: Record<string, number> = {};
|
|
48
|
+
|
|
49
|
+
for (let i: number = 0; i < sampleSize; i++) {
|
|
50
|
+
for (const digit of Text.generateRandomNumber(digitsPerSample)) {
|
|
51
|
+
counts[digit] = (counts[digit] || 0) + 1;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const totalDigits: number = sampleSize * digitsPerSample;
|
|
56
|
+
const expectedPerDigit: number = totalDigits / 10;
|
|
57
|
+
|
|
58
|
+
/*
|
|
59
|
+
* Every digit must actually appear — "8" was reachable before, but a
|
|
60
|
+
* future typo in the alphabet would show up here.
|
|
61
|
+
*/
|
|
62
|
+
expect(Object.keys(counts).sort()).toEqual([
|
|
63
|
+
"0",
|
|
64
|
+
"1",
|
|
65
|
+
"2",
|
|
66
|
+
"3",
|
|
67
|
+
"4",
|
|
68
|
+
"5",
|
|
69
|
+
"6",
|
|
70
|
+
"7",
|
|
71
|
+
"8",
|
|
72
|
+
"9",
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
for (const digit of Object.keys(counts)) {
|
|
76
|
+
const count: number = counts[digit] as number;
|
|
77
|
+
|
|
78
|
+
/*
|
|
79
|
+
* Six sigma either way: a fair generator fails this about once in
|
|
80
|
+
* 500 million runs, the old one fails it every time.
|
|
81
|
+
*/
|
|
82
|
+
expect(count).toBeGreaterThan(expectedPerDigit * 0.9);
|
|
83
|
+
expect(count).toBeLessThan(expectedPerDigit * 1.1);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
/*
|
|
88
|
+
* Leading zeros are part of the code space. Dropping them — by going
|
|
89
|
+
* through a number, say — would quietly remove a tenth of it.
|
|
90
|
+
*/
|
|
91
|
+
it("can produce codes with leading zeros", () => {
|
|
92
|
+
let sawLeadingZero: boolean = false;
|
|
93
|
+
|
|
94
|
+
for (let i: number = 0; i < 500; i++) {
|
|
95
|
+
if (Text.generateRandomNumber(6).startsWith("0")) {
|
|
96
|
+
sawLeadingZero = true;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
expect(sawLeadingZero).toBe(true);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
/*
|
|
105
|
+
* The other half of CWE-330. Math.random is seeded per process and its
|
|
106
|
+
* internal state can be recovered from a handful of outputs, after which
|
|
107
|
+
* every future value is known exactly — no guessing required. Asserting
|
|
108
|
+
* on the SOURCE is the only way to pin this: any specific output is a
|
|
109
|
+
* legal output of either generator.
|
|
110
|
+
*/
|
|
111
|
+
it("does not fall back to Math.random when a CSPRNG is available", () => {
|
|
112
|
+
const mathRandomSpy: jest.SpyInstance = jest.spyOn(Math, "random");
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
for (let i: number = 0; i < 100; i++) {
|
|
116
|
+
Text.generateRandomNumber(6);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
expect(mathRandomSpy).not.toHaveBeenCalled();
|
|
120
|
+
} finally {
|
|
121
|
+
mathRandomSpy.mockRestore();
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("takes its bytes from crypto.getRandomValues", () => {
|
|
126
|
+
const getRandomValuesSpy: jest.SpyInstance = jest.spyOn(
|
|
127
|
+
globalThis.crypto,
|
|
128
|
+
"getRandomValues",
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
Text.generateRandomNumber(6);
|
|
133
|
+
|
|
134
|
+
expect(getRandomValuesSpy).toHaveBeenCalled();
|
|
135
|
+
} finally {
|
|
136
|
+
getRandomValuesSpy.mockRestore();
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("produces a different value practically every time", () => {
|
|
141
|
+
const seen: Set<string> = new Set<string>();
|
|
142
|
+
|
|
143
|
+
for (let i: number = 0; i < 1000; i++) {
|
|
144
|
+
seen.add(Text.generateRandomNumber(10));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/*
|
|
148
|
+
* Ten digits, a thousand draws: collisions are vanishingly unlikely,
|
|
149
|
+
* and a stuck generator would collapse this to 1.
|
|
150
|
+
*/
|
|
151
|
+
expect(seen.size).toBe(1000);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
describe("generateRandomText", () => {
|
|
156
|
+
it("emits only letters, at the requested length", () => {
|
|
157
|
+
for (let length: number = 1; length <= 40; length += 7) {
|
|
158
|
+
const value: string = Text.generateRandomText(length);
|
|
159
|
+
|
|
160
|
+
expect(value).toHaveLength(length);
|
|
161
|
+
expect(value).toMatch(/^[A-Za-z]+$/);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it("defaults to ten characters", () => {
|
|
166
|
+
expect(Text.generateRandomText()).toHaveLength(10);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("does not fall back to Math.random when a CSPRNG is available", () => {
|
|
170
|
+
const mathRandomSpy: jest.SpyInstance = jest.spyOn(Math, "random");
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
for (let i: number = 0; i < 100; i++) {
|
|
174
|
+
Text.generateRandomText(20);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
expect(mathRandomSpy).not.toHaveBeenCalled();
|
|
178
|
+
} finally {
|
|
179
|
+
mathRandomSpy.mockRestore();
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
/*
|
|
184
|
+
* Both alphabets have 52 characters, which does NOT divide 256 — so
|
|
185
|
+
* `byte % 52` would be biased towards the first 48 letters. The rejection
|
|
186
|
+
* sampling is what removes that, and this is the test that would notice
|
|
187
|
+
* if somebody "simplified" it away.
|
|
188
|
+
*/
|
|
189
|
+
it("draws every letter with roughly equal probability", () => {
|
|
190
|
+
const counts: Record<string, number> = {};
|
|
191
|
+
const totalCharacters: number = 52 * 2000;
|
|
192
|
+
|
|
193
|
+
for (let i: number = 0; i < 2000; i++) {
|
|
194
|
+
for (const character of Text.generateRandomText(52)) {
|
|
195
|
+
counts[character] = (counts[character] || 0) + 1;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
expect(Object.keys(counts)).toHaveLength(52);
|
|
200
|
+
|
|
201
|
+
const expectedPerCharacter: number = totalCharacters / 52;
|
|
202
|
+
|
|
203
|
+
for (const character of Object.keys(counts)) {
|
|
204
|
+
const count: number = counts[character] as number;
|
|
205
|
+
|
|
206
|
+
expect(count).toBeGreaterThan(expectedPerCharacter * 0.85);
|
|
207
|
+
expect(count).toBeLessThan(expectedPerCharacter * 1.15);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
});
|