@oneuptime/common 12.0.30 → 12.0.31
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/SecurityEvent.ts +48 -16
- package/Models/AnalyticsModels/ThreatIntelIndicator.ts +10 -5
- package/Models/DatabaseModels/AlertSeverity.ts +44 -0
- package/Models/DatabaseModels/DetectionRule.ts +16 -5
- package/Models/DatabaseModels/GoogleSecOpsConnection.ts +14 -5
- package/Models/DatabaseModels/IncidentSeverity.ts +44 -0
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/NetworkDevice.ts +113 -3
- package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +88 -0
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +22 -0
- package/Models/DatabaseModels/NetworkDeviceOidTemplate.ts +499 -0
- package/Models/DatabaseModels/ThreatIntelFeed.ts +16 -5
- package/Server/API/GlobalConfigAPI.ts +362 -183
- package/Server/API/TelemetryAPI.ts +42 -4
- package/Server/EnvironmentConfig.ts +112 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790500000000-AddNetworkDeviceOidTemplate.ts +59 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790600000000-AddAutoImportRuleOidTemplate.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Middleware/MultipartFormData.ts +118 -32
- package/Server/Services/AlertEpisodeLabelRuleEngineService.ts +9 -1
- package/Server/Services/AlertEpisodeOnCallRuleEngineService.ts +9 -1
- package/Server/Services/AlertEpisodeOwnerRuleEngineService.ts +9 -1
- package/Server/Services/AlertEpisodePrivacyRuleEngineService.ts +9 -1
- package/Server/Services/AlertGroupingEngineService.ts +9 -1
- package/Server/Services/AlertLabelRuleEngineService.ts +9 -1
- package/Server/Services/AlertOnCallRuleEngineService.ts +9 -1
- package/Server/Services/AlertOwnerRuleEngineService.ts +9 -1
- package/Server/Services/AlertPrivacyRuleEngineService.ts +9 -1
- package/Server/Services/AlertReminderRuleService.ts +9 -1
- package/Server/Services/AutoRemediationRuleEngineService.ts +9 -1
- package/Server/Services/CephClusterLabelRuleEngineService.ts +9 -1
- package/Server/Services/CephClusterOwnerRuleEngineService.ts +9 -1
- package/Server/Services/CloudResourceLabelRuleEngineService.ts +9 -1
- package/Server/Services/CloudResourceOwnerRuleEngineService.ts +9 -1
- package/Server/Services/DashboardLabelRuleEngineService.ts +9 -1
- package/Server/Services/DashboardOwnerRuleEngineService.ts +9 -1
- package/Server/Services/DockerHostLabelRuleEngineService.ts +9 -1
- package/Server/Services/DockerHostOwnerRuleEngineService.ts +9 -1
- package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +9 -1
- package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +9 -1
- package/Server/Services/HostLabelRuleEngineService.ts +9 -1
- package/Server/Services/HostOwnerRuleEngineService.ts +9 -1
- package/Server/Services/IncidentEpisodeLabelRuleEngineService.ts +9 -1
- package/Server/Services/IncidentEpisodeOnCallRuleEngineService.ts +9 -1
- package/Server/Services/IncidentEpisodeOwnerRuleEngineService.ts +9 -1
- package/Server/Services/IncidentEpisodePrivacyRuleEngineService.ts +9 -1
- package/Server/Services/IncidentGroupingEngineService.ts +9 -1
- package/Server/Services/IncidentLabelRuleEngineService.ts +9 -1
- package/Server/Services/IncidentOnCallRuleEngineService.ts +9 -1
- package/Server/Services/IncidentOwnerRuleEngineService.ts +9 -1
- package/Server/Services/IncidentPrivacyRuleEngineService.ts +9 -1
- package/Server/Services/IncidentReminderRuleService.ts +9 -1
- package/Server/Services/IncidentSlaRuleService.ts +9 -1
- package/Server/Services/IncomingCallPolicyLabelRuleEngineService.ts +9 -1
- package/Server/Services/IncomingCallPolicyOwnerRuleEngineService.ts +9 -1
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/IoTFleetLabelRuleEngineService.ts +9 -1
- package/Server/Services/IoTFleetOwnerRuleEngineService.ts +9 -1
- package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +9 -1
- package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +9 -1
- package/Server/Services/KubernetesResourceService.ts +5 -1
- package/Server/Services/MonitorLabelRuleEngineService.ts +9 -1
- package/Server/Services/MonitorOwnerRuleEngineService.ts +9 -1
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +35 -0
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +96 -0
- package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +9 -1
- package/Server/Services/NetworkDeviceOidTemplateService.ts +201 -0
- package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +9 -1
- package/Server/Services/NetworkDeviceService.ts +209 -1
- package/Server/Services/OnCallDutyPolicyLabelRuleEngineService.ts +9 -1
- package/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.ts +9 -1
- package/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.ts +9 -1
- package/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.ts +9 -1
- package/Server/Services/PodmanHostLabelRuleEngineService.ts +9 -1
- package/Server/Services/PodmanHostOwnerRuleEngineService.ts +9 -1
- package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +9 -1
- package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +9 -1
- package/Server/Services/RumApplicationLabelRuleEngineService.ts +9 -1
- package/Server/Services/RumApplicationOwnerRuleEngineService.ts +9 -1
- package/Server/Services/RunbookLabelRuleEngineService.ts +9 -1
- package/Server/Services/RunbookOwnerRuleEngineService.ts +9 -1
- package/Server/Services/RunbookRuleEngineService.ts +9 -1
- package/Server/Services/ScheduledMaintenanceLabelRuleEngineService.ts +9 -1
- package/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.ts +9 -1
- package/Server/Services/ScheduledMaintenanceReminderRuleService.ts +9 -1
- package/Server/Services/ServerlessFunctionLabelRuleEngineService.ts +9 -1
- package/Server/Services/ServerlessFunctionOwnerRuleEngineService.ts +9 -1
- package/Server/Services/ServiceLabelRuleEngineService.ts +9 -1
- package/Server/Services/ServiceOwnerRuleEngineService.ts +9 -1
- package/Server/Services/StatusPageLabelRuleEngineService.ts +9 -1
- package/Server/Services/StatusPageMonitorRuleEngineService.ts +7 -0
- package/Server/Services/StatusPageOwnerRuleEngineService.ts +9 -1
- package/Server/Services/TelemetrySourceMapService.ts +266 -23
- package/Server/Services/UserService.ts +27 -0
- package/Server/Services/WorkflowLabelRuleEngineService.ts +9 -1
- package/Server/Services/WorkflowOwnerRuleEngineService.ts +9 -1
- package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +186 -0
- package/Server/Utils/Monitor/CapturedMetricAttributeUtil.ts +245 -0
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +21 -2
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +55 -21
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +32 -0
- package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +15 -2
- package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +18 -1
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +10 -0
- package/Server/Utils/Monitor/SeriesResourceLabels.ts +34 -0
- package/Server/Utils/Rules/RuleEngineRuleRead.ts +48 -0
- package/Server/Utils/Telemetry/ExceptionSanitizer.ts +14 -1
- package/Server/Utils/Telemetry/LogExceptionExtractor.ts +14 -2
- package/Server/Utils/Telemetry/SourceMapResolver.ts +16 -5
- package/Server/Utils/Telemetry/StackTraceParser.ts +399 -0
- package/Tests/App/Dashboard/EventOverlayHook.test.tsx +125 -0
- package/Tests/App/Dashboard/HeaderImageAssets.test.tsx +93 -0
- package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +3 -3
- package/Tests/App/Dashboard/UserElementEmail.test.tsx +12 -4
- package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +1 -1
- package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +14 -0
- package/Tests/Models/DatabaseModels/ModelRegistryInvariants.test.ts +469 -0
- package/Tests/Models/SecurityDomainAccessControl.test.ts +429 -0
- package/Tests/Server/API/GlobalConfigLicense.test.ts +657 -0
- package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +84 -6
- package/Tests/Server/API/TelemetryResolveStackTraceAPI.test.ts +805 -0
- package/Tests/Server/Infrastructure/Postgres/AddOnCallCalendarFeedsMigration.test.ts +32 -7
- package/Tests/Server/Middleware/IdentityRateLimit.test.ts +1144 -0
- package/Tests/Server/Middleware/MultipartFormData.test.ts +618 -3
- package/Tests/Server/Services/MonitorLabelRuleEngineScale.test.ts +520 -0
- package/Tests/Server/Services/NetworkDeviceOidTemplateService.test.ts +332 -0
- package/Tests/Server/Services/NetworkDeviceOidTemplateWriteGuards.test.ts +409 -0
- package/Tests/Server/Services/RuleEngineRuleFetchLimit.test.ts +239 -0
- package/Tests/Server/Services/TelemetrySourceMapService.test.ts +1210 -2
- package/Tests/Server/Services/UserServiceSeatLimit.test.ts +182 -0
- package/Tests/Server/Types/AnalyticsDatabase/SecurityEventModelPermission.test.ts +255 -0
- package/Tests/Server/Types/Database/Permissions/ReadBlockPermission.test.ts +212 -0
- package/Tests/Server/Types/Database/Permissions/SecurityRoleAccess.test.ts +413 -0
- package/Tests/Server/Utils/CodeRepository.test.ts +689 -0
- package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +495 -0
- package/Tests/Server/Utils/ExceptionSanitizer.test.ts +77 -0
- package/Tests/Server/Utils/Monitor/CapturedMetricAttributeUtil.test.ts +284 -0
- package/Tests/Server/Utils/Monitor/MonitorCustomMetricAttributes.test.ts +503 -0
- package/Tests/Server/Utils/Monitor/MonitorTemplatePrototypePollution.test.ts +106 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkLogWritePath.test.ts +33 -4
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +14 -4
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +44 -0
- package/Tests/Server/Utils/OpenAPISpec.test.ts +536 -0
- package/Tests/Server/Utils/Rules/RuleEngineRuleRead.test.ts +115 -0
- package/Tests/Server/Utils/StackTraceParser.test.ts +610 -0
- package/Tests/Server/Utils/Telemetry/LogExceptionExtractor.test.ts +0 -0
- package/Tests/Server/Utils/Telemetry/SourceMapLimits.test.ts +656 -0
- package/Tests/Server/Utils/Telemetry/SourceMapResolver.test.ts +100 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpOidListUtil.test.ts +454 -0
- package/Tests/Types/SecurityRolePermissions.test.ts +193 -0
- package/Tests/UI/Components/Charts/AnnotationLayout.test.ts +773 -0
- package/Tests/UI/Components/Charts/ChartAnnotationRail.test.tsx +789 -0
- package/Tests/UI/Components/Charts/ChartBucketIdentity.test.ts +254 -0
- package/Tests/UI/Components/Charts/TimeAnnotation.test.ts +471 -0
- package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +405 -0
- package/Tests/UI/Components/ErrorMessageRefreshControl.test.tsx +83 -0
- package/Tests/UI/Components/MarkdownConverters.test.ts +686 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableDeleteAndEmptyStates.test.tsx +341 -0
- package/Tests/UI/Components/OrderedStatesList.test.tsx +5 -5
- package/Tests/UI/Components/PendingProjectInvitations.test.tsx +1 -1
- package/Tests/UI/Components/TableSortAndMobileColumns.test.tsx +195 -0
- package/Tests/UI/Components/XAxis.test.ts +270 -5
- package/Tests/UI/Components/XAxisDaylightSaving.test.ts +113 -0
- package/Tests/UI/Styles/ChartFocusRing.test.ts +153 -0
- package/Tests/UI/Styles/ChartFocusRingCoverage.test.tsx +377 -0
- package/Tests/UI/Styles/ThemeStylesheet.ts +162 -0
- package/Tests/Utils/EnterpriseLicenseSeats.test.ts +507 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +951 -1
- package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +238 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +1056 -0
- package/Tests/Utils/NetworkDiscovery/ReverseDnsNameUtil.test.ts +882 -0
- package/Types/Date.ts +39 -0
- package/Types/Monitor/SnmpMonitor/SnmpOidListUtil.ts +333 -0
- package/Types/Permission.ts +96 -0
- package/Types/Rum/SessionReplay.ts +21 -0
- package/Types/Telemetry/SourceMap.ts +8 -0
- package/UI/Components/Charts/ChartLibrary/Annotations/AnnotationHoverCard.tsx +176 -0
- package/UI/Components/Charts/ChartLibrary/Annotations/AnnotationLayout.ts +745 -0
- package/UI/Components/Charts/ChartLibrary/Annotations/ChartAnnotationLayer.tsx +576 -0
- package/UI/Components/Charts/ChartLibrary/Annotations/UseChartAnnotations.tsx +204 -0
- package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +491 -544
- package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +324 -372
- package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +487 -540
- package/UI/Components/Charts/ChartLibrary/Types/FormattedReferenceRegion.ts +7 -3
- package/UI/Components/Charts/ChartLibrary/Types/FormattedTimeReferenceLine.ts +14 -3
- package/UI/Components/Charts/Types/ChartEventKind.ts +13 -0
- package/UI/Components/Charts/Types/ReferenceRegionProps.ts +6 -0
- package/UI/Components/Charts/Types/TimeReferenceLineProps.ts +20 -3
- package/UI/Components/Charts/Utils/TimeAnnotation.ts +69 -35
- package/UI/Components/Charts/Utils/XAxis.ts +125 -18
- package/UI/Components/EditionLabel/EditionLabel.tsx +280 -26
- package/UI/Components/ErrorMessage/ErrorMessage.tsx +21 -10
- package/UI/Components/Feed/FeedItem.tsx +4 -5
- package/UI/Components/Header/HeaderIconDropdownButton.tsx +1 -2
- package/UI/Components/Header/UserProfile/UserProfile.tsx +1 -2
- package/UI/Components/Image/Image.tsx +20 -3
- package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
- package/UI/Components/MemberRoleAssignment/MemberRoleAssignment.tsx +1 -2
- package/UI/Components/ModelTable/BaseModelTable.tsx +150 -24
- package/UI/Components/Table/TableHeader.tsx +64 -48
- package/UI/Components/Table/TableRow.tsx +13 -3
- package/UI/Styles/Theme.css +38 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +271 -0
- package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +6 -0
- package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +141 -10
- package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +55 -3
- package/Utils/NetworkDiscovery/ReverseDnsNameUtil.ts +151 -0
- package/Utils/Rules/RuleEngineLimits.ts +32 -0
- package/build/dist/Models/AnalyticsModels/SecurityEvent.js +48 -16
- package/build/dist/Models/AnalyticsModels/SecurityEvent.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js +10 -5
- package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertSeverity.js +46 -1
- package/build/dist/Models/DatabaseModels/AlertSeverity.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DetectionRule.js +16 -5
- package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +14 -5
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentSeverity.js +46 -1
- package/build/dist/Models/DatabaseModels/IncidentSeverity.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +115 -3
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +88 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js +519 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js +16 -5
- package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js.map +1 -1
- package/build/dist/Server/API/GlobalConfigAPI.js +293 -176
- package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +31 -3
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +83 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790500000000-AddNetworkDeviceOidTemplate.js +26 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790500000000-AddNetworkDeviceOidTemplate.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790600000000-AddAutoImportRuleOidTemplate.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790600000000-AddAutoImportRuleOidTemplate.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/MultipartFormData.js +93 -28
- package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js +8 -1
- package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js +8 -1
- package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertGroupingEngineService.js +8 -1
- package/build/dist/Server/Services/AlertGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/AlertLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertOnCallRuleEngineService.js +8 -1
- package/build/dist/Server/Services/AlertOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/AlertOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js +8 -1
- package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertReminderRuleService.js +8 -1
- package/build/dist/Server/Services/AlertReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +8 -1
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DashboardLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/DashboardLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js +8 -1
- package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js +8 -1
- package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentGroupingEngineService.js +8 -1
- package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/IncidentLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js +8 -1
- package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js +8 -1
- package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentReminderRuleService.js +8 -1
- package/build/dist/Server/Services/IncidentReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/IncidentSlaRuleService.js +8 -1
- package/build/dist/Server/Services/IncidentSlaRuleService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesResourceService.js +5 -1
- package/build/dist/Server/Services/KubernetesResourceService.js.map +1 -1
- package/build/dist/Server/Services/MonitorLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/MonitorLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +30 -21
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +64 -0
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceOidTemplateService.js +180 -0
- package/build/dist/Server/Services/NetworkDeviceOidTemplateService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +154 -1
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/RunbookLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookRuleEngineService.js +8 -1
- package/build/dist/Server/Services/RunbookRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js +8 -1
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js +6 -0
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/TelemetrySourceMapService.js +213 -19
- package/build/dist/Server/Services/TelemetrySourceMapService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +25 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js +8 -1
- package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js +8 -1
- package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +145 -0
- package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/CapturedMetricAttributeUtil.js +201 -0
- package/build/dist/Server/Utils/Monitor/CapturedMetricAttributeUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +19 -2
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +42 -23
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +29 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +11 -2
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +16 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +10 -0
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +33 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
- package/build/dist/Server/Utils/Rules/RuleEngineRuleRead.js +37 -0
- package/build/dist/Server/Utils/Rules/RuleEngineRuleRead.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ExceptionSanitizer.js +12 -1
- package/build/dist/Server/Utils/Telemetry/ExceptionSanitizer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js +14 -2
- package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js +15 -5
- package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/StackTraceParser.js +307 -0
- package/build/dist/Server/Utils/Telemetry/StackTraceParser.js.map +1 -1
- package/build/dist/Types/Date.js +27 -0
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpOidListUtil.js +253 -0
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpOidListUtil.js.map +1 -0
- package/build/dist/Types/Permission.js +86 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplay.js +19 -0
- package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationHoverCard.js +83 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationHoverCard.js.map +1 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationLayout.js +531 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationLayout.js.map +1 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/ChartAnnotationLayer.js +264 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/ChartAnnotationLayer.js.map +1 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/UseChartAnnotations.js +122 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/UseChartAnnotations.js.map +1 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +213 -233
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +139 -152
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +212 -232
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Types/ChartEventKind.js +14 -0
- package/build/dist/UI/Components/Charts/Types/ChartEventKind.js.map +1 -0
- package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js +57 -28
- package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js.map +1 -1
- package/build/dist/UI/Components/Charts/Utils/XAxis.js +103 -17
- package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +198 -23
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js +15 -5
- package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js.map +1 -1
- package/build/dist/UI/Components/Feed/FeedItem.js +4 -5
- package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +1 -2
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
- package/build/dist/UI/Components/Header/UserProfile/UserProfile.js.map +1 -1
- package/build/dist/UI/Components/Image/Image.js +6 -1
- package/build/dist/UI/Components/Image/Image.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/MemberRoleAssignment/MemberRoleAssignment.js +1 -2
- package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +104 -23
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/Table/TableHeader.js +20 -22
- package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +13 -4
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +153 -0
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +127 -7
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +50 -3
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/ReverseDnsNameUtil.js +132 -0
- package/build/dist/Utils/NetworkDiscovery/ReverseDnsNameUtil.js.map +1 -0
- package/build/dist/Utils/Rules/RuleEngineLimits.js +31 -0
- package/build/dist/Utils/Rules/RuleEngineLimits.js.map +1 -0
- package/jest.config.json +1 -0
- package/package.json +2 -2
|
@@ -989,4 +989,48 @@ describe("NetworkInventoryUtil.updateFromWalk — vendor health template auto-ap
|
|
|
989
989
|
|
|
990
990
|
expect(deviceUpdatePayload()).not.toHaveProperty("snmpOids");
|
|
991
991
|
});
|
|
992
|
+
|
|
993
|
+
/*
|
|
994
|
+
* A device linked to an OID Collection Template is exempt outright, even
|
|
995
|
+
* though it satisfies every other condition: opted in, empty local list,
|
|
996
|
+
* vendor fingerprinted.
|
|
997
|
+
*
|
|
998
|
+
* Its effective OID list already comes from the template, resolved fresh on
|
|
999
|
+
* every poll, and its own snmpOids column is by design the small set of
|
|
1000
|
+
* device-specific ADDITIONS — usually empty, which is exactly the condition
|
|
1001
|
+
* this auto-apply keys off. Without the guard, the first poll after linking
|
|
1002
|
+
* writes a vendor copy on top of the template and the device silently
|
|
1003
|
+
* collects the union of two sources, only one of which the operator can see
|
|
1004
|
+
* or edit. Auto-imported devices are all opted in, so this would have been
|
|
1005
|
+
* the common case rather than an edge one.
|
|
1006
|
+
*/
|
|
1007
|
+
test("a device linked to an OID Collection Template is never seeded", async () => {
|
|
1008
|
+
mockServices([], {
|
|
1009
|
+
autoApplyVendorHealthTemplate: true,
|
|
1010
|
+
oidTemplateId: new ObjectID("33333333-3333-4333-8333-333333333333"),
|
|
1011
|
+
});
|
|
1012
|
+
|
|
1013
|
+
await runWalk({
|
|
1014
|
+
systemInfo: {
|
|
1015
|
+
sysObjectId: CISCO_SYS_OBJECT_ID,
|
|
1016
|
+
},
|
|
1017
|
+
});
|
|
1018
|
+
|
|
1019
|
+
expect(deviceUpdatePayload()).not.toHaveProperty("snmpOids");
|
|
1020
|
+
});
|
|
1021
|
+
|
|
1022
|
+
test("selects oidTemplateId, or the guard above can never see the link", async () => {
|
|
1023
|
+
mockServices([], { autoApplyVendorHealthTemplate: true });
|
|
1024
|
+
|
|
1025
|
+
await runWalk({
|
|
1026
|
+
systemInfo: {
|
|
1027
|
+
sysObjectId: CISCO_SYS_OBJECT_ID,
|
|
1028
|
+
},
|
|
1029
|
+
});
|
|
1030
|
+
|
|
1031
|
+
const findArgs: { select?: Record<string, boolean> } = deviceFindSpy.mock
|
|
1032
|
+
.calls[0]![0] as unknown as { select?: Record<string, boolean> };
|
|
1033
|
+
|
|
1034
|
+
expect(findArgs.select?.["oidTemplateId"]).toBe(true);
|
|
1035
|
+
});
|
|
992
1036
|
});
|
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
import { beforeAll, describe, expect, it } from "@jest/globals";
|
|
2
|
+
import OpenAPIUtil from "../../../Server/Utils/OpenAPI";
|
|
3
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* The published OpenAPI specification, as a contract.
|
|
7
|
+
*
|
|
8
|
+
* The spec is what every generated client is built from: the Terraform
|
|
9
|
+
* provider under Scripts/TerraformProvider parses it, and anybody pointing a
|
|
10
|
+
* generator at OneUptime consumes it. So a defect here is not a cosmetic one
|
|
11
|
+
* -- it breaks code generation for everybody downstream.
|
|
12
|
+
*
|
|
13
|
+
* The CI job that produces this file (.github/workflows/openapi-spec-generation.yml)
|
|
14
|
+
* asserts three things: the file exists, `jq` can parse it, and it has
|
|
15
|
+
* `openapi`, `info` and `paths` keys. Everything below is what that check
|
|
16
|
+
* cannot see. A spec with a `$ref` pointing at a schema that was never
|
|
17
|
+
* registered, with two operations sharing an operationId, or with an operation
|
|
18
|
+
* carrying no success response at all is valid JSON with all three keys
|
|
19
|
+
* present -- and useless to a generator.
|
|
20
|
+
*
|
|
21
|
+
* The whole spec is generated once for the suite, because generating it walks
|
|
22
|
+
* every database and analytics model in the product.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
interface Operation {
|
|
26
|
+
operationId?: string;
|
|
27
|
+
tags?: Array<string>;
|
|
28
|
+
responses?: JSONObject;
|
|
29
|
+
security?: unknown;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
* Extracted to a named const so the callsite reads `RE_X.test(...)` rather
|
|
34
|
+
* than `!/.../.test(...)`, which eslint's wrap-regex rule rejects here.
|
|
35
|
+
*/
|
|
36
|
+
const RE_HTTP_STATUS: RegExp = /^[1-5]\d{2}$/;
|
|
37
|
+
|
|
38
|
+
const HTTP_METHODS: Array<string> = [
|
|
39
|
+
"get",
|
|
40
|
+
"put",
|
|
41
|
+
"post",
|
|
42
|
+
"delete",
|
|
43
|
+
"options",
|
|
44
|
+
"head",
|
|
45
|
+
"patch",
|
|
46
|
+
"trace",
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
describe("OpenAPI specification", () => {
|
|
50
|
+
let spec: JSONObject;
|
|
51
|
+
let paths: JSONObject;
|
|
52
|
+
let schemas: JSONObject;
|
|
53
|
+
|
|
54
|
+
/* Every (path, method, operation) triple in the document, flattened. */
|
|
55
|
+
let operations: Array<{
|
|
56
|
+
path: string;
|
|
57
|
+
method: string;
|
|
58
|
+
operation: Operation;
|
|
59
|
+
}>;
|
|
60
|
+
|
|
61
|
+
beforeAll(() => {
|
|
62
|
+
spec = OpenAPIUtil.generateOpenAPISpec();
|
|
63
|
+
paths = (spec["paths"] || {}) as JSONObject;
|
|
64
|
+
schemas = ((spec["components"] as JSONObject | undefined)?.["schemas"] ||
|
|
65
|
+
{}) as JSONObject;
|
|
66
|
+
|
|
67
|
+
operations = [];
|
|
68
|
+
|
|
69
|
+
for (const path of Object.keys(paths)) {
|
|
70
|
+
const pathItem: JSONObject = paths[path] as JSONObject;
|
|
71
|
+
|
|
72
|
+
for (const method of HTTP_METHODS) {
|
|
73
|
+
const operation: Operation | undefined = pathItem[method] as
|
|
74
|
+
| Operation
|
|
75
|
+
| undefined;
|
|
76
|
+
|
|
77
|
+
if (operation) {
|
|
78
|
+
operations.push({ path, method, operation });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/*
|
|
83
|
+
* Generating the spec walks every database and analytics model in the
|
|
84
|
+
* product and took ~55s cold on a developer machine, against the 60s
|
|
85
|
+
* suite-wide testTimeout in jest.config.json. A CI runner is slower and
|
|
86
|
+
* colder than that, so this hook gets its own generous bound rather than
|
|
87
|
+
* sitting one bad minute away from failing the build.
|
|
88
|
+
*/
|
|
89
|
+
}, 300000);
|
|
90
|
+
|
|
91
|
+
describe("document shape", () => {
|
|
92
|
+
it("declares an OpenAPI 3 version", () => {
|
|
93
|
+
expect(String(spec["openapi"])).toMatch(/^3\./);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("carries a title and a version", () => {
|
|
97
|
+
const info: JSONObject = spec["info"] as JSONObject;
|
|
98
|
+
|
|
99
|
+
expect(info["title"]).toBeTruthy();
|
|
100
|
+
expect(info["version"]).toBeTruthy();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("declares at least one server", () => {
|
|
104
|
+
expect(Array.isArray(spec["servers"])).toBe(true);
|
|
105
|
+
expect((spec["servers"] as Array<unknown>).length).toBeGreaterThan(0);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("documents a non-trivial number of paths", () => {
|
|
109
|
+
expect(Object.keys(paths).length).toBeGreaterThan(0);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("has at least one operation on every path it lists", () => {
|
|
113
|
+
const empty: Array<string> = Object.keys(paths).filter((path: string) => {
|
|
114
|
+
const pathItem: JSONObject = paths[path] as JSONObject;
|
|
115
|
+
|
|
116
|
+
return !HTTP_METHODS.some((method: string) => {
|
|
117
|
+
return Boolean(pathItem[method]);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
expect(empty).toEqual([]);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("starts every path with a slash, as the spec requires", () => {
|
|
125
|
+
const malformed: Array<string> = Object.keys(paths).filter(
|
|
126
|
+
(path: string) => {
|
|
127
|
+
return !path.startsWith("/");
|
|
128
|
+
},
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
expect(malformed).toEqual([]);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe("authentication", () => {
|
|
136
|
+
/*
|
|
137
|
+
* Every documented endpoint needs an API key. A spec that omits the scheme
|
|
138
|
+
* generates clients with no way to authenticate at all.
|
|
139
|
+
*/
|
|
140
|
+
it("declares the ApiKey security scheme", () => {
|
|
141
|
+
const schemes: JSONObject = (spec["components"] as JSONObject)[
|
|
142
|
+
"securitySchemes"
|
|
143
|
+
] as JSONObject;
|
|
144
|
+
|
|
145
|
+
expect(schemes["ApiKey"]).toBeDefined();
|
|
146
|
+
|
|
147
|
+
const apiKey: JSONObject = schemes["ApiKey"] as JSONObject;
|
|
148
|
+
|
|
149
|
+
expect(apiKey["type"]).toBe("apiKey");
|
|
150
|
+
expect(apiKey["in"]).toBe("header");
|
|
151
|
+
expect(apiKey["name"]).toBeTruthy();
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("applies that scheme globally", () => {
|
|
155
|
+
const security: Array<JSONObject> = spec["security"] as Array<JSONObject>;
|
|
156
|
+
|
|
157
|
+
expect(Array.isArray(security)).toBe(true);
|
|
158
|
+
expect(security.length).toBeGreaterThan(0);
|
|
159
|
+
expect(security[0]).toHaveProperty("ApiKey");
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
/*
|
|
163
|
+
* A global requirement only covers an operation that does not override it.
|
|
164
|
+
* An operation declaring `security: []` opts out entirely, which on this
|
|
165
|
+
* API would document an authenticated endpoint as anonymous.
|
|
166
|
+
*/
|
|
167
|
+
it("has no operation that opts out of security", () => {
|
|
168
|
+
const anonymous: Array<string> = operations
|
|
169
|
+
.filter((entry: { operation: Operation }) => {
|
|
170
|
+
return (
|
|
171
|
+
Array.isArray(entry.operation.security) &&
|
|
172
|
+
(entry.operation.security as Array<unknown>).length === 0
|
|
173
|
+
);
|
|
174
|
+
})
|
|
175
|
+
.map((entry: { path: string; method: string }) => {
|
|
176
|
+
return `${entry.method.toUpperCase()} ${entry.path}`;
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
expect(anonymous).toEqual([]);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
describe("operations", () => {
|
|
184
|
+
it("gives every operation an operationId", () => {
|
|
185
|
+
const missing: Array<string> = operations
|
|
186
|
+
.filter((entry: { operation: Operation }) => {
|
|
187
|
+
return !entry.operation.operationId;
|
|
188
|
+
})
|
|
189
|
+
.map((entry: { path: string; method: string }) => {
|
|
190
|
+
return `${entry.method.toUpperCase()} ${entry.path}`;
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
expect(missing).toEqual([]);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
/*
|
|
197
|
+
* Generators name the client method after the operationId. Two operations
|
|
198
|
+
* sharing one produce a client where the second silently overwrites the
|
|
199
|
+
* first, and the endpoint it belonged to becomes unreachable.
|
|
200
|
+
*/
|
|
201
|
+
it("gives every operation a unique operationId", () => {
|
|
202
|
+
const seen: Map<string, string> = new Map();
|
|
203
|
+
const duplicates: Array<string> = [];
|
|
204
|
+
|
|
205
|
+
for (const entry of operations) {
|
|
206
|
+
const id: string = entry.operation.operationId as string;
|
|
207
|
+
|
|
208
|
+
if (!id) {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const where: string = `${entry.method.toUpperCase()} ${entry.path}`;
|
|
213
|
+
const previous: string | undefined = seen.get(id);
|
|
214
|
+
|
|
215
|
+
if (previous) {
|
|
216
|
+
duplicates.push(`${id}: ${previous} and ${where}`);
|
|
217
|
+
} else {
|
|
218
|
+
seen.set(id, where);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
expect(duplicates).toEqual([]);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it("tags every operation", () => {
|
|
226
|
+
const untagged: Array<string> = operations
|
|
227
|
+
.filter((entry: { operation: Operation }) => {
|
|
228
|
+
return (
|
|
229
|
+
!Array.isArray(entry.operation.tags) ||
|
|
230
|
+
entry.operation.tags.length === 0
|
|
231
|
+
);
|
|
232
|
+
})
|
|
233
|
+
.map((entry: { path: string; method: string }) => {
|
|
234
|
+
return `${entry.method.toUpperCase()} ${entry.path}`;
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
expect(untagged).toEqual([]);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
/*
|
|
241
|
+
* A tag that is not declared at the top level gets no description in the
|
|
242
|
+
* rendered documentation, and generators that group by tag put the
|
|
243
|
+
* endpoint in a section with no name.
|
|
244
|
+
*/
|
|
245
|
+
it("declares every tag an operation uses", () => {
|
|
246
|
+
const declared: Set<string> = new Set(
|
|
247
|
+
((spec["tags"] || []) as Array<{ name: string }>).map(
|
|
248
|
+
(tag: { name: string }) => {
|
|
249
|
+
return tag.name;
|
|
250
|
+
},
|
|
251
|
+
),
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
const undeclared: Set<string> = new Set<string>();
|
|
255
|
+
|
|
256
|
+
for (const entry of operations) {
|
|
257
|
+
for (const tag of entry.operation.tags || []) {
|
|
258
|
+
if (!declared.has(tag)) {
|
|
259
|
+
undeclared.add(tag);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
expect(Array.from(undeclared)).toEqual([]);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it("gives every declared tag a description", () => {
|
|
268
|
+
const withoutDescription: Array<string> = (
|
|
269
|
+
(spec["tags"] || []) as Array<{ name: string; description?: string }>
|
|
270
|
+
)
|
|
271
|
+
.filter((tag: { description?: string }) => {
|
|
272
|
+
return !tag.description;
|
|
273
|
+
})
|
|
274
|
+
.map((tag: { name: string }) => {
|
|
275
|
+
return tag.name;
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
expect(withoutDescription).toEqual([]);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it("sorts the declared tags", () => {
|
|
282
|
+
const names: Array<string> = (
|
|
283
|
+
(spec["tags"] || []) as Array<{ name: string }>
|
|
284
|
+
).map((tag: { name: string }) => {
|
|
285
|
+
return tag.name;
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
const sorted: Array<string> = [...names].sort(
|
|
289
|
+
(a: string, b: string): number => {
|
|
290
|
+
return a.localeCompare(b);
|
|
291
|
+
},
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
expect(names).toEqual(sorted);
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
describe("responses", () => {
|
|
299
|
+
it("documents responses for every operation", () => {
|
|
300
|
+
const missing: Array<string> = operations
|
|
301
|
+
.filter((entry: { operation: Operation }) => {
|
|
302
|
+
return (
|
|
303
|
+
!entry.operation.responses ||
|
|
304
|
+
Object.keys(entry.operation.responses).length === 0
|
|
305
|
+
);
|
|
306
|
+
})
|
|
307
|
+
.map((entry: { path: string; method: string }) => {
|
|
308
|
+
return `${entry.method.toUpperCase()} ${entry.path}`;
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
expect(missing).toEqual([]);
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
/*
|
|
315
|
+
* A generated client types its return value from the success response. An
|
|
316
|
+
* operation documenting only failures generates a method that can only
|
|
317
|
+
* return an error.
|
|
318
|
+
*/
|
|
319
|
+
it("documents a success response for every operation", () => {
|
|
320
|
+
const missing: Array<string> = operations
|
|
321
|
+
.filter((entry: { operation: Operation }) => {
|
|
322
|
+
return !Object.keys(entry.operation.responses || {}).some(
|
|
323
|
+
(status: string) => {
|
|
324
|
+
return status.startsWith("2") || status === "default";
|
|
325
|
+
},
|
|
326
|
+
);
|
|
327
|
+
})
|
|
328
|
+
.map((entry: { path: string; method: string }) => {
|
|
329
|
+
return `${entry.method.toUpperCase()} ${entry.path}`;
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
expect(missing).toEqual([]);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it("uses only numeric statuses or 'default' as response keys", () => {
|
|
336
|
+
const malformed: Array<string> = [];
|
|
337
|
+
|
|
338
|
+
for (const entry of operations) {
|
|
339
|
+
for (const status of Object.keys(entry.operation.responses || {})) {
|
|
340
|
+
if (status !== "default" && !RE_HTTP_STATUS.test(status)) {
|
|
341
|
+
malformed.push(
|
|
342
|
+
`${entry.method.toUpperCase()} ${entry.path}: ${status}`,
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
expect(malformed).toEqual([]);
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
describe("schema references", () => {
|
|
353
|
+
/*
|
|
354
|
+
* The check the CI job cannot make. A `$ref` naming a schema that was
|
|
355
|
+
* never registered parses as valid JSON and has every required top-level
|
|
356
|
+
* key, and then every generator pointed at the document fails on it.
|
|
357
|
+
*/
|
|
358
|
+
it("resolves every component reference to a registered schema", () => {
|
|
359
|
+
const referenced: Set<string> = new Set<string>();
|
|
360
|
+
|
|
361
|
+
const walk: (node: unknown) => void = (node: unknown): void => {
|
|
362
|
+
if (!node || typeof node !== "object") {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (Array.isArray(node)) {
|
|
367
|
+
for (const item of node) {
|
|
368
|
+
walk(item);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const record: Record<string, unknown> = node as Record<string, unknown>;
|
|
375
|
+
|
|
376
|
+
for (const key of Object.keys(record)) {
|
|
377
|
+
const value: unknown = record[key];
|
|
378
|
+
|
|
379
|
+
if (key === "$ref" && typeof value === "string") {
|
|
380
|
+
referenced.add(value);
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
walk(value);
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
walk(spec);
|
|
389
|
+
|
|
390
|
+
const components: JSONObject =
|
|
391
|
+
(spec["components"] as JSONObject | undefined) || {};
|
|
392
|
+
|
|
393
|
+
const dangling: Array<string> = Array.from(referenced).filter(
|
|
394
|
+
(ref: string) => {
|
|
395
|
+
const match: RegExpMatchArray | null = ref.match(
|
|
396
|
+
/^#\/components\/([^/]+)\/(.+)$/,
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
if (!match) {
|
|
400
|
+
/* Anything that is not a local component ref is out of scope. */
|
|
401
|
+
return false;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const section: JSONObject | undefined = components[
|
|
405
|
+
match[1] as string
|
|
406
|
+
] as JSONObject | undefined;
|
|
407
|
+
|
|
408
|
+
return !section || !((match[2] as string) in section);
|
|
409
|
+
},
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
expect(dangling).toEqual([]);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it("registers at least one component schema", () => {
|
|
416
|
+
expect(Object.keys(schemas).length).toBeGreaterThan(0);
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
it("gives every registered schema a type or a composition keyword", () => {
|
|
420
|
+
const shapeless: Array<string> = Object.keys(schemas).filter(
|
|
421
|
+
(name: string) => {
|
|
422
|
+
const schema: JSONObject = schemas[name] as JSONObject;
|
|
423
|
+
|
|
424
|
+
return (
|
|
425
|
+
schema["type"] === undefined &&
|
|
426
|
+
schema["allOf"] === undefined &&
|
|
427
|
+
schema["oneOf"] === undefined &&
|
|
428
|
+
schema["anyOf"] === undefined &&
|
|
429
|
+
schema["$ref"] === undefined &&
|
|
430
|
+
schema["properties"] === undefined
|
|
431
|
+
);
|
|
432
|
+
},
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
expect(shapeless).toEqual([]);
|
|
436
|
+
});
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
describe("path parameters", () => {
|
|
440
|
+
/*
|
|
441
|
+
* A `{placeholder}` in a path with no matching parameter definition is a
|
|
442
|
+
* generated client method that cannot fill in the URL it is meant to call.
|
|
443
|
+
*/
|
|
444
|
+
it("declares every placeholder its path template uses", () => {
|
|
445
|
+
const missing: Array<string> = [];
|
|
446
|
+
|
|
447
|
+
for (const path of Object.keys(paths)) {
|
|
448
|
+
const placeholders: Array<string> = Array.from(
|
|
449
|
+
path.matchAll(/\{([^}]+)\}/g),
|
|
450
|
+
).map((match: RegExpMatchArray) => {
|
|
451
|
+
return match[1] as string;
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
if (placeholders.length === 0) {
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const pathItem: JSONObject = paths[path] as JSONObject;
|
|
459
|
+
|
|
460
|
+
const pathLevel: Array<JSONObject> = (pathItem["parameters"] ||
|
|
461
|
+
[]) as Array<JSONObject>;
|
|
462
|
+
|
|
463
|
+
for (const method of HTTP_METHODS) {
|
|
464
|
+
const operation: JSONObject | undefined = pathItem[method] as
|
|
465
|
+
| JSONObject
|
|
466
|
+
| undefined;
|
|
467
|
+
|
|
468
|
+
if (!operation) {
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
const declared: Set<string> = new Set<string>();
|
|
473
|
+
|
|
474
|
+
for (const parameter of [
|
|
475
|
+
...pathLevel,
|
|
476
|
+
...((operation["parameters"] || []) as Array<JSONObject>),
|
|
477
|
+
]) {
|
|
478
|
+
if (parameter["in"] === "path") {
|
|
479
|
+
declared.add(String(parameter["name"]));
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
for (const placeholder of placeholders) {
|
|
484
|
+
if (!declared.has(placeholder)) {
|
|
485
|
+
missing.push(`${method.toUpperCase()} ${path}: {${placeholder}}`);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
expect(missing).toEqual([]);
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
it("marks every path parameter required, as the spec demands", () => {
|
|
495
|
+
const optional: Array<string> = [];
|
|
496
|
+
|
|
497
|
+
for (const path of Object.keys(paths)) {
|
|
498
|
+
const pathItem: JSONObject = paths[path] as JSONObject;
|
|
499
|
+
|
|
500
|
+
for (const method of [...HTTP_METHODS, "parameters"]) {
|
|
501
|
+
const holder: JSONObject | undefined = pathItem[method] as
|
|
502
|
+
| JSONObject
|
|
503
|
+
| undefined;
|
|
504
|
+
|
|
505
|
+
if (!holder) {
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const parameters: Array<JSONObject> =
|
|
510
|
+
method === "parameters"
|
|
511
|
+
? (pathItem["parameters"] as Array<JSONObject>)
|
|
512
|
+
: ((holder["parameters"] || []) as Array<JSONObject>);
|
|
513
|
+
|
|
514
|
+
for (const parameter of parameters || []) {
|
|
515
|
+
if (parameter["in"] === "path" && parameter["required"] !== true) {
|
|
516
|
+
optional.push(`${path}: ${String(parameter["name"])}`);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
expect(optional).toEqual([]);
|
|
523
|
+
});
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
describe("caching", () => {
|
|
527
|
+
/*
|
|
528
|
+
* The spec is expensive to build -- it walks every model in the product --
|
|
529
|
+
* so it is cached. The cached value must be the same document, not a
|
|
530
|
+
* rebuild that could drift from the one already handed out.
|
|
531
|
+
*/
|
|
532
|
+
it("returns the identical document on a second call", () => {
|
|
533
|
+
expect(OpenAPIUtil.generateOpenAPISpec()).toBe(spec);
|
|
534
|
+
});
|
|
535
|
+
});
|
|
536
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import logIfRuleReadWasTruncated from "../../../../Server/Utils/Rules/RuleEngineRuleRead";
|
|
2
|
+
import { MAX_RULES_EVALUATED_PER_PROJECT } from "../../../../Utils/Rules/RuleEngineLimits";
|
|
3
|
+
import logger from "../../../../Server/Utils/Logger";
|
|
4
|
+
import ObjectID from "../../../../Types/ObjectID";
|
|
5
|
+
import { describe, expect, it, afterEach } from "@jest/globals";
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
* A rule engine reads its project's rules as `limit: <cap>, skip: 0` and
|
|
9
|
+
* evaluates whatever comes back. There is no second page, so a project past
|
|
10
|
+
* the cap has the remainder evaluated by nobody - and the read cannot tell
|
|
11
|
+
* "that is all of them" from "that is all I was allowed to ask for".
|
|
12
|
+
*
|
|
13
|
+
* That gap IS OneUptime/oneuptime#3506: the cap was 100, a project had 1,243
|
|
14
|
+
* rules, and the 1,143 that never ran produced no log and no counter. Raising
|
|
15
|
+
* the cap to 10,000 moves the threshold; it does not change the shape of the
|
|
16
|
+
* failure. This guard is what changes the shape - crossing the ceiling is now
|
|
17
|
+
* an operator-visible error rather than silence.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const PROJECT_ID: ObjectID = new ObjectID(
|
|
21
|
+
"22222222-2222-4222-8222-222222222222",
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
describe("logIfRuleReadWasTruncated", () => {
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
jest.restoreAllMocks();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("says nothing for a project comfortably under the ceiling", () => {
|
|
30
|
+
const errorSpy: jest.SpyInstance = jest
|
|
31
|
+
.spyOn(logger, "error")
|
|
32
|
+
.mockImplementation(() => {});
|
|
33
|
+
|
|
34
|
+
// The reporter's own rule count. It must not produce noise.
|
|
35
|
+
const wasTruncated: boolean = logIfRuleReadWasTruncated({
|
|
36
|
+
ruleKind: "MonitorLabelRule",
|
|
37
|
+
projectId: PROJECT_ID,
|
|
38
|
+
rulesRead: 1243,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
expect(wasTruncated).toBe(false);
|
|
42
|
+
expect(errorSpy).not.toHaveBeenCalled();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("says nothing at exactly one rule below the ceiling", () => {
|
|
46
|
+
const errorSpy: jest.SpyInstance = jest
|
|
47
|
+
.spyOn(logger, "error")
|
|
48
|
+
.mockImplementation(() => {});
|
|
49
|
+
|
|
50
|
+
const wasTruncated: boolean = logIfRuleReadWasTruncated({
|
|
51
|
+
ruleKind: "MonitorLabelRule",
|
|
52
|
+
projectId: PROJECT_ID,
|
|
53
|
+
rulesRead: MAX_RULES_EVALUATED_PER_PROJECT - 1,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
expect(wasTruncated).toBe(false);
|
|
57
|
+
expect(errorSpy).not.toHaveBeenCalled();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
/*
|
|
61
|
+
* A read that comes back exactly full is indistinguishable from a truncated
|
|
62
|
+
* one - the row that would have been 10,001st was never fetched to be
|
|
63
|
+
* counted. It has to be reported, even though a project sitting at exactly
|
|
64
|
+
* the cap has in fact lost nothing.
|
|
65
|
+
*/
|
|
66
|
+
it("reports a read that comes back exactly at the ceiling", () => {
|
|
67
|
+
const errorSpy: jest.SpyInstance = jest
|
|
68
|
+
.spyOn(logger, "error")
|
|
69
|
+
.mockImplementation(() => {});
|
|
70
|
+
|
|
71
|
+
const wasTruncated: boolean = logIfRuleReadWasTruncated({
|
|
72
|
+
ruleKind: "MonitorLabelRule",
|
|
73
|
+
projectId: PROJECT_ID,
|
|
74
|
+
rulesRead: MAX_RULES_EVALUATED_PER_PROJECT,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
expect(wasTruncated).toBe(true);
|
|
78
|
+
expect(errorSpy).toHaveBeenCalledTimes(1);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("names the rule kind and the project so the config can be found", () => {
|
|
82
|
+
const errorSpy: jest.SpyInstance = jest
|
|
83
|
+
.spyOn(logger, "error")
|
|
84
|
+
.mockImplementation(() => {});
|
|
85
|
+
|
|
86
|
+
logIfRuleReadWasTruncated({
|
|
87
|
+
ruleKind: "MonitorLabelRule",
|
|
88
|
+
projectId: PROJECT_ID,
|
|
89
|
+
rulesRead: 100000,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const message: string = errorSpy.mock.calls[0]![0] as string;
|
|
93
|
+
const attributes: { projectId?: string } = errorSpy.mock.calls[0]![1] as {
|
|
94
|
+
projectId?: string;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
expect(message).toContain("MonitorLabelRule");
|
|
98
|
+
expect(message).toContain(String(MAX_RULES_EVALUATED_PER_PROJECT));
|
|
99
|
+
expect(message).toContain("NOT being evaluated");
|
|
100
|
+
expect(attributes.projectId).toBe(PROJECT_ID.toString());
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// The guard reports; it never throws. A partial evaluation beats none.
|
|
104
|
+
it("does not throw when the project has no id", () => {
|
|
105
|
+
jest.spyOn(logger, "error").mockImplementation(() => {});
|
|
106
|
+
|
|
107
|
+
expect(() => {
|
|
108
|
+
return logIfRuleReadWasTruncated({
|
|
109
|
+
ruleKind: "MonitorLabelRule",
|
|
110
|
+
projectId: undefined,
|
|
111
|
+
rulesRead: 100000,
|
|
112
|
+
});
|
|
113
|
+
}).not.toThrow();
|
|
114
|
+
});
|
|
115
|
+
});
|