@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,248 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* A stand-in for the authenticator app on the user's phone.
|
|
5
|
+
*
|
|
6
|
+
* Every function here is derived from RFC 4648 (base32), RFC 4226 (HOTP) and
|
|
7
|
+
* RFC 6238 (TOTP) using Node's own crypto primitives. Nothing in this file
|
|
8
|
+
* imports `otpauth`, and that is the entire point: the server verifies with
|
|
9
|
+
* `otpauth`, so a test that also generates its expected codes with `otpauth`
|
|
10
|
+
* proves only that the library agrees with itself. It would have passed
|
|
11
|
+
* happily throughout issue #3275, while every user with Google Authenticator
|
|
12
|
+
* was locked out.
|
|
13
|
+
*
|
|
14
|
+
* The most useful thing in here is `googleAuthenticatorCode`, which models the
|
|
15
|
+
* behaviour that caused that bug: real phone apps parse the otpauth:// URI,
|
|
16
|
+
* IGNORE its `algorithm` parameter, and compute SHA1 regardless.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const BASE32_ALPHABET: string = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
20
|
+
|
|
21
|
+
export const DEFAULT_DIGITS: number = 6;
|
|
22
|
+
export const DEFAULT_PERIOD_IN_SECONDS: number = 30;
|
|
23
|
+
|
|
24
|
+
/** The algorithm a phone app uses no matter what the QR code claims. */
|
|
25
|
+
export const PHONE_APP_ALGORITHM: string = "SHA1";
|
|
26
|
+
|
|
27
|
+
export type Base32EncodeFunction = (bytes: Buffer) => string;
|
|
28
|
+
|
|
29
|
+
export const base32Encode: Base32EncodeFunction = (bytes: Buffer): string => {
|
|
30
|
+
let bits: string = "";
|
|
31
|
+
|
|
32
|
+
for (const byte of bytes) {
|
|
33
|
+
bits += byte.toString(2).padStart(8, "0");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let output: string = "";
|
|
37
|
+
|
|
38
|
+
for (let i: number = 0; i < bits.length; i += 5) {
|
|
39
|
+
const chunk: string = bits.slice(i, i + 5).padEnd(5, "0");
|
|
40
|
+
output += BASE32_ALPHABET[parseInt(chunk, 2)];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return output;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type Base32DecodeFunction = (encoded: string) => Buffer;
|
|
47
|
+
|
|
48
|
+
export const base32Decode: Base32DecodeFunction = (encoded: string): Buffer => {
|
|
49
|
+
let bits: string = "";
|
|
50
|
+
|
|
51
|
+
for (const character of encoded.replace(/[=]+$/, "").toUpperCase()) {
|
|
52
|
+
const value: number = BASE32_ALPHABET.indexOf(character);
|
|
53
|
+
|
|
54
|
+
if (value === -1) {
|
|
55
|
+
throw new Error(`Not base32: ${character}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
bits += value.toString(2).padStart(5, "0");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const bytes: Array<number> = [];
|
|
62
|
+
|
|
63
|
+
for (let i: number = 0; i + 8 <= bits.length; i += 8) {
|
|
64
|
+
bytes.push(parseInt(bits.slice(i, i + 8), 2));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return Buffer.from(bytes);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/*
|
|
71
|
+
* HOTP, RFC 4226 section 5.3: HMAC the 8-byte big-endian counter under the
|
|
72
|
+
* shared key, take the low nibble of the last byte as an offset, read a
|
|
73
|
+
* big-endian 31-bit integer from there, reduce modulo 10^digits.
|
|
74
|
+
*/
|
|
75
|
+
export type HotpFunction = (data: {
|
|
76
|
+
key: Buffer;
|
|
77
|
+
counter: number;
|
|
78
|
+
algorithm: string;
|
|
79
|
+
digits: number;
|
|
80
|
+
}) => string;
|
|
81
|
+
|
|
82
|
+
export const hotp: HotpFunction = (data: {
|
|
83
|
+
key: Buffer;
|
|
84
|
+
counter: number;
|
|
85
|
+
algorithm: string;
|
|
86
|
+
digits: number;
|
|
87
|
+
}): string => {
|
|
88
|
+
const counterBytes: Buffer = Buffer.alloc(8);
|
|
89
|
+
counterBytes.writeBigUInt64BE(BigInt(data.counter));
|
|
90
|
+
|
|
91
|
+
const digest: Buffer = crypto
|
|
92
|
+
.createHmac(data.algorithm.toLowerCase(), data.key)
|
|
93
|
+
.update(counterBytes)
|
|
94
|
+
.digest();
|
|
95
|
+
|
|
96
|
+
const offset: number = digest[digest.length - 1]! & 0x0f;
|
|
97
|
+
|
|
98
|
+
const binary: number =
|
|
99
|
+
((digest[offset]! & 0x7f) << 24) |
|
|
100
|
+
((digest[offset + 1]! & 0xff) << 16) |
|
|
101
|
+
((digest[offset + 2]! & 0xff) << 8) |
|
|
102
|
+
(digest[offset + 3]! & 0xff);
|
|
103
|
+
|
|
104
|
+
return (binary % 10 ** data.digits).toString().padStart(data.digits, "0");
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/*
|
|
108
|
+
* TOTP: HOTP with the counter derived from the clock (RFC 6238 section 4).
|
|
109
|
+
*/
|
|
110
|
+
export type AuthenticatorCodeFunction = (data: {
|
|
111
|
+
secretBase32: string;
|
|
112
|
+
algorithm?: string | undefined;
|
|
113
|
+
digits?: number | undefined;
|
|
114
|
+
periodInSeconds?: number | undefined;
|
|
115
|
+
atUnixSeconds?: number | undefined;
|
|
116
|
+
}) => string;
|
|
117
|
+
|
|
118
|
+
export const authenticatorCode: AuthenticatorCodeFunction = (data: {
|
|
119
|
+
secretBase32: string;
|
|
120
|
+
algorithm?: string | undefined;
|
|
121
|
+
digits?: number | undefined;
|
|
122
|
+
periodInSeconds?: number | undefined;
|
|
123
|
+
atUnixSeconds?: number | undefined;
|
|
124
|
+
}): string => {
|
|
125
|
+
const period: number = data.periodInSeconds || DEFAULT_PERIOD_IN_SECONDS;
|
|
126
|
+
|
|
127
|
+
const seconds: number =
|
|
128
|
+
data.atUnixSeconds === undefined
|
|
129
|
+
? Math.floor(Date.now() / 1000)
|
|
130
|
+
: data.atUnixSeconds;
|
|
131
|
+
|
|
132
|
+
return hotp({
|
|
133
|
+
key: base32Decode(data.secretBase32),
|
|
134
|
+
counter: Math.floor(seconds / period),
|
|
135
|
+
algorithm: data.algorithm || PHONE_APP_ALGORITHM,
|
|
136
|
+
digits: data.digits === undefined ? DEFAULT_DIGITS : data.digits,
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export type OtpauthUriParams = {
|
|
141
|
+
secret: string;
|
|
142
|
+
algorithm: string;
|
|
143
|
+
digits: number;
|
|
144
|
+
periodInSeconds: number;
|
|
145
|
+
issuer: string | null;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export type ParseOtpauthUriFunction = (uri: string) => OtpauthUriParams;
|
|
149
|
+
|
|
150
|
+
export const parseOtpauthUri: ParseOtpauthUriFunction = (
|
|
151
|
+
uri: string,
|
|
152
|
+
): OtpauthUriParams => {
|
|
153
|
+
const params: URLSearchParams = new URLSearchParams(
|
|
154
|
+
uri.slice(uri.indexOf("?") + 1),
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
secret: params.get("secret") || "",
|
|
159
|
+
algorithm: params.get("algorithm") || PHONE_APP_ALGORITHM,
|
|
160
|
+
digits: parseInt(params.get("digits") || String(DEFAULT_DIGITS), 10),
|
|
161
|
+
periodInSeconds: parseInt(
|
|
162
|
+
params.get("period") || String(DEFAULT_PERIOD_IN_SECONDS),
|
|
163
|
+
10,
|
|
164
|
+
),
|
|
165
|
+
issuer: params.get("issuer"),
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/*
|
|
170
|
+
* What an app that honours every parameter in the URI shows — 1Password,
|
|
171
|
+
* Bitwarden, Aegis, FreeOTP.
|
|
172
|
+
*/
|
|
173
|
+
export type CodeFromUriFunction = (
|
|
174
|
+
uri: string,
|
|
175
|
+
atUnixSeconds?: number,
|
|
176
|
+
) => string;
|
|
177
|
+
|
|
178
|
+
export const conformingAppCode: CodeFromUriFunction = (
|
|
179
|
+
uri: string,
|
|
180
|
+
atUnixSeconds?: number,
|
|
181
|
+
): string => {
|
|
182
|
+
const params: OtpauthUriParams = parseOtpauthUri(uri);
|
|
183
|
+
|
|
184
|
+
return authenticatorCode({
|
|
185
|
+
secretBase32: params.secret,
|
|
186
|
+
algorithm: params.algorithm,
|
|
187
|
+
digits: params.digits,
|
|
188
|
+
periodInSeconds: params.periodInSeconds,
|
|
189
|
+
atUnixSeconds: atUnixSeconds,
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
/*
|
|
194
|
+
* What Google Authenticator shows: the secret from the URI, but SHA1 whatever
|
|
195
|
+
* the URI says. This is the function that reproduces issue #3275 — hand it a
|
|
196
|
+
* SHA256 URI and the code it returns is the one the user typed in and the
|
|
197
|
+
* server rejected.
|
|
198
|
+
*/
|
|
199
|
+
export const googleAuthenticatorCode: CodeFromUriFunction = (
|
|
200
|
+
uri: string,
|
|
201
|
+
atUnixSeconds?: number,
|
|
202
|
+
): string => {
|
|
203
|
+
const params: OtpauthUriParams = parseOtpauthUri(uri);
|
|
204
|
+
|
|
205
|
+
return authenticatorCode({
|
|
206
|
+
secretBase32: params.secret,
|
|
207
|
+
algorithm: PHONE_APP_ALGORITHM,
|
|
208
|
+
digits: params.digits,
|
|
209
|
+
periodInSeconds: params.periodInSeconds,
|
|
210
|
+
atUnixSeconds: atUnixSeconds,
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
/*
|
|
215
|
+
* The otpauth:// URI a server hands to a QR code, built by hand so a test can
|
|
216
|
+
* produce the exact shape the OLD OneUptime code used to emit.
|
|
217
|
+
*/
|
|
218
|
+
export type BuildOtpauthUriFunction = (data: {
|
|
219
|
+
secret: string;
|
|
220
|
+
label: string;
|
|
221
|
+
issuer?: string | undefined;
|
|
222
|
+
algorithm?: string | undefined;
|
|
223
|
+
digits?: number | undefined;
|
|
224
|
+
periodInSeconds?: number | undefined;
|
|
225
|
+
}) => string;
|
|
226
|
+
|
|
227
|
+
export const buildOtpauthUri: BuildOtpauthUriFunction = (data: {
|
|
228
|
+
secret: string;
|
|
229
|
+
label: string;
|
|
230
|
+
issuer?: string | undefined;
|
|
231
|
+
algorithm?: string | undefined;
|
|
232
|
+
digits?: number | undefined;
|
|
233
|
+
periodInSeconds?: number | undefined;
|
|
234
|
+
}): string => {
|
|
235
|
+
const issuer: string = data.issuer || "OneUptime";
|
|
236
|
+
|
|
237
|
+
const query: string = [
|
|
238
|
+
`issuer=${encodeURIComponent(issuer)}`,
|
|
239
|
+
`secret=${data.secret}`,
|
|
240
|
+
`algorithm=${data.algorithm || PHONE_APP_ALGORITHM}`,
|
|
241
|
+
`digits=${data.digits === undefined ? DEFAULT_DIGITS : data.digits}`,
|
|
242
|
+
`period=${data.periodInSeconds || DEFAULT_PERIOD_IN_SECONDS}`,
|
|
243
|
+
].join("&");
|
|
244
|
+
|
|
245
|
+
return `otpauth://totp/${encodeURIComponent(issuer)}:${encodeURIComponent(
|
|
246
|
+
data.label,
|
|
247
|
+
)}?${query}`;
|
|
248
|
+
};
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
import { AggregateUtil } from "../../../../Server/Types/AnalyticsDatabase/AggregateBy";
|
|
2
|
+
import AggregationInterval from "../../../../Types/BaseDatabase/AggregationInterval";
|
|
3
|
+
import { describe, expect, it } from "@jest/globals";
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* AggregateUtil is the server's single source of truth for turning a query
|
|
7
|
+
* window into an aggregation bucket size and for compiling that bucket into a
|
|
8
|
+
* ClickHouse timestamp expression. The tests below exercise the real branches:
|
|
9
|
+
*
|
|
10
|
+
* - getAggregationInterval: window-derived tier ladder, its <=-inclusive
|
|
11
|
+
* boundaries, and the explicit-override precedence (including Total, which
|
|
12
|
+
* the window picker itself never returns, and invalid overrides that fall
|
|
13
|
+
* through to the window).
|
|
14
|
+
* - isTotalAggregation: the Total-vs-everything-else predicate.
|
|
15
|
+
* - buildBucketTimestampExpression: the sub-hour toStartOfInterval tiers vs
|
|
16
|
+
* the lowercased date_trunc default, plus raw expression interpolation.
|
|
17
|
+
* - buildBucketTimestampSelect: the Total min() shape vs the aliased bucket
|
|
18
|
+
* expression it delegates to.
|
|
19
|
+
*
|
|
20
|
+
* Everything is deterministic: getAggregationInterval only reads the numeric
|
|
21
|
+
* millisecond diff between the two dates, so windows are built from a fixed
|
|
22
|
+
* epoch anchor plus an exact millisecond span.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/*
|
|
26
|
+
* Fixed anchor for every window. getAggregationInterval depends only on
|
|
27
|
+
* endDate - startDate, so the absolute instant is irrelevant; pinning it makes
|
|
28
|
+
* the boundary arithmetic obvious.
|
|
29
|
+
*/
|
|
30
|
+
const ANCHOR_MS: number = 0;
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
* Tier upper bounds, copied from the implementation so a change in the ladder
|
|
34
|
+
* is caught here rather than silently re-tiering every chart. Each value is the
|
|
35
|
+
* largest diff (inclusive) that still resolves to the tier it labels.
|
|
36
|
+
*/
|
|
37
|
+
const THREE_HOURS_MS: number = 1000 * 60 * 60 * 3;
|
|
38
|
+
const TWELVE_HOURS_MS: number = 1000 * 60 * 60 * 12;
|
|
39
|
+
const TWENTY_FOUR_HOURS_MS: number = 1000 * 60 * 60 * 24;
|
|
40
|
+
const THREE_DAYS_MS: number = 1000 * 60 * 60 * 24 * 3;
|
|
41
|
+
const SEVEN_DAYS_MS: number = 1000 * 60 * 60 * 24 * 7;
|
|
42
|
+
const SIX_WEEKS_MS: number = 1000 * 60 * 60 * 24 * 7 * 6;
|
|
43
|
+
const SIX_MONTHS_MS: number = 1000 * 60 * 60 * 24 * 30 * 6;
|
|
44
|
+
const SIX_YEARS_MS: number = 1000 * 60 * 60 * 24 * 365 * 6;
|
|
45
|
+
|
|
46
|
+
function intervalForDiff(
|
|
47
|
+
diffMs: number,
|
|
48
|
+
aggregationInterval?: AggregationInterval,
|
|
49
|
+
): AggregationInterval {
|
|
50
|
+
const startDate: Date = new Date(ANCHOR_MS);
|
|
51
|
+
const endDate: Date = new Date(ANCHOR_MS + diffMs);
|
|
52
|
+
return AggregateUtil.getAggregationInterval({
|
|
53
|
+
startDate,
|
|
54
|
+
endDate,
|
|
55
|
+
aggregationInterval,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
describe("AggregateUtil.getAggregationInterval window-derived ladder", () => {
|
|
60
|
+
it("returns Minute for a zero-length window", () => {
|
|
61
|
+
const result: AggregationInterval = intervalForDiff(0);
|
|
62
|
+
expect(result).toBe(AggregationInterval.Minute);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("returns Minute for a negative (end-before-start) window", () => {
|
|
66
|
+
/*
|
|
67
|
+
* A malformed window makes the diff negative, which is still <= every
|
|
68
|
+
* upper bound, so it collapses to the finest tier rather than throwing.
|
|
69
|
+
*/
|
|
70
|
+
const result: AggregationInterval = intervalForDiff(-1000 * 60 * 60);
|
|
71
|
+
expect(result).toBe(AggregationInterval.Minute);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("never returns Total from the window derivation (huge window -> Year)", () => {
|
|
75
|
+
const result: AggregationInterval = intervalForDiff(SIX_YEARS_MS + 1);
|
|
76
|
+
expect(result).toBe(AggregationInterval.Year);
|
|
77
|
+
expect(result).not.toBe(AggregationInterval.Total);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
type LadderCase = {
|
|
81
|
+
label: string;
|
|
82
|
+
diffMs: number;
|
|
83
|
+
expected: AggregationInterval;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/*
|
|
87
|
+
* Each tier is probed at three points: comfortably inside the tier, exactly
|
|
88
|
+
* on its inclusive upper bound (must stay in the tier), and one millisecond
|
|
89
|
+
* past it (must roll to the next coarser tier). The last pair proves the
|
|
90
|
+
* ladder uses <= and not <.
|
|
91
|
+
*/
|
|
92
|
+
const ladderCases: Array<LadderCase> = [
|
|
93
|
+
{
|
|
94
|
+
label: "1 hour -> Minute",
|
|
95
|
+
diffMs: 1000 * 60 * 60,
|
|
96
|
+
expected: AggregationInterval.Minute,
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
label: "exactly 3 hours -> Minute (inclusive bound)",
|
|
100
|
+
diffMs: THREE_HOURS_MS,
|
|
101
|
+
expected: AggregationInterval.Minute,
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
label: "3 hours + 1ms -> FiveMinutes",
|
|
105
|
+
diffMs: THREE_HOURS_MS + 1,
|
|
106
|
+
expected: AggregationInterval.FiveMinutes,
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
label: "exactly 12 hours -> FiveMinutes (inclusive bound)",
|
|
110
|
+
diffMs: TWELVE_HOURS_MS,
|
|
111
|
+
expected: AggregationInterval.FiveMinutes,
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
label: "12 hours + 1ms -> FifteenMinutes",
|
|
115
|
+
diffMs: TWELVE_HOURS_MS + 1,
|
|
116
|
+
expected: AggregationInterval.FifteenMinutes,
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
label: "exactly 24 hours -> FifteenMinutes (inclusive bound)",
|
|
120
|
+
diffMs: TWENTY_FOUR_HOURS_MS,
|
|
121
|
+
expected: AggregationInterval.FifteenMinutes,
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
label: "24 hours + 1ms -> ThirtyMinutes",
|
|
125
|
+
diffMs: TWENTY_FOUR_HOURS_MS + 1,
|
|
126
|
+
expected: AggregationInterval.ThirtyMinutes,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
label: "exactly 3 days -> ThirtyMinutes (inclusive bound)",
|
|
130
|
+
diffMs: THREE_DAYS_MS,
|
|
131
|
+
expected: AggregationInterval.ThirtyMinutes,
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
label: "3 days + 1ms -> Hour",
|
|
135
|
+
diffMs: THREE_DAYS_MS + 1,
|
|
136
|
+
expected: AggregationInterval.Hour,
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
label: "exactly 7 days -> Hour (inclusive bound)",
|
|
140
|
+
diffMs: SEVEN_DAYS_MS,
|
|
141
|
+
expected: AggregationInterval.Hour,
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
label: "7 days + 1ms -> Day",
|
|
145
|
+
diffMs: SEVEN_DAYS_MS + 1,
|
|
146
|
+
expected: AggregationInterval.Day,
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
label: "exactly 6 weeks -> Day (inclusive bound)",
|
|
150
|
+
diffMs: SIX_WEEKS_MS,
|
|
151
|
+
expected: AggregationInterval.Day,
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
label: "6 weeks + 1ms -> Week",
|
|
155
|
+
diffMs: SIX_WEEKS_MS + 1,
|
|
156
|
+
expected: AggregationInterval.Week,
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
label: "exactly 6 months -> Week (inclusive bound)",
|
|
160
|
+
diffMs: SIX_MONTHS_MS,
|
|
161
|
+
expected: AggregationInterval.Week,
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
label: "6 months + 1ms -> Month",
|
|
165
|
+
diffMs: SIX_MONTHS_MS + 1,
|
|
166
|
+
expected: AggregationInterval.Month,
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
label: "exactly 6 years -> Month (inclusive bound)",
|
|
170
|
+
diffMs: SIX_YEARS_MS,
|
|
171
|
+
expected: AggregationInterval.Month,
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
label: "6 years + 1ms -> Year",
|
|
175
|
+
diffMs: SIX_YEARS_MS + 1,
|
|
176
|
+
expected: AggregationInterval.Year,
|
|
177
|
+
},
|
|
178
|
+
];
|
|
179
|
+
|
|
180
|
+
it.each(ladderCases)(
|
|
181
|
+
"resolves $label",
|
|
182
|
+
({ diffMs, expected }: LadderCase) => {
|
|
183
|
+
const result: AggregationInterval = intervalForDiff(diffMs);
|
|
184
|
+
expect(result).toBe(expected);
|
|
185
|
+
},
|
|
186
|
+
);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe("AggregateUtil.getAggregationInterval explicit override precedence", () => {
|
|
190
|
+
it("returns a valid override verbatim, ignoring the (finer) window tier", () => {
|
|
191
|
+
/*
|
|
192
|
+
* A 1-hour window would derive Minute, but the override pins Year, proving
|
|
193
|
+
* the override short-circuits the window derivation entirely.
|
|
194
|
+
*/
|
|
195
|
+
const result: AggregationInterval = intervalForDiff(
|
|
196
|
+
1000 * 60 * 60,
|
|
197
|
+
AggregationInterval.Year,
|
|
198
|
+
);
|
|
199
|
+
expect(result).toBe(AggregationInterval.Year);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it("returns a valid override verbatim, ignoring the (coarser) window tier", () => {
|
|
203
|
+
const result: AggregationInterval = intervalForDiff(
|
|
204
|
+
SIX_YEARS_MS + 1,
|
|
205
|
+
AggregationInterval.Minute,
|
|
206
|
+
);
|
|
207
|
+
expect(result).toBe(AggregationInterval.Minute);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it("honours a Total override even though the window picker never yields Total", () => {
|
|
211
|
+
const result: AggregationInterval = intervalForDiff(
|
|
212
|
+
1000 * 60 * 60,
|
|
213
|
+
AggregationInterval.Total,
|
|
214
|
+
);
|
|
215
|
+
expect(result).toBe(AggregationInterval.Total);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it("falls through to the window tier when the override is not a real enum value", () => {
|
|
219
|
+
/*
|
|
220
|
+
* Object.values(AggregationInterval).includes(...) rejects an unknown
|
|
221
|
+
* string, so the derivation runs and a 1-hour window resolves to Minute.
|
|
222
|
+
*/
|
|
223
|
+
const bogusOverride: AggregationInterval =
|
|
224
|
+
"NotARealInterval" as AggregationInterval;
|
|
225
|
+
const result: AggregationInterval = intervalForDiff(
|
|
226
|
+
1000 * 60 * 60,
|
|
227
|
+
bogusOverride,
|
|
228
|
+
);
|
|
229
|
+
expect(result).toBe(AggregationInterval.Minute);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it("preserves every enum value when passed as an explicit override", () => {
|
|
233
|
+
const allIntervals: Array<AggregationInterval> =
|
|
234
|
+
Object.values(AggregationInterval);
|
|
235
|
+
for (const interval of allIntervals) {
|
|
236
|
+
const result: AggregationInterval = intervalForDiff(
|
|
237
|
+
1000 * 60 * 60,
|
|
238
|
+
interval,
|
|
239
|
+
);
|
|
240
|
+
expect(result).toBe(interval);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
describe("AggregateUtil.isTotalAggregation", () => {
|
|
246
|
+
it("is true only for Total", () => {
|
|
247
|
+
expect(AggregateUtil.isTotalAggregation(AggregationInterval.Total)).toBe(
|
|
248
|
+
true,
|
|
249
|
+
);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it("is false for every non-Total interval", () => {
|
|
253
|
+
const nonTotalIntervals: Array<AggregationInterval> = Object.values(
|
|
254
|
+
AggregationInterval,
|
|
255
|
+
).filter((interval: AggregationInterval) => {
|
|
256
|
+
return interval !== AggregationInterval.Total;
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
for (const interval of nonTotalIntervals) {
|
|
260
|
+
expect(AggregateUtil.isTotalAggregation(interval)).toBe(false);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
describe("AggregateUtil.buildBucketTimestampExpression", () => {
|
|
266
|
+
const COL: string = "createdAt";
|
|
267
|
+
|
|
268
|
+
it("compiles FiveMinutes to a 5 MINUTE toStartOfInterval", () => {
|
|
269
|
+
const result: string = AggregateUtil.buildBucketTimestampExpression(
|
|
270
|
+
AggregationInterval.FiveMinutes,
|
|
271
|
+
COL,
|
|
272
|
+
);
|
|
273
|
+
expect(result).toBe(`toStartOfInterval(${COL}, INTERVAL 5 MINUTE)`);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it("compiles FifteenMinutes to a 15 MINUTE toStartOfInterval", () => {
|
|
277
|
+
const result: string = AggregateUtil.buildBucketTimestampExpression(
|
|
278
|
+
AggregationInterval.FifteenMinutes,
|
|
279
|
+
COL,
|
|
280
|
+
);
|
|
281
|
+
expect(result).toBe(`toStartOfInterval(${COL}, INTERVAL 15 MINUTE)`);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it("compiles ThirtyMinutes to a 30 MINUTE toStartOfInterval", () => {
|
|
285
|
+
const result: string = AggregateUtil.buildBucketTimestampExpression(
|
|
286
|
+
AggregationInterval.ThirtyMinutes,
|
|
287
|
+
COL,
|
|
288
|
+
);
|
|
289
|
+
expect(result).toBe(`toStartOfInterval(${COL}, INTERVAL 30 MINUTE)`);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
type DefaultCase = {
|
|
293
|
+
interval: AggregationInterval;
|
|
294
|
+
unit: string;
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
/*
|
|
298
|
+
* The default branch lowercases the enum value into both the date_trunc unit
|
|
299
|
+
* and the INTERVAL 1 <unit> guard. These calendar units happen to be valid
|
|
300
|
+
* ClickHouse units, which is exactly why they route through the default arm.
|
|
301
|
+
*/
|
|
302
|
+
const defaultCases: Array<DefaultCase> = [
|
|
303
|
+
{ interval: AggregationInterval.Minute, unit: "minute" },
|
|
304
|
+
{ interval: AggregationInterval.Hour, unit: "hour" },
|
|
305
|
+
{ interval: AggregationInterval.Day, unit: "day" },
|
|
306
|
+
{ interval: AggregationInterval.Week, unit: "week" },
|
|
307
|
+
{ interval: AggregationInterval.Month, unit: "month" },
|
|
308
|
+
{ interval: AggregationInterval.Year, unit: "year" },
|
|
309
|
+
];
|
|
310
|
+
|
|
311
|
+
it.each(defaultCases)(
|
|
312
|
+
"compiles $interval via the lowercased date_trunc default",
|
|
313
|
+
({ interval, unit }: DefaultCase) => {
|
|
314
|
+
const result: string = AggregateUtil.buildBucketTimestampExpression(
|
|
315
|
+
interval,
|
|
316
|
+
COL,
|
|
317
|
+
);
|
|
318
|
+
expect(result).toBe(
|
|
319
|
+
`date_trunc('${unit}', toStartOfInterval(${COL}, INTERVAL 1 ${unit}))`,
|
|
320
|
+
);
|
|
321
|
+
},
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
it("routes Total through the default branch as a lowercased unit in isolation", () => {
|
|
325
|
+
/*
|
|
326
|
+
* buildBucketTimestampSelect short-circuits Total before ever calling this
|
|
327
|
+
* function, but called directly Total falls into the default arm and is
|
|
328
|
+
* lowercased like any other value. This pins that isolated behavior so a
|
|
329
|
+
* future refactor cannot change it unnoticed.
|
|
330
|
+
*/
|
|
331
|
+
const result: string = AggregateUtil.buildBucketTimestampExpression(
|
|
332
|
+
AggregationInterval.Total,
|
|
333
|
+
COL,
|
|
334
|
+
);
|
|
335
|
+
expect(result).toBe(
|
|
336
|
+
`date_trunc('total', toStartOfInterval(${COL}, INTERVAL 1 total))`,
|
|
337
|
+
);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it("interpolates a compound builder expression verbatim in the sub-hour branch", () => {
|
|
341
|
+
const expression: string = "toDateTime(t.created_at)";
|
|
342
|
+
const result: string = AggregateUtil.buildBucketTimestampExpression(
|
|
343
|
+
AggregationInterval.FiveMinutes,
|
|
344
|
+
expression,
|
|
345
|
+
);
|
|
346
|
+
expect(result).toBe(`toStartOfInterval(${expression}, INTERVAL 5 MINUTE)`);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
it("interpolates a compound builder expression verbatim in the default branch", () => {
|
|
350
|
+
const expression: string = "toDateTime(t.created_at)";
|
|
351
|
+
const result: string = AggregateUtil.buildBucketTimestampExpression(
|
|
352
|
+
AggregationInterval.Hour,
|
|
353
|
+
expression,
|
|
354
|
+
);
|
|
355
|
+
expect(result).toBe(
|
|
356
|
+
`date_trunc('hour', toStartOfInterval(${expression}, INTERVAL 1 hour))`,
|
|
357
|
+
);
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
describe("AggregateUtil.buildBucketTimestampSelect", () => {
|
|
362
|
+
const COL: string = "createdAt";
|
|
363
|
+
|
|
364
|
+
it("emits a self-aliased min() for Total (whole-window bucket)", () => {
|
|
365
|
+
const result: string = AggregateUtil.buildBucketTimestampSelect(
|
|
366
|
+
AggregationInterval.Total,
|
|
367
|
+
COL,
|
|
368
|
+
);
|
|
369
|
+
expect(result).toBe(`min(${COL}) as ${COL}`);
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
it("aliases the bucket expression for a sub-hour interval", () => {
|
|
373
|
+
const result: string = AggregateUtil.buildBucketTimestampSelect(
|
|
374
|
+
AggregationInterval.FiveMinutes,
|
|
375
|
+
COL,
|
|
376
|
+
);
|
|
377
|
+
expect(result).toBe(
|
|
378
|
+
`toStartOfInterval(${COL}, INTERVAL 5 MINUTE) as ${COL}`,
|
|
379
|
+
);
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
it("aliases the date_trunc expression for a calendar interval", () => {
|
|
383
|
+
const result: string = AggregateUtil.buildBucketTimestampSelect(
|
|
384
|
+
AggregationInterval.Minute,
|
|
385
|
+
COL,
|
|
386
|
+
);
|
|
387
|
+
expect(result).toBe(
|
|
388
|
+
`date_trunc('minute', toStartOfInterval(${COL}, INTERVAL 1 minute)) as ${COL}`,
|
|
389
|
+
);
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
it("delegates non-Total intervals to buildBucketTimestampExpression plus an alias", () => {
|
|
393
|
+
/*
|
|
394
|
+
* The select fragment for any non-Total interval must be exactly the
|
|
395
|
+
* bucket expression suffixed with `as <col>`; anything else would mean the
|
|
396
|
+
* two helpers had drifted apart.
|
|
397
|
+
*/
|
|
398
|
+
const nonTotalIntervals: Array<AggregationInterval> = Object.values(
|
|
399
|
+
AggregationInterval,
|
|
400
|
+
).filter((interval: AggregationInterval) => {
|
|
401
|
+
return interval !== AggregationInterval.Total;
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
for (const interval of nonTotalIntervals) {
|
|
405
|
+
const expression: string = AggregateUtil.buildBucketTimestampExpression(
|
|
406
|
+
interval,
|
|
407
|
+
COL,
|
|
408
|
+
);
|
|
409
|
+
const select: string = AggregateUtil.buildBucketTimestampSelect(
|
|
410
|
+
interval,
|
|
411
|
+
COL,
|
|
412
|
+
);
|
|
413
|
+
expect(select).toBe(`${expression} as ${COL}`);
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
});
|