@oneuptime/common 13.0.7 → 14.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/AnalyticsModels/AuditLog.ts +23 -15
- package/Models/DatabaseModels/GlobalConfig.ts +24 -0
- package/Models/DatabaseModels/Monitor.ts +3 -2
- package/Models/DatabaseModels/MonitorTemplate.ts +2 -1
- package/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.ts +1 -1
- package/Models/DatabaseModels/ProjectOnCallCalendarFeed.ts +1 -1
- package/Models/DatabaseModels/UserOnCallCalendarFeed.ts +1 -1
- package/Scripts/generate-service-worker.js +65 -4
- package/Server/API/AIBillingAPI.ts +1 -0
- package/Server/API/AIInsightAPI.ts +1 -4
- package/Server/API/AIInvestigationAPI.ts +1 -4
- package/Server/API/AIReadinessAPI.ts +4 -5
- package/Server/API/AlertAPI.ts +1 -0
- package/Server/API/AutoRemediationAPI.ts +1 -4
- package/Server/API/BaseAPI.ts +34 -0
- package/Server/API/BaseAnalyticsAPI.ts +80 -9
- package/Server/API/BillingAPI.ts +2 -0
- package/Server/API/BillingInvoiceAPI.ts +1 -0
- package/Server/API/BillingPaymentMethodAPI.ts +2 -0
- package/Server/API/CodeFixRunAPI.ts +1 -3
- package/Server/API/CommonAPI.ts +68 -4
- package/Server/API/DashboardAPI.ts +12 -12
- package/Server/API/GlobalConfigAPI.ts +243 -460
- package/Server/API/IncidentAPI.ts +2 -0
- package/Server/API/IncidentEpisodeAPI.ts +1 -0
- package/Server/API/NotificationAPI.ts +1 -0
- package/Server/API/OnCallCalendarAPI.ts +4 -5
- package/Server/API/OnCallDutyPolicyAPI.ts +7 -0
- package/Server/API/OnCallReadinessAPI.ts +4 -1
- package/Server/API/OnCallScheduleTimelineAPI.ts +731 -0
- package/Server/API/ProjectAPI.ts +1 -0
- package/Server/API/ProjectOIDC.ts +25 -16
- package/Server/API/ProjectSSO.ts +24 -16
- package/Server/API/ScheduledMaintenanceAPI.ts +1 -0
- package/Server/API/StatusPageAPI.ts +261 -74
- package/Server/API/TeamMemberAPI.ts +13 -1
- package/Server/API/UserCallAPI.ts +2 -0
- package/Server/API/UserEmailAPI.ts +2 -0
- package/Server/API/UserIncomingCallNumberAPI.ts +2 -0
- package/Server/API/UserMicrosoftTeamsAPI.ts +1 -0
- package/Server/API/UserSlackAPI.ts +1 -0
- package/Server/API/UserSmsAPI.ts +2 -0
- package/Server/API/UserTotpAuthAPI.ts +1 -0
- package/Server/API/UserWebAuthnAPI.ts +2 -0
- package/Server/API/UserWebhookAPI.ts +1 -0
- package/Server/API/UserWhatsAppAPI.ts +2 -0
- package/Server/Enterprise/EnterpriseEdition.ts +649 -0
- package/Server/Enterprise/EnterpriseFeature.ts +48 -0
- package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +192 -0
- package/Server/Enterprise/EnterpriseServerModule.ts +233 -0
- package/Server/EnvironmentConfig.ts +147 -2
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Middleware/MasterAdminAuthorization.ts +13 -2
- package/Server/Middleware/UserAuthorization.ts +117 -21
- package/Server/Services/ApiKeyPermissionService.ts +101 -4
- package/Server/Services/AuditLogService.ts +84 -1079
- package/Server/Services/DatabaseService.ts +245 -0
- package/Server/Services/DetectionRuleService.ts +5 -4
- package/Server/Services/EnterpriseLicenseService.ts +38 -0
- package/Server/Services/GlobalConfigService.ts +80 -1
- package/Server/Services/MonitorProbeService.ts +116 -20
- package/Server/Services/MonitorService.ts +56 -4
- package/Server/Services/MonitorStatusTimelineService.ts +284 -0
- package/Server/Services/MonitorTemplateService.ts +26 -0
- package/Server/Services/OnCallDutyPolicyChildService.ts +261 -0
- package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +2 -2
- package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +2 -2
- package/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.ts +2 -2
- package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +2 -2
- package/Server/Services/PayAsYouGoBillingService.ts +23 -28
- package/Server/Services/ProjectService.ts +302 -0
- package/Server/Services/RumSessionPinService.ts +293 -22
- package/Server/Services/StatusPagePrivateUserService.ts +7 -3
- package/Server/Services/StatusPageService.ts +78 -1
- package/Server/Services/TeamMemberService.ts +11 -0
- package/Server/Services/TeamPermissionService.ts +120 -26
- package/Server/Services/TeamService.ts +10 -0
- package/Server/Services/ThreatIntelFeedService.ts +6 -3
- package/Server/Services/UserService.ts +10 -17
- package/Server/Types/Database/Permissions/BasePermission.ts +9 -7
- package/Server/Types/Database/Permissions/CreatePermission.ts +15 -0
- package/Server/Types/Database/Permissions/EditionPermission.ts +208 -18
- package/Server/Types/Database/Permissions/Index.ts +75 -11
- package/Server/Types/Database/Permissions/TablePermission.ts +34 -31
- package/Server/Types/Database/Permissions/UpdatePermission.ts +29 -0
- package/Server/Types/Markdown.ts +41 -0
- package/Server/Utils/AI/AIChatPrivacyFilter.ts +8 -0
- package/Server/Utils/AI/AIRunPrivacyFilter.ts +8 -0
- package/Server/Utils/CommunityEditionSsoReport.ts +361 -0
- package/Server/Utils/EditionEnforcement.ts +233 -0
- package/Server/Utils/FrontendEnvironment.ts +41 -2
- package/Server/Utils/InstanceHealth/RedisHealth.ts +12 -277
- package/Server/Utils/MasterAdminPageAccess.ts +61 -0
- package/Server/Utils/Monitor/AffectedResourceList.ts +190 -0
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +10 -1
- package/Server/Utils/Monitor/MonitorAlert.ts +3 -1
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +543 -333
- package/Server/Utils/Monitor/MonitorIncident.ts +3 -1
- package/Server/Utils/Monitor/MonitoringIntervalValidator.ts +116 -0
- package/Server/Utils/OnCall/OnCallCalendarFeedRenderer.ts +1 -1
- package/Server/Utils/Realtime.ts +163 -45
- package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +11 -28
- package/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.ts +170 -0
- package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +1 -1
- package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.ts +6 -2
- package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.ts +10 -9
- package/Server/Utils/Workspace/Slack/Slack.ts +423 -10
- package/Tests/App/Accounts/LoginPasskey.test.tsx +18 -0
- package/Tests/App/Accounts/LoginSsoEdition.test.tsx +616 -0
- package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +217 -0
- package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +357 -0
- package/Tests/App/AdminDashboard/EnterpriseLicensesShell.test.tsx +214 -0
- package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +271 -0
- package/Tests/App/AdminDashboard/HealthShells.test.tsx +659 -0
- package/Tests/App/Dashboard/AffectedResourcesPicker.test.tsx +1059 -0
- package/Tests/App/Dashboard/AffectedResourcesPickerEditForm.test.tsx +376 -0
- package/Tests/App/Dashboard/AffectedResourcesPickerHiddenTypes.test.tsx +757 -0
- package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +307 -0
- package/Tests/App/Dashboard/ArgumentsFormGroupByUnlistedAttributes.test.tsx +131 -0
- package/Tests/App/Dashboard/AuditLogsAndComplianceShells.test.tsx +572 -0
- package/Tests/App/Dashboard/DashboardHeaderRequests.test.tsx +1 -1
- package/Tests/App/Dashboard/DashboardMonitorLabelVariable.test.tsx +9 -1
- package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +24 -0
- package/Tests/App/Dashboard/DashboardVariableSelector.test.tsx +162 -8
- package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +547 -0
- package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +667 -0
- package/Tests/App/Dashboard/EntityFilterDropdownArchivedSlos.test.tsx +105 -6
- package/Tests/App/Dashboard/EntityFilterDropdownUnlistedSelection.test.tsx +434 -0
- package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +276 -1
- package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +319 -0
- package/Tests/App/Dashboard/OnCallCalendarFeedSideMenus.test.tsx +9 -1
- package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +185 -0
- package/Tests/App/Dashboard/PayAsYouGoConsentGate.test.tsx +58 -42
- package/Tests/App/Dashboard/PayAsYouGoNotices.test.tsx +42 -5
- package/Tests/App/Dashboard/ResourceAuditLogsSideMenus.test.tsx +34 -23
- package/Tests/App/Dashboard/ScheduleTimeline.test.tsx +1580 -0
- package/Tests/App/Dashboard/ScheduleTimelineAPI.test.ts +280 -0
- package/Tests/App/Dashboard/ScheduleTimelineModel.test.ts +673 -0
- package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +133 -70
- package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +399 -0
- package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +214 -0
- package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +86 -3
- package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +1 -58
- package/Tests/App/Dashboard/SecurityEventsGuideContent.test.ts +1313 -0
- package/Tests/App/Dashboard/SecurityEventsHowItWorksCard.test.tsx +536 -0
- package/Tests/App/Dashboard/SecurityEventsNavTabs.test.tsx +248 -0
- package/Tests/App/Dashboard/SecurityEventsNoResults.test.tsx +222 -0
- package/Tests/App/Dashboard/SecurityEventsThreatIntelPage.test.tsx +199 -0
- package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +1203 -0
- package/Tests/App/Dashboard/SloOverviewHero.test.tsx +171 -36
- package/Tests/App/Dashboard/SloViewSideMenu.test.tsx +215 -0
- package/Tests/App/Dashboard/SloViewSideMenuCounts.test.tsx +40 -3
- package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +11 -91
- package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +12 -4
- package/Tests/App/PublicDashboard/PublicDashboardWidgetListAuth.test.tsx +623 -0
- package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +319 -0
- package/Tests/Helpers/RefreshAwareApiScan.ts +757 -0
- package/Tests/Helpers/TenantScopedRequestScan.ts +515 -0
- package/Tests/Models/OnCallCalendarFeedModels.test.ts +23 -1
- package/Tests/Scripts/GenerateServiceWorker.test.ts +931 -0
- package/Tests/Server/API/AIChatRouteAuthorization.test.ts +138 -5
- package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +187 -0
- package/Tests/Server/API/AIInvestigationAvailabilityAuthorization.test.ts +51 -3
- package/Tests/Server/API/AIInvestigationEvidenceAPI.test.ts +55 -2
- package/Tests/Server/API/BaseAPICreateItemDoesNotMutateModel.test.ts +130 -0
- package/Tests/Server/API/BaseAnalyticsAPIAggregateCache.test.ts +729 -0
- package/Tests/Server/API/BillingPayAsYouGoStatus.test.ts +93 -7
- package/Tests/Server/API/BillingPaymentMethodAPI.test.ts +36 -3
- package/Tests/Server/API/CommonAPIAuthGuard.test.ts +1003 -24
- package/Tests/Server/API/DashboardPublicRateLimit.test.ts +6 -3
- package/Tests/Server/API/ExpiredSessionAIRoutes.test.ts +708 -0
- package/Tests/Server/API/ExpiredSessionCustomRoutes.test.ts +928 -0
- package/Tests/Server/API/ExpiredSessionMonitorTemplate.test.ts +319 -0
- package/Tests/Server/API/ExpiredSessionOnCallDutyPolicy.test.ts +336 -0
- package/Tests/Server/API/ExpiredSessionRouteGuards.test.ts +820 -0
- package/Tests/Server/API/GlobalConfigLicense.test.ts +766 -381
- package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +115 -12
- package/Tests/Server/API/OnCallCalendarAPI.test.ts +375 -8
- package/Tests/Server/API/OnCallReadinessAPI.test.ts +196 -912
- package/Tests/Server/API/OnCallScheduleTimelineAPI.test.ts +1513 -0
- package/Tests/Server/API/OnCallSetupReminderAPI.test.ts +119 -7
- package/Tests/Server/API/ProjectScopedCustomRouteAuth.test.ts +111 -4
- package/Tests/Server/API/PublicRouteInvalidAccessToken.test.ts +615 -0
- package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +89 -2
- package/Tests/Server/API/SessionReplayAPI.test.ts +121 -0
- package/Tests/Server/API/SsoProviderListingsEdition.test.ts +432 -0
- package/Tests/Server/API/StatusPageMasterPasswordRateLimit.test.ts +4 -2
- package/Tests/Server/API/StatusPagePostmortemVisibility.test.ts +441 -0
- package/Tests/Server/API/StatusPageTestEmailReportAuth.test.ts +664 -0
- package/Tests/Server/API/TeamMemberLeaveScimLockEdition.test.ts +252 -0
- package/Tests/Server/API/TeamMemberRemoveUserFromProjectAPI.test.ts +7 -0
- package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +6 -0
- package/Tests/Server/API/UserNotificationSettingAPI.test.ts +65 -4
- package/Tests/Server/API/UserProjectsAPI.test.ts +63 -3
- package/Tests/Server/API/UserTotpAuthAPI.test.ts +48 -2
- package/Tests/Server/API/UserWebAuthnAuthenticationOptionsRoute.test.ts +11 -2
- package/Tests/Server/API/UserWebAuthnBackupCodeMinting.test.ts +46 -3
- package/Tests/Server/API/UserWebAuthnPasskeyAPI.test.ts +18 -2
- package/Tests/Server/API/ZZVerifyChatsAuth.test.ts +24 -7
- package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +824 -0
- package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +643 -0
- package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +294 -0
- package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +93 -0
- package/Tests/Server/Enterprise/EnterpriseOnlyModulesLiveInEe.test.ts +582 -0
- package/Tests/Server/Enterprise/EnterpriseServerModule.test.ts +247 -0
- package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +502 -0
- package/Tests/Server/Enterprise/TestBillingFlag.ts +70 -0
- package/Tests/Server/EnvironmentConfigEnterpriseEdition.test.ts +314 -0
- package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +289 -0
- package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +5 -1
- package/Tests/Server/Middleware/ExpiredSessionUserMiddleware.test.ts +563 -0
- package/Tests/Server/Middleware/MasterAdminAuthorization.test.ts +299 -19
- package/Tests/Server/Middleware/PublicRouteUserMiddleware.test.ts +453 -0
- package/Tests/Server/Middleware/UserAuthorization.test.ts +37 -2
- package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +516 -0
- package/Tests/Server/Services/AIChatPrivacyPin.test.ts +24 -0
- package/Tests/Server/Services/ApiKeyPermissionSecurity.test.ts +2 -0
- package/Tests/Server/Services/ApiKeyPermissionService.test.ts +3 -3
- package/Tests/Server/Services/AuditLogService.test.ts +460 -990
- package/Tests/Server/Services/CreateAndReadResponsesKeepIds.test.ts +263 -0
- package/Tests/Server/Services/DatabaseServiceCreateSuppliedId.test.ts +147 -0
- package/Tests/Server/Services/DatabaseServiceLoginBeforeHooks.test.ts +1078 -0
- package/Tests/Server/Services/DatabaseServiceTenantRelationGuard.test.ts +259 -0
- package/Tests/Server/Services/DatabaseServiceWriteOperatorValues.test.ts +147 -0
- package/Tests/Server/Services/EnterpriseLicenseServiceKeyGeneration.test.ts +151 -0
- package/Tests/Server/Services/GlobalConfigServiceLicenseColumns.test.ts +357 -0
- package/Tests/Server/Services/MonitorDestinationInfoIPv6.test.ts +101 -0
- package/Tests/Server/Services/MonitorPayAsYouGoBilling.test.ts +115 -1
- package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +333 -0
- package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +303 -0
- package/Tests/Server/Services/OnCallChildCreateAuthorizationPostgres.test.ts +711 -0
- package/Tests/Server/Services/OnCallDutyPolicyChildService.test.ts +733 -0
- package/Tests/Server/Services/PayAsYouGoBillingService.test.ts +190 -140
- package/Tests/Server/Services/PayAsYouGoStripeRateLimitBudget.test.ts +4 -9
- package/Tests/Server/Services/PermissionBlockDeletion.test.ts +780 -0
- package/Tests/Server/Services/PermissionBlockDeletionPostgres.test.ts +628 -0
- package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +701 -0
- package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +31 -35
- package/Tests/Server/Services/ProjectServiceCreateSubscriptionStarted.test.ts +77 -1
- package/Tests/Server/Services/RumSessionPinCreatePermission.test.ts +715 -0
- package/Tests/Server/Services/ScimPushGroupsTeamLocksEdition.test.ts +431 -0
- package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +419 -0
- package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +769 -0
- package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +94 -0
- package/Tests/Server/Services/TeamMemberMultiTenantReadPostgres.test.ts +394 -0
- package/Tests/Server/Services/TeamPrivilegeEscalation.test.ts +6 -0
- package/Tests/Server/Services/TelemetryPayAsYouGoBilling.test.ts +131 -0
- package/Tests/Server/Services/UserAuthenticationService.test.ts +35 -0
- package/Tests/Server/Services/UserNotificationRuleAdminGuards.test.ts +13 -2
- package/Tests/Server/Services/UserServiceSeatLimit.test.ts +94 -56
- package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +1823 -0
- package/Tests/Server/Types/Database/Permissions/ModelPermissionAnonymousRefusal.test.ts +518 -0
- package/Tests/Server/Types/Database/Permissions/MultiTenantPermissions.test.ts +350 -0
- package/Tests/Server/Types/Database/Permissions/OnCallCalendarFeedPermissions.test.ts +282 -25
- package/Tests/Server/Types/Database/Permissions/TableLevelBlockPermission.test.ts +459 -0
- package/Tests/Server/Types/Markdown.test.ts +181 -0
- package/Tests/Server/Utils/AI/AIRunPrivacyFilter.test.ts +101 -9
- package/Tests/Server/Utils/AI/ChatAgentHelpers.test.ts +88 -4
- package/Tests/Server/Utils/AI/Toolbox/ExceptionTools.test.ts +459 -0
- package/Tests/Server/Utils/AI/Toolbox/LogTools.test.ts +794 -0
- package/Tests/Server/Utils/AI/Toolbox/RecentChangesTools.test.ts +574 -0
- package/Tests/Server/Utils/AI/Toolbox/SecurityEventTools.test.ts +596 -0
- package/Tests/Server/Utils/CaptchaRequestAndLogging.test.ts +395 -0
- package/Tests/Server/Utils/CommunityEditionSsoReport.test.ts +565 -0
- package/Tests/Server/Utils/EditionEnforcement.test.ts +303 -0
- package/Tests/Server/Utils/FrontendEnvironment.test.ts +367 -0
- package/Tests/Server/Utils/InstanceHealth/RedisHealth.test.ts +38 -418
- package/Tests/Server/Utils/MasterAdminPageAccess.test.ts +251 -0
- package/Tests/Server/Utils/Monitor/AffectedResourceList.test.ts +518 -0
- package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +24 -4
- package/Tests/Server/Utils/Monitor/MonitorActionTimestamps.test.ts +616 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +934 -96
- package/Tests/Server/Utils/Monitor/MonitoringIntervalValidator.test.ts +188 -0
- package/Tests/Server/Utils/Realtime.test.ts +502 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorSeverity.test.ts +216 -0
- package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +142 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.test.ts +140 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepairClickhouseIntegration.test.ts +542 -0
- package/Tests/Server/Utils/Telemetry/ChangeEventRow.test.ts +743 -0
- package/Tests/Server/Utils/Telemetry/RuntimeMetrics.test.ts +465 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/Alert.test.ts +202 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.test.ts +194 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/ScheduledMaintenance.test.ts +231 -0
- package/Tests/Server/Utils/Workspace/Slack/Messages/Alert.test.ts +194 -0
- package/Tests/Server/Utils/Workspace/Slack/Messages/AlertEpisode.test.ts +194 -0
- package/Tests/Server/Utils/Workspace/Slack/Messages/Incident.test.ts +194 -0
- package/Tests/Server/Utils/Workspace/Slack/Messages/IncidentEpisode.test.ts +194 -0
- package/Tests/Server/Utils/Workspace/Slack/Messages/ScheduledMaintenance.test.ts +247 -0
- package/Tests/Server/Utils/Workspace/Slack/SlackMarkdownSectionSplit.test.ts +1209 -0
- package/Tests/Types/AI/AIInsightEvidence.test.ts +206 -0
- package/Tests/Types/API/HostnameFromAuthority.test.ts +20 -10
- package/Tests/Types/API/HostnameIPv6.test.ts +149 -0
- package/Tests/Types/BaseDatabase/DatabaseCommonInteractionPropsUtilAnonymous.test.ts +144 -0
- package/Tests/Types/Call/CallProvider.test.ts +528 -0
- package/Tests/Types/Database/CanonicalModelInstance.test.ts +190 -0
- package/Tests/Types/Kubernetes/KubernetesCostIngest.test.ts +236 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleTimeline.test.ts +736 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleTimelineLayout.test.ts +996 -0
- package/Tests/Types/SecurityEvent/SigmaRule.test.ts +142 -0
- package/Tests/Types/Workflow/Components/JSON.test.ts +182 -0
- package/Tests/UI/Components/BasicFormDropdownNormalization.test.tsx +116 -1
- package/Tests/UI/Components/Dropdown/DropdownAsyncOptions.test.tsx +81 -0
- package/Tests/UI/Components/EditionLabelLapseCopy.ts +104 -0
- package/Tests/UI/Components/EditionLabelLicenseManagerWiring.test.tsx +254 -0
- package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +165 -171
- package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +1586 -0
- package/Tests/UI/Components/EditionLabelLicenseWritesGuard.test.tsx +157 -0
- package/Tests/UI/Components/EventAttachmentList.test.tsx +174 -0
- package/Tests/UI/Components/Forms/BasicFormBurnRateTemplateDefaults.test.tsx +395 -0
- package/Tests/UI/Components/Forms/BasicFormCollapsibleSections.test.tsx +286 -0
- package/Tests/UI/Components/Forms/FormSummary.test.tsx +128 -0
- package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +49 -2
- package/Tests/UI/Components/MarkdownConverters.test.ts +684 -0
- package/Tests/UI/Components/ModelListEmptyState.test.tsx +289 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableQueryChange.test.tsx +365 -0
- package/Tests/UI/Components/OpenAuthenticatedUrl.test.ts +358 -0
- package/Tests/UI/Components/SessionAwareImage.test.tsx +496 -0
- package/Tests/UI/Components/TelemetryHistogramZeroBuckets.test.tsx +190 -0
- package/Tests/UI/Components/TelemetryViewer/TelemetryViewerEmptyContent.test.tsx +131 -0
- package/Tests/UI/Components/TooltipInteractive.test.tsx +97 -0
- package/Tests/UI/EsbuildEnterpriseAlias.test.ts +1127 -0
- package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardInstallGuidance.test.tsx +1 -1
- package/Tests/UI/Monitor/EvaluationLogListTimestamps.test.tsx +367 -0
- package/Tests/UI/Utils/API/BaseAPIRefreshSession.test.ts +1087 -0
- package/Tests/UI/Utils/API/DashboardHost.ts +12 -0
- package/Tests/UI/Utils/API/FakeAxiosServer.ts +183 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +10 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
- package/Tests/UI/Utils/Cookie.test.ts +440 -0
- package/Tests/UI/Utils/ModelAPIRequestClient.test.ts +278 -0
- package/Tests/UI/Utils/Navigation.test.ts +33 -0
- package/Tests/UI/Utils/PricingPlan.test.ts +295 -0
- package/Tests/UI/Utils/Realtime.test.ts +759 -0
- package/Tests/UI/Utils/Telemetry/Telemetry.test.ts +500 -0
- package/Tests/Utils/APIInstanceDispatch.test.ts +311 -0
- package/Tests/Utils/HostAddressUtil.test.ts +138 -0
- package/Tests/Utils/Monitor/MonitorDestinationUtil.test.ts +313 -0
- package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +304 -0
- package/Tests/Utils/SecurityEvent/GoogleSecOpsAlertNormalizerSeverity.test.ts +565 -0
- package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +248 -0
- package/Types/API/Hostname.ts +63 -16
- package/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.ts +40 -0
- package/Types/Database/AccessControl/ColumnAccessControl.ts +19 -7
- package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +19 -7
- package/Types/Database/AccessControl/OwnerOnlyColumn.ts +15 -6
- package/Types/Database/CanonicalModelInstance.ts +102 -0
- package/Types/Database/TableColumn.ts +20 -6
- package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +29 -0
- package/Types/IP/IPv6.ts +6 -1
- package/Types/Monitor/MonitorEvaluationSummary.ts +3 -0
- package/Types/Monitor/MonitorStep.ts +6 -1
- package/Types/Monitor/ProxmoxAlertTemplates.ts +1 -1
- package/Types/OnCallDutyPolicy/ScheduleTimeline.ts +507 -0
- package/Types/OnCallDutyPolicy/ScheduleTimelineLayout.ts +589 -0
- package/Types/Realtime/EventName.ts +11 -0
- package/Types/SecurityEvent/DetectionFindingConstants.ts +14 -0
- package/Types/SecurityEvent/OcsfSeverity.ts +31 -26
- package/Types/SecurityEvent/SigmaRule.ts +51 -0
- package/Types/SecurityEvent/ThreatIntelConstants.ts +18 -0
- package/Types/StatusPage/UptimeDailyAggregate.ts +110 -0
- package/UI/Components/AttachmentList/EventAttachmentList.tsx +30 -2
- package/UI/Components/Dashboard/DashboardVariableControl.tsx +12 -2
- package/UI/Components/Dropdown/Dropdown.tsx +6 -1
- package/UI/Components/EditionLabel/EditionLabel.tsx +808 -1195
- package/UI/Components/EditionLabel/LicenseManager.ts +119 -0
- package/UI/Components/EventItem/EventItem.tsx +12 -1
- package/UI/Components/Forms/BasicForm.tsx +151 -126
- package/UI/Components/Forms/CollapsibleFormSection.tsx +63 -0
- package/UI/Components/Forms/Fields/FormField.tsx +10 -4
- package/UI/Components/Forms/FormSummary.tsx +7 -0
- package/UI/Components/Forms/Types/Field.ts +10 -0
- package/UI/Components/Graphs/DayUptimeGraph.tsx +123 -15
- package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +2 -1
- package/UI/Components/Markdown.tsx/SessionAwareImage.tsx +122 -0
- package/UI/Components/ModelList/ModelList.tsx +11 -1
- package/UI/Components/ModelTable/BaseModelTable.tsx +34 -5
- package/UI/Components/ModelTable/TableView.tsx +1 -1
- package/UI/Components/MonitorGraphs/Uptime.tsx +69 -0
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +28 -12
- package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +8 -1
- package/UI/Components/Tooltip/Tooltip.tsx +8 -1
- package/UI/Utils/API/API.ts +173 -12
- package/UI/Utils/API/RequestOptions.ts +11 -0
- package/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.ts +31 -7
- package/UI/Utils/ModelAPI/ModelAPI.ts +30 -9
- package/UI/Utils/Navigation.ts +9 -0
- package/UI/Utils/OpenAuthenticatedUrl.ts +154 -0
- package/UI/Utils/Realtime.ts +176 -30
- package/UI/esbuild-enterprise.js +263 -0
- package/Utils/API.ts +14 -5
- package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +7 -2
- package/Utils/HostAddressUtil.ts +94 -0
- package/Utils/Monitor/MonitorDestinationUtil.ts +157 -0
- package/Utils/Monitor/MonitoringIntervalUtil.ts +436 -0
- package/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.ts +157 -7
- package/Utils/SecurityEvent/Sigma/SigmaRuleParser.ts +9 -17
- package/Utils/Slo/SloBurnRateTemplate.ts +2 -2
- package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +192 -0
- package/build/dist/Models/AnalyticsModels/AuditLog.js +23 -15
- package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +25 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +2 -2
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorTemplate.js +2 -1
- package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js +1 -1
- package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js.map +1 -1
- package/build/dist/Server/API/AIBillingAPI.js +1 -1
- package/build/dist/Server/API/AIBillingAPI.js.map +1 -1
- package/build/dist/Server/API/AIInsightAPI.js +1 -4
- package/build/dist/Server/API/AIInsightAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +1 -4
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/AIReadinessAPI.js +1 -3
- package/build/dist/Server/API/AIReadinessAPI.js.map +1 -1
- package/build/dist/Server/API/AlertAPI.js +1 -1
- package/build/dist/Server/API/AlertAPI.js.map +1 -1
- package/build/dist/Server/API/AutoRemediationAPI.js +1 -4
- package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +33 -0
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/BaseAnalyticsAPI.js +55 -10
- package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
- package/build/dist/Server/API/BillingAPI.js +2 -2
- package/build/dist/Server/API/BillingAPI.js.map +1 -1
- package/build/dist/Server/API/BillingInvoiceAPI.js +1 -1
- package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
- package/build/dist/Server/API/BillingPaymentMethodAPI.js +2 -2
- package/build/dist/Server/API/BillingPaymentMethodAPI.js.map +1 -1
- package/build/dist/Server/API/CodeFixRunAPI.js +1 -3
- package/build/dist/Server/API/CodeFixRunAPI.js.map +1 -1
- package/build/dist/Server/API/CommonAPI.js +50 -5
- package/build/dist/Server/API/CommonAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +12 -12
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/GlobalConfigAPI.js +158 -342
- package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentAPI.js +2 -2
- package/build/dist/Server/API/IncidentAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentEpisodeAPI.js +1 -1
- package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
- package/build/dist/Server/API/NotificationAPI.js +1 -1
- package/build/dist/Server/API/NotificationAPI.js.map +1 -1
- package/build/dist/Server/API/OnCallCalendarAPI.js +1 -4
- package/build/dist/Server/API/OnCallCalendarAPI.js.map +1 -1
- package/build/dist/Server/API/OnCallDutyPolicyAPI.js +6 -0
- package/build/dist/Server/API/OnCallDutyPolicyAPI.js.map +1 -1
- package/build/dist/Server/API/OnCallReadinessAPI.js +4 -1
- package/build/dist/Server/API/OnCallReadinessAPI.js.map +1 -1
- package/build/dist/Server/API/OnCallScheduleTimelineAPI.js +494 -0
- package/build/dist/Server/API/OnCallScheduleTimelineAPI.js.map +1 -0
- package/build/dist/Server/API/ProjectAPI.js +1 -1
- package/build/dist/Server/API/ProjectAPI.js.map +1 -1
- package/build/dist/Server/API/ProjectOIDC.js +24 -16
- package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
- package/build/dist/Server/API/ProjectSSO.js +24 -16
- package/build/dist/Server/API/ProjectSSO.js.map +1 -1
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js +1 -1
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +218 -76
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/TeamMemberAPI.js +11 -4
- package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
- package/build/dist/Server/API/UserCallAPI.js +2 -2
- package/build/dist/Server/API/UserCallAPI.js.map +1 -1
- package/build/dist/Server/API/UserEmailAPI.js +2 -2
- package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js +2 -2
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
- package/build/dist/Server/API/UserMicrosoftTeamsAPI.js +1 -1
- package/build/dist/Server/API/UserMicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/UserSlackAPI.js +1 -1
- package/build/dist/Server/API/UserSlackAPI.js.map +1 -1
- package/build/dist/Server/API/UserSmsAPI.js +2 -2
- package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
- package/build/dist/Server/API/UserTotpAuthAPI.js +1 -1
- package/build/dist/Server/API/UserTotpAuthAPI.js.map +1 -1
- package/build/dist/Server/API/UserWebAuthnAPI.js +2 -2
- package/build/dist/Server/API/UserWebAuthnAPI.js.map +1 -1
- package/build/dist/Server/API/UserWebhookAPI.js +1 -1
- package/build/dist/Server/API/UserWebhookAPI.js.map +1 -1
- package/build/dist/Server/API/UserWhatsAppAPI.js +2 -2
- package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseEdition.js +466 -0
- package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -0
- package/build/dist/Server/Enterprise/EnterpriseFeature.js +39 -0
- package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -0
- package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +70 -0
- package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js.map +1 -0
- package/build/dist/Server/Enterprise/EnterpriseServerModule.js +84 -0
- package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -0
- package/build/dist/Server/EnvironmentConfig.js +84 -2
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/MasterAdminAuthorization.js +11 -2
- package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +94 -15
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Services/ApiKeyPermissionService.js +80 -4
- package/build/dist/Server/Services/ApiKeyPermissionService.js.map +1 -1
- package/build/dist/Server/Services/AuditLogService.js +71 -740
- package/build/dist/Server/Services/AuditLogService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +171 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DetectionRuleService.js +4 -4
- package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseService.js +34 -0
- package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
- package/build/dist/Server/Services/GlobalConfigService.js +63 -0
- package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
- package/build/dist/Server/Services/MonitorProbeService.js +90 -17
- package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +45 -4
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusTimelineService.js +242 -0
- package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +16 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyChildService.js +170 -0
- package/build/dist/Server/Services/OnCallDutyPolicyChildService.js.map +1 -0
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +2 -2
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +2 -2
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js +2 -2
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +2 -2
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
- package/build/dist/Server/Services/PayAsYouGoBillingService.js +20 -27
- package/build/dist/Server/Services/PayAsYouGoBillingService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +231 -0
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/RumSessionPinService.js +198 -16
- package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserService.js +7 -3
- package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +71 -0
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +10 -0
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/TeamPermissionService.js +89 -27
- package/build/dist/Server/Services/TeamPermissionService.js.map +1 -1
- package/build/dist/Server/Services/TeamService.js +9 -0
- package/build/dist/Server/Services/TeamService.js.map +1 -1
- package/build/dist/Server/Services/ThreatIntelFeedService.js +5 -4
- package/build/dist/Server/Services/ThreatIntelFeedService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +10 -16
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/BasePermission.js +9 -6
- package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +10 -0
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +154 -14
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/Index.js +60 -6
- package/build/dist/Server/Types/Database/Permissions/Index.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/TablePermission.js +24 -16
- package/build/dist/Server/Types/Database/Permissions/TablePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +17 -0
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
- package/build/dist/Server/Types/Markdown.js +31 -0
- package/build/dist/Server/Types/Markdown.js.map +1 -1
- package/build/dist/Server/Utils/AI/AIChatPrivacyFilter.js +7 -0
- package/build/dist/Server/Utils/AI/AIChatPrivacyFilter.js.map +1 -1
- package/build/dist/Server/Utils/AI/AIRunPrivacyFilter.js +7 -0
- package/build/dist/Server/Utils/AI/AIRunPrivacyFilter.js.map +1 -1
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js +223 -0
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +1 -0
- package/build/dist/Server/Utils/EditionEnforcement.js +187 -0
- package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -0
- package/build/dist/Server/Utils/FrontendEnvironment.js +31 -2
- package/build/dist/Server/Utils/FrontendEnvironment.js.map +1 -1
- package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js +6 -193
- package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js.map +1 -1
- package/build/dist/Server/Utils/MasterAdminPageAccess.js +39 -0
- package/build/dist/Server/Utils/MasterAdminPageAccess.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/AffectedResourceList.js +96 -0
- package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +3 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +449 -261
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +3 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js +88 -0
- package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js.map +1 -0
- package/build/dist/Server/Utils/Realtime.js +126 -37
- package/build/dist/Server/Utils/Realtime.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +7 -25
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.js +127 -0
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js +3 -2
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js +4 -8
- package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js +331 -11
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
- package/build/dist/Types/API/Hostname.js +59 -11
- package/build/dist/Types/API/Hostname.js.map +1 -1
- package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js +31 -1
- package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +19 -7
- package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +19 -7
- package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +13 -6
- package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -1
- package/build/dist/Types/Database/CanonicalModelInstance.js +88 -0
- package/build/dist/Types/Database/CanonicalModelInstance.js.map +1 -0
- package/build/dist/Types/Database/TableColumn.js +19 -6
- package/build/dist/Types/Database/TableColumn.js.map +1 -1
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +28 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js.map +1 -0
- package/build/dist/Types/IP/IPv6.js +6 -1
- package/build/dist/Types/IP/IPv6.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +5 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +1 -1
- package/build/dist/Types/OnCallDutyPolicy/ScheduleTimeline.js +321 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleTimeline.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleTimelineLayout.js +372 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleTimelineLayout.js.map +1 -0
- package/build/dist/Types/Realtime/EventName.js +10 -0
- package/build/dist/Types/Realtime/EventName.js.map +1 -1
- package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +11 -0
- package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
- package/build/dist/Types/SecurityEvent/OcsfSeverity.js +30 -25
- package/build/dist/Types/SecurityEvent/OcsfSeverity.js.map +1 -1
- package/build/dist/Types/SecurityEvent/SigmaRule.js +47 -0
- package/build/dist/Types/SecurityEvent/SigmaRule.js.map +1 -1
- package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js +14 -0
- package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js.map +1 -1
- package/build/dist/Types/StatusPage/UptimeDailyAggregate.js +32 -0
- package/build/dist/Types/StatusPage/UptimeDailyAggregate.js.map +1 -0
- package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js +9 -4
- package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js.map +1 -1
- package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js +10 -2
- package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js.map +1 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js +5 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +425 -585
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/LicenseManager.js +2 -0
- package/build/dist/UI/Components/EditionLabel/LicenseManager.js.map +1 -0
- package/build/dist/UI/Components/EventItem/EventItem.js +2 -2
- package/build/dist/UI/Components/EventItem/EventItem.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js +70 -64
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/CollapsibleFormSection.js +27 -0
- package/build/dist/UI/Components/Forms/CollapsibleFormSection.js.map +1 -0
- package/build/dist/UI/Components/Forms/Fields/FormField.js +10 -7
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Forms/FormSummary.js +7 -0
- package/build/dist/UI/Components/Forms/FormSummary.js.map +1 -1
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +90 -17
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +2 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/SessionAwareImage.js +84 -0
- package/build/dist/UI/Components/Markdown.tsx/SessionAwareImage.js.map +1 -0
- package/build/dist/UI/Components/ModelList/ModelList.js +4 -1
- package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +14 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/TableView.js +1 -1
- package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js +42 -1
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +2 -2
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +8 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js +2 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
- package/build/dist/UI/Utils/API/API.js +143 -19
- package/build/dist/UI/Utils/API/API.js.map +1 -1
- package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js +21 -7
- package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +26 -9
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +8 -0
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/UI/Utils/OpenAuthenticatedUrl.js +92 -0
- package/build/dist/UI/Utils/OpenAuthenticatedUrl.js.map +1 -0
- package/build/dist/UI/Utils/Realtime.js +120 -15
- package/build/dist/UI/Utils/Realtime.js.map +1 -1
- package/build/dist/Utils/API.js +13 -5
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +6 -2
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
- package/build/dist/Utils/HostAddressUtil.js +80 -0
- package/build/dist/Utils/HostAddressUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorDestinationUtil.js +127 -0
- package/build/dist/Utils/Monitor/MonitorDestinationUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js +374 -0
- package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js +123 -6
- package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js.map +1 -1
- package/build/dist/Utils/SecurityEvent/Sigma/SigmaRuleParser.js +4 -18
- package/build/dist/Utils/SecurityEvent/Sigma/SigmaRuleParser.js.map +1 -1
- package/build/dist/Utils/Slo/SloBurnRateTemplate.js +2 -2
- package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js +148 -0
- package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js.map +1 -0
- package/jest.config.json +3 -1
- package/package.json +1 -1
- package/test-setup.sh +103 -34
- package/tsconfig.json +13 -0
- package/Server/API/EnterpriseLicenseAPI.ts +0 -925
- package/Server/API/TeamComplianceAPI.ts +0 -158
- package/Server/Middleware/SCIMAuthorization.ts +0 -141
- package/Server/Services/TeamComplianceService.ts +0 -733
- package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +0 -186
- package/Server/Utils/InstanceHealth/PostgresHealth.ts +0 -286
- package/Tests/App/AdminDashboard/EnterpriseLicenseInstanceActivity.test.tsx +0 -451
- package/Tests/App/Dashboard/AuditLogsTable.test.tsx +0 -598
- package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +0 -247
- package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +0 -382
- package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +0 -1851
- package/Tests/Server/Middleware/SCIMAuthorization.test.ts +0 -525
- package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +0 -1845
- package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +0 -495
- package/Tests/Server/Utils/InstanceHealth/PostgresHealth.test.ts +0 -337
- package/Tests/Utils/EnterpriseLicenseSeats.test.ts +0 -576
- package/Tests/Utils/EnterpriseLicenseSync.test.ts +0 -568
- package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +0 -287
- package/Utils/EnterpriseLicense/EnterpriseLicenseSync.ts +0 -244
- package/build/dist/Server/API/EnterpriseLicenseAPI.js +0 -646
- package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +0 -1
- package/build/dist/Server/API/TeamComplianceAPI.js +0 -111
- package/build/dist/Server/API/TeamComplianceAPI.js.map +0 -1
- package/build/dist/Server/Middleware/SCIMAuthorization.js +0 -124
- package/build/dist/Server/Middleware/SCIMAuthorization.js.map +0 -1
- package/build/dist/Server/Services/TeamComplianceService.js +0 -537
- package/build/dist/Server/Services/TeamComplianceService.js.map +0 -1
- package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +0 -145
- package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +0 -1
- package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js +0 -194
- package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js.map +0 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +0 -168
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +0 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js +0 -174
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js.map +0 -1
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
2
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
3
|
+
import {
|
|
4
|
+
UptimeDailyAggregate,
|
|
5
|
+
UptimeDayBucket,
|
|
6
|
+
} from "../../../Types/StatusPage/UptimeDailyAggregate";
|
|
7
|
+
import UptimeDailyAggregateUtil from "../../../Utils/StatusPage/UptimeDailyAggregateUtil";
|
|
8
|
+
import { describe, expect, test } from "@jest/globals";
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* WHAT THIS FILE IS DEFENDING
|
|
12
|
+
*
|
|
13
|
+
* The wire format for the uptime aggregate, which replaced shipping raw
|
|
14
|
+
* MonitorStatusTimeline rows to the status page.
|
|
15
|
+
*
|
|
16
|
+
* Two properties matter more than the round trip itself:
|
|
17
|
+
*
|
|
18
|
+
* 1. It must be SMALL. The rows it replaces serialize to ~431 bytes each,
|
|
19
|
+
* almost entirely typed-JSON envelopes, so one real status page's 254,550
|
|
20
|
+
* matching rows came to ~105 MB. If this format ever grows envelopes it
|
|
21
|
+
* gives that back.
|
|
22
|
+
*
|
|
23
|
+
* 2. Parsing must be TOTAL. A status page that cannot read its aggregate has
|
|
24
|
+
* to fall back to "no data", which is honest. What it must never do is
|
|
25
|
+
* fall back to something that looks like uptime.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
const MONITOR_A: string = "11111111-1111-4111-8111-111111111111";
|
|
29
|
+
const STATUS_UP: string = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa";
|
|
30
|
+
|
|
31
|
+
function sample(): UptimeDailyAggregate {
|
|
32
|
+
return {
|
|
33
|
+
monitors: [
|
|
34
|
+
{
|
|
35
|
+
monitorId: new ObjectID(MONITOR_A),
|
|
36
|
+
buckets: [
|
|
37
|
+
{
|
|
38
|
+
bucketStart: new Date("2026-07-01T00:00:00.000Z"),
|
|
39
|
+
bucketEnd: new Date("2026-07-02T00:00:00.000Z"),
|
|
40
|
+
daySeconds: 86400,
|
|
41
|
+
coveredSeconds: 86400,
|
|
42
|
+
statusDurations: [
|
|
43
|
+
{
|
|
44
|
+
monitorStatusId: new ObjectID(STATUS_UP),
|
|
45
|
+
seconds: 86400,
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
bucketStart: new Date("2026-07-02T00:00:00.000Z"),
|
|
51
|
+
bucketEnd: new Date("2026-07-03T00:00:00.000Z"),
|
|
52
|
+
daySeconds: 86400,
|
|
53
|
+
coveredSeconds: 0,
|
|
54
|
+
statusDurations: [],
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
isComplete: true,
|
|
60
|
+
completeFrom: null,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
describe("UptimeDailyAggregateUtil", () => {
|
|
65
|
+
describe("round trip", () => {
|
|
66
|
+
test("survives toJSON -> fromJSON unchanged", () => {
|
|
67
|
+
const parsed: UptimeDailyAggregate = UptimeDailyAggregateUtil.fromJSON(
|
|
68
|
+
UptimeDailyAggregateUtil.toJSON(sample()),
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
expect(parsed.monitors).toHaveLength(1);
|
|
72
|
+
expect(parsed.monitors[0]!.monitorId.toString()).toBe(MONITOR_A);
|
|
73
|
+
expect(parsed.monitors[0]!.buckets).toHaveLength(2);
|
|
74
|
+
|
|
75
|
+
const first: UptimeDayBucket = parsed.monitors[0]!.buckets[0]!;
|
|
76
|
+
|
|
77
|
+
expect(first.coveredSeconds).toBe(86400);
|
|
78
|
+
expect(first.daySeconds).toBe(86400);
|
|
79
|
+
expect(first.bucketStart.toISOString()).toBe("2026-07-01T00:00:00.000Z");
|
|
80
|
+
expect(first.statusDurations[0]!.monitorStatusId.toString()).toBe(
|
|
81
|
+
STATUS_UP,
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test("a no-data day survives as a no-data day", () => {
|
|
86
|
+
/*
|
|
87
|
+
* The single most important thing to preserve. If coverage were lost in
|
|
88
|
+
* transit the client would treat the day as ordinary and paint it with
|
|
89
|
+
* the operator's colour - which is the bug this whole change removes.
|
|
90
|
+
*/
|
|
91
|
+
const parsed: UptimeDailyAggregate = UptimeDailyAggregateUtil.fromJSON(
|
|
92
|
+
UptimeDailyAggregateUtil.toJSON(sample()),
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
expect(parsed.monitors[0]!.buckets[1]!.coveredSeconds).toBe(0);
|
|
96
|
+
expect(parsed.monitors[0]!.buckets[1]!.statusDurations).toHaveLength(0);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe("the wire format stays small", () => {
|
|
101
|
+
test("dates and ids are plain strings, not typed-JSON envelopes", () => {
|
|
102
|
+
const json: JSONObject = UptimeDailyAggregateUtil.toJSON(sample());
|
|
103
|
+
const encoded: string = JSON.stringify(json);
|
|
104
|
+
|
|
105
|
+
expect(encoded).not.toContain("_type");
|
|
106
|
+
expect(encoded).toContain("2026-07-01T00:00:00.000Z");
|
|
107
|
+
expect(encoded).toContain(MONITOR_A);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("a 90-day, 50-monitor page stays far below the row payload it replaces", () => {
|
|
111
|
+
/*
|
|
112
|
+
* The rows this replaces were ~431 bytes each and a real page matched
|
|
113
|
+
* 254,550 of them (~105 MB). This asserts the replacement is bounded by
|
|
114
|
+
* structure rather than by how much a monitor flaps.
|
|
115
|
+
*/
|
|
116
|
+
const aggregate: UptimeDailyAggregate = {
|
|
117
|
+
monitors: [],
|
|
118
|
+
isComplete: true,
|
|
119
|
+
completeFrom: null,
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
for (let m: number = 0; m < 50; m++) {
|
|
123
|
+
const buckets: Array<UptimeDayBucket> = [];
|
|
124
|
+
|
|
125
|
+
for (let d: number = 0; d < 90; d++) {
|
|
126
|
+
const start: Date = new Date(
|
|
127
|
+
Date.UTC(2026, 3, 1) + d * 24 * 60 * 60 * 1000,
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
buckets.push({
|
|
131
|
+
bucketStart: start,
|
|
132
|
+
bucketEnd: new Date(start.getTime() + 86400000),
|
|
133
|
+
daySeconds: 86400,
|
|
134
|
+
coveredSeconds: 86400,
|
|
135
|
+
statusDurations: [
|
|
136
|
+
{ monitorStatusId: new ObjectID(STATUS_UP), seconds: 86000 },
|
|
137
|
+
{ monitorStatusId: new ObjectID(MONITOR_A), seconds: 400 },
|
|
138
|
+
],
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
aggregate.monitors.push({
|
|
143
|
+
monitorId: new ObjectID(
|
|
144
|
+
`${MONITOR_A.slice(0, -2)}${m % 10}${m % 10}`,
|
|
145
|
+
),
|
|
146
|
+
buckets,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const bytes: number = JSON.stringify(
|
|
151
|
+
UptimeDailyAggregateUtil.toJSON(aggregate),
|
|
152
|
+
).length;
|
|
153
|
+
|
|
154
|
+
// Comfortably under a megabyte for the largest page the product allows.
|
|
155
|
+
expect(bytes).toBeLessThan(1_500_000);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
describe("parsing is total", () => {
|
|
160
|
+
test.each([
|
|
161
|
+
["null", null],
|
|
162
|
+
["undefined", undefined],
|
|
163
|
+
["an empty object", {}],
|
|
164
|
+
["monitors not an array", { monitors: "nope" }],
|
|
165
|
+
])(
|
|
166
|
+
"%s yields an empty aggregate rather than throwing",
|
|
167
|
+
(_name: string, input: unknown) => {
|
|
168
|
+
expect(() => {
|
|
169
|
+
return UptimeDailyAggregateUtil.fromJSON(input as JSONObject);
|
|
170
|
+
}).not.toThrow();
|
|
171
|
+
|
|
172
|
+
const parsed: UptimeDailyAggregate = UptimeDailyAggregateUtil.fromJSON(
|
|
173
|
+
input as JSONObject,
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
expect(parsed.monitors).toHaveLength(0);
|
|
177
|
+
},
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
test("a bucket with an unparseable date is dropped, not turned into coverage", () => {
|
|
181
|
+
const parsed: UptimeDailyAggregate = UptimeDailyAggregateUtil.fromJSON({
|
|
182
|
+
monitors: [
|
|
183
|
+
{
|
|
184
|
+
monitorId: MONITOR_A,
|
|
185
|
+
buckets: [
|
|
186
|
+
{
|
|
187
|
+
bucketStart: "not-a-date",
|
|
188
|
+
bucketEnd: "also-not",
|
|
189
|
+
daySeconds: 1,
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
weird: true,
|
|
195
|
+
} as unknown as JSONObject);
|
|
196
|
+
|
|
197
|
+
expect(parsed.monitors[0]!.buckets).toHaveLength(0);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("a missing isComplete means complete, not incomplete", () => {
|
|
201
|
+
/*
|
|
202
|
+
* An older server has no cap in this path either. Defaulting to
|
|
203
|
+
* incomplete would grey out every bar on a perfectly healthy page.
|
|
204
|
+
*/
|
|
205
|
+
const parsed: UptimeDailyAggregate = UptimeDailyAggregateUtil.fromJSON({
|
|
206
|
+
monitors: [],
|
|
207
|
+
} as unknown as JSONObject);
|
|
208
|
+
|
|
209
|
+
expect(parsed.isComplete).toBe(true);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test("an explicit isComplete false is honoured", () => {
|
|
213
|
+
const parsed: UptimeDailyAggregate = UptimeDailyAggregateUtil.fromJSON({
|
|
214
|
+
monitors: [],
|
|
215
|
+
isComplete: false,
|
|
216
|
+
completeFrom: "2026-07-05T00:00:00.000Z",
|
|
217
|
+
} as unknown as JSONObject);
|
|
218
|
+
|
|
219
|
+
expect(parsed.isComplete).toBe(false);
|
|
220
|
+
expect(parsed.completeFrom?.toISOString()).toBe(
|
|
221
|
+
"2026-07-05T00:00:00.000Z",
|
|
222
|
+
);
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
describe("getBucketsForMonitor", () => {
|
|
227
|
+
test("returns that monitor's buckets", () => {
|
|
228
|
+
expect(
|
|
229
|
+
UptimeDailyAggregateUtil.getBucketsForMonitor(sample(), MONITOR_A),
|
|
230
|
+
).toHaveLength(2);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
test("returns empty for a monitor that is not in the aggregate", () => {
|
|
234
|
+
expect(
|
|
235
|
+
UptimeDailyAggregateUtil.getBucketsForMonitor(
|
|
236
|
+
sample(),
|
|
237
|
+
"99999999-9999-4999-8999-999999999999",
|
|
238
|
+
),
|
|
239
|
+
).toHaveLength(0);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test("returns empty rather than throwing when there is no aggregate", () => {
|
|
243
|
+
expect(
|
|
244
|
+
UptimeDailyAggregateUtil.getBucketsForMonitor(null, MONITOR_A),
|
|
245
|
+
).toHaveLength(0);
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
});
|
package/Types/API/Hostname.ts
CHANGED
|
@@ -3,6 +3,8 @@ import BadDataException from "../Exception/BadDataException";
|
|
|
3
3
|
import { JSONObject, ObjectType } from "../JSON";
|
|
4
4
|
import Port from "../Port";
|
|
5
5
|
import Typeof from "../Typeof";
|
|
6
|
+
import HostAddressUtil from "../../Utils/HostAddressUtil";
|
|
7
|
+
import IP from "../IP/IP";
|
|
6
8
|
import { FindOperator } from "typeorm";
|
|
7
9
|
|
|
8
10
|
/*
|
|
@@ -22,10 +24,26 @@ const HOST_REGEX: RegExp =
|
|
|
22
24
|
*/
|
|
23
25
|
const USER_INFO_REGEX: RegExp = /^[^@/?#\s[\]]*$/;
|
|
24
26
|
|
|
25
|
-
const IPV6_CHARS_REGEX: RegExp = /^[0-9a-fA-F:.]+$/;
|
|
26
|
-
|
|
27
27
|
const PORT_REGEX: RegExp = /^\d{1,5}$/;
|
|
28
28
|
|
|
29
|
+
/*
|
|
30
|
+
* The authority spellings of an IPv6 host: bracketed ("[::1]", "[::1]:8080")
|
|
31
|
+
* or bare. Two or more colons cannot be a "host:port", so every colon in a
|
|
32
|
+
* bare value belongs to the address itself.
|
|
33
|
+
*
|
|
34
|
+
* This only decides which SHAPE a value has. Whether what it holds is really
|
|
35
|
+
* an address is IP.isIP's job, and isValid below asks it -- the old code
|
|
36
|
+
* settled for a "[0-9a-fA-F:.]+" charset, which called "::::" and
|
|
37
|
+
* "1.2.3.4.5.6" valid hosts and then handed them to a socket.
|
|
38
|
+
*/
|
|
39
|
+
function isIPv6Authority(authority: string): boolean {
|
|
40
|
+
return authority.startsWith("[") || (authority.match(/:/g) || []).length > 1;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isIPv6Address(value: string): boolean {
|
|
44
|
+
return Boolean(value) && IP.isIP(value) && new IP(value).isIPv6();
|
|
45
|
+
}
|
|
46
|
+
|
|
29
47
|
export default class Hostname extends DatabaseProperty {
|
|
30
48
|
private _route: string = "";
|
|
31
49
|
public get hostname(): string {
|
|
@@ -104,15 +122,15 @@ export default class Hostname extends DatabaseProperty {
|
|
|
104
122
|
/^\[([0-9a-fA-F:.]+)\](?::(\d{1,5}))?$/,
|
|
105
123
|
);
|
|
106
124
|
if (bracketedIpv6Match) {
|
|
107
|
-
return
|
|
125
|
+
return isIPv6Address(bracketedIpv6Match[1] as string);
|
|
108
126
|
}
|
|
109
127
|
|
|
110
128
|
/*
|
|
111
129
|
* Unbracketed IPv6 literal. Two or more colons cannot be a "host:port",
|
|
112
130
|
* so the colons must be part of the address itself.
|
|
113
131
|
*/
|
|
114
|
-
if ((authority
|
|
115
|
-
return
|
|
132
|
+
if (isIPv6Authority(authority)) {
|
|
133
|
+
return isIPv6Address(authority);
|
|
116
134
|
}
|
|
117
135
|
|
|
118
136
|
const colonIndex: number = authority.indexOf(":");
|
|
@@ -158,28 +176,57 @@ export default class Hostname extends DatabaseProperty {
|
|
|
158
176
|
throw new BadDataException("Invalid JSON: " + JSON.stringify(json));
|
|
159
177
|
}
|
|
160
178
|
|
|
179
|
+
/*
|
|
180
|
+
* The authority form. An IPv6 host is BRACKETED once a port is appended,
|
|
181
|
+
* because "2001:db8::1" + ":179" is not an ambiguous-looking string — it is
|
|
182
|
+
* "2001:db8::1:179", which net.isIP() accepts as a different, perfectly
|
|
183
|
+
* valid address. Anything that read this back (or showed it to an operator)
|
|
184
|
+
* was therefore pointed at a host nobody configured.
|
|
185
|
+
*
|
|
186
|
+
* Without a port the host is returned exactly as it is held, brackets and
|
|
187
|
+
* all. A bracketed value came from a URL authority and has to go back into
|
|
188
|
+
* one — dropping the brackets there would make URL.toString() emit
|
|
189
|
+
* "https://2001:db8::1/", which no URL parser accepts.
|
|
190
|
+
*/
|
|
161
191
|
public override toString(): string {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if (this.port) {
|
|
165
|
-
hostname += ":" + this.port.toString();
|
|
192
|
+
if (!this.port) {
|
|
193
|
+
return this.hostname;
|
|
166
194
|
}
|
|
167
195
|
|
|
168
|
-
return
|
|
196
|
+
return HostAddressUtil.formatHostAndPort({
|
|
197
|
+
host: this.hostname,
|
|
198
|
+
port: this.port.toString(),
|
|
199
|
+
});
|
|
169
200
|
}
|
|
170
201
|
|
|
202
|
+
/*
|
|
203
|
+
* Reads a stored host, which may carry a ":port".
|
|
204
|
+
*
|
|
205
|
+
* IPv6 literals are handed to fromAuthority instead of being split, because
|
|
206
|
+
* splitting on the first colon is meaningless for an address that is made
|
|
207
|
+
* of colons: "2001:518:2800:9::2" used to come back as host "2001" with
|
|
208
|
+
* port 518 — and because 518 is a legal port number NOTHING threw. A
|
|
209
|
+
* monitor saved from the dashboard therefore silently pointed at a host
|
|
210
|
+
* called "2001", and the address the operator typed was simply gone.
|
|
211
|
+
*
|
|
212
|
+
* DNS names and IPv4 literals keep the original behaviour exactly: neither
|
|
213
|
+
* can contain two colons, so neither can reach the new branch.
|
|
214
|
+
*/
|
|
171
215
|
public static fromString(hostname: string | Hostname): Hostname {
|
|
172
216
|
if (hostname instanceof Hostname) {
|
|
173
217
|
hostname = hostname.toString();
|
|
174
218
|
}
|
|
175
219
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
220
|
+
const value: string = (hostname || "").trim();
|
|
221
|
+
|
|
222
|
+
if (isIPv6Authority(value)) {
|
|
223
|
+
return Hostname.fromAuthority(value);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (value.includes(":")) {
|
|
227
|
+
return new Hostname(value.split(":")[0] as string, value.split(":")[1]);
|
|
181
228
|
}
|
|
182
|
-
return new Hostname(
|
|
229
|
+
return new Hostname(value);
|
|
183
230
|
}
|
|
184
231
|
|
|
185
232
|
/*
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import Permission, { UserPermission } from "../Permission";
|
|
2
2
|
import DatabaseCommonInteractionProps from "./DatabaseCommonInteractionProps";
|
|
3
|
+
import NotAuthenticatedException from "../Exception/NotAuthenticatedException";
|
|
4
|
+
import UserType from "../UserType";
|
|
3
5
|
|
|
4
6
|
export enum PermissionType {
|
|
5
7
|
Allow = "Allow",
|
|
@@ -7,6 +9,44 @@ export enum PermissionType {
|
|
|
7
9
|
}
|
|
8
10
|
|
|
9
11
|
export default class DatabaseCommonInteractionPropsUtil {
|
|
12
|
+
public static readonly AUTHENTICATION_REQUIRED_MESSAGE: string =
|
|
13
|
+
"Authentication required. Please log in to access this resource.";
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
* No credentials at all: no user, no project API key, no master key.
|
|
17
|
+
*
|
|
18
|
+
* In practice this is almost never a stranger. The dashboard's access-token
|
|
19
|
+
* cookie expires together with the JWT inside it, so once a tab has sat idle
|
|
20
|
+
* past the token lifetime the browser simply stops sending it, and
|
|
21
|
+
* getUserMiddleware lets the request through as Public with no userId. The
|
|
22
|
+
* caller is a signed-in user whose session needs refreshing.
|
|
23
|
+
*/
|
|
24
|
+
public static isAnonymous(props: DatabaseCommonInteractionProps): boolean {
|
|
25
|
+
if (props.userId) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
props.userType !== UserType.API && props.userType !== UserType.MasterAdmin
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
* "Who are you?" comes before "may you?". An anonymous caller has to be
|
|
36
|
+
* refused with 401, never 422 or 400: the browser client refreshes the
|
|
37
|
+
* session and replays the request on a 401 and on nothing else, so any other
|
|
38
|
+
* status leaves a signed-in user looking at a bogus error.
|
|
39
|
+
*/
|
|
40
|
+
public static assertCredentialsPresent(
|
|
41
|
+
props: DatabaseCommonInteractionProps,
|
|
42
|
+
): void {
|
|
43
|
+
if (DatabaseCommonInteractionPropsUtil.isAnonymous(props)) {
|
|
44
|
+
throw new NotAuthenticatedException(
|
|
45
|
+
DatabaseCommonInteractionPropsUtil.AUTHENTICATION_REQUIRED_MESSAGE,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
10
50
|
public static getUserPermissions(
|
|
11
51
|
props: DatabaseCommonInteractionProps,
|
|
12
52
|
permissionType: PermissionType,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
2
2
|
import { ColumnAccessControl } from "../../BaseDatabase/AccessControl";
|
|
3
|
+
import getCanonicalModelInstance from "../CanonicalModelInstance";
|
|
3
4
|
import Dictionary from "../../Dictionary";
|
|
4
5
|
import { ReflectionMetadataType } from "../../Reflection";
|
|
5
6
|
import "reflect-metadata";
|
|
@@ -31,10 +32,12 @@ type GetColumnAccessControlForAllColumnsFunction = <T extends BaseModel>(
|
|
|
31
32
|
) => Dictionary<ColumnAccessControl>;
|
|
32
33
|
|
|
33
34
|
/*
|
|
34
|
-
* Per-class cache
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
35
|
+
* Per-class cache, keyed on the constructor and built from a canonical
|
|
36
|
+
* instance of that class rather than from whichever instance asked first, so
|
|
37
|
+
* a caller that has deleted a column off its own instance cannot define what
|
|
38
|
+
* the class reports for the rest of the process. See
|
|
39
|
+
* CanonicalModelInstance.ts for the bug this prevents. Callers must treat the
|
|
40
|
+
* returned dictionary as read-only.
|
|
38
41
|
*/
|
|
39
42
|
const accessControlCache: WeakMap<
|
|
40
43
|
{ new (): BaseModel },
|
|
@@ -50,12 +53,14 @@ export const getColumnAccessControlForAllColumns: GetColumnAccessControlForAllCo
|
|
|
50
53
|
accessControlCache.get(modelClass);
|
|
51
54
|
|
|
52
55
|
if (!cached) {
|
|
56
|
+
const canonical: T | null = getCanonicalModelInstance(target);
|
|
57
|
+
const metadataSource: T = canonical || target;
|
|
53
58
|
const dictonary: Dictionary<ColumnAccessControl> = {};
|
|
54
|
-
const keys: Array<string> = Object.keys(
|
|
59
|
+
const keys: Array<string> = Object.keys(metadataSource);
|
|
55
60
|
|
|
56
61
|
for (const key of keys) {
|
|
57
62
|
const accessControl: ColumnAccessControl | undefined =
|
|
58
|
-
Reflect.getMetadata(accessControlSymbol,
|
|
63
|
+
Reflect.getMetadata(accessControlSymbol, metadataSource, key) as
|
|
59
64
|
| ColumnAccessControl
|
|
60
65
|
| undefined;
|
|
61
66
|
if (accessControl) {
|
|
@@ -64,7 +69,14 @@ export const getColumnAccessControlForAllColumns: GetColumnAccessControlForAllCo
|
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
cached = dictonary;
|
|
67
|
-
|
|
72
|
+
/*
|
|
73
|
+
* No canonical instance (see CanonicalModelInstance): answer from the
|
|
74
|
+
* instance we were handed, but do NOT cache it for the class - that
|
|
75
|
+
* instance may be a mutilated one, and a cached answer outlives it.
|
|
76
|
+
*/
|
|
77
|
+
if (canonical) {
|
|
78
|
+
accessControlCache.set(modelClass, cached);
|
|
79
|
+
}
|
|
68
80
|
}
|
|
69
81
|
|
|
70
82
|
return cached;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
2
2
|
import ColumnBillingAccessControl from "../../BaseDatabase/ColumnBillingAccessControl";
|
|
3
|
+
import getCanonicalModelInstance from "../CanonicalModelInstance";
|
|
3
4
|
import Dictionary from "../../Dictionary";
|
|
4
5
|
import { ReflectionMetadataType } from "../../Reflection";
|
|
5
6
|
import "reflect-metadata";
|
|
@@ -31,10 +32,12 @@ type GetColumnBillingAccessControlForAllColumnsFunction = <T extends BaseModel>(
|
|
|
31
32
|
) => Dictionary<ColumnBillingAccessControl>;
|
|
32
33
|
|
|
33
34
|
/*
|
|
34
|
-
* Per-class cache
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
35
|
+
* Per-class cache, keyed on the constructor and built from a canonical
|
|
36
|
+
* instance of that class rather than from whichever instance asked first, so
|
|
37
|
+
* a caller that has deleted a column off its own instance cannot define what
|
|
38
|
+
* the class reports for the rest of the process. See
|
|
39
|
+
* CanonicalModelInstance.ts for the bug this prevents. Callers must treat the
|
|
40
|
+
* returned dictionary as read-only.
|
|
38
41
|
*/
|
|
39
42
|
const billingAccessControlCache: WeakMap<
|
|
40
43
|
{ new (): BaseModel },
|
|
@@ -50,12 +53,14 @@ export const getColumnBillingAccessControlForAllColumns: GetColumnBillingAccessC
|
|
|
50
53
|
billingAccessControlCache.get(modelClass);
|
|
51
54
|
|
|
52
55
|
if (!cached) {
|
|
56
|
+
const canonical: T | null = getCanonicalModelInstance(target);
|
|
57
|
+
const metadataSource: T = canonical || target;
|
|
53
58
|
const dictonary: Dictionary<ColumnBillingAccessControl> = {};
|
|
54
|
-
const keys: Array<string> = Object.keys(
|
|
59
|
+
const keys: Array<string> = Object.keys(metadataSource);
|
|
55
60
|
|
|
56
61
|
for (const key of keys) {
|
|
57
62
|
const accessControl: ColumnBillingAccessControl | undefined =
|
|
58
|
-
Reflect.getMetadata(accessControlSymbol,
|
|
63
|
+
Reflect.getMetadata(accessControlSymbol, metadataSource, key) as
|
|
59
64
|
| ColumnBillingAccessControl
|
|
60
65
|
| undefined;
|
|
61
66
|
if (accessControl) {
|
|
@@ -64,7 +69,14 @@ export const getColumnBillingAccessControlForAllColumns: GetColumnBillingAccessC
|
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
cached = dictonary;
|
|
67
|
-
|
|
72
|
+
/*
|
|
73
|
+
* No canonical instance (see CanonicalModelInstance): answer from the
|
|
74
|
+
* instance we were handed, but do NOT cache it for the class - that
|
|
75
|
+
* instance may be a mutilated one, and a cached answer outlives it.
|
|
76
|
+
*/
|
|
77
|
+
if (canonical) {
|
|
78
|
+
billingAccessControlCache.set(modelClass, cached);
|
|
79
|
+
}
|
|
68
80
|
}
|
|
69
81
|
|
|
70
82
|
return cached;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
2
|
+
import getCanonicalModelInstance from "../CanonicalModelInstance";
|
|
2
3
|
import { ReflectionMetadataType } from "../../Reflection";
|
|
3
4
|
import "reflect-metadata";
|
|
4
5
|
|
|
@@ -66,10 +67,14 @@ type GetOwnerOnlyColumnsFunction = <T extends BaseModel>(
|
|
|
66
67
|
) => Array<string>;
|
|
67
68
|
|
|
68
69
|
/**
|
|
69
|
-
* Every owner-only column on this model.
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
70
|
+
* Every owner-only column on this model. Which columns a MODEL marks is a
|
|
71
|
+
* property of the class, so the enumeration reads a canonical instance of the
|
|
72
|
+
* class rather than the caller's own instance: a caller that had deleted a
|
|
73
|
+
* key off its instance would otherwise get an answer that silently omits a
|
|
74
|
+
* marked column, and this list is what OwnerOnlyColumnPermission enforces
|
|
75
|
+
* against. See CanonicalModelInstance.ts. (Enumerating at all relies on every
|
|
76
|
+
* declared column being initialised to `undefined` in the class body - the
|
|
77
|
+
* same assumption getTableColumns() makes.)
|
|
73
78
|
*/
|
|
74
79
|
export const getOwnerOnlyColumns: GetOwnerOnlyColumnsFunction = <
|
|
75
80
|
T extends BaseModel,
|
|
@@ -77,9 +82,13 @@ export const getOwnerOnlyColumns: GetOwnerOnlyColumnsFunction = <
|
|
|
77
82
|
target: T,
|
|
78
83
|
): Array<string> => {
|
|
79
84
|
const columns: Array<string> = [];
|
|
85
|
+
// Nothing is cached here, so falling back to the caller's instance is safe.
|
|
86
|
+
const metadataSource: T = getCanonicalModelInstance(target) || target;
|
|
80
87
|
|
|
81
|
-
for (const key of Object.keys(
|
|
82
|
-
if (
|
|
88
|
+
for (const key of Object.keys(metadataSource)) {
|
|
89
|
+
if (
|
|
90
|
+
Reflect.getMetadata(ownerOnlyColumnSymbol, metadataSource, key) === true
|
|
91
|
+
) {
|
|
83
92
|
columns.push(key);
|
|
84
93
|
}
|
|
85
94
|
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The one instance of a model class that column-metadata enumeration is
|
|
3
|
+
* allowed to look at.
|
|
4
|
+
*
|
|
5
|
+
* WHY THIS EXISTS.
|
|
6
|
+
*
|
|
7
|
+
* Every "which columns does this model have" lookup in this directory answers
|
|
8
|
+
* the question by enumerating an INSTANCE's own keys (Object.keys) and then
|
|
9
|
+
* caching the answer per CLASS. That is only sound while every instance of a
|
|
10
|
+
* class has the same own keys. The class bodies do guarantee that - each
|
|
11
|
+
* decorated column is initialised to `undefined` - right up until some caller
|
|
12
|
+
* deletes a key off a live instance.
|
|
13
|
+
*
|
|
14
|
+
* One caller did. BaseAPI.createItem used to `delete item._id` before handing
|
|
15
|
+
* the model to the service, and DatabaseService.create asks that very instance
|
|
16
|
+
* for its columns (generateDefaultValues). Whenever the mutilated instance was
|
|
17
|
+
* the first to ask, the class's cached column list was built WITHOUT `_id` -
|
|
18
|
+
* permanently, for the life of the process, for every later caller - and since
|
|
19
|
+
* DatabaseBaseModel.toJSONObject serialises a row by iterating exactly that
|
|
20
|
+
* list, every API response for that model silently lost its id. A single
|
|
21
|
+
* create was enough, including a create that was refused, because the columns
|
|
22
|
+
* are read before the permission check. Rows still carried their real `_id` in
|
|
23
|
+
* memory and in the SQL projection; it was dropped on the way out.
|
|
24
|
+
*
|
|
25
|
+
* So enumeration stopped reading the caller's instance. It reads a frozen,
|
|
26
|
+
* private instance of the caller's CLASS instead - constructed here, reachable
|
|
27
|
+
* by nobody, impossible to mutate - so what a class reports about itself can
|
|
28
|
+
* never depend on which instance happened to ask first, or on what anyone did
|
|
29
|
+
* to that instance. Reads already constructed a throwaway instance for exactly
|
|
30
|
+
* this purpose (SelectPermission, QueryPermission, ColumnPermission all do
|
|
31
|
+
* `new modelType()`), which is why a single read of a model was enough to make
|
|
32
|
+
* the same create harmless; this makes that the only behaviour.
|
|
33
|
+
*
|
|
34
|
+
* Every database model is no-arg constructible (Models/DatabaseModels/Index.ts
|
|
35
|
+
* relies on it already, in getModelTypeByName), and a fresh instance carries
|
|
36
|
+
* every declared column - both facts are asserted by
|
|
37
|
+
* Tests/Types/Database/CanonicalModelInstance.test.ts against all 400+ models.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
type NoArgConstructor = new () => unknown;
|
|
41
|
+
|
|
42
|
+
const canonicalInstanceCache: WeakMap<NoArgConstructor, unknown> =
|
|
43
|
+
new WeakMap();
|
|
44
|
+
|
|
45
|
+
/*
|
|
46
|
+
* Classes whose canonical instance is being constructed right now. A model
|
|
47
|
+
* constructor that asked for its own columns would otherwise recurse forever;
|
|
48
|
+
* such a call gets the caller's instance instead, which is the old behaviour.
|
|
49
|
+
*/
|
|
50
|
+
const beingConstructed: WeakSet<NoArgConstructor> = new WeakSet();
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* A frozen, shared instance of `target`'s class, safe to enumerate for
|
|
54
|
+
* metadata - or NULL when no such instance can be made: a class that needs
|
|
55
|
+
* constructor arguments, a class still being defined (circular imports), a
|
|
56
|
+
* constructor that throws, or a plain object with no useful constructor.
|
|
57
|
+
*
|
|
58
|
+
* Null, rather than falling back to `target`, because the two are NOT
|
|
59
|
+
* interchangeable and treating them as if they were is how this bug worked in
|
|
60
|
+
* the first place. A caller with no canonical instance may still answer from
|
|
61
|
+
* whatever instance it was handed - a metadata lookup must never be the reason
|
|
62
|
+
* a process fails to boot - but it must not then CACHE that answer for the
|
|
63
|
+
* class, because the instance it read may be a mutilated one and the cached
|
|
64
|
+
* answer would outlive it. Returning null forces each caller to make that
|
|
65
|
+
* decision in the open; the four caches in this directory all take the same
|
|
66
|
+
* route, and say so where they do it.
|
|
67
|
+
*/
|
|
68
|
+
export default function getCanonicalModelInstance<T>(target: T): T | null {
|
|
69
|
+
const modelClass: NoArgConstructor | undefined = (
|
|
70
|
+
target as { constructor?: NoArgConstructor } | null | undefined
|
|
71
|
+
)?.constructor;
|
|
72
|
+
|
|
73
|
+
if (typeof modelClass !== "function") {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const cached: unknown = canonicalInstanceCache.get(modelClass);
|
|
78
|
+
|
|
79
|
+
if (cached) {
|
|
80
|
+
return cached as T;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (beingConstructed.has(modelClass)) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
let canonical: T;
|
|
88
|
+
|
|
89
|
+
beingConstructed.add(modelClass);
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
canonical = Object.freeze(new modelClass()) as T;
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
95
|
+
} finally {
|
|
96
|
+
beingConstructed.delete(modelClass);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
canonicalInstanceCache.set(modelClass, canonical);
|
|
100
|
+
|
|
101
|
+
return canonical;
|
|
102
|
+
}
|