@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
|
@@ -47,6 +47,16 @@ export default class ModelAPI {
|
|
|
47
47
|
return API;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/*
|
|
51
|
+
* The client for ONE request: a client the caller routed this request
|
|
52
|
+
* through (RequestOptions.apiClient) wins; otherwise this class's client.
|
|
53
|
+
*/
|
|
54
|
+
protected static getApiClientForRequest(
|
|
55
|
+
requestOptions?: RequestOptions | undefined,
|
|
56
|
+
): typeof API {
|
|
57
|
+
return requestOptions?.apiClient || this.getApiClient();
|
|
58
|
+
}
|
|
59
|
+
|
|
50
60
|
public static async create<TBaseModel extends BaseModel>(data: {
|
|
51
61
|
model: TBaseModel;
|
|
52
62
|
modelType: { new (): TBaseModel };
|
|
@@ -109,7 +119,7 @@ export default class ModelAPI {
|
|
|
109
119
|
|
|
110
120
|
const result: HTTPResponse<
|
|
111
121
|
JSONObject | JSONArray | TBaseModel | Array<TBaseModel>
|
|
112
|
-
> = await this.
|
|
122
|
+
> = await this.getApiClientForRequest(data.requestOptions).fetch<
|
|
113
123
|
JSONObject | JSONArray | TBaseModel | Array<TBaseModel>
|
|
114
124
|
>({
|
|
115
125
|
method: HTTPMethod.PUT,
|
|
@@ -163,7 +173,7 @@ export default class ModelAPI {
|
|
|
163
173
|
}
|
|
164
174
|
|
|
165
175
|
const apiResult: HTTPErrorResponse | HTTPResponse<TBaseModel> =
|
|
166
|
-
await this.
|
|
176
|
+
await this.getApiClientForRequest(data.requestOptions).fetch<TBaseModel>({
|
|
167
177
|
method: httpMethod,
|
|
168
178
|
url: apiUrl,
|
|
169
179
|
data: {
|
|
@@ -241,7 +251,7 @@ export default class ModelAPI {
|
|
|
241
251
|
}
|
|
242
252
|
|
|
243
253
|
const result: HTTPResponse<JSONArray> | HTTPErrorResponse =
|
|
244
|
-
await this.
|
|
254
|
+
await this.getApiClientForRequest(data.requestOptions).fetch<JSONArray>({
|
|
245
255
|
method: HTTPMethod.POST,
|
|
246
256
|
url: apiUrl,
|
|
247
257
|
data: {
|
|
@@ -315,7 +325,7 @@ export default class ModelAPI {
|
|
|
315
325
|
}
|
|
316
326
|
|
|
317
327
|
const result: HTTPResponse<JSONObject> | HTTPErrorResponse =
|
|
318
|
-
await this.
|
|
328
|
+
await this.getApiClientForRequest(data.requestOptions).fetch<JSONObject>({
|
|
319
329
|
method: HTTPMethod.POST,
|
|
320
330
|
url: apiUrl,
|
|
321
331
|
data: {
|
|
@@ -343,10 +353,21 @@ export default class ModelAPI {
|
|
|
343
353
|
): Dictionary<string> {
|
|
344
354
|
let headers: Dictionary<string> = {};
|
|
345
355
|
|
|
356
|
+
/*
|
|
357
|
+
* A request routed through another app's client (a public dashboard
|
|
358
|
+
* widget's /public-dashboard-api read) is not scoped to the viewer's own
|
|
359
|
+
* project: that client sends its own tenant header. The viewer's
|
|
360
|
+
* last-opened dashboard project would override it, and a stale or
|
|
361
|
+
* foreign one turns the public read into a 405 (tenant not found) that
|
|
362
|
+
* the public page treats as a login event.
|
|
363
|
+
*/
|
|
364
|
+
const isRoutedToAnotherClient: boolean = Boolean(requestOptions?.apiClient);
|
|
365
|
+
|
|
346
366
|
if (
|
|
347
|
-
!
|
|
348
|
-
!requestOptions
|
|
349
|
-
|
|
367
|
+
!isRoutedToAnotherClient &&
|
|
368
|
+
(!requestOptions ||
|
|
369
|
+
!requestOptions.isMultiTenantRequest ||
|
|
370
|
+
Object.keys(requestOptions).length === 0)
|
|
350
371
|
) {
|
|
351
372
|
/*
|
|
352
373
|
* Read the tenant id via getCurrentProjectId() first - a plain string
|
|
@@ -427,7 +448,7 @@ export default class ModelAPI {
|
|
|
427
448
|
requestOptions?: RequestOptions | undefined;
|
|
428
449
|
}): Promise<TBaseModel | null> {
|
|
429
450
|
const result: HTTPResponse<TBaseModel> | HTTPErrorResponse =
|
|
430
|
-
await this.
|
|
451
|
+
await this.getApiClientForRequest(data.requestOptions).fetch<TBaseModel>({
|
|
431
452
|
method: HTTPMethod.POST,
|
|
432
453
|
url: data.apiUrl,
|
|
433
454
|
data: {
|
|
@@ -476,7 +497,7 @@ export default class ModelAPI {
|
|
|
476
497
|
}
|
|
477
498
|
|
|
478
499
|
const result: HTTPResponse<TBaseModel> | HTTPErrorResponse =
|
|
479
|
-
await this.
|
|
500
|
+
await this.getApiClientForRequest(data.requestOptions).fetch<TBaseModel>({
|
|
480
501
|
method: HTTPMethod.DELETE,
|
|
481
502
|
url: apiUrl,
|
|
482
503
|
headers: this.getCommonHeaders(data.requestOptions),
|
package/UI/Utils/Navigation.ts
CHANGED
|
@@ -174,6 +174,15 @@ abstract class Navigation {
|
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
public static getCurrentRoute(): Route {
|
|
177
|
+
/*
|
|
178
|
+
* The router hands us its location once it has rendered. An API error can
|
|
179
|
+
* be handled before that (or outside a router altogether), and the address
|
|
180
|
+
* bar is the same answer then.
|
|
181
|
+
*/
|
|
182
|
+
if (!this.location) {
|
|
183
|
+
return new Route(window.location.pathname);
|
|
184
|
+
}
|
|
185
|
+
|
|
177
186
|
return new Route(this.location.pathname);
|
|
178
187
|
}
|
|
179
188
|
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import BaseAPI from "./API/API";
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Opening an authenticated URL in a new tab, with the session refreshed first.
|
|
5
|
+
*
|
|
6
|
+
* A link to an authenticated API route (an attachment, a pprof export) is a
|
|
7
|
+
* plain navigation. It carries the session cookies but none of the API
|
|
8
|
+
* class's recovery: a request made through BaseAPI that comes back 401
|
|
9
|
+
* refreshes the session and replays itself, while a navigation simply shows
|
|
10
|
+
* the 401. The access cookie expires with the 15-minute access token, so on a
|
|
11
|
+
* page left open that long every such link opened a bare "Authentication
|
|
12
|
+
* required" page although the refresh token was still good. Refreshing before
|
|
13
|
+
* navigating makes the new tab arrive with a live access cookie. It costs
|
|
14
|
+
* nothing extra when another request or another tab has just refreshed:
|
|
15
|
+
* refreshSession() reuses that result.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export type RefreshSessionFunction = () => Promise<boolean>;
|
|
19
|
+
|
|
20
|
+
/*
|
|
21
|
+
* The part of a click event the link handler reads. React.MouseEvent
|
|
22
|
+
* satisfies it, and so does a DOM MouseEvent, so this module needs neither.
|
|
23
|
+
*/
|
|
24
|
+
export interface AuthenticatedLinkClickEvent {
|
|
25
|
+
button: number;
|
|
26
|
+
metaKey: boolean;
|
|
27
|
+
ctrlKey: boolean;
|
|
28
|
+
shiftKey: boolean;
|
|
29
|
+
altKey: boolean;
|
|
30
|
+
defaultPrevented: boolean;
|
|
31
|
+
preventDefault: () => void;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
* The dashboard's session. A client with a session of its own (the status
|
|
36
|
+
* page) passes its API class's refresh instead.
|
|
37
|
+
*/
|
|
38
|
+
const refreshDashboardSession: RefreshSessionFunction =
|
|
39
|
+
async (): Promise<boolean> => {
|
|
40
|
+
return await BaseAPI.refreshSession();
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/*
|
|
44
|
+
* Point a tab this click already opened at the URL, once the session has been
|
|
45
|
+
* refreshed. A refresh that did not work closes the tab instead: a refused one
|
|
46
|
+
* means the session has ended and this page's API client is already taking
|
|
47
|
+
* the user to the login page, and one that got no answer means the server
|
|
48
|
+
* cannot be reached, so the tab would only show an error either way.
|
|
49
|
+
*/
|
|
50
|
+
async function navigateTabAfterRefresh(
|
|
51
|
+
tab: Window,
|
|
52
|
+
url: string,
|
|
53
|
+
refreshSession: RefreshSessionFunction,
|
|
54
|
+
): Promise<void> {
|
|
55
|
+
/*
|
|
56
|
+
* Cut loose from this page, as rel="noopener" would have done. A blank tab
|
|
57
|
+
* opened WITH the "noopener" feature could not be pointed anywhere
|
|
58
|
+
* afterwards, because window.open returns null for it.
|
|
59
|
+
*/
|
|
60
|
+
tab.opener = null;
|
|
61
|
+
|
|
62
|
+
let refreshed: boolean = false;
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
refreshed = await refreshSession();
|
|
66
|
+
} catch {
|
|
67
|
+
refreshed = false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Closed while the refresh ran: the user changed their mind.
|
|
71
|
+
if (tab.closed) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!refreshed) {
|
|
76
|
+
tab.close();
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
tab.location.href = url;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export default async function openAuthenticatedUrl(
|
|
84
|
+
url: string,
|
|
85
|
+
refreshSession: RefreshSessionFunction = refreshDashboardSession,
|
|
86
|
+
): Promise<void> {
|
|
87
|
+
/*
|
|
88
|
+
* Popup blockers let window.open through only while the click is still
|
|
89
|
+
* being handled; once the handler has awaited something, Safari and Firefox
|
|
90
|
+
* no longer count the new tab as the user's doing and block it. So the tab
|
|
91
|
+
* is opened now, blank, and pointed at the URL once the refresh has settled.
|
|
92
|
+
*/
|
|
93
|
+
const newTab: Window | null = window.open("", "_blank");
|
|
94
|
+
|
|
95
|
+
if (!newTab) {
|
|
96
|
+
/*
|
|
97
|
+
* Blocked. Ask for the URL itself, still inside the click: without a tab
|
|
98
|
+
* to hold, there is nothing to refresh the session for.
|
|
99
|
+
*/
|
|
100
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
await navigateTabAfterRefresh(newTab, url, refreshSession);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/*
|
|
108
|
+
* The onClick for an <a href={url} target="_blank"> that points at an
|
|
109
|
+
* authenticated route. The href stays on the element so middle-click, "copy
|
|
110
|
+
* link address" and the context menu keep working exactly as before (those
|
|
111
|
+
* paths get no refresh); a plain click opens the URL in a tab of its own once
|
|
112
|
+
* the session is refreshed.
|
|
113
|
+
*/
|
|
114
|
+
export function handleAuthenticatedLinkClick(
|
|
115
|
+
event: AuthenticatedLinkClickEvent,
|
|
116
|
+
url: string,
|
|
117
|
+
refreshSession?: RefreshSessionFunction,
|
|
118
|
+
): void {
|
|
119
|
+
/*
|
|
120
|
+
* Modified clicks stay the browser's: cmd/ctrl-click opens a background
|
|
121
|
+
* tab, shift-click a new window, alt-click downloads. Turning all of them
|
|
122
|
+
* into a foreground tab would be a surprise.
|
|
123
|
+
*/
|
|
124
|
+
if (
|
|
125
|
+
event.defaultPrevented ||
|
|
126
|
+
event.button !== 0 ||
|
|
127
|
+
event.metaKey ||
|
|
128
|
+
event.ctrlKey ||
|
|
129
|
+
event.shiftKey ||
|
|
130
|
+
event.altKey
|
|
131
|
+
) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/*
|
|
136
|
+
* Open the tab before deciding to take the click over. Where window.open
|
|
137
|
+
* is refused (a popup-blocking extension, some in-app browsers) the anchor's
|
|
138
|
+
* own navigation may still be allowed, so the click is left to it - no
|
|
139
|
+
* refresh, but a link that opens, as it always did.
|
|
140
|
+
*/
|
|
141
|
+
const newTab: Window | null = window.open("", "_blank");
|
|
142
|
+
|
|
143
|
+
if (!newTab) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
event.preventDefault();
|
|
148
|
+
|
|
149
|
+
void navigateTabAfterRefresh(
|
|
150
|
+
newTab,
|
|
151
|
+
url,
|
|
152
|
+
refreshSession || refreshDashboardSession,
|
|
153
|
+
);
|
|
154
|
+
}
|
package/UI/Utils/Realtime.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HOST, HTTP_PROTOCOL } from "../Config";
|
|
2
|
+
import API from "./API/API";
|
|
2
3
|
import AnalyticsBaseModel from "../../Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
|
|
3
4
|
import BaseModel from "../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
4
5
|
import { RealtimeRoute } from "../../ServiceRoute";
|
|
@@ -21,14 +22,55 @@ export interface ListenToModelEvent<
|
|
|
21
22
|
modelId?: ObjectID | undefined;
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
/*
|
|
26
|
+
* One subscription a caller holds: what the server has to be asked for (again
|
|
27
|
+
* after every reconnect) and the handler listening on its room.
|
|
28
|
+
*/
|
|
29
|
+
interface RealtimeSubscription {
|
|
30
|
+
request: ListenToModelEventJSON;
|
|
31
|
+
roomId: string;
|
|
32
|
+
handler: (data: JSONObject) => void;
|
|
33
|
+
}
|
|
34
|
+
|
|
24
35
|
export default abstract class Realtime {
|
|
36
|
+
/*
|
|
37
|
+
* The least time between two refresh-and-reconnects. A reconnect with a
|
|
38
|
+
* freshly refreshed session that the server still refuses (a cookie that
|
|
39
|
+
* does not reach the socket, say) must not turn into a reconnect loop; the
|
|
40
|
+
* next refusal after this long tries again. Far shorter than the 15-minute
|
|
41
|
+
* access token, so a session that genuinely expires again is still renewed.
|
|
42
|
+
*/
|
|
43
|
+
public static readonly AUTHENTICATION_RECOVERY_COOLDOWN_IN_MS: number =
|
|
44
|
+
60 * 1000;
|
|
45
|
+
|
|
25
46
|
private static socket: Socket;
|
|
26
47
|
|
|
48
|
+
/*
|
|
49
|
+
* Every subscription still wanted, by identity: two callers asking for the
|
|
50
|
+
* same room are two entries, and each one's stop function removes only its
|
|
51
|
+
* own. The server forgets a socket's rooms when the connection drops, so
|
|
52
|
+
* this is what gets re-sent on every (re)connect.
|
|
53
|
+
*/
|
|
54
|
+
private static subscriptions: Set<RealtimeSubscription> = new Set();
|
|
55
|
+
|
|
56
|
+
private static isRecoveringAuthentication: boolean = false;
|
|
57
|
+
|
|
58
|
+
private static lastAuthenticationRecoveryAt: number | null = null;
|
|
59
|
+
|
|
27
60
|
public static init(): void {
|
|
28
61
|
const socket: Socket = SocketIO(new URL(HTTP_PROTOCOL, HOST).toString(), {
|
|
29
62
|
path: RealtimeRoute.toString(),
|
|
30
63
|
});
|
|
31
64
|
|
|
65
|
+
// Initial connect and every reconnect: the new connection is in no rooms.
|
|
66
|
+
socket.on("connect", (): void => {
|
|
67
|
+
this.resubscribeAll();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
socket.on(EventName.AuthenticationRequired, (): void => {
|
|
71
|
+
this.onAuthenticationRequired();
|
|
72
|
+
});
|
|
73
|
+
|
|
32
74
|
this.socket = socket;
|
|
33
75
|
}
|
|
34
76
|
|
|
@@ -55,27 +97,22 @@ export default abstract class Realtime {
|
|
|
55
97
|
tenantId: listenToModelEvent.tenantId.toString(),
|
|
56
98
|
};
|
|
57
99
|
|
|
58
|
-
this.emit(EventName.ListenToModalEvent, listenToModelEventJSON as any);
|
|
59
|
-
|
|
60
100
|
const roomId: string = RealtimeUtil.getRoomId(
|
|
61
101
|
listenToModelEvent.tenantId,
|
|
62
102
|
listenToModelEvent.modelType.name,
|
|
63
103
|
listenToModelEvent.eventType,
|
|
64
104
|
);
|
|
65
105
|
|
|
66
|
-
this.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
return stopListening;
|
|
106
|
+
return this.subscribe(
|
|
107
|
+
listenToModelEventJSON,
|
|
108
|
+
roomId,
|
|
109
|
+
(data: JSONObject): void => {
|
|
110
|
+
const id: ObjectID = ObjectID.fromString(
|
|
111
|
+
data["modelId"]?.toString() as string,
|
|
112
|
+
);
|
|
113
|
+
onEvent(id);
|
|
114
|
+
},
|
|
115
|
+
);
|
|
79
116
|
}
|
|
80
117
|
|
|
81
118
|
public static listenToAnalyticsModelEvent<Model extends AnalyticsBaseModel>(
|
|
@@ -93,8 +130,6 @@ export default abstract class Realtime {
|
|
|
93
130
|
tenantId: listenToModelEvent.tenantId.toString(),
|
|
94
131
|
};
|
|
95
132
|
|
|
96
|
-
this.emit(EventName.ListenToModalEvent, listenToModelEventJSON as any);
|
|
97
|
-
|
|
98
133
|
let roomId: string = RealtimeUtil.getRoomId(
|
|
99
134
|
listenToModelEvent.tenantId,
|
|
100
135
|
listenToModelEvent.modelType.name,
|
|
@@ -110,28 +145,139 @@ export default abstract class Realtime {
|
|
|
110
145
|
);
|
|
111
146
|
}
|
|
112
147
|
|
|
113
|
-
this.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
148
|
+
return this.subscribe(
|
|
149
|
+
listenToModelEventJSON,
|
|
150
|
+
roomId,
|
|
151
|
+
(model: JSONObject): void => {
|
|
152
|
+
onEvent(
|
|
153
|
+
AnalyticsBaseModel.fromJSON(
|
|
154
|
+
model,
|
|
155
|
+
listenToModelEvent.modelType,
|
|
156
|
+
) as Model,
|
|
157
|
+
);
|
|
158
|
+
},
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public static emit(eventName: string, data: JSONObject): void {
|
|
163
|
+
if (!this.socket) {
|
|
164
|
+
this.init();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
this.socket.emit(eventName, data);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private static subscribe(
|
|
171
|
+
request: ListenToModelEventJSON,
|
|
172
|
+
roomId: string,
|
|
173
|
+
handler: (data: JSONObject) => void,
|
|
174
|
+
): () => void {
|
|
175
|
+
const subscription: RealtimeSubscription = {
|
|
176
|
+
request: request,
|
|
177
|
+
roomId: roomId,
|
|
178
|
+
handler: handler,
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
this.subscriptions.add(subscription);
|
|
182
|
+
|
|
183
|
+
this.socket.on(roomId, handler);
|
|
184
|
+
|
|
185
|
+
/*
|
|
186
|
+
* Not connected yet (or between a disconnect and a reconnect): the
|
|
187
|
+
* 'connect' handler sends every registered subscription, this one
|
|
188
|
+
* included. Emitting now as well would have socket.io buffer this one and
|
|
189
|
+
* send it a second time on connect.
|
|
190
|
+
*/
|
|
191
|
+
if (this.socket.connected) {
|
|
192
|
+
this.socket.emit(EventName.ListenToModalEvent, request);
|
|
193
|
+
}
|
|
121
194
|
|
|
122
195
|
// Stop listening to the event.
|
|
123
196
|
const stopListening: () => void = (): void => {
|
|
124
|
-
this.
|
|
197
|
+
this.subscriptions.delete(subscription);
|
|
198
|
+
|
|
199
|
+
/*
|
|
200
|
+
* Only this subscription's handler. Removing every listener on the room
|
|
201
|
+
* would also silence any other subscription to the same room.
|
|
202
|
+
*/
|
|
203
|
+
this.socket.off(roomId, handler);
|
|
125
204
|
};
|
|
126
205
|
|
|
127
206
|
return stopListening;
|
|
128
207
|
}
|
|
129
208
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
209
|
+
private static resubscribeAll(): void {
|
|
210
|
+
// The server's join is idempotent, so identical requests go once.
|
|
211
|
+
const sentRequests: Set<string> = new Set();
|
|
212
|
+
|
|
213
|
+
for (const subscription of this.subscriptions) {
|
|
214
|
+
const requestKey: string = JSON.stringify(subscription.request);
|
|
215
|
+
|
|
216
|
+
if (sentRequests.has(requestKey)) {
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
sentRequests.add(requestKey);
|
|
221
|
+
|
|
222
|
+
this.socket.emit(EventName.ListenToModalEvent, subscription.request);
|
|
133
223
|
}
|
|
224
|
+
}
|
|
134
225
|
|
|
135
|
-
|
|
226
|
+
/*
|
|
227
|
+
* The server refused a subscription because this socket's handshake carries
|
|
228
|
+
* no access token, or an expired one. The cookie is read once, when the
|
|
229
|
+
* socket connects, so an HTTP request refreshing the session does nothing
|
|
230
|
+
* for the socket: refresh (or reuse a refresh another request or tab just
|
|
231
|
+
* did), then reconnect so the new handshake carries the new cookie. The
|
|
232
|
+
* reconnect's 'connect' re-sends every subscription, including the refused
|
|
233
|
+
* one.
|
|
234
|
+
*
|
|
235
|
+
* A burst of refusals (a page subscribing to several rooms at once) is one
|
|
236
|
+
* recovery: the first starts it, the rest arrive while it is in flight or
|
|
237
|
+
* inside the cool-down.
|
|
238
|
+
*/
|
|
239
|
+
private static onAuthenticationRequired(): void {
|
|
240
|
+
if (this.isRecoveringAuthentication) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (
|
|
245
|
+
this.lastAuthenticationRecoveryAt !== null &&
|
|
246
|
+
Date.now() - this.lastAuthenticationRecoveryAt <
|
|
247
|
+
this.AUTHENTICATION_RECOVERY_COOLDOWN_IN_MS
|
|
248
|
+
) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
this.isRecoveringAuthentication = true;
|
|
253
|
+
this.lastAuthenticationRecoveryAt = Date.now();
|
|
254
|
+
|
|
255
|
+
this.recoverAuthentication().catch(() => {
|
|
256
|
+
// recoverAuthentication settles every outcome itself.
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
private static async recoverAuthentication(): Promise<void> {
|
|
261
|
+
try {
|
|
262
|
+
/*
|
|
263
|
+
* Without a new cookie a reconnect would only be refused again. When
|
|
264
|
+
* the refresh failed because the session is over, the refresh request
|
|
265
|
+
* has already sent the user to the login page.
|
|
266
|
+
*/
|
|
267
|
+
const refreshed: boolean = await API.refreshSession();
|
|
268
|
+
|
|
269
|
+
if (!refreshed) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
this.socket.disconnect();
|
|
274
|
+
this.socket.connect();
|
|
275
|
+
} catch {
|
|
276
|
+
// A refresh that could not complete (offline, say) did not happen.
|
|
277
|
+
} finally {
|
|
278
|
+
this.isRecoveringAuthentication = false;
|
|
279
|
+
// The cool-down runs from the end of the attempt, however long it took.
|
|
280
|
+
this.lastAuthenticationRecoveryAt = Date.now();
|
|
281
|
+
}
|
|
136
282
|
}
|
|
137
283
|
}
|
package/Utils/API.ts
CHANGED
|
@@ -247,34 +247,43 @@ export default class API {
|
|
|
247
247
|
return false;
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
/*
|
|
251
|
+
* The class this instance was built from, so `new BaseAPI(...).get()` gets
|
|
252
|
+
* BaseAPI's session refresh, error handling and headers rather than the
|
|
253
|
+
* base class's no-op versions.
|
|
254
|
+
*/
|
|
255
|
+
private getStaticClient(): typeof API {
|
|
256
|
+
return this.constructor as typeof API;
|
|
257
|
+
}
|
|
258
|
+
|
|
250
259
|
public async get<
|
|
251
260
|
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>,
|
|
252
261
|
>(options: APIRequestOptions): Promise<HTTPResponse<T> | HTTPErrorResponse> {
|
|
253
|
-
return await
|
|
262
|
+
return await this.getStaticClient().get<T>(options);
|
|
254
263
|
}
|
|
255
264
|
|
|
256
265
|
public async delete<
|
|
257
266
|
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>,
|
|
258
267
|
>(options: APIRequestOptions): Promise<HTTPResponse<T> | HTTPErrorResponse> {
|
|
259
|
-
return await
|
|
268
|
+
return await this.getStaticClient().delete<T>(options);
|
|
260
269
|
}
|
|
261
270
|
|
|
262
271
|
public async head<
|
|
263
272
|
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>,
|
|
264
273
|
>(options: APIRequestOptions): Promise<HTTPResponse<T> | HTTPErrorResponse> {
|
|
265
|
-
return await
|
|
274
|
+
return await this.getStaticClient().head<T>(options);
|
|
266
275
|
}
|
|
267
276
|
|
|
268
277
|
public async put<
|
|
269
278
|
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>,
|
|
270
279
|
>(options: APIRequestOptions): Promise<HTTPResponse<T> | HTTPErrorResponse> {
|
|
271
|
-
return await
|
|
280
|
+
return await this.getStaticClient().put<T>(options);
|
|
272
281
|
}
|
|
273
282
|
|
|
274
283
|
public async patch<
|
|
275
284
|
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>,
|
|
276
285
|
>(options: APIRequestOptions): Promise<HTTPResponse<T> | HTTPErrorResponse> {
|
|
277
|
-
return await
|
|
286
|
+
return await this.getStaticClient().patch<T>(options);
|
|
278
287
|
}
|
|
279
288
|
|
|
280
289
|
public static handleError(
|