@oneuptime/common 13.0.8 → 14.0.1
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/Index.ts +4 -0
- package/Models/DatabaseModels/Monitor.ts +3 -2
- package/Models/DatabaseModels/MonitorTemplate.ts +2 -1
- package/Models/DatabaseModels/ServiceLevelObjectiveFeed.ts +2 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.ts +522 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.ts +38 -4
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.ts +603 -0
- package/Scripts/generate-service-worker.js +65 -4
- package/Server/API/BaseAPI.ts +26 -5
- package/Server/API/GlobalConfigAPI.ts +228 -462
- package/Server/API/ProjectOIDC.ts +25 -16
- package/Server/API/ProjectSSO.ts +24 -16
- package/Server/API/StatusPageAPI.ts +100 -42
- package/Server/API/TeamMemberAPI.ts +10 -1
- 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/1794100000000-AddSloLabelAndOwnerRules.ts +248 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.ts +19 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Middleware/UserAuthorization.ts +38 -16
- package/Server/Services/AuditLogService.ts +84 -1079
- package/Server/Services/DatabaseService.ts +10 -0
- package/Server/Services/EnterpriseLicenseService.ts +38 -0
- package/Server/Services/GlobalConfigService.ts +80 -1
- package/Server/Services/Index.ts +4 -0
- package/Server/Services/MonitorProbeService.ts +116 -20
- package/Server/Services/MonitorService.ts +59 -6
- package/Server/Services/MonitorStatusTimelineService.ts +284 -0
- package/Server/Services/MonitorTemplateService.ts +26 -0
- package/Server/Services/ProjectService.ts +284 -0
- package/Server/Services/RumSessionPinService.ts +25 -6
- package/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.ts +385 -0
- package/Server/Services/ServiceLevelObjectiveLabelRuleService.ts +51 -0
- package/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.ts +92 -16
- package/Server/Services/ServiceLevelObjectiveMonitorRuleService.ts +36 -1
- package/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.ts +521 -0
- package/Server/Services/ServiceLevelObjectiveOwnerRuleService.ts +51 -0
- package/Server/Services/ServiceLevelObjectiveService.ts +28 -0
- package/Server/Services/StatusPagePrivateUserService.ts +7 -3
- package/Server/Services/StatusPageService.ts +78 -1
- package/Server/Services/TeamMemberService.ts +11 -0
- package/Server/Services/TeamService.ts +10 -0
- package/Server/Services/UserService.ts +10 -17
- package/Server/Types/Database/Permissions/CreatePermission.ts +15 -0
- package/Server/Types/Database/Permissions/EditionPermission.ts +208 -18
- package/Server/Types/Database/Permissions/TablePermission.ts +10 -3
- package/Server/Types/Database/Permissions/UpdatePermission.ts +29 -0
- package/Server/Types/Markdown.ts +41 -0
- package/Server/Types/Workflow/Components/Telegram/SendMessageToChat.ts +27 -1
- package/Server/Utils/AI/Toolbox/SloTools.ts +1 -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/Monitor/AffectedResourceList.ts +148 -0
- package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +1 -1
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +10 -1
- package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +1 -1
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +720 -465
- package/Server/Utils/Monitor/MonitoringIntervalValidator.ts +116 -0
- package/Server/Utils/Monitor/RootCauseList.ts +139 -0
- package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +28 -0
- package/Server/Utils/Slo/SloRulePatternValidator.ts +42 -0
- 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/AuditLogsAndComplianceShells.test.tsx +572 -0
- package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +547 -0
- package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +667 -0
- package/Tests/App/Dashboard/FeedFilterSortIntegration.test.tsx +1632 -0
- package/Tests/App/Dashboard/FeedOptionsLocales.test.ts +250 -0
- package/Tests/App/Dashboard/FeedOrdering.test.ts +279 -9
- package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +319 -0
- package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +60 -1
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +594 -3
- package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +185 -0
- package/Tests/App/Dashboard/ProductOrientation.test.tsx +646 -0
- package/Tests/App/Dashboard/ResourceFeed.test.tsx +612 -2
- package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +30 -0
- package/Tests/App/Dashboard/ResourceFeedPagesFilterSort.test.tsx +1202 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceFeedRefresh.test.tsx +52 -1
- package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +45 -9
- package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +399 -0
- package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +214 -0
- package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +1 -83
- package/Tests/App/Dashboard/SecurityEventsNavTabs.test.tsx +248 -0
- package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +1203 -0
- package/Tests/App/Dashboard/SloFeed.test.tsx +106 -1
- package/Tests/App/Dashboard/SloMonitorRuleCriteria.test.tsx +566 -0
- package/Tests/App/Dashboard/SloNavigationWiring.test.tsx +6 -4
- package/Tests/App/Dashboard/SloNoticeBanner.test.tsx +186 -0
- package/Tests/App/Dashboard/SloOverviewKpiStrip.test.tsx +388 -44
- package/Tests/App/Dashboard/SloOverviewLayout.test.tsx +613 -0
- package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +11 -91
- 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/DatabaseModels/ResourceFeedModels.test.ts +0 -8
- package/Tests/Models/DatabaseModels/SloLabelAndOwnerRuleModels.test.ts +404 -0
- package/Tests/Models/DatabaseModels/SloOverhaulModels.test.ts +17 -1
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
- package/Tests/Scripts/GenerateServiceWorker.test.ts +931 -0
- package/Tests/Server/API/BaseAPICreateItemDoesNotMutateModel.test.ts +130 -0
- package/Tests/Server/API/GlobalConfigLicense.test.ts +742 -497
- package/Tests/Server/API/OnCallReadinessAPI.test.ts +35 -909
- package/Tests/Server/API/SsoProviderListingsEdition.test.ts +432 -0
- package/Tests/Server/API/TeamMemberLeaveScimLockEdition.test.ts +252 -0
- 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/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
- package/Tests/Server/Infrastructure/Postgres/AddSloLabelAndOwnerRulesMigration.test.ts +407 -0
- package/Tests/Server/Infrastructure/Postgres/AddSloMonitorRuleMonitorTypeMigration.test.ts +171 -0
- package/Tests/Server/Infrastructure/Postgres/SloProductOverhaulMigration.test.ts +88 -4
- package/Tests/Server/Middleware/UserAuthorization.test.ts +37 -2
- package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +516 -0
- package/Tests/Server/Services/AuditLogService.test.ts +460 -990
- package/Tests/Server/Services/CreateAndReadResponsesKeepIds.test.ts +263 -0
- package/Tests/Server/Services/DatabaseServiceRuleCriteriaValidation.test.ts +104 -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/MonitorProbeServiceIntervalScheduling.test.ts +333 -0
- package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +303 -0
- package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +701 -0
- package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +31 -35
- package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +48 -1
- package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -0
- package/Tests/Server/Services/ScimPushGroupsTeamLocksEdition.test.ts +431 -0
- package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleEngines.test.ts +1170 -0
- package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleServices.test.ts +172 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.test.ts +323 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleService.test.ts +115 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleTriggers.test.ts +21 -2
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorTypePostgres.test.ts +480 -0
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +162 -0
- package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +419 -0
- package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +769 -0
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +45 -6
- package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +94 -0
- package/Tests/Server/Services/UserAuthenticationService.test.ts +35 -0
- package/Tests/Server/Services/UserServiceSeatLimit.test.ts +94 -56
- package/Tests/Server/Types/Database/FeedEventTypeFilterQuery.test.ts +745 -0
- package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +1823 -0
- package/Tests/Server/Types/Markdown.test.ts +183 -1
- package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +49 -0
- package/Tests/Server/Types/Workflow/Components/TelegramSendMessageToChat.test.ts +331 -0
- package/Tests/Server/Utils/AI/SloTools.test.ts +10 -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/Monitor/AffectedResourceList.test.ts +518 -0
- package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +24 -4
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +1 -1
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +1339 -96
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorBreachingSamples.test.ts +1101 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorMetricUnits.test.ts +106 -80
- package/Tests/Server/Utils/Monitor/MonitoringIntervalValidator.test.ts +188 -0
- package/Tests/Server/Utils/Monitor/RootCauseList.test.ts +252 -0
- package/Tests/Server/Utils/Rules/RuleRun/RuleRunPermission.test.ts +154 -0
- package/Tests/Server/Utils/SSRFProtection.test.ts +111 -0
- package/Tests/Server/Utils/Slo/SloRulePatternValidator.test.ts +67 -0
- package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +213 -0
- package/Tests/Server/Utils/Workspace/Slack/SlackMarkdownSectionSplit.test.ts +1209 -0
- package/Tests/Types/API/HostnameFromAuthority.test.ts +20 -10
- package/Tests/Types/API/HostnameIPv6.test.ts +149 -0
- package/Tests/Types/API/Route.test.ts +56 -0
- package/Tests/Types/API/URLSchemeLikePath.test.ts +304 -0
- package/Tests/Types/Database/CanonicalModelInstance.test.ts +190 -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 +84 -178
- package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +1586 -0
- package/Tests/UI/Components/EditionLabelLicenseWritesGuard.test.tsx +157 -0
- package/Tests/UI/Components/FeedOptions.test.ts +1404 -0
- package/Tests/UI/Components/FeedOptionsButton.test.tsx +2603 -0
- package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +49 -2
- package/Tests/UI/Components/Icon.test.tsx +26 -0
- package/Tests/UI/Components/MarkdownConverters.test.ts +684 -0
- package/Tests/UI/Components/ModelListEmptyState.test.tsx +289 -0
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
- package/Tests/UI/Components/TelemetryViewer/TelemetryViewerEmptyContent.test.tsx +131 -0
- package/Tests/UI/Components/useFeedItemsViewKey.test.tsx +1017 -0
- package/Tests/UI/Components/useFeedOptions.test.tsx +1107 -0
- package/Tests/UI/EsbuildEnterpriseAlias.test.ts +1127 -0
- package/Tests/Utils/HostAddressUtil.test.ts +138 -0
- package/Tests/Utils/LabelRuleImportExport.test.ts +102 -0
- package/Tests/Utils/Monitor/MonitorDestinationUtil.test.ts +313 -0
- package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +304 -0
- package/Tests/Utils/Slo/SloDuration.test.ts +115 -24
- package/Tests/Utils/Slo/SloHealth.test.ts +93 -10
- package/Tests/Utils/Slo/SloMonitorRuleCriteria.test.ts +109 -0
- package/Tests/Utils/Slo/SloOverviewText.test.ts +64 -0
- package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +248 -0
- package/Types/API/Hostname.ts +63 -16
- package/Types/API/Route.ts +19 -2
- package/Types/API/URL.ts +26 -2
- 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/MetricMonitor/MetricCriteriaContext.ts +6 -5
- package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +9 -0
- package/Types/Monitor/MonitorStep.ts +6 -1
- package/Types/Monitor/ProxmoxAlertTemplates.ts +1 -1
- package/Types/Permission.ts +90 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +11 -0
- package/Types/Rules/RuleRun.ts +4 -0
- package/Types/StatusPage/UptimeDailyAggregate.ts +110 -0
- package/UI/Components/EditionLabel/EditionLabel.tsx +796 -1195
- package/UI/Components/EditionLabel/LicenseManager.ts +119 -0
- package/UI/Components/Feed/FeedOptions.ts +427 -0
- package/UI/Components/Feed/FeedOptionsButton.tsx +692 -0
- package/UI/Components/Feed/useFeedItems.ts +28 -9
- package/UI/Components/Feed/useFeedOptions.ts +225 -0
- package/UI/Components/Graphs/DayUptimeGraph.tsx +123 -15
- package/UI/Components/Icon/Icon.tsx +1 -1
- package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
- package/UI/Components/ModelList/ModelList.tsx +11 -1
- package/UI/Components/MonitorGraphs/Uptime.tsx +69 -0
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +28 -12
- package/UI/esbuild-enterprise.js +263 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +7 -2
- package/Utils/HostAddressUtil.ts +94 -0
- package/Utils/LabelRuleImportExport.ts +27 -9
- package/Utils/Monitor/MetricValueFormatter.ts +2 -2
- package/Utils/Monitor/MonitorDestinationUtil.ts +157 -0
- package/Utils/Monitor/MonitoringIntervalUtil.ts +436 -0
- package/Utils/Rules/MonitorTypeRuleCriteria.ts +31 -0
- package/Utils/Slo/SloDuration.ts +22 -6
- package/Utils/Slo/SloHealth.ts +8 -7
- package/Utils/Slo/SloMonitorRuleCriteria.ts +33 -1
- package/Utils/Slo/SloOverviewText.ts +33 -0
- package/Utils/Slo/SloProjection.ts +4 -3
- 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/Index.js +4 -0
- package/build/dist/Models/DatabaseModels/Index.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/ServiceLevelObjectiveFeed.js +2 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js +530 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js +39 -4
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js +612 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js.map +1 -0
- package/build/dist/Server/API/BaseAPI.js +26 -5
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/GlobalConfigAPI.js +148 -344
- package/build/dist/Server/API/GlobalConfigAPI.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/StatusPageAPI.js +93 -43
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/TeamMemberAPI.js +8 -1
- package/build/dist/Server/API/TeamMemberAPI.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/1794100000000-AddSloLabelAndOwnerRules.js +93 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +30 -11
- package/build/dist/Server/Middleware/UserAuthorization.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 +7 -0
- package/build/dist/Server/Services/DatabaseService.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/Index.js +4 -0
- package/build/dist/Server/Services/Index.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 +48 -6
- 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/ProjectService.js +214 -0
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/RumSessionPinService.js +24 -6
- package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js +295 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js +56 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js +59 -14
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js +22 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js +400 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js +56 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js +21 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.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/TeamService.js +9 -0
- package/build/dist/Server/Services/TeamService.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/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/TablePermission.js +10 -3
- 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/Types/Workflow/Components/Telegram/SendMessageToChat.js +20 -1
- package/build/dist/Server/Types/Workflow/Components/Telegram/SendMessageToChat.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.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/Monitor/AffectedResourceList.js +67 -0
- package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +1 -1
- 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/Criteria/MetricMonitorCriteria.js +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +585 -367
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.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/Monitor/RootCauseList.js +101 -0
- package/build/dist/Server/Utils/Monitor/RootCauseList.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +28 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js +28 -0
- package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js.map +1 -0
- 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/API/Route.js +18 -2
- package/build/dist/Types/API/Route.js.map +1 -1
- package/build/dist/Types/API/URL.js +23 -2
- package/build/dist/Types/API/URL.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/Permission.js +84 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +11 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rules/RuleRun.js +4 -0
- package/build/dist/Types/Rules/RuleRun.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/EditionLabel/EditionLabel.js +414 -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/Feed/FeedOptions.js +235 -0
- package/build/dist/UI/Components/Feed/FeedOptions.js.map +1 -0
- package/build/dist/UI/Components/Feed/FeedOptionsButton.js +346 -0
- package/build/dist/UI/Components/Feed/FeedOptionsButton.js.map +1 -0
- package/build/dist/UI/Components/Feed/useFeedItems.js +17 -7
- package/build/dist/UI/Components/Feed/useFeedItems.js.map +1 -1
- package/build/dist/UI/Components/Feed/useFeedOptions.js +130 -0
- package/build/dist/UI/Components/Feed/useFeedOptions.js.map +1 -0
- 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/Icon/Icon.js +1 -1
- package/build/dist/UI/Components/Icon/Icon.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/ModelList/ModelList.js +4 -1
- package/build/dist/UI/Components/ModelList/ModelList.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/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/LabelRuleImportExport.js +22 -6
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
- package/build/dist/Utils/Monitor/MetricValueFormatter.js +2 -2
- 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/Rules/MonitorTypeRuleCriteria.js +18 -0
- package/build/dist/Utils/Rules/MonitorTypeRuleCriteria.js.map +1 -0
- package/build/dist/Utils/Slo/SloDuration.js +13 -5
- package/build/dist/Utils/Slo/SloDuration.js.map +1 -1
- package/build/dist/Utils/Slo/SloHealth.js +8 -7
- package/build/dist/Utils/Slo/SloHealth.js.map +1 -1
- package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js +16 -1
- package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js.map +1 -1
- package/build/dist/Utils/Slo/SloOverviewText.js +16 -0
- package/build/dist/Utils/Slo/SloOverviewText.js.map +1 -1
- package/build/dist/Utils/Slo/SloProjection.js.map +1 -1
- 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/SecurityEventsExplorer.test.tsx +0 -761
- package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +0 -247
- package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +0 -382
- package/Tests/App/Dashboard/SecurityEventsVolumeChart.test.tsx +0 -321
- 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,515 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import ts from "typescript";
|
|
3
|
+
import {
|
|
4
|
+
AllowlistEntry,
|
|
5
|
+
Finding,
|
|
6
|
+
allowlistedFiles,
|
|
7
|
+
fromRelativePath,
|
|
8
|
+
toRelativePath,
|
|
9
|
+
} from "./RefreshAwareApiScan";
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
* The detector behind the "Dashboard requests name the project they are for"
|
|
13
|
+
* guard.
|
|
14
|
+
*
|
|
15
|
+
* Model CRUD goes through ModelAPI, which calls getCommonHeaders() on every
|
|
16
|
+
* request and so always sends a `tenantid` header. Custom (non-CRUD) routes
|
|
17
|
+
* have no ModelAPI to go through, so pages reach them with a raw
|
|
18
|
+
* `API.post` / `API.get` from Common/UI/Utils/API/API - and BaseAPI.getHeaders()
|
|
19
|
+
* adds only the default and permission-hash headers. It does NOT add
|
|
20
|
+
* `tenantid`. ModelAPI.getCommonHeaders() is the only producer of that header
|
|
21
|
+
* in the entire codebase.
|
|
22
|
+
*
|
|
23
|
+
* Server side, ProjectMiddleware.getProjectId is the only thing that resolves
|
|
24
|
+
* the project, and it looks in exactly these places:
|
|
25
|
+
*
|
|
26
|
+
* req.params.projectId, req.params.tenantid, req.query.tenantid,
|
|
27
|
+
* req.headers.tenantid, req.headers.projectid, req.body.projectId
|
|
28
|
+
*
|
|
29
|
+
* So a raw call from the Dashboard has to make the project explicit in one of
|
|
30
|
+
* three ways: the tenant header, a `projectId` in the body, or a project id in
|
|
31
|
+
* the URL. A call that does none of them arrives with no project at all.
|
|
32
|
+
*
|
|
33
|
+
* What that costs is not theoretical. OneUptime issue #3920 ("Can't test SMTP
|
|
34
|
+
* connection") was `/smtp-config/test` posted without the header: the route
|
|
35
|
+
* had been hardened to require an authenticated member of the config's own
|
|
36
|
+
* project, and with no `tenantid` there was no project to check, so every
|
|
37
|
+
* click on "Send Test Email" came back "Project ID is required". Before that
|
|
38
|
+
* hardening the same omission showed up as "You do not have permissions to
|
|
39
|
+
* read <model>", naming permissions the caller already held. Neither failure
|
|
40
|
+
* is visible in a type check, in a compile, or in any test that does not send
|
|
41
|
+
* the request - which is what this scan is for.
|
|
42
|
+
*
|
|
43
|
+
* The three existing guards (ProjectScopedApiTenantHeader,
|
|
44
|
+
* ProjectScopedCustomRouteTenantHeader, MonitorTemplateSyncTenantHeader) each
|
|
45
|
+
* pin a hardcoded list of files and routes, which is why none of them saw
|
|
46
|
+
* `/smtp-config/test`: it was not on any list. This one sweeps instead, so a
|
|
47
|
+
* new page is covered the day it lands and the only way out is an allowlist
|
|
48
|
+
* entry with a reason.
|
|
49
|
+
*
|
|
50
|
+
* It lives under Common/Tests so both the core suite and ee/ reach it through
|
|
51
|
+
* the "Common/..." specifier, the same way RefreshAwareApiScan does.
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/* The HTTP verbs the browser client exposes as `API.<verb>({ ... })`. */
|
|
55
|
+
const REQUEST_VERBS: ReadonlySet<string> = new Set<string>([
|
|
56
|
+
"get",
|
|
57
|
+
"post",
|
|
58
|
+
"put",
|
|
59
|
+
"delete",
|
|
60
|
+
"patch",
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
/*
|
|
64
|
+
* Module specifiers whose default export is a raw, non-model client: it sends
|
|
65
|
+
* the session cookie but never a tenant header. Matched as a suffix so both
|
|
66
|
+
* "Common/UI/Utils/API/API" and a relative "../../Utils/API/API" resolve.
|
|
67
|
+
*
|
|
68
|
+
* ModelAPI and AnalyticsModelAPI are deliberately absent: those attach the
|
|
69
|
+
* header themselves, so demanding an explicit one from their call sites would
|
|
70
|
+
* be wrong.
|
|
71
|
+
*/
|
|
72
|
+
const RAW_CLIENT_SPECIFIERS: ReadonlyArray<string> = [
|
|
73
|
+
"UI/Utils/API/API",
|
|
74
|
+
"Utils/API/API",
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
/*
|
|
78
|
+
* Every file that opens a request spells one of these, so a module with
|
|
79
|
+
* neither needs no parse.
|
|
80
|
+
*/
|
|
81
|
+
const REQUEST_HINT: RegExp = /API\s*\.\s*(?:get|post|put|delete|patch)\b/;
|
|
82
|
+
|
|
83
|
+
/*
|
|
84
|
+
* A `headers` expression that reaches getCommonHeaders(). Both ModelAPI and
|
|
85
|
+
* AnalyticsModelAPI expose it and both produce the tenant header, so the
|
|
86
|
+
* method is what is matched rather than the class.
|
|
87
|
+
*/
|
|
88
|
+
const TENANT_HEADER: RegExp = /\bgetCommonHeaders\s*\(/;
|
|
89
|
+
|
|
90
|
+
/* `projectId: value`, or the shorthand `projectId`, in an object literal. */
|
|
91
|
+
const PROJECT_ID_PROPERTY: RegExp = /\bprojectId\b\s*(?::|,|\}|$)/m;
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
* A project id named in the url itself - a `:projectId` path segment, or a
|
|
95
|
+
* lookup of the current one.
|
|
96
|
+
*/
|
|
97
|
+
const PROJECT_ID_IN_URL: RegExp = /\bprojectId\b|getCurrentProjectId\s*\(/;
|
|
98
|
+
|
|
99
|
+
export interface RawApiCall {
|
|
100
|
+
// 1-based, for a clickable file:line in the failure message.
|
|
101
|
+
line: number;
|
|
102
|
+
verb: string;
|
|
103
|
+
// Source text of the call's `url:`, `data:` and `headers:` properties.
|
|
104
|
+
url: string;
|
|
105
|
+
data: string;
|
|
106
|
+
headers: string;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/*
|
|
110
|
+
* Identifiers this file declares at any level, mapped to the source text of
|
|
111
|
+
* their declaration - but only when the name is declared exactly once.
|
|
112
|
+
*
|
|
113
|
+
* This is what lets the scan see through the one indirection these pages
|
|
114
|
+
* actually use: LogsViewer.tsx writes `headers: getHeaders()` and declares
|
|
115
|
+
* `function getHeaders() { return ModelAPI.getCommonHeaders(); }` a few lines
|
|
116
|
+
* above. Resolving that is the difference between a true reading and a false
|
|
117
|
+
* accusation.
|
|
118
|
+
*
|
|
119
|
+
* Ambiguity has to read as "cannot tell", never as "take the first one": a
|
|
120
|
+
* name declared twice (two branches of a conditional, a shadowed parameter)
|
|
121
|
+
* would otherwise attribute a call to whichever declaration happened to come
|
|
122
|
+
* first. Such a name is simply absent from the map, and the call is then
|
|
123
|
+
* judged on its own text - which fails closed, into a finding a human reads.
|
|
124
|
+
*/
|
|
125
|
+
function collectDeclarations(sourceFile: ts.SourceFile): Map<string, string> {
|
|
126
|
+
const seen: Map<string, number> = new Map<string, number>();
|
|
127
|
+
const text: Map<string, string> = new Map<string, string>();
|
|
128
|
+
|
|
129
|
+
const record: (name: string, node: ts.Node) => void = (
|
|
130
|
+
name: string,
|
|
131
|
+
node: ts.Node,
|
|
132
|
+
): void => {
|
|
133
|
+
seen.set(name, (seen.get(name) || 0) + 1);
|
|
134
|
+
text.set(name, node.getText(sourceFile));
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const visit: (node: ts.Node) => void = (node: ts.Node): void => {
|
|
138
|
+
if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name)) {
|
|
139
|
+
record(node.name.text, node);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
143
|
+
record(node.name.text, node);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
ts.forEachChild(node, visit);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
ts.forEachChild(sourceFile, visit);
|
|
150
|
+
|
|
151
|
+
for (const [name, count] of seen) {
|
|
152
|
+
if (count !== 1) {
|
|
153
|
+
text.delete(name);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return text;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/*
|
|
161
|
+
* An expression's own text, plus the text of every identifier in it that this
|
|
162
|
+
* file declares - one level deep.
|
|
163
|
+
*
|
|
164
|
+
* One level is what the indirection in these pages is worth (`getHeaders()`
|
|
165
|
+
* returning `ModelAPI.getCommonHeaders()`), and stopping there keeps the
|
|
166
|
+
* expansion bounded and readable. A deeper chain reads as unresolved, which
|
|
167
|
+
* fails closed into a finding rather than quietly passing.
|
|
168
|
+
*/
|
|
169
|
+
function expand(expression: string, declarations: Map<string, string>): string {
|
|
170
|
+
const identifiers: Array<string> =
|
|
171
|
+
expression.match(/[A-Za-z_$][\w$]*/g) || [];
|
|
172
|
+
const parts: Array<string> = [expression];
|
|
173
|
+
|
|
174
|
+
for (const identifier of new Set<string>(identifiers)) {
|
|
175
|
+
const declaration: string | undefined = declarations.get(identifier);
|
|
176
|
+
|
|
177
|
+
if (declaration) {
|
|
178
|
+
parts.push(declaration);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return parts.join("\n");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/*
|
|
186
|
+
* The local names bound to a raw client in this file, e.g. `API` from
|
|
187
|
+
* `import API from "Common/UI/Utils/API/API"`.
|
|
188
|
+
*
|
|
189
|
+
* Reading the imports rather than matching the literal name `API` is what
|
|
190
|
+
* keeps `ModelAPI.post` and `AnalyticsModelAPI.post` out of the sweep: those
|
|
191
|
+
* resolve to a different module, and demanding an explicit tenant header from
|
|
192
|
+
* them would be wrong - they send one already.
|
|
193
|
+
*/
|
|
194
|
+
function rawClientNames(sourceFile: ts.SourceFile): Set<string> {
|
|
195
|
+
const names: Set<string> = new Set<string>();
|
|
196
|
+
|
|
197
|
+
for (const statement of sourceFile.statements) {
|
|
198
|
+
if (!ts.isImportDeclaration(statement)) {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (!ts.isStringLiteral(statement.moduleSpecifier)) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const specifier: string = statement.moduleSpecifier.text;
|
|
207
|
+
|
|
208
|
+
const isRawClient: boolean = RAW_CLIENT_SPECIFIERS.some(
|
|
209
|
+
(suffix: string): boolean => {
|
|
210
|
+
return specifier.endsWith(suffix);
|
|
211
|
+
},
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
if (!isRawClient || !statement.importClause) {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// A type-only import carries no client, so it opens no request.
|
|
219
|
+
if (statement.importClause.isTypeOnly) {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (statement.importClause.name) {
|
|
224
|
+
names.add(statement.importClause.name.text);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return names;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/* The source text of one property of an object literal, or "" when unset. */
|
|
232
|
+
function readProperty(
|
|
233
|
+
literal: ts.ObjectLiteralExpression,
|
|
234
|
+
name: string,
|
|
235
|
+
sourceFile: ts.SourceFile,
|
|
236
|
+
): string {
|
|
237
|
+
for (const property of literal.properties) {
|
|
238
|
+
if (!ts.isPropertyAssignment(property)) {
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (!ts.isIdentifier(property.name) && !ts.isStringLiteral(property.name)) {
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (property.name.text === name) {
|
|
247
|
+
return property.initializer.getText(sourceFile);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return "";
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/* One module's syntax tree. JSX only parses under the TSX script kind. */
|
|
255
|
+
function parse(source: string, file: string): ts.SourceFile {
|
|
256
|
+
return ts.createSourceFile(
|
|
257
|
+
file,
|
|
258
|
+
source,
|
|
259
|
+
ts.ScriptTarget.Latest,
|
|
260
|
+
true,
|
|
261
|
+
file.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS,
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/*
|
|
266
|
+
* Every `API.<verb>(...)` in one browser module, where `API` is a raw client
|
|
267
|
+
* this file imported.
|
|
268
|
+
*
|
|
269
|
+
* A call whose argument is not an object literal - `API.post(buildRequest())`
|
|
270
|
+
* - has no `url`/`data`/`headers` to read, so it is reported with all three
|
|
271
|
+
* empty rather than dropped. Empty reads as "names no project", which turns
|
|
272
|
+
* an unreadable call into a finding a human looks at instead of a hole the
|
|
273
|
+
* sweep walks past. There are none in the Dashboard today; the point is that
|
|
274
|
+
* the first one cannot arrive unnoticed.
|
|
275
|
+
*/
|
|
276
|
+
export function findRawApiCalls(
|
|
277
|
+
source: string,
|
|
278
|
+
file: string,
|
|
279
|
+
): Array<RawApiCall> {
|
|
280
|
+
if (!REQUEST_HINT.test(source)) {
|
|
281
|
+
return [];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const sourceFile: ts.SourceFile = parse(source, file);
|
|
285
|
+
|
|
286
|
+
const clients: Set<string> = rawClientNames(sourceFile);
|
|
287
|
+
|
|
288
|
+
if (clients.size === 0) {
|
|
289
|
+
return [];
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const calls: Array<RawApiCall> = [];
|
|
293
|
+
|
|
294
|
+
const visit: (node: ts.Node) => void = (node: ts.Node): void => {
|
|
295
|
+
ts.forEachChild(node, visit);
|
|
296
|
+
|
|
297
|
+
if (!ts.isCallExpression(node)) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const callee: ts.LeftHandSideExpression = node.expression;
|
|
302
|
+
|
|
303
|
+
/*
|
|
304
|
+
* `API.post<T>({...})` parses as a call whose expression is the property
|
|
305
|
+
* access; the type argument lives on the call, so nothing extra is needed
|
|
306
|
+
* to match both spellings.
|
|
307
|
+
*/
|
|
308
|
+
if (!ts.isPropertyAccessExpression(callee)) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (!ts.isIdentifier(callee.expression)) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (!clients.has(callee.expression.text)) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (!REQUEST_VERBS.has(callee.name.text)) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const argument: ts.Expression | undefined = node.arguments[0];
|
|
325
|
+
|
|
326
|
+
const literal: ts.ObjectLiteralExpression | null =
|
|
327
|
+
argument && ts.isObjectLiteralExpression(argument) ? argument : null;
|
|
328
|
+
|
|
329
|
+
calls.push({
|
|
330
|
+
line:
|
|
331
|
+
sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile))
|
|
332
|
+
.line + 1,
|
|
333
|
+
verb: callee.name.text,
|
|
334
|
+
url: literal ? readProperty(literal, "url", sourceFile) : "",
|
|
335
|
+
data: literal ? readProperty(literal, "data", sourceFile) : "",
|
|
336
|
+
headers: literal ? readProperty(literal, "headers", sourceFile) : "",
|
|
337
|
+
});
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
ts.forEachChild(sourceFile, visit);
|
|
341
|
+
|
|
342
|
+
return calls.sort((left: RawApiCall, right: RawApiCall): number => {
|
|
343
|
+
return left.line - right.line;
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/* Whether a call sends `tenantid` - see TENANT_HEADER. */
|
|
348
|
+
export function sendsTenantHeader(
|
|
349
|
+
call: RawApiCall,
|
|
350
|
+
declarations: Map<string, string>,
|
|
351
|
+
): boolean {
|
|
352
|
+
if (!call.headers) {
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return TENANT_HEADER.test(expand(call.headers, declarations));
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/*
|
|
360
|
+
* Whether the request body carries `projectId`, which
|
|
361
|
+
* ProjectMiddleware.getProjectId reads as its last fallback. Most of the
|
|
362
|
+
* Dashboard's raw posts scope themselves this way rather than with the
|
|
363
|
+
* header - `projectId: ProjectUtil.getCurrentProjectId()!` - and that is a
|
|
364
|
+
* perfectly good answer to "which project is this for?".
|
|
365
|
+
*
|
|
366
|
+
* Both spellings count: `projectId: x` and the shorthand `projectId`.
|
|
367
|
+
*/
|
|
368
|
+
export function sendsProjectIdInBody(
|
|
369
|
+
call: RawApiCall,
|
|
370
|
+
declarations: Map<string, string>,
|
|
371
|
+
): boolean {
|
|
372
|
+
if (!call.data) {
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const text: string = expand(call.data, declarations);
|
|
377
|
+
|
|
378
|
+
return PROJECT_ID_PROPERTY.test(text);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/*
|
|
382
|
+
* Whether the project is named in the URL itself - either as a path segment
|
|
383
|
+
* the route declares as `:projectId`, or by a call to getCurrentProjectId().
|
|
384
|
+
*/
|
|
385
|
+
export function urlCarriesProjectId(
|
|
386
|
+
call: RawApiCall,
|
|
387
|
+
declarations: Map<string, string>,
|
|
388
|
+
): boolean {
|
|
389
|
+
if (!call.url) {
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const text: string = expand(call.url, declarations);
|
|
394
|
+
|
|
395
|
+
return PROJECT_ID_IN_URL.test(text);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/* The three ways a request can name its project, in one question. */
|
|
399
|
+
export function makesProjectExplicit(
|
|
400
|
+
call: RawApiCall,
|
|
401
|
+
declarations: Map<string, string>,
|
|
402
|
+
): boolean {
|
|
403
|
+
return (
|
|
404
|
+
sendsTenantHeader(call, declarations) ||
|
|
405
|
+
sendsProjectIdInBody(call, declarations) ||
|
|
406
|
+
urlCarriesProjectId(call, declarations)
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/* Every raw call in one module that names no project. */
|
|
411
|
+
export function findImplicitProjectCalls(
|
|
412
|
+
source: string,
|
|
413
|
+
file: string,
|
|
414
|
+
): Array<Finding> {
|
|
415
|
+
const calls: Array<RawApiCall> = findRawApiCalls(source, file);
|
|
416
|
+
|
|
417
|
+
if (calls.length === 0) {
|
|
418
|
+
return [];
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const declarations: Map<string, string> = collectDeclarations(
|
|
422
|
+
parse(source, file),
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
return calls
|
|
426
|
+
.filter((call: RawApiCall): boolean => {
|
|
427
|
+
return !makesProjectExplicit(call, declarations);
|
|
428
|
+
})
|
|
429
|
+
.map((call: RawApiCall): Finding => {
|
|
430
|
+
const target: string = call.url.replace(/\s+/g, " ").trim();
|
|
431
|
+
|
|
432
|
+
return {
|
|
433
|
+
line: call.line,
|
|
434
|
+
description: target
|
|
435
|
+
? `API.${call.verb} to ${target} sends no project`
|
|
436
|
+
: `API.${call.verb} is not written as an object literal, so the scan cannot tell whether it names a project`,
|
|
437
|
+
};
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/*
|
|
442
|
+
* One line per request that names no project, naming the file, the line and
|
|
443
|
+
* the fix. The strings ARE the failure message: jest prints the received
|
|
444
|
+
* array.
|
|
445
|
+
*/
|
|
446
|
+
export function findImplicitProjectOffenders(data: {
|
|
447
|
+
sources: ReadonlyMap<string, string>;
|
|
448
|
+
baseDir: string;
|
|
449
|
+
allowlist: ReadonlyArray<AllowlistEntry>;
|
|
450
|
+
}): Array<string> {
|
|
451
|
+
const allowed: Set<string> = allowlistedFiles(data.allowlist);
|
|
452
|
+
const offenders: Array<string> = [];
|
|
453
|
+
|
|
454
|
+
for (const [file, source] of data.sources) {
|
|
455
|
+
const relative: string = toRelativePath(data.baseDir, file);
|
|
456
|
+
|
|
457
|
+
if (allowed.has(relative)) {
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
for (const finding of findImplicitProjectCalls(source, file)) {
|
|
462
|
+
offenders.push(
|
|
463
|
+
`${relative}:${finding.line} ${finding.description}. Add \`headers: ModelAPI.getCommonHeaders(),\` to the call so a \`tenantid\` header is sent (or put \`projectId\` in the body). Without it ProjectMiddleware.getProjectId finds no project, and a project-scoped route answers "Project ID is required".`,
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return offenders;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/*
|
|
472
|
+
* Allowlist entries that no longer earn their place: the file is gone, or
|
|
473
|
+
* every raw call in it now names a project. A suite asserts this is empty, so
|
|
474
|
+
* an allowlist cannot quietly outlive its reasons.
|
|
475
|
+
*/
|
|
476
|
+
export function findStaleProjectAllowlistEntries(data: {
|
|
477
|
+
baseDir: string;
|
|
478
|
+
allowlist: ReadonlyArray<AllowlistEntry>;
|
|
479
|
+
allowlistName: string;
|
|
480
|
+
}): Array<string> {
|
|
481
|
+
const stale: Array<string> = [];
|
|
482
|
+
|
|
483
|
+
for (const entry of data.allowlist) {
|
|
484
|
+
const filePath: string = fromRelativePath(data.baseDir, entry.file);
|
|
485
|
+
|
|
486
|
+
if (!fs.existsSync(filePath)) {
|
|
487
|
+
stale.push(
|
|
488
|
+
`${entry.file} no longer exists - remove it from ${data.allowlistName}`,
|
|
489
|
+
);
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (
|
|
494
|
+
findImplicitProjectCalls(fs.readFileSync(filePath, "utf8"), filePath)
|
|
495
|
+
.length === 0
|
|
496
|
+
) {
|
|
497
|
+
stale.push(
|
|
498
|
+
`${entry.file} no longer makes a request without a project - remove it from ${data.allowlistName}`,
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
return stale;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/*
|
|
507
|
+
* The declarations one module contributes to the scan, exposed so a suite can
|
|
508
|
+
* ask about a single call it names rather than only about the whole sweep.
|
|
509
|
+
*/
|
|
510
|
+
export function readDeclarations(
|
|
511
|
+
source: string,
|
|
512
|
+
file: string,
|
|
513
|
+
): Map<string, string> {
|
|
514
|
+
return collectDeclarations(parse(source, file));
|
|
515
|
+
}
|
|
@@ -258,14 +258,6 @@ const FEED_MODELS: Array<FeedModelSpec> = [
|
|
|
258
258
|
"ServiceLevelObjectiveArchived",
|
|
259
259
|
"ServiceLevelObjectiveRestored",
|
|
260
260
|
],
|
|
261
|
-
/*
|
|
262
|
-
* SLOs have no owner rules and no label rules - the rules they do have
|
|
263
|
-
* (burn rate and monitor rules) post their own events - so these two would
|
|
264
|
-
* be enum members nothing can ever write. Enum values are stored verbatim
|
|
265
|
-
* and can never be removed once rows exist, so they are exempted here
|
|
266
|
-
* rather than added as dead values. The four owner events still apply.
|
|
267
|
-
*/
|
|
268
|
-
exemptSharedEventTypes: ["OwnerRuleExecuted", "LabelRuleExecuted"],
|
|
269
261
|
},
|
|
270
262
|
];
|
|
271
263
|
|