@oneuptime/common 12.0.13 → 12.0.14
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/OnCallDutyPolicySchedule.ts +14 -0
- 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/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/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/Index.ts +6 -0
- package/Server/Middleware/VerificationCodeRateLimit.ts +586 -0
- package/Server/Services/AnalyticsDatabaseService.ts +169 -0
- package/Server/Services/DatabaseService.ts +101 -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/Monitor/Criteria/IncomingRequestCriteria.ts +13 -16
- package/Server/Utils/Monitor/MonitorAlert.ts +24 -21
- package/Server/Utils/Monitor/MonitorIncident.ts +21 -18
- 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/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/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 +315 -0
- package/Tests/Server/Middleware/VerificationCodeRateLimit.test.ts +775 -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/LogAggregationScanMemory.test.ts +421 -0
- package/Tests/Server/Services/LogAggregationService.test.ts +2 -2
- 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/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/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/Express.test.ts +371 -0
- 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/IncomingEmailBodyCriteria.test.ts +243 -0
- package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestBodyCriteria.test.ts +278 -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/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/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/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/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/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/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/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/Rum/UrlScrubberSegments.test.ts +362 -0
- package/Types/Email/EmailTemplateType.ts +1 -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/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/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/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/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +14 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.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/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/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/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.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/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/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/Monitor/Criteria/IncomingRequestCriteria.js +13 -12
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.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/MonitorIncident.js +17 -14
- package/build/dist/Server/Utils/Monitor/MonitorIncident.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/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/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/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/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/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/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,134 @@
|
|
|
1
|
+
import { EncryptionSecret } from "../EnvironmentConfig";
|
|
2
|
+
import ObjectID from "../../Types/ObjectID";
|
|
3
|
+
import crypto from "crypto";
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* The cryptography behind notification-channel ownership checks: the codes
|
|
7
|
+
* mailed/texted/read out to a user to prove they hold the address or number
|
|
8
|
+
* they just added.
|
|
9
|
+
*
|
|
10
|
+
* This is deliberately server-only. Common/Types/Text is bundled into the
|
|
11
|
+
* dashboard and therefore has to tolerate a runtime with no CSPRNG; a code
|
|
12
|
+
* minted here has no such excuse, so nothing in this file falls back to
|
|
13
|
+
* Math.random. If the platform cannot produce secure randomness, generation
|
|
14
|
+
* throws and the channel simply cannot be added.
|
|
15
|
+
*
|
|
16
|
+
* WHY THE STORED VALUE IS A DIGEST
|
|
17
|
+
*
|
|
18
|
+
* A six-digit code is only a secret for as long as it is in flight. Storing
|
|
19
|
+
* the plaintext puts a live account-takeover token in a database column, a
|
|
20
|
+
* backup, a replica and every log line that ever dumps the row - and the
|
|
21
|
+
* column sits on a table (UserEmail and friends) whose entire access-control
|
|
22
|
+
* design exists because reading somebody else's row IS the attack. Keeping a
|
|
23
|
+
* keyed digest means a database dump alone yields nothing: the attacker also
|
|
24
|
+
* needs the deployment's EncryptionSecret, and even holding both, recovering
|
|
25
|
+
* the code means re-running the HMAC over the code space per row, because...
|
|
26
|
+
*
|
|
27
|
+
* WHY THE ROW ID IS IN THE MESSAGE
|
|
28
|
+
*
|
|
29
|
+
* ...the digest is domain-separated by the row it belongs to. Without that,
|
|
30
|
+
* one HMAC table of all 10^6 codes inverts every row in the table at once,
|
|
31
|
+
* and two rows that happened to draw the same code would be visibly equal.
|
|
32
|
+
* With it, the same code on two rows produces two unrelated digests.
|
|
33
|
+
*
|
|
34
|
+
* A fast hash is right here, unlike a password: the input is a value the
|
|
35
|
+
* server minted at random, so there is nothing to guess offline that the
|
|
36
|
+
* attempt counter is not already bounding online. The scheme version prefix
|
|
37
|
+
* is there so a future change of construction can be told apart from this one
|
|
38
|
+
* rather than silently invalidating or, worse, colliding with it.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
const HASH_SCHEME_VERSION: string = "v1";
|
|
42
|
+
|
|
43
|
+
/*
|
|
44
|
+
* Six digits, matching what the notification templates and the dashboard's
|
|
45
|
+
* code input already expect. The code space is small on purpose - it has to
|
|
46
|
+
* be readable off a phone screen - which is exactly why every control around
|
|
47
|
+
* it (expiry, attempt counter, lockout, rate limit) is load-bearing rather
|
|
48
|
+
* than defence in depth.
|
|
49
|
+
*/
|
|
50
|
+
export const VERIFICATION_CODE_LENGTH: number = 6;
|
|
51
|
+
|
|
52
|
+
export default class VerificationCode {
|
|
53
|
+
/*
|
|
54
|
+
* A fresh code, drawn uniformly from the whole code space.
|
|
55
|
+
*
|
|
56
|
+
* crypto.randomInt does the rejection sampling itself, so there is no modulo
|
|
57
|
+
* bias here and no need to hand-roll one. Leading zeros are kept: "000123"
|
|
58
|
+
* is a perfectly good code, and dropping them would quietly shrink the
|
|
59
|
+
* space by 10%.
|
|
60
|
+
*/
|
|
61
|
+
public static generate(length: number = VERIFICATION_CODE_LENGTH): string {
|
|
62
|
+
let code: string = "";
|
|
63
|
+
|
|
64
|
+
for (let i: number = 0; i < length; i++) {
|
|
65
|
+
code += crypto.randomInt(0, 10).toString();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return code;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/*
|
|
72
|
+
* The digest to store for `code` on the row identified by `channelId`.
|
|
73
|
+
*
|
|
74
|
+
* Both inputs are length-prefixed into the message rather than merely
|
|
75
|
+
* concatenated, so no pair of (id, code) values can be rearranged into the
|
|
76
|
+
* same byte string as another pair.
|
|
77
|
+
*/
|
|
78
|
+
public static hashCode(data: { code: string; channelId: ObjectID }): string {
|
|
79
|
+
const message: string = [
|
|
80
|
+
HASH_SCHEME_VERSION,
|
|
81
|
+
data.channelId.toString(),
|
|
82
|
+
data.code,
|
|
83
|
+
]
|
|
84
|
+
.map((part: string) => {
|
|
85
|
+
return `${part.length}:${part}`;
|
|
86
|
+
})
|
|
87
|
+
.join("");
|
|
88
|
+
|
|
89
|
+
return crypto
|
|
90
|
+
.createHmac("sha256", EncryptionSecret.toString())
|
|
91
|
+
.update(message)
|
|
92
|
+
.digest("hex");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/*
|
|
96
|
+
* Compare two digests without leaking, through timing, how many leading
|
|
97
|
+
* bytes matched.
|
|
98
|
+
*
|
|
99
|
+
* `===` on strings short-circuits at the first differing character, and the
|
|
100
|
+
* attacker here controls the plaintext that produces one side of the
|
|
101
|
+
* comparison. That is a much weaker oracle than it is for a password check -
|
|
102
|
+
* they would be recovering a digest of a value that expires in minutes - but
|
|
103
|
+
* a constant-time compare costs nothing and removes the question.
|
|
104
|
+
*
|
|
105
|
+
* Lengths are compared first. Both digests are always 64 hex characters, so
|
|
106
|
+
* an early return only happens on malformed input, where the length is not
|
|
107
|
+
* the secret.
|
|
108
|
+
*/
|
|
109
|
+
public static isHashEqual(a: string, b: string): boolean {
|
|
110
|
+
if (!a || !b || a.length !== b.length) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return crypto.timingSafeEqual(
|
|
115
|
+
Buffer.from(a, "utf8"),
|
|
116
|
+
Buffer.from(b, "utf8"),
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/*
|
|
121
|
+
* A digest that no code can ever produce, for burning the outstanding
|
|
122
|
+
* challenge.
|
|
123
|
+
*
|
|
124
|
+
* Used when a row is locked out or successfully verified. The column is NOT
|
|
125
|
+
* NULL, so "there is no live code" cannot be expressed as null; it is
|
|
126
|
+
* expressed as a digest drawn at random from a 256-bit space, which the
|
|
127
|
+
* 10^6 possible codes cannot hit. Rotating rather than leaving the old
|
|
128
|
+
* digest in place matters: it means a lockout is not merely a pause an
|
|
129
|
+
* attacker can wait out with the same target still valid behind it.
|
|
130
|
+
*/
|
|
131
|
+
public static generateUnusableHash(): string {
|
|
132
|
+
return crypto.randomBytes(32).toString("hex");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -15,6 +15,11 @@ import {
|
|
|
15
15
|
waitFor,
|
|
16
16
|
within,
|
|
17
17
|
} from "@testing-library/react";
|
|
18
|
+
import {
|
|
19
|
+
MemoryRouter,
|
|
20
|
+
Route as RouterRoute,
|
|
21
|
+
Routes as RouterRoutes,
|
|
22
|
+
} from "react-router-dom";
|
|
18
23
|
import React, { FunctionComponent, ReactElement } from "react";
|
|
19
24
|
import getJestMockFunction, { MockFunction } from "../../MockType";
|
|
20
25
|
|
|
@@ -365,7 +370,14 @@ jest.mock("../../../UI/Components/ModelTable/ModelTable", () => {
|
|
|
365
370
|
});
|
|
366
371
|
|
|
367
372
|
import PageComponentProps from "../../../../App/FeatureSet/Dashboard/src/Pages/PageComponentProps";
|
|
368
|
-
import
|
|
373
|
+
import UserViewOnCallLayout from "../../../../App/FeatureSet/Dashboard/src/Pages/Users/View/OnCall/Layout";
|
|
374
|
+
import UserViewOnCallReadiness from "../../../../App/FeatureSet/Dashboard/src/Pages/Users/View/OnCall/Readiness";
|
|
375
|
+
import UserViewOnCallRules, {
|
|
376
|
+
ALERT_EPISODE_RULES_PROPS,
|
|
377
|
+
ALERT_RULES_PROPS,
|
|
378
|
+
INCIDENT_EPISODE_RULES_PROPS,
|
|
379
|
+
INCIDENT_RULES_PROPS,
|
|
380
|
+
} from "../../../../App/FeatureSet/Dashboard/src/Pages/Users/View/OnCall/Rules";
|
|
369
381
|
import AlertOnCallRules from "../../../../App/FeatureSet/Dashboard/src/Pages/UserSettings/AlertOnCallRules";
|
|
370
382
|
import EpisodeOnCallRules from "../../../../App/FeatureSet/Dashboard/src/Pages/UserSettings/EpisodeOnCallRules";
|
|
371
383
|
import IncidentEpisodeOnCallRules from "../../../../App/FeatureSet/Dashboard/src/Pages/UserSettings/IncidentEpisodeOnCallRules";
|
|
@@ -758,17 +770,81 @@ type RenderAdminPageFunction = (
|
|
|
758
770
|
* offset yields an ObjectID of the literal string "notification-rules", which
|
|
759
771
|
* every assertion about whose rules these are would then fail on.
|
|
760
772
|
*/
|
|
773
|
+
|
|
774
|
+
/*
|
|
775
|
+
* Every page the On-Call section holds that has a rule table or a readiness
|
|
776
|
+
* surface on it, mounted at once under ONE section layout.
|
|
777
|
+
*
|
|
778
|
+
* The section used to be a single route and is six now, and these assertions
|
|
779
|
+
* are about the shared machinery underneath rather than about which URL a card
|
|
780
|
+
* ends up on: the severity axes, the masked dropdown, the on-behalf-of context,
|
|
781
|
+
* the coverage grid. Mounting the readiness page beside all four rule pages
|
|
782
|
+
* keeps every one of them pointed at a single load of identity and readiness -
|
|
783
|
+
* which is exactly what the layout does in the product - so what is asserted
|
|
784
|
+
* here is what the section actually composes to.
|
|
785
|
+
*
|
|
786
|
+
* That each ROUTE renders only its own page is a different claim, and it is
|
|
787
|
+
* asserted where it belongs: AdminUserOnCallPages.test.tsx walks the real route
|
|
788
|
+
* table.
|
|
789
|
+
*/
|
|
790
|
+
const AdminOnCallSection: FunctionComponent = (): ReactElement => {
|
|
791
|
+
return (
|
|
792
|
+
<>
|
|
793
|
+
<UserViewOnCallReadiness {...pageProps} />
|
|
794
|
+
<UserViewOnCallRules {...INCIDENT_RULES_PROPS} />
|
|
795
|
+
<UserViewOnCallRules {...INCIDENT_EPISODE_RULES_PROPS} />
|
|
796
|
+
<UserViewOnCallRules {...ALERT_RULES_PROPS} />
|
|
797
|
+
<UserViewOnCallRules {...ALERT_EPISODE_RULES_PROPS} />
|
|
798
|
+
</>
|
|
799
|
+
);
|
|
800
|
+
};
|
|
801
|
+
|
|
802
|
+
type RenderSectionFunction = (
|
|
803
|
+
targetUserId: string,
|
|
804
|
+
children: ReactElement,
|
|
805
|
+
) => HTMLElement;
|
|
806
|
+
|
|
807
|
+
/*
|
|
808
|
+
* The real nesting, through a real router.
|
|
809
|
+
*
|
|
810
|
+
* The section layout reads the target user from `useParams`, not by counting
|
|
811
|
+
* segments off window.location, so a stubbed location would tell it nothing.
|
|
812
|
+
* Driving it through MemoryRouter with the same `:id` parent the app uses is
|
|
813
|
+
* what makes "whose configuration is this?" answered here the same way it is
|
|
814
|
+
* answered in the product - and reading the wrong param would leave every
|
|
815
|
+
* assertion about the target user failing on an id of "on-call-readiness".
|
|
816
|
+
*/
|
|
817
|
+
const renderSection: RenderSectionFunction = (
|
|
818
|
+
targetUserId: string,
|
|
819
|
+
children: ReactElement,
|
|
820
|
+
): HTMLElement => {
|
|
821
|
+
const { container } = render(
|
|
822
|
+
<MemoryRouter
|
|
823
|
+
initialEntries={[
|
|
824
|
+
`/dashboard/${PROJECT_ID_STRING}/users/${targetUserId}/on-call-readiness`,
|
|
825
|
+
]}
|
|
826
|
+
>
|
|
827
|
+
<RouterRoutes>
|
|
828
|
+
<RouterRoute path="/dashboard/:projectId/users/:id">
|
|
829
|
+
<RouterRoute element={<UserViewOnCallLayout />}>
|
|
830
|
+
<RouterRoute path="on-call-readiness" element={children} />
|
|
831
|
+
</RouterRoute>
|
|
832
|
+
</RouterRoute>
|
|
833
|
+
</RouterRoutes>
|
|
834
|
+
</MemoryRouter>,
|
|
835
|
+
);
|
|
836
|
+
|
|
837
|
+
return container;
|
|
838
|
+
};
|
|
839
|
+
|
|
761
840
|
const renderAdminPage: RenderAdminPageFunction = async (
|
|
762
841
|
targetUserId: string = TARGET_USER_ID_STRING,
|
|
763
842
|
): Promise<HTMLElement> => {
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
`/dashboard/${PROJECT_ID_STRING}/users/${targetUserId}/notification-rules`,
|
|
843
|
+
const container: HTMLElement = renderSection(
|
|
844
|
+
targetUserId,
|
|
845
|
+
<AdminOnCallSection />,
|
|
768
846
|
);
|
|
769
847
|
|
|
770
|
-
const { container } = render(<UserViewNotificationRules {...pageProps} />);
|
|
771
|
-
|
|
772
848
|
await waitForSettledPage(ADMIN_TABLE_COUNT);
|
|
773
849
|
|
|
774
850
|
return container;
|
|
@@ -1852,7 +1928,7 @@ describe("the on-behalf-of banner", () => {
|
|
|
1852
1928
|
const container: HTMLElement = await renderAdminPage();
|
|
1853
1929
|
|
|
1854
1930
|
expect(container.textContent).toContain(
|
|
1855
|
-
"
|
|
1931
|
+
"This is your own on-call configuration.",
|
|
1856
1932
|
);
|
|
1857
1933
|
expect(container.textContent).not.toContain("on behalf of");
|
|
1858
1934
|
|
|
@@ -1869,13 +1945,7 @@ describe("the on-behalf-of banner", () => {
|
|
|
1869
1945
|
test("a member with no permission is refused, and the page reads nothing about the user", async () => {
|
|
1870
1946
|
jest.spyOn(PermissionUtil, "getAllPermissions").mockReturnValue([]);
|
|
1871
1947
|
|
|
1872
|
-
|
|
1873
|
-
{},
|
|
1874
|
-
"",
|
|
1875
|
-
`/dashboard/${PROJECT_ID_STRING}/users/${TARGET_USER_ID_STRING}/notification-rules`,
|
|
1876
|
-
);
|
|
1877
|
-
|
|
1878
|
-
render(<UserViewNotificationRules {...pageProps} />);
|
|
1948
|
+
renderSection(TARGET_USER_ID_STRING, <AdminOnCallSection />);
|
|
1879
1949
|
|
|
1880
1950
|
expect(
|
|
1881
1951
|
await screen.findByText(/do not have permission to view this user/),
|
|
@@ -1913,111 +1983,111 @@ describe("the on-behalf-of banner", () => {
|
|
|
1913
1983
|
});
|
|
1914
1984
|
|
|
1915
1985
|
/*
|
|
1916
|
-
* And it must not invent
|
|
1917
|
-
*
|
|
1918
|
-
*
|
|
1919
|
-
*
|
|
1986
|
+
* And it must not invent a diagnosis out of a failed request. An unreported
|
|
1987
|
+
* coverage matrix and a matrix full of holes look identical once drawn, and
|
|
1988
|
+
* only one of them is a reason to go and add rules - so a failed readiness
|
|
1989
|
+
* read says so rather than rendering an empty grid.
|
|
1920
1990
|
*/
|
|
1921
|
-
expect(container.textContent).toContain(
|
|
1922
|
-
"Notification methods could not be loaded",
|
|
1923
|
-
);
|
|
1991
|
+
expect(container.textContent).toContain("Coverage could not be loaded");
|
|
1924
1992
|
expect(container.textContent).not.toContain(
|
|
1925
1993
|
"has no notification methods at all",
|
|
1926
1994
|
);
|
|
1927
1995
|
});
|
|
1928
1996
|
});
|
|
1929
1997
|
|
|
1930
|
-
describe("
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1998
|
+
describe("methods are a page of their own now, not a card on this one", () => {
|
|
1999
|
+
/*
|
|
2000
|
+
* WHAT THIS BLOCK USED TO SAY, AND WHY IT NO LONGER DOES.
|
|
2001
|
+
*
|
|
2002
|
+
* It asserted that an administrator was offered NO control for adding a
|
|
2003
|
+
* notification method to somebody else's account: a masked, read-only list
|
|
2004
|
+
* and a prefilled "please add one yourself" email. That was correct for what
|
|
2005
|
+
* the server could do at the time - the seven method models are scoped to
|
|
2006
|
+
* their owner and the attempt to widen them leaked every raw column behind
|
|
2007
|
+
* them - but it left the commonest broken responder, a new joiner with no
|
|
2008
|
+
* method at all, fixable by nobody but themselves.
|
|
2009
|
+
*
|
|
2010
|
+
* An administrator can now add one, through a narrow server-side capability
|
|
2011
|
+
* that never hands them the row, and CANNOT MAKE IT LIVE: the method is
|
|
2012
|
+
* written unverified, the code goes to the device, and every verify endpoint
|
|
2013
|
+
* refuses a caller who is not the row's owner. That capability and its
|
|
2014
|
+
* limits are tested in AdminUserNotificationMethodsPage.test.tsx and in the
|
|
2015
|
+
* server suites; what matters HERE is that the rule surfaces did not quietly
|
|
2016
|
+
* inherit it.
|
|
2017
|
+
*/
|
|
2018
|
+
test("the readiness page no longer carries the method list", async () => {
|
|
2019
|
+
const container: HTMLElement = await renderAdminPage();
|
|
1935
2020
|
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
2021
|
+
/*
|
|
2022
|
+
* The masked identifiers are what the RULE dropdown is built from, so they
|
|
2023
|
+
* are still in the section's props - but the standing list of a colleague's
|
|
2024
|
+
* devices belongs on the page that manages them, not under a diagnosis.
|
|
2025
|
+
*/
|
|
2026
|
+
expect(
|
|
2027
|
+
screen.queryByTestId("admin-notification-method-list"),
|
|
2028
|
+
).not.toBeInTheDocument();
|
|
1941
2029
|
|
|
1942
|
-
|
|
1943
|
-
expect(methods.textContent).toContain(
|
|
2030
|
+
expect(container.textContent).not.toContain(
|
|
1944
2031
|
"Identifiers are masked and cannot be edited from here",
|
|
1945
2032
|
);
|
|
1946
2033
|
});
|
|
1947
2034
|
|
|
1948
|
-
test("
|
|
1949
|
-
await renderAdminPage();
|
|
1950
|
-
|
|
1951
|
-
const methods: HTMLElement = cardNamed("Notification methods");
|
|
2035
|
+
test("points at the page that does manage them", async () => {
|
|
2036
|
+
const container: HTMLElement = await renderAdminPage();
|
|
1952
2037
|
|
|
1953
2038
|
/*
|
|
1954
|
-
*
|
|
1955
|
-
*
|
|
1956
|
-
*
|
|
1957
|
-
* and it would not solve the case it appears to solve: a responder with no
|
|
1958
|
-
* methods needs a device THEY hold and can verify.
|
|
2039
|
+
* A diagnosis with no route to the repair is how the single page this
|
|
2040
|
+
* replaced came to be scrolled past. The readiness page names every page
|
|
2041
|
+
* that can change the answer it just gave.
|
|
1959
2042
|
*/
|
|
1960
|
-
expect(
|
|
1961
|
-
|
|
1962
|
-
).
|
|
2043
|
+
expect(container.textContent).toContain("Notification methods");
|
|
2044
|
+
expect(container.textContent).toContain("Incident on-call rules");
|
|
2045
|
+
expect(container.textContent).toContain("Alert episode on-call rules");
|
|
2046
|
+
});
|
|
2047
|
+
|
|
2048
|
+
test("the rule tables stay editable for a user with no method at all", async () => {
|
|
2049
|
+
respondWithReadiness(NO_METHODS_READINESS);
|
|
2050
|
+
|
|
2051
|
+
await renderAdminPage();
|
|
1963
2052
|
|
|
1964
2053
|
/*
|
|
1965
|
-
*
|
|
1966
|
-
*
|
|
1967
|
-
*
|
|
2054
|
+
* A responder with no verified method still needs rules waiting for the
|
|
2055
|
+
* moment one is added - by them, or now by an admin on the methods page.
|
|
2056
|
+
* Folding "cannot be reached" into "cannot be configured" would make the
|
|
2057
|
+
* broken case the one that is hardest to repair.
|
|
1968
2058
|
*/
|
|
1969
|
-
|
|
1970
|
-
expect(
|
|
2059
|
+
capturedTables.forEach((table: CapturedTableProps) => {
|
|
2060
|
+
expect(table.isCreateable).toBe(true);
|
|
2061
|
+
expect(table.isDeleteable).toBe(true);
|
|
2062
|
+
expect(table.modelType).toBe(UserNotificationRule);
|
|
1971
2063
|
});
|
|
1972
2064
|
});
|
|
1973
2065
|
|
|
1974
|
-
test("the
|
|
2066
|
+
test("still asks the reader to chase the one thing an admin cannot do", async () => {
|
|
1975
2067
|
respondWithReadiness(NO_METHODS_READINESS);
|
|
1976
2068
|
|
|
1977
2069
|
await renderAdminPage();
|
|
1978
2070
|
|
|
1979
|
-
const
|
|
1980
|
-
|
|
1981
|
-
expect(methods.textContent).toContain("has no notification methods at all");
|
|
1982
|
-
expect(methods.textContent).toContain(
|
|
1983
|
-
`Only ${TARGET_USER_FIRST_NAME} can add one`,
|
|
1984
|
-
);
|
|
1985
|
-
|
|
1986
|
-
// A nudge, with the link already in it - and still not a single control.
|
|
1987
|
-
expect(
|
|
1988
|
-
methods.querySelectorAll("button, input, select, textarea, form"),
|
|
1989
|
-
).toHaveLength(0);
|
|
1990
|
-
|
|
1991
|
-
const href: string = mailtoHrefIn(methods);
|
|
2071
|
+
const href: string = mailtoHrefIn(cardNamed("On-call readiness"));
|
|
1992
2072
|
|
|
1993
2073
|
expect(href).toContain(TARGET_LOGIN_EMAIL);
|
|
1994
2074
|
expect(href).toContain("notification-methods");
|
|
1995
|
-
expect(href).toContain(
|
|
1996
|
-
"only you can add the device or address they send to",
|
|
1997
|
-
);
|
|
1998
2075
|
|
|
1999
2076
|
/*
|
|
2000
|
-
* The draft
|
|
2001
|
-
*
|
|
2077
|
+
* The draft's ask moved with the capability. An admin can add a method now,
|
|
2078
|
+
* so asking the responder to add one would be asking them to do work that
|
|
2079
|
+
* has already been offered to the admin; what is still theirs alone is
|
|
2080
|
+
* VERIFYING it, because the code goes to their device.
|
|
2002
2081
|
*/
|
|
2003
|
-
expect(href).toContain(
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
test("the rule tables stay editable while the methods stay locked", async () => {
|
|
2007
|
-
respondWithReadiness(NO_METHODS_READINESS);
|
|
2008
|
-
|
|
2009
|
-
await renderAdminPage();
|
|
2082
|
+
expect(href).toContain(
|
|
2083
|
+
"only you can verify the device or address it sends to",
|
|
2084
|
+
);
|
|
2010
2085
|
|
|
2011
2086
|
/*
|
|
2012
|
-
*
|
|
2013
|
-
*
|
|
2014
|
-
* rules waiting for the moment they add one.
|
|
2087
|
+
* And it has to say what is actually wrong, or it is a form letter. With no
|
|
2088
|
+
* method at all the consequence is not a late page, it is no page.
|
|
2015
2089
|
*/
|
|
2016
|
-
|
|
2017
|
-
expect(table.isCreateable).toBe(true);
|
|
2018
|
-
expect(table.isDeleteable).toBe(true);
|
|
2019
|
-
expect(table.modelType).toBe(UserNotificationRule);
|
|
2020
|
-
});
|
|
2090
|
+
expect(href).toContain("dropped");
|
|
2021
2091
|
});
|
|
2022
2092
|
});
|
|
2023
2093
|
|
|
@@ -2377,24 +2447,33 @@ describe("no unmasked identifier reaches the DOM", () => {
|
|
|
2377
2447
|
expect(container.textContent || "").not.toMatch(UNMASKED_PHONE_PATTERN);
|
|
2378
2448
|
};
|
|
2379
2449
|
|
|
2380
|
-
test("the admin
|
|
2450
|
+
test("the admin rule surfaces render no identifier at all", async () => {
|
|
2381
2451
|
const container: HTMLElement = await renderAdminPage();
|
|
2382
2452
|
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2453
|
+
/*
|
|
2454
|
+
* Not vacuous: readiness DID hand this section three methods, and their
|
|
2455
|
+
* masked labels are on the rule dropdown's props a few tests below. What
|
|
2456
|
+
* the rule surfaces render is none of them - the standing list of somebody
|
|
2457
|
+
* else's devices belongs on the page that manages them, and a page that
|
|
2458
|
+
* prints a colleague's channels under a diagnosis was one of the reasons
|
|
2459
|
+
* the old combined page was too long to read.
|
|
2460
|
+
*/
|
|
2461
|
+
expect(capturedTables.length).toBeGreaterThan(0);
|
|
2462
|
+
expect(methodOptionsFor(capturedTables[0]!).length).toBeGreaterThan(0);
|
|
2463
|
+
|
|
2464
|
+
expect(container.textContent).not.toContain(MASKED_EMAIL);
|
|
2465
|
+
expect(container.textContent).not.toContain(MASKED_PHONE);
|
|
2386
2466
|
|
|
2387
2467
|
assertNoRawIdentifiers(container);
|
|
2388
2468
|
});
|
|
2389
2469
|
|
|
2390
|
-
test("an unreachable user's
|
|
2470
|
+
test("an unreachable user's readiness page leaks nothing either", async () => {
|
|
2391
2471
|
respondWithReadiness(NO_METHODS_READINESS);
|
|
2392
2472
|
|
|
2393
2473
|
const container: HTMLElement = await renderAdminPage();
|
|
2394
2474
|
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
);
|
|
2475
|
+
// Not vacuous: the page really is reporting the unreachable state.
|
|
2476
|
+
expect(container.textContent).toContain("Unreachable");
|
|
2398
2477
|
|
|
2399
2478
|
assertNoRawIdentifiers(container);
|
|
2400
2479
|
});
|
|
@@ -2443,7 +2522,7 @@ describe("no unmasked identifier reaches the DOM", () => {
|
|
|
2443
2522
|
|
|
2444
2523
|
await renderAdminPage();
|
|
2445
2524
|
|
|
2446
|
-
const href: string = mailtoHrefIn(cardNamed("
|
|
2525
|
+
const href: string = mailtoHrefIn(cardNamed("On-call readiness"));
|
|
2447
2526
|
|
|
2448
2527
|
expect(href).toContain(TARGET_LOGIN_EMAIL);
|
|
2449
2528
|
|