@oneuptime/common 13.0.8 → 14.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/AnalyticsModels/AuditLog.ts +23 -15
- package/Models/DatabaseModels/GlobalConfig.ts +24 -0
- package/Models/DatabaseModels/Monitor.ts +3 -2
- package/Models/DatabaseModels/MonitorTemplate.ts +2 -1
- package/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/Index.ts +2 -0
- package/Server/Middleware/UserAuthorization.ts +38 -16
- package/Server/Services/AuditLogService.ts +84 -1079
- package/Server/Services/EnterpriseLicenseService.ts +38 -0
- package/Server/Services/GlobalConfigService.ts +80 -1
- package/Server/Services/MonitorProbeService.ts +116 -20
- package/Server/Services/MonitorService.ts +56 -4
- package/Server/Services/MonitorStatusTimelineService.ts +284 -0
- package/Server/Services/MonitorTemplateService.ts +26 -0
- package/Server/Services/ProjectService.ts +284 -0
- package/Server/Services/RumSessionPinService.ts +25 -6
- 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/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 +190 -0
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +10 -1
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +543 -333
- package/Server/Utils/Monitor/MonitoringIntervalValidator.ts +116 -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/IdentityEnterpriseShells.test.tsx +319 -0
- package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +185 -0
- 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/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/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/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/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/ScimPushGroupsTeamLocksEdition.test.ts +431 -0
- package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +419 -0
- package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +769 -0
- package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +94 -0
- package/Tests/Server/Services/UserAuthenticationService.test.ts +35 -0
- package/Tests/Server/Services/UserServiceSeatLimit.test.ts +94 -56
- package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +1823 -0
- package/Tests/Server/Types/Markdown.test.ts +181 -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/MonitorCriteriaEvaluator.test.ts +934 -96
- package/Tests/Server/Utils/Monitor/MonitoringIntervalValidator.test.ts +188 -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/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/Graphs/DayUptimeGraph.test.tsx +49 -2
- package/Tests/UI/Components/MarkdownConverters.test.ts +684 -0
- package/Tests/UI/Components/ModelListEmptyState.test.tsx +289 -0
- package/Tests/UI/Components/TelemetryViewer/TelemetryViewerEmptyContent.test.tsx +131 -0
- package/Tests/UI/EsbuildEnterpriseAlias.test.ts +1127 -0
- package/Tests/Utils/HostAddressUtil.test.ts +138 -0
- package/Tests/Utils/Monitor/MonitorDestinationUtil.test.ts +313 -0
- package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +304 -0
- package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +248 -0
- package/Types/API/Hostname.ts +63 -16
- 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/MonitorStep.ts +6 -1
- package/Types/Monitor/ProxmoxAlertTemplates.ts +1 -1
- 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/Graphs/DayUptimeGraph.tsx +123 -15
- 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/Monitor/MonitorDestinationUtil.ts +157 -0
- package/Utils/Monitor/MonitoringIntervalUtil.ts +436 -0
- package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +192 -0
- package/build/dist/Models/AnalyticsModels/AuditLog.js +23 -15
- package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +25 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +2 -2
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorTemplate.js +2 -1
- package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
- package/build/dist/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/Index.js +2 -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/EnterpriseLicenseService.js +34 -0
- package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
- package/build/dist/Server/Services/GlobalConfigService.js +63 -0
- package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
- package/build/dist/Server/Services/MonitorProbeService.js +90 -17
- package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +45 -4
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusTimelineService.js +242 -0
- package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +16 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/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/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/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 +96 -0
- package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +449 -261
- 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/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/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/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/Graphs/DayUptimeGraph.js +90 -17
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
- package/build/dist/UI/Components/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/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/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
|
@@ -12,26 +12,58 @@ import BaseAPI from "./BaseAPI";
|
|
|
12
12
|
import GlobalConfig from "../../Models/DatabaseModels/GlobalConfig";
|
|
13
13
|
import ObjectID from "../../Types/ObjectID";
|
|
14
14
|
import { JSONObject } from "../../Types/JSON";
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
import HTTPErrorResponse from "../../Types/API/HTTPErrorResponse";
|
|
18
|
-
import HTTPResponse from "../../Types/API/HTTPResponse";
|
|
19
|
-
import PartialEntity from "../../Types/Database/PartialEntity";
|
|
20
|
-
import {
|
|
21
|
-
AppVersion,
|
|
22
|
-
DisableUpdateCheck,
|
|
23
|
-
EnterpriseLicenseValidationUrl,
|
|
24
|
-
Host,
|
|
25
|
-
} from "../EnvironmentConfig";
|
|
15
|
+
import Select from "../Types/Database/Select";
|
|
16
|
+
import { AppVersion, DisableUpdateCheck } from "../EnvironmentConfig";
|
|
26
17
|
import EnterpriseLicenseInstanceSummary from "../../Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary";
|
|
27
18
|
import VersionUtil from "../../Utils/VersionUtil";
|
|
28
19
|
import UserMiddleware from "../Middleware/UserAuthorization";
|
|
29
20
|
import NotAuthenticatedException from "../../Types/Exception/NotAuthenticatedException";
|
|
30
|
-
import
|
|
31
|
-
import
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
21
|
+
import EnterpriseEdition from "../Enterprise/EnterpriseEdition";
|
|
22
|
+
import {
|
|
23
|
+
EnterpriseLicenseSnapshot,
|
|
24
|
+
EnterpriseLicenseSnapshotUtil,
|
|
25
|
+
SeatUsage,
|
|
26
|
+
} from "../Enterprise/EnterpriseLicenseSnapshot";
|
|
27
|
+
|
|
28
|
+
/*
|
|
29
|
+
* Who is asking for the license state, which decides how much of it they get.
|
|
30
|
+
*
|
|
31
|
+
* master-admin everything, including the license key, the token, the
|
|
32
|
+
* instance topology, this installation's version and seat
|
|
33
|
+
* usage - the things a master admin needs to manage the
|
|
34
|
+
* license and nobody else has any business reading.
|
|
35
|
+
* public anybody else, signed in or not (this route also serves the
|
|
36
|
+
* signed-out login page): only what the edition pill shows.
|
|
37
|
+
*/
|
|
38
|
+
export type LicenseResponseAudience = "master-admin" | "public";
|
|
39
|
+
|
|
40
|
+
export interface BuildLicenseResponseData {
|
|
41
|
+
audience: LicenseResponseAudience;
|
|
42
|
+
// Whether the enterprise module is loaded in this process.
|
|
43
|
+
isEnterpriseEditionLoaded: boolean;
|
|
44
|
+
// The license snapshot, or null on the Community Edition.
|
|
45
|
+
snapshot: EnterpriseLicenseSnapshot | null;
|
|
46
|
+
/*
|
|
47
|
+
* The GlobalConfig row, selected with LICENSE_RESPONSE_CONFIG_SELECT. Only
|
|
48
|
+
* read for the master-admin audience.
|
|
49
|
+
*/
|
|
50
|
+
config: GlobalConfig | null;
|
|
51
|
+
// Seat usage as the license client enforces it. Only for master admins.
|
|
52
|
+
seatUsage: SeatUsage | null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Everything buildLicenseResponse reads off the GlobalConfig row.
|
|
56
|
+
export const LICENSE_RESPONSE_CONFIG_SELECT: Select<GlobalConfig> = {
|
|
57
|
+
enterpriseLicenseKey: true,
|
|
58
|
+
enterpriseLicenseToken: true,
|
|
59
|
+
enterpriseLicenseCurrentUserCount: true,
|
|
60
|
+
enterpriseLicenseUserCountUpdatedAt: true,
|
|
61
|
+
enterpriseLicenseInstances: true,
|
|
62
|
+
instanceId: true,
|
|
63
|
+
latestReleaseVersion: true,
|
|
64
|
+
latestReleasePublishedAt: true,
|
|
65
|
+
latestReleaseCheckedAt: true,
|
|
66
|
+
};
|
|
35
67
|
|
|
36
68
|
export default class GlobalConfigAPI extends BaseAPI<
|
|
37
69
|
GlobalConfig,
|
|
@@ -66,6 +98,20 @@ export default class GlobalConfigAPI extends BaseAPI<
|
|
|
66
98
|
},
|
|
67
99
|
);
|
|
68
100
|
|
|
101
|
+
/*
|
|
102
|
+
* The license state of this installation, for the edition pill and the
|
|
103
|
+
* license dialog.
|
|
104
|
+
*
|
|
105
|
+
* This route stays in core so the Community Edition can still serve the
|
|
106
|
+
* version and update-check half of the dialog. The license half comes
|
|
107
|
+
* from the Enterprise license client through EnterpriseEdition; activating
|
|
108
|
+
* and refreshing a license (the POSTs on this path) are served by the
|
|
109
|
+
* Enterprise module itself (ee/Server/License).
|
|
110
|
+
*
|
|
111
|
+
* This route also serves the login page (before sign-in), so it cannot
|
|
112
|
+
* require authentication outright. Anybody but a master admin gets only
|
|
113
|
+
* what the edition pill shows - see buildLicenseResponse.
|
|
114
|
+
*/
|
|
69
115
|
this.router.get(
|
|
70
116
|
`${new this.entityType().getCrudApiPath()?.toString()}/license`,
|
|
71
117
|
UserMiddleware.getUserMiddleware,
|
|
@@ -87,484 +133,190 @@ export default class GlobalConfigAPI extends BaseAPI<
|
|
|
87
133
|
);
|
|
88
134
|
}
|
|
89
135
|
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
enterpriseCompanyName: true,
|
|
95
|
-
enterpriseLicenseExpiresAt: true,
|
|
96
|
-
enterpriseLicenseKey: true,
|
|
97
|
-
enterpriseLicenseToken: true,
|
|
98
|
-
enterpriseLicenseIsEvaluation: true,
|
|
99
|
-
enterpriseLicenseUserLimit: true,
|
|
100
|
-
enterpriseLicenseCurrentUserCount: true,
|
|
101
|
-
enterpriseLicenseUserCountUpdatedAt: true,
|
|
102
|
-
enterpriseLicenseInstances: true,
|
|
103
|
-
instanceId: true,
|
|
104
|
-
latestReleaseVersion: true,
|
|
105
|
-
latestReleasePublishedAt: true,
|
|
106
|
-
latestReleaseCheckedAt: true,
|
|
107
|
-
},
|
|
108
|
-
props: {
|
|
109
|
-
isRoot: true,
|
|
110
|
-
},
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
/*
|
|
114
|
-
* This route also serves the login page (before sign-in), so it
|
|
115
|
-
* cannot require authentication outright. Anonymous callers only
|
|
116
|
-
* get enough to render the edition pill — the license key, token
|
|
117
|
-
* and instance topology require a signed-in user.
|
|
118
|
-
*/
|
|
119
|
-
const isAuthenticatedUser: boolean = Boolean(
|
|
120
|
-
(req as OneUptimeRequest).userAuthorization?.userId,
|
|
121
|
-
);
|
|
136
|
+
const audience: LicenseResponseAudience =
|
|
137
|
+
GlobalConfigAPI.getLicenseResponseAudience(req);
|
|
138
|
+
const isEnterpriseEditionLoaded: boolean =
|
|
139
|
+
EnterpriseEdition.isLoaded();
|
|
122
140
|
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
);
|
|
141
|
+
const snapshot: EnterpriseLicenseSnapshot | null =
|
|
142
|
+
isEnterpriseEditionLoaded
|
|
143
|
+
? await EnterpriseEdition.getLicenseSnapshot()
|
|
144
|
+
: null;
|
|
128
145
|
|
|
129
146
|
/*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* callers: it is derived from the live User table, and an anonymous
|
|
133
|
-
* visitor on the login page has no business being told how close this
|
|
134
|
-
* server is to refusing new accounts.
|
|
147
|
+
* Only a master admin's response carries anything read from the row
|
|
148
|
+
* or derived from the live User table, so nobody else costs a read.
|
|
135
149
|
*/
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const responseBody: JSONObject = {
|
|
146
|
-
companyName: config?.enterpriseCompanyName || null,
|
|
147
|
-
expiresAt: config?.enterpriseLicenseExpiresAt
|
|
148
|
-
? config.enterpriseLicenseExpiresAt.toISOString()
|
|
149
|
-
: null,
|
|
150
|
-
licenseKey: isAuthenticatedUser
|
|
151
|
-
? config?.enterpriseLicenseKey || null
|
|
152
|
-
: null,
|
|
153
|
-
token: isAuthenticatedUser
|
|
154
|
-
? config?.enterpriseLicenseToken || null
|
|
155
|
-
: null,
|
|
156
|
-
licenseValid: licenseValid,
|
|
157
|
-
/*
|
|
158
|
-
* Whether this is an evaluation/testing license. Benign like the
|
|
159
|
-
* company name and expiry, so it is not gated behind sign-in — the
|
|
160
|
-
* edition modal shows the evaluation notice to anyone who opens it.
|
|
161
|
-
*/
|
|
162
|
-
isEvaluationLicense: Boolean(config?.enterpriseLicenseIsEvaluation),
|
|
163
|
-
userLimit:
|
|
164
|
-
typeof config?.enterpriseLicenseUserLimit === "number"
|
|
165
|
-
? config.enterpriseLicenseUserLimit
|
|
166
|
-
: null,
|
|
167
|
-
currentUserCount:
|
|
168
|
-
typeof config?.enterpriseLicenseCurrentUserCount === "number"
|
|
169
|
-
? config.enterpriseLicenseCurrentUserCount
|
|
170
|
-
: null,
|
|
171
|
-
userCountUpdatedAt: config?.enterpriseLicenseUserCountUpdatedAt
|
|
172
|
-
? config.enterpriseLicenseUserCountUpdatedAt.toISOString()
|
|
173
|
-
: null,
|
|
174
|
-
instances:
|
|
175
|
-
isAuthenticatedUser &&
|
|
176
|
-
Array.isArray(config?.enterpriseLicenseInstances)
|
|
177
|
-
? config.enterpriseLicenseInstances
|
|
178
|
-
: [],
|
|
179
|
-
instanceId:
|
|
180
|
-
isAuthenticatedUser && config?.instanceId
|
|
181
|
-
? config.instanceId.toString()
|
|
182
|
-
: null,
|
|
183
|
-
/*
|
|
184
|
-
* Which build this installation runs, and whether a newer one has
|
|
185
|
-
* been released, are gated the same way as the instance topology:
|
|
186
|
-
* telling an anonymous visitor on the login page that this server
|
|
187
|
-
* is behind on patches advertises an unpatched target.
|
|
188
|
-
*/
|
|
189
|
-
currentVersion: isAuthenticatedUser ? AppVersion : null,
|
|
190
|
-
latestVersion: isAuthenticatedUser
|
|
191
|
-
? config?.latestReleaseVersion || null
|
|
192
|
-
: null,
|
|
193
|
-
latestVersionPublishedAt:
|
|
194
|
-
isAuthenticatedUser && config?.latestReleasePublishedAt
|
|
195
|
-
? config.latestReleasePublishedAt.toISOString()
|
|
196
|
-
: null,
|
|
197
|
-
latestVersionCheckedAt:
|
|
198
|
-
isAuthenticatedUser && config?.latestReleaseCheckedAt
|
|
199
|
-
? config.latestReleaseCheckedAt.toISOString()
|
|
200
|
-
: null,
|
|
201
|
-
isUpdateAvailable: isAuthenticatedUser
|
|
202
|
-
? VersionUtil.isUpdateAvailable({
|
|
203
|
-
currentVersion: AppVersion,
|
|
204
|
-
latestVersion: config?.latestReleaseVersion,
|
|
150
|
+
const config: GlobalConfig | null =
|
|
151
|
+
audience === "master-admin"
|
|
152
|
+
? await GlobalConfigService.findOneById({
|
|
153
|
+
id: ObjectID.getZeroObjectID(),
|
|
154
|
+
select: LICENSE_RESPONSE_CONFIG_SELECT,
|
|
155
|
+
props: {
|
|
156
|
+
isRoot: true,
|
|
157
|
+
},
|
|
205
158
|
})
|
|
206
|
-
:
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
/*
|
|
226
|
-
* Activating (or replacing) the license key for the whole installation.
|
|
227
|
-
*
|
|
228
|
-
* Master admin only. This writes the terms that bound how many users the
|
|
229
|
-
* installation may have, so anyone who can reach it can change the seat
|
|
230
|
-
* limit UserService now enforces. It used to run on
|
|
231
|
-
* UserMiddleware.getUserMiddleware, which lets anonymous callers through
|
|
232
|
-
* (it has to — the GET above serves the signed-out login page), so the
|
|
233
|
-
* route was in practice unauthenticated.
|
|
234
|
-
*/
|
|
235
|
-
this.router.post(
|
|
236
|
-
`${new this.entityType().getCrudApiPath()?.toString()}/license`,
|
|
237
|
-
MasterAdminAuthorization.isAuthorizedMasterAdminMiddleware,
|
|
238
|
-
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
239
|
-
try {
|
|
240
|
-
const licenseKey: string =
|
|
241
|
-
(req.body["licenseKey"] as string | undefined)?.trim() || "";
|
|
242
|
-
|
|
243
|
-
if (!licenseKey) {
|
|
244
|
-
throw new BadDataException("License key is required");
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const responseBody: JSONObject =
|
|
248
|
-
await this.validateAndStoreLicenseKey(licenseKey);
|
|
249
|
-
|
|
250
|
-
return Response.sendJsonObjectResponse(req, res, responseBody);
|
|
159
|
+
: null;
|
|
160
|
+
|
|
161
|
+
const seatUsage: SeatUsage | null =
|
|
162
|
+
audience === "master-admin" && isEnterpriseEditionLoaded
|
|
163
|
+
? await EnterpriseEdition.getSeatUsage()
|
|
164
|
+
: null;
|
|
165
|
+
|
|
166
|
+
return Response.sendJsonObjectResponse(
|
|
167
|
+
req,
|
|
168
|
+
res,
|
|
169
|
+
GlobalConfigAPI.buildLicenseResponse({
|
|
170
|
+
audience,
|
|
171
|
+
isEnterpriseEditionLoaded,
|
|
172
|
+
snapshot,
|
|
173
|
+
config,
|
|
174
|
+
seatUsage,
|
|
175
|
+
}),
|
|
176
|
+
);
|
|
251
177
|
} catch (err) {
|
|
252
178
|
next(err);
|
|
253
179
|
}
|
|
254
180
|
},
|
|
255
181
|
);
|
|
182
|
+
}
|
|
256
183
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
* would let a mistyped key replace a working license by accident.
|
|
269
|
-
*/
|
|
270
|
-
this.router.post(
|
|
271
|
-
`${new this.entityType().getCrudApiPath()?.toString()}/license/refresh`,
|
|
272
|
-
MasterAdminAuthorization.isAuthorizedMasterAdminMiddleware,
|
|
273
|
-
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
274
|
-
try {
|
|
275
|
-
const config: GlobalConfig | null =
|
|
276
|
-
await GlobalConfigService.findOneById({
|
|
277
|
-
id: ObjectID.getZeroObjectID(),
|
|
278
|
-
select: {
|
|
279
|
-
enterpriseLicenseKey: true,
|
|
280
|
-
},
|
|
281
|
-
props: {
|
|
282
|
-
isRoot: true,
|
|
283
|
-
},
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
const licenseKey: string = config?.enterpriseLicenseKey?.trim() || "";
|
|
287
|
-
|
|
288
|
-
if (!licenseKey) {
|
|
289
|
-
throw new BadDataException(
|
|
290
|
-
"This installation does not have an enterprise license key yet. Enter a license key to activate it first.",
|
|
291
|
-
);
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
const responseBody: JSONObject =
|
|
295
|
-
await this.validateAndStoreLicenseKey(licenseKey);
|
|
296
|
-
|
|
297
|
-
return Response.sendJsonObjectResponse(req, res, responseBody);
|
|
298
|
-
} catch (err) {
|
|
299
|
-
next(err);
|
|
300
|
-
}
|
|
301
|
-
},
|
|
302
|
-
);
|
|
184
|
+
/*
|
|
185
|
+
* A master admin is recognised from the verified access token that
|
|
186
|
+
* UserMiddleware.getUserMiddleware decoded. Anything else - no token, an
|
|
187
|
+
* API key, a status-page user, a signed-in project member - is "public".
|
|
188
|
+
*/
|
|
189
|
+
public static getLicenseResponseAudience(
|
|
190
|
+
req: ExpressRequest,
|
|
191
|
+
): LicenseResponseAudience {
|
|
192
|
+
return (req as OneUptimeRequest).userAuthorization?.isMasterAdmin === true
|
|
193
|
+
? "master-admin"
|
|
194
|
+
: "public";
|
|
303
195
|
}
|
|
304
196
|
|
|
305
197
|
/*
|
|
306
|
-
*
|
|
307
|
-
*
|
|
198
|
+
* The body of GET /global-config/license, and of the Enterprise license
|
|
199
|
+
* client's activation and refresh responses, so the three can never
|
|
200
|
+
* disagree on a field.
|
|
308
201
|
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
* to be dropped on the floor by the daily report job before.
|
|
202
|
+
* licenseValid is true for a valid license AND one in its grace period:
|
|
203
|
+
* grace means nothing has changed yet, and the dialog must not tell an
|
|
204
|
+
* administrator the license is gone while everything still works.
|
|
313
205
|
*/
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
):
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
const validationResponse: HTTPResponse<JSONObject> | HTTPErrorResponse =
|
|
342
|
-
await API.post<JSONObject>({
|
|
343
|
-
url: EnterpriseLicenseValidationUrl,
|
|
344
|
-
data: {
|
|
345
|
-
licenseKey,
|
|
346
|
-
instanceId: instanceId.toString(),
|
|
347
|
-
host: Host,
|
|
348
|
-
/*
|
|
349
|
-
* Sent here as well as from the daily report job so the version
|
|
350
|
-
* lands on the license server the moment the key is validated,
|
|
351
|
-
* rather than up to 24 hours later.
|
|
352
|
-
*/
|
|
353
|
-
version: AppVersion,
|
|
354
|
-
},
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
if (!validationResponse.isSuccess()) {
|
|
358
|
-
const errorMessage: string =
|
|
359
|
-
validationResponse instanceof HTTPErrorResponse
|
|
360
|
-
? validationResponse.message || "Failed to validate license key."
|
|
361
|
-
: "Failed to validate license key.";
|
|
362
|
-
throw new BadDataException(errorMessage);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
const payload: JSONObject = validationResponse.data as JSONObject;
|
|
366
|
-
|
|
367
|
-
const companyNameRaw: string =
|
|
368
|
-
(payload["companyName"] as string | undefined)?.trim() || "";
|
|
369
|
-
const expiresAtRaw: string =
|
|
370
|
-
(payload["expiresAt"] as string | undefined) || "";
|
|
371
|
-
const licenseKeyRaw: string =
|
|
372
|
-
(payload["licenseKey"] as string | undefined)?.trim() || licenseKey;
|
|
373
|
-
const licenseToken: string = (payload["token"] as string | undefined) || "";
|
|
374
|
-
|
|
375
|
-
let licenseExpiry: Date | undefined = undefined;
|
|
376
|
-
if (expiresAtRaw) {
|
|
377
|
-
const parsedDate: Date = new Date(expiresAtRaw);
|
|
378
|
-
|
|
379
|
-
if (Number.isNaN(parsedDate.getTime())) {
|
|
380
|
-
throw new BadDataException(
|
|
381
|
-
"License expiration returned from server is invalid.",
|
|
382
|
-
);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
licenseExpiry = parsedDate;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
const userLimitRaw: unknown = payload["userLimit"];
|
|
389
|
-
const userLimit: number | null =
|
|
390
|
-
typeof userLimitRaw === "number" && Number.isFinite(userLimitRaw)
|
|
391
|
-
? userLimitRaw
|
|
392
|
-
: null;
|
|
393
|
-
|
|
394
|
-
const currentUserCountRaw: unknown = payload["currentUserCount"];
|
|
395
|
-
const currentUserCount: number | null =
|
|
396
|
-
typeof currentUserCountRaw === "number" &&
|
|
397
|
-
Number.isFinite(currentUserCountRaw)
|
|
398
|
-
? currentUserCountRaw
|
|
399
|
-
: null;
|
|
400
|
-
|
|
401
|
-
const userCountUpdatedAtRaw: string | undefined = payload[
|
|
402
|
-
"userCountUpdatedAt"
|
|
403
|
-
] as string | undefined;
|
|
404
|
-
let userCountUpdatedAt: Date | null = null;
|
|
405
|
-
if (userCountUpdatedAtRaw) {
|
|
406
|
-
const parsedReportedAt: Date = new Date(userCountUpdatedAtRaw);
|
|
407
|
-
if (!Number.isNaN(parsedReportedAt.getTime())) {
|
|
408
|
-
userCountUpdatedAt = parsedReportedAt;
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
const isEvaluationLicense: boolean =
|
|
413
|
-
payload["isEvaluationLicense"] === true;
|
|
414
|
-
|
|
415
|
-
const instances: Array<EnterpriseLicenseInstanceSummary> = Array.isArray(
|
|
416
|
-
payload["instances"],
|
|
417
|
-
)
|
|
418
|
-
? (payload["instances"] as Array<EnterpriseLicenseInstanceSummary>)
|
|
419
|
-
: [];
|
|
420
|
-
|
|
421
|
-
const updatePayload: PartialEntity<GlobalConfig> = {
|
|
422
|
-
enterpriseCompanyName: companyNameRaw || null,
|
|
423
|
-
enterpriseLicenseKey: licenseKeyRaw || null,
|
|
424
|
-
enterpriseLicenseExpiresAt: licenseExpiry || null,
|
|
425
|
-
enterpriseLicenseToken: licenseToken || null,
|
|
426
|
-
enterpriseLicenseIsEvaluation: isEvaluationLicense,
|
|
427
|
-
enterpriseLicenseUserLimit: userLimit,
|
|
428
|
-
enterpriseLicenseCurrentUserCount: currentUserCount,
|
|
429
|
-
enterpriseLicenseUserCountUpdatedAt: userCountUpdatedAt,
|
|
430
|
-
enterpriseLicenseInstances: instances,
|
|
206
|
+
public static buildLicenseResponse(
|
|
207
|
+
data: BuildLicenseResponseData,
|
|
208
|
+
): JSONObject {
|
|
209
|
+
const snapshot: EnterpriseLicenseSnapshot | null =
|
|
210
|
+
data.isEnterpriseEditionLoaded ? data.snapshot : null;
|
|
211
|
+
|
|
212
|
+
const publicFields: JSONObject = {
|
|
213
|
+
edition: data.isEnterpriseEditionLoaded ? "enterprise" : "community",
|
|
214
|
+
status: snapshot ? snapshot.status : null,
|
|
215
|
+
verification: snapshot ? snapshot.verification : null,
|
|
216
|
+
graceReason: snapshot?.graceReason || null,
|
|
217
|
+
licenseValid: EnterpriseLicenseSnapshotUtil.isUsable(snapshot),
|
|
218
|
+
companyName: snapshot?.companyName || null,
|
|
219
|
+
expiresAt: GlobalConfigAPI.toIsoString(snapshot?.expiresAt),
|
|
220
|
+
graceEndsAt: GlobalConfigAPI.toIsoString(snapshot?.graceEndsAt),
|
|
221
|
+
isEvaluation: Boolean(snapshot?.isEvaluation),
|
|
222
|
+
// The name older dialogs read; same value as isEvaluation.
|
|
223
|
+
isEvaluationLicense: Boolean(snapshot?.isEvaluation),
|
|
224
|
+
/*
|
|
225
|
+
* Which enterprise features the license covers: "all", or the
|
|
226
|
+
* EnterpriseFeature values it lists (null on the Community Edition).
|
|
227
|
+
* A valid license that leaves a feature out stops that feature (see
|
|
228
|
+
* EnterpriseEdition.isFeatureActive), which licenseValid alone cannot
|
|
229
|
+
* tell a screen.
|
|
230
|
+
*/
|
|
231
|
+
features: GlobalConfigAPI.toFeaturesResponse(snapshot),
|
|
431
232
|
};
|
|
432
233
|
|
|
433
|
-
if (
|
|
434
|
-
|
|
435
|
-
updatePayload.instanceId = instanceId;
|
|
234
|
+
if (data.audience !== "master-admin") {
|
|
235
|
+
return publicFields;
|
|
436
236
|
}
|
|
437
237
|
|
|
438
|
-
|
|
439
|
-
await GlobalConfigService.updateOneById({
|
|
440
|
-
id: globalConfigId,
|
|
441
|
-
data: updatePayload,
|
|
442
|
-
props: {
|
|
443
|
-
isRoot: true,
|
|
444
|
-
ignoreHooks: true,
|
|
445
|
-
},
|
|
446
|
-
});
|
|
447
|
-
} else {
|
|
448
|
-
const newConfig: GlobalConfig = new GlobalConfig();
|
|
449
|
-
newConfig.id = globalConfigId;
|
|
450
|
-
|
|
451
|
-
if (companyNameRaw) {
|
|
452
|
-
newConfig.enterpriseCompanyName = companyNameRaw;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
if (licenseKeyRaw) {
|
|
456
|
-
newConfig.enterpriseLicenseKey = licenseKeyRaw;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
if (licenseToken) {
|
|
460
|
-
newConfig.enterpriseLicenseToken = licenseToken;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
newConfig.enterpriseLicenseIsEvaluation = isEvaluationLicense;
|
|
464
|
-
|
|
465
|
-
if (licenseExpiry) {
|
|
466
|
-
newConfig.enterpriseLicenseExpiresAt = licenseExpiry;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
if (userLimit !== null) {
|
|
470
|
-
newConfig.enterpriseLicenseUserLimit = userLimit;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
if (currentUserCount !== null) {
|
|
474
|
-
newConfig.enterpriseLicenseCurrentUserCount = currentUserCount;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
if (userCountUpdatedAt) {
|
|
478
|
-
newConfig.enterpriseLicenseUserCountUpdatedAt = userCountUpdatedAt;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
newConfig.enterpriseLicenseInstances = instances;
|
|
482
|
-
newConfig.instanceId = instanceId;
|
|
483
|
-
|
|
484
|
-
await GlobalConfigService.create({
|
|
485
|
-
data: newConfig,
|
|
486
|
-
props: {
|
|
487
|
-
isRoot: true,
|
|
488
|
-
ignoreHooks: true,
|
|
489
|
-
},
|
|
490
|
-
});
|
|
491
|
-
}
|
|
238
|
+
const config: GlobalConfig | null = data.config;
|
|
492
239
|
|
|
493
240
|
/*
|
|
494
|
-
*
|
|
495
|
-
*
|
|
496
|
-
*
|
|
497
|
-
* seats sees them land.
|
|
241
|
+
* The license columns mean nothing on the Community Edition (a leftover
|
|
242
|
+
* key from an earlier Enterprise image licenses nothing here), so only
|
|
243
|
+
* the version half of the dialog is filled in there.
|
|
498
244
|
*/
|
|
499
|
-
const
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
});
|
|
245
|
+
const licenseConfig: GlobalConfig | null = snapshot ? config : null;
|
|
246
|
+
|
|
247
|
+
const licenseToken: string | null =
|
|
248
|
+
licenseConfig?.enterpriseLicenseToken || null;
|
|
249
|
+
const licenseKey: string | null =
|
|
250
|
+
licenseConfig?.enterpriseLicenseKey || null;
|
|
506
251
|
|
|
507
252
|
return {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
licenseKey:
|
|
511
|
-
token: licenseToken
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
253
|
+
...publicFields,
|
|
254
|
+
message: snapshot?.message || null,
|
|
255
|
+
licenseKey: licenseKey,
|
|
256
|
+
token: licenseToken,
|
|
257
|
+
/*
|
|
258
|
+
* "offline" when the license was activated by pasting a signed token:
|
|
259
|
+
* such an installation holds no license key and never calls home.
|
|
260
|
+
*/
|
|
261
|
+
activationMode: licenseToken ? (licenseKey ? "online" : "offline") : null,
|
|
262
|
+
// From the signed claims for a verified license, else the stored column.
|
|
263
|
+
userLimit:
|
|
264
|
+
typeof snapshot?.userLimit === "number" ? snapshot.userLimit : null,
|
|
265
|
+
currentUserCount:
|
|
266
|
+
typeof licenseConfig?.enterpriseLicenseCurrentUserCount === "number"
|
|
267
|
+
? licenseConfig.enterpriseLicenseCurrentUserCount
|
|
268
|
+
: null,
|
|
269
|
+
userCountUpdatedAt: GlobalConfigAPI.toIsoString(
|
|
270
|
+
licenseConfig?.enterpriseLicenseUserCountUpdatedAt,
|
|
271
|
+
),
|
|
272
|
+
instances: Array.isArray(licenseConfig?.enterpriseLicenseInstances)
|
|
273
|
+
? (licenseConfig?.enterpriseLicenseInstances as Array<EnterpriseLicenseInstanceSummary>)
|
|
274
|
+
: [],
|
|
275
|
+
instanceId: licenseConfig?.instanceId
|
|
276
|
+
? licenseConfig.instanceId.toString()
|
|
517
277
|
: null,
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
278
|
+
/*
|
|
279
|
+
* Which build this installation runs, and whether a newer one has been
|
|
280
|
+
* released. Master admins only: telling anybody else that this server
|
|
281
|
+
* is behind on patches advertises an unpatched target.
|
|
282
|
+
*/
|
|
283
|
+
currentVersion: AppVersion,
|
|
284
|
+
latestVersion: config?.latestReleaseVersion || null,
|
|
285
|
+
latestVersionPublishedAt: GlobalConfigAPI.toIsoString(
|
|
286
|
+
config?.latestReleasePublishedAt,
|
|
287
|
+
),
|
|
288
|
+
latestVersionCheckedAt: GlobalConfigAPI.toIsoString(
|
|
289
|
+
config?.latestReleaseCheckedAt,
|
|
290
|
+
),
|
|
291
|
+
isUpdateAvailable: VersionUtil.isUpdateAvailable({
|
|
292
|
+
currentVersion: AppVersion,
|
|
293
|
+
latestVersion: config?.latestReleaseVersion,
|
|
294
|
+
}),
|
|
295
|
+
/*
|
|
296
|
+
* Lets the dialog say "update checks are off" instead of "has not
|
|
297
|
+
* checked yet", which would be a promise the installation is never
|
|
298
|
+
* going to keep.
|
|
299
|
+
*/
|
|
300
|
+
isUpdateCheckDisabled: DisableUpdateCheck,
|
|
301
|
+
...GlobalConfigAPI.getSeatUsageResponseFields(
|
|
302
|
+
snapshot ? data.seatUsage : null,
|
|
303
|
+
),
|
|
521
304
|
};
|
|
522
305
|
}
|
|
523
306
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
userLimit: number | null;
|
|
531
|
-
currentUserCount: number | null;
|
|
532
|
-
instances: Array<EnterpriseLicenseInstanceSummary>;
|
|
533
|
-
instanceId: ObjectID;
|
|
534
|
-
}): Promise<SeatUsage | null> {
|
|
535
|
-
const config: GlobalConfig = new GlobalConfig();
|
|
536
|
-
config.instanceId = data.instanceId;
|
|
537
|
-
config.enterpriseLicenseInstances = data.instances;
|
|
538
|
-
|
|
539
|
-
if (data.userLimit !== null) {
|
|
540
|
-
config.enterpriseLicenseUserLimit = data.userLimit;
|
|
307
|
+
// The license's features for a response: "all", a copy of the list, or null.
|
|
308
|
+
public static toFeaturesResponse(
|
|
309
|
+
snapshot: EnterpriseLicenseSnapshot | null,
|
|
310
|
+
): "all" | Array<string> | null {
|
|
311
|
+
if (!snapshot) {
|
|
312
|
+
return null;
|
|
541
313
|
}
|
|
542
314
|
|
|
543
|
-
if (
|
|
544
|
-
|
|
315
|
+
if (snapshot.features === "all") {
|
|
316
|
+
return "all";
|
|
545
317
|
}
|
|
546
318
|
|
|
547
|
-
return
|
|
548
|
-
config: config,
|
|
549
|
-
getLocalUserCount: GlobalConfigAPI.getLocalUserCount,
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
/*
|
|
554
|
-
* How many users exist on this installation right now. Deliberately the live
|
|
555
|
-
* count rather than the last reported one: the number an administrator is
|
|
556
|
-
* about to act on is the number that decides whether the next invitation
|
|
557
|
-
* goes through.
|
|
558
|
-
*/
|
|
559
|
-
private static async getLocalUserCount(): Promise<number> {
|
|
560
|
-
const userCount: PositiveNumber = await UserService.countBy({
|
|
561
|
-
query: {},
|
|
562
|
-
props: {
|
|
563
|
-
isRoot: true,
|
|
564
|
-
},
|
|
565
|
-
});
|
|
566
|
-
|
|
567
|
-
return userCount.toNumber();
|
|
319
|
+
return Array.isArray(snapshot.features) ? [...snapshot.features] : [];
|
|
568
320
|
}
|
|
569
321
|
|
|
570
322
|
/*
|
|
@@ -573,7 +325,7 @@ export default class GlobalConfigAPI extends BaseAPI<
|
|
|
573
325
|
* "this installation does not enforce them" by which fields are missing:
|
|
574
326
|
* isSeatLimitEnforced is the single flag that answers that.
|
|
575
327
|
*/
|
|
576
|
-
|
|
328
|
+
public static getSeatUsageResponseFields(
|
|
577
329
|
seatUsage: SeatUsage | null,
|
|
578
330
|
): JSONObject {
|
|
579
331
|
if (!seatUsage || !seatUsage.isEnforced) {
|
|
@@ -592,4 +344,18 @@ export default class GlobalConfigAPI extends BaseAPI<
|
|
|
592
344
|
canAddMoreUsers: seatUsage.hasSeatForNewUser,
|
|
593
345
|
};
|
|
594
346
|
}
|
|
347
|
+
|
|
348
|
+
private static toIsoString(value: Date | null | undefined): string | null {
|
|
349
|
+
if (!value) {
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const date: Date = value instanceof Date ? value : new Date(value);
|
|
354
|
+
|
|
355
|
+
if (Number.isNaN(date.getTime())) {
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return date.toISOString();
|
|
360
|
+
}
|
|
595
361
|
}
|