@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
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
import ModelPermission from "../../../../../Server/Types/Database/Permissions/Index";
|
|
2
|
+
import CreatePermission from "../../../../../Server/Types/Database/Permissions/CreatePermission";
|
|
3
|
+
import DeletePermission from "../../../../../Server/Types/Database/Permissions/DeletePermission";
|
|
4
|
+
import ReadPermission from "../../../../../Server/Types/Database/Permissions/ReadPermission";
|
|
5
|
+
import UpdatePermission from "../../../../../Server/Types/Database/Permissions/UpdatePermission";
|
|
6
|
+
import Probe from "../../../../../Models/DatabaseModels/Probe";
|
|
7
|
+
import DatabaseCommonInteractionProps from "../../../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
8
|
+
import BadDataException from "../../../../../Types/Exception/BadDataException";
|
|
9
|
+
import Exception from "../../../../../Types/Exception/Exception";
|
|
10
|
+
import ExceptionCode from "../../../../../Types/Exception/ExceptionCode";
|
|
11
|
+
import NotAuthenticatedException from "../../../../../Types/Exception/NotAuthenticatedException";
|
|
12
|
+
import NotAuthorizedException from "../../../../../Types/Exception/NotAuthorizedException";
|
|
13
|
+
import ObjectID from "../../../../../Types/ObjectID";
|
|
14
|
+
import Permission from "../../../../../Types/Permission";
|
|
15
|
+
import UserType from "../../../../../Types/UserType";
|
|
16
|
+
import { getJestSpyOn } from "../../../../Spy";
|
|
17
|
+
import { afterEach, describe, expect, jest, test } from "@jest/globals";
|
|
18
|
+
|
|
19
|
+
/*
|
|
20
|
+
* Every throw below is deliberate and asserted on, but @CaptureSpan hands each
|
|
21
|
+
* one to Telemetry, which logs the whole stack. Mocking Logger keeps the run
|
|
22
|
+
* readable.
|
|
23
|
+
*/
|
|
24
|
+
jest.mock("../../../../../Server/Utils/Logger");
|
|
25
|
+
|
|
26
|
+
/*
|
|
27
|
+
* WHAT THIS FILE PINS
|
|
28
|
+
*
|
|
29
|
+
* The dashboard's access-token cookie expires together with the 15-minute JWT
|
|
30
|
+
* inside it, so an idle tab's next request arrives with no credentials at all
|
|
31
|
+
* and getUserMiddleware lets it through as Public. The browser client
|
|
32
|
+
* refreshes the session and replays the request on a 401 and on nothing else.
|
|
33
|
+
*
|
|
34
|
+
* On a model whose table ACL includes Permission.Public (Probe, AIAgent and
|
|
35
|
+
* LlmProvider reads; StatusPageSubscriber create) that anonymous caller passes
|
|
36
|
+
* the "is anyone logged in" check at the top of the permission layer, and is
|
|
37
|
+
* then refused by the column, select or query checks with a 422
|
|
38
|
+
* NotAuthorizedException - a bogus error for a user whose session merely
|
|
39
|
+
* needs refreshing. ModelPermission's entry points therefore turn a
|
|
40
|
+
* NotAuthorizedException into a NotAuthenticatedException (401, same message)
|
|
41
|
+
* when, and only when, the caller has no credentials at all.
|
|
42
|
+
*
|
|
43
|
+
* The first half drives each entry point against a stubbed underlying check so
|
|
44
|
+
* every branch is reached on every entry point. The second half runs the real
|
|
45
|
+
* permission layer on Probe, so the conversion is proved against a refusal the
|
|
46
|
+
* permission code actually produces.
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
const REFUSAL_MESSAGE: string = "x";
|
|
50
|
+
|
|
51
|
+
type EntryPointCall = (
|
|
52
|
+
props: DatabaseCommonInteractionProps,
|
|
53
|
+
) => Promise<unknown>;
|
|
54
|
+
|
|
55
|
+
interface EntryPoint {
|
|
56
|
+
name: string;
|
|
57
|
+
// Stubs the underlying Read/Create/Update/Delete check.
|
|
58
|
+
stubUnderlying: () => jest.SpyInstance<any, any>;
|
|
59
|
+
// Calls the ModelPermission entry point; a sync throw becomes a rejection.
|
|
60
|
+
call: EntryPointCall;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const fetchNothing: () => Promise<Probe | null> =
|
|
64
|
+
async (): Promise<Probe | null> => {
|
|
65
|
+
return null;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const entryPoints: Array<EntryPoint> = [
|
|
69
|
+
{
|
|
70
|
+
name: "checkReadQueryPermission",
|
|
71
|
+
stubUnderlying: () => {
|
|
72
|
+
return getJestSpyOn(ReadPermission, "checkReadPermission");
|
|
73
|
+
},
|
|
74
|
+
call: async (props: DatabaseCommonInteractionProps): Promise<unknown> => {
|
|
75
|
+
return await ModelPermission.checkReadQueryPermission(
|
|
76
|
+
Probe,
|
|
77
|
+
{},
|
|
78
|
+
{ name: true },
|
|
79
|
+
props,
|
|
80
|
+
);
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "checkCreatePermissions",
|
|
85
|
+
stubUnderlying: () => {
|
|
86
|
+
return getJestSpyOn(CreatePermission, "checkCreatePermissions");
|
|
87
|
+
},
|
|
88
|
+
call: async (props: DatabaseCommonInteractionProps): Promise<unknown> => {
|
|
89
|
+
return ModelPermission.checkCreatePermissions(Probe, new Probe(), props);
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "checkUpdateQueryPermissions",
|
|
94
|
+
stubUnderlying: () => {
|
|
95
|
+
return getJestSpyOn(UpdatePermission, "checkUpdatePermissions");
|
|
96
|
+
},
|
|
97
|
+
call: async (props: DatabaseCommonInteractionProps): Promise<unknown> => {
|
|
98
|
+
return await ModelPermission.checkUpdateQueryPermissions(
|
|
99
|
+
Probe,
|
|
100
|
+
{},
|
|
101
|
+
{ name: "renamed" },
|
|
102
|
+
props,
|
|
103
|
+
);
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: "checkUpdatePermissionByModel",
|
|
108
|
+
stubUnderlying: () => {
|
|
109
|
+
return getJestSpyOn(UpdatePermission, "checkUpdatePermissionByModel");
|
|
110
|
+
},
|
|
111
|
+
call: async (props: DatabaseCommonInteractionProps): Promise<unknown> => {
|
|
112
|
+
return await ModelPermission.checkUpdatePermissionByModel({
|
|
113
|
+
modelType: Probe,
|
|
114
|
+
fetchModelWithAccessControlIds: fetchNothing,
|
|
115
|
+
props: props,
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: "checkDeleteQueryPermission",
|
|
121
|
+
stubUnderlying: () => {
|
|
122
|
+
return getJestSpyOn(DeletePermission, "checkDeletePermission");
|
|
123
|
+
},
|
|
124
|
+
call: async (props: DatabaseCommonInteractionProps): Promise<unknown> => {
|
|
125
|
+
return await ModelPermission.checkDeleteQueryPermission(Probe, {}, props);
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: "checkDeletePermissionByModel",
|
|
130
|
+
stubUnderlying: () => {
|
|
131
|
+
return getJestSpyOn(DeletePermission, "checkDeletePermissionByModel");
|
|
132
|
+
},
|
|
133
|
+
call: async (props: DatabaseCommonInteractionProps): Promise<unknown> => {
|
|
134
|
+
return await ModelPermission.checkDeletePermissionByModel({
|
|
135
|
+
modelType: Probe,
|
|
136
|
+
fetchModelWithAccessControlIds: fetchNothing,
|
|
137
|
+
props: props,
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
];
|
|
142
|
+
|
|
143
|
+
type PropsCase = [string, () => DatabaseCommonInteractionProps];
|
|
144
|
+
|
|
145
|
+
// Callers with no credentials at all: the expired-session shape.
|
|
146
|
+
const anonymousCases: Array<PropsCase> = [
|
|
147
|
+
[
|
|
148
|
+
"no props at all",
|
|
149
|
+
(): DatabaseCommonInteractionProps => {
|
|
150
|
+
return {};
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
[
|
|
154
|
+
"a tenant but no user",
|
|
155
|
+
(): DatabaseCommonInteractionProps => {
|
|
156
|
+
return { tenantId: ObjectID.generate() };
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
[
|
|
160
|
+
"an explicitly Public caller",
|
|
161
|
+
(): DatabaseCommonInteractionProps => {
|
|
162
|
+
return { userType: UserType.Public };
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
[
|
|
166
|
+
"a Public caller with a tenant",
|
|
167
|
+
(): DatabaseCommonInteractionProps => {
|
|
168
|
+
return { tenantId: ObjectID.generate(), userType: UserType.Public };
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
];
|
|
172
|
+
|
|
173
|
+
/*
|
|
174
|
+
* Callers who ARE identified. Refreshing cannot change their answer, and a
|
|
175
|
+
* 401 would send the client round a refresh-and-replay loop.
|
|
176
|
+
*/
|
|
177
|
+
const credentialedCases: Array<PropsCase> = [
|
|
178
|
+
[
|
|
179
|
+
"a signed-in user",
|
|
180
|
+
(): DatabaseCommonInteractionProps => {
|
|
181
|
+
return { userId: ObjectID.generate(), tenantId: ObjectID.generate() };
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
[
|
|
185
|
+
"a signed-in user with userType User",
|
|
186
|
+
(): DatabaseCommonInteractionProps => {
|
|
187
|
+
return { userId: ObjectID.generate(), userType: UserType.User };
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
[
|
|
191
|
+
"a project API key (no user)",
|
|
192
|
+
(): DatabaseCommonInteractionProps => {
|
|
193
|
+
return { tenantId: ObjectID.generate(), userType: UserType.API };
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
[
|
|
197
|
+
"a master-admin userType with no user",
|
|
198
|
+
(): DatabaseCommonInteractionProps => {
|
|
199
|
+
return { userType: UserType.MasterAdmin };
|
|
200
|
+
},
|
|
201
|
+
],
|
|
202
|
+
[
|
|
203
|
+
"isRoot with no user",
|
|
204
|
+
(): DatabaseCommonInteractionProps => {
|
|
205
|
+
return { isRoot: true };
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
[
|
|
209
|
+
"isMasterAdmin with no user",
|
|
210
|
+
(): DatabaseCommonInteractionProps => {
|
|
211
|
+
return { isMasterAdmin: true };
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
];
|
|
215
|
+
|
|
216
|
+
type RejectionOfFunction = (promise: Promise<unknown>) => Promise<unknown>;
|
|
217
|
+
|
|
218
|
+
// What the promise rejected with; fails the test if it resolved.
|
|
219
|
+
const rejectionOf: RejectionOfFunction = async (
|
|
220
|
+
promise: Promise<unknown>,
|
|
221
|
+
): Promise<unknown> => {
|
|
222
|
+
try {
|
|
223
|
+
await promise;
|
|
224
|
+
} catch (error) {
|
|
225
|
+
return error;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
throw new Error("Expected the permission check to reject, but it resolved.");
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
type ExpectNotAuthenticatedFunction = (error: unknown, message: string) => void;
|
|
232
|
+
|
|
233
|
+
const expectNotAuthenticated: ExpectNotAuthenticatedFunction = (
|
|
234
|
+
error: unknown,
|
|
235
|
+
message: string,
|
|
236
|
+
): void => {
|
|
237
|
+
expect(error).toBeInstanceOf(NotAuthenticatedException);
|
|
238
|
+
expect(error).not.toBeInstanceOf(NotAuthorizedException);
|
|
239
|
+
expect((error as Exception).code).toBe(
|
|
240
|
+
ExceptionCode.NotAuthenticatedException,
|
|
241
|
+
);
|
|
242
|
+
expect((error as Exception).code).toBe(401);
|
|
243
|
+
expect((error as Exception).message).toBe(message);
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
describe("ModelPermission: anonymous refusals become 401 (stubbed underlying checks)", () => {
|
|
247
|
+
afterEach(() => {
|
|
248
|
+
jest.restoreAllMocks();
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
describe.each(
|
|
252
|
+
entryPoints.map((entry: EntryPoint): [string, EntryPoint] => {
|
|
253
|
+
return [entry.name, entry];
|
|
254
|
+
}),
|
|
255
|
+
)("%s", (_name: string, entry: EntryPoint) => {
|
|
256
|
+
test.each(anonymousCases)(
|
|
257
|
+
"turns a NotAuthorizedException for %s into a 401 with the same message",
|
|
258
|
+
async (
|
|
259
|
+
_label: string,
|
|
260
|
+
makeProps: () => DatabaseCommonInteractionProps,
|
|
261
|
+
) => {
|
|
262
|
+
const original: NotAuthorizedException = new NotAuthorizedException(
|
|
263
|
+
REFUSAL_MESSAGE,
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
entry.stubUnderlying().mockImplementation(() => {
|
|
267
|
+
throw original;
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
const error: unknown = await rejectionOf(entry.call(makeProps()));
|
|
271
|
+
|
|
272
|
+
expectNotAuthenticated(error, REFUSAL_MESSAGE);
|
|
273
|
+
expect(error).not.toBe(original);
|
|
274
|
+
},
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
test.each(credentialedCases)(
|
|
278
|
+
"rethrows the original NotAuthorizedException for %s",
|
|
279
|
+
async (
|
|
280
|
+
_label: string,
|
|
281
|
+
makeProps: () => DatabaseCommonInteractionProps,
|
|
282
|
+
) => {
|
|
283
|
+
const original: NotAuthorizedException = new NotAuthorizedException(
|
|
284
|
+
REFUSAL_MESSAGE,
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
entry.stubUnderlying().mockImplementation(() => {
|
|
288
|
+
throw original;
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
const error: unknown = await rejectionOf(entry.call(makeProps()));
|
|
292
|
+
|
|
293
|
+
expect(error).toBe(original);
|
|
294
|
+
expect((error as Exception).code).toBe(422);
|
|
295
|
+
},
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
/*
|
|
299
|
+
* Only a NotAuthorizedException is converted. A 400 is the caller's data
|
|
300
|
+
* being wrong, whoever they are, and must reach the client unchanged; a
|
|
301
|
+
* 401 thrown further down is already the right answer.
|
|
302
|
+
*/
|
|
303
|
+
test.each([
|
|
304
|
+
[
|
|
305
|
+
"a BadDataException",
|
|
306
|
+
(): Error => {
|
|
307
|
+
return new BadDataException(REFUSAL_MESSAGE);
|
|
308
|
+
},
|
|
309
|
+
],
|
|
310
|
+
[
|
|
311
|
+
"a plain Error",
|
|
312
|
+
(): Error => {
|
|
313
|
+
return new Error(REFUSAL_MESSAGE);
|
|
314
|
+
},
|
|
315
|
+
],
|
|
316
|
+
[
|
|
317
|
+
"an existing NotAuthenticatedException",
|
|
318
|
+
(): Error => {
|
|
319
|
+
return new NotAuthenticatedException(REFUSAL_MESSAGE);
|
|
320
|
+
},
|
|
321
|
+
],
|
|
322
|
+
])(
|
|
323
|
+
"passes %s from an anonymous caller through unchanged",
|
|
324
|
+
async (_label: string, makeError: () => Error) => {
|
|
325
|
+
const original: Error = makeError();
|
|
326
|
+
|
|
327
|
+
entry.stubUnderlying().mockImplementation(() => {
|
|
328
|
+
throw original;
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
const error: unknown = await rejectionOf(entry.call({}));
|
|
332
|
+
|
|
333
|
+
expect(error).toBe(original);
|
|
334
|
+
},
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
test("passes the underlying return value through for an anonymous caller", async () => {
|
|
338
|
+
const sentinel: { sentinel: string } = { sentinel: entry.name };
|
|
339
|
+
|
|
340
|
+
const spy: jest.SpyInstance<any, any> = entry.stubUnderlying();
|
|
341
|
+
|
|
342
|
+
if (entry.name === "checkCreatePermissions") {
|
|
343
|
+
spy.mockImplementation(() => {
|
|
344
|
+
return sentinel;
|
|
345
|
+
});
|
|
346
|
+
} else {
|
|
347
|
+
spy.mockImplementation(async () => {
|
|
348
|
+
return sentinel;
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const props: DatabaseCommonInteractionProps = {
|
|
353
|
+
tenantId: ObjectID.generate(),
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
await expect(entry.call(props)).resolves.toBe(sentinel);
|
|
357
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
test("a rejected promise (not just a sync throw) is converted too", async () => {
|
|
361
|
+
if (entry.name === "checkCreatePermissions") {
|
|
362
|
+
// Create is synchronous; its sync throw is covered above.
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
entry.stubUnderlying().mockImplementation(async () => {
|
|
367
|
+
throw new NotAuthorizedException(REFUSAL_MESSAGE);
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
expectNotAuthenticated(
|
|
371
|
+
await rejectionOf(entry.call({})),
|
|
372
|
+
REFUSAL_MESSAGE,
|
|
373
|
+
);
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
/*
|
|
378
|
+
* checkCreatePermissions is synchronous, and DatabaseService calls it
|
|
379
|
+
* without awaiting. The conversion has to happen as a synchronous throw, not
|
|
380
|
+
* as a returned rejected promise nobody looks at.
|
|
381
|
+
*/
|
|
382
|
+
test("checkCreatePermissions converts synchronously", () => {
|
|
383
|
+
getJestSpyOn(CreatePermission, "checkCreatePermissions").mockImplementation(
|
|
384
|
+
() => {
|
|
385
|
+
throw new NotAuthorizedException(REFUSAL_MESSAGE);
|
|
386
|
+
},
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
let thrown: unknown = undefined;
|
|
390
|
+
|
|
391
|
+
try {
|
|
392
|
+
ModelPermission.checkCreatePermissions(Probe, new Probe(), {});
|
|
393
|
+
} catch (error) {
|
|
394
|
+
thrown = error;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
expectNotAuthenticated(thrown, REFUSAL_MESSAGE);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
test("hands the caller's arguments to the underlying check unchanged", async () => {
|
|
401
|
+
const spy: jest.SpyInstance<any, any> = getJestSpyOn(
|
|
402
|
+
ReadPermission,
|
|
403
|
+
"checkReadPermission",
|
|
404
|
+
).mockImplementation(async () => {
|
|
405
|
+
return { query: {}, select: null, relationSelect: null };
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
const props: DatabaseCommonInteractionProps = {
|
|
409
|
+
tenantId: ObjectID.generate(),
|
|
410
|
+
};
|
|
411
|
+
const query: Record<string, unknown> = { name: "probe-1" };
|
|
412
|
+
const select: Record<string, boolean> = { name: true };
|
|
413
|
+
|
|
414
|
+
await ModelPermission.checkReadQueryPermission(Probe, query, select, props);
|
|
415
|
+
|
|
416
|
+
expect(spy).toHaveBeenCalledWith(Probe, query, select, props);
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
/*
|
|
421
|
+
* The real thing, no stubs. Probe's table read list carries Permission.Public
|
|
422
|
+
* (status pages show probe names to logged-out visitors), so an anonymous
|
|
423
|
+
* read of Probe gets past the login check. Its `key` column is readable only
|
|
424
|
+
* by ProjectOwner / ProjectAdmin, so selecting it is refused by
|
|
425
|
+
* SelectPermission with a NotAuthorizedException - exactly the 422 an expired
|
|
426
|
+
* dashboard session used to get on the probes page.
|
|
427
|
+
*/
|
|
428
|
+
describe("ModelPermission: anonymous refusals become 401 (real permission layer)", () => {
|
|
429
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
430
|
+
|
|
431
|
+
type ReadKeyFunction = (
|
|
432
|
+
props: DatabaseCommonInteractionProps,
|
|
433
|
+
) => Promise<unknown>;
|
|
434
|
+
|
|
435
|
+
const readProbeKey: ReadKeyFunction = async (
|
|
436
|
+
props: DatabaseCommonInteractionProps,
|
|
437
|
+
): Promise<unknown> => {
|
|
438
|
+
return await ModelPermission.checkReadQueryPermission(
|
|
439
|
+
Probe,
|
|
440
|
+
{},
|
|
441
|
+
{ key: true },
|
|
442
|
+
props,
|
|
443
|
+
);
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
test("the fixture: Probe is publicly readable but its key column is not", () => {
|
|
447
|
+
expect(new Probe().readRecordPermissions).toContain(Permission.Public);
|
|
448
|
+
expect(new Probe().getColumnAccessControlFor("key")!.read).not.toContain(
|
|
449
|
+
Permission.Public,
|
|
450
|
+
);
|
|
451
|
+
expect(new Probe().getColumnAccessControlFor("name")!.read).toContain(
|
|
452
|
+
Permission.Public,
|
|
453
|
+
);
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
test.each([
|
|
457
|
+
["with a tenant", { tenantId: projectId }],
|
|
458
|
+
[
|
|
459
|
+
"with a tenant and a Public userType",
|
|
460
|
+
{ tenantId: projectId, userType: UserType.Public },
|
|
461
|
+
],
|
|
462
|
+
])(
|
|
463
|
+
"an anonymous caller (%s) selecting a non-public column gets a 401",
|
|
464
|
+
async (_label: string, props: DatabaseCommonInteractionProps) => {
|
|
465
|
+
const error: unknown = await rejectionOf(readProbeKey(props));
|
|
466
|
+
|
|
467
|
+
expect(error).toBeInstanceOf(NotAuthenticatedException);
|
|
468
|
+
expect((error as Exception).code).toBe(401);
|
|
469
|
+
// The select refusal's own wording survives the conversion.
|
|
470
|
+
expect((error as Exception).message).toContain(
|
|
471
|
+
"You do not have permissions to select on - key.",
|
|
472
|
+
);
|
|
473
|
+
},
|
|
474
|
+
);
|
|
475
|
+
|
|
476
|
+
/*
|
|
477
|
+
* The same refusal for a caller who has credentials stays the 422 it always
|
|
478
|
+
* was: a project API key without ProjectOwner/ProjectAdmin really may not
|
|
479
|
+
* see probe keys, and refreshing a session would not change that.
|
|
480
|
+
*/
|
|
481
|
+
test("a project API key selecting the same column still gets the 422", async () => {
|
|
482
|
+
const error: unknown = await rejectionOf(
|
|
483
|
+
readProbeKey({ tenantId: projectId, userType: UserType.API }),
|
|
484
|
+
);
|
|
485
|
+
|
|
486
|
+
expect(error).toBeInstanceOf(NotAuthorizedException);
|
|
487
|
+
expect(error).not.toBeInstanceOf(NotAuthenticatedException);
|
|
488
|
+
expect((error as Exception).code).toBe(422);
|
|
489
|
+
expect((error as Exception).message).toContain(
|
|
490
|
+
"You do not have permissions to select on - key.",
|
|
491
|
+
);
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
test("a signed-in user without the column permission still gets the 422", async () => {
|
|
495
|
+
const error: unknown = await rejectionOf(
|
|
496
|
+
readProbeKey({
|
|
497
|
+
tenantId: projectId,
|
|
498
|
+
userId: ObjectID.generate(),
|
|
499
|
+
userType: UserType.User,
|
|
500
|
+
}),
|
|
501
|
+
);
|
|
502
|
+
|
|
503
|
+
expect(error).toBeInstanceOf(NotAuthorizedException);
|
|
504
|
+
expect((error as Exception).code).toBe(422);
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
// Control: the anonymous read itself is allowed; only the column is refused.
|
|
508
|
+
test("an anonymous caller selecting only public columns is not refused", async () => {
|
|
509
|
+
await expect(
|
|
510
|
+
ModelPermission.checkReadQueryPermission(
|
|
511
|
+
Probe,
|
|
512
|
+
{},
|
|
513
|
+
{ name: true },
|
|
514
|
+
{ tenantId: projectId },
|
|
515
|
+
),
|
|
516
|
+
).resolves.toBeDefined();
|
|
517
|
+
});
|
|
518
|
+
});
|