@oneuptime/common 12.0.13 → 12.0.14

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 (376) hide show
  1. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +14 -0
  2. package/Models/DatabaseModels/UserCall.ts +94 -3
  3. package/Models/DatabaseModels/UserEmail.ts +94 -3
  4. package/Models/DatabaseModels/UserIncomingCallNumber.ts +94 -3
  5. package/Models/DatabaseModels/UserPush.ts +37 -0
  6. package/Models/DatabaseModels/UserSMS.ts +94 -3
  7. package/Models/DatabaseModels/UserWhatsApp.ts +93 -2
  8. package/Server/API/BaseAPI.ts +79 -14
  9. package/Server/API/UserCallAPI.ts +53 -45
  10. package/Server/API/UserEmailAPI.ts +53 -44
  11. package/Server/API/UserIncomingCallNumberAPI.ts +48 -38
  12. package/Server/API/UserNotificationMethodAdminAPI.ts +481 -0
  13. package/Server/API/UserPushAPI.ts +126 -2
  14. package/Server/API/UserSmsAPI.ts +53 -44
  15. package/Server/API/UserWhatsAppAPI.ts +53 -50
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.ts +154 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.ts +17 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.ts +45 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  20. package/Server/Middleware/VerificationCodeRateLimit.ts +586 -0
  21. package/Server/Services/AnalyticsDatabaseService.ts +169 -0
  22. package/Server/Services/DatabaseService.ts +101 -0
  23. package/Server/Services/LogAggregationService.ts +5 -0
  24. package/Server/Services/PushNotificationService.ts +127 -12
  25. package/Server/Services/TeamMemberService.ts +53 -13
  26. package/Server/Services/UserCallService.ts +55 -24
  27. package/Server/Services/UserEmailService.ts +83 -17
  28. package/Server/Services/UserIncomingCallNumberService.ts +49 -85
  29. package/Server/Services/UserNotificationMethodAdminService.ts +1527 -0
  30. package/Server/Services/UserNotificationRuleService.ts +26 -0
  31. package/Server/Services/UserPushService.ts +89 -0
  32. package/Server/Services/UserSmsService.ts +50 -17
  33. package/Server/Services/UserWhatsAppService.ts +48 -15
  34. package/Server/Types/Database/QueryHelper.ts +30 -0
  35. package/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.ts +59 -0
  36. package/Server/Utils/ChannelVerification.ts +510 -0
  37. package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +13 -16
  38. package/Server/Utils/Monitor/MonitorAlert.ts +24 -21
  39. package/Server/Utils/Monitor/MonitorIncident.ts +21 -18
  40. package/Server/Utils/Monitor/MonitorResourceContext.ts +107 -0
  41. package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +442 -0
  42. package/Server/Utils/Monitor/SeriesResourceLabels.ts +3 -3
  43. package/Server/Utils/Monitor/SeriesResourceLinker.ts +96 -28
  44. package/Server/Utils/TotpAuth.ts +137 -9
  45. package/Server/Utils/UserRegistrationToken.ts +182 -0
  46. package/Server/Utils/VerificationCode.ts +134 -0
  47. package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +173 -94
  48. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +1151 -0
  49. package/Tests/App/Dashboard/AdminUserOnCallPages.test.tsx +905 -0
  50. package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +338 -0
  51. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1 -1
  52. package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +28 -0
  53. package/Tests/Models/UserPushCriticalAlertColumn.test.ts +172 -0
  54. package/Tests/Server/API/BaseAPIGetListParallel.test.ts +519 -0
  55. package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +543 -0
  56. package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +108 -18
  57. package/Tests/Server/API/UserNotificationMethodAdminAPI.test.ts +963 -0
  58. package/Tests/Server/API/UserPushCriticalAlertsApi.test.ts +114 -0
  59. package/Tests/Server/API/UserSmsApi.test.ts +107 -14
  60. package/Tests/Server/API/UserTotpAuthAPI.test.ts +427 -0
  61. package/Tests/Server/Infrastructure/Postgres/FixTotpOtpUrlAlgorithmMigration.test.ts +315 -0
  62. package/Tests/Server/Middleware/VerificationCodeRateLimit.test.ts +775 -0
  63. package/Tests/Server/Services/AddNetworkDeviceReachabilityColumnsMigration.test.ts +10 -62
  64. package/Tests/Server/Services/AnalyticsDatabasePaginationStability.test.ts +33 -13
  65. package/Tests/Server/Services/AnalyticsDatabaseSortKeyBoundary.test.ts +658 -0
  66. package/Tests/Server/Services/CriticalOnCallAlertDelivery.test.ts +458 -0
  67. package/Tests/Server/Services/CriticalPushAlertPayload.test.ts +301 -0
  68. package/Tests/Server/Services/DatabaseServiceAtomicIncrement.test.ts +143 -0
  69. package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1 -0
  70. package/Tests/Server/Services/LogAggregationScanMemory.test.ts +421 -0
  71. package/Tests/Server/Services/LogAggregationService.test.ts +2 -2
  72. package/Tests/Server/Services/NotificationChannelCodeIssuance.test.ts +401 -0
  73. package/Tests/Server/Services/PushNotificationDeliveryOptions.test.ts +204 -0
  74. package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +21 -1
  75. package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +290 -0
  76. package/Tests/Server/Services/UserNotificationMethodAdminService.test.ts +948 -0
  77. package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1 -0
  78. package/Tests/Server/Services/UserPushCriticalAlertToggle.test.ts +255 -0
  79. package/Tests/Server/Services/UserTotpAuthEnrolment.test.ts +218 -0
  80. package/Tests/Server/TestingUtils/AuthenticatorApp.ts +248 -0
  81. package/Tests/Server/Types/Database/Permissions/NotificationChannelVerificationColumns.test.ts +135 -0
  82. package/Tests/Server/Types/Database/Permissions/OnCallScheduleRelationSelect.test.ts +504 -0
  83. package/Tests/Server/Types/Database/QueryHelperFindWithSameTextAnyOf.test.ts +91 -0
  84. package/Tests/Server/Types/Workflow/Components/JsonToText.test.ts +384 -0
  85. package/Tests/Server/Types/Workflow/Components/MergeJson.test.ts +403 -0
  86. package/Tests/Server/Utils/Browser.test.ts +162 -0
  87. package/Tests/Server/Utils/ChannelVerification.test.ts +689 -0
  88. package/Tests/Server/Utils/Express.test.ts +371 -0
  89. package/Tests/Server/Utils/Monitor/Criteria/CustomCodeMonitorCriteria.test.ts +707 -0
  90. package/Tests/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.test.ts +698 -0
  91. package/Tests/Server/Utils/Monitor/Criteria/IncomingEmailBodyCriteria.test.ts +243 -0
  92. package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestBodyCriteria.test.ts +278 -0
  93. package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +160 -20
  94. package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +13 -8
  95. package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +162 -18
  96. package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +349 -0
  97. package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +690 -0
  98. package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +7 -2
  99. package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +92 -18
  100. package/Tests/Server/Utils/PushNotificationUtilCreators.test.ts +267 -0
  101. package/Tests/Server/Utils/Telemetry/OneuptimeLabel.test.ts +439 -0
  102. package/Tests/Server/Utils/TotpAuth.test.ts +719 -0
  103. package/Tests/Server/Utils/UserRegistrationToken.test.ts +322 -0
  104. package/Tests/Server/Utils/VerificationCode.test.ts +296 -0
  105. package/Tests/Types/AutoRemediation/AutoRemediationSuggestionStatus.test.ts +192 -0
  106. package/Tests/Types/Call/CallRequest.test.ts +189 -0
  107. package/Tests/Types/Dashboard/DashboardSize.test.ts +226 -0
  108. package/Tests/Types/Incident/IncidentSlaStatus.test.ts +191 -0
  109. package/Tests/Types/Metrics/MetricDashboardMetricType.test.ts +278 -0
  110. package/Tests/Types/Metrics/MetricPipelineRuleType.test.ts +517 -0
  111. package/Tests/Types/Monitor/IncomingMonitorDefaultCriteria.test.ts +470 -0
  112. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +6 -4
  113. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +262 -5
  114. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +1 -1
  115. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +1 -1
  116. package/Tests/Types/Monitor/ServiceAlertTemplates.test.ts +905 -0
  117. package/Tests/Types/Service/ServiceLanguage.test.ts +255 -0
  118. package/Tests/Types/TextRandomGeneration.test.ts +211 -0
  119. package/Tests/UI/Components/Button.test.tsx +175 -1
  120. package/Tests/UI/Components/CodeBlockLanguages.test.tsx +236 -0
  121. package/Tests/UI/Components/CommandPalette/CommandPalette.test.tsx +568 -0
  122. package/Tests/UI/Components/CommandPalette/CommandPaletteKeyboard.test.tsx +239 -0
  123. package/Tests/UI/Components/CommandPalette/CommandPaletteProviders.test.tsx +400 -0
  124. package/Tests/UI/Components/CommandPalette/PaletteFilter.test.ts +234 -0
  125. package/Tests/UI/Components/CommandPalette/RecentCommands.test.ts +97 -0
  126. package/Tests/UI/Components/CountModelSideMenuItemGuard.test.tsx +198 -0
  127. package/Tests/UI/Components/FeedItemSafeMode.test.tsx +1 -1
  128. package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +267 -0
  129. package/Tests/UI/Components/List.test.tsx +9 -2
  130. package/Tests/UI/Components/ListLoadingStates.test.tsx +173 -0
  131. package/Tests/UI/Components/MarkdownLazy.test.tsx +113 -0
  132. package/Tests/UI/Components/MarkdownMermaidRetry.test.tsx +110 -0
  133. package/Tests/UI/Components/ModelTable/useCustomFieldColumns.test.tsx +8 -0
  134. package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +692 -0
  135. package/Tests/UI/Components/MoreMenuMotion.test.tsx +118 -0
  136. package/Tests/UI/Components/NavBarCommandKGating.test.tsx +178 -0
  137. package/Tests/UI/Components/OrderedStatesList.test.tsx +19 -2
  138. package/Tests/UI/Components/SideOverMotion.test.tsx +109 -0
  139. package/Tests/UI/Components/Skeleton.test.tsx +71 -0
  140. package/Tests/UI/Components/TableLoadingStates.test.tsx +279 -0
  141. package/Tests/UI/Components/Tabs.test.tsx +24 -0
  142. package/Tests/UI/Components/Toast.test.tsx +130 -7
  143. package/Tests/UI/Components/ToastStacking.test.tsx +198 -0
  144. package/Tests/UI/Utils/Dropdown.test.ts +423 -0
  145. package/Tests/UI/Utils/ModelAPITenantHeader.test.ts +122 -0
  146. package/Tests/UI/Utils/ModelListCache.test.ts +338 -0
  147. package/Tests/UI/Utils/ProjectListCacheInvalidation.test.ts +225 -0
  148. package/Tests/Utils/API.test.ts +16 -2
  149. package/Tests/Utils/Dashboard/Components/DashboardKubernetesResourceListShared.test.ts +347 -0
  150. package/Tests/Utils/Dashboard/Components/DashboardListSharedArgs.test.ts +259 -0
  151. package/Tests/Utils/Dashboard/Components/DashboardMonitorListComponent.test.ts +466 -0
  152. package/Tests/Utils/Rum/UrlScrubberSegments.test.ts +362 -0
  153. package/Types/Email/EmailTemplateType.ts +1 -0
  154. package/Types/Monitor/MonitorCriteriaInstance.ts +41 -20
  155. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +131 -8
  156. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +48 -8
  157. package/Types/Monitor/ServiceAlertTemplates.ts +1352 -0
  158. package/Types/Permission.ts +35 -0
  159. package/Types/PushNotification/AndroidNotificationChannel.ts +26 -0
  160. package/Types/PushNotification/PushNotificationMessage.ts +15 -0
  161. package/Types/PushNotification/PushNotificationRequest.ts +8 -16
  162. package/Types/Service/ServiceLanguage.ts +144 -0
  163. package/Types/Text.ts +111 -19
  164. package/UI/Components/Button/Button.tsx +27 -14
  165. package/UI/Components/CodeBlock/CodeBlock.tsx +54 -7
  166. package/UI/Components/CodeBlock/LanguageRegistry.ts +103 -0
  167. package/UI/Components/CommandPalette/CommandPalette.tsx +790 -0
  168. package/UI/Components/CommandPalette/PaletteFilter.ts +196 -0
  169. package/UI/Components/CommandPalette/PaletteRow.tsx +173 -0
  170. package/UI/Components/CommandPalette/RecentCommands.ts +57 -0
  171. package/UI/Components/CommandPalette/Types.ts +49 -0
  172. package/UI/Components/CommandPalette/UseProviderSearch.ts +129 -0
  173. package/UI/Components/Dropdown/Dropdown.tsx +6 -1
  174. package/UI/Components/Feed/FeedItem.tsx +1 -1
  175. package/UI/Components/List/List.tsx +37 -5
  176. package/UI/Components/List/ListSkeleton.tsx +54 -0
  177. package/UI/Components/Markdown.tsx/LazyMarkdownViewer.tsx +6 -1
  178. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +71 -26
  179. package/UI/Components/Modal/Modal.tsx +2 -2
  180. package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
  181. package/UI/Components/ModelTable/useCustomFieldColumns.ts +11 -5
  182. package/UI/Components/MoreMenu/MoreMenu.tsx +39 -1
  183. package/UI/Components/Navbar/NavBar.tsx +14 -1
  184. package/UI/Components/OrderedStatesList/OrderedStatesList.tsx +50 -5
  185. package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +40 -1
  186. package/UI/Components/SideOver/SideOver.tsx +37 -2
  187. package/UI/Components/Skeleton/Skeleton.tsx +53 -0
  188. package/UI/Components/Table/Table.tsx +74 -44
  189. package/UI/Components/Table/TableSkeletonRows.tsx +141 -0
  190. package/UI/Components/Tabs/Tab.tsx +1 -1
  191. package/UI/Components/Toast/Toast.tsx +118 -53
  192. package/UI/Components/Toast/ToastInit.tsx +82 -32
  193. package/UI/Styles/Theme.css +40 -0
  194. package/UI/Utils/ModelAPI/ModelAPI.ts +20 -10
  195. package/UI/Utils/ModelListCache.ts +188 -0
  196. package/UI/Utils/Project.ts +29 -0
  197. package/Utils/API.ts +6 -1
  198. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +14 -0
  199. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  200. package/build/dist/Models/DatabaseModels/UserCall.js +101 -3
  201. package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
  202. package/build/dist/Models/DatabaseModels/UserEmail.js +101 -3
  203. package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
  204. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js +101 -3
  205. package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js.map +1 -1
  206. package/build/dist/Models/DatabaseModels/UserPush.js +38 -0
  207. package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
  208. package/build/dist/Models/DatabaseModels/UserSMS.js +101 -3
  209. package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
  210. package/build/dist/Models/DatabaseModels/UserWhatsApp.js +100 -2
  211. package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
  212. package/build/dist/Server/API/BaseAPI.js +69 -13
  213. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  214. package/build/dist/Server/API/UserCallAPI.js +42 -38
  215. package/build/dist/Server/API/UserCallAPI.js.map +1 -1
  216. package/build/dist/Server/API/UserEmailAPI.js +42 -38
  217. package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
  218. package/build/dist/Server/API/UserIncomingCallNumberAPI.js +37 -32
  219. package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
  220. package/build/dist/Server/API/UserNotificationMethodAdminAPI.js +341 -0
  221. package/build/dist/Server/API/UserNotificationMethodAdminAPI.js.map +1 -0
  222. package/build/dist/Server/API/UserPushAPI.js +95 -2
  223. package/build/dist/Server/API/UserPushAPI.js.map +1 -1
  224. package/build/dist/Server/API/UserSmsAPI.js +42 -38
  225. package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
  226. package/build/dist/Server/API/UserWhatsAppAPI.js +42 -40
  227. package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
  228. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js +89 -0
  229. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js.map +1 -0
  230. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js +12 -0
  231. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js.map +1 -0
  232. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js +40 -0
  233. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js.map +1 -0
  234. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  235. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  236. package/build/dist/Server/Middleware/VerificationCodeRateLimit.js +393 -0
  237. package/build/dist/Server/Middleware/VerificationCodeRateLimit.js.map +1 -0
  238. package/build/dist/Server/Services/AnalyticsDatabaseService.js +136 -0
  239. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  240. package/build/dist/Server/Services/DatabaseService.js +74 -0
  241. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  242. package/build/dist/Server/Services/LogAggregationService.js +5 -0
  243. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  244. package/build/dist/Server/Services/PushNotificationService.js +69 -30
  245. package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
  246. package/build/dist/Server/Services/TeamMemberService.js +43 -7
  247. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  248. package/build/dist/Server/Services/UserCallService.js +54 -22
  249. package/build/dist/Server/Services/UserCallService.js.map +1 -1
  250. package/build/dist/Server/Services/UserEmailService.js +78 -17
  251. package/build/dist/Server/Services/UserEmailService.js.map +1 -1
  252. package/build/dist/Server/Services/UserIncomingCallNumberService.js +45 -74
  253. package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -1
  254. package/build/dist/Server/Services/UserNotificationMethodAdminService.js +1117 -0
  255. package/build/dist/Server/Services/UserNotificationMethodAdminService.js.map +1 -0
  256. package/build/dist/Server/Services/UserNotificationRuleService.js +20 -0
  257. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  258. package/build/dist/Server/Services/UserPushService.js +77 -0
  259. package/build/dist/Server/Services/UserPushService.js.map +1 -1
  260. package/build/dist/Server/Services/UserSmsService.js +50 -17
  261. package/build/dist/Server/Services/UserSmsService.js.map +1 -1
  262. package/build/dist/Server/Services/UserWhatsAppService.js +48 -15
  263. package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
  264. package/build/dist/Server/Types/Database/QueryHelper.js +27 -0
  265. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  266. package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js +46 -0
  267. package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js.map +1 -1
  268. package/build/dist/Server/Utils/ChannelVerification.js +348 -0
  269. package/build/dist/Server/Utils/ChannelVerification.js.map +1 -0
  270. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +13 -12
  271. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
  272. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +20 -17
  273. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  274. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +17 -14
  275. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  276. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +95 -0
  277. package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -0
  278. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +313 -0
  279. package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -0
  280. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +3 -3
  281. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +67 -26
  282. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
  283. package/build/dist/Server/Utils/TotpAuth.js +127 -8
  284. package/build/dist/Server/Utils/TotpAuth.js.map +1 -1
  285. package/build/dist/Server/Utils/UserRegistrationToken.js +170 -0
  286. package/build/dist/Server/Utils/UserRegistrationToken.js.map +1 -0
  287. package/build/dist/Server/Utils/VerificationCode.js +120 -0
  288. package/build/dist/Server/Utils/VerificationCode.js.map +1 -0
  289. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  290. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  291. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +42 -21
  292. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  293. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +77 -5
  294. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
  295. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +18 -6
  296. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
  297. package/build/dist/Types/Monitor/ServiceAlertTemplates.js +1028 -0
  298. package/build/dist/Types/Monitor/ServiceAlertTemplates.js.map +1 -0
  299. package/build/dist/Types/Permission.js +33 -0
  300. package/build/dist/Types/Permission.js.map +1 -1
  301. package/build/dist/Types/PushNotification/AndroidNotificationChannel.js +27 -0
  302. package/build/dist/Types/PushNotification/AndroidNotificationChannel.js.map +1 -0
  303. package/build/dist/Types/Service/ServiceLanguage.js +96 -0
  304. package/build/dist/Types/Service/ServiceLanguage.js.map +1 -0
  305. package/build/dist/Types/Text.js +82 -17
  306. package/build/dist/Types/Text.js.map +1 -1
  307. package/build/dist/UI/Components/Button/Button.js +22 -14
  308. package/build/dist/UI/Components/Button/Button.js.map +1 -1
  309. package/build/dist/UI/Components/CodeBlock/CodeBlock.js +35 -3
  310. package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
  311. package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js +57 -0
  312. package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js.map +1 -0
  313. package/build/dist/UI/Components/CommandPalette/CommandPalette.js +439 -0
  314. package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -0
  315. package/build/dist/UI/Components/CommandPalette/PaletteFilter.js +135 -0
  316. package/build/dist/UI/Components/CommandPalette/PaletteFilter.js.map +1 -0
  317. package/build/dist/UI/Components/CommandPalette/PaletteRow.js +83 -0
  318. package/build/dist/UI/Components/CommandPalette/PaletteRow.js.map +1 -0
  319. package/build/dist/UI/Components/CommandPalette/RecentCommands.js +47 -0
  320. package/build/dist/UI/Components/CommandPalette/RecentCommands.js.map +1 -0
  321. package/build/dist/UI/Components/CommandPalette/Types.js +2 -0
  322. package/build/dist/UI/Components/CommandPalette/Types.js.map +1 -0
  323. package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js +88 -0
  324. package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js.map +1 -0
  325. package/build/dist/UI/Components/Dropdown/Dropdown.js +6 -1
  326. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  327. package/build/dist/UI/Components/Feed/FeedItem.js +1 -1
  328. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
  329. package/build/dist/UI/Components/List/List.js +19 -5
  330. package/build/dist/UI/Components/List/List.js.map +1 -1
  331. package/build/dist/UI/Components/List/ListSkeleton.js +21 -0
  332. package/build/dist/UI/Components/List/ListSkeleton.js.map +1 -0
  333. package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js.map +1 -1
  334. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +52 -25
  335. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  336. package/build/dist/UI/Components/Modal/Modal.js +2 -2
  337. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
  338. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  339. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +9 -2
  340. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -1
  341. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +32 -1
  342. package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
  343. package/build/dist/UI/Components/Navbar/NavBar.js +5 -1
  344. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  345. package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js +29 -5
  346. package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js.map +1 -1
  347. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js +23 -1
  348. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
  349. package/build/dist/UI/Components/SideOver/SideOver.js +23 -2
  350. package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
  351. package/build/dist/UI/Components/Skeleton/Skeleton.js +23 -0
  352. package/build/dist/UI/Components/Skeleton/Skeleton.js.map +1 -0
  353. package/build/dist/UI/Components/Table/Table.js +35 -24
  354. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  355. package/build/dist/UI/Components/Table/TableSkeletonRows.js +52 -0
  356. package/build/dist/UI/Components/Table/TableSkeletonRows.js.map +1 -0
  357. package/build/dist/UI/Components/Tabs/Tab.js +1 -1
  358. package/build/dist/UI/Components/Tabs/Tab.js.map +1 -1
  359. package/build/dist/UI/Components/Toast/Toast.js +77 -23
  360. package/build/dist/UI/Components/Toast/Toast.js.map +1 -1
  361. package/build/dist/UI/Components/Toast/ToastInit.js +37 -15
  362. package/build/dist/UI/Components/Toast/ToastInit.js.map +1 -1
  363. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -9
  364. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  365. package/build/dist/UI/Utils/ModelListCache.js +126 -0
  366. package/build/dist/UI/Utils/ModelListCache.js.map +1 -0
  367. package/build/dist/UI/Utils/Project.js +24 -1
  368. package/build/dist/UI/Utils/Project.js.map +1 -1
  369. package/build/dist/Utils/API.js +6 -1
  370. package/build/dist/Utils/API.js.map +1 -1
  371. package/jest.config.json +1 -1
  372. package/package.json +2 -3
  373. package/Server/Utils/Monitor/MonitorClusterContext.ts +0 -182
  374. package/Tests/__mocks__/otpauth.js +0 -30
  375. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +0 -141
  376. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +0 -1
@@ -1,21 +1,44 @@
1
1
  import UserMiddleware from "../Middleware/UserAuthorization";
2
+ import VerificationCodeRateLimit, {
3
+ VerificationCodeRateLimitBucket,
4
+ } from "../Middleware/VerificationCodeRateLimit";
2
5
  import UserSMSService, {
3
6
  Service as UserSMSServiceType,
4
7
  } from "../Services/UserSmsService";
5
- import UserNotificationRuleService from "../Services/UserNotificationRuleService";
6
8
  import {
7
9
  ExpressRequest,
8
10
  ExpressResponse,
9
11
  NextFunction,
10
12
  OneUptimeRequest,
11
13
  } from "../Utils/Express";
14
+ import ChannelVerification, {
15
+ ChannelVerificationOutcome,
16
+ ChannelVerificationResult,
17
+ } from "../Utils/ChannelVerification";
12
18
  import Response from "../Utils/Response";
13
- import logger, { getLogAttributesFromRequest } from "../Utils/Logger";
14
19
  import BaseAPI from "./BaseAPI";
15
20
  import BadDataException from "../../Types/Exception/BadDataException";
16
21
  import ObjectID from "../../Types/ObjectID";
17
22
  import UserSMS from "../../Models/DatabaseModels/UserSMS";
23
+ import UserNotificationRuleService from "../Services/UserNotificationRuleService";
24
+ import logger, { getLogAttributesFromRequest } from "../Utils/Logger";
18
25
 
26
+ /*
27
+ * The verify and resend routes for this notification channel.
28
+ *
29
+ * Neither the checking of a submitted code nor the issuing of a new one lives
30
+ * here, on purpose. The state machine is shared by all five channels
31
+ * (Common/Server/Utils/ChannelVerification.ts) so that a control added for one
32
+ * of them cannot quietly go missing on another — which is exactly what went
33
+ * wrong before: five hand-written copies of "compare the column, set
34
+ * isVerified", none of which expired the code, counted attempts, or refused a
35
+ * caller running the comparison a million times against somebody else's phone
36
+ * number.
37
+ *
38
+ * What is left here is the HTTP shape: reject malformed bodies, run the rate
39
+ * limiter before anything costs a database read, and turn the outcome into a
40
+ * response.
41
+ */
19
42
  export default class UserSMSAPI extends BaseAPI<UserSMS, UserSMSServiceType> {
20
43
  public constructor() {
21
44
  super(UserSMS, UserSMSService);
@@ -23,6 +46,9 @@ export default class UserSMSAPI extends BaseAPI<UserSMS, UserSMSServiceType> {
23
46
  this.router.post(
24
47
  `/user-sms/verify`,
25
48
  UserMiddleware.getUserMiddleware,
49
+ VerificationCodeRateLimit.getMiddleware(
50
+ VerificationCodeRateLimitBucket.Verify,
51
+ ),
26
52
  async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
27
53
  try {
28
54
  req = req as OneUptimeRequest;
@@ -43,33 +69,10 @@ export default class UserSMSAPI extends BaseAPI<UserSMS, UserSMSServiceType> {
43
69
  );
44
70
  }
45
71
 
46
- // Check if the code matches and verify the phone number.
47
- const item: UserSMS | null = await this.service.findOneById({
48
- id: req.body["itemId"],
49
- props: {
50
- isRoot: true,
51
- },
52
- select: {
53
- userId: true,
54
- projectId: true,
55
- verificationCode: true,
56
- },
57
- });
58
-
59
- if (!item) {
60
- return Response.sendErrorResponse(
61
- req,
62
- res,
63
- new BadDataException("Item not found"),
64
- );
65
- }
66
-
67
- //check user id
72
+ const userId: ObjectID | undefined = (req as OneUptimeRequest)
73
+ ?.userAuthorization?.userId;
68
74
 
69
- if (
70
- item.userId?.toString() !==
71
- (req as OneUptimeRequest)?.userAuthorization?.userId?.toString()
72
- ) {
75
+ if (!userId) {
73
76
  return Response.sendErrorResponse(
74
77
  req,
75
78
  res,
@@ -77,32 +80,30 @@ export default class UserSMSAPI extends BaseAPI<UserSMS, UserSMSServiceType> {
77
80
  );
78
81
  }
79
82
 
80
- if (item.verificationCode !== req.body["code"]) {
83
+ const result: ChannelVerificationResult =
84
+ await ChannelVerification.verifyCode({
85
+ service: this.service,
86
+ itemId: new ObjectID(req.body["itemId"].toString()),
87
+ userId: userId,
88
+ code: req.body["code"].toString(),
89
+ });
90
+
91
+ if (result.outcome !== ChannelVerificationOutcome.Verified) {
81
92
  return Response.sendErrorResponse(
82
93
  req,
83
94
  res,
84
- new BadDataException("Invalid code"),
95
+ ChannelVerification.getFailureException(result.outcome),
85
96
  );
86
97
  }
87
98
 
88
- await this.service.updateOneById({
89
- id: item.id!,
90
- props: {
91
- isRoot: true,
92
- },
93
- data: {
94
- isVerified: true,
95
- },
96
- });
97
-
98
- // Create default notification rules for this verified SMS
99
+ /* Create default notification rules for this verified SMS number */
99
100
  try {
100
101
  await UserNotificationRuleService.addDefaultNotificationRulesForVerifiedMethod(
101
102
  {
102
- projectId: new ObjectID(item.projectId!.toString()),
103
- userId: new ObjectID(item.userId!.toString()),
103
+ projectId: new ObjectID(result.projectId!.toString()),
104
+ userId: new ObjectID(result.userId!.toString()),
104
105
  notificationMethod: {
105
- userSmsId: item.id!,
106
+ userSmsId: result.itemId!,
106
107
  },
107
108
  },
108
109
  );
@@ -123,6 +124,9 @@ export default class UserSMSAPI extends BaseAPI<UserSMS, UserSMSServiceType> {
123
124
  this.router.post(
124
125
  `/user-sms/resend-verification-code`,
125
126
  UserMiddleware.getUserMiddleware,
127
+ VerificationCodeRateLimit.getMiddleware(
128
+ VerificationCodeRateLimitBucket.Resend,
129
+ ),
126
130
  async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
127
131
  try {
128
132
  req = req as OneUptimeRequest;
@@ -153,6 +157,11 @@ export default class UserSMSAPI extends BaseAPI<UserSMS, UserSMSServiceType> {
153
157
  );
154
158
  }
155
159
 
160
+ /*
161
+ * A caller may only ask for a code to be sent to a row they own.
162
+ * Without this the resend route is a way to make somebody else's
163
+ * device ring on demand.
164
+ */
156
165
  if (
157
166
  item.userId?.toString() !==
158
167
  (req as OneUptimeRequest)?.userAuthorization?.userId?.toString()
@@ -1,21 +1,44 @@
1
1
  import UserMiddleware from "../Middleware/UserAuthorization";
2
+ import VerificationCodeRateLimit, {
3
+ VerificationCodeRateLimitBucket,
4
+ } from "../Middleware/VerificationCodeRateLimit";
2
5
  import UserWhatsAppService, {
3
6
  Service as UserWhatsAppServiceType,
4
7
  } from "../Services/UserWhatsAppService";
5
- import UserNotificationRuleService from "../Services/UserNotificationRuleService";
6
8
  import {
7
9
  ExpressRequest,
8
10
  ExpressResponse,
9
11
  NextFunction,
10
12
  OneUptimeRequest,
11
13
  } from "../Utils/Express";
14
+ import ChannelVerification, {
15
+ ChannelVerificationOutcome,
16
+ ChannelVerificationResult,
17
+ } from "../Utils/ChannelVerification";
12
18
  import Response from "../Utils/Response";
13
- import logger, { getLogAttributesFromRequest } from "../Utils/Logger";
14
19
  import BaseAPI from "./BaseAPI";
15
20
  import BadDataException from "../../Types/Exception/BadDataException";
16
21
  import ObjectID from "../../Types/ObjectID";
17
22
  import UserWhatsApp from "../../Models/DatabaseModels/UserWhatsApp";
23
+ import UserNotificationRuleService from "../Services/UserNotificationRuleService";
24
+ import logger, { getLogAttributesFromRequest } from "../Utils/Logger";
18
25
 
26
+ /*
27
+ * The verify and resend routes for this notification channel.
28
+ *
29
+ * Neither the checking of a submitted code nor the issuing of a new one lives
30
+ * here, on purpose. The state machine is shared by all five channels
31
+ * (Common/Server/Utils/ChannelVerification.ts) so that a control added for one
32
+ * of them cannot quietly go missing on another — which is exactly what went
33
+ * wrong before: five hand-written copies of "compare the column, set
34
+ * isVerified", none of which expired the code, counted attempts, or refused a
35
+ * caller running the comparison a million times against somebody else's phone
36
+ * number.
37
+ *
38
+ * What is left here is the HTTP shape: reject malformed bodies, run the rate
39
+ * limiter before anything costs a database read, and turn the outcome into a
40
+ * response.
41
+ */
19
42
  export default class UserWhatsAppAPI extends BaseAPI<
20
43
  UserWhatsApp,
21
44
  UserWhatsAppServiceType
@@ -26,6 +49,9 @@ export default class UserWhatsAppAPI extends BaseAPI<
26
49
  this.router.post(
27
50
  `${new this.entityType().getCrudApiPath()?.toString()}/verify`,
28
51
  UserMiddleware.getUserMiddleware,
52
+ VerificationCodeRateLimit.getMiddleware(
53
+ VerificationCodeRateLimitBucket.Verify,
54
+ ),
29
55
  async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
30
56
  try {
31
57
  req = req as OneUptimeRequest;
@@ -46,39 +72,10 @@ export default class UserWhatsAppAPI extends BaseAPI<
46
72
  );
47
73
  }
48
74
 
49
- const item: UserWhatsApp | null = await this.service.findOneById({
50
- id: req.body["itemId"],
51
- props: {
52
- isRoot: true,
53
- },
54
- select: {
55
- userId: true,
56
- projectId: true,
57
- verificationCode: true,
58
- isVerified: true,
59
- },
60
- });
75
+ const userId: ObjectID | undefined = (req as OneUptimeRequest)
76
+ ?.userAuthorization?.userId;
61
77
 
62
- if (!item) {
63
- return Response.sendErrorResponse(
64
- req,
65
- res,
66
- new BadDataException("Item not found"),
67
- );
68
- }
69
-
70
- if (item.isVerified) {
71
- return Response.sendErrorResponse(
72
- req,
73
- res,
74
- new BadDataException("WhatsApp number already verified"),
75
- );
76
- }
77
-
78
- if (
79
- item.userId?.toString() !==
80
- (req as OneUptimeRequest)?.userAuthorization?.userId?.toString()
81
- ) {
78
+ if (!userId) {
82
79
  return Response.sendErrorResponse(
83
80
  req,
84
81
  res,
@@ -86,32 +83,30 @@ export default class UserWhatsAppAPI extends BaseAPI<
86
83
  );
87
84
  }
88
85
 
89
- if (item.verificationCode !== req.body["code"]) {
86
+ const result: ChannelVerificationResult =
87
+ await ChannelVerification.verifyCode({
88
+ service: this.service,
89
+ itemId: new ObjectID(req.body["itemId"].toString()),
90
+ userId: userId,
91
+ code: req.body["code"].toString(),
92
+ });
93
+
94
+ if (result.outcome !== ChannelVerificationOutcome.Verified) {
90
95
  return Response.sendErrorResponse(
91
96
  req,
92
97
  res,
93
- new BadDataException("Invalid code"),
98
+ ChannelVerification.getFailureException(result.outcome),
94
99
  );
95
100
  }
96
101
 
97
- await this.service.updateOneById({
98
- id: item.id!,
99
- props: {
100
- isRoot: true,
101
- },
102
- data: {
103
- isVerified: true,
104
- },
105
- });
106
-
107
- // Create default notification rules for this verified WhatsApp number
102
+ /* Create default notification rules for this verified WhatsApp number */
108
103
  try {
109
104
  await UserNotificationRuleService.addDefaultNotificationRulesForVerifiedMethod(
110
105
  {
111
- projectId: new ObjectID(item.projectId!.toString()),
112
- userId: new ObjectID(item.userId!.toString()),
106
+ projectId: new ObjectID(result.projectId!.toString()),
107
+ userId: new ObjectID(result.userId!.toString()),
113
108
  notificationMethod: {
114
- userWhatsAppId: item.id!,
109
+ userWhatsAppId: result.itemId!,
115
110
  },
116
111
  },
117
112
  );
@@ -134,6 +129,9 @@ export default class UserWhatsAppAPI extends BaseAPI<
134
129
  .getCrudApiPath()
135
130
  ?.toString()}/resend-verification-code`,
136
131
  UserMiddleware.getUserMiddleware,
132
+ VerificationCodeRateLimit.getMiddleware(
133
+ VerificationCodeRateLimitBucket.Resend,
134
+ ),
137
135
  async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
138
136
  try {
139
137
  req = req as OneUptimeRequest;
@@ -164,6 +162,11 @@ export default class UserWhatsAppAPI extends BaseAPI<
164
162
  );
165
163
  }
166
164
 
165
+ /*
166
+ * A caller may only ask for a code to be sent to a row they own.
167
+ * Without this the resend route is a way to make somebody else's
168
+ * device ring on demand.
169
+ */
167
170
  if (
168
171
  item.userId?.toString() !==
169
172
  (req as OneUptimeRequest)?.userAuthorization?.userId?.toString()
@@ -0,0 +1,154 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ /*
4
+ * GHSA-5cr8-vph4-3hrf: expiry, attempt counting and resend throttling for the
5
+ * notification-channel verification codes.
6
+ *
7
+ * Three columns per channel table:
8
+ *
9
+ * verificationCodeExpiresAt NULL means there is no live code. Every row
10
+ * that exists when this runs gets NULL, which
11
+ * is read as expired — so the plaintext codes
12
+ * those rows are carrying stop being accepted
13
+ * the moment this lands, and their owners
14
+ * press "resend" once. That is the intended
15
+ * behaviour, not a side effect: those codes
16
+ * never expired and were never attempt-limited.
17
+ *
18
+ * verificationFailedAttempts The counter that bounds guessing. NOT NULL
19
+ * DEFAULT 0 so the atomic increment never has
20
+ * to deal with a NULL.
21
+ *
22
+ * verificationCodeSentAt Drives the resend cooldown. NULL on existing
23
+ * rows, which allows one immediate resend —
24
+ * correct, since the code they hold has just
25
+ * been invalidated above.
26
+ *
27
+ * The up() also SCRUBS the plaintext codes those rows are still carrying.
28
+ * They are already unusable by the time the scrub runs, but they are live
29
+ * six-digit secrets sitting in a table, its replicas and every backup taken
30
+ * while they were there, and the whole point of the change this migration
31
+ * supports is that the column holds a keyed digest and never the code.
32
+ */
33
+
34
+ export class MigrationName1787142779538 implements MigrationInterface {
35
+ public name: string = "MigrationName1787142779538";
36
+
37
+ public async up(queryRunner: QueryRunner): Promise<void> {
38
+ await queryRunner.query(
39
+ `ALTER TABLE "UserCall" ADD "verificationCodeExpiresAt" TIMESTAMP WITH TIME ZONE`,
40
+ );
41
+ await queryRunner.query(
42
+ `ALTER TABLE "UserCall" ADD "verificationFailedAttempts" integer NOT NULL DEFAULT '0'`,
43
+ );
44
+ await queryRunner.query(
45
+ `ALTER TABLE "UserCall" ADD "verificationCodeSentAt" TIMESTAMP WITH TIME ZONE`,
46
+ );
47
+ await queryRunner.query(
48
+ `ALTER TABLE "UserEmail" ADD "verificationCodeExpiresAt" TIMESTAMP WITH TIME ZONE`,
49
+ );
50
+ await queryRunner.query(
51
+ `ALTER TABLE "UserEmail" ADD "verificationFailedAttempts" integer NOT NULL DEFAULT '0'`,
52
+ );
53
+ await queryRunner.query(
54
+ `ALTER TABLE "UserEmail" ADD "verificationCodeSentAt" TIMESTAMP WITH TIME ZONE`,
55
+ );
56
+ await queryRunner.query(
57
+ `ALTER TABLE "UserSMS" ADD "verificationCodeExpiresAt" TIMESTAMP WITH TIME ZONE`,
58
+ );
59
+ await queryRunner.query(
60
+ `ALTER TABLE "UserSMS" ADD "verificationFailedAttempts" integer NOT NULL DEFAULT '0'`,
61
+ );
62
+ await queryRunner.query(
63
+ `ALTER TABLE "UserSMS" ADD "verificationCodeSentAt" TIMESTAMP WITH TIME ZONE`,
64
+ );
65
+ await queryRunner.query(
66
+ `ALTER TABLE "UserWhatsApp" ADD "verificationCodeExpiresAt" TIMESTAMP WITH TIME ZONE`,
67
+ );
68
+ await queryRunner.query(
69
+ `ALTER TABLE "UserWhatsApp" ADD "verificationFailedAttempts" integer NOT NULL DEFAULT '0'`,
70
+ );
71
+ await queryRunner.query(
72
+ `ALTER TABLE "UserWhatsApp" ADD "verificationCodeSentAt" TIMESTAMP WITH TIME ZONE`,
73
+ );
74
+ await queryRunner.query(
75
+ `ALTER TABLE "UserIncomingCallNumber" ADD "verificationCodeExpiresAt" TIMESTAMP WITH TIME ZONE`,
76
+ );
77
+ await queryRunner.query(
78
+ `ALTER TABLE "UserIncomingCallNumber" ADD "verificationFailedAttempts" integer NOT NULL DEFAULT '0'`,
79
+ );
80
+ await queryRunner.query(
81
+ `ALTER TABLE "UserIncomingCallNumber" ADD "verificationCodeSentAt" TIMESTAMP WITH TIME ZONE`,
82
+ );
83
+
84
+ /*
85
+ * Replace every stored plaintext code with a value nothing can hash
86
+ * to. Two md5s give the 64 hex characters a real digest has, using
87
+ * only functions core Postgres always has — gen_random_bytes would
88
+ * need pgcrypto, which is not a dependency this schema otherwise has.
89
+ *
90
+ * Restricted to values that look like a code rather than applied
91
+ * blindly, so re-running against a database that has already moved on
92
+ * cannot damage a real digest.
93
+ */
94
+ for (const tableName of [
95
+ "UserEmail",
96
+ "UserSMS",
97
+ "UserCall",
98
+ "UserWhatsApp",
99
+ "UserIncomingCallNumber",
100
+ ]) {
101
+ await queryRunner.query(
102
+ `UPDATE "${tableName}" SET "verificationCode" = md5(random()::text || clock_timestamp()::text) || md5(random()::text || clock_timestamp()::text) WHERE "verificationCode" ~ '^[0-9]{1,10}$'`,
103
+ );
104
+ }
105
+ }
106
+
107
+ public async down(queryRunner: QueryRunner): Promise<void> {
108
+ await queryRunner.query(
109
+ `ALTER TABLE "UserIncomingCallNumber" DROP COLUMN "verificationCodeSentAt"`,
110
+ );
111
+ await queryRunner.query(
112
+ `ALTER TABLE "UserIncomingCallNumber" DROP COLUMN "verificationFailedAttempts"`,
113
+ );
114
+ await queryRunner.query(
115
+ `ALTER TABLE "UserIncomingCallNumber" DROP COLUMN "verificationCodeExpiresAt"`,
116
+ );
117
+ await queryRunner.query(
118
+ `ALTER TABLE "UserWhatsApp" DROP COLUMN "verificationCodeSentAt"`,
119
+ );
120
+ await queryRunner.query(
121
+ `ALTER TABLE "UserWhatsApp" DROP COLUMN "verificationFailedAttempts"`,
122
+ );
123
+ await queryRunner.query(
124
+ `ALTER TABLE "UserWhatsApp" DROP COLUMN "verificationCodeExpiresAt"`,
125
+ );
126
+ await queryRunner.query(
127
+ `ALTER TABLE "UserSMS" DROP COLUMN "verificationCodeSentAt"`,
128
+ );
129
+ await queryRunner.query(
130
+ `ALTER TABLE "UserSMS" DROP COLUMN "verificationFailedAttempts"`,
131
+ );
132
+ await queryRunner.query(
133
+ `ALTER TABLE "UserSMS" DROP COLUMN "verificationCodeExpiresAt"`,
134
+ );
135
+ await queryRunner.query(
136
+ `ALTER TABLE "UserEmail" DROP COLUMN "verificationCodeSentAt"`,
137
+ );
138
+ await queryRunner.query(
139
+ `ALTER TABLE "UserEmail" DROP COLUMN "verificationFailedAttempts"`,
140
+ );
141
+ await queryRunner.query(
142
+ `ALTER TABLE "UserEmail" DROP COLUMN "verificationCodeExpiresAt"`,
143
+ );
144
+ await queryRunner.query(
145
+ `ALTER TABLE "UserCall" DROP COLUMN "verificationCodeSentAt"`,
146
+ );
147
+ await queryRunner.query(
148
+ `ALTER TABLE "UserCall" DROP COLUMN "verificationFailedAttempts"`,
149
+ );
150
+ await queryRunner.query(
151
+ `ALTER TABLE "UserCall" DROP COLUMN "verificationCodeExpiresAt"`,
152
+ );
153
+ }
154
+ }
@@ -0,0 +1,17 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class MigrationName1787156982416 implements MigrationInterface {
4
+ public name = "MigrationName1787156982416";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `ALTER TABLE "UserPush" ADD "isCriticalAlertEnabled" boolean NOT NULL DEFAULT false`,
9
+ );
10
+ }
11
+
12
+ public async down(queryRunner: QueryRunner): Promise<void> {
13
+ await queryRunner.query(
14
+ `ALTER TABLE "UserPush" DROP COLUMN "isCriticalAlertEnabled"`,
15
+ );
16
+ }
17
+ }
@@ -0,0 +1,45 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ /*
4
+ * Corrects the otpauth:// URLs behind every un-scanned 2FA QR code.
5
+ *
6
+ * OneUptime used to build those URLs with `algorithm=SHA256`. Google
7
+ * Authenticator and Microsoft Authenticator parse the URL, ignore that
8
+ * parameter, and compute SHA1 — so the app displayed six digits the server
9
+ * could never agree with and enrolment failed with "Invalid code" forever, no
10
+ * matter how many fresh codes the user tried.
11
+ *
12
+ * This migration is NOT what unsticks those users. The code fix already does:
13
+ * verification tries SHA1 first, which is what those apps were emitting all
14
+ * along, so a pending enrolment starts working the moment the new build ships
15
+ * and the stored URL is never consulted during verification. What this fixes
16
+ * is the URL still claiming something untrue, which matters for the apps that
17
+ * DO honour the parameter and do not implement SHA256 — some hardware tokens,
18
+ * older FreeOTP builds — and which would otherwise keep minting new rows that
19
+ * depend on the SHA256 fallback long after the fallback should have gone.
20
+ *
21
+ * Only the algorithm label changes; the secret is untouched, so an app that
22
+ * already scanned the old QR keeps working. Verification accepts SHA1 and
23
+ * legacy SHA256 either way (see Common/Server/Utils/TotpAuth.ts), which is
24
+ * what makes rewriting the label safe rather than a second lockout.
25
+ *
26
+ * Verified rows are deliberately left alone. Their QR code is never shown
27
+ * again — the Verify action only exists for unverified entries — so the stored
28
+ * URL is a record of what the user's authenticator actually holds, and that
29
+ * record should stay accurate.
30
+ */
31
+ export class FixTotpOtpUrlAlgorithm1787700000000 implements MigrationInterface {
32
+ public name = "FixTotpOtpUrlAlgorithm1787700000000";
33
+
34
+ public async up(queryRunner: QueryRunner): Promise<void> {
35
+ await queryRunner.query(
36
+ `UPDATE "UserTotpAuth" SET "twoFactorOtpUrl" = REPLACE("twoFactorOtpUrl", 'algorithm=SHA256', 'algorithm=SHA1') WHERE "isVerified" = false AND "twoFactorOtpUrl" LIKE '%algorithm=SHA256%'`,
37
+ );
38
+ }
39
+
40
+ public async down(queryRunner: QueryRunner): Promise<void> {
41
+ await queryRunner.query(
42
+ `UPDATE "UserTotpAuth" SET "twoFactorOtpUrl" = REPLACE("twoFactorOtpUrl", 'algorithm=SHA1', 'algorithm=SHA256') WHERE "isVerified" = false AND "twoFactorOtpUrl" LIKE '%algorithm=SHA1%'`,
43
+ );
44
+ }
45
+ }
@@ -530,6 +530,9 @@ import { AddEpisodeMemberNotifyIndexes1787300000000 } from "./1787300000000-AddE
530
530
  import { AddDeviceRoleAndDeclaredLinkParent1787400000000 } from "./1787400000000-AddDeviceRoleAndDeclaredLinkParent";
531
531
  import { AddEnableSearchEngineIndexingToStatusPage1787500000000 } from "./1787500000000-AddEnableSearchEngineIndexingToStatusPage";
532
532
  import { AddNetworkDeviceReachabilityColumns1787600000000 } from "./1787600000000-AddNetworkDeviceReachabilityColumns";
533
+ import { FixTotpOtpUrlAlgorithm1787700000000 } from "./1787700000000-FixTotpOtpUrlAlgorithm";
534
+ import { MigrationName1787142779538 } from "./1787142779538-MigrationName";
535
+ import { MigrationName1787156982416 } from "./1787156982416-MigrationName";
533
536
 
534
537
  export default [
535
538
  InitialMigration,
@@ -1059,9 +1062,12 @@ export default [
1059
1062
  AddInventoryItemArchiveAndCustomFields1786900000000,
1060
1063
  AddOnCallNotificationFallbackColumns1787000000000,
1061
1064
  AddAIConversationPageContext1787100000000,
1065
+ MigrationName1787142779538,
1066
+ MigrationName1787156982416,
1062
1067
  AddAIChatMessageFeedback1787200000000,
1063
1068
  AddEpisodeMemberNotifyIndexes1787300000000,
1064
1069
  AddDeviceRoleAndDeclaredLinkParent1787400000000,
1065
1070
  AddEnableSearchEngineIndexingToStatusPage1787500000000,
1066
1071
  AddNetworkDeviceReachabilityColumns1787600000000,
1072
+ FixTotpOtpUrlAlgorithm1787700000000,
1067
1073
  ];