@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
|
@@ -1542,6 +1542,159 @@ export default class AnalyticsDatabaseService<
|
|
|
1542
1542
|
return { ...sort, _id: direction } as Sort<TBaseModel>;
|
|
1543
1543
|
}
|
|
1544
1544
|
|
|
1545
|
+
/**
|
|
1546
|
+
* Bounds the rows an `ORDER BY ... , _id` find has to sort, without
|
|
1547
|
+
* changing which rows it returns.
|
|
1548
|
+
*
|
|
1549
|
+
* ClickHouse can read in sorting-key order — and stop early — only when the
|
|
1550
|
+
* ORDER BY lines up with the table's physical key. The `_id` tiebreaker
|
|
1551
|
+
* appended by `toPaginationStableSort` is deliberately NOT a sorting-key
|
|
1552
|
+
* column, so it denies that plan: the engine reads every row matching the
|
|
1553
|
+
* WHERE, sorts the lot in memory, then discards all but one page. On the
|
|
1554
|
+
* Logs viewer that turned a 100-row page into a full-window scan and tripped
|
|
1555
|
+
* the 3 GiB `max_memory_usage` ceiling (Code 241, surfacing as
|
|
1556
|
+
* "Server Error").
|
|
1557
|
+
*
|
|
1558
|
+
* Weakening the tiebreaker would reintroduce the skip/repeat paging bug it
|
|
1559
|
+
* was added to fix, so bound the input instead. `min(k)` over the top
|
|
1560
|
+
* `skip + limit` values of the leading sort key `k` is a rank statistic of
|
|
1561
|
+
* k's MULTISET: it does not depend on which of several tied rows the inner
|
|
1562
|
+
* LIMIT happened to keep. Every row that could reach position `skip + limit`
|
|
1563
|
+
* satisfies `k >= min(k)`, and every row tied at the boundary value is
|
|
1564
|
+
* admitted — so the page is exactly the page the unbounded query returns.
|
|
1565
|
+
* That is what makes this a pure cost change: every gate below is a
|
|
1566
|
+
* performance gate, and getting one wrong can only make a query slower,
|
|
1567
|
+
* never lose or repeat a row.
|
|
1568
|
+
*
|
|
1569
|
+
* The inner pass reads one narrow key column in physical order and stops at
|
|
1570
|
+
* `skip + limit` rows, so it costs far less than the wide outer read it
|
|
1571
|
+
* saves.
|
|
1572
|
+
*
|
|
1573
|
+
* `min()` is nested over a subquery rather than taken as the N-th value via
|
|
1574
|
+
* `ORDER BY k DESC LIMIT 1 OFFSET n - 1` on purpose: on a final page with
|
|
1575
|
+
* fewer than `skip + limit` matching rows the latter returns no row, the
|
|
1576
|
+
* scalar is NULL, `k >= NULL` is NULL, and the page comes back empty.
|
|
1577
|
+
* `min()` over the available rows degrades to the smallest matching value.
|
|
1578
|
+
*/
|
|
1579
|
+
private toSortKeyBoundaryFilter(
|
|
1580
|
+
findBy: FindBy<TBaseModel>,
|
|
1581
|
+
sort: Sort<TBaseModel>,
|
|
1582
|
+
options: { hasGroupBy: boolean; databaseName: string },
|
|
1583
|
+
): Statement | null {
|
|
1584
|
+
/*
|
|
1585
|
+
* Under GROUP BY the predicate would restrict the aggregation INPUT
|
|
1586
|
+
* rather than the page, so it would change results. Mirrors the
|
|
1587
|
+
* tiebreaker's own exemption, leaving grouped finds byte-identical.
|
|
1588
|
+
*/
|
|
1589
|
+
if (options.hasGroupBy) {
|
|
1590
|
+
return null;
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
/*
|
|
1594
|
+
* Without an `_id` column there is no off-key tiebreaker — the six
|
|
1595
|
+
* `includeBaseColumns: false` aggregate targets — so the ORDER BY is
|
|
1596
|
+
* already key-aligned and the bound would be pure overhead. Same
|
|
1597
|
+
* condition toPaginationStableSort bails on.
|
|
1598
|
+
*/
|
|
1599
|
+
const hasIdColumn: boolean = this.model.tableColumns.some(
|
|
1600
|
+
(column: AnalyticsTableColumn): boolean => {
|
|
1601
|
+
return column.key === "_id";
|
|
1602
|
+
},
|
|
1603
|
+
);
|
|
1604
|
+
|
|
1605
|
+
if (!hasIdColumn) {
|
|
1606
|
+
return null;
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
const leadingSortKey: string | undefined = Object.keys(sort || {})[0];
|
|
1610
|
+
|
|
1611
|
+
if (!leadingSortKey) {
|
|
1612
|
+
return null;
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
/*
|
|
1616
|
+
* Only a column in the physical sorting key can be read in order, so
|
|
1617
|
+
* only there can the off-key `_id` term have cost anything. Off-key
|
|
1618
|
+
* leads (e.g. Log by `severityText`) already plan a bounded top-N and
|
|
1619
|
+
* an extra pass would be pure waste.
|
|
1620
|
+
*/
|
|
1621
|
+
if (!this.model.sortKeys.includes(leadingSortKey)) {
|
|
1622
|
+
return null;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
/*
|
|
1626
|
+
* A non-required column is `Nullable(...)` in the DDL, and `k >= NULL`
|
|
1627
|
+
* is NULL — the predicate would DROP those rows rather than just
|
|
1628
|
+
* narrowing the scan. Fail safe to today's behavior.
|
|
1629
|
+
*/
|
|
1630
|
+
const leadingSortColumn: AnalyticsTableColumn | null =
|
|
1631
|
+
this.model.getTableColumn(leadingSortKey);
|
|
1632
|
+
|
|
1633
|
+
if (!leadingSortColumn || !leadingSortColumn.required) {
|
|
1634
|
+
return null;
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
/*
|
|
1638
|
+
* `findOneById` funnels a point lookup through `findOneBy` carrying the
|
|
1639
|
+
* model's default sort. At most one row can match, so bounding it would
|
|
1640
|
+
* double a query that has no ordering problem to begin with.
|
|
1641
|
+
*/
|
|
1642
|
+
if ((findBy.query as Record<string, unknown> | undefined)?.["_id"]) {
|
|
1643
|
+
return null;
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
/*
|
|
1647
|
+
* The predicate is valid only BECAUSE of LIMIT/OFFSET: it admits the
|
|
1648
|
+
* rows that can reach position `skip + limit` and no more. Guards the
|
|
1649
|
+
* `new PositiveNumber(undefined)` -> NaN path that exists upstream.
|
|
1650
|
+
*/
|
|
1651
|
+
const limit: number = Number(findBy.limit);
|
|
1652
|
+
const skip: number = Number(findBy.skip);
|
|
1653
|
+
|
|
1654
|
+
if (!Number.isFinite(limit) || !Number.isFinite(skip)) {
|
|
1655
|
+
return null;
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
const boundaryRowCount: number = skip + limit;
|
|
1659
|
+
|
|
1660
|
+
if (boundaryRowCount <= 0) {
|
|
1661
|
+
return null;
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
const isDescending: boolean =
|
|
1665
|
+
(sort as Record<string, SortOrder | undefined>)[leadingSortKey] !==
|
|
1666
|
+
SortOrder.Ascending;
|
|
1667
|
+
|
|
1668
|
+
/*
|
|
1669
|
+
* The bound must be computed over the same row set the outer query
|
|
1670
|
+
* filters on, so the WHERE is regenerated rather than shared: appending
|
|
1671
|
+
* one Statement into two places would bind its parameters twice.
|
|
1672
|
+
*/
|
|
1673
|
+
const boundaryWhereStatement: Statement =
|
|
1674
|
+
this.statementGenerator.toWhereStatement(findBy.query);
|
|
1675
|
+
|
|
1676
|
+
const boundaryStatement: Statement = SQL` AND ${leadingSortKey} `;
|
|
1677
|
+
|
|
1678
|
+
boundaryStatement.append(isDescending ? SQL`>=` : SQL`<=`);
|
|
1679
|
+
boundaryStatement.append(
|
|
1680
|
+
isDescending
|
|
1681
|
+
? SQL` (SELECT min(${leadingSortKey}) FROM (SELECT ${leadingSortKey} FROM ${options.databaseName}.${this.model.tableName} WHERE TRUE `
|
|
1682
|
+
: SQL` (SELECT max(${leadingSortKey}) FROM (SELECT ${leadingSortKey} FROM ${options.databaseName}.${this.model.tableName} WHERE TRUE `,
|
|
1683
|
+
);
|
|
1684
|
+
boundaryStatement.append(boundaryWhereStatement);
|
|
1685
|
+
boundaryStatement.append(this.getRetentionReadFilter());
|
|
1686
|
+
boundaryStatement.append(SQL` ORDER BY ${leadingSortKey} `);
|
|
1687
|
+
boundaryStatement.append(isDescending ? SQL`DESC` : SQL`ASC`);
|
|
1688
|
+
boundaryStatement.append(
|
|
1689
|
+
SQL` LIMIT ${{
|
|
1690
|
+
value: boundaryRowCount,
|
|
1691
|
+
type: TableColumnType.Number,
|
|
1692
|
+
}}))`,
|
|
1693
|
+
);
|
|
1694
|
+
|
|
1695
|
+
return boundaryStatement;
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1545
1698
|
public toFindStatement(findBy: FindBy<TBaseModel>): {
|
|
1546
1699
|
statement: Statement;
|
|
1547
1700
|
columns: Array<string>;
|
|
@@ -1577,6 +1730,18 @@ export default class AnalyticsDatabaseService<
|
|
|
1577
1730
|
}),
|
|
1578
1731
|
);
|
|
1579
1732
|
|
|
1733
|
+
/*
|
|
1734
|
+
* Keeps the `_id` tiebreaker affordable. Result-preserving by
|
|
1735
|
+
* construction, so it is appended to the WHERE without touching the
|
|
1736
|
+
* ORDER BY above. Null whenever the bound cannot help or cannot be
|
|
1737
|
+
* proven safe.
|
|
1738
|
+
*/
|
|
1739
|
+
const sortKeyBoundaryStatement: Statement | null =
|
|
1740
|
+
this.toSortKeyBoundaryFilter(findBy, findBy.sort!, {
|
|
1741
|
+
hasGroupBy: Boolean(groupByStatement),
|
|
1742
|
+
databaseName: databaseName,
|
|
1743
|
+
});
|
|
1744
|
+
|
|
1580
1745
|
const statement: Statement = SQL``;
|
|
1581
1746
|
|
|
1582
1747
|
statement.append(SQL`SELECT `.append(select.statement));
|
|
@@ -1586,6 +1751,10 @@ export default class AnalyticsDatabaseService<
|
|
|
1586
1751
|
.append(whereStatement)
|
|
1587
1752
|
.append(this.getRetentionReadFilter());
|
|
1588
1753
|
|
|
1754
|
+
if (sortKeyBoundaryStatement) {
|
|
1755
|
+
statement.append(sortKeyBoundaryStatement);
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1589
1758
|
if (groupByStatement) {
|
|
1590
1759
|
statement.append(SQL` GROUP BY `).append(groupByStatement);
|
|
1591
1760
|
}
|
|
@@ -2886,6 +2886,107 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
2886
2886
|
await repository.manager.query(sql, params);
|
|
2887
2887
|
}
|
|
2888
2888
|
|
|
2889
|
+
/*
|
|
2890
|
+
* Add one to a numeric column and return what it became, in a SINGLE
|
|
2891
|
+
* statement.
|
|
2892
|
+
*
|
|
2893
|
+
* This exists for counters that GATE something, where the read and the
|
|
2894
|
+
* write cannot be allowed to come apart. The motivating case is the failed
|
|
2895
|
+
* attempt counter on a notification-channel verification code: read the
|
|
2896
|
+
* count, decide, then write it back, and N requests racing each other all
|
|
2897
|
+
* read the same pre-increment value and all decide they are under the
|
|
2898
|
+
* limit — which is precisely the shape an attacker running a brute-force
|
|
2899
|
+
* loop produces. `atomicAddToColumnsByIdWithoutHooks` closes the
|
|
2900
|
+
* lost-update half of that but cannot answer "and what is it now?", and
|
|
2901
|
+
* `getRepository().increment()` cannot either.
|
|
2902
|
+
*
|
|
2903
|
+
* RETURNING makes the increment and the observation the same operation, so
|
|
2904
|
+
* every concurrent caller gets a distinct value and the k-th attempt is
|
|
2905
|
+
* refused no matter how the requests interleave.
|
|
2906
|
+
*
|
|
2907
|
+
* COALESCE so a NULL counter starts from zero rather than staying NULL.
|
|
2908
|
+
*
|
|
2909
|
+
* The column and table identifiers come from entity metadata, never from
|
|
2910
|
+
* the caller, and the id is bound as a parameter. Hooks, the `version`
|
|
2911
|
+
* bump and access control are all skipped: use ONLY for trusted internal
|
|
2912
|
+
* counter writes.
|
|
2913
|
+
*/
|
|
2914
|
+
@CaptureSpan()
|
|
2915
|
+
public async atomicIncrementColumnValueByOneAndGetValue(data: {
|
|
2916
|
+
id: ObjectID;
|
|
2917
|
+
columnName: keyof TBaseModel;
|
|
2918
|
+
}): Promise<number> {
|
|
2919
|
+
if (!data.id) {
|
|
2920
|
+
throw new BadDataException("id is required");
|
|
2921
|
+
}
|
|
2922
|
+
|
|
2923
|
+
const repository: Repository<TBaseModel> = this.getRepository();
|
|
2924
|
+
const metadata: EntityMetadata = repository.metadata;
|
|
2925
|
+
|
|
2926
|
+
const column: ColumnMetadata | undefined =
|
|
2927
|
+
metadata.findColumnWithPropertyName(data.columnName as string);
|
|
2928
|
+
|
|
2929
|
+
if (!column) {
|
|
2930
|
+
throw new BadDataException(
|
|
2931
|
+
`atomicIncrementColumnValueByOneAndGetValue: unknown column "${String(
|
|
2932
|
+
data.columnName,
|
|
2933
|
+
)}" on "${metadata.tableName}"`,
|
|
2934
|
+
);
|
|
2935
|
+
}
|
|
2936
|
+
|
|
2937
|
+
const primaryColumnName: string =
|
|
2938
|
+
metadata.primaryColumns[0]?.databaseName || "_id";
|
|
2939
|
+
|
|
2940
|
+
const quoted: string = `"${column.databaseName}"`;
|
|
2941
|
+
|
|
2942
|
+
const sql: string = `UPDATE "${metadata.tableName}" SET ${quoted} = COALESCE(${quoted}, 0) + 1 WHERE "${primaryColumnName}" = $1 RETURNING ${quoted}`;
|
|
2943
|
+
|
|
2944
|
+
const result: unknown = await repository.manager.query(sql, [
|
|
2945
|
+
data.id.toString(),
|
|
2946
|
+
]);
|
|
2947
|
+
|
|
2948
|
+
/*
|
|
2949
|
+
* TypeORM's Postgres driver returns `[rows, affectedCount]` for an UPDATE
|
|
2950
|
+
* and a bare row array for everything else, so both shapes are unwrapped
|
|
2951
|
+
* rather than one being assumed.
|
|
2952
|
+
*/
|
|
2953
|
+
const rows: Array<unknown> = Array.isArray(result)
|
|
2954
|
+
? Array.isArray(result[0])
|
|
2955
|
+
? (result[0] as Array<unknown>)
|
|
2956
|
+
: (result as Array<unknown>)
|
|
2957
|
+
: [];
|
|
2958
|
+
|
|
2959
|
+
const row: unknown = rows[0];
|
|
2960
|
+
|
|
2961
|
+
if (!row || typeof row !== "object" || Array.isArray(row)) {
|
|
2962
|
+
/*
|
|
2963
|
+
* Nothing came back, so the row does not exist — deleted underneath us,
|
|
2964
|
+
* or never there. Callers gate on the returned count, so this must be an
|
|
2965
|
+
* error and not a zero, which would read as a fresh allowance.
|
|
2966
|
+
*/
|
|
2967
|
+
throw new BadDataException(
|
|
2968
|
+
`Item with ID ${data.id.toString()} not found`,
|
|
2969
|
+
);
|
|
2970
|
+
}
|
|
2971
|
+
|
|
2972
|
+
const value: unknown = (row as Record<string, unknown>)[
|
|
2973
|
+
column.databaseName
|
|
2974
|
+
];
|
|
2975
|
+
|
|
2976
|
+
const parsed: number =
|
|
2977
|
+
typeof value === "number" ? value : parseInt(String(value), 10);
|
|
2978
|
+
|
|
2979
|
+
if (!Number.isFinite(parsed)) {
|
|
2980
|
+
throw new BadDataException(
|
|
2981
|
+
`atomicIncrementColumnValueByOneAndGetValue: "${String(
|
|
2982
|
+
data.columnName,
|
|
2983
|
+
)}" did not return a number`,
|
|
2984
|
+
);
|
|
2985
|
+
}
|
|
2986
|
+
|
|
2987
|
+
return parsed;
|
|
2988
|
+
}
|
|
2989
|
+
|
|
2889
2990
|
@CaptureSpan()
|
|
2890
2991
|
protected async atomicIncrementColumnValueByOne(data: {
|
|
2891
2992
|
id: ObjectID;
|
|
@@ -4,18 +4,138 @@ import Team from "../../Models/DatabaseModels/Team";
|
|
|
4
4
|
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
5
5
|
import ObjectID from "../../Types/ObjectID";
|
|
6
6
|
import CreateBy from "../Types/Database/CreateBy";
|
|
7
|
-
import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
|
|
7
|
+
import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
|
|
8
8
|
import UpdateBy from "../Types/Database/UpdateBy";
|
|
9
9
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
10
10
|
import validateGlobalProviderProjectTeams, {
|
|
11
11
|
resolveAttachmentProjectId,
|
|
12
12
|
} from "../Utils/ValidateGlobalProviderProjectTeams";
|
|
13
|
+
import {
|
|
14
|
+
GLOBAL_SSO_AUTHORIZATION_CACHE_TTL_MS,
|
|
15
|
+
GlobalProviderAttachments,
|
|
16
|
+
clearGlobalSsoAuthorizationCaches,
|
|
17
|
+
doAttachmentsGovernProject,
|
|
18
|
+
globalProviderCacheKey,
|
|
19
|
+
globalSsoAttachmentsCache,
|
|
20
|
+
loadAttachmentsOnce,
|
|
21
|
+
} from "../Utils/GlobalSsoAuthorization";
|
|
22
|
+
import DeleteBy from "../Types/Database/DeleteBy";
|
|
13
23
|
|
|
14
24
|
export class Service extends DatabaseService<Model> {
|
|
15
25
|
public constructor() {
|
|
16
26
|
super(Model);
|
|
17
27
|
}
|
|
18
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Whether this provider's attachments cover `projectId`.
|
|
31
|
+
*
|
|
32
|
+
* Only consulted when the provider has `restrictToAttachedProjects` on -
|
|
33
|
+
* attachments are the PROVISIONING allow-list by default, not an access
|
|
34
|
+
* boundary, and reading them as one without the admin asking would lock
|
|
35
|
+
* existing users out of projects they legitimately reach.
|
|
36
|
+
*
|
|
37
|
+
* "No attachment rows at all" means instance-wide, matching the login
|
|
38
|
+
* router's default-all mode. "Rows exist but none are enabled" is a
|
|
39
|
+
* different answer and denies - otherwise an admin disabling the last
|
|
40
|
+
* attachment would WIDEN the provider to every project.
|
|
41
|
+
*
|
|
42
|
+
* Cached for 60s, with concurrent misses sharing one query.
|
|
43
|
+
*/
|
|
44
|
+
@CaptureSpan()
|
|
45
|
+
public async doesProviderGovernProject(data: {
|
|
46
|
+
globalOidcId: ObjectID;
|
|
47
|
+
projectId: ObjectID;
|
|
48
|
+
}): Promise<boolean> {
|
|
49
|
+
const key: string = globalProviderCacheKey("oidc", data.globalOidcId);
|
|
50
|
+
|
|
51
|
+
const cached: GlobalProviderAttachments | undefined =
|
|
52
|
+
globalSsoAttachmentsCache.get(key);
|
|
53
|
+
|
|
54
|
+
if (cached !== undefined) {
|
|
55
|
+
return doAttachmentsGovernProject(cached, data.projectId);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const attachments: GlobalProviderAttachments = await loadAttachmentsOnce(
|
|
59
|
+
key,
|
|
60
|
+
async (): Promise<GlobalProviderAttachments> => {
|
|
61
|
+
/*
|
|
62
|
+
* Fetched WITHOUT the isEnabled filter so a disabled row still counts
|
|
63
|
+
* as "this provider has attachments"; the enabled ones are selected
|
|
64
|
+
* out below.
|
|
65
|
+
*/
|
|
66
|
+
const rows: Array<Model> = await this.findBy({
|
|
67
|
+
query: { globalOidcId: data.globalOidcId },
|
|
68
|
+
select: { _id: true, projectId: true, isEnabled: true },
|
|
69
|
+
limit: LIMIT_PER_PROJECT,
|
|
70
|
+
skip: 0,
|
|
71
|
+
props: { isRoot: true },
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const loaded: GlobalProviderAttachments = {
|
|
75
|
+
hasAnyAttachmentRows: rows.length > 0,
|
|
76
|
+
enabledProjectIds: rows
|
|
77
|
+
.filter((row: Model) => {
|
|
78
|
+
return Boolean(row.isEnabled) && Boolean(row.projectId);
|
|
79
|
+
})
|
|
80
|
+
.map((row: Model) => {
|
|
81
|
+
return row.projectId!.toString();
|
|
82
|
+
}),
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
globalSsoAttachmentsCache.set(
|
|
86
|
+
key,
|
|
87
|
+
loaded,
|
|
88
|
+
GLOBAL_SSO_AUTHORIZATION_CACHE_TTL_MS,
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
return loaded;
|
|
92
|
+
},
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
return doAttachmentsGovernProject(attachments, data.projectId);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@CaptureSpan()
|
|
99
|
+
protected override async onBeforeDelete(
|
|
100
|
+
deleteBy: DeleteBy<Model>,
|
|
101
|
+
): Promise<OnDelete<Model>> {
|
|
102
|
+
// Detaching a project has to take effect now, not in 60s, on this node.
|
|
103
|
+
clearGlobalSsoAuthorizationCaches();
|
|
104
|
+
return { deleteBy, carryForward: null };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/*
|
|
108
|
+
* Cleared again AFTER the write commits. A clear that runs before the row
|
|
109
|
+
* lands can be immediately re-filled with the pre-change answer by a
|
|
110
|
+
* concurrent request, handing the old attachment set another full TTL.
|
|
111
|
+
*/
|
|
112
|
+
@CaptureSpan()
|
|
113
|
+
protected override async onDeleteSuccess(
|
|
114
|
+
onDelete: OnDelete<Model>,
|
|
115
|
+
_itemIdsBeforeDelete: Array<ObjectID>,
|
|
116
|
+
): Promise<OnDelete<Model>> {
|
|
117
|
+
clearGlobalSsoAuthorizationCaches();
|
|
118
|
+
return onDelete;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@CaptureSpan()
|
|
122
|
+
protected override async onCreateSuccess(
|
|
123
|
+
_onCreate: OnCreate<Model>,
|
|
124
|
+
createdItem: Model,
|
|
125
|
+
): Promise<Model> {
|
|
126
|
+
clearGlobalSsoAuthorizationCaches();
|
|
127
|
+
return createdItem;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@CaptureSpan()
|
|
131
|
+
protected override async onUpdateSuccess(
|
|
132
|
+
onUpdate: OnUpdate<Model>,
|
|
133
|
+
_updatedItemIds: Array<ObjectID>,
|
|
134
|
+
): Promise<OnUpdate<Model>> {
|
|
135
|
+
clearGlobalSsoAuthorizationCaches();
|
|
136
|
+
return onUpdate;
|
|
137
|
+
}
|
|
138
|
+
|
|
19
139
|
@CaptureSpan()
|
|
20
140
|
protected override async onBeforeCreate(
|
|
21
141
|
createBy: CreateBy<Model>,
|
|
@@ -38,6 +158,9 @@ export class Service extends DatabaseService<Model> {
|
|
|
38
158
|
projectId,
|
|
39
159
|
});
|
|
40
160
|
|
|
161
|
+
// A new attachment narrows (or widens) which projects the provider governs.
|
|
162
|
+
clearGlobalSsoAuthorizationCaches();
|
|
163
|
+
|
|
41
164
|
return { createBy, carryForward: null };
|
|
42
165
|
}
|
|
43
166
|
|
|
@@ -78,6 +201,8 @@ export class Service extends DatabaseService<Model> {
|
|
|
78
201
|
}
|
|
79
202
|
}
|
|
80
203
|
|
|
204
|
+
clearGlobalSsoAuthorizationCaches();
|
|
205
|
+
|
|
81
206
|
return { updateBy, carryForward: null };
|
|
82
207
|
}
|
|
83
208
|
}
|
|
@@ -1,10 +1,142 @@
|
|
|
1
1
|
import DatabaseService from "./DatabaseService";
|
|
2
2
|
import Model from "../../Models/DatabaseModels/GlobalOidc";
|
|
3
|
+
import ObjectID from "../../Types/ObjectID";
|
|
4
|
+
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
5
|
+
import CreateBy from "../Types/Database/CreateBy";
|
|
6
|
+
import DeleteBy from "../Types/Database/DeleteBy";
|
|
7
|
+
import UpdateBy from "../Types/Database/UpdateBy";
|
|
8
|
+
import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
|
|
9
|
+
import {
|
|
10
|
+
GLOBAL_SSO_AUTHORIZATION_CACHE_TTL_MS,
|
|
11
|
+
GlobalProviderTrust,
|
|
12
|
+
clearGlobalSsoAuthorizationCaches,
|
|
13
|
+
globalProviderCacheKey,
|
|
14
|
+
globalSsoProviderTrustCache,
|
|
15
|
+
loadTrustOnce,
|
|
16
|
+
} from "../Utils/GlobalSsoAuthorization";
|
|
3
17
|
|
|
4
18
|
export class Service extends DatabaseService<Model> {
|
|
5
19
|
public constructor() {
|
|
6
20
|
super(Model);
|
|
7
21
|
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* What the SSO-enforcement middleware needs to know about this provider:
|
|
25
|
+
* whether it is still usable at all, and whether the admin opted it into
|
|
26
|
+
* attachment-scoped access.
|
|
27
|
+
*
|
|
28
|
+
* Called on every authenticated request against an SSO-enforced project, so
|
|
29
|
+
* the answer is cached for 60s and concurrent misses share one query.
|
|
30
|
+
* Without this lookup, turning a provider off leaves every token it ever
|
|
31
|
+
* issued working until each one expires - up to thirty days.
|
|
32
|
+
*/
|
|
33
|
+
@CaptureSpan()
|
|
34
|
+
public async getProviderTrust(
|
|
35
|
+
providerId: ObjectID,
|
|
36
|
+
): Promise<GlobalProviderTrust> {
|
|
37
|
+
const key: string = globalProviderCacheKey("oidc", providerId);
|
|
38
|
+
|
|
39
|
+
const cached: GlobalProviderTrust | undefined =
|
|
40
|
+
globalSsoProviderTrustCache.get(key);
|
|
41
|
+
|
|
42
|
+
if (cached !== undefined) {
|
|
43
|
+
return cached;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return loadTrustOnce(key, async (): Promise<GlobalProviderTrust> => {
|
|
47
|
+
const provider: Model | null = await this.findOneBy({
|
|
48
|
+
query: { _id: providerId.toString() },
|
|
49
|
+
select: {
|
|
50
|
+
_id: true,
|
|
51
|
+
isEnabled: true,
|
|
52
|
+
restrictToAttachedProjects: true,
|
|
53
|
+
},
|
|
54
|
+
props: { isRoot: true },
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
/*
|
|
58
|
+
* A deleted provider and a disabled one are the same answer: no. Both
|
|
59
|
+
* are cached, so a revoked provider does not cost a query per request.
|
|
60
|
+
*/
|
|
61
|
+
const trust: GlobalProviderTrust = {
|
|
62
|
+
isUsable: Boolean(provider && provider.isEnabled),
|
|
63
|
+
restrictToAttachedProjects: Boolean(
|
|
64
|
+
provider && provider.restrictToAttachedProjects,
|
|
65
|
+
),
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
globalSsoProviderTrustCache.set(
|
|
69
|
+
key,
|
|
70
|
+
trust,
|
|
71
|
+
GLOBAL_SSO_AUTHORIZATION_CACHE_TTL_MS,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
return trust;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/*
|
|
79
|
+
* Cache invalidation runs in the SUCCESS hooks, not the before-hooks: a
|
|
80
|
+
* clear that happens before the row is written can be immediately re-filled
|
|
81
|
+
* with the pre-change answer by a concurrent request, which would hand a
|
|
82
|
+
* disabled provider another full TTL of life on the very node that served
|
|
83
|
+
* the disable. Clearing in both is deliberate - the before-hook narrows the
|
|
84
|
+
* window, the success hook closes it.
|
|
85
|
+
*
|
|
86
|
+
* These caches are per-process, so the hooks make a change immediate on the
|
|
87
|
+
* node that served it and the TTL bounds every other node.
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
@CaptureSpan()
|
|
91
|
+
protected override async onBeforeUpdate(
|
|
92
|
+
updateBy: UpdateBy<Model>,
|
|
93
|
+
): Promise<OnUpdate<Model>> {
|
|
94
|
+
clearGlobalSsoAuthorizationCaches();
|
|
95
|
+
return { updateBy, carryForward: null };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@CaptureSpan()
|
|
99
|
+
protected override async onUpdateSuccess(
|
|
100
|
+
onUpdate: OnUpdate<Model>,
|
|
101
|
+
_updatedItemIds: Array<ObjectID>,
|
|
102
|
+
): Promise<OnUpdate<Model>> {
|
|
103
|
+
clearGlobalSsoAuthorizationCaches();
|
|
104
|
+
return onUpdate;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@CaptureSpan()
|
|
108
|
+
protected override async onBeforeDelete(
|
|
109
|
+
deleteBy: DeleteBy<Model>,
|
|
110
|
+
): Promise<OnDelete<Model>> {
|
|
111
|
+
clearGlobalSsoAuthorizationCaches();
|
|
112
|
+
return { deleteBy, carryForward: null };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@CaptureSpan()
|
|
116
|
+
protected override async onDeleteSuccess(
|
|
117
|
+
onDelete: OnDelete<Model>,
|
|
118
|
+
_itemIdsBeforeDelete: Array<ObjectID>,
|
|
119
|
+
): Promise<OnDelete<Model>> {
|
|
120
|
+
clearGlobalSsoAuthorizationCaches();
|
|
121
|
+
return onDelete;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@CaptureSpan()
|
|
125
|
+
protected override async onBeforeCreate(
|
|
126
|
+
createBy: CreateBy<Model>,
|
|
127
|
+
): Promise<OnCreate<Model>> {
|
|
128
|
+
clearGlobalSsoAuthorizationCaches();
|
|
129
|
+
return { createBy, carryForward: null };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
@CaptureSpan()
|
|
133
|
+
protected override async onCreateSuccess(
|
|
134
|
+
_onCreate: OnCreate<Model>,
|
|
135
|
+
createdItem: Model,
|
|
136
|
+
): Promise<Model> {
|
|
137
|
+
clearGlobalSsoAuthorizationCaches();
|
|
138
|
+
return createdItem;
|
|
139
|
+
}
|
|
8
140
|
}
|
|
9
141
|
|
|
10
142
|
export default new Service();
|