@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
|
@@ -495,6 +495,49 @@ export default class UserMiddleware {
|
|
|
495
495
|
req: ExpressRequest,
|
|
496
496
|
res: ExpressResponse,
|
|
497
497
|
next: NextFunction,
|
|
498
|
+
): Promise<void> {
|
|
499
|
+
return await UserMiddleware.resolveRequestUser(req, res, next, {
|
|
500
|
+
treatInvalidAccessTokenAsAnonymous: false,
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/*
|
|
505
|
+
* getUserMiddleware for the anonymous surfaces: the public dashboard and
|
|
506
|
+
* public status page routes. Their handlers decide access themselves
|
|
507
|
+
* (DashboardService / StatusPageService.hasReadAccess: public flag, IP
|
|
508
|
+
* allowlist, master-password cookie, the page's own session cookie) and
|
|
509
|
+
* never read the caller's user identity.
|
|
510
|
+
*
|
|
511
|
+
* The one difference: an access token that is present but cannot be decoded
|
|
512
|
+
* makes the request anonymous (UserType.Public) instead of answering 401.
|
|
513
|
+
* The host-wide dashboard access-token cookie reaches these routes whenever
|
|
514
|
+
* the page is served from the dashboard's host (the preview routes), and it
|
|
515
|
+
* can stay in the browser after it stops decoding - an encryption-secret
|
|
516
|
+
* rotation, say. The public clients cannot refresh a dashboard session, so
|
|
517
|
+
* that 401 only ever meant "sent back to the login route": a reload loop on
|
|
518
|
+
* the preview route, and a password prompt for a master password the viewer
|
|
519
|
+
* already entered.
|
|
520
|
+
*
|
|
521
|
+
* A token that does decode is still resolved exactly as getUserMiddleware
|
|
522
|
+
* resolves it, and an API key is still validated. Never mount this on a
|
|
523
|
+
* route that needs to know who the caller is.
|
|
524
|
+
*/
|
|
525
|
+
@CaptureSpan()
|
|
526
|
+
public static async getPublicRouteUserMiddleware(
|
|
527
|
+
req: ExpressRequest,
|
|
528
|
+
res: ExpressResponse,
|
|
529
|
+
next: NextFunction,
|
|
530
|
+
): Promise<void> {
|
|
531
|
+
return await UserMiddleware.resolveRequestUser(req, res, next, {
|
|
532
|
+
treatInvalidAccessTokenAsAnonymous: true,
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
private static async resolveRequestUser(
|
|
537
|
+
req: ExpressRequest,
|
|
538
|
+
res: ExpressResponse,
|
|
539
|
+
next: NextFunction,
|
|
540
|
+
options: { treatInvalidAccessTokenAsAnonymous: boolean },
|
|
498
541
|
): Promise<void> {
|
|
499
542
|
const tenantId: ObjectID | null = ProjectMiddleware.getProjectId(req);
|
|
500
543
|
const oneuptimeRequest: OneUptimeRequest = req as OneUptimeRequest;
|
|
@@ -529,6 +572,12 @@ export default class UserMiddleware {
|
|
|
529
572
|
try {
|
|
530
573
|
oneuptimeRequest.userAuthorization = JSONWebToken.decode(accessToken);
|
|
531
574
|
} catch (err) {
|
|
575
|
+
if (options.treatInvalidAccessTokenAsAnonymous) {
|
|
576
|
+
// decode() has already logged why the token was refused.
|
|
577
|
+
oneuptimeRequest.userType = UserType.Public;
|
|
578
|
+
return next();
|
|
579
|
+
}
|
|
580
|
+
|
|
532
581
|
// if the token is invalid or expired, return 401 so clients can refresh the token.
|
|
533
582
|
logger.error(err, getLogAttributesFromRequest(oneuptimeRequest));
|
|
534
583
|
return Response.sendErrorResponse(
|
|
@@ -712,15 +761,12 @@ export default class UserMiddleware {
|
|
|
712
761
|
): Promise<void> {
|
|
713
762
|
const oneuptimeRequest: OneUptimeRequest = req as OneUptimeRequest;
|
|
714
763
|
|
|
715
|
-
if (
|
|
716
|
-
!oneuptimeRequest.userType ||
|
|
717
|
-
oneuptimeRequest.userType === UserType.Public
|
|
718
|
-
) {
|
|
764
|
+
if (UserMiddleware.isAnonymousRequest(oneuptimeRequest)) {
|
|
719
765
|
return Response.sendErrorResponse(
|
|
720
766
|
req,
|
|
721
767
|
res,
|
|
722
768
|
new NotAuthenticatedException(
|
|
723
|
-
|
|
769
|
+
UserMiddleware.AUTHENTICATION_REQUIRED_MESSAGE,
|
|
724
770
|
),
|
|
725
771
|
);
|
|
726
772
|
}
|
|
@@ -728,6 +774,19 @@ export default class UserMiddleware {
|
|
|
728
774
|
return next();
|
|
729
775
|
}
|
|
730
776
|
|
|
777
|
+
// Same wording as CommonAPI.AUTHENTICATION_REQUIRED_MESSAGE.
|
|
778
|
+
public static readonly AUTHENTICATION_REQUIRED_MESSAGE: string =
|
|
779
|
+
"Authentication required. Please log in to access this resource.";
|
|
780
|
+
|
|
781
|
+
/*
|
|
782
|
+
* The request-level twin of CommonAPI.isAnonymous: getUserMiddleware found
|
|
783
|
+
* no access token and no API key. Usually an expired session, since the
|
|
784
|
+
* access-token cookie expires with the JWT inside it.
|
|
785
|
+
*/
|
|
786
|
+
public static isAnonymousRequest(req: OneUptimeRequest): boolean {
|
|
787
|
+
return !req.userType || req.userType === UserType.Public;
|
|
788
|
+
}
|
|
789
|
+
|
|
731
790
|
public static requirePermission(data: {
|
|
732
791
|
permissions: Array<Permission>;
|
|
733
792
|
}): (
|
|
@@ -742,6 +801,21 @@ export default class UserMiddleware {
|
|
|
742
801
|
): Promise<void> => {
|
|
743
802
|
const oneuptimeRequest: OneUptimeRequest = req as OneUptimeRequest;
|
|
744
803
|
|
|
804
|
+
/*
|
|
805
|
+
* An anonymous caller has no permissions to compare, and telling it so
|
|
806
|
+
* with a 422 would stop the browser client from refreshing an expired
|
|
807
|
+
* session. Ask who it is first.
|
|
808
|
+
*/
|
|
809
|
+
if (UserMiddleware.isAnonymousRequest(oneuptimeRequest)) {
|
|
810
|
+
return Response.sendErrorResponse(
|
|
811
|
+
req,
|
|
812
|
+
res,
|
|
813
|
+
new NotAuthenticatedException(
|
|
814
|
+
UserMiddleware.AUTHENTICATION_REQUIRED_MESSAGE,
|
|
815
|
+
),
|
|
816
|
+
);
|
|
817
|
+
}
|
|
818
|
+
|
|
745
819
|
// Master admins bypass permission checks
|
|
746
820
|
if (oneuptimeRequest.userType === UserType.MasterAdmin) {
|
|
747
821
|
return next();
|
|
@@ -2,6 +2,7 @@ import CreateBy from "../Types/Database/CreateBy";
|
|
|
2
2
|
import DeleteBy from "../Types/Database/DeleteBy";
|
|
3
3
|
import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
|
|
4
4
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
5
|
+
import ModelPermission from "../Types/Database/Permissions/Index";
|
|
5
6
|
import UpdateBy from "../Types/Database/UpdateBy";
|
|
6
7
|
import ApiKeyService from "./ApiKeyService";
|
|
7
8
|
import DatabaseService from "./DatabaseService";
|
|
@@ -10,7 +11,7 @@ import DatabaseCommonInteractionPropsUtil, {
|
|
|
10
11
|
PermissionType,
|
|
11
12
|
} from "../../Types/BaseDatabase/DatabaseCommonInteractionPropsUtil";
|
|
12
13
|
import PermissionScope from "../../Types/Database/AccessControl/PermissionScope";
|
|
13
|
-
import LIMIT_MAX
|
|
14
|
+
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
14
15
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
15
16
|
import Exception from "../../Types/Exception/Exception";
|
|
16
17
|
import NotAuthorizedException from "../../Types/Exception/NotAuthorizedException";
|
|
@@ -493,8 +494,27 @@ export class Service extends DatabaseService<Model> {
|
|
|
493
494
|
*/
|
|
494
495
|
this.clearCache();
|
|
495
496
|
|
|
496
|
-
|
|
497
|
+
updateBy.query = await ModelPermission.checkUpdateQueryPermissions(
|
|
498
|
+
Model,
|
|
499
|
+
updateBy.query,
|
|
500
|
+
updateBy.data,
|
|
501
|
+
updateBy.props,
|
|
502
|
+
);
|
|
503
|
+
const selectedPermissions: Array<Model> = await this.findAllBy({
|
|
497
504
|
query: updateBy.query,
|
|
505
|
+
select: { _id: true },
|
|
506
|
+
skip: updateBy.skip,
|
|
507
|
+
limit: updateBy.limit,
|
|
508
|
+
props: { isRoot: true },
|
|
509
|
+
});
|
|
510
|
+
const selectedIds: Array<ObjectID> = selectedPermissions.map(
|
|
511
|
+
(row: Model) => {
|
|
512
|
+
return row.id!;
|
|
513
|
+
},
|
|
514
|
+
);
|
|
515
|
+
// Reload by ID so a label filter cannot hide part of a saved block's scope.
|
|
516
|
+
const existingPermissions: Array<Model> = await this.findAllBy({
|
|
517
|
+
query: { _id: QueryHelper.any(selectedIds) },
|
|
498
518
|
select: {
|
|
499
519
|
_id: true,
|
|
500
520
|
labels: true,
|
|
@@ -503,8 +523,6 @@ export class Service extends DatabaseService<Model> {
|
|
|
503
523
|
apiKeyId: true,
|
|
504
524
|
permission: true,
|
|
505
525
|
},
|
|
506
|
-
limit: LIMIT_PER_PROJECT,
|
|
507
|
-
skip: 0,
|
|
508
526
|
props: {
|
|
509
527
|
isRoot: true,
|
|
510
528
|
},
|
|
@@ -565,6 +583,15 @@ export class Service extends DatabaseService<Model> {
|
|
|
565
583
|
}
|
|
566
584
|
|
|
567
585
|
await this.assertApiKeyBelongsToProject(apiKeyId, projectId);
|
|
586
|
+
// Changing a block's permission or labels can restore its old scope.
|
|
587
|
+
if (existingPermission.isBlockPermission) {
|
|
588
|
+
this.assertCallerCanGrantPermission({
|
|
589
|
+
permission: existingPermission.permission!,
|
|
590
|
+
labels: existingPermission.labels,
|
|
591
|
+
projectId,
|
|
592
|
+
props: updateBy.props,
|
|
593
|
+
});
|
|
594
|
+
}
|
|
568
595
|
this.assertCallerCanGrantPermission({
|
|
569
596
|
permission,
|
|
570
597
|
labels: isLabelsUpdateRequested
|
|
@@ -647,6 +674,8 @@ export class Service extends DatabaseService<Model> {
|
|
|
647
674
|
}
|
|
648
675
|
}
|
|
649
676
|
|
|
677
|
+
updateBy.query = { ...updateBy.query, _id: QueryHelper.any(selectedIds) };
|
|
678
|
+
updateBy.skip = 0;
|
|
650
679
|
return { updateBy, carryForward: null };
|
|
651
680
|
}
|
|
652
681
|
|
|
@@ -655,6 +684,74 @@ export class Service extends DatabaseService<Model> {
|
|
|
655
684
|
deleteBy: DeleteBy<Model>,
|
|
656
685
|
): Promise<OnDelete<Model>> {
|
|
657
686
|
this.clearCache();
|
|
687
|
+
|
|
688
|
+
if (!deleteBy.props.isRoot && !deleteBy.props.isMasterAdmin) {
|
|
689
|
+
// Hooks run before DatabaseService applies the delete ACL and tenant.
|
|
690
|
+
deleteBy.query = await ModelPermission.checkDeleteQueryPermission(
|
|
691
|
+
Model,
|
|
692
|
+
deleteBy.query,
|
|
693
|
+
deleteBy.props,
|
|
694
|
+
);
|
|
695
|
+
const selectedPermissions: Array<Model> = await this.findAllBy({
|
|
696
|
+
query: deleteBy.query,
|
|
697
|
+
select: { _id: true },
|
|
698
|
+
skip: deleteBy.skip,
|
|
699
|
+
limit: deleteBy.limit,
|
|
700
|
+
props: { isRoot: true },
|
|
701
|
+
});
|
|
702
|
+
const selectedIds: Array<ObjectID> = selectedPermissions.map(
|
|
703
|
+
(row: Model) => {
|
|
704
|
+
return row.id!;
|
|
705
|
+
},
|
|
706
|
+
);
|
|
707
|
+
// A relation filter may select a row, but must not trim its saved labels.
|
|
708
|
+
const permissions: Array<Model> = await this.findAllBy({
|
|
709
|
+
query: { _id: QueryHelper.any(selectedIds) },
|
|
710
|
+
select: {
|
|
711
|
+
_id: true,
|
|
712
|
+
projectId: true,
|
|
713
|
+
permission: true,
|
|
714
|
+
labels: { _id: true },
|
|
715
|
+
isBlockPermission: true,
|
|
716
|
+
},
|
|
717
|
+
props: { isRoot: true },
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
for (const permission of permissions) {
|
|
721
|
+
/*
|
|
722
|
+
* Revoking an allow cannot expand access. Removing a deny can expose
|
|
723
|
+
* an existing allow, so it requires authority over the entire deny.
|
|
724
|
+
*/
|
|
725
|
+
if (permission.isBlockPermission) {
|
|
726
|
+
if (!permission.projectId || !permission.permission) {
|
|
727
|
+
throw new BadDataException("Invalid API Key permission");
|
|
728
|
+
}
|
|
729
|
+
if (
|
|
730
|
+
!deleteBy.props.tenantId ||
|
|
731
|
+
deleteBy.props.tenantId.toString() !==
|
|
732
|
+
permission.projectId.toString()
|
|
733
|
+
) {
|
|
734
|
+
throw new BadDataException("Invalid API Key ID for this project");
|
|
735
|
+
}
|
|
736
|
+
this.assertCallerCanGrantPermission({
|
|
737
|
+
permission: permission.permission,
|
|
738
|
+
labels: permission.labels,
|
|
739
|
+
projectId: permission.projectId,
|
|
740
|
+
props: deleteBy.props,
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
/*
|
|
746
|
+
* Delete exactly the checked page, even when the query matches more
|
|
747
|
+
* than one batch. The original offset has already been applied.
|
|
748
|
+
*/
|
|
749
|
+
deleteBy.query = {
|
|
750
|
+
...deleteBy.query,
|
|
751
|
+
_id: QueryHelper.any(selectedIds),
|
|
752
|
+
};
|
|
753
|
+
deleteBy.skip = 0;
|
|
754
|
+
}
|
|
658
755
|
return { deleteBy, carryForward: null };
|
|
659
756
|
}
|
|
660
757
|
|
|
@@ -22,6 +22,8 @@ import {
|
|
|
22
22
|
OnUpdate,
|
|
23
23
|
} from "../Types/Database/Hooks";
|
|
24
24
|
import ModelPermission from "../Types/Database/Permissions/Index";
|
|
25
|
+
import PublicPermission from "../Types/Database/Permissions/PublicPermission";
|
|
26
|
+
import DatabaseRequestType from "../Types/BaseDatabase/DatabaseRequestType";
|
|
25
27
|
import OwnerOnlyColumnPermission from "../Types/Database/Permissions/OwnerOnlyColumnPermission";
|
|
26
28
|
import { CheckReadPermissionType } from "../Types/Database/Permissions/ReadPermission";
|
|
27
29
|
import Query from "../Types/Database/Query";
|
|
@@ -57,6 +59,7 @@ import PartialEntity from "../../Types/Database/PartialEntity";
|
|
|
57
59
|
import { TableColumnMetadata } from "../../Types/Database/TableColumn";
|
|
58
60
|
import TableColumnType from "../../Types/Database/TableColumnType";
|
|
59
61
|
import { getUniqueColumnsBy } from "../../Types/Database/UniqueColumnBy";
|
|
62
|
+
import QueryOperator from "../../Types/BaseDatabase/QueryOperator";
|
|
60
63
|
import OneUptimeDate from "../../Types/Date";
|
|
61
64
|
import Dictionary from "../../Types/Dictionary";
|
|
62
65
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
@@ -96,6 +99,7 @@ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
|
96
99
|
import type AuditLogServiceType from "./AuditLogService";
|
|
97
100
|
import EnableAuditLogOn from "../../Types/BaseDatabase/EnableAuditLogOn";
|
|
98
101
|
import RelationValueUtil from "../Utils/Database/RelationValueUtil";
|
|
102
|
+
import RelationIdUtil from "../Utils/Database/RelationIdUtil";
|
|
99
103
|
|
|
100
104
|
const RULE_CRITERIA_RELATION_OPERATORS: ReadonlySet<RuleCriteriaOperator> =
|
|
101
105
|
new Set<RuleCriteriaOperator>([
|
|
@@ -295,6 +299,31 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
295
299
|
return data;
|
|
296
300
|
}
|
|
297
301
|
|
|
302
|
+
/*
|
|
303
|
+
* The permission layer's login check, run BEFORE the hooks instead of only
|
|
304
|
+
* after them.
|
|
305
|
+
*
|
|
306
|
+
* The hooks run first, and many of them key off props.userId: a missing one
|
|
307
|
+
* reads as "userId is required" (400), "User should be logged in" (422), or,
|
|
308
|
+
* for Project reads, an empty list with a 200. For an anonymous caller that
|
|
309
|
+
* is almost always a dashboard tab whose access-token cookie expired, and
|
|
310
|
+
* only a 401 makes the browser client refresh the session and replay the
|
|
311
|
+
* request. Everything this admits, the permission check would have admitted
|
|
312
|
+
* too (same condition, same exemptions for API keys and public models), so
|
|
313
|
+
* it only changes which refusal an anonymous caller gets, and it keeps hooks
|
|
314
|
+
* with side effects from running for them at all.
|
|
315
|
+
*/
|
|
316
|
+
private checkIfUserIsLoggedInBeforeHooks(
|
|
317
|
+
props: DatabaseCommonInteractionProps,
|
|
318
|
+
type: DatabaseRequestType,
|
|
319
|
+
): void {
|
|
320
|
+
if (props.isRoot || props.isMasterAdmin) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
PublicPermission.checkIfUserIsLoggedIn(this.modelType, props, type);
|
|
325
|
+
}
|
|
326
|
+
|
|
298
327
|
protected async onBeforeCreate(
|
|
299
328
|
createBy: CreateBy<TBaseModel>,
|
|
300
329
|
): Promise<OnCreate<TBaseModel>> {
|
|
@@ -347,6 +376,49 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
347
376
|
}
|
|
348
377
|
}
|
|
349
378
|
|
|
379
|
+
/*
|
|
380
|
+
* Query operators (StartsWith, NotNull, Search, GreaterThan, Includes...)
|
|
381
|
+
* belong in the `query` of a read/update, never in the `data` of a write.
|
|
382
|
+
* They can reach create/update data because JSONFunctions.deserialize - run
|
|
383
|
+
* on every request body while building the model - turns
|
|
384
|
+
* `{"_type":"StartsWith","value":"a"}` into a real operator instance, and
|
|
385
|
+
* DatabaseBaseModel._fromJSON assigns it to an id/text column unchanged.
|
|
386
|
+
*
|
|
387
|
+
* An operator is never a valid stored value, and leaving one on a write
|
|
388
|
+
* payload also feeds it to the lookups built from that data - the uniqueness
|
|
389
|
+
* check here and the findBy/countBy calls in service hooks - where QueryUtil
|
|
390
|
+
* turns the intended exact comparison into a pattern match, quietly matching
|
|
391
|
+
* rows the caller never named. Refuse such a write up front instead. JSON
|
|
392
|
+
* columns are exempt: they legitimately hold arbitrary objects, and their
|
|
393
|
+
* values are not used to build a query.
|
|
394
|
+
*/
|
|
395
|
+
private rejectQueryOperatorsInData(
|
|
396
|
+
data: TBaseModel | PartialEntity<TBaseModel>,
|
|
397
|
+
): void {
|
|
398
|
+
for (const columnName of Object.keys(data)) {
|
|
399
|
+
const value: unknown = (data as Record<string, unknown>)[columnName];
|
|
400
|
+
|
|
401
|
+
if (!(value instanceof QueryOperator)) {
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (!this.model.isTableColumn(columnName)) {
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const metadata: TableColumnMetadata =
|
|
410
|
+
this.model.getTableColumnMetadata(columnName);
|
|
411
|
+
|
|
412
|
+
if (metadata && metadata.type === TableColumnType.JSON) {
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
throw new BadDataException(
|
|
417
|
+
`Invalid value for ${columnName}. A query operator cannot be used as a value when creating or updating ${this.model.singularName}.`,
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
350
422
|
/*
|
|
351
423
|
* Rows written before the fix above hold their ciphertext inside that
|
|
352
424
|
* HashedString envelope. Decrypting the envelope itself is not just wrong
|
|
@@ -984,6 +1056,107 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
984
1056
|
RULE_CRITERIA_LEGACY_NEVER_MATCH_PATTERN;
|
|
985
1057
|
}
|
|
986
1058
|
|
|
1059
|
+
/*
|
|
1060
|
+
* A tenant model declares its tenant TWICE: a scalar column (e.g.
|
|
1061
|
+
* `projectId`) AND a ManyToOne relation (`project`) whose @JoinColumn names
|
|
1062
|
+
* that same scalar. Both are separately writable through the public API, and
|
|
1063
|
+
* both land on the entity that reaches getRepository().save()/update().
|
|
1064
|
+
* TypeORM (metadata/ColumnMetadata.js getEntityValue) resolves the relation
|
|
1065
|
+
* object to the join-column value with PRECEDENCE over the scalar, so a
|
|
1066
|
+
* request carrying `project: { _id: <another project> }` is persisted under
|
|
1067
|
+
* THAT project even though create() has just stamped the scalar to
|
|
1068
|
+
* props.tenantId. That is a cross-tenant write of the whole row (reproduced
|
|
1069
|
+
* end to end: the generated INSERT binds `projectId` to the relation's id,
|
|
1070
|
+
* not the stamped scalar).
|
|
1071
|
+
*
|
|
1072
|
+
* The stamped scalar is the authoritative tenant for every non-root write,
|
|
1073
|
+
* and no `project` relation in the schema legitimately points at a project
|
|
1074
|
+
* other than the tenant (every one joins on `projectId`; there is no second,
|
|
1075
|
+
* foreign-project reference to preserve). So neutralize the relation
|
|
1076
|
+
* spelling: reject a tenant relation that points anywhere other than the
|
|
1077
|
+
* request tenant, then delete it so the scalar is the single source of truth
|
|
1078
|
+
* and no TypeORM precedence rule between the two can move the row. This is
|
|
1079
|
+
* the framework-level generalisation of the per-service fixes already
|
|
1080
|
+
* shipped in ApiKeyPermissionService and UserTelegramService.
|
|
1081
|
+
*
|
|
1082
|
+
* Root / master-admin / internal callers are left untouched — they have no
|
|
1083
|
+
* request tenant (props.tenantId is unset) and legitimately set the tenant
|
|
1084
|
+
* relation for another project during seeding, migrations and
|
|
1085
|
+
* invitation-acceptance. This mirrors the create() scalar stamp, which is
|
|
1086
|
+
* likewise gated on props.tenantId.
|
|
1087
|
+
*/
|
|
1088
|
+
private enforceTenantRelationMatchesScalar(
|
|
1089
|
+
data: TBaseModel | PartialEntity<TBaseModel>,
|
|
1090
|
+
props: DatabaseCommonInteractionProps,
|
|
1091
|
+
): void {
|
|
1092
|
+
if (props.isRoot || props.isMasterAdmin) {
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
const tenantColumn: string | null = this.model.getTenantColumn();
|
|
1097
|
+
|
|
1098
|
+
if (!tenantColumn || !props.tenantId) {
|
|
1099
|
+
return;
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
const tenantRelationProperty: string | null =
|
|
1103
|
+
this.getTenantRelationProperty(tenantColumn);
|
|
1104
|
+
|
|
1105
|
+
if (!tenantRelationProperty) {
|
|
1106
|
+
/*
|
|
1107
|
+
* e.g. Project itself, whose tenant column is its own `_id`, has no such
|
|
1108
|
+
* relation; global (non-tenant) models return null from getTenantColumn.
|
|
1109
|
+
*/
|
|
1110
|
+
return;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
const suppliedRelation: unknown = (data as Record<string, unknown>)[
|
|
1114
|
+
tenantRelationProperty
|
|
1115
|
+
];
|
|
1116
|
+
|
|
1117
|
+
if (suppliedRelation === undefined) {
|
|
1118
|
+
return;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
const relationTenantId: ObjectID | null = RelationIdUtil.read(
|
|
1122
|
+
data as Record<string, unknown>,
|
|
1123
|
+
[tenantRelationProperty],
|
|
1124
|
+
);
|
|
1125
|
+
|
|
1126
|
+
if (
|
|
1127
|
+
relationTenantId &&
|
|
1128
|
+
relationTenantId.toString() !== props.tenantId.toString()
|
|
1129
|
+
) {
|
|
1130
|
+
throw new BadDataException(
|
|
1131
|
+
`The ${tenantRelationProperty} relation does not belong to this project.`,
|
|
1132
|
+
);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
delete (data as Record<string, unknown>)[tenantRelationProperty];
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
/*
|
|
1139
|
+
* Property name of the ManyToOne relation that shares the tenant scalar
|
|
1140
|
+
* column as its join column (`project` for the `projectId` tenant column),
|
|
1141
|
+
* or null when the model has no such relation.
|
|
1142
|
+
*/
|
|
1143
|
+
private getTenantRelationProperty(tenantColumn: string): string | null {
|
|
1144
|
+
for (const columnName of this.model.getTableColumns().columns) {
|
|
1145
|
+
const metadata: TableColumnMetadata | undefined =
|
|
1146
|
+
this.model.getTableColumnMetadata(columnName);
|
|
1147
|
+
|
|
1148
|
+
if (
|
|
1149
|
+
metadata &&
|
|
1150
|
+
metadata.type === TableColumnType.Entity &&
|
|
1151
|
+
metadata.manyToOneRelationColumn === tenantColumn
|
|
1152
|
+
) {
|
|
1153
|
+
return columnName;
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
return null;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
987
1160
|
private async sanitizeCreateOrUpdate(
|
|
988
1161
|
data: TBaseModel | PartialEntity<TBaseModel>,
|
|
989
1162
|
props: DatabaseCommonInteractionProps,
|
|
@@ -1368,6 +1541,34 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
1368
1541
|
|
|
1369
1542
|
@CaptureSpan()
|
|
1370
1543
|
public async create(createBy: CreateBy<TBaseModel>): Promise<TBaseModel> {
|
|
1544
|
+
this.checkIfUserIsLoggedInBeforeHooks(
|
|
1545
|
+
createBy.props,
|
|
1546
|
+
DatabaseRequestType.Create,
|
|
1547
|
+
);
|
|
1548
|
+
|
|
1549
|
+
/*
|
|
1550
|
+
* A non-root create must not pin the row's own primary key. save() treats
|
|
1551
|
+
* an entity carrying an existing id as an update of that row rather than an
|
|
1552
|
+
* insert, so a supplied `_id` turns a create into an in-place modification
|
|
1553
|
+
* of a record the caller never named. BaseAPI.createItem already strips it;
|
|
1554
|
+
* this guards every other non-root caller (custom routes, workflow
|
|
1555
|
+
* components) too. Root/internal seeding legitimately assigns ids and is
|
|
1556
|
+
* exempt. Only the top-level primary key is checked - nested relation
|
|
1557
|
+
* `_id`s reference existing related rows and are fine.
|
|
1558
|
+
*/
|
|
1559
|
+
if (
|
|
1560
|
+
!createBy.props.isRoot &&
|
|
1561
|
+
!createBy.props.isMasterAdmin &&
|
|
1562
|
+
(createBy.data as TBaseModel)._id
|
|
1563
|
+
) {
|
|
1564
|
+
throw new BadDataException(
|
|
1565
|
+
`An id cannot be supplied when creating ${this.model.singularName}.`,
|
|
1566
|
+
);
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
// Query operators are for queries, not for write payloads. See the helper.
|
|
1570
|
+
this.rejectQueryOperatorsInData(createBy.data);
|
|
1571
|
+
|
|
1371
1572
|
this.unwrapHashedStringsForUnhashedColumns(createBy.data);
|
|
1372
1573
|
|
|
1373
1574
|
const onCreate: OnCreate<TBaseModel> = createBy.props.ignoreHooks
|
|
@@ -1389,6 +1590,15 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
1389
1590
|
data.setColumnValue(tenantColumnName, _createdBy.props.tenantId);
|
|
1390
1591
|
}
|
|
1391
1592
|
|
|
1593
|
+
/*
|
|
1594
|
+
* The tenant scalar has just been stamped to the request tenant, but the
|
|
1595
|
+
* matching tenant RELATION object (e.g. `project`) is still whatever the
|
|
1596
|
+
* caller sent, and TypeORM lets that relation override the scalar on the
|
|
1597
|
+
* INSERT. Force the relation to agree with — or be dropped in favour of —
|
|
1598
|
+
* the stamped scalar so a caller cannot write the row into another tenant.
|
|
1599
|
+
*/
|
|
1600
|
+
this.enforceTenantRelationMatchesScalar(data, _createdBy.props);
|
|
1601
|
+
|
|
1392
1602
|
data = this.generateDefaultValues(data);
|
|
1393
1603
|
|
|
1394
1604
|
data = this.checkRequiredFields(data);
|
|
@@ -2291,6 +2501,11 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
2291
2501
|
@CaptureSpan()
|
|
2292
2502
|
public async hardDeleteBy(deleteBy: DeleteBy<TBaseModel>): Promise<number> {
|
|
2293
2503
|
try {
|
|
2504
|
+
this.checkIfUserIsLoggedInBeforeHooks(
|
|
2505
|
+
deleteBy.props,
|
|
2506
|
+
DatabaseRequestType.Delete,
|
|
2507
|
+
);
|
|
2508
|
+
|
|
2294
2509
|
const onDelete: OnDelete<TBaseModel> = deleteBy.props.ignoreHooks
|
|
2295
2510
|
? { deleteBy, carryForward: [] }
|
|
2296
2511
|
: await this.onBeforeDelete(deleteBy);
|
|
@@ -2353,6 +2568,11 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
2353
2568
|
try {
|
|
2354
2569
|
this.setTelemetryContextFromProps(deleteBy.props);
|
|
2355
2570
|
|
|
2571
|
+
this.checkIfUserIsLoggedInBeforeHooks(
|
|
2572
|
+
deleteBy.props,
|
|
2573
|
+
DatabaseRequestType.Delete,
|
|
2574
|
+
);
|
|
2575
|
+
|
|
2356
2576
|
if (this.doNotAllowDelete && !deleteBy.props.isRoot) {
|
|
2357
2577
|
throw new BadDataException("Delete not allowed");
|
|
2358
2578
|
}
|
|
@@ -2587,6 +2807,11 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
2587
2807
|
try {
|
|
2588
2808
|
this.setTelemetryContextFromProps(findBy.props);
|
|
2589
2809
|
|
|
2810
|
+
this.checkIfUserIsLoggedInBeforeHooks(
|
|
2811
|
+
findBy.props,
|
|
2812
|
+
DatabaseRequestType.Read,
|
|
2813
|
+
);
|
|
2814
|
+
|
|
2590
2815
|
if (!findBy.sort || Object.keys(findBy.sort).length === 0) {
|
|
2591
2816
|
findBy.sort = {
|
|
2592
2817
|
createdAt: SortOrder.Descending,
|
|
@@ -2967,8 +3192,28 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
2967
3192
|
try {
|
|
2968
3193
|
this.setTelemetryContextFromProps(updateBy.props);
|
|
2969
3194
|
|
|
3195
|
+
this.checkIfUserIsLoggedInBeforeHooks(
|
|
3196
|
+
updateBy.props,
|
|
3197
|
+
DatabaseRequestType.Update,
|
|
3198
|
+
);
|
|
3199
|
+
|
|
2970
3200
|
updateBy.data = this.sanitizeUpdateData(updateBy.data);
|
|
2971
3201
|
|
|
3202
|
+
// Query operators are for queries, not for write payloads. See the helper.
|
|
3203
|
+
this.rejectQueryOperatorsInData(updateBy.data);
|
|
3204
|
+
|
|
3205
|
+
/*
|
|
3206
|
+
* Defense in depth for the tenant confused-deputy on the update path.
|
|
3207
|
+
* Unlike create(), _updateBy() never re-stamps the tenant scalar, and a
|
|
3208
|
+
* tenant relation object would likewise override the scalar join column
|
|
3209
|
+
* on the UPDATE. Today the tenant columns carry `update: []` so the
|
|
3210
|
+
* column-permission check rejects them first, but that is incidental —
|
|
3211
|
+
* this keeps the row's tenant immutable even if a model ever grants
|
|
3212
|
+
* update on the tenant relation. Runs before the permission check so the
|
|
3213
|
+
* ACL stays a redundant second line rather than the only one.
|
|
3214
|
+
*/
|
|
3215
|
+
this.enforceTenantRelationMatchesScalar(updateBy.data, updateBy.props);
|
|
3216
|
+
|
|
2972
3217
|
this.unwrapHashedStringsForUnhashedColumns(updateBy.data);
|
|
2973
3218
|
|
|
2974
3219
|
const onUpdate: OnUpdate<TBaseModel> = updateBy.props.ignoreHooks
|
|
@@ -5,6 +5,8 @@ import UpdateBy from "../Types/Database/UpdateBy";
|
|
|
5
5
|
import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
|
|
6
6
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
7
7
|
import {
|
|
8
|
+
DETECTION_EVALUATION_INTERVAL_MAX_IN_MINUTES,
|
|
9
|
+
DETECTION_EVALUATION_INTERVAL_MIN_IN_MINUTES,
|
|
8
10
|
DETECTION_MATCH_COUNT_THRESHOLD_MAX,
|
|
9
11
|
DETECTION_MATCH_COUNT_THRESHOLD_MIN,
|
|
10
12
|
} from "../../Types/SecurityEvent/DetectionFindingConstants";
|
|
@@ -52,10 +54,9 @@ export class Service extends DatabaseService<Model> {
|
|
|
52
54
|
private validateEvaluationInterval(interval: number | undefined): void {
|
|
53
55
|
this.validateIntegerInRange({
|
|
54
56
|
value: interval,
|
|
55
|
-
min:
|
|
56
|
-
max:
|
|
57
|
-
message:
|
|
58
|
-
"Evaluation interval must be a whole number of minutes between 1 and 1440.",
|
|
57
|
+
min: DETECTION_EVALUATION_INTERVAL_MIN_IN_MINUTES,
|
|
58
|
+
max: DETECTION_EVALUATION_INTERVAL_MAX_IN_MINUTES,
|
|
59
|
+
message: `Evaluation interval must be a whole number of minutes between ${DETECTION_EVALUATION_INTERVAL_MIN_IN_MINUTES} and ${DETECTION_EVALUATION_INTERVAL_MAX_IN_MINUTES}.`,
|
|
59
60
|
});
|
|
60
61
|
}
|
|
61
62
|
|