@oneuptime/common 13.0.7 → 14.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/AnalyticsModels/AuditLog.ts +23 -15
- package/Models/DatabaseModels/GlobalConfig.ts +24 -0
- package/Models/DatabaseModels/Monitor.ts +3 -2
- package/Models/DatabaseModels/MonitorTemplate.ts +2 -1
- package/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.ts +1 -1
- package/Models/DatabaseModels/ProjectOnCallCalendarFeed.ts +1 -1
- package/Models/DatabaseModels/UserOnCallCalendarFeed.ts +1 -1
- package/Scripts/generate-service-worker.js +65 -4
- package/Server/API/AIBillingAPI.ts +1 -0
- package/Server/API/AIInsightAPI.ts +1 -4
- package/Server/API/AIInvestigationAPI.ts +1 -4
- package/Server/API/AIReadinessAPI.ts +4 -5
- package/Server/API/AlertAPI.ts +1 -0
- package/Server/API/AutoRemediationAPI.ts +1 -4
- package/Server/API/BaseAPI.ts +34 -0
- package/Server/API/BaseAnalyticsAPI.ts +80 -9
- package/Server/API/BillingAPI.ts +2 -0
- package/Server/API/BillingInvoiceAPI.ts +1 -0
- package/Server/API/BillingPaymentMethodAPI.ts +2 -0
- package/Server/API/CodeFixRunAPI.ts +1 -3
- package/Server/API/CommonAPI.ts +68 -4
- package/Server/API/DashboardAPI.ts +12 -12
- package/Server/API/GlobalConfigAPI.ts +243 -460
- package/Server/API/IncidentAPI.ts +2 -0
- package/Server/API/IncidentEpisodeAPI.ts +1 -0
- package/Server/API/NotificationAPI.ts +1 -0
- package/Server/API/OnCallCalendarAPI.ts +4 -5
- package/Server/API/OnCallDutyPolicyAPI.ts +7 -0
- package/Server/API/OnCallReadinessAPI.ts +4 -1
- package/Server/API/OnCallScheduleTimelineAPI.ts +731 -0
- package/Server/API/ProjectAPI.ts +1 -0
- package/Server/API/ProjectOIDC.ts +25 -16
- package/Server/API/ProjectSSO.ts +24 -16
- package/Server/API/ScheduledMaintenanceAPI.ts +1 -0
- package/Server/API/StatusPageAPI.ts +261 -74
- package/Server/API/TeamMemberAPI.ts +13 -1
- package/Server/API/UserCallAPI.ts +2 -0
- package/Server/API/UserEmailAPI.ts +2 -0
- package/Server/API/UserIncomingCallNumberAPI.ts +2 -0
- package/Server/API/UserMicrosoftTeamsAPI.ts +1 -0
- package/Server/API/UserSlackAPI.ts +1 -0
- package/Server/API/UserSmsAPI.ts +2 -0
- package/Server/API/UserTotpAuthAPI.ts +1 -0
- package/Server/API/UserWebAuthnAPI.ts +2 -0
- package/Server/API/UserWebhookAPI.ts +1 -0
- package/Server/API/UserWhatsAppAPI.ts +2 -0
- package/Server/Enterprise/EnterpriseEdition.ts +649 -0
- package/Server/Enterprise/EnterpriseFeature.ts +48 -0
- package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +192 -0
- package/Server/Enterprise/EnterpriseServerModule.ts +233 -0
- package/Server/EnvironmentConfig.ts +147 -2
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Middleware/MasterAdminAuthorization.ts +13 -2
- package/Server/Middleware/UserAuthorization.ts +117 -21
- package/Server/Services/ApiKeyPermissionService.ts +101 -4
- package/Server/Services/AuditLogService.ts +84 -1079
- package/Server/Services/DatabaseService.ts +245 -0
- package/Server/Services/DetectionRuleService.ts +5 -4
- package/Server/Services/EnterpriseLicenseService.ts +38 -0
- package/Server/Services/GlobalConfigService.ts +80 -1
- package/Server/Services/MonitorProbeService.ts +116 -20
- package/Server/Services/MonitorService.ts +56 -4
- package/Server/Services/MonitorStatusTimelineService.ts +284 -0
- package/Server/Services/MonitorTemplateService.ts +26 -0
- package/Server/Services/OnCallDutyPolicyChildService.ts +261 -0
- package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +2 -2
- package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +2 -2
- package/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.ts +2 -2
- package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +2 -2
- package/Server/Services/PayAsYouGoBillingService.ts +23 -28
- package/Server/Services/ProjectService.ts +302 -0
- package/Server/Services/RumSessionPinService.ts +293 -22
- package/Server/Services/StatusPagePrivateUserService.ts +7 -3
- package/Server/Services/StatusPageService.ts +78 -1
- package/Server/Services/TeamMemberService.ts +11 -0
- package/Server/Services/TeamPermissionService.ts +120 -26
- package/Server/Services/TeamService.ts +10 -0
- package/Server/Services/ThreatIntelFeedService.ts +6 -3
- package/Server/Services/UserService.ts +10 -17
- package/Server/Types/Database/Permissions/BasePermission.ts +9 -7
- package/Server/Types/Database/Permissions/CreatePermission.ts +15 -0
- package/Server/Types/Database/Permissions/EditionPermission.ts +208 -18
- package/Server/Types/Database/Permissions/Index.ts +75 -11
- package/Server/Types/Database/Permissions/TablePermission.ts +34 -31
- package/Server/Types/Database/Permissions/UpdatePermission.ts +29 -0
- package/Server/Types/Markdown.ts +41 -0
- package/Server/Utils/AI/AIChatPrivacyFilter.ts +8 -0
- package/Server/Utils/AI/AIRunPrivacyFilter.ts +8 -0
- package/Server/Utils/CommunityEditionSsoReport.ts +361 -0
- package/Server/Utils/EditionEnforcement.ts +233 -0
- package/Server/Utils/FrontendEnvironment.ts +41 -2
- package/Server/Utils/InstanceHealth/RedisHealth.ts +12 -277
- package/Server/Utils/MasterAdminPageAccess.ts +61 -0
- package/Server/Utils/Monitor/AffectedResourceList.ts +190 -0
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +10 -1
- package/Server/Utils/Monitor/MonitorAlert.ts +3 -1
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +543 -333
- package/Server/Utils/Monitor/MonitorIncident.ts +3 -1
- package/Server/Utils/Monitor/MonitoringIntervalValidator.ts +116 -0
- package/Server/Utils/OnCall/OnCallCalendarFeedRenderer.ts +1 -1
- package/Server/Utils/Realtime.ts +163 -45
- package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +11 -28
- package/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.ts +170 -0
- package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +1 -1
- package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.ts +6 -2
- package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.ts +10 -9
- package/Server/Utils/Workspace/Slack/Slack.ts +423 -10
- package/Tests/App/Accounts/LoginPasskey.test.tsx +18 -0
- package/Tests/App/Accounts/LoginSsoEdition.test.tsx +616 -0
- package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +217 -0
- package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +357 -0
- package/Tests/App/AdminDashboard/EnterpriseLicensesShell.test.tsx +214 -0
- package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +271 -0
- package/Tests/App/AdminDashboard/HealthShells.test.tsx +659 -0
- package/Tests/App/Dashboard/AffectedResourcesPicker.test.tsx +1059 -0
- package/Tests/App/Dashboard/AffectedResourcesPickerEditForm.test.tsx +376 -0
- package/Tests/App/Dashboard/AffectedResourcesPickerHiddenTypes.test.tsx +757 -0
- package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +307 -0
- package/Tests/App/Dashboard/ArgumentsFormGroupByUnlistedAttributes.test.tsx +131 -0
- package/Tests/App/Dashboard/AuditLogsAndComplianceShells.test.tsx +572 -0
- package/Tests/App/Dashboard/DashboardHeaderRequests.test.tsx +1 -1
- package/Tests/App/Dashboard/DashboardMonitorLabelVariable.test.tsx +9 -1
- package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +24 -0
- package/Tests/App/Dashboard/DashboardVariableSelector.test.tsx +162 -8
- package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +547 -0
- package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +667 -0
- package/Tests/App/Dashboard/EntityFilterDropdownArchivedSlos.test.tsx +105 -6
- package/Tests/App/Dashboard/EntityFilterDropdownUnlistedSelection.test.tsx +434 -0
- package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +276 -1
- package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +319 -0
- package/Tests/App/Dashboard/OnCallCalendarFeedSideMenus.test.tsx +9 -1
- package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +185 -0
- package/Tests/App/Dashboard/PayAsYouGoConsentGate.test.tsx +58 -42
- package/Tests/App/Dashboard/PayAsYouGoNotices.test.tsx +42 -5
- package/Tests/App/Dashboard/ResourceAuditLogsSideMenus.test.tsx +34 -23
- package/Tests/App/Dashboard/ScheduleTimeline.test.tsx +1580 -0
- package/Tests/App/Dashboard/ScheduleTimelineAPI.test.ts +280 -0
- package/Tests/App/Dashboard/ScheduleTimelineModel.test.ts +673 -0
- package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +133 -70
- package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +399 -0
- package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +214 -0
- package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +86 -3
- package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +1 -58
- package/Tests/App/Dashboard/SecurityEventsGuideContent.test.ts +1313 -0
- package/Tests/App/Dashboard/SecurityEventsHowItWorksCard.test.tsx +536 -0
- package/Tests/App/Dashboard/SecurityEventsNavTabs.test.tsx +248 -0
- package/Tests/App/Dashboard/SecurityEventsNoResults.test.tsx +222 -0
- package/Tests/App/Dashboard/SecurityEventsThreatIntelPage.test.tsx +199 -0
- package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +1203 -0
- package/Tests/App/Dashboard/SloOverviewHero.test.tsx +171 -36
- package/Tests/App/Dashboard/SloViewSideMenu.test.tsx +215 -0
- package/Tests/App/Dashboard/SloViewSideMenuCounts.test.tsx +40 -3
- package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +11 -91
- package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +12 -4
- package/Tests/App/PublicDashboard/PublicDashboardWidgetListAuth.test.tsx +623 -0
- package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +319 -0
- package/Tests/Helpers/RefreshAwareApiScan.ts +757 -0
- package/Tests/Helpers/TenantScopedRequestScan.ts +515 -0
- package/Tests/Models/OnCallCalendarFeedModels.test.ts +23 -1
- package/Tests/Scripts/GenerateServiceWorker.test.ts +931 -0
- package/Tests/Server/API/AIChatRouteAuthorization.test.ts +138 -5
- package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +187 -0
- package/Tests/Server/API/AIInvestigationAvailabilityAuthorization.test.ts +51 -3
- package/Tests/Server/API/AIInvestigationEvidenceAPI.test.ts +55 -2
- package/Tests/Server/API/BaseAPICreateItemDoesNotMutateModel.test.ts +130 -0
- package/Tests/Server/API/BaseAnalyticsAPIAggregateCache.test.ts +729 -0
- package/Tests/Server/API/BillingPayAsYouGoStatus.test.ts +93 -7
- package/Tests/Server/API/BillingPaymentMethodAPI.test.ts +36 -3
- package/Tests/Server/API/CommonAPIAuthGuard.test.ts +1003 -24
- package/Tests/Server/API/DashboardPublicRateLimit.test.ts +6 -3
- package/Tests/Server/API/ExpiredSessionAIRoutes.test.ts +708 -0
- package/Tests/Server/API/ExpiredSessionCustomRoutes.test.ts +928 -0
- package/Tests/Server/API/ExpiredSessionMonitorTemplate.test.ts +319 -0
- package/Tests/Server/API/ExpiredSessionOnCallDutyPolicy.test.ts +336 -0
- package/Tests/Server/API/ExpiredSessionRouteGuards.test.ts +820 -0
- package/Tests/Server/API/GlobalConfigLicense.test.ts +766 -381
- package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +115 -12
- package/Tests/Server/API/OnCallCalendarAPI.test.ts +375 -8
- package/Tests/Server/API/OnCallReadinessAPI.test.ts +196 -912
- package/Tests/Server/API/OnCallScheduleTimelineAPI.test.ts +1513 -0
- package/Tests/Server/API/OnCallSetupReminderAPI.test.ts +119 -7
- package/Tests/Server/API/ProjectScopedCustomRouteAuth.test.ts +111 -4
- package/Tests/Server/API/PublicRouteInvalidAccessToken.test.ts +615 -0
- package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +89 -2
- package/Tests/Server/API/SessionReplayAPI.test.ts +121 -0
- package/Tests/Server/API/SsoProviderListingsEdition.test.ts +432 -0
- package/Tests/Server/API/StatusPageMasterPasswordRateLimit.test.ts +4 -2
- package/Tests/Server/API/StatusPagePostmortemVisibility.test.ts +441 -0
- package/Tests/Server/API/StatusPageTestEmailReportAuth.test.ts +664 -0
- package/Tests/Server/API/TeamMemberLeaveScimLockEdition.test.ts +252 -0
- package/Tests/Server/API/TeamMemberRemoveUserFromProjectAPI.test.ts +7 -0
- package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +6 -0
- package/Tests/Server/API/UserNotificationSettingAPI.test.ts +65 -4
- package/Tests/Server/API/UserProjectsAPI.test.ts +63 -3
- package/Tests/Server/API/UserTotpAuthAPI.test.ts +48 -2
- package/Tests/Server/API/UserWebAuthnAuthenticationOptionsRoute.test.ts +11 -2
- package/Tests/Server/API/UserWebAuthnBackupCodeMinting.test.ts +46 -3
- package/Tests/Server/API/UserWebAuthnPasskeyAPI.test.ts +18 -2
- package/Tests/Server/API/ZZVerifyChatsAuth.test.ts +24 -7
- package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +824 -0
- package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +643 -0
- package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +294 -0
- package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +93 -0
- package/Tests/Server/Enterprise/EnterpriseOnlyModulesLiveInEe.test.ts +582 -0
- package/Tests/Server/Enterprise/EnterpriseServerModule.test.ts +247 -0
- package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +502 -0
- package/Tests/Server/Enterprise/TestBillingFlag.ts +70 -0
- package/Tests/Server/EnvironmentConfigEnterpriseEdition.test.ts +314 -0
- package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +289 -0
- package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +5 -1
- package/Tests/Server/Middleware/ExpiredSessionUserMiddleware.test.ts +563 -0
- package/Tests/Server/Middleware/MasterAdminAuthorization.test.ts +299 -19
- package/Tests/Server/Middleware/PublicRouteUserMiddleware.test.ts +453 -0
- package/Tests/Server/Middleware/UserAuthorization.test.ts +37 -2
- package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +516 -0
- package/Tests/Server/Services/AIChatPrivacyPin.test.ts +24 -0
- package/Tests/Server/Services/ApiKeyPermissionSecurity.test.ts +2 -0
- package/Tests/Server/Services/ApiKeyPermissionService.test.ts +3 -3
- package/Tests/Server/Services/AuditLogService.test.ts +460 -990
- package/Tests/Server/Services/CreateAndReadResponsesKeepIds.test.ts +263 -0
- package/Tests/Server/Services/DatabaseServiceCreateSuppliedId.test.ts +147 -0
- package/Tests/Server/Services/DatabaseServiceLoginBeforeHooks.test.ts +1078 -0
- package/Tests/Server/Services/DatabaseServiceTenantRelationGuard.test.ts +259 -0
- package/Tests/Server/Services/DatabaseServiceWriteOperatorValues.test.ts +147 -0
- package/Tests/Server/Services/EnterpriseLicenseServiceKeyGeneration.test.ts +151 -0
- package/Tests/Server/Services/GlobalConfigServiceLicenseColumns.test.ts +357 -0
- package/Tests/Server/Services/MonitorDestinationInfoIPv6.test.ts +101 -0
- package/Tests/Server/Services/MonitorPayAsYouGoBilling.test.ts +115 -1
- package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +333 -0
- package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +303 -0
- package/Tests/Server/Services/OnCallChildCreateAuthorizationPostgres.test.ts +711 -0
- package/Tests/Server/Services/OnCallDutyPolicyChildService.test.ts +733 -0
- package/Tests/Server/Services/PayAsYouGoBillingService.test.ts +190 -140
- package/Tests/Server/Services/PayAsYouGoStripeRateLimitBudget.test.ts +4 -9
- package/Tests/Server/Services/PermissionBlockDeletion.test.ts +780 -0
- package/Tests/Server/Services/PermissionBlockDeletionPostgres.test.ts +628 -0
- package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +701 -0
- package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +31 -35
- package/Tests/Server/Services/ProjectServiceCreateSubscriptionStarted.test.ts +77 -1
- package/Tests/Server/Services/RumSessionPinCreatePermission.test.ts +715 -0
- package/Tests/Server/Services/ScimPushGroupsTeamLocksEdition.test.ts +431 -0
- package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +419 -0
- package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +769 -0
- package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +94 -0
- package/Tests/Server/Services/TeamMemberMultiTenantReadPostgres.test.ts +394 -0
- package/Tests/Server/Services/TeamPrivilegeEscalation.test.ts +6 -0
- package/Tests/Server/Services/TelemetryPayAsYouGoBilling.test.ts +131 -0
- package/Tests/Server/Services/UserAuthenticationService.test.ts +35 -0
- package/Tests/Server/Services/UserNotificationRuleAdminGuards.test.ts +13 -2
- package/Tests/Server/Services/UserServiceSeatLimit.test.ts +94 -56
- package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +1823 -0
- package/Tests/Server/Types/Database/Permissions/ModelPermissionAnonymousRefusal.test.ts +518 -0
- package/Tests/Server/Types/Database/Permissions/MultiTenantPermissions.test.ts +350 -0
- package/Tests/Server/Types/Database/Permissions/OnCallCalendarFeedPermissions.test.ts +282 -25
- package/Tests/Server/Types/Database/Permissions/TableLevelBlockPermission.test.ts +459 -0
- package/Tests/Server/Types/Markdown.test.ts +181 -0
- package/Tests/Server/Utils/AI/AIRunPrivacyFilter.test.ts +101 -9
- package/Tests/Server/Utils/AI/ChatAgentHelpers.test.ts +88 -4
- package/Tests/Server/Utils/AI/Toolbox/ExceptionTools.test.ts +459 -0
- package/Tests/Server/Utils/AI/Toolbox/LogTools.test.ts +794 -0
- package/Tests/Server/Utils/AI/Toolbox/RecentChangesTools.test.ts +574 -0
- package/Tests/Server/Utils/AI/Toolbox/SecurityEventTools.test.ts +596 -0
- package/Tests/Server/Utils/CaptchaRequestAndLogging.test.ts +395 -0
- package/Tests/Server/Utils/CommunityEditionSsoReport.test.ts +565 -0
- package/Tests/Server/Utils/EditionEnforcement.test.ts +303 -0
- package/Tests/Server/Utils/FrontendEnvironment.test.ts +367 -0
- package/Tests/Server/Utils/InstanceHealth/RedisHealth.test.ts +38 -418
- package/Tests/Server/Utils/MasterAdminPageAccess.test.ts +251 -0
- package/Tests/Server/Utils/Monitor/AffectedResourceList.test.ts +518 -0
- package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +24 -4
- package/Tests/Server/Utils/Monitor/MonitorActionTimestamps.test.ts +616 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +934 -96
- package/Tests/Server/Utils/Monitor/MonitoringIntervalValidator.test.ts +188 -0
- package/Tests/Server/Utils/Realtime.test.ts +502 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorSeverity.test.ts +216 -0
- package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +142 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.test.ts +140 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepairClickhouseIntegration.test.ts +542 -0
- package/Tests/Server/Utils/Telemetry/ChangeEventRow.test.ts +743 -0
- package/Tests/Server/Utils/Telemetry/RuntimeMetrics.test.ts +465 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/Alert.test.ts +202 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.test.ts +194 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/ScheduledMaintenance.test.ts +231 -0
- package/Tests/Server/Utils/Workspace/Slack/Messages/Alert.test.ts +194 -0
- package/Tests/Server/Utils/Workspace/Slack/Messages/AlertEpisode.test.ts +194 -0
- package/Tests/Server/Utils/Workspace/Slack/Messages/Incident.test.ts +194 -0
- package/Tests/Server/Utils/Workspace/Slack/Messages/IncidentEpisode.test.ts +194 -0
- package/Tests/Server/Utils/Workspace/Slack/Messages/ScheduledMaintenance.test.ts +247 -0
- package/Tests/Server/Utils/Workspace/Slack/SlackMarkdownSectionSplit.test.ts +1209 -0
- package/Tests/Types/AI/AIInsightEvidence.test.ts +206 -0
- package/Tests/Types/API/HostnameFromAuthority.test.ts +20 -10
- package/Tests/Types/API/HostnameIPv6.test.ts +149 -0
- package/Tests/Types/BaseDatabase/DatabaseCommonInteractionPropsUtilAnonymous.test.ts +144 -0
- package/Tests/Types/Call/CallProvider.test.ts +528 -0
- package/Tests/Types/Database/CanonicalModelInstance.test.ts +190 -0
- package/Tests/Types/Kubernetes/KubernetesCostIngest.test.ts +236 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleTimeline.test.ts +736 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleTimelineLayout.test.ts +996 -0
- package/Tests/Types/SecurityEvent/SigmaRule.test.ts +142 -0
- package/Tests/Types/Workflow/Components/JSON.test.ts +182 -0
- package/Tests/UI/Components/BasicFormDropdownNormalization.test.tsx +116 -1
- package/Tests/UI/Components/Dropdown/DropdownAsyncOptions.test.tsx +81 -0
- package/Tests/UI/Components/EditionLabelLapseCopy.ts +104 -0
- package/Tests/UI/Components/EditionLabelLicenseManagerWiring.test.tsx +254 -0
- package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +165 -171
- package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +1586 -0
- package/Tests/UI/Components/EditionLabelLicenseWritesGuard.test.tsx +157 -0
- package/Tests/UI/Components/EventAttachmentList.test.tsx +174 -0
- package/Tests/UI/Components/Forms/BasicFormBurnRateTemplateDefaults.test.tsx +395 -0
- package/Tests/UI/Components/Forms/BasicFormCollapsibleSections.test.tsx +286 -0
- package/Tests/UI/Components/Forms/FormSummary.test.tsx +128 -0
- package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +49 -2
- package/Tests/UI/Components/MarkdownConverters.test.ts +684 -0
- package/Tests/UI/Components/ModelListEmptyState.test.tsx +289 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableQueryChange.test.tsx +365 -0
- package/Tests/UI/Components/OpenAuthenticatedUrl.test.ts +358 -0
- package/Tests/UI/Components/SessionAwareImage.test.tsx +496 -0
- package/Tests/UI/Components/TelemetryHistogramZeroBuckets.test.tsx +190 -0
- package/Tests/UI/Components/TelemetryViewer/TelemetryViewerEmptyContent.test.tsx +131 -0
- package/Tests/UI/Components/TooltipInteractive.test.tsx +97 -0
- package/Tests/UI/EsbuildEnterpriseAlias.test.ts +1127 -0
- package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardInstallGuidance.test.tsx +1 -1
- package/Tests/UI/Monitor/EvaluationLogListTimestamps.test.tsx +367 -0
- package/Tests/UI/Utils/API/BaseAPIRefreshSession.test.ts +1087 -0
- package/Tests/UI/Utils/API/DashboardHost.ts +12 -0
- package/Tests/UI/Utils/API/FakeAxiosServer.ts +183 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +10 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
- package/Tests/UI/Utils/Cookie.test.ts +440 -0
- package/Tests/UI/Utils/ModelAPIRequestClient.test.ts +278 -0
- package/Tests/UI/Utils/Navigation.test.ts +33 -0
- package/Tests/UI/Utils/PricingPlan.test.ts +295 -0
- package/Tests/UI/Utils/Realtime.test.ts +759 -0
- package/Tests/UI/Utils/Telemetry/Telemetry.test.ts +500 -0
- package/Tests/Utils/APIInstanceDispatch.test.ts +311 -0
- package/Tests/Utils/HostAddressUtil.test.ts +138 -0
- package/Tests/Utils/Monitor/MonitorDestinationUtil.test.ts +313 -0
- package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +304 -0
- package/Tests/Utils/SecurityEvent/GoogleSecOpsAlertNormalizerSeverity.test.ts +565 -0
- package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +248 -0
- package/Types/API/Hostname.ts +63 -16
- package/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.ts +40 -0
- package/Types/Database/AccessControl/ColumnAccessControl.ts +19 -7
- package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +19 -7
- package/Types/Database/AccessControl/OwnerOnlyColumn.ts +15 -6
- package/Types/Database/CanonicalModelInstance.ts +102 -0
- package/Types/Database/TableColumn.ts +20 -6
- package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +29 -0
- package/Types/IP/IPv6.ts +6 -1
- package/Types/Monitor/MonitorEvaluationSummary.ts +3 -0
- package/Types/Monitor/MonitorStep.ts +6 -1
- package/Types/Monitor/ProxmoxAlertTemplates.ts +1 -1
- package/Types/OnCallDutyPolicy/ScheduleTimeline.ts +507 -0
- package/Types/OnCallDutyPolicy/ScheduleTimelineLayout.ts +589 -0
- package/Types/Realtime/EventName.ts +11 -0
- package/Types/SecurityEvent/DetectionFindingConstants.ts +14 -0
- package/Types/SecurityEvent/OcsfSeverity.ts +31 -26
- package/Types/SecurityEvent/SigmaRule.ts +51 -0
- package/Types/SecurityEvent/ThreatIntelConstants.ts +18 -0
- package/Types/StatusPage/UptimeDailyAggregate.ts +110 -0
- package/UI/Components/AttachmentList/EventAttachmentList.tsx +30 -2
- package/UI/Components/Dashboard/DashboardVariableControl.tsx +12 -2
- package/UI/Components/Dropdown/Dropdown.tsx +6 -1
- package/UI/Components/EditionLabel/EditionLabel.tsx +808 -1195
- package/UI/Components/EditionLabel/LicenseManager.ts +119 -0
- package/UI/Components/EventItem/EventItem.tsx +12 -1
- package/UI/Components/Forms/BasicForm.tsx +151 -126
- package/UI/Components/Forms/CollapsibleFormSection.tsx +63 -0
- package/UI/Components/Forms/Fields/FormField.tsx +10 -4
- package/UI/Components/Forms/FormSummary.tsx +7 -0
- package/UI/Components/Forms/Types/Field.ts +10 -0
- package/UI/Components/Graphs/DayUptimeGraph.tsx +123 -15
- package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +2 -1
- package/UI/Components/Markdown.tsx/SessionAwareImage.tsx +122 -0
- package/UI/Components/ModelList/ModelList.tsx +11 -1
- package/UI/Components/ModelTable/BaseModelTable.tsx +34 -5
- package/UI/Components/ModelTable/TableView.tsx +1 -1
- package/UI/Components/MonitorGraphs/Uptime.tsx +69 -0
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +28 -12
- package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +8 -1
- package/UI/Components/Tooltip/Tooltip.tsx +8 -1
- package/UI/Utils/API/API.ts +173 -12
- package/UI/Utils/API/RequestOptions.ts +11 -0
- package/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.ts +31 -7
- package/UI/Utils/ModelAPI/ModelAPI.ts +30 -9
- package/UI/Utils/Navigation.ts +9 -0
- package/UI/Utils/OpenAuthenticatedUrl.ts +154 -0
- package/UI/Utils/Realtime.ts +176 -30
- package/UI/esbuild-enterprise.js +263 -0
- package/Utils/API.ts +14 -5
- package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +7 -2
- package/Utils/HostAddressUtil.ts +94 -0
- package/Utils/Monitor/MonitorDestinationUtil.ts +157 -0
- package/Utils/Monitor/MonitoringIntervalUtil.ts +436 -0
- package/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.ts +157 -7
- package/Utils/SecurityEvent/Sigma/SigmaRuleParser.ts +9 -17
- package/Utils/Slo/SloBurnRateTemplate.ts +2 -2
- package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +192 -0
- package/build/dist/Models/AnalyticsModels/AuditLog.js +23 -15
- package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +25 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +2 -2
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorTemplate.js +2 -1
- package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js +1 -1
- package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js.map +1 -1
- package/build/dist/Server/API/AIBillingAPI.js +1 -1
- package/build/dist/Server/API/AIBillingAPI.js.map +1 -1
- package/build/dist/Server/API/AIInsightAPI.js +1 -4
- package/build/dist/Server/API/AIInsightAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +1 -4
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/AIReadinessAPI.js +1 -3
- package/build/dist/Server/API/AIReadinessAPI.js.map +1 -1
- package/build/dist/Server/API/AlertAPI.js +1 -1
- package/build/dist/Server/API/AlertAPI.js.map +1 -1
- package/build/dist/Server/API/AutoRemediationAPI.js +1 -4
- package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +33 -0
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/BaseAnalyticsAPI.js +55 -10
- package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
- package/build/dist/Server/API/BillingAPI.js +2 -2
- package/build/dist/Server/API/BillingAPI.js.map +1 -1
- package/build/dist/Server/API/BillingInvoiceAPI.js +1 -1
- package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
- package/build/dist/Server/API/BillingPaymentMethodAPI.js +2 -2
- package/build/dist/Server/API/BillingPaymentMethodAPI.js.map +1 -1
- package/build/dist/Server/API/CodeFixRunAPI.js +1 -3
- package/build/dist/Server/API/CodeFixRunAPI.js.map +1 -1
- package/build/dist/Server/API/CommonAPI.js +50 -5
- package/build/dist/Server/API/CommonAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +12 -12
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/GlobalConfigAPI.js +158 -342
- package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentAPI.js +2 -2
- package/build/dist/Server/API/IncidentAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentEpisodeAPI.js +1 -1
- package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
- package/build/dist/Server/API/NotificationAPI.js +1 -1
- package/build/dist/Server/API/NotificationAPI.js.map +1 -1
- package/build/dist/Server/API/OnCallCalendarAPI.js +1 -4
- package/build/dist/Server/API/OnCallCalendarAPI.js.map +1 -1
- package/build/dist/Server/API/OnCallDutyPolicyAPI.js +6 -0
- package/build/dist/Server/API/OnCallDutyPolicyAPI.js.map +1 -1
- package/build/dist/Server/API/OnCallReadinessAPI.js +4 -1
- package/build/dist/Server/API/OnCallReadinessAPI.js.map +1 -1
- package/build/dist/Server/API/OnCallScheduleTimelineAPI.js +494 -0
- package/build/dist/Server/API/OnCallScheduleTimelineAPI.js.map +1 -0
- package/build/dist/Server/API/ProjectAPI.js +1 -1
- package/build/dist/Server/API/ProjectAPI.js.map +1 -1
- package/build/dist/Server/API/ProjectOIDC.js +24 -16
- package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
- package/build/dist/Server/API/ProjectSSO.js +24 -16
- package/build/dist/Server/API/ProjectSSO.js.map +1 -1
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js +1 -1
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +218 -76
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/TeamMemberAPI.js +11 -4
- package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
- package/build/dist/Server/API/UserCallAPI.js +2 -2
- package/build/dist/Server/API/UserCallAPI.js.map +1 -1
- package/build/dist/Server/API/UserEmailAPI.js +2 -2
- package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js +2 -2
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
- package/build/dist/Server/API/UserMicrosoftTeamsAPI.js +1 -1
- package/build/dist/Server/API/UserMicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/UserSlackAPI.js +1 -1
- package/build/dist/Server/API/UserSlackAPI.js.map +1 -1
- package/build/dist/Server/API/UserSmsAPI.js +2 -2
- package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
- package/build/dist/Server/API/UserTotpAuthAPI.js +1 -1
- package/build/dist/Server/API/UserTotpAuthAPI.js.map +1 -1
- package/build/dist/Server/API/UserWebAuthnAPI.js +2 -2
- package/build/dist/Server/API/UserWebAuthnAPI.js.map +1 -1
- package/build/dist/Server/API/UserWebhookAPI.js +1 -1
- package/build/dist/Server/API/UserWebhookAPI.js.map +1 -1
- package/build/dist/Server/API/UserWhatsAppAPI.js +2 -2
- package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseEdition.js +466 -0
- package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -0
- package/build/dist/Server/Enterprise/EnterpriseFeature.js +39 -0
- package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -0
- package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +70 -0
- package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js.map +1 -0
- package/build/dist/Server/Enterprise/EnterpriseServerModule.js +84 -0
- package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -0
- package/build/dist/Server/EnvironmentConfig.js +84 -2
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/MasterAdminAuthorization.js +11 -2
- package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +94 -15
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Services/ApiKeyPermissionService.js +80 -4
- package/build/dist/Server/Services/ApiKeyPermissionService.js.map +1 -1
- package/build/dist/Server/Services/AuditLogService.js +71 -740
- package/build/dist/Server/Services/AuditLogService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +171 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DetectionRuleService.js +4 -4
- package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseService.js +34 -0
- package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
- package/build/dist/Server/Services/GlobalConfigService.js +63 -0
- package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
- package/build/dist/Server/Services/MonitorProbeService.js +90 -17
- package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +45 -4
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusTimelineService.js +242 -0
- package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +16 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyChildService.js +170 -0
- package/build/dist/Server/Services/OnCallDutyPolicyChildService.js.map +1 -0
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +2 -2
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +2 -2
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js +2 -2
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +2 -2
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
- package/build/dist/Server/Services/PayAsYouGoBillingService.js +20 -27
- package/build/dist/Server/Services/PayAsYouGoBillingService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +231 -0
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/RumSessionPinService.js +198 -16
- package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserService.js +7 -3
- package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +71 -0
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +10 -0
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/TeamPermissionService.js +89 -27
- package/build/dist/Server/Services/TeamPermissionService.js.map +1 -1
- package/build/dist/Server/Services/TeamService.js +9 -0
- package/build/dist/Server/Services/TeamService.js.map +1 -1
- package/build/dist/Server/Services/ThreatIntelFeedService.js +5 -4
- package/build/dist/Server/Services/ThreatIntelFeedService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +10 -16
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/BasePermission.js +9 -6
- package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +10 -0
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +154 -14
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/Index.js +60 -6
- package/build/dist/Server/Types/Database/Permissions/Index.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/TablePermission.js +24 -16
- package/build/dist/Server/Types/Database/Permissions/TablePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +17 -0
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
- package/build/dist/Server/Types/Markdown.js +31 -0
- package/build/dist/Server/Types/Markdown.js.map +1 -1
- package/build/dist/Server/Utils/AI/AIChatPrivacyFilter.js +7 -0
- package/build/dist/Server/Utils/AI/AIChatPrivacyFilter.js.map +1 -1
- package/build/dist/Server/Utils/AI/AIRunPrivacyFilter.js +7 -0
- package/build/dist/Server/Utils/AI/AIRunPrivacyFilter.js.map +1 -1
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js +223 -0
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +1 -0
- package/build/dist/Server/Utils/EditionEnforcement.js +187 -0
- package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -0
- package/build/dist/Server/Utils/FrontendEnvironment.js +31 -2
- package/build/dist/Server/Utils/FrontendEnvironment.js.map +1 -1
- package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js +6 -193
- package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js.map +1 -1
- package/build/dist/Server/Utils/MasterAdminPageAccess.js +39 -0
- package/build/dist/Server/Utils/MasterAdminPageAccess.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/AffectedResourceList.js +96 -0
- package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +3 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +449 -261
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +3 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js +88 -0
- package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js.map +1 -0
- package/build/dist/Server/Utils/Realtime.js +126 -37
- package/build/dist/Server/Utils/Realtime.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +7 -25
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.js +127 -0
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js +3 -2
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js +4 -8
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js +331 -11
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
- package/build/dist/Types/API/Hostname.js +59 -11
- package/build/dist/Types/API/Hostname.js.map +1 -1
- package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js +31 -1
- package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +19 -7
- package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +19 -7
- package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +13 -6
- package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -1
- package/build/dist/Types/Database/CanonicalModelInstance.js +88 -0
- package/build/dist/Types/Database/CanonicalModelInstance.js.map +1 -0
- package/build/dist/Types/Database/TableColumn.js +19 -6
- package/build/dist/Types/Database/TableColumn.js.map +1 -1
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +28 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js.map +1 -0
- package/build/dist/Types/IP/IPv6.js +6 -1
- package/build/dist/Types/IP/IPv6.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +5 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +1 -1
- package/build/dist/Types/OnCallDutyPolicy/ScheduleTimeline.js +321 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleTimeline.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleTimelineLayout.js +372 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleTimelineLayout.js.map +1 -0
- package/build/dist/Types/Realtime/EventName.js +10 -0
- package/build/dist/Types/Realtime/EventName.js.map +1 -1
- package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +11 -0
- package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
- package/build/dist/Types/SecurityEvent/OcsfSeverity.js +30 -25
- package/build/dist/Types/SecurityEvent/OcsfSeverity.js.map +1 -1
- package/build/dist/Types/SecurityEvent/SigmaRule.js +47 -0
- package/build/dist/Types/SecurityEvent/SigmaRule.js.map +1 -1
- package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js +14 -0
- package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js.map +1 -1
- package/build/dist/Types/StatusPage/UptimeDailyAggregate.js +32 -0
- package/build/dist/Types/StatusPage/UptimeDailyAggregate.js.map +1 -0
- package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js +9 -4
- package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js.map +1 -1
- package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js +10 -2
- package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js.map +1 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js +5 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +425 -585
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/LicenseManager.js +2 -0
- package/build/dist/UI/Components/EditionLabel/LicenseManager.js.map +1 -0
- package/build/dist/UI/Components/EventItem/EventItem.js +2 -2
- package/build/dist/UI/Components/EventItem/EventItem.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js +70 -64
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/CollapsibleFormSection.js +27 -0
- package/build/dist/UI/Components/Forms/CollapsibleFormSection.js.map +1 -0
- package/build/dist/UI/Components/Forms/Fields/FormField.js +10 -7
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Forms/FormSummary.js +7 -0
- package/build/dist/UI/Components/Forms/FormSummary.js.map +1 -1
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +90 -17
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +2 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/SessionAwareImage.js +84 -0
- package/build/dist/UI/Components/Markdown.tsx/SessionAwareImage.js.map +1 -0
- package/build/dist/UI/Components/ModelList/ModelList.js +4 -1
- package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +14 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/TableView.js +1 -1
- package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js +42 -1
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +2 -2
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +8 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js +2 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
- package/build/dist/UI/Utils/API/API.js +143 -19
- package/build/dist/UI/Utils/API/API.js.map +1 -1
- package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js +21 -7
- package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +26 -9
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +8 -0
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/UI/Utils/OpenAuthenticatedUrl.js +92 -0
- package/build/dist/UI/Utils/OpenAuthenticatedUrl.js.map +1 -0
- package/build/dist/UI/Utils/Realtime.js +120 -15
- package/build/dist/UI/Utils/Realtime.js.map +1 -1
- package/build/dist/Utils/API.js +13 -5
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +6 -2
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
- package/build/dist/Utils/HostAddressUtil.js +80 -0
- package/build/dist/Utils/HostAddressUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorDestinationUtil.js +127 -0
- package/build/dist/Utils/Monitor/MonitorDestinationUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js +374 -0
- package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js +123 -6
- package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js.map +1 -1
- package/build/dist/Utils/SecurityEvent/Sigma/SigmaRuleParser.js +4 -18
- package/build/dist/Utils/SecurityEvent/Sigma/SigmaRuleParser.js.map +1 -1
- package/build/dist/Utils/Slo/SloBurnRateTemplate.js +2 -2
- package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js +148 -0
- package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js.map +1 -0
- package/jest.config.json +3 -1
- package/package.json +1 -1
- package/test-setup.sh +103 -34
- package/tsconfig.json +13 -0
- package/Server/API/EnterpriseLicenseAPI.ts +0 -925
- package/Server/API/TeamComplianceAPI.ts +0 -158
- package/Server/Middleware/SCIMAuthorization.ts +0 -141
- package/Server/Services/TeamComplianceService.ts +0 -733
- package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +0 -186
- package/Server/Utils/InstanceHealth/PostgresHealth.ts +0 -286
- package/Tests/App/AdminDashboard/EnterpriseLicenseInstanceActivity.test.tsx +0 -451
- package/Tests/App/Dashboard/AuditLogsTable.test.tsx +0 -598
- package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +0 -247
- package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +0 -382
- package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +0 -1851
- package/Tests/Server/Middleware/SCIMAuthorization.test.ts +0 -525
- package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +0 -1845
- package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +0 -495
- package/Tests/Server/Utils/InstanceHealth/PostgresHealth.test.ts +0 -337
- package/Tests/Utils/EnterpriseLicenseSeats.test.ts +0 -576
- package/Tests/Utils/EnterpriseLicenseSync.test.ts +0 -568
- package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +0 -287
- package/Utils/EnterpriseLicense/EnterpriseLicenseSync.ts +0 -244
- package/build/dist/Server/API/EnterpriseLicenseAPI.js +0 -646
- package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +0 -1
- package/build/dist/Server/API/TeamComplianceAPI.js +0 -111
- package/build/dist/Server/API/TeamComplianceAPI.js.map +0 -1
- package/build/dist/Server/Middleware/SCIMAuthorization.js +0 -124
- package/build/dist/Server/Middleware/SCIMAuthorization.js.map +0 -1
- package/build/dist/Server/Services/TeamComplianceService.js +0 -537
- package/build/dist/Server/Services/TeamComplianceService.js.map +0 -1
- package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +0 -145
- package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +0 -1
- package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js +0 -194
- package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js.map +0 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +0 -168
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +0 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js +0 -174
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js.map +0 -1
|
@@ -0,0 +1,820 @@
|
|
|
1
|
+
import { mockRouter } from "./Helpers";
|
|
2
|
+
import AIBillingRouter from "../../../Server/API/AIBillingAPI";
|
|
3
|
+
import AlertAPI from "../../../Server/API/AlertAPI";
|
|
4
|
+
import BillingAPI from "../../../Server/API/BillingAPI";
|
|
5
|
+
import BillingInvoiceAPI from "../../../Server/API/BillingInvoiceAPI";
|
|
6
|
+
import BillingPaymentMethodAPI from "../../../Server/API/BillingPaymentMethodAPI";
|
|
7
|
+
import IncidentAPI from "../../../Server/API/IncidentAPI";
|
|
8
|
+
import IncidentEpisodeAPI from "../../../Server/API/IncidentEpisodeAPI";
|
|
9
|
+
import NotificationRouter from "../../../Server/API/NotificationAPI";
|
|
10
|
+
import ProjectAPI from "../../../Server/API/ProjectAPI";
|
|
11
|
+
import ScheduledMaintenanceAPI from "../../../Server/API/ScheduledMaintenanceAPI";
|
|
12
|
+
import TeamMemberAPI from "../../../Server/API/TeamMemberAPI";
|
|
13
|
+
import UserCallAPI from "../../../Server/API/UserCallAPI";
|
|
14
|
+
import UserEmailAPI from "../../../Server/API/UserEmailAPI";
|
|
15
|
+
import UserIncomingCallNumberAPI from "../../../Server/API/UserIncomingCallNumberAPI";
|
|
16
|
+
import UserMicrosoftTeamsAPI from "../../../Server/API/UserMicrosoftTeamsAPI";
|
|
17
|
+
import UserSlackAPI from "../../../Server/API/UserSlackAPI";
|
|
18
|
+
import UserSmsAPI from "../../../Server/API/UserSmsAPI";
|
|
19
|
+
import UserTotpAuthAPI from "../../../Server/API/UserTotpAuthAPI";
|
|
20
|
+
import UserWebAuthnAPI from "../../../Server/API/UserWebAuthnAPI";
|
|
21
|
+
import UserWebhookAPI from "../../../Server/API/UserWebhookAPI";
|
|
22
|
+
import UserWhatsAppAPI from "../../../Server/API/UserWhatsAppAPI";
|
|
23
|
+
import UserMiddleware from "../../../Server/Middleware/UserAuthorization";
|
|
24
|
+
import VerificationCodeRateLimit, {
|
|
25
|
+
VerificationCodeRateLimitBucket,
|
|
26
|
+
} from "../../../Server/Middleware/VerificationCodeRateLimit";
|
|
27
|
+
import ProjectService from "../../../Server/Services/ProjectService";
|
|
28
|
+
import TeamMemberService from "../../../Server/Services/TeamMemberService";
|
|
29
|
+
import {
|
|
30
|
+
ExpressRequest,
|
|
31
|
+
ExpressResponse,
|
|
32
|
+
NextFunction,
|
|
33
|
+
OneUptimeRequest,
|
|
34
|
+
} from "../../../Server/Utils/Express";
|
|
35
|
+
import Response from "../../../Server/Utils/Response";
|
|
36
|
+
import Dictionary from "../../../Types/Dictionary";
|
|
37
|
+
import Exception from "../../../Types/Exception/Exception";
|
|
38
|
+
import ExceptionCode from "../../../Types/Exception/ExceptionCode";
|
|
39
|
+
import NotAuthenticatedException from "../../../Types/Exception/NotAuthenticatedException";
|
|
40
|
+
import JSONWebTokenData from "../../../Types/JsonWebTokenData";
|
|
41
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
42
|
+
import UserType from "../../../Types/UserType";
|
|
43
|
+
import {
|
|
44
|
+
afterEach,
|
|
45
|
+
beforeAll,
|
|
46
|
+
beforeEach,
|
|
47
|
+
describe,
|
|
48
|
+
expect,
|
|
49
|
+
test,
|
|
50
|
+
} from "@jest/globals";
|
|
51
|
+
|
|
52
|
+
/*
|
|
53
|
+
* Every custom route that gained UserMiddleware.requireUserAuthentication in
|
|
54
|
+
* the expired-session fix, in one table.
|
|
55
|
+
*
|
|
56
|
+
* THE BUG
|
|
57
|
+
*
|
|
58
|
+
* A customer left the Dashboard open for more than 15 minutes, clicked a
|
|
59
|
+
* button, and was told "You are not authorized to access this project's
|
|
60
|
+
* data." The access-token cookie's maxAge is the JWT's own lifetime, so the
|
|
61
|
+
* browser had dropped it and the request arrived with no token at all.
|
|
62
|
+
* getUserMiddleware does not refuse that request - it marks it UserType.Public
|
|
63
|
+
* and calls next(), because some routes are meant to be anonymous - and each
|
|
64
|
+
* of these handlers then refused it in its own words: a 422, a 400, or worse,
|
|
65
|
+
* a root read that answered with nothing. The browser client only refreshes
|
|
66
|
+
* the session and replays the request on a 401, so every one of those
|
|
67
|
+
* surfaced as a hard error instead of a silent refresh.
|
|
68
|
+
*
|
|
69
|
+
* THE FIX, AS IT APPEARS ON THE ROUTER
|
|
70
|
+
*
|
|
71
|
+
* requireUserAuthentication sits IMMEDIATELY after getUserMiddleware on each
|
|
72
|
+
* of these routes. Immediately, because:
|
|
73
|
+
*
|
|
74
|
+
* - before getUserMiddleware there is no userType to look at, so it would
|
|
75
|
+
* refuse everybody;
|
|
76
|
+
* - on the verification-code routes the VerificationCodeRateLimit limiter
|
|
77
|
+
* must come AFTER it. The limiter spends item and IP budgets as soon as
|
|
78
|
+
* it runs, so running it first would let a stale tab burn a user's
|
|
79
|
+
* attempts on requests that were going to be refused anyway, and a
|
|
80
|
+
* limited request would be answered with a 429 - also not a cue to
|
|
81
|
+
* refresh.
|
|
82
|
+
*
|
|
83
|
+
* WHY A TABLE
|
|
84
|
+
*
|
|
85
|
+
* Twenty-odd routes across nineteen files, each an independent one-line
|
|
86
|
+
* registration. Dropping the guard from one of them breaks nothing that the
|
|
87
|
+
* route's own tests would notice - they call the handler directly - and the
|
|
88
|
+
* symptom only appears for a user whose tab has been idle for a quarter of an
|
|
89
|
+
* hour. So each route is named here, located on the router the API class (or
|
|
90
|
+
* module) actually registered it on, and its middleware list is asserted by
|
|
91
|
+
* identity.
|
|
92
|
+
*
|
|
93
|
+
* Then the chain is RUN for every route with the request an idle tab really
|
|
94
|
+
* sends: no cookie, no API key, but the tenantid header the Dashboard always
|
|
95
|
+
* attaches. getUserMiddleware is the real one, so the test also proves the
|
|
96
|
+
* premise - that such a request reaches the guard as Public rather than
|
|
97
|
+
* being refused earlier - and the guard must answer it with a 401 before the
|
|
98
|
+
* limiter or the handler is reached.
|
|
99
|
+
*/
|
|
100
|
+
|
|
101
|
+
jest.mock("../../../Server/Utils/Express", () => {
|
|
102
|
+
return {
|
|
103
|
+
getRouter: () => {
|
|
104
|
+
return mockRouter;
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
jest.mock("../../../Server/Utils/Response", () => {
|
|
110
|
+
return {
|
|
111
|
+
sendEntityArrayResponse: jest.fn(),
|
|
112
|
+
sendJsonArrayResponse: jest.fn(),
|
|
113
|
+
sendJsonObjectResponse: jest.fn(),
|
|
114
|
+
sendEmptySuccessResponse: jest.fn(),
|
|
115
|
+
sendEntityResponse: jest.fn(),
|
|
116
|
+
sendErrorResponse: jest.fn(),
|
|
117
|
+
sendFileResponse: jest.fn(),
|
|
118
|
+
setNoCacheHeaders: jest.fn(),
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const AUTHENTICATION_REQUIRED_MESSAGE: string =
|
|
123
|
+
"Authentication required. Please log in to access this resource.";
|
|
124
|
+
|
|
125
|
+
const PROJECT_ID: string = "11111111-1111-4111-8111-111111111111";
|
|
126
|
+
const USER_ID: ObjectID = new ObjectID("22222222-2222-4222-8222-222222222222");
|
|
127
|
+
const ROW_ID: string = "33333333-3333-4333-8333-333333333333";
|
|
128
|
+
|
|
129
|
+
type HttpMethod = "GET" | "POST" | "PUT";
|
|
130
|
+
|
|
131
|
+
type GuardedRoute = {
|
|
132
|
+
method: HttpMethod;
|
|
133
|
+
|
|
134
|
+
// Relative to /api, exactly as the router registers it.
|
|
135
|
+
uri: string;
|
|
136
|
+
|
|
137
|
+
// Where the route is registered, for the test names.
|
|
138
|
+
registeredBy: string;
|
|
139
|
+
|
|
140
|
+
// Set only for the routes that also carry a verification-code limiter.
|
|
141
|
+
limiter?: VerificationCodeRateLimitBucket | undefined;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const GUARDED_ROUTES: Array<GuardedRoute> = [
|
|
145
|
+
// Credit top-ups.
|
|
146
|
+
{
|
|
147
|
+
method: "POST",
|
|
148
|
+
uri: "/notification/recharge",
|
|
149
|
+
registeredBy: "NotificationAPI",
|
|
150
|
+
},
|
|
151
|
+
{ method: "POST", uri: "/ai/recharge", registeredBy: "AIBillingAPI" },
|
|
152
|
+
|
|
153
|
+
// "Send a test message" buttons on the user's notification settings.
|
|
154
|
+
{ method: "POST", uri: "/user-slack/test", registeredBy: "UserSlackAPI" },
|
|
155
|
+
{
|
|
156
|
+
method: "POST",
|
|
157
|
+
uri: "/user-microsoft-teams/test",
|
|
158
|
+
registeredBy: "UserMicrosoftTeamsAPI",
|
|
159
|
+
},
|
|
160
|
+
{ method: "POST", uri: "/user-webhook/test", registeredBy: "UserWebhookAPI" },
|
|
161
|
+
|
|
162
|
+
// Security key enrolment.
|
|
163
|
+
{
|
|
164
|
+
method: "POST",
|
|
165
|
+
uri: "/user-webauthn/generate-registration-options",
|
|
166
|
+
registeredBy: "UserWebAuthnAPI",
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
method: "POST",
|
|
170
|
+
uri: "/user-webauthn/verify-registration",
|
|
171
|
+
registeredBy: "UserWebAuthnAPI",
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
// Contact-method verification, each behind a verification-code limiter.
|
|
175
|
+
{
|
|
176
|
+
method: "POST",
|
|
177
|
+
uri: "/user-incoming-call-number/verify",
|
|
178
|
+
registeredBy: "UserIncomingCallNumberAPI",
|
|
179
|
+
limiter: VerificationCodeRateLimitBucket.Verify,
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
method: "POST",
|
|
183
|
+
uri: "/user-incoming-call-number/resend-verification-code",
|
|
184
|
+
registeredBy: "UserIncomingCallNumberAPI",
|
|
185
|
+
limiter: VerificationCodeRateLimitBucket.Resend,
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
method: "POST",
|
|
189
|
+
uri: "/user-sms/verify",
|
|
190
|
+
registeredBy: "UserSmsAPI",
|
|
191
|
+
limiter: VerificationCodeRateLimitBucket.Verify,
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
method: "POST",
|
|
195
|
+
uri: "/user-sms/resend-verification-code",
|
|
196
|
+
registeredBy: "UserSmsAPI",
|
|
197
|
+
limiter: VerificationCodeRateLimitBucket.Resend,
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
method: "POST",
|
|
201
|
+
uri: "/user-call/verify",
|
|
202
|
+
registeredBy: "UserCallAPI",
|
|
203
|
+
limiter: VerificationCodeRateLimitBucket.Verify,
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
method: "POST",
|
|
207
|
+
uri: "/user-call/resend-verification-code",
|
|
208
|
+
registeredBy: "UserCallAPI",
|
|
209
|
+
limiter: VerificationCodeRateLimitBucket.Resend,
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
method: "POST",
|
|
213
|
+
uri: "/user-email/verify",
|
|
214
|
+
registeredBy: "UserEmailAPI",
|
|
215
|
+
limiter: VerificationCodeRateLimitBucket.Verify,
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
method: "POST",
|
|
219
|
+
uri: "/user-email/resend-verification-code",
|
|
220
|
+
registeredBy: "UserEmailAPI",
|
|
221
|
+
limiter: VerificationCodeRateLimitBucket.Resend,
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
method: "POST",
|
|
225
|
+
uri: "/user-whatsapp/verify",
|
|
226
|
+
registeredBy: "UserWhatsAppAPI",
|
|
227
|
+
limiter: VerificationCodeRateLimitBucket.Verify,
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
method: "POST",
|
|
231
|
+
uri: "/user-whatsapp/resend-verification-code",
|
|
232
|
+
registeredBy: "UserWhatsAppAPI",
|
|
233
|
+
limiter: VerificationCodeRateLimitBucket.Resend,
|
|
234
|
+
},
|
|
235
|
+
|
|
236
|
+
// Authenticator app enrolment.
|
|
237
|
+
{
|
|
238
|
+
method: "POST",
|
|
239
|
+
uri: "/user-totp-auth/validate",
|
|
240
|
+
registeredBy: "UserTotpAuthAPI",
|
|
241
|
+
},
|
|
242
|
+
|
|
243
|
+
// Team membership.
|
|
244
|
+
{
|
|
245
|
+
method: "POST",
|
|
246
|
+
uri: "/team-member/is-user-registered",
|
|
247
|
+
registeredBy: "TeamMemberAPI",
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
method: "POST",
|
|
251
|
+
uri: "/team-member/remove-user-from-project",
|
|
252
|
+
registeredBy: "TeamMemberAPI",
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
method: "POST",
|
|
256
|
+
uri: "/team-member/:id/leave",
|
|
257
|
+
registeredBy: "TeamMemberAPI",
|
|
258
|
+
},
|
|
259
|
+
|
|
260
|
+
// Billing.
|
|
261
|
+
{
|
|
262
|
+
method: "POST",
|
|
263
|
+
uri: "/billing-payment-methods/setup",
|
|
264
|
+
registeredBy: "BillingPaymentMethodAPI",
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
method: "POST",
|
|
268
|
+
uri: "/billing-payment-methods/set-default",
|
|
269
|
+
registeredBy: "BillingPaymentMethodAPI",
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
method: "GET",
|
|
273
|
+
uri: "/billing/pay-as-you-go-status",
|
|
274
|
+
registeredBy: "BillingAPI",
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
method: "GET",
|
|
278
|
+
uri: "/billing/customer-balance",
|
|
279
|
+
registeredBy: "BillingAPI",
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
method: "POST",
|
|
283
|
+
uri: "/billing-invoices/pay",
|
|
284
|
+
registeredBy: "BillingInvoiceAPI",
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
method: "PUT",
|
|
288
|
+
uri: "/project/:id/change-plan",
|
|
289
|
+
registeredBy: "ProjectAPI",
|
|
290
|
+
},
|
|
291
|
+
|
|
292
|
+
// "Generate with AI" buttons.
|
|
293
|
+
{
|
|
294
|
+
method: "POST",
|
|
295
|
+
uri: "/incident/generate-postmortem-from-ai/:incidentId",
|
|
296
|
+
registeredBy: "IncidentAPI",
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
method: "POST",
|
|
300
|
+
uri: "/incident/generate-note-from-ai/:incidentId",
|
|
301
|
+
registeredBy: "IncidentAPI",
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
method: "POST",
|
|
305
|
+
uri: "/alert/generate-note-from-ai/:alertId",
|
|
306
|
+
registeredBy: "AlertAPI",
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
method: "POST",
|
|
310
|
+
uri: "/incident-episode/generate-postmortem-from-ai/:episodeId",
|
|
311
|
+
registeredBy: "IncidentEpisodeAPI",
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
method: "POST",
|
|
315
|
+
uri: "/scheduled-maintenance/generate-note-from-ai/:scheduledMaintenanceId",
|
|
316
|
+
registeredBy: "ScheduledMaintenanceAPI",
|
|
317
|
+
},
|
|
318
|
+
];
|
|
319
|
+
|
|
320
|
+
type RecordedRoute = ReturnType<typeof mockRouter.match>;
|
|
321
|
+
|
|
322
|
+
type RouterFunction = RecordedRoute["handlerFunction"];
|
|
323
|
+
|
|
324
|
+
type FindRouteFunction = (route: GuardedRoute) => RecordedRoute;
|
|
325
|
+
|
|
326
|
+
const findRoute: FindRouteFunction = (route: GuardedRoute): RecordedRoute => {
|
|
327
|
+
return mockRouter.match(route.method, route.uri);
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
/*
|
|
331
|
+
* Every limiter the API classes were built with, mapped to its bucket.
|
|
332
|
+
* getMiddleware returns a fresh closure per route, so this is the only way to
|
|
333
|
+
* tell "the limiter" apart from any other function by identity.
|
|
334
|
+
*/
|
|
335
|
+
const limiterBuckets: Map<unknown, VerificationCodeRateLimitBucket> = new Map<
|
|
336
|
+
unknown,
|
|
337
|
+
VerificationCodeRateLimitBucket
|
|
338
|
+
>();
|
|
339
|
+
|
|
340
|
+
beforeAll(() => {
|
|
341
|
+
const realGetMiddleware: typeof VerificationCodeRateLimit.getMiddleware =
|
|
342
|
+
VerificationCodeRateLimit.getMiddleware.bind(VerificationCodeRateLimit);
|
|
343
|
+
|
|
344
|
+
const capture: jest.SpyInstance = jest
|
|
345
|
+
.spyOn(VerificationCodeRateLimit, "getMiddleware")
|
|
346
|
+
.mockImplementation(((bucket: VerificationCodeRateLimitBucket) => {
|
|
347
|
+
const limiter: ReturnType<
|
|
348
|
+
typeof VerificationCodeRateLimit.getMiddleware
|
|
349
|
+
> = realGetMiddleware(bucket);
|
|
350
|
+
limiterBuckets.set(limiter, bucket);
|
|
351
|
+
return limiter;
|
|
352
|
+
}) as never);
|
|
353
|
+
|
|
354
|
+
/*
|
|
355
|
+
* NotificationAPI and AIBillingAPI register at import time on a module-level
|
|
356
|
+
* router, so their routes are already on the recorder. mockRouter.routes is
|
|
357
|
+
* therefore NOT cleared here.
|
|
358
|
+
*/
|
|
359
|
+
new UserSlackAPI();
|
|
360
|
+
new UserMicrosoftTeamsAPI();
|
|
361
|
+
new UserWebhookAPI();
|
|
362
|
+
new UserWebAuthnAPI();
|
|
363
|
+
new UserIncomingCallNumberAPI();
|
|
364
|
+
new UserSmsAPI();
|
|
365
|
+
new UserCallAPI();
|
|
366
|
+
new UserEmailAPI();
|
|
367
|
+
new UserWhatsAppAPI();
|
|
368
|
+
new UserTotpAuthAPI();
|
|
369
|
+
new TeamMemberAPI();
|
|
370
|
+
new BillingPaymentMethodAPI();
|
|
371
|
+
new BillingAPI();
|
|
372
|
+
new BillingInvoiceAPI();
|
|
373
|
+
new ProjectAPI();
|
|
374
|
+
new IncidentAPI();
|
|
375
|
+
new IncidentEpisodeAPI();
|
|
376
|
+
new AlertAPI();
|
|
377
|
+
new ScheduledMaintenanceAPI();
|
|
378
|
+
|
|
379
|
+
capture.mockRestore();
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
afterEach(() => {
|
|
383
|
+
jest.restoreAllMocks();
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
describe("the harness", () => {
|
|
387
|
+
/*
|
|
388
|
+
* The two module-level routers are the ones most likely to be recorded
|
|
389
|
+
* somewhere other than here, so prove they are the recorder before
|
|
390
|
+
* trusting anything the table says about them.
|
|
391
|
+
*/
|
|
392
|
+
test("the module-level routers are the recorder this file reads", () => {
|
|
393
|
+
expect(NotificationRouter).toBe(mockRouter);
|
|
394
|
+
expect(AIBillingRouter).toBe(mockRouter);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
test("captured a limiter for each verification-code route", () => {
|
|
398
|
+
const limiterRoutes: Array<GuardedRoute> = GUARDED_ROUTES.filter(
|
|
399
|
+
(route: GuardedRoute): boolean => {
|
|
400
|
+
return Boolean(route.limiter);
|
|
401
|
+
},
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
expect(limiterRoutes).toHaveLength(10);
|
|
405
|
+
expect(limiterBuckets.size).toBeGreaterThanOrEqual(limiterRoutes.length);
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
/*
|
|
409
|
+
* mockRouter.match returns the FIRST registration of a method and path, so
|
|
410
|
+
* a second registration of the same route - one with the guard, one
|
|
411
|
+
* without - would hide behind it. Each must be registered exactly once.
|
|
412
|
+
*/
|
|
413
|
+
test.each(GUARDED_ROUTES)(
|
|
414
|
+
"$method $uri ($registeredBy) is registered exactly once",
|
|
415
|
+
(route: GuardedRoute) => {
|
|
416
|
+
const registrations: Array<RecordedRoute> = mockRouter.routes.filter(
|
|
417
|
+
(recorded: RecordedRoute): boolean => {
|
|
418
|
+
return recorded.method === route.method && recorded.uri === route.uri;
|
|
419
|
+
},
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
expect(registrations).toHaveLength(1);
|
|
423
|
+
},
|
|
424
|
+
);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
describe("middleware order on every guarded route", () => {
|
|
428
|
+
test.each(GUARDED_ROUTES)(
|
|
429
|
+
"$method $uri ($registeredBy) resolves the session, then requires it",
|
|
430
|
+
(route: GuardedRoute) => {
|
|
431
|
+
const middlewares: Array<RouterFunction> = findRoute(route).middlewares;
|
|
432
|
+
|
|
433
|
+
expect(middlewares[0]).toBe(UserMiddleware.getUserMiddleware);
|
|
434
|
+
expect(middlewares[1]).toBe(UserMiddleware.requireUserAuthentication);
|
|
435
|
+
|
|
436
|
+
// Exactly once: a second copy further down would mean a mis-edit.
|
|
437
|
+
expect(
|
|
438
|
+
middlewares.filter((middleware: RouterFunction): boolean => {
|
|
439
|
+
return (
|
|
440
|
+
(middleware as unknown) ===
|
|
441
|
+
(UserMiddleware.requireUserAuthentication as unknown)
|
|
442
|
+
);
|
|
443
|
+
}),
|
|
444
|
+
).toHaveLength(1);
|
|
445
|
+
|
|
446
|
+
// The guard is middleware, never the handler itself.
|
|
447
|
+
expect(findRoute(route).handlerFunction).not.toBe(
|
|
448
|
+
UserMiddleware.requireUserAuthentication,
|
|
449
|
+
);
|
|
450
|
+
},
|
|
451
|
+
);
|
|
452
|
+
|
|
453
|
+
const limiterRoutes: Array<GuardedRoute> = GUARDED_ROUTES.filter(
|
|
454
|
+
(route: GuardedRoute): boolean => {
|
|
455
|
+
return Boolean(route.limiter);
|
|
456
|
+
},
|
|
457
|
+
);
|
|
458
|
+
|
|
459
|
+
test.each(limiterRoutes)(
|
|
460
|
+
"$method $uri ($registeredBy) runs its $limiter limiter only after the guard",
|
|
461
|
+
(route: GuardedRoute) => {
|
|
462
|
+
const middlewares: Array<RouterFunction> = findRoute(route).middlewares;
|
|
463
|
+
|
|
464
|
+
const guardIndex: number = middlewares.indexOf(
|
|
465
|
+
UserMiddleware.requireUserAuthentication as unknown as RouterFunction,
|
|
466
|
+
);
|
|
467
|
+
|
|
468
|
+
const limiterIndexes: Array<number> = middlewares
|
|
469
|
+
.map((middleware: RouterFunction, index: number): number => {
|
|
470
|
+
return limiterBuckets.has(middleware) ? index : -1;
|
|
471
|
+
})
|
|
472
|
+
.filter((index: number): boolean => {
|
|
473
|
+
return index >= 0;
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
expect(guardIndex).toBe(1);
|
|
477
|
+
expect(limiterIndexes).toEqual([2]);
|
|
478
|
+
expect(limiterBuckets.get(middlewares[2])).toBe(route.limiter);
|
|
479
|
+
},
|
|
480
|
+
);
|
|
481
|
+
|
|
482
|
+
test.each(
|
|
483
|
+
GUARDED_ROUTES.filter((route: GuardedRoute): boolean => {
|
|
484
|
+
return !route.limiter;
|
|
485
|
+
}),
|
|
486
|
+
)(
|
|
487
|
+
"$method $uri ($registeredBy) carries no verification-code limiter",
|
|
488
|
+
(route: GuardedRoute) => {
|
|
489
|
+
const middlewares: Array<RouterFunction> = findRoute(route).middlewares;
|
|
490
|
+
|
|
491
|
+
expect(
|
|
492
|
+
middlewares.some((middleware: RouterFunction): boolean => {
|
|
493
|
+
return limiterBuckets.has(middleware);
|
|
494
|
+
}),
|
|
495
|
+
).toBe(false);
|
|
496
|
+
},
|
|
497
|
+
);
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
type ChainResult = {
|
|
501
|
+
// Index of the middleware that answered instead of calling next(), or -1.
|
|
502
|
+
stoppedAt: number;
|
|
503
|
+
reachedHandler: boolean;
|
|
504
|
+
sentError: Exception | undefined;
|
|
505
|
+
sendErrorCallCount: number;
|
|
506
|
+
request: OneUptimeRequest;
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
type RunChainFunction = (data: {
|
|
510
|
+
route: GuardedRoute;
|
|
511
|
+
request: Dictionary<unknown>;
|
|
512
|
+
runHandler?: boolean | undefined;
|
|
513
|
+
}) => Promise<ChainResult>;
|
|
514
|
+
|
|
515
|
+
/*
|
|
516
|
+
* Runs the recorded middlewares in order, from getUserMiddleware, the way
|
|
517
|
+
* Express would, and stops at the first one that answers instead of calling
|
|
518
|
+
* next(). The handler is only invoked when asked for and only if every
|
|
519
|
+
* middleware let the request through.
|
|
520
|
+
*/
|
|
521
|
+
const runChain: RunChainFunction = async (data: {
|
|
522
|
+
route: GuardedRoute;
|
|
523
|
+
request: Dictionary<unknown>;
|
|
524
|
+
runHandler?: boolean | undefined;
|
|
525
|
+
}): Promise<ChainResult> => {
|
|
526
|
+
const recorded: RecordedRoute = findRoute(data.route);
|
|
527
|
+
|
|
528
|
+
const req: OneUptimeRequest = {
|
|
529
|
+
params: {},
|
|
530
|
+
query: {},
|
|
531
|
+
body: {},
|
|
532
|
+
cookies: {},
|
|
533
|
+
...data.request,
|
|
534
|
+
} as unknown as OneUptimeRequest;
|
|
535
|
+
|
|
536
|
+
const res: ExpressResponse = {
|
|
537
|
+
status: jest.fn().mockReturnThis(),
|
|
538
|
+
json: jest.fn().mockReturnThis(),
|
|
539
|
+
send: jest.fn().mockReturnThis(),
|
|
540
|
+
set: jest.fn().mockReturnThis(),
|
|
541
|
+
setHeader: jest.fn().mockReturnThis(),
|
|
542
|
+
} as unknown as ExpressResponse;
|
|
543
|
+
|
|
544
|
+
let stoppedAt: number = -1;
|
|
545
|
+
|
|
546
|
+
for (let index: number = 0; index < recorded.middlewares.length; index++) {
|
|
547
|
+
const next: jest.Mock = jest.fn();
|
|
548
|
+
|
|
549
|
+
await recorded.middlewares[index]!(
|
|
550
|
+
req as ExpressRequest,
|
|
551
|
+
res,
|
|
552
|
+
next as unknown as NextFunction,
|
|
553
|
+
);
|
|
554
|
+
|
|
555
|
+
if (next.mock.calls.length === 0) {
|
|
556
|
+
stoppedAt = index;
|
|
557
|
+
break;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const reachedHandler: boolean = stoppedAt === -1;
|
|
562
|
+
|
|
563
|
+
if (reachedHandler && data.runHandler) {
|
|
564
|
+
await recorded.handlerFunction(
|
|
565
|
+
req as ExpressRequest,
|
|
566
|
+
res,
|
|
567
|
+
jest.fn() as unknown as NextFunction,
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
const errorCalls: Array<Array<unknown>> = (
|
|
572
|
+
Response.sendErrorResponse as unknown as jest.Mock
|
|
573
|
+
).mock.calls as Array<Array<unknown>>;
|
|
574
|
+
|
|
575
|
+
return {
|
|
576
|
+
stoppedAt: stoppedAt,
|
|
577
|
+
reachedHandler: reachedHandler,
|
|
578
|
+
sentError: errorCalls[0]?.[2] as Exception | undefined,
|
|
579
|
+
sendErrorCallCount: errorCalls.length,
|
|
580
|
+
request: req,
|
|
581
|
+
};
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
/*
|
|
585
|
+
* What a Dashboard tab sends once its access-token cookie has expired: the
|
|
586
|
+
* tenantid header it always attaches, no cookie, no Authorization header, no
|
|
587
|
+
* apikey. The params fill every route parameter in the table with a
|
|
588
|
+
* well-formed id so nothing fails on the path before it fails on the session.
|
|
589
|
+
*/
|
|
590
|
+
const EXPIRED_SESSION_REQUEST: Dictionary<unknown> = {
|
|
591
|
+
headers: { tenantid: PROJECT_ID, "user-agent": "jest" },
|
|
592
|
+
params: {
|
|
593
|
+
id: PROJECT_ID,
|
|
594
|
+
incidentId: ROW_ID,
|
|
595
|
+
alertId: ROW_ID,
|
|
596
|
+
episodeId: ROW_ID,
|
|
597
|
+
scheduledMaintenanceId: ROW_ID,
|
|
598
|
+
},
|
|
599
|
+
body: { itemId: ROW_ID, code: "123456", userId: USER_ID.toString() },
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
describe("an expired session on every guarded route", () => {
|
|
603
|
+
let consumeSpy: jest.SpyInstance;
|
|
604
|
+
|
|
605
|
+
beforeEach(() => {
|
|
606
|
+
jest.clearAllMocks();
|
|
607
|
+
|
|
608
|
+
/*
|
|
609
|
+
* getUserMiddleware records the tenant's last-active time fire-and-forget
|
|
610
|
+
* whenever a tenantid header is present. Stubbed so the anonymous request
|
|
611
|
+
* never reaches Postgres.
|
|
612
|
+
*/
|
|
613
|
+
jest
|
|
614
|
+
.spyOn(ProjectService, "updateLastActive")
|
|
615
|
+
.mockResolvedValue(undefined as never);
|
|
616
|
+
|
|
617
|
+
/*
|
|
618
|
+
* If the guard ever slips behind a limiter, the limiter would run here.
|
|
619
|
+
* Stubbed so that shows up as a spent-budget assertion failure rather
|
|
620
|
+
* than as a Redis connection error.
|
|
621
|
+
*/
|
|
622
|
+
consumeSpy = jest
|
|
623
|
+
.spyOn(VerificationCodeRateLimit, "consume")
|
|
624
|
+
.mockResolvedValue({ outcome: "allowed" } as never);
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
test.each(GUARDED_ROUTES)(
|
|
628
|
+
"$method $uri ($registeredBy) answers 401 at the guard, before anything else runs",
|
|
629
|
+
async (route: GuardedRoute) => {
|
|
630
|
+
const result: ChainResult = await runChain({
|
|
631
|
+
route: route,
|
|
632
|
+
request: EXPIRED_SESSION_REQUEST,
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
// The premise: getUserMiddleware let the request through as Public.
|
|
636
|
+
expect(result.request.userType).toBe(UserType.Public);
|
|
637
|
+
|
|
638
|
+
// The fix: the guard, at index 1, answered it.
|
|
639
|
+
expect(result.stoppedAt).toBe(1);
|
|
640
|
+
expect(result.reachedHandler).toBe(false);
|
|
641
|
+
expect(result.sendErrorCallCount).toBe(1);
|
|
642
|
+
expect(result.sentError).toBeInstanceOf(NotAuthenticatedException);
|
|
643
|
+
expect(result.sentError?.code).toBe(
|
|
644
|
+
ExceptionCode.NotAuthenticatedException,
|
|
645
|
+
);
|
|
646
|
+
expect(result.sentError?.message).toBe(AUTHENTICATION_REQUIRED_MESSAGE);
|
|
647
|
+
|
|
648
|
+
// Nothing downstream spent anything.
|
|
649
|
+
expect(consumeSpy).not.toHaveBeenCalled();
|
|
650
|
+
},
|
|
651
|
+
);
|
|
652
|
+
|
|
653
|
+
/*
|
|
654
|
+
* The same request without the tenantid header - a call the page makes
|
|
655
|
+
* before a project is selected - must get the same 401, not a
|
|
656
|
+
* "project required" answer.
|
|
657
|
+
*/
|
|
658
|
+
test.each(GUARDED_ROUTES)(
|
|
659
|
+
"$method $uri ($registeredBy) answers 401 even without a tenant",
|
|
660
|
+
async (route: GuardedRoute) => {
|
|
661
|
+
const result: ChainResult = await runChain({
|
|
662
|
+
route: route,
|
|
663
|
+
request: { ...EXPIRED_SESSION_REQUEST, headers: {} },
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
expect(result.stoppedAt).toBe(1);
|
|
667
|
+
expect(result.sentError).toBeInstanceOf(NotAuthenticatedException);
|
|
668
|
+
},
|
|
669
|
+
);
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
describe("credentialed callers get past the guard on every route", () => {
|
|
673
|
+
beforeEach(() => {
|
|
674
|
+
jest.clearAllMocks();
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
/*
|
|
678
|
+
* requireUserAuthentication is presence-only. Signed-in users obviously,
|
|
679
|
+
* but also project API keys and master admins: automation that already
|
|
680
|
+
* calls these routes with a key must keep working, and whatever the handler
|
|
681
|
+
* then decides about a key is the handler's business, unchanged by this
|
|
682
|
+
* fix.
|
|
683
|
+
*/
|
|
684
|
+
const callers: Array<[string, Dictionary<unknown>]> = [
|
|
685
|
+
[
|
|
686
|
+
"a signed-in user",
|
|
687
|
+
{
|
|
688
|
+
userType: UserType.User,
|
|
689
|
+
userAuthorization: { userId: USER_ID } as JSONWebTokenData,
|
|
690
|
+
},
|
|
691
|
+
],
|
|
692
|
+
["a project API key", { userType: UserType.API }],
|
|
693
|
+
[
|
|
694
|
+
"a master admin",
|
|
695
|
+
{
|
|
696
|
+
userType: UserType.MasterAdmin,
|
|
697
|
+
userAuthorization: {
|
|
698
|
+
userId: USER_ID,
|
|
699
|
+
isMasterAdmin: true,
|
|
700
|
+
} as JSONWebTokenData,
|
|
701
|
+
},
|
|
702
|
+
],
|
|
703
|
+
];
|
|
704
|
+
|
|
705
|
+
test.each(GUARDED_ROUTES)(
|
|
706
|
+
"$method $uri ($registeredBy) admits a user, an API key and a master admin",
|
|
707
|
+
async (route: GuardedRoute) => {
|
|
708
|
+
const guard: RouterFunction = findRoute(route).middlewares[1]!;
|
|
709
|
+
|
|
710
|
+
for (const [label, caller] of callers) {
|
|
711
|
+
const next: jest.Mock = jest.fn();
|
|
712
|
+
|
|
713
|
+
await guard(
|
|
714
|
+
{ headers: {}, ...caller } as unknown as ExpressRequest,
|
|
715
|
+
{} as ExpressResponse,
|
|
716
|
+
next as unknown as NextFunction,
|
|
717
|
+
);
|
|
718
|
+
|
|
719
|
+
expect({ caller: label, nextCalls: next.mock.calls }).toEqual({
|
|
720
|
+
caller: label,
|
|
721
|
+
nextCalls: [[]],
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
expect(Response.sendErrorResponse).not.toHaveBeenCalled();
|
|
726
|
+
},
|
|
727
|
+
);
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
/*
|
|
731
|
+
* One route driven end to end, handler included: POST
|
|
732
|
+
* /team-member/remove-user-from-project, because it is destructive and
|
|
733
|
+
* because its handler has its own "Not authenticated" check that answers with
|
|
734
|
+
* a 422. If the guard were missing, the chain would fall through to that
|
|
735
|
+
* handler and the answer would be the 422 - exactly the kind of refusal the
|
|
736
|
+
* browser client does not recover from.
|
|
737
|
+
*/
|
|
738
|
+
describe("POST /team-member/remove-user-from-project with an expired session", () => {
|
|
739
|
+
const ROUTE: GuardedRoute = {
|
|
740
|
+
method: "POST",
|
|
741
|
+
uri: "/team-member/remove-user-from-project",
|
|
742
|
+
registeredBy: "TeamMemberAPI",
|
|
743
|
+
};
|
|
744
|
+
|
|
745
|
+
let deleteBySpy: jest.SpyInstance;
|
|
746
|
+
|
|
747
|
+
beforeEach(() => {
|
|
748
|
+
jest.clearAllMocks();
|
|
749
|
+
|
|
750
|
+
jest
|
|
751
|
+
.spyOn(ProjectService, "updateLastActive")
|
|
752
|
+
.mockResolvedValue(undefined as never);
|
|
753
|
+
|
|
754
|
+
deleteBySpy = jest
|
|
755
|
+
.spyOn(TeamMemberService, "deleteBy")
|
|
756
|
+
.mockResolvedValue(1 as never);
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
test("is refused with a 401 and deletes nothing", async () => {
|
|
760
|
+
const result: ChainResult = await runChain({
|
|
761
|
+
route: ROUTE,
|
|
762
|
+
request: {
|
|
763
|
+
headers: { tenantid: PROJECT_ID },
|
|
764
|
+
body: { userId: USER_ID.toString() },
|
|
765
|
+
},
|
|
766
|
+
runHandler: true,
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
expect(result.reachedHandler).toBe(false);
|
|
770
|
+
expect(deleteBySpy).not.toHaveBeenCalled();
|
|
771
|
+
expect(Response.sendErrorResponse).toHaveBeenCalledTimes(1);
|
|
772
|
+
expect(Response.sendErrorResponse).toHaveBeenCalledWith(
|
|
773
|
+
result.request,
|
|
774
|
+
expect.anything(),
|
|
775
|
+
expect.any(NotAuthenticatedException),
|
|
776
|
+
);
|
|
777
|
+
expect(result.sentError?.code).toBe(401);
|
|
778
|
+
expect(Response.sendJsonObjectResponse).not.toHaveBeenCalled();
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
/*
|
|
782
|
+
* The contrast that makes the assertion above meaningful: the same request
|
|
783
|
+
* with the guard skipped reaches the handler, which refuses it with its
|
|
784
|
+
* own 422. That is the answer an expired session used to get.
|
|
785
|
+
*/
|
|
786
|
+
test("would have been a 422 from the handler without the guard", async () => {
|
|
787
|
+
const recorded: RecordedRoute = findRoute(ROUTE);
|
|
788
|
+
|
|
789
|
+
const req: OneUptimeRequest = {
|
|
790
|
+
params: {},
|
|
791
|
+
query: {},
|
|
792
|
+
cookies: {},
|
|
793
|
+
headers: { tenantid: PROJECT_ID },
|
|
794
|
+
body: { userId: USER_ID.toString() },
|
|
795
|
+
} as unknown as OneUptimeRequest;
|
|
796
|
+
|
|
797
|
+
const res: ExpressResponse = {
|
|
798
|
+
status: jest.fn().mockReturnThis(),
|
|
799
|
+
} as unknown as ExpressResponse;
|
|
800
|
+
|
|
801
|
+
// getUserMiddleware only, then straight to the handler.
|
|
802
|
+
await recorded.middlewares[0]!(
|
|
803
|
+
req as ExpressRequest,
|
|
804
|
+
res,
|
|
805
|
+
jest.fn() as unknown as NextFunction,
|
|
806
|
+
);
|
|
807
|
+
|
|
808
|
+
await recorded.handlerFunction(
|
|
809
|
+
req as ExpressRequest,
|
|
810
|
+
res,
|
|
811
|
+
jest.fn() as unknown as NextFunction,
|
|
812
|
+
);
|
|
813
|
+
|
|
814
|
+
const sent: Exception = (Response.sendErrorResponse as unknown as jest.Mock)
|
|
815
|
+
.mock.calls[0]![2] as Exception;
|
|
816
|
+
|
|
817
|
+
expect(sent.code).toBe(ExceptionCode.NotAuthorizedException);
|
|
818
|
+
expect(deleteBySpy).not.toHaveBeenCalled();
|
|
819
|
+
});
|
|
820
|
+
});
|