@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.
Files changed (514) hide show
  1. package/Models/AnalyticsModels/AuditLog.ts +23 -15
  2. package/Models/DatabaseModels/GlobalConfig.ts +24 -0
  3. package/Models/DatabaseModels/Index.ts +4 -0
  4. package/Models/DatabaseModels/Monitor.ts +3 -2
  5. package/Models/DatabaseModels/MonitorTemplate.ts +2 -1
  6. package/Models/DatabaseModels/ServiceLevelObjectiveFeed.ts +2 -0
  7. package/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.ts +522 -0
  8. package/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.ts +38 -4
  9. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.ts +603 -0
  10. package/Scripts/generate-service-worker.js +65 -4
  11. package/Server/API/BaseAPI.ts +26 -5
  12. package/Server/API/GlobalConfigAPI.ts +228 -462
  13. package/Server/API/ProjectOIDC.ts +25 -16
  14. package/Server/API/ProjectSSO.ts +24 -16
  15. package/Server/API/StatusPageAPI.ts +100 -42
  16. package/Server/API/TeamMemberAPI.ts +10 -1
  17. package/Server/Enterprise/EnterpriseEdition.ts +649 -0
  18. package/Server/Enterprise/EnterpriseFeature.ts +48 -0
  19. package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +192 -0
  20. package/Server/Enterprise/EnterpriseServerModule.ts +233 -0
  21. package/Server/EnvironmentConfig.ts +147 -2
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.ts +25 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.ts +248 -0
  24. package/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.ts +19 -0
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  26. package/Server/Middleware/UserAuthorization.ts +38 -16
  27. package/Server/Services/AuditLogService.ts +84 -1079
  28. package/Server/Services/DatabaseService.ts +10 -0
  29. package/Server/Services/EnterpriseLicenseService.ts +38 -0
  30. package/Server/Services/GlobalConfigService.ts +80 -1
  31. package/Server/Services/Index.ts +4 -0
  32. package/Server/Services/MonitorProbeService.ts +116 -20
  33. package/Server/Services/MonitorService.ts +59 -6
  34. package/Server/Services/MonitorStatusTimelineService.ts +284 -0
  35. package/Server/Services/MonitorTemplateService.ts +26 -0
  36. package/Server/Services/ProjectService.ts +284 -0
  37. package/Server/Services/RumSessionPinService.ts +25 -6
  38. package/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.ts +385 -0
  39. package/Server/Services/ServiceLevelObjectiveLabelRuleService.ts +51 -0
  40. package/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.ts +92 -16
  41. package/Server/Services/ServiceLevelObjectiveMonitorRuleService.ts +36 -1
  42. package/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.ts +521 -0
  43. package/Server/Services/ServiceLevelObjectiveOwnerRuleService.ts +51 -0
  44. package/Server/Services/ServiceLevelObjectiveService.ts +28 -0
  45. package/Server/Services/StatusPagePrivateUserService.ts +7 -3
  46. package/Server/Services/StatusPageService.ts +78 -1
  47. package/Server/Services/TeamMemberService.ts +11 -0
  48. package/Server/Services/TeamService.ts +10 -0
  49. package/Server/Services/UserService.ts +10 -17
  50. package/Server/Types/Database/Permissions/CreatePermission.ts +15 -0
  51. package/Server/Types/Database/Permissions/EditionPermission.ts +208 -18
  52. package/Server/Types/Database/Permissions/TablePermission.ts +10 -3
  53. package/Server/Types/Database/Permissions/UpdatePermission.ts +29 -0
  54. package/Server/Types/Markdown.ts +41 -0
  55. package/Server/Types/Workflow/Components/Telegram/SendMessageToChat.ts +27 -1
  56. package/Server/Utils/AI/Toolbox/SloTools.ts +1 -0
  57. package/Server/Utils/CommunityEditionSsoReport.ts +361 -0
  58. package/Server/Utils/EditionEnforcement.ts +233 -0
  59. package/Server/Utils/FrontendEnvironment.ts +41 -2
  60. package/Server/Utils/InstanceHealth/RedisHealth.ts +12 -277
  61. package/Server/Utils/Monitor/AffectedResourceList.ts +148 -0
  62. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +1 -1
  63. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +10 -1
  64. package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +1 -1
  65. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +720 -465
  66. package/Server/Utils/Monitor/MonitoringIntervalValidator.ts +116 -0
  67. package/Server/Utils/Monitor/RootCauseList.ts +139 -0
  68. package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +28 -0
  69. package/Server/Utils/Slo/SloRulePatternValidator.ts +42 -0
  70. package/Server/Utils/Workspace/Slack/Slack.ts +423 -10
  71. package/Tests/App/Accounts/LoginPasskey.test.tsx +18 -0
  72. package/Tests/App/Accounts/LoginSsoEdition.test.tsx +616 -0
  73. package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +217 -0
  74. package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +357 -0
  75. package/Tests/App/AdminDashboard/EnterpriseLicensesShell.test.tsx +214 -0
  76. package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +271 -0
  77. package/Tests/App/AdminDashboard/HealthShells.test.tsx +659 -0
  78. package/Tests/App/Dashboard/AuditLogsAndComplianceShells.test.tsx +572 -0
  79. package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +547 -0
  80. package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +667 -0
  81. package/Tests/App/Dashboard/FeedFilterSortIntegration.test.tsx +1632 -0
  82. package/Tests/App/Dashboard/FeedOptionsLocales.test.ts +250 -0
  83. package/Tests/App/Dashboard/FeedOrdering.test.ts +279 -9
  84. package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +319 -0
  85. package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +60 -1
  86. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +594 -3
  87. package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +185 -0
  88. package/Tests/App/Dashboard/ProductOrientation.test.tsx +646 -0
  89. package/Tests/App/Dashboard/ResourceFeed.test.tsx +612 -2
  90. package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +30 -0
  91. package/Tests/App/Dashboard/ResourceFeedPagesFilterSort.test.tsx +1202 -0
  92. package/Tests/App/Dashboard/ScheduledMaintenanceFeedRefresh.test.tsx +52 -1
  93. package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +45 -9
  94. package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +399 -0
  95. package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +214 -0
  96. package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +1 -83
  97. package/Tests/App/Dashboard/SecurityEventsNavTabs.test.tsx +248 -0
  98. package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +1203 -0
  99. package/Tests/App/Dashboard/SloFeed.test.tsx +106 -1
  100. package/Tests/App/Dashboard/SloMonitorRuleCriteria.test.tsx +566 -0
  101. package/Tests/App/Dashboard/SloNavigationWiring.test.tsx +6 -4
  102. package/Tests/App/Dashboard/SloNoticeBanner.test.tsx +186 -0
  103. package/Tests/App/Dashboard/SloOverviewKpiStrip.test.tsx +388 -44
  104. package/Tests/App/Dashboard/SloOverviewLayout.test.tsx +613 -0
  105. package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +11 -91
  106. package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +319 -0
  107. package/Tests/Helpers/RefreshAwareApiScan.ts +757 -0
  108. package/Tests/Helpers/TenantScopedRequestScan.ts +515 -0
  109. package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +0 -8
  110. package/Tests/Models/DatabaseModels/SloLabelAndOwnerRuleModels.test.ts +404 -0
  111. package/Tests/Models/DatabaseModels/SloOverhaulModels.test.ts +17 -1
  112. package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
  113. package/Tests/Scripts/GenerateServiceWorker.test.ts +931 -0
  114. package/Tests/Server/API/BaseAPICreateItemDoesNotMutateModel.test.ts +130 -0
  115. package/Tests/Server/API/GlobalConfigLicense.test.ts +742 -497
  116. package/Tests/Server/API/OnCallReadinessAPI.test.ts +35 -909
  117. package/Tests/Server/API/SsoProviderListingsEdition.test.ts +432 -0
  118. package/Tests/Server/API/TeamMemberLeaveScimLockEdition.test.ts +252 -0
  119. package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +824 -0
  120. package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +643 -0
  121. package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +294 -0
  122. package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +93 -0
  123. package/Tests/Server/Enterprise/EnterpriseOnlyModulesLiveInEe.test.ts +582 -0
  124. package/Tests/Server/Enterprise/EnterpriseServerModule.test.ts +247 -0
  125. package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +502 -0
  126. package/Tests/Server/Enterprise/TestBillingFlag.ts +70 -0
  127. package/Tests/Server/EnvironmentConfigEnterpriseEdition.test.ts +314 -0
  128. package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +289 -0
  129. package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +5 -1
  130. package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
  131. package/Tests/Server/Infrastructure/Postgres/AddSloLabelAndOwnerRulesMigration.test.ts +407 -0
  132. package/Tests/Server/Infrastructure/Postgres/AddSloMonitorRuleMonitorTypeMigration.test.ts +171 -0
  133. package/Tests/Server/Infrastructure/Postgres/SloProductOverhaulMigration.test.ts +88 -4
  134. package/Tests/Server/Middleware/UserAuthorization.test.ts +37 -2
  135. package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +516 -0
  136. package/Tests/Server/Services/AuditLogService.test.ts +460 -990
  137. package/Tests/Server/Services/CreateAndReadResponsesKeepIds.test.ts +263 -0
  138. package/Tests/Server/Services/DatabaseServiceRuleCriteriaValidation.test.ts +104 -0
  139. package/Tests/Server/Services/EnterpriseLicenseServiceKeyGeneration.test.ts +151 -0
  140. package/Tests/Server/Services/GlobalConfigServiceLicenseColumns.test.ts +357 -0
  141. package/Tests/Server/Services/MonitorDestinationInfoIPv6.test.ts +101 -0
  142. package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +333 -0
  143. package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +303 -0
  144. package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +701 -0
  145. package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +31 -35
  146. package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +48 -1
  147. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -0
  148. package/Tests/Server/Services/ScimPushGroupsTeamLocksEdition.test.ts +431 -0
  149. package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleEngines.test.ts +1170 -0
  150. package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleServices.test.ts +172 -0
  151. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.test.ts +323 -0
  152. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleService.test.ts +115 -0
  153. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleTriggers.test.ts +21 -2
  154. package/Tests/Server/Services/ServiceLevelObjectiveMonitorTypePostgres.test.ts +480 -0
  155. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +162 -0
  156. package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +419 -0
  157. package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +769 -0
  158. package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +45 -6
  159. package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +94 -0
  160. package/Tests/Server/Services/UserAuthenticationService.test.ts +35 -0
  161. package/Tests/Server/Services/UserServiceSeatLimit.test.ts +94 -56
  162. package/Tests/Server/Types/Database/FeedEventTypeFilterQuery.test.ts +745 -0
  163. package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +1823 -0
  164. package/Tests/Server/Types/Markdown.test.ts +183 -1
  165. package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +49 -0
  166. package/Tests/Server/Types/Workflow/Components/TelegramSendMessageToChat.test.ts +331 -0
  167. package/Tests/Server/Utils/AI/SloTools.test.ts +10 -0
  168. package/Tests/Server/Utils/CommunityEditionSsoReport.test.ts +565 -0
  169. package/Tests/Server/Utils/EditionEnforcement.test.ts +303 -0
  170. package/Tests/Server/Utils/FrontendEnvironment.test.ts +367 -0
  171. package/Tests/Server/Utils/InstanceHealth/RedisHealth.test.ts +38 -418
  172. package/Tests/Server/Utils/Monitor/AffectedResourceList.test.ts +518 -0
  173. package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +24 -4
  174. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +1 -1
  175. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +1339 -96
  176. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorBreachingSamples.test.ts +1101 -0
  177. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorMetricUnits.test.ts +106 -80
  178. package/Tests/Server/Utils/Monitor/MonitoringIntervalValidator.test.ts +188 -0
  179. package/Tests/Server/Utils/Monitor/RootCauseList.test.ts +252 -0
  180. package/Tests/Server/Utils/Rules/RuleRun/RuleRunPermission.test.ts +154 -0
  181. package/Tests/Server/Utils/SSRFProtection.test.ts +111 -0
  182. package/Tests/Server/Utils/Slo/SloRulePatternValidator.test.ts +67 -0
  183. package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +213 -0
  184. package/Tests/Server/Utils/Workspace/Slack/SlackMarkdownSectionSplit.test.ts +1209 -0
  185. package/Tests/Types/API/HostnameFromAuthority.test.ts +20 -10
  186. package/Tests/Types/API/HostnameIPv6.test.ts +149 -0
  187. package/Tests/Types/API/Route.test.ts +56 -0
  188. package/Tests/Types/API/URLSchemeLikePath.test.ts +304 -0
  189. package/Tests/Types/Database/CanonicalModelInstance.test.ts +190 -0
  190. package/Tests/UI/Components/EditionLabelLapseCopy.ts +104 -0
  191. package/Tests/UI/Components/EditionLabelLicenseManagerWiring.test.tsx +254 -0
  192. package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +84 -178
  193. package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +1586 -0
  194. package/Tests/UI/Components/EditionLabelLicenseWritesGuard.test.tsx +157 -0
  195. package/Tests/UI/Components/FeedOptions.test.ts +1404 -0
  196. package/Tests/UI/Components/FeedOptionsButton.test.tsx +2603 -0
  197. package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +49 -2
  198. package/Tests/UI/Components/Icon.test.tsx +26 -0
  199. package/Tests/UI/Components/MarkdownConverters.test.ts +684 -0
  200. package/Tests/UI/Components/ModelListEmptyState.test.tsx +289 -0
  201. package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
  202. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerEmptyContent.test.tsx +131 -0
  203. package/Tests/UI/Components/useFeedItemsViewKey.test.tsx +1017 -0
  204. package/Tests/UI/Components/useFeedOptions.test.tsx +1107 -0
  205. package/Tests/UI/EsbuildEnterpriseAlias.test.ts +1127 -0
  206. package/Tests/Utils/HostAddressUtil.test.ts +138 -0
  207. package/Tests/Utils/LabelRuleImportExport.test.ts +102 -0
  208. package/Tests/Utils/Monitor/MonitorDestinationUtil.test.ts +313 -0
  209. package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +304 -0
  210. package/Tests/Utils/Slo/SloDuration.test.ts +115 -24
  211. package/Tests/Utils/Slo/SloHealth.test.ts +93 -10
  212. package/Tests/Utils/Slo/SloMonitorRuleCriteria.test.ts +109 -0
  213. package/Tests/Utils/Slo/SloOverviewText.test.ts +64 -0
  214. package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +248 -0
  215. package/Types/API/Hostname.ts +63 -16
  216. package/Types/API/Route.ts +19 -2
  217. package/Types/API/URL.ts +26 -2
  218. package/Types/Database/AccessControl/ColumnAccessControl.ts +19 -7
  219. package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +19 -7
  220. package/Types/Database/AccessControl/OwnerOnlyColumn.ts +15 -6
  221. package/Types/Database/CanonicalModelInstance.ts +102 -0
  222. package/Types/Database/TableColumn.ts +20 -6
  223. package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +29 -0
  224. package/Types/IP/IPv6.ts +6 -1
  225. package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +6 -5
  226. package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +9 -0
  227. package/Types/Monitor/MonitorStep.ts +6 -1
  228. package/Types/Monitor/ProxmoxAlertTemplates.ts +1 -1
  229. package/Types/Permission.ts +90 -0
  230. package/Types/Rules/RuleCriteriaFieldRegistry.ts +11 -0
  231. package/Types/Rules/RuleRun.ts +4 -0
  232. package/Types/StatusPage/UptimeDailyAggregate.ts +110 -0
  233. package/UI/Components/EditionLabel/EditionLabel.tsx +796 -1195
  234. package/UI/Components/EditionLabel/LicenseManager.ts +119 -0
  235. package/UI/Components/Feed/FeedOptions.ts +427 -0
  236. package/UI/Components/Feed/FeedOptionsButton.tsx +692 -0
  237. package/UI/Components/Feed/useFeedItems.ts +28 -9
  238. package/UI/Components/Feed/useFeedOptions.ts +225 -0
  239. package/UI/Components/Graphs/DayUptimeGraph.tsx +123 -15
  240. package/UI/Components/Icon/Icon.tsx +1 -1
  241. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  242. package/UI/Components/ModelList/ModelList.tsx +11 -1
  243. package/UI/Components/MonitorGraphs/Uptime.tsx +69 -0
  244. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +28 -12
  245. package/UI/esbuild-enterprise.js +263 -0
  246. package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +7 -2
  247. package/Utils/HostAddressUtil.ts +94 -0
  248. package/Utils/LabelRuleImportExport.ts +27 -9
  249. package/Utils/Monitor/MetricValueFormatter.ts +2 -2
  250. package/Utils/Monitor/MonitorDestinationUtil.ts +157 -0
  251. package/Utils/Monitor/MonitoringIntervalUtil.ts +436 -0
  252. package/Utils/Rules/MonitorTypeRuleCriteria.ts +31 -0
  253. package/Utils/Slo/SloDuration.ts +22 -6
  254. package/Utils/Slo/SloHealth.ts +8 -7
  255. package/Utils/Slo/SloMonitorRuleCriteria.ts +33 -1
  256. package/Utils/Slo/SloOverviewText.ts +33 -0
  257. package/Utils/Slo/SloProjection.ts +4 -3
  258. package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +192 -0
  259. package/build/dist/Models/AnalyticsModels/AuditLog.js +23 -15
  260. package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
  261. package/build/dist/Models/DatabaseModels/GlobalConfig.js +25 -0
  262. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  263. package/build/dist/Models/DatabaseModels/Index.js +4 -0
  264. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  265. package/build/dist/Models/DatabaseModels/Monitor.js +2 -2
  266. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  267. package/build/dist/Models/DatabaseModels/MonitorTemplate.js +2 -1
  268. package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
  269. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js +2 -0
  270. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js.map +1 -1
  271. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js +530 -0
  272. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js.map +1 -0
  273. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js +39 -4
  274. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js.map +1 -1
  275. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js +612 -0
  276. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js.map +1 -0
  277. package/build/dist/Server/API/BaseAPI.js +26 -5
  278. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  279. package/build/dist/Server/API/GlobalConfigAPI.js +148 -344
  280. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  281. package/build/dist/Server/API/ProjectOIDC.js +24 -16
  282. package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
  283. package/build/dist/Server/API/ProjectSSO.js +24 -16
  284. package/build/dist/Server/API/ProjectSSO.js.map +1 -1
  285. package/build/dist/Server/API/StatusPageAPI.js +93 -43
  286. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  287. package/build/dist/Server/API/TeamMemberAPI.js +8 -1
  288. package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
  289. package/build/dist/Server/Enterprise/EnterpriseEdition.js +466 -0
  290. package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -0
  291. package/build/dist/Server/Enterprise/EnterpriseFeature.js +39 -0
  292. package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -0
  293. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +70 -0
  294. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js.map +1 -0
  295. package/build/dist/Server/Enterprise/EnterpriseServerModule.js +84 -0
  296. package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -0
  297. package/build/dist/Server/EnvironmentConfig.js +84 -2
  298. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  299. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js +18 -0
  300. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js.map +1 -0
  301. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.js +93 -0
  302. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.js.map +1 -0
  303. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.js +12 -0
  304. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.js.map +1 -0
  305. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  306. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  307. package/build/dist/Server/Middleware/UserAuthorization.js +30 -11
  308. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  309. package/build/dist/Server/Services/AuditLogService.js +71 -740
  310. package/build/dist/Server/Services/AuditLogService.js.map +1 -1
  311. package/build/dist/Server/Services/DatabaseService.js +7 -0
  312. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  313. package/build/dist/Server/Services/EnterpriseLicenseService.js +34 -0
  314. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  315. package/build/dist/Server/Services/GlobalConfigService.js +63 -0
  316. package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
  317. package/build/dist/Server/Services/Index.js +4 -0
  318. package/build/dist/Server/Services/Index.js.map +1 -1
  319. package/build/dist/Server/Services/MonitorProbeService.js +90 -17
  320. package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
  321. package/build/dist/Server/Services/MonitorService.js +48 -6
  322. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  323. package/build/dist/Server/Services/MonitorStatusTimelineService.js +242 -0
  324. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  325. package/build/dist/Server/Services/MonitorTemplateService.js +16 -0
  326. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  327. package/build/dist/Server/Services/ProjectService.js +214 -0
  328. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  329. package/build/dist/Server/Services/RumSessionPinService.js +24 -6
  330. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
  331. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js +295 -0
  332. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js.map +1 -0
  333. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js +56 -0
  334. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js.map +1 -0
  335. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js +59 -14
  336. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js.map +1 -1
  337. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js +22 -1
  338. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js.map +1 -1
  339. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js +400 -0
  340. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js.map +1 -0
  341. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js +56 -0
  342. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js.map +1 -0
  343. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +21 -0
  344. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
  345. package/build/dist/Server/Services/StatusPagePrivateUserService.js +7 -3
  346. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  347. package/build/dist/Server/Services/StatusPageService.js +71 -0
  348. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  349. package/build/dist/Server/Services/TeamMemberService.js +10 -0
  350. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  351. package/build/dist/Server/Services/TeamService.js +9 -0
  352. package/build/dist/Server/Services/TeamService.js.map +1 -1
  353. package/build/dist/Server/Services/UserService.js +10 -16
  354. package/build/dist/Server/Services/UserService.js.map +1 -1
  355. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +10 -0
  356. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
  357. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +154 -14
  358. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
  359. package/build/dist/Server/Types/Database/Permissions/TablePermission.js +10 -3
  360. package/build/dist/Server/Types/Database/Permissions/TablePermission.js.map +1 -1
  361. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +17 -0
  362. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
  363. package/build/dist/Server/Types/Markdown.js +31 -0
  364. package/build/dist/Server/Types/Markdown.js.map +1 -1
  365. package/build/dist/Server/Types/Workflow/Components/Telegram/SendMessageToChat.js +20 -1
  366. package/build/dist/Server/Types/Workflow/Components/Telegram/SendMessageToChat.js.map +1 -1
  367. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +1 -0
  368. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -1
  369. package/build/dist/Server/Utils/CommunityEditionSsoReport.js +223 -0
  370. package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +1 -0
  371. package/build/dist/Server/Utils/EditionEnforcement.js +187 -0
  372. package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -0
  373. package/build/dist/Server/Utils/FrontendEnvironment.js +31 -2
  374. package/build/dist/Server/Utils/FrontendEnvironment.js.map +1 -1
  375. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js +6 -193
  376. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js.map +1 -1
  377. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js +67 -0
  378. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -0
  379. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +1 -1
  380. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
  381. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  382. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +1 -1
  383. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +585 -367
  384. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  385. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js +88 -0
  386. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js.map +1 -0
  387. package/build/dist/Server/Utils/Monitor/RootCauseList.js +101 -0
  388. package/build/dist/Server/Utils/Monitor/RootCauseList.js.map +1 -0
  389. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +28 -0
  390. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
  391. package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js +28 -0
  392. package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js.map +1 -0
  393. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +331 -11
  394. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  395. package/build/dist/Types/API/Hostname.js +59 -11
  396. package/build/dist/Types/API/Hostname.js.map +1 -1
  397. package/build/dist/Types/API/Route.js +18 -2
  398. package/build/dist/Types/API/Route.js.map +1 -1
  399. package/build/dist/Types/API/URL.js +23 -2
  400. package/build/dist/Types/API/URL.js.map +1 -1
  401. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +19 -7
  402. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
  403. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +19 -7
  404. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
  405. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +13 -6
  406. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -1
  407. package/build/dist/Types/Database/CanonicalModelInstance.js +88 -0
  408. package/build/dist/Types/Database/CanonicalModelInstance.js.map +1 -0
  409. package/build/dist/Types/Database/TableColumn.js +19 -6
  410. package/build/dist/Types/Database/TableColumn.js.map +1 -1
  411. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +28 -0
  412. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js.map +1 -0
  413. package/build/dist/Types/IP/IPv6.js +6 -1
  414. package/build/dist/Types/IP/IPv6.js.map +1 -1
  415. package/build/dist/Types/Monitor/MonitorStep.js +5 -0
  416. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  417. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +1 -1
  418. package/build/dist/Types/Permission.js +84 -0
  419. package/build/dist/Types/Permission.js.map +1 -1
  420. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +11 -0
  421. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
  422. package/build/dist/Types/Rules/RuleRun.js +4 -0
  423. package/build/dist/Types/Rules/RuleRun.js.map +1 -1
  424. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js +32 -0
  425. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js.map +1 -0
  426. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +414 -585
  427. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  428. package/build/dist/UI/Components/EditionLabel/LicenseManager.js +2 -0
  429. package/build/dist/UI/Components/EditionLabel/LicenseManager.js.map +1 -0
  430. package/build/dist/UI/Components/Feed/FeedOptions.js +235 -0
  431. package/build/dist/UI/Components/Feed/FeedOptions.js.map +1 -0
  432. package/build/dist/UI/Components/Feed/FeedOptionsButton.js +346 -0
  433. package/build/dist/UI/Components/Feed/FeedOptionsButton.js.map +1 -0
  434. package/build/dist/UI/Components/Feed/useFeedItems.js +17 -7
  435. package/build/dist/UI/Components/Feed/useFeedItems.js.map +1 -1
  436. package/build/dist/UI/Components/Feed/useFeedOptions.js +130 -0
  437. package/build/dist/UI/Components/Feed/useFeedOptions.js.map +1 -0
  438. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +90 -17
  439. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
  440. package/build/dist/UI/Components/Icon/Icon.js +1 -1
  441. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  442. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  443. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  444. package/build/dist/UI/Components/ModelList/ModelList.js +4 -1
  445. package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
  446. package/build/dist/UI/Components/MonitorGraphs/Uptime.js +42 -1
  447. package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
  448. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +2 -2
  449. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  450. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +6 -2
  451. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
  452. package/build/dist/Utils/HostAddressUtil.js +80 -0
  453. package/build/dist/Utils/HostAddressUtil.js.map +1 -0
  454. package/build/dist/Utils/LabelRuleImportExport.js +22 -6
  455. package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
  456. package/build/dist/Utils/Monitor/MetricValueFormatter.js +2 -2
  457. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js +127 -0
  458. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js.map +1 -0
  459. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js +374 -0
  460. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js.map +1 -0
  461. package/build/dist/Utils/Rules/MonitorTypeRuleCriteria.js +18 -0
  462. package/build/dist/Utils/Rules/MonitorTypeRuleCriteria.js.map +1 -0
  463. package/build/dist/Utils/Slo/SloDuration.js +13 -5
  464. package/build/dist/Utils/Slo/SloDuration.js.map +1 -1
  465. package/build/dist/Utils/Slo/SloHealth.js +8 -7
  466. package/build/dist/Utils/Slo/SloHealth.js.map +1 -1
  467. package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js +16 -1
  468. package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js.map +1 -1
  469. package/build/dist/Utils/Slo/SloOverviewText.js +16 -0
  470. package/build/dist/Utils/Slo/SloOverviewText.js.map +1 -1
  471. package/build/dist/Utils/Slo/SloProjection.js.map +1 -1
  472. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js +148 -0
  473. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js.map +1 -0
  474. package/jest.config.json +3 -1
  475. package/package.json +1 -1
  476. package/test-setup.sh +103 -34
  477. package/tsconfig.json +13 -0
  478. package/Server/API/EnterpriseLicenseAPI.ts +0 -925
  479. package/Server/API/TeamComplianceAPI.ts +0 -158
  480. package/Server/Middleware/SCIMAuthorization.ts +0 -141
  481. package/Server/Services/TeamComplianceService.ts +0 -733
  482. package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +0 -186
  483. package/Server/Utils/InstanceHealth/PostgresHealth.ts +0 -286
  484. package/Tests/App/AdminDashboard/EnterpriseLicenseInstanceActivity.test.tsx +0 -451
  485. package/Tests/App/Dashboard/AuditLogsTable.test.tsx +0 -598
  486. package/Tests/App/Dashboard/SecurityEventsExplorer.test.tsx +0 -761
  487. package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +0 -247
  488. package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +0 -382
  489. package/Tests/App/Dashboard/SecurityEventsVolumeChart.test.tsx +0 -321
  490. package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +0 -1851
  491. package/Tests/Server/Middleware/SCIMAuthorization.test.ts +0 -525
  492. package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +0 -1845
  493. package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +0 -495
  494. package/Tests/Server/Utils/InstanceHealth/PostgresHealth.test.ts +0 -337
  495. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +0 -576
  496. package/Tests/Utils/EnterpriseLicenseSync.test.ts +0 -568
  497. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +0 -287
  498. package/Utils/EnterpriseLicense/EnterpriseLicenseSync.ts +0 -244
  499. package/build/dist/Server/API/EnterpriseLicenseAPI.js +0 -646
  500. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +0 -1
  501. package/build/dist/Server/API/TeamComplianceAPI.js +0 -111
  502. package/build/dist/Server/API/TeamComplianceAPI.js.map +0 -1
  503. package/build/dist/Server/Middleware/SCIMAuthorization.js +0 -124
  504. package/build/dist/Server/Middleware/SCIMAuthorization.js.map +0 -1
  505. package/build/dist/Server/Services/TeamComplianceService.js +0 -537
  506. package/build/dist/Server/Services/TeamComplianceService.js.map +0 -1
  507. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +0 -145
  508. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +0 -1
  509. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js +0 -194
  510. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js.map +0 -1
  511. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +0 -168
  512. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +0 -1
  513. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js +0 -174
  514. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js.map +0 -1
@@ -207,6 +207,47 @@ export default class Markdown {
207
207
  );
208
208
  };
209
209
 
210
+ /*
211
+ * Lists. A platform monitor's root cause lists its affected resources
212
+ * as a numbered list with a bullet list of details nested under each
213
+ * item, and the cluster and metric details above it are bullets too.
214
+ *
215
+ * Left to the client, Gmail and Apple Mail indent every list level by
216
+ * 40px — close to a tenth of the card, twice over for a nested list —
217
+ * and Outlook's Word engine ignores padding on <ul>/<ol> and picks its
218
+ * own margins. So the indent is a margin-left, which Outlook honours,
219
+ * with padding zeroed: 24px holds a bullet, and 32px holds a numbered
220
+ * marker up to three digits ("100."). The vertical margins give each
221
+ * item's nested details a little air above and a gap below that
222
+ * separates it from the next item.
223
+ *
224
+ * margin-left is a physical side, so it is followed by the logical
225
+ * margin-inline-start / -end: a client that understands them moves
226
+ * the indent to the marker side in right-to-left text, and one that
227
+ * does not keeps the margin-left.
228
+ */
229
+ renderer.list = function (
230
+ body: string,
231
+ ordered: boolean,
232
+ start: number | "",
233
+ ): string {
234
+ const tag: string = ordered ? "ol" : "ul";
235
+ const startAttribute: string =
236
+ ordered && start !== "" && start !== 1 ? ` start="${start}"` : "";
237
+ const indent: string = ordered ? "32px" : "24px";
238
+
239
+ return (
240
+ `<${tag}${startAttribute} style="margin:6px 0 12px 0;` +
241
+ `margin-left:${indent};margin-inline-start:${indent};` +
242
+ `margin-inline-end:0;padding:0;">` +
243
+ `${body}</${tag}>`
244
+ );
245
+ };
246
+
247
+ renderer.listitem = function (text: string): string {
248
+ return `<li style="margin:0 0 4px;padding:0;">${text}</li>`;
249
+ };
250
+
210
251
  /*
211
252
  * The root cause backticks metric names, aliases and timestamps. Left
212
253
  * bare they were indistinguishable from the prose around them.
@@ -13,7 +13,17 @@ import TelegramComponents from "../../../../../Types/Workflow/Components/Telegra
13
13
  import API from "../../../../../Utils/API";
14
14
  import CaptureSpan from "../../../../Utils/Telemetry/CaptureSpan";
15
15
 
16
+ /*
17
+ * https://core.telegram.org/bots/api#authorizing-your-bot — a numeric bot id,
18
+ * a ":", then the secret, e.g. "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11".
19
+ */
20
+ const TELEGRAM_BOT_TOKEN_REGEX: RegExp = /^\d+:[A-Za-z0-9_-]+$/;
21
+
16
22
  export default class SendMessageToChat extends ComponentCode {
23
+ public static isValidBotToken(botToken: string): boolean {
24
+ return TELEGRAM_BOT_TOKEN_REGEX.test(botToken);
25
+ }
26
+
17
27
  public constructor() {
18
28
  super();
19
29
 
@@ -69,10 +79,26 @@ export default class SendMessageToChat extends ComponentCode {
69
79
  throw options.onError(new BadDataException("Telegram message not found"));
70
80
  }
71
81
 
72
- const botToken: string = args["bot-token"]?.toString() as string;
82
+ // A token pasted or stored with a trailing newline is still the token.
83
+ const botToken: string = (args["bot-token"]?.toString() || "").trim();
73
84
  const chatId: string = args["chat-id"]?.toString() as string;
74
85
  const text: string = args["text"]?.toString() as string;
75
86
 
87
+ /*
88
+ * The token becomes a path segment of the request URL, so anything other
89
+ * than Telegram's "<bot id>:<secret>" shape is refused before it gets
90
+ * there. The message deliberately does not quote the value: the step's
91
+ * error is written to the run log, and the token is a credential. Before
92
+ * this check, a URL parse failure put the whole token into the log.
93
+ */
94
+ if (!SendMessageToChat.isValidBotToken(botToken)) {
95
+ throw options.onError(
96
+ new BadDataException(
97
+ "Telegram Bot Token is not in a valid format. It should look like 123456789:ABCdefGhIJKlmnoPQRstuVWxyz, exactly as BotFather issued it.",
98
+ ),
99
+ );
100
+ }
101
+
76
102
  const telegramApiUrl: URL = URL.fromString(
77
103
  `https://api.telegram.org/bot${botToken}/sendMessage`,
78
104
  );
@@ -382,6 +382,7 @@ export const QuerySlosTool: ObservabilityTool = {
382
382
  _id: true,
383
383
  name: true,
384
384
  },
385
+ monitorType: true,
385
386
  monitorNamePattern: true,
386
387
  monitorDescriptionPattern: true,
387
388
  criteria: true,
@@ -0,0 +1,361 @@
1
+ import EnterpriseEdition, {
2
+ EnterpriseFeatureStateChange,
3
+ } from "../Enterprise/EnterpriseEdition";
4
+ import EnterpriseFeature from "../Enterprise/EnterpriseFeature";
5
+ import {
6
+ ENTERPRISE_LICENSE_GRACE_PERIOD_IN_DAYS,
7
+ ENTERPRISE_LICENSE_TRIAL_PERIOD_IN_DAYS,
8
+ } from "../Enterprise/EnterpriseLicenseSnapshot";
9
+ import GlobalConfigService from "../Services/GlobalConfigService";
10
+ import ProjectSCIMService from "../Services/ProjectSCIMService";
11
+ import ProjectService from "../Services/ProjectService";
12
+ import StatusPageService from "../Services/StatusPageService";
13
+ import logger from "./Logger";
14
+ import PositiveNumber from "../../Types/PositiveNumber";
15
+ import Project from "../../Models/DatabaseModels/Project";
16
+ import ProjectSCIM from "../../Models/DatabaseModels/ProjectSCIM";
17
+ import StatusPage from "../../Models/DatabaseModels/StatusPage";
18
+
19
+ // How many ids of each kind the log line names; the counts are always exact.
20
+ export const MAX_IDS_LISTED_PER_KIND: number = 20;
21
+
22
+ /*
23
+ * The SSO requirements and SCIM team locks that are configured but not
24
+ * enforced (see EditionEnforcement): left over from an Enterprise Edition
25
+ * install on a Community Edition process, or configured on an Enterprise
26
+ * install whose license has lapsed.
27
+ */
28
+ export interface RelaxedEnforcementSummary {
29
+ instanceRequiresSso: boolean;
30
+ projectsRequiringSso: number;
31
+ projectIdsRequiringSso: Array<string>;
32
+ statusPagesRequiringSso: number;
33
+ statusPageIdsRequiringSso: Array<string>;
34
+ scimConfigurationsWithPushGroups: number;
35
+ projectIdsWithScimPushGroups: Array<string>;
36
+ }
37
+
38
+ /*
39
+ * Why the settings in a report are not enforced:
40
+ *
41
+ * community a Community Edition process, which has no SSO login and
42
+ * no SCIM endpoint at all;
43
+ * lapsed-license an Enterprise install whose license no longer covers SSO
44
+ * and/or SCIM (EnterpriseEdition.isFeatureActive). Only the
45
+ * relaxed half is reported.
46
+ */
47
+ export type RelaxedEnforcementContext =
48
+ | { reason: "community" }
49
+ | { reason: "lapsed-license"; isSsoRelaxed: boolean; isScimRelaxed: boolean };
50
+
51
+ const COMMUNITY_CONTEXT: RelaxedEnforcementContext = { reason: "community" };
52
+
53
+ /*
54
+ * Tells the operator which configured security settings this server is not
55
+ * enforcing, so that never happens silently:
56
+ *
57
+ * - Community Edition: moving from the Enterprise image to the Community
58
+ * one keeps the database as it is, so a project that required SSO still
59
+ * says so - but the SSO login routes are part of the Enterprise Edition,
60
+ * so the requirement is relaxed rather than locking everyone out. Logged
61
+ * once per process at boot.
62
+ * - Enterprise Edition: when the license lapses, SSO and SCIM stop and the
63
+ * same settings are relaxed until a license is activated. Logged each time
64
+ * SSO or SCIM stops (EnterpriseEdition reports each change once),
65
+ * including a license that has already lapsed at boot.
66
+ */
67
+ export default class CommunityEditionSsoReport {
68
+ private static hasRun: boolean = false;
69
+
70
+ private static stopWatchingLicense: (() => void) | null = null;
71
+
72
+ /*
73
+ * Called once at boot, after the enterprise loader. On the Community
74
+ * Edition it logs the relaxed settings once per process. On the Enterprise
75
+ * Edition it starts watching the license (once per process) and reports
76
+ * whenever SSO or SCIM stops. Never throws: a failed check is logged and
77
+ * boot carries on. Returns what the Community Edition report found (null
78
+ * when it did not run or the check failed).
79
+ */
80
+ public static async logRelaxedEnforcementOnce(): Promise<RelaxedEnforcementSummary | null> {
81
+ if (EnterpriseEdition.isLoaded()) {
82
+ CommunityEditionSsoReport.watchLicenseOnce();
83
+ return null;
84
+ }
85
+
86
+ if (CommunityEditionSsoReport.hasRun) {
87
+ return null;
88
+ }
89
+
90
+ CommunityEditionSsoReport.hasRun = true;
91
+
92
+ return await CommunityEditionSsoReport.report(COMMUNITY_CONTEXT);
93
+ }
94
+
95
+ /*
96
+ * Collects and logs the relaxed settings. Never throws. Returns what it
97
+ * found (null when the check failed).
98
+ */
99
+ public static async report(
100
+ context: RelaxedEnforcementContext,
101
+ ): Promise<RelaxedEnforcementSummary | null> {
102
+ try {
103
+ const summary: RelaxedEnforcementSummary =
104
+ await CommunityEditionSsoReport.collect();
105
+
106
+ const message: string | null = CommunityEditionSsoReport.describe(
107
+ summary,
108
+ context,
109
+ );
110
+
111
+ if (message) {
112
+ logger.warn(message);
113
+ }
114
+
115
+ return summary;
116
+ } catch (err) {
117
+ logger.error(
118
+ context.reason === "community"
119
+ ? "Community Edition: could not check for SSO requirements and SCIM team locks left over from an Enterprise Edition install."
120
+ : "OneUptime Enterprise license lapsed: could not check which SSO requirements and SCIM team locks are no longer enforced.",
121
+ );
122
+ logger.error(err);
123
+ return null;
124
+ }
125
+ }
126
+
127
+ /*
128
+ * Watches the Enterprise license for SSO or SCIM stopping, once per
129
+ * process. The first look happens here, so a license that has already
130
+ * lapsed at boot is reported like a lapse at runtime.
131
+ */
132
+ private static watchLicenseOnce(): void {
133
+ if (CommunityEditionSsoReport.stopWatchingLicense) {
134
+ return;
135
+ }
136
+
137
+ CommunityEditionSsoReport.stopWatchingLicense =
138
+ EnterpriseEdition.onFeatureStateChange(
139
+ (change: EnterpriseFeatureStateChange): void => {
140
+ CommunityEditionSsoReport.onFeatureStateChange(change);
141
+ },
142
+ );
143
+
144
+ try {
145
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
146
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SCIM);
147
+ } catch (err) {
148
+ logger.error(err);
149
+ }
150
+ }
151
+
152
+ private static onFeatureStateChange(
153
+ change: EnterpriseFeatureStateChange,
154
+ ): void {
155
+ const isSsoRelaxed: boolean = change.stopped.includes(
156
+ EnterpriseFeature.SSO,
157
+ );
158
+ const isScimRelaxed: boolean = change.stopped.includes(
159
+ EnterpriseFeature.SCIM,
160
+ );
161
+
162
+ if (!isSsoRelaxed && !isScimRelaxed) {
163
+ return;
164
+ }
165
+
166
+ void CommunityEditionSsoReport.report({
167
+ reason: "lapsed-license",
168
+ isSsoRelaxed,
169
+ isScimRelaxed,
170
+ });
171
+ }
172
+
173
+ // Reads the stored (not the masked) settings. Root reads are never masked.
174
+ public static async collect(): Promise<RelaxedEnforcementSummary> {
175
+ const [
176
+ instanceRequiresSso,
177
+ projectCount,
178
+ projects,
179
+ statusPageCount,
180
+ statusPages,
181
+ scimCount,
182
+ scimConfigurations,
183
+ ]: [
184
+ boolean,
185
+ PositiveNumber,
186
+ Array<Project>,
187
+ PositiveNumber,
188
+ Array<StatusPage>,
189
+ PositiveNumber,
190
+ Array<ProjectSCIM>,
191
+ ] = await Promise.all([
192
+ GlobalConfigService.getRequireSsoForLogin(),
193
+ ProjectService.countBy({
194
+ query: { requireSsoForLogin: true },
195
+ props: { isRoot: true },
196
+ }),
197
+ ProjectService.findBy({
198
+ query: { requireSsoForLogin: true },
199
+ select: { _id: true },
200
+ limit: MAX_IDS_LISTED_PER_KIND,
201
+ skip: 0,
202
+ props: { isRoot: true },
203
+ }),
204
+ StatusPageService.countBy({
205
+ query: { requireSsoForLogin: true },
206
+ props: { isRoot: true },
207
+ }),
208
+ StatusPageService.findBy({
209
+ query: { requireSsoForLogin: true },
210
+ select: { _id: true },
211
+ limit: MAX_IDS_LISTED_PER_KIND,
212
+ skip: 0,
213
+ props: { isRoot: true },
214
+ }),
215
+ ProjectSCIMService.countBy({
216
+ query: { enablePushGroups: true },
217
+ props: { isRoot: true },
218
+ }),
219
+ ProjectSCIMService.findBy({
220
+ query: { enablePushGroups: true },
221
+ select: { projectId: true },
222
+ limit: MAX_IDS_LISTED_PER_KIND,
223
+ skip: 0,
224
+ props: { isRoot: true },
225
+ }),
226
+ ]);
227
+
228
+ return {
229
+ instanceRequiresSso: Boolean(instanceRequiresSso),
230
+ projectsRequiringSso: projectCount.toNumber(),
231
+ projectIdsRequiringSso: CommunityEditionSsoReport.toIds(
232
+ projects.map((project: Project) => {
233
+ return project.id?.toString() || project._id?.toString();
234
+ }),
235
+ ),
236
+ statusPagesRequiringSso: statusPageCount.toNumber(),
237
+ statusPageIdsRequiringSso: CommunityEditionSsoReport.toIds(
238
+ statusPages.map((statusPage: StatusPage) => {
239
+ return statusPage.id?.toString() || statusPage._id?.toString();
240
+ }),
241
+ ),
242
+ scimConfigurationsWithPushGroups: scimCount.toNumber(),
243
+ projectIdsWithScimPushGroups: CommunityEditionSsoReport.toIds(
244
+ scimConfigurations.map((scim: ProjectSCIM) => {
245
+ return scim.projectId?.toString();
246
+ }),
247
+ ),
248
+ };
249
+ }
250
+
251
+ // The log line, or null when nothing is relaxed.
252
+ public static describe(
253
+ summary: RelaxedEnforcementSummary,
254
+ context: RelaxedEnforcementContext = COMMUNITY_CONTEXT,
255
+ ): string | null {
256
+ const isSsoRelaxed: boolean =
257
+ context.reason === "community" || context.isSsoRelaxed;
258
+ const isScimRelaxed: boolean =
259
+ context.reason === "community" || context.isScimRelaxed;
260
+
261
+ const relaxed: Array<string> = [];
262
+
263
+ if (isSsoRelaxed && summary.instanceRequiresSso) {
264
+ relaxed.push(
265
+ 'the instance-wide "Require SSO for Login" setting (Admin Dashboard > Settings > Authentication)',
266
+ );
267
+ }
268
+
269
+ if (isSsoRelaxed && summary.projectsRequiringSso > 0) {
270
+ relaxed.push(
271
+ `${summary.projectsRequiringSso} project(s) that require SSO for login${CommunityEditionSsoReport.describeIds(
272
+ summary.projectIdsRequiringSso,
273
+ summary.projectsRequiringSso,
274
+ )}`,
275
+ );
276
+ }
277
+
278
+ if (isSsoRelaxed && summary.statusPagesRequiringSso > 0) {
279
+ relaxed.push(
280
+ `${summary.statusPagesRequiringSso} private status page(s) that require SSO for login${CommunityEditionSsoReport.describeIds(
281
+ summary.statusPageIdsRequiringSso,
282
+ summary.statusPagesRequiringSso,
283
+ )}`,
284
+ );
285
+ }
286
+
287
+ if (isScimRelaxed && summary.scimConfigurationsWithPushGroups > 0) {
288
+ relaxed.push(
289
+ `${summary.scimConfigurationsWithPushGroups} SCIM configuration(s) with Push Groups on, whose teams can be edited in OneUptime again${CommunityEditionSsoReport.describeIds(
290
+ summary.projectIdsWithScimPushGroups,
291
+ summary.scimConfigurationsWithPushGroups,
292
+ "project ids",
293
+ )}`,
294
+ );
295
+ }
296
+
297
+ if (relaxed.length === 0) {
298
+ return null;
299
+ }
300
+
301
+ if (context.reason === "lapsed-license") {
302
+ const stopped: string =
303
+ isSsoRelaxed && isScimRelaxed
304
+ ? "SSO login and SCIM provisioning have"
305
+ : isSsoRelaxed
306
+ ? "SSO login has"
307
+ : "SCIM provisioning has";
308
+
309
+ return (
310
+ "OneUptime Enterprise license lapsed: this server has security settings that it no longer enforces, " +
311
+ `because ${stopped} stopped until a license that includes ${isSsoRelaxed && isScimRelaxed ? "them" : "it"} is activated. ` +
312
+ (isSsoRelaxed
313
+ ? "Users of these projects and status pages sign in with email and password instead (users who only ever signed in with SSO can reset their password). "
314
+ : "") +
315
+ `Not enforced: ${relaxed.join("; ")}. ` +
316
+ "The settings are kept unchanged and are enforced again as soon as a license is activated, without a restart."
317
+ );
318
+ }
319
+
320
+ return (
321
+ "Community Edition: this server has security settings from an Enterprise Edition install that it does not enforce, " +
322
+ "because SSO login and SCIM provisioning are part of the OneUptime Enterprise Edition. " +
323
+ "Users of these projects and status pages sign in with email and password instead. " +
324
+ `Not enforced: ${relaxed.join("; ")}. ` +
325
+ `The settings are kept unchanged and are enforced again when this server runs the Enterprise Edition image with a valid license (or during its ${ENTERPRISE_LICENSE_TRIAL_PERIOD_IN_DAYS}-day trial, or the ${ENTERPRISE_LICENSE_GRACE_PERIOD_IN_DAYS}-day grace period after a license expires).`
326
+ );
327
+ }
328
+
329
+ // Test suites only: allow the next call to run again and stop watching.
330
+ public static resetForTests(): void {
331
+ CommunityEditionSsoReport.hasRun = false;
332
+
333
+ if (CommunityEditionSsoReport.stopWatchingLicense) {
334
+ CommunityEditionSsoReport.stopWatchingLicense();
335
+ CommunityEditionSsoReport.stopWatchingLicense = null;
336
+ }
337
+ }
338
+
339
+ private static toIds(values: Array<string | undefined>): Array<string> {
340
+ return values
341
+ .filter((value: string | undefined): value is string => {
342
+ return Boolean(value);
343
+ })
344
+ .slice(0, MAX_IDS_LISTED_PER_KIND);
345
+ }
346
+
347
+ private static describeIds(
348
+ ids: Array<string>,
349
+ total: number,
350
+ label: string = "ids",
351
+ ): string {
352
+ if (ids.length === 0) {
353
+ return "";
354
+ }
355
+
356
+ const more: string =
357
+ total > ids.length ? ` and ${total - ids.length} more` : "";
358
+
359
+ return ` (${label}: ${ids.join(", ")}${more})`;
360
+ }
361
+ }
@@ -0,0 +1,233 @@
1
+ import EnterpriseEdition from "../Enterprise/EnterpriseEdition";
2
+ import EnterpriseFeature from "../Enterprise/EnterpriseFeature";
3
+ import {
4
+ ENTERPRISE_LICENSE_GRACE_PERIOD_IN_DAYS,
5
+ ENTERPRISE_LICENSE_TRIAL_PERIOD_IN_DAYS,
6
+ } from "../Enterprise/EnterpriseLicenseSnapshot";
7
+ import logger from "./Logger";
8
+ import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
9
+ import PaymentRequiredException from "../../Types/Exception/PaymentRequiredException";
10
+
11
+ /*
12
+ * Which enterprise identity controls are live in this process.
13
+ *
14
+ * Every answer here follows the RUNTIME state of the feature behind it
15
+ * (EnterpriseEdition.isFeatureActive): SSO for the SSO requirements, the
16
+ * SAML/OIDC sign-in routes and the provider listings, SCIM for the SCIM Push
17
+ * Groups team locks. A feature is active when the Enterprise Edition is loaded
18
+ * and, with billing off, its license covers the feature (valid, in the grace
19
+ * period after it expired, or - with no license - inside the trial).
20
+ *
21
+ * The controls are relaxed where they cannot work:
22
+ * - on the Community Edition, which has no SAML/OIDC sign-in routes and no
23
+ * SCIM endpoints;
24
+ * - on an Enterprise install whose license has lapsed, where those routes
25
+ * refuse (ee/Server/Identity).
26
+ * Enforcing a leftover "Require SSO for login" there would lock every user
27
+ * out, and a leftover SCIM Push Groups lock would leave teams nobody can
28
+ * manage. Users sign in with their password instead (users who only ever used
29
+ * SSO reset it). The configuration itself is kept untouched - reads made for
30
+ * a caller report the requirement as off, and a caller's write can neither
31
+ * switch it off nor set it meanwhile (guardSsoRequirementWrite) - so running
32
+ * the Enterprise Edition again (with a valid license, or during its trial or
33
+ * grace period), or renewing the license, restores enforcement without a
34
+ * restart.
35
+ *
36
+ * Failure direction: an error while deciding answers "enforce", and an
37
+ * unknown license state counts as active (see isFeatureActive), so a read
38
+ * error never switches a control off.
39
+ */
40
+ export default class EditionEnforcement {
41
+ // Why guardSsoRequirementWrite refuses a write, on the Community Edition.
42
+ public static readonly SSO_REQUIREMENT_UNCHANGEABLE_COMMUNITY_MESSAGE: string =
43
+ 'Single sign-on is part of the OneUptime Enterprise Edition and this server runs the Community Edition, so "Require SSO for login" shows as off, is not enforced and cannot be changed here. ' +
44
+ `A setting saved earlier is kept, and it is enforced again when this server runs the Enterprise Edition image with a valid license (or during its ${ENTERPRISE_LICENSE_TRIAL_PERIOD_IN_DAYS}-day trial, or the ${ENTERPRISE_LICENSE_GRACE_PERIOD_IN_DAYS}-day grace period after a license expires).`;
45
+
46
+ /*
47
+ * Why guardSsoRequirementWrite refuses a write, on an Enterprise install
48
+ * whose license does not cover SSO right now.
49
+ */
50
+ public static readonly SSO_REQUIREMENT_UNCHANGEABLE_LICENSE_MESSAGE: string =
51
+ 'Single sign-on has stopped because the OneUptime Enterprise license is missing, expired or does not include SSO, so "Require SSO for login" shows as off, is not enforced and cannot be changed. ' +
52
+ "The saved setting is kept, and it is enforced again as soon as a master admin activates or renews the license from the edition label in the Admin Dashboard header.";
53
+
54
+ /*
55
+ * Whether configured SSO requirements - a project's requireSsoForLogin (and
56
+ * its required provider), the instance-wide requireSsoForLogin and a status
57
+ * page's requireSsoForLogin - are enforced.
58
+ */
59
+ public static isSsoEnforced(): boolean {
60
+ try {
61
+ return EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
62
+ } catch (err) {
63
+ logger.error(
64
+ "EditionEnforcement: could not tell whether SSO is enforced; enforcing it.",
65
+ );
66
+ logger.error(err);
67
+ return true;
68
+ }
69
+ }
70
+
71
+ // A configured SSO requirement that is also enforced in this process.
72
+ public static isSsoRequired(
73
+ configuredRequirement: boolean | null | undefined,
74
+ ): boolean {
75
+ if (!configuredRequirement) {
76
+ return false;
77
+ }
78
+
79
+ return EditionEnforcement.isSsoEnforced();
80
+ }
81
+
82
+ /*
83
+ * Whether SCIM Push Groups owns team membership: while a project's SCIM
84
+ * configuration has Push Groups on, teams and team members can only be
85
+ * changed by the identity provider. Relaxed on the Community Edition, and
86
+ * while the license does not cover SCIM, because then no SCIM endpoint
87
+ * answers the identity provider and nobody else could manage those teams.
88
+ */
89
+ public static areScimTeamLocksEnforced(): boolean {
90
+ try {
91
+ return EnterpriseEdition.isFeatureActive(EnterpriseFeature.SCIM);
92
+ } catch (err) {
93
+ logger.error(
94
+ "EditionEnforcement: could not tell whether SCIM team locks apply; applying them.",
95
+ );
96
+ logger.error(err);
97
+ return true;
98
+ }
99
+ }
100
+
101
+ /*
102
+ * Whether the SAML/OIDC sign-in routes answer right now. Provider listings
103
+ * (the lists a sign-in page offers) are empty when they do not, so no client
104
+ * sends a user into a route that answers 404 (Community Edition) or refuses
105
+ * because the license lapsed (Enterprise Edition).
106
+ */
107
+ public static areSsoRoutesServed(): boolean {
108
+ try {
109
+ return EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
110
+ } catch (err) {
111
+ logger.error(
112
+ "EditionEnforcement: could not tell whether the SSO routes are served; serving them.",
113
+ );
114
+ logger.error(err);
115
+ return true;
116
+ }
117
+ }
118
+
119
+ /*
120
+ * Whether a read should report the EFFECTIVE SSO requirement (false)
121
+ * instead of the stored one. Clients - the mobile app in particular, whose
122
+ * store builds cannot be patched - decide from these columns whether to
123
+ * start an SSO flow, and while SSO is not active that flow does not exist
124
+ * (Community Edition) or refuses (lapsed license).
125
+ *
126
+ * Only reads made for a caller are masked. Internal (root) reads see the
127
+ * stored value, and a read never writes, so the configuration is intact
128
+ * when SSO is active again. The write half is guardSsoRequirementWrite.
129
+ */
130
+ public static shouldMaskSsoRequirementOnRead(
131
+ props: DatabaseCommonInteractionProps | null | undefined,
132
+ ): boolean {
133
+ if (!props || props.isRoot) {
134
+ return false;
135
+ }
136
+
137
+ return !EditionEnforcement.isSsoEnforced();
138
+ }
139
+
140
+ /*
141
+ * The write half of shouldMaskSsoRequirementOnRead, for the services'
142
+ * onBeforeUpdate. A caller whose reads are masked has only ever seen the
143
+ * requirement as off (no required provider), so what it writes to those
144
+ * columns cannot be taken at face value: a settings form, or an API client
145
+ * doing a read-modify-write, sends back the masked value it read. Saving it
146
+ * would switch a configured requirement off without anybody deciding to,
147
+ * and it would stay off once SSO is active again.
148
+ *
149
+ * So while this caller's reads are masked:
150
+ * - a write of the masked value (false, or no provider) is dropped from
151
+ * `data`, and the stored requirement is kept;
152
+ * - a write that would set a requirement (true, or a provider) is
153
+ * refused: it could neither be seen nor enforced until SSO is active;
154
+ * - a write that is left with nothing else to save is refused with the
155
+ * same explanation, rather than reporting a save that did not happen.
156
+ *
157
+ * Root writes, and every write while SSO is active, are left alone.
158
+ * Mutates `data`. Throws PaymentRequiredException.
159
+ */
160
+ public static guardSsoRequirementWrite(input: {
161
+ props: DatabaseCommonInteractionProps | null | undefined;
162
+ data: Record<string, unknown>;
163
+ // The requirement columns of the model being written.
164
+ columns: ReadonlyArray<string>;
165
+ }): void {
166
+ if (!EditionEnforcement.shouldMaskSsoRequirementOnRead(input.props)) {
167
+ return;
168
+ }
169
+
170
+ const writtenColumns: Array<string> = input.columns.filter(
171
+ (column: string): boolean => {
172
+ return input.data[column] !== undefined;
173
+ },
174
+ );
175
+
176
+ if (writtenColumns.length === 0) {
177
+ return;
178
+ }
179
+
180
+ const setsRequirement: boolean = writtenColumns.some(
181
+ (column: string): boolean => {
182
+ return !EditionEnforcement.isMaskedSsoRequirementValue(
183
+ input.data[column],
184
+ );
185
+ },
186
+ );
187
+
188
+ if (setsRequirement) {
189
+ throw EditionEnforcement.createSsoRequirementUnchangeableException();
190
+ }
191
+
192
+ for (const column of writtenColumns) {
193
+ delete input.data[column];
194
+ }
195
+
196
+ /*
197
+ * `data` is the plain update onBeforeUpdate receives (a model instance
198
+ * has already been reduced to its set columns by
199
+ * DatabaseService.sanitizeUpdateData); a key left undefined writes
200
+ * nothing, so it does not count.
201
+ */
202
+ const hasOtherColumns: boolean = Object.keys(input.data).some(
203
+ (key: string): boolean => {
204
+ return input.data[key] !== undefined;
205
+ },
206
+ );
207
+
208
+ if (!hasOtherColumns) {
209
+ throw EditionEnforcement.createSsoRequirementUnchangeableException();
210
+ }
211
+ }
212
+
213
+ // What a masked read reports for a requirement column: false or null.
214
+ private static isMaskedSsoRequirementValue(value: unknown): boolean {
215
+ return value === false || value === null;
216
+ }
217
+
218
+ private static createSsoRequirementUnchangeableException(): PaymentRequiredException {
219
+ let isEnterpriseEditionLoaded: boolean = true;
220
+
221
+ try {
222
+ isEnterpriseEditionLoaded = EnterpriseEdition.isLoaded();
223
+ } catch (err) {
224
+ logger.error(err);
225
+ }
226
+
227
+ return new PaymentRequiredException(
228
+ isEnterpriseEditionLoaded
229
+ ? EditionEnforcement.SSO_REQUIREMENT_UNCHANGEABLE_LICENSE_MESSAGE
230
+ : EditionEnforcement.SSO_REQUIREMENT_UNCHANGEABLE_COMMUNITY_MESSAGE,
231
+ );
232
+ }
233
+ }