@oneuptime/common 13.0.7 → 13.0.8
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/OnCallDutyPolicyScheduleCalendarFeed.ts +1 -1
- package/Models/DatabaseModels/ProjectOnCallCalendarFeed.ts +1 -1
- package/Models/DatabaseModels/UserOnCallCalendarFeed.ts +1 -1
- 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 +13 -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 +17 -0
- 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/ScheduledMaintenanceAPI.ts +1 -0
- package/Server/API/StatusPageAPI.ts +161 -32
- package/Server/API/TeamMemberAPI.ts +3 -0
- 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/Middleware/MasterAdminAuthorization.ts +13 -2
- package/Server/Middleware/UserAuthorization.ts +79 -5
- package/Server/Services/ApiKeyPermissionService.ts +101 -4
- package/Server/Services/DatabaseService.ts +245 -0
- package/Server/Services/DetectionRuleService.ts +5 -4
- 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 +18 -0
- package/Server/Services/RumSessionPinService.ts +274 -22
- package/Server/Services/TeamPermissionService.ts +120 -26
- package/Server/Services/ThreatIntelFeedService.ts +6 -3
- package/Server/Types/Database/Permissions/BasePermission.ts +9 -7
- package/Server/Types/Database/Permissions/Index.ts +75 -11
- package/Server/Types/Database/Permissions/TablePermission.ts +24 -28
- package/Server/Utils/AI/AIChatPrivacyFilter.ts +8 -0
- package/Server/Utils/AI/AIRunPrivacyFilter.ts +8 -0
- package/Server/Utils/MasterAdminPageAccess.ts +61 -0
- package/Server/Utils/Monitor/MonitorAlert.ts +3 -1
- package/Server/Utils/Monitor/MonitorIncident.ts +3 -1
- 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/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/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/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/OnCallCalendarFeedSideMenus.test.tsx +9 -1
- 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 +95 -68
- package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +86 -3
- package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +28 -3
- package/Tests/App/Dashboard/SecurityEventsExplorer.test.tsx +761 -0
- package/Tests/App/Dashboard/SecurityEventsGuideContent.test.ts +1313 -0
- package/Tests/App/Dashboard/SecurityEventsHowItWorksCard.test.tsx +536 -0
- package/Tests/App/Dashboard/SecurityEventsNoResults.test.tsx +222 -0
- package/Tests/App/Dashboard/SecurityEventsThreatIntelPage.test.tsx +199 -0
- package/Tests/App/Dashboard/SecurityEventsVolumeChart.test.tsx +321 -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/PublicDashboard/DashboardVariableSelector.test.tsx +12 -4
- package/Tests/App/PublicDashboard/PublicDashboardWidgetListAuth.test.tsx +623 -0
- package/Tests/Models/OnCallCalendarFeedModels.test.ts +23 -1
- 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/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 +140 -0
- 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 +175 -17
- 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/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/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/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/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/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/MonitorPayAsYouGoBilling.test.ts +115 -1
- 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/ProjectServiceCreateSubscriptionStarted.test.ts +77 -1
- package/Tests/Server/Services/RumSessionPinCreatePermission.test.ts +715 -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/UserNotificationRuleAdminGuards.test.ts +13 -2
- 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/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/MasterAdminPageAccess.test.ts +251 -0
- package/Tests/Server/Utils/Monitor/MonitorActionTimestamps.test.ts +616 -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/Types/AI/AIInsightEvidence.test.ts +206 -0
- package/Tests/Types/BaseDatabase/DatabaseCommonInteractionPropsUtilAnonymous.test.ts +144 -0
- package/Tests/Types/Call/CallProvider.test.ts +528 -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/EditionLabelLicenseRefresh.test.tsx +89 -1
- 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/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/TooltipInteractive.test.tsx +97 -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/SecurityEvent/GoogleSecOpsAlertNormalizerSeverity.test.ts +565 -0
- package/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.ts +40 -0
- package/Types/Monitor/MonitorEvaluationSummary.ts +3 -0
- 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/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 +12 -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/Markdown.tsx/MarkdownViewer.tsx +2 -1
- package/UI/Components/Markdown.tsx/SessionAwareImage.tsx +122 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +34 -5
- package/UI/Components/ModelTable/TableView.tsx +1 -1
- 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/Utils/API.ts +14 -5
- package/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.ts +157 -7
- package/Utils/SecurityEvent/Sigma/SigmaRuleParser.ts +9 -17
- package/Utils/Slo/SloBurnRateTemplate.ts +2 -2
- 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 +12 -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 +12 -0
- 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/ScheduledMaintenanceAPI.js +1 -1
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +125 -33
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/TeamMemberAPI.js +3 -3
- 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/Middleware/MasterAdminAuthorization.js +11 -2
- package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +64 -4
- 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/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/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 +17 -0
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/RumSessionPinService.js +180 -16
- package/build/dist/Server/Services/RumSessionPinService.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/ThreatIntelFeedService.js +5 -4
- package/build/dist/Server/Services/ThreatIntelFeedService.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/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 +14 -13
- package/build/dist/Server/Types/Database/Permissions/TablePermission.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/MasterAdminPageAccess.js +39 -0
- package/build/dist/Server/Utils/MasterAdminPageAccess.js.map +1 -0
- 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/MonitorIncident.js +3 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- 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/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js +31 -1
- package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js.map +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/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 +11 -0
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- 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/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/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/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/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/package.json +1 -1
|
@@ -12,9 +12,13 @@ import Response from "../../../Server/Utils/Response";
|
|
|
12
12
|
import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
13
13
|
import BadDataException from "../../../Types/Exception/BadDataException";
|
|
14
14
|
import NotAuthorizedException from "../../../Types/Exception/NotAuthorizedException";
|
|
15
|
+
import NotAuthenticatedException from "../../../Types/Exception/NotAuthenticatedException";
|
|
16
|
+
import Exception from "../../../Types/Exception/Exception";
|
|
17
|
+
import ExceptionCode from "../../../Types/Exception/ExceptionCode";
|
|
15
18
|
import { ROUTINE_EMAIL_EVENT_TYPES } from "../../../Types/NotificationSetting/RoutineEmailEvents";
|
|
16
19
|
import ObjectID from "../../../Types/ObjectID";
|
|
17
20
|
import Permission from "../../../Types/Permission";
|
|
21
|
+
import UserType from "../../../Types/UserType";
|
|
18
22
|
|
|
19
23
|
jest.mock("../../../Server/Utils/Express", () => {
|
|
20
24
|
return {
|
|
@@ -29,6 +33,15 @@ const USER_ID: ObjectID = ObjectID.generate();
|
|
|
29
33
|
const PROJECT_ID: ObjectID = ObjectID.generate();
|
|
30
34
|
const OTHER_PROJECT_ID: ObjectID = ObjectID.generate();
|
|
31
35
|
|
|
36
|
+
/*
|
|
37
|
+
* The exception the handler handed to next(). Its code is the HTTP status the
|
|
38
|
+
* client sees, and the browser client refreshes the session on 401 only, so
|
|
39
|
+
* the code is asserted alongside the class.
|
|
40
|
+
*/
|
|
41
|
+
function errorPassedTo(next: jest.Mock): Exception {
|
|
42
|
+
return next.mock.calls[0]![0] as Exception;
|
|
43
|
+
}
|
|
44
|
+
|
|
32
45
|
describe("POST reduce routine emails", () => {
|
|
33
46
|
let props: DatabaseCommonInteractionProps;
|
|
34
47
|
let reduceSpy: jest.SpyInstance;
|
|
@@ -128,21 +141,67 @@ describe("POST reduce routine emails", () => {
|
|
|
128
141
|
});
|
|
129
142
|
});
|
|
130
143
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
144
|
+
/*
|
|
145
|
+
* Both callers are refused, but differently. The anonymous one - no user, no
|
|
146
|
+
* key, typically a dashboard tab whose access-token cookie expired - gets
|
|
147
|
+
* NotAuthenticatedException (401), which is what makes the browser refresh
|
|
148
|
+
* the session and resend; it used to get the 422 below. A project API key
|
|
149
|
+
* is authenticated but is nobody's preferences, so it keeps the 422: a 401
|
|
150
|
+
* would send its client off to refresh a session it never had.
|
|
151
|
+
*/
|
|
152
|
+
test.each([
|
|
153
|
+
{
|
|
154
|
+
caller: "an anonymous caller",
|
|
155
|
+
userType: undefined,
|
|
156
|
+
exception: NotAuthenticatedException,
|
|
157
|
+
code: ExceptionCode.NotAuthenticatedException,
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
caller: "an explicitly Public caller",
|
|
161
|
+
userType: UserType.Public,
|
|
162
|
+
exception: NotAuthenticatedException,
|
|
163
|
+
code: ExceptionCode.NotAuthenticatedException,
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
caller: "a project API key",
|
|
167
|
+
userType: UserType.API,
|
|
168
|
+
exception: NotAuthorizedException,
|
|
169
|
+
code: ExceptionCode.NotAuthorizedException,
|
|
170
|
+
},
|
|
171
|
+
])(
|
|
172
|
+
"rejects $caller without an authenticated user",
|
|
173
|
+
async (testCase: {
|
|
174
|
+
caller: string;
|
|
175
|
+
userType: UserType | undefined;
|
|
176
|
+
exception:
|
|
177
|
+
| typeof NotAuthenticatedException
|
|
178
|
+
| typeof NotAuthorizedException;
|
|
179
|
+
code: ExceptionCode;
|
|
180
|
+
}) => {
|
|
134
181
|
props.userId = undefined;
|
|
182
|
+
props.userType = testCase.userType;
|
|
135
183
|
const next: jest.Mock = await call({ userId: USER_ID.toString() });
|
|
136
|
-
expect(next).toHaveBeenCalledWith(expect.any(
|
|
184
|
+
expect(next).toHaveBeenCalledWith(expect.any(testCase.exception));
|
|
185
|
+
expect(errorPassedTo(next).code).toBe(testCase.code);
|
|
137
186
|
expect(reduceSpy).not.toHaveBeenCalled();
|
|
138
187
|
expect(responseSpy).not.toHaveBeenCalled();
|
|
139
188
|
},
|
|
140
189
|
);
|
|
141
190
|
|
|
191
|
+
test("an anonymous caller with no tenant is asked to log in before the missing project is reported", async () => {
|
|
192
|
+
props.userId = undefined;
|
|
193
|
+
props.tenantId = undefined;
|
|
194
|
+
const next: jest.Mock = await call();
|
|
195
|
+
expect(next).toHaveBeenCalledWith(expect.any(NotAuthenticatedException));
|
|
196
|
+
expect(errorPassedTo(next).code).toBe(401);
|
|
197
|
+
expect(reduceSpy).not.toHaveBeenCalled();
|
|
198
|
+
});
|
|
199
|
+
|
|
142
200
|
test("rejects missing project context before changing preferences", async () => {
|
|
143
201
|
props.tenantId = undefined;
|
|
144
202
|
const next: jest.Mock = await call({ projectId: PROJECT_ID.toString() });
|
|
145
203
|
expect(next).toHaveBeenCalledWith(expect.any(BadDataException));
|
|
204
|
+
expect(errorPassedTo(next).code).toBe(ExceptionCode.BadDataException);
|
|
146
205
|
expect(reduceSpy).not.toHaveBeenCalled();
|
|
147
206
|
});
|
|
148
207
|
|
|
@@ -150,6 +209,7 @@ describe("POST reduce routine emails", () => {
|
|
|
150
209
|
props.userTenantAccessPermission = undefined;
|
|
151
210
|
const next: jest.Mock = await call();
|
|
152
211
|
expect(next).toHaveBeenCalledWith(expect.any(NotAuthorizedException));
|
|
212
|
+
expect(errorPassedTo(next).code).toBe(ExceptionCode.NotAuthorizedException);
|
|
153
213
|
expect(reduceSpy).not.toHaveBeenCalled();
|
|
154
214
|
});
|
|
155
215
|
|
|
@@ -157,6 +217,7 @@ describe("POST reduce routine emails", () => {
|
|
|
157
217
|
props.tenantId = OTHER_PROJECT_ID;
|
|
158
218
|
const next: jest.Mock = await call();
|
|
159
219
|
expect(next).toHaveBeenCalledWith(expect.any(NotAuthorizedException));
|
|
220
|
+
expect(errorPassedTo(next).code).toBe(ExceptionCode.NotAuthorizedException);
|
|
160
221
|
expect(reduceSpy).not.toHaveBeenCalled();
|
|
161
222
|
});
|
|
162
223
|
|
|
@@ -18,6 +18,10 @@ import TeamMember from "../../../Models/DatabaseModels/TeamMember";
|
|
|
18
18
|
import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
19
19
|
import { DEFAULT_LIMIT } from "../../../Types/Database/LimitMax";
|
|
20
20
|
import Dictionary from "../../../Types/Dictionary";
|
|
21
|
+
import BadDataException from "../../../Types/Exception/BadDataException";
|
|
22
|
+
import Exception from "../../../Types/Exception/Exception";
|
|
23
|
+
import ExceptionCode from "../../../Types/Exception/ExceptionCode";
|
|
24
|
+
import NotAuthenticatedException from "../../../Types/Exception/NotAuthenticatedException";
|
|
21
25
|
import NotAuthorizedException from "../../../Types/Exception/NotAuthorizedException";
|
|
22
26
|
import { JSONObject } from "../../../Types/JSON";
|
|
23
27
|
import JSONWebTokenData from "../../../Types/JsonWebTokenData";
|
|
@@ -916,7 +920,7 @@ describe("POST /user/:userId/projects — the master API key path", () => {
|
|
|
916
920
|
type MiddlewareCallResult = {
|
|
917
921
|
// Whether the gate let the request through to the read.
|
|
918
922
|
reachedHandler: boolean;
|
|
919
|
-
errorSentToClient:
|
|
923
|
+
errorSentToClient: Exception | undefined;
|
|
920
924
|
// The request object as the handler saw it, to inspect what the gate set.
|
|
921
925
|
request: ExpressRequest;
|
|
922
926
|
};
|
|
@@ -974,7 +978,7 @@ describe("POST /user/:userId/projects — the master API key path", () => {
|
|
|
974
978
|
|
|
975
979
|
return {
|
|
976
980
|
reachedHandler: reachedHandler,
|
|
977
|
-
errorSentToClient: errorCall?.[2] as
|
|
981
|
+
errorSentToClient: errorCall?.[2] as Exception | undefined,
|
|
978
982
|
request: req,
|
|
979
983
|
};
|
|
980
984
|
}
|
|
@@ -1145,7 +1149,19 @@ describe("POST /user/:userId/projects — the master API key path", () => {
|
|
|
1145
1149
|
expect(findBySpy).not.toHaveBeenCalled();
|
|
1146
1150
|
expect(Response.sendJsonArrayResponse).not.toHaveBeenCalled();
|
|
1147
1151
|
|
|
1148
|
-
|
|
1152
|
+
/*
|
|
1153
|
+
* An unusable key falls through to the session check, and with no
|
|
1154
|
+
* session that is the no-token refusal - a 401 now, where it used to
|
|
1155
|
+
* be a NotAuthorizedException (422). Still a refusal, and still AT the
|
|
1156
|
+
* gate; only the status changed, so that an Admin Dashboard tab whose
|
|
1157
|
+
* session cookie has expired refreshes instead of showing an error.
|
|
1158
|
+
*/
|
|
1159
|
+
expect(result.errorSentToClient).toBeInstanceOf(
|
|
1160
|
+
NotAuthenticatedException,
|
|
1161
|
+
);
|
|
1162
|
+
expect(result.errorSentToClient?.code).toBe(
|
|
1163
|
+
ExceptionCode.NotAuthenticatedException,
|
|
1164
|
+
);
|
|
1149
1165
|
expect(result.errorSentToClient?.message).toBe(
|
|
1150
1166
|
"Unauthorized: Access token is required.",
|
|
1151
1167
|
);
|
|
@@ -1159,6 +1175,41 @@ describe("POST /user/:userId/projects — the master API key path", () => {
|
|
|
1159
1175
|
|
|
1160
1176
|
expect(result.reachedHandler).toBe(false);
|
|
1161
1177
|
expect(findBySpy).not.toHaveBeenCalled();
|
|
1178
|
+
|
|
1179
|
+
/*
|
|
1180
|
+
* This is what the Admin Dashboard's User > Projects page sends once
|
|
1181
|
+
* its session cookie has expired. Only a 401 makes the browser client
|
|
1182
|
+
* refresh the session and replay the read.
|
|
1183
|
+
*/
|
|
1184
|
+
expect(result.errorSentToClient).toBeInstanceOf(
|
|
1185
|
+
NotAuthenticatedException,
|
|
1186
|
+
);
|
|
1187
|
+
expect(result.errorSentToClient?.code).toBe(
|
|
1188
|
+
ExceptionCode.NotAuthenticatedException,
|
|
1189
|
+
);
|
|
1190
|
+
});
|
|
1191
|
+
|
|
1192
|
+
test("refuses an expired session with no key with a 401, without reading anything", async () => {
|
|
1193
|
+
jest
|
|
1194
|
+
.spyOn(UserMiddleware, "getAccessTokenFromExpressRequest")
|
|
1195
|
+
.mockReturnValue("an.expired.token" as never);
|
|
1196
|
+
|
|
1197
|
+
jest.spyOn(JSONWebToken, "decode").mockImplementation(() => {
|
|
1198
|
+
throw new BadDataException("AccessToken is invalid or expired");
|
|
1199
|
+
});
|
|
1200
|
+
|
|
1201
|
+
const result: MiddlewareCallResult = await callThroughMiddleware({
|
|
1202
|
+
headers: {},
|
|
1203
|
+
});
|
|
1204
|
+
|
|
1205
|
+
expect(result.reachedHandler).toBe(false);
|
|
1206
|
+
expect(findBySpy).not.toHaveBeenCalled();
|
|
1207
|
+
expect(result.errorSentToClient).toBeInstanceOf(
|
|
1208
|
+
NotAuthenticatedException,
|
|
1209
|
+
);
|
|
1210
|
+
expect(result.errorSentToClient?.message).toBe(
|
|
1211
|
+
"Unauthorized: Invalid or expired access token.",
|
|
1212
|
+
);
|
|
1162
1213
|
});
|
|
1163
1214
|
|
|
1164
1215
|
/*
|
|
@@ -1231,6 +1282,15 @@ describe("POST /user/:userId/projects — the master API key path", () => {
|
|
|
1231
1282
|
expect(result.errorSentToClient?.message).toBe(
|
|
1232
1283
|
"Unauthorized: Only master admins can perform this action.",
|
|
1233
1284
|
);
|
|
1285
|
+
|
|
1286
|
+
/*
|
|
1287
|
+
* Still a 422, unlike the missing-token case: this caller is signed in,
|
|
1288
|
+
* and refreshing their session would not make them a master admin.
|
|
1289
|
+
*/
|
|
1290
|
+
expect(result.errorSentToClient).toBeInstanceOf(NotAuthorizedException);
|
|
1291
|
+
expect(result.errorSentToClient?.code).toBe(
|
|
1292
|
+
ExceptionCode.NotAuthorizedException,
|
|
1293
|
+
);
|
|
1234
1294
|
});
|
|
1235
1295
|
|
|
1236
1296
|
/*
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import UserTotpAuthAPI from "../../../Server/API/UserTotpAuthAPI";
|
|
2
|
+
import UserMiddleware from "../../../Server/Middleware/UserAuthorization";
|
|
2
3
|
import UserTotpAuthService from "../../../Server/Services/UserTotpAuthService";
|
|
3
4
|
import UserService from "../../../Server/Services/UserService";
|
|
4
5
|
import UserTwoFactorBackupCodeService from "../../../Server/Services/UserTwoFactorBackupCodeService";
|
|
@@ -17,6 +18,8 @@ import Dictionary from "../../../Types/Dictionary";
|
|
|
17
18
|
import Email from "../../../Types/Email";
|
|
18
19
|
import BadDataException from "../../../Types/Exception/BadDataException";
|
|
19
20
|
import Exception from "../../../Types/Exception/Exception";
|
|
21
|
+
import ExceptionCode from "../../../Types/Exception/ExceptionCode";
|
|
22
|
+
import NotAuthenticatedException from "../../../Types/Exception/NotAuthenticatedException";
|
|
20
23
|
import { JSONObject } from "../../../Types/JSON";
|
|
21
24
|
import ObjectID from "../../../Types/ObjectID";
|
|
22
25
|
import UserTotpAuth from "../../../Models/DatabaseModels/UserTotpAuth";
|
|
@@ -358,11 +361,54 @@ describe("POST /user-totp-auth/validate", () => {
|
|
|
358
361
|
* `userAuthorization` off an unauthenticated request, the ownership
|
|
359
362
|
* comparison below would compare against `undefined`, and anybody could
|
|
360
363
|
* verify anybody's TOTP row.
|
|
364
|
+
*
|
|
365
|
+
* Two middlewares now, asserted by identity (a count of two would not
|
|
366
|
+
* notice one being swapped for another). getUserMiddleware resolves the
|
|
367
|
+
* session, but lets a request with NO session through as Public;
|
|
368
|
+
* requireUserAuthentication is what turns that request into a 401. It was
|
|
369
|
+
* added because an enrolment page left open past the session lifetime
|
|
370
|
+
* sends exactly that request - the access-token cookie expires with the
|
|
371
|
+
* token - and the handler answered it with a "Two factor auth not found"
|
|
372
|
+
* 400 (after reading the row as root), which the browser client does not
|
|
373
|
+
* treat as a cue to refresh the session and retry.
|
|
361
374
|
*/
|
|
362
375
|
test("is behind an authentication middleware", () => {
|
|
363
|
-
expect(mockRouter.match("post", VALIDATE_ROUTE).middlewares
|
|
364
|
-
|
|
376
|
+
expect(mockRouter.match("post", VALIDATE_ROUTE).middlewares).toEqual([
|
|
377
|
+
UserMiddleware.getUserMiddleware,
|
|
378
|
+
UserMiddleware.requireUserAuthentication,
|
|
379
|
+
]);
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
test("answers a request with no session 401 before any row is read", async () => {
|
|
383
|
+
const req: OneUptimeRequest = {
|
|
384
|
+
body: { id: TOTP_ID.toString(), code: "123456" },
|
|
385
|
+
params: {},
|
|
386
|
+
query: {},
|
|
387
|
+
headers: {},
|
|
388
|
+
} as unknown as OneUptimeRequest;
|
|
389
|
+
|
|
390
|
+
const res: OneUptimeResponse = {
|
|
391
|
+
status: jest.fn().mockReturnThis(),
|
|
392
|
+
} as unknown as OneUptimeResponse;
|
|
393
|
+
|
|
394
|
+
const next: jest.Mock = jest.fn();
|
|
395
|
+
|
|
396
|
+
await mockRouter.match("post", VALIDATE_ROUTE).middlewares[1]!(
|
|
397
|
+
req,
|
|
398
|
+
res,
|
|
399
|
+
next as unknown as NextFunction,
|
|
365
400
|
);
|
|
401
|
+
|
|
402
|
+
expect(next).not.toHaveBeenCalled();
|
|
403
|
+
|
|
404
|
+
const error: Exception = asMock(Response.sendErrorResponse).mock
|
|
405
|
+
.calls[0]![2] as Exception;
|
|
406
|
+
|
|
407
|
+
expect(error).toBeInstanceOf(NotAuthenticatedException);
|
|
408
|
+
expect(error.code).toBe(ExceptionCode.NotAuthenticatedException);
|
|
409
|
+
expect(findTotpById).not.toHaveBeenCalled();
|
|
410
|
+
expect(updateTotpById).not.toHaveBeenCalled();
|
|
411
|
+
expect(generateForUserIfNoneSpy).not.toHaveBeenCalled();
|
|
366
412
|
});
|
|
367
413
|
});
|
|
368
414
|
|
|
@@ -281,20 +281,29 @@ describe("POST /user-webauthn/generate-authentication-options", () => {
|
|
|
281
281
|
["registration options", REGISTRATION_OPTIONS_ROUTE],
|
|
282
282
|
["verify registration", VERIFY_REGISTRATION_ROUTE],
|
|
283
283
|
])(
|
|
284
|
-
"%s stays behind the user middleware alone",
|
|
284
|
+
"%s stays behind the user middleware and its authentication guard alone",
|
|
285
285
|
(_name: string, uri: string) => {
|
|
286
286
|
/*
|
|
287
287
|
* Both are authenticated, and neither carries an email in its body --
|
|
288
288
|
* so the limiter's account key would collapse to the same value for
|
|
289
289
|
* every caller and one user's enrolment attempts would throttle
|
|
290
290
|
* everybody's.
|
|
291
|
+
*
|
|
292
|
+
* The second entry is requireUserAuthentication, not a limiter. It
|
|
293
|
+
* turns a request with no session (the access-token cookie expired
|
|
294
|
+
* while the enrolment dialog was open) into a 401 the browser client
|
|
295
|
+
* refreshes on. It is the only thing allowed after getUserMiddleware.
|
|
291
296
|
*/
|
|
292
297
|
const route: { middlewares: Array<unknown> } = mockRouter.match(
|
|
293
298
|
"post",
|
|
294
299
|
uri,
|
|
295
300
|
);
|
|
296
301
|
|
|
297
|
-
expect(route.middlewares).toEqual([
|
|
302
|
+
expect(route.middlewares).toEqual([
|
|
303
|
+
UserMiddleware.getUserMiddleware,
|
|
304
|
+
UserMiddleware.requireUserAuthentication,
|
|
305
|
+
]);
|
|
306
|
+
expect(route.middlewares).not.toContain(mountedMiddleware);
|
|
298
307
|
},
|
|
299
308
|
);
|
|
300
309
|
});
|
|
@@ -13,6 +13,9 @@ import { mockRouter } from "./Helpers";
|
|
|
13
13
|
import { getJestSpyOn } from "../../Spy";
|
|
14
14
|
import Dictionary from "../../../Types/Dictionary";
|
|
15
15
|
import BadDataException from "../../../Types/Exception/BadDataException";
|
|
16
|
+
import Exception from "../../../Types/Exception/Exception";
|
|
17
|
+
import ExceptionCode from "../../../Types/Exception/ExceptionCode";
|
|
18
|
+
import NotAuthenticatedException from "../../../Types/Exception/NotAuthenticatedException";
|
|
16
19
|
import { JSONObject } from "../../../Types/JSON";
|
|
17
20
|
import ObjectID from "../../../Types/ObjectID";
|
|
18
21
|
import {
|
|
@@ -336,20 +339,60 @@ afterEach(() => {
|
|
|
336
339
|
|
|
337
340
|
describe("POST /user-webauthn/verify-registration", () => {
|
|
338
341
|
describe("the route itself", () => {
|
|
339
|
-
test("is registered as a POST behind the user middleware", () => {
|
|
342
|
+
test("is registered as a POST behind the user middleware and the authentication guard", () => {
|
|
340
343
|
/*
|
|
341
344
|
* The handler takes the owning user from `userAuthorization`, which is
|
|
342
345
|
* put on the request by this middleware and by nothing else. Without it
|
|
343
346
|
* the id would be undefined for every caller, and asserted by IDENTITY
|
|
344
347
|
* rather than by counting because swapping in a different middleware
|
|
345
|
-
* keeps the count
|
|
348
|
+
* keeps the count the same.
|
|
349
|
+
*
|
|
350
|
+
* getUserMiddleware lets a request with NO session through as Public,
|
|
351
|
+
* so requireUserAuthentication follows it and answers that request with
|
|
352
|
+
* a 401. A key-enrolment dialog left open until the access-token cookie
|
|
353
|
+
* expired sends exactly that request, and only a 401 makes the browser
|
|
354
|
+
* client refresh the session and replay the registration.
|
|
346
355
|
*/
|
|
347
356
|
const route: { middlewares: Array<unknown> } = mockRouter.match(
|
|
348
357
|
"post",
|
|
349
358
|
VERIFY_REGISTRATION_ROUTE,
|
|
350
359
|
);
|
|
351
360
|
|
|
352
|
-
expect(route.middlewares).toEqual([
|
|
361
|
+
expect(route.middlewares).toEqual([
|
|
362
|
+
UserMiddleware.getUserMiddleware,
|
|
363
|
+
UserMiddleware.requireUserAuthentication,
|
|
364
|
+
]);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
test("answers a request with no session 401 before registering or minting anything", async () => {
|
|
368
|
+
const req: OneUptimeRequest = {
|
|
369
|
+
params: {},
|
|
370
|
+
query: {},
|
|
371
|
+
body: { credential: CREDENTIAL_FROM_THE_BROWSER, name: KEY_NAME },
|
|
372
|
+
headers: {},
|
|
373
|
+
} as unknown as OneUptimeRequest;
|
|
374
|
+
|
|
375
|
+
const res: OneUptimeResponse = {
|
|
376
|
+
status: jest.fn().mockReturnThis(),
|
|
377
|
+
} as unknown as OneUptimeResponse;
|
|
378
|
+
|
|
379
|
+
const next: jest.Mock = jest.fn();
|
|
380
|
+
|
|
381
|
+
await mockRouter.match("post", VERIFY_REGISTRATION_ROUTE).middlewares[1]!(
|
|
382
|
+
req,
|
|
383
|
+
res,
|
|
384
|
+
next as unknown as NextFunction,
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
expect(next).not.toHaveBeenCalled();
|
|
388
|
+
|
|
389
|
+
const error: Exception = asMock(Response.sendErrorResponse).mock
|
|
390
|
+
.calls[0]![2] as Exception;
|
|
391
|
+
|
|
392
|
+
expect(error).toBeInstanceOf(NotAuthenticatedException);
|
|
393
|
+
expect(error.code).toBe(ExceptionCode.NotAuthenticatedException);
|
|
394
|
+
expect(verifyRegistrationSpy).not.toHaveBeenCalled();
|
|
395
|
+
expect(mintSpy).not.toHaveBeenCalled();
|
|
353
396
|
});
|
|
354
397
|
|
|
355
398
|
test("carries no route parameter that could name a user", () => {
|
|
@@ -27,7 +27,13 @@ jest.mock("../../../Server/API/CommonAPI", () => {
|
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
jest.mock("../../../Server/Middleware/UserAuthorization", () => {
|
|
30
|
-
return {
|
|
30
|
+
return {
|
|
31
|
+
__esModule: true,
|
|
32
|
+
default: {
|
|
33
|
+
getUserMiddleware: jest.fn(),
|
|
34
|
+
requireUserAuthentication: jest.fn(),
|
|
35
|
+
},
|
|
36
|
+
};
|
|
31
37
|
});
|
|
32
38
|
|
|
33
39
|
jest.mock("../../../Server/Middleware/IdentityRateLimit", () => {
|
|
@@ -107,9 +113,19 @@ describe("passkey registration API", () => {
|
|
|
107
113
|
jest.restoreAllMocks();
|
|
108
114
|
});
|
|
109
115
|
|
|
116
|
+
/*
|
|
117
|
+
* getUserMiddleware resolves the session; requireUserAuthentication turns a
|
|
118
|
+
* request that has none (a settings page left open until the access-token
|
|
119
|
+
* cookie expired) into a 401 the browser client refreshes on, rather than
|
|
120
|
+
* letting the handler dereference a missing userAuthorization. Both are
|
|
121
|
+
* mocked to distinct functions so the identity check below is real: with
|
|
122
|
+
* the second left out of the mock, the route would register `undefined` in
|
|
123
|
+
* its place and toEqual would still match a one-element list.
|
|
124
|
+
*/
|
|
110
125
|
test("requires authentication before allowing registration", () => {
|
|
111
|
-
expect(mockRouter.match("post", ROUTE).middlewares).
|
|
126
|
+
expect(mockRouter.match("post", ROUTE).middlewares).toStrictEqual([
|
|
112
127
|
UserMiddleware.getUserMiddleware,
|
|
128
|
+
UserMiddleware.requireUserAuthentication,
|
|
113
129
|
]);
|
|
114
130
|
});
|
|
115
131
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, expect, test } from "@jest/globals";
|
|
1
|
+
import { beforeAll, describe, expect, test } from "@jest/globals";
|
|
2
2
|
import express from "express";
|
|
3
3
|
import http from "http";
|
|
4
4
|
import { AddressInfo } from "net";
|
|
@@ -118,11 +118,21 @@ const httpGetJson: HttpGetJsonFunction = (data: {
|
|
|
118
118
|
};
|
|
119
119
|
|
|
120
120
|
describe("ANON ACCESS PROBE /microsoft-teams/chats", () => {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
121
|
+
let MicrosoftTeamsAPI: any = undefined;
|
|
122
|
+
|
|
123
|
+
/*
|
|
124
|
+
* Loading MicrosoftTeamsAPI pulls in a large module graph. Done inside the
|
|
125
|
+
* test, that load counted against the probe's 30s budget and timed the test
|
|
126
|
+
* out on a busy machine even though the route answered correctly. The load
|
|
127
|
+
* gets its own, generous budget here so the test's timeout measures only the
|
|
128
|
+
* HTTP round trip it is about.
|
|
129
|
+
*/
|
|
130
|
+
beforeAll(async () => {
|
|
131
|
+
MicrosoftTeamsAPI = (await import("../../../Server/API/MicrosoftTeamsAPI"))
|
|
132
|
+
.default;
|
|
133
|
+
}, 600000);
|
|
125
134
|
|
|
135
|
+
test("unauthenticated GET with only a tenantid header", async () => {
|
|
126
136
|
const app: express.Express = express();
|
|
127
137
|
app.use("/api", new MicrosoftTeamsAPI().getRouter());
|
|
128
138
|
|
|
@@ -148,9 +158,16 @@ describe("ANON ACCESS PROBE /microsoft-teams/chats", () => {
|
|
|
148
158
|
* route must reject one carrying only a tenantid header. A 200 here would
|
|
149
159
|
* mean the captured chat list leaks to anonymous callers - the exact
|
|
150
160
|
* regression this probe guards against.
|
|
161
|
+
*
|
|
162
|
+
* Pinned to exactly 401 (it used to accept any 4xx, and was a 422). A
|
|
163
|
+
* request with only a tenantid header is what a signed-in user's browser
|
|
164
|
+
* sends once the access-token cookie has expired, and the dashboard
|
|
165
|
+
* refreshes the session and resends on a 401 and on nothing else.
|
|
151
166
|
*/
|
|
152
|
-
expect(result.status).
|
|
153
|
-
expect(result.
|
|
167
|
+
expect(result.status).toBe(401);
|
|
168
|
+
expect((result.body as { message?: string }).message).toBe(
|
|
169
|
+
"Authentication required. Please log in to access this resource.",
|
|
170
|
+
);
|
|
154
171
|
|
|
155
172
|
const serializedBody: string = JSON.stringify(result.body);
|
|
156
173
|
expect(serializedBody).not.toContain("Jane Doe");
|