@oneuptime/common 8.0.5239 → 8.0.5283

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 (359) hide show
  1. package/Models/DatabaseModels/Index.ts +4 -2
  2. package/Models/DatabaseModels/OnCallDutyPolicyUserOverride.ts +5 -3
  3. package/Models/DatabaseModels/Project.ts +4 -2
  4. package/Models/DatabaseModels/ProjectSmtpConfig.ts +4 -2
  5. package/Models/DatabaseModels/StatusPageDomain.ts +6 -4
  6. package/Models/DatabaseModels/User.ts +0 -46
  7. package/Models/DatabaseModels/{UserTwoFactorAuth.ts → UserTotpAuth.ts} +16 -16
  8. package/Models/DatabaseModels/UserWebAuthn.ts +244 -0
  9. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +21 -0
  10. package/Server/API/BaseAPI.ts +4 -2
  11. package/Server/API/GlobalConfigAPI.ts +16 -12
  12. package/Server/API/MicrosoftTeamsAPI.ts +1240 -0
  13. package/Server/API/ProjectAPI.ts +4 -2
  14. package/Server/API/ResellerPlanAPI.ts +4 -2
  15. package/Server/API/SlackAPI.ts +54 -48
  16. package/Server/API/StatusPageAPI.ts +5 -3
  17. package/Server/API/UserOnCallLogTimelineAPI.ts +5 -3
  18. package/Server/API/{UserTwoFactorAuthAPI.ts → UserTotpAuthAPI.ts} +20 -20
  19. package/Server/API/UserWebAuthnAPI.ts +103 -0
  20. package/Server/EnvironmentConfig.ts +6 -0
  21. package/Server/Images/MicrosoftTeams/color.png +0 -0
  22. package/Server/Images/MicrosoftTeams/outline.png +0 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/1753131488925-AddEnableCustomSubscriberEmailNotificationFooterText.ts +4 -2
  24. package/Server/Infrastructure/Postgres/SchemaMigrations/1759175457008-MigrationName.ts +27 -0
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/1759232954703-MigrationName.ts +25 -0
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1759234532998-MigrationName.ts +15 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  28. package/Server/Infrastructure/Queue.ts +4 -2
  29. package/Server/Infrastructure/SocketIO.ts +4 -2
  30. package/Server/Middleware/ProjectAuthorization.ts +5 -3
  31. package/Server/Middleware/SlackAuthorization.ts +2 -2
  32. package/Server/Middleware/TelemetryIngest.ts +12 -6
  33. package/Server/Services/AlertStateTimelineService.ts +34 -18
  34. package/Server/Services/BillingInvoiceService.ts +8 -4
  35. package/Server/Services/BillingService.ts +13 -9
  36. package/Server/Services/DatabaseService.ts +42 -30
  37. package/Server/Services/IncidentService.ts +5 -3
  38. package/Server/Services/IncidentStateTimelineService.ts +34 -18
  39. package/Server/Services/Index.ts +4 -2
  40. package/Server/Services/MonitorStatusTimelineService.ts +34 -18
  41. package/Server/Services/OnCallDutyPolicyScheduleService.ts +4 -2
  42. package/Server/Services/ProjectService.ts +6 -4
  43. package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +26 -14
  44. package/Server/Services/StatusPageService.ts +4 -2
  45. package/Server/Services/UserService.ts +21 -5
  46. package/Server/Services/{UserTwoFactorAuthService.ts → UserTotpAuthService.ts} +26 -7
  47. package/Server/Services/UserWebAuthnService.ts +419 -0
  48. package/Server/Services/WorkspaceNotificationRuleService.ts +257 -77
  49. package/Server/Services/WorkspaceProjectAuthTokenService.ts +2 -2
  50. package/Server/Types/AnalyticsDatabase/ModelPermission.ts +9 -5
  51. package/Server/Types/Database/Permissions/BasePermission.ts +4 -2
  52. package/Server/Types/Database/Permissions/TenantPermission.ts +5 -3
  53. package/Server/Types/Database/QueryHelper.ts +4 -2
  54. package/Server/Types/Markdown.ts +6 -4
  55. package/Server/Types/Workflow/ComponentCode.ts +4 -2
  56. package/Server/Types/Workflow/Components/Conditions/IfElse.ts +5 -3
  57. package/Server/Types/Workflow/Components/JavaScript.ts +5 -3
  58. package/Server/Types/Workflow/TriggerCode.ts +4 -2
  59. package/Server/Utils/AnalyticsDatabase/Statement.ts +4 -2
  60. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +21 -11
  61. package/Server/Utils/Browser.ts +6 -4
  62. package/Server/Utils/CodeRepository/GitHub/GitHub.ts +4 -2
  63. package/Server/Utils/LocalFile.ts +14 -0
  64. package/Server/Utils/Monitor/MonitorResource.ts +17 -9
  65. package/Server/Utils/Realtime.ts +4 -2
  66. package/Server/Utils/StartServer.ts +1 -1
  67. package/Server/Utils/Telemetry.ts +15 -9
  68. package/Server/Utils/{TwoFactorAuth.ts → TotpAuth.ts} +2 -2
  69. package/Server/Utils/Workspace/MicrosoftTeams/Actions/ActionTypes.ts +75 -16
  70. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +649 -0
  71. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.ts +237 -0
  72. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +1321 -0
  73. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Monitor.ts +155 -0
  74. package/Server/Utils/Workspace/MicrosoftTeams/Actions/OnCallDutyPolicy.ts +119 -0
  75. package/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.ts +959 -0
  76. package/Server/Utils/Workspace/MicrosoftTeams/Messages/Alert.ts +16 -14
  77. package/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.ts +17 -14
  78. package/Server/Utils/Workspace/MicrosoftTeams/Messages/ScheduledMaintenance.ts +18 -13
  79. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +2547 -14
  80. package/Server/Utils/Workspace/Slack/Actions/Alert.ts +4 -2
  81. package/Server/Utils/Workspace/Slack/Actions/Auth.ts +4 -2
  82. package/Server/Utils/Workspace/Slack/Actions/Incident.ts +14 -10
  83. package/Server/Utils/Workspace/Slack/Actions/Monitor.ts +4 -2
  84. package/Server/Utils/Workspace/Slack/Actions/OnCallDutyPolicy.ts +4 -2
  85. package/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.ts +14 -10
  86. package/Server/Utils/Workspace/Slack/Messages/Alert.ts +9 -7
  87. package/Server/Utils/Workspace/Slack/Messages/Incident.ts +9 -7
  88. package/Server/Utils/Workspace/Slack/Messages/Monitor.ts +9 -7
  89. package/Server/Utils/Workspace/Slack/Messages/ScheduledMaintenance.ts +9 -7
  90. package/Server/Utils/Workspace/Slack/Slack.ts +6 -0
  91. package/Server/Utils/Workspace/Workspace.ts +13 -10
  92. package/Server/Utils/Workspace/WorkspaceBase.ts +9 -0
  93. package/Tests/Server/API/BaseAPI.test.ts +64 -52
  94. package/Tests/Server/Services/BillingService.test.ts +4 -4
  95. package/Tests/Server/Services/TeamMemberService.test.ts +20 -12
  96. package/Tests/Server/TestingUtils/Services/BillingServiceHelper.ts +2 -2
  97. package/Tests/Types/OnCallDutyPolicy/LayerUtil.test.ts +8 -4
  98. package/Tests/UI/Components/DictionaryOfStrings.test.tsx +4 -2
  99. package/Tests/UI/Components/FilePicker.test.tsx +2 -2
  100. package/Tests/Utils/API.test.ts +9 -8
  101. package/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.ts +5 -3
  102. package/Types/Html.ts +5 -3
  103. package/Types/JSONFunctions.ts +5 -5
  104. package/Types/Metrics/MetricsQuery.ts +6 -4
  105. package/Types/Monitor/MonitorType.ts +8 -6
  106. package/Types/OnCallDutyPolicy/Layer.ts +29 -17
  107. package/Types/Phone.ts +5 -3
  108. package/Types/Workspace/NotificationRules/BaseNotificationRule.ts +1 -0
  109. package/Types/Workspace/NotificationRules/CreateChannelNotificationRule.ts +5 -2
  110. package/Types/Workspace/WorkspaceMessagePayload.ts +1 -0
  111. package/Types/Workspace/WorkspaceType.ts +13 -0
  112. package/UI/Components/Charts/Utils/DataPoint.ts +8 -6
  113. package/UI/Components/Detail/Detail.tsx +4 -1
  114. package/UI/Components/FilePicker/FilePicker.tsx +1 -1
  115. package/UI/Components/Forms/Types/Field.ts +4 -2
  116. package/UI/Components/Image/Image.tsx +1 -1
  117. package/UI/Components/JSONTable/JSONTable.tsx +4 -2
  118. package/UI/Components/ModelTable/BaseModelTable.tsx +5 -3
  119. package/UI/Components/SideMenu/SideMenu.tsx +4 -2
  120. package/UI/Components/SideMenu/SideMenuItem.tsx +69 -45
  121. package/UI/Config.ts +3 -0
  122. package/UI/Utils/API/API.ts +5 -3
  123. package/UI/Utils/Countries.ts +5 -3
  124. package/UI/Utils/Login.ts +6 -1
  125. package/Utils/Base64.ts +13 -0
  126. package/Utils/Schema/ModelSchema.ts +4 -2
  127. package/build/dist/Models/DatabaseModels/Index.js +4 -2
  128. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  129. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyUserOverride.js +5 -3
  130. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyUserOverride.js.map +1 -1
  131. package/build/dist/Models/DatabaseModels/Project.js +4 -2
  132. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  133. package/build/dist/Models/DatabaseModels/ProjectSmtpConfig.js +4 -2
  134. package/build/dist/Models/DatabaseModels/ProjectSmtpConfig.js.map +1 -1
  135. package/build/dist/Models/DatabaseModels/StatusPageDomain.js +6 -4
  136. package/build/dist/Models/DatabaseModels/StatusPageDomain.js.map +1 -1
  137. package/build/dist/Models/DatabaseModels/User.js +0 -49
  138. package/build/dist/Models/DatabaseModels/User.js.map +1 -1
  139. package/build/dist/Models/DatabaseModels/{UserTwoFactorAuth.js → UserTotpAuth.js} +27 -27
  140. package/build/dist/Models/DatabaseModels/UserTotpAuth.js.map +1 -0
  141. package/build/dist/Models/DatabaseModels/UserWebAuthn.js +270 -0
  142. package/build/dist/Models/DatabaseModels/UserWebAuthn.js.map +1 -0
  143. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  144. package/build/dist/Server/API/BaseAPI.js +4 -2
  145. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  146. package/build/dist/Server/API/GlobalConfigAPI.js +16 -12
  147. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  148. package/build/dist/Server/API/MicrosoftTeamsAPI.js +771 -0
  149. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -0
  150. package/build/dist/Server/API/ProjectAPI.js +4 -2
  151. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  152. package/build/dist/Server/API/ResellerPlanAPI.js +4 -2
  153. package/build/dist/Server/API/ResellerPlanAPI.js.map +1 -1
  154. package/build/dist/Server/API/SlackAPI.js +53 -47
  155. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  156. package/build/dist/Server/API/StatusPageAPI.js +5 -3
  157. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  158. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js +5 -3
  159. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
  160. package/build/dist/Server/API/{UserTwoFactorAuthAPI.js → UserTotpAuthAPI.js} +16 -16
  161. package/build/dist/Server/API/UserTotpAuthAPI.js.map +1 -0
  162. package/build/dist/Server/API/UserWebAuthnAPI.js +65 -0
  163. package/build/dist/Server/API/UserWebAuthnAPI.js.map +1 -0
  164. package/build/dist/Server/EnvironmentConfig.js +3 -0
  165. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  166. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1753131488925-AddEnableCustomSubscriberEmailNotificationFooterText.js +4 -2
  167. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1753131488925-AddEnableCustomSubscriberEmailNotificationFooterText.js.map +1 -1
  168. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759175457008-MigrationName.js +16 -0
  169. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759175457008-MigrationName.js.map +1 -0
  170. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759232954703-MigrationName.js +16 -0
  171. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759232954703-MigrationName.js.map +1 -0
  172. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759234532998-MigrationName.js +12 -0
  173. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1759234532998-MigrationName.js.map +1 -0
  174. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  175. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  176. package/build/dist/Server/Infrastructure/Queue.js +4 -2
  177. package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
  178. package/build/dist/Server/Infrastructure/SocketIO.js +4 -2
  179. package/build/dist/Server/Infrastructure/SocketIO.js.map +1 -1
  180. package/build/dist/Server/Middleware/ProjectAuthorization.js +5 -3
  181. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  182. package/build/dist/Server/Middleware/SlackAuthorization.js.map +1 -1
  183. package/build/dist/Server/Middleware/TelemetryIngest.js +12 -6
  184. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  185. package/build/dist/Server/Services/AlertStateTimelineService.js +34 -18
  186. package/build/dist/Server/Services/AlertStateTimelineService.js.map +1 -1
  187. package/build/dist/Server/Services/BillingInvoiceService.js +8 -4
  188. package/build/dist/Server/Services/BillingInvoiceService.js.map +1 -1
  189. package/build/dist/Server/Services/BillingService.js +13 -9
  190. package/build/dist/Server/Services/BillingService.js.map +1 -1
  191. package/build/dist/Server/Services/DatabaseService.js +40 -28
  192. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  193. package/build/dist/Server/Services/IncidentService.js +5 -3
  194. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  195. package/build/dist/Server/Services/IncidentStateTimelineService.js +34 -18
  196. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  197. package/build/dist/Server/Services/Index.js +4 -2
  198. package/build/dist/Server/Services/Index.js.map +1 -1
  199. package/build/dist/Server/Services/MonitorStatusTimelineService.js +34 -18
  200. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  201. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +4 -2
  202. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  203. package/build/dist/Server/Services/ProjectService.js +6 -4
  204. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  205. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +26 -14
  206. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
  207. package/build/dist/Server/Services/StatusPageService.js +4 -2
  208. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  209. package/build/dist/Server/Services/UserService.js +16 -3
  210. package/build/dist/Server/Services/UserService.js.map +1 -1
  211. package/build/dist/Server/Services/{UserTwoFactorAuthService.js → UserTotpAuthService.js} +22 -8
  212. package/build/dist/Server/Services/UserTotpAuthService.js.map +1 -0
  213. package/build/dist/Server/Services/UserWebAuthnService.js +365 -0
  214. package/build/dist/Server/Services/UserWebAuthnService.js.map +1 -0
  215. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +142 -51
  216. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  217. package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js +9 -5
  218. package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js.map +1 -1
  219. package/build/dist/Server/Types/Database/Permissions/BasePermission.js +4 -2
  220. package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
  221. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js +5 -3
  222. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js.map +1 -1
  223. package/build/dist/Server/Types/Database/QueryHelper.js +4 -2
  224. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  225. package/build/dist/Server/Types/Markdown.js +6 -4
  226. package/build/dist/Server/Types/Markdown.js.map +1 -1
  227. package/build/dist/Server/Types/Workflow/ComponentCode.js +4 -2
  228. package/build/dist/Server/Types/Workflow/ComponentCode.js.map +1 -1
  229. package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js +5 -3
  230. package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js.map +1 -1
  231. package/build/dist/Server/Types/Workflow/Components/JavaScript.js +5 -3
  232. package/build/dist/Server/Types/Workflow/Components/JavaScript.js.map +1 -1
  233. package/build/dist/Server/Types/Workflow/TriggerCode.js.map +1 -1
  234. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +4 -2
  235. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  236. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +21 -11
  237. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  238. package/build/dist/Server/Utils/Browser.js +6 -4
  239. package/build/dist/Server/Utils/Browser.js.map +1 -1
  240. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +4 -2
  241. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
  242. package/build/dist/Server/Utils/LocalFile.js +16 -0
  243. package/build/dist/Server/Utils/LocalFile.js.map +1 -1
  244. package/build/dist/Server/Utils/Monitor/MonitorResource.js +17 -9
  245. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  246. package/build/dist/Server/Utils/Realtime.js +4 -2
  247. package/build/dist/Server/Utils/Realtime.js.map +1 -1
  248. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  249. package/build/dist/Server/Utils/Telemetry.js +6 -4
  250. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  251. package/build/dist/Server/Utils/{TwoFactorAuth.js → TotpAuth.js} +8 -8
  252. package/build/dist/Server/Utils/TotpAuth.js.map +1 -0
  253. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ActionTypes.js +86 -36
  254. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ActionTypes.js.map +1 -1
  255. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +531 -0
  256. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -0
  257. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js +206 -0
  258. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js.map +1 -0
  259. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +1102 -0
  260. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -0
  261. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Monitor.js +136 -0
  262. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Monitor.js.map +1 -0
  263. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/OnCallDutyPolicy.js +107 -0
  264. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/OnCallDutyPolicy.js.map +1 -0
  265. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js +795 -0
  266. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js.map +1 -0
  267. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/Alert.js +16 -14
  268. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/Alert.js.map +1 -1
  269. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.js +16 -14
  270. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.js.map +1 -1
  271. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/ScheduledMaintenance.js +15 -13
  272. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/ScheduledMaintenance.js.map +1 -1
  273. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +1982 -13
  274. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  275. package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js +4 -2
  276. package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js.map +1 -1
  277. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js +4 -2
  278. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js.map +1 -1
  279. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js +14 -10
  280. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js.map +1 -1
  281. package/build/dist/Server/Utils/Workspace/Slack/Actions/Monitor.js +4 -2
  282. package/build/dist/Server/Utils/Workspace/Slack/Actions/Monitor.js.map +1 -1
  283. package/build/dist/Server/Utils/Workspace/Slack/Actions/OnCallDutyPolicy.js +4 -2
  284. package/build/dist/Server/Utils/Workspace/Slack/Actions/OnCallDutyPolicy.js.map +1 -1
  285. package/build/dist/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.js +14 -10
  286. package/build/dist/Server/Utils/Workspace/Slack/Actions/ScheduledMaintenance.js.map +1 -1
  287. package/build/dist/Server/Utils/Workspace/Slack/Messages/Alert.js +9 -7
  288. package/build/dist/Server/Utils/Workspace/Slack/Messages/Alert.js.map +1 -1
  289. package/build/dist/Server/Utils/Workspace/Slack/Messages/Incident.js +9 -7
  290. package/build/dist/Server/Utils/Workspace/Slack/Messages/Incident.js.map +1 -1
  291. package/build/dist/Server/Utils/Workspace/Slack/Messages/Monitor.js +9 -7
  292. package/build/dist/Server/Utils/Workspace/Slack/Messages/Monitor.js.map +1 -1
  293. package/build/dist/Server/Utils/Workspace/Slack/Messages/ScheduledMaintenance.js +9 -7
  294. package/build/dist/Server/Utils/Workspace/Slack/Messages/ScheduledMaintenance.js.map +1 -1
  295. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +5 -0
  296. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  297. package/build/dist/Server/Utils/Workspace/Workspace.js +12 -10
  298. package/build/dist/Server/Utils/Workspace/Workspace.js.map +1 -1
  299. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
  300. package/build/dist/Tests/Server/API/BaseAPI.test.js +59 -47
  301. package/build/dist/Tests/Server/API/BaseAPI.test.js.map +1 -1
  302. package/build/dist/Tests/Server/Services/BillingService.test.js +4 -4
  303. package/build/dist/Tests/Server/Services/BillingService.test.js.map +1 -1
  304. package/build/dist/Tests/Server/Services/TeamMemberService.test.js +20 -12
  305. package/build/dist/Tests/Server/Services/TeamMemberService.test.js.map +1 -1
  306. package/build/dist/Tests/Server/TestingUtils/Services/BillingServiceHelper.js +2 -2
  307. package/build/dist/Tests/Server/TestingUtils/Services/BillingServiceHelper.js.map +1 -1
  308. package/build/dist/Tests/Types/OnCallDutyPolicy/LayerUtil.test.js +8 -4
  309. package/build/dist/Tests/Types/OnCallDutyPolicy/LayerUtil.test.js.map +1 -1
  310. package/build/dist/Tests/UI/Components/DictionaryOfStrings.test.js +4 -2
  311. package/build/dist/Tests/UI/Components/DictionaryOfStrings.test.js.map +1 -1
  312. package/build/dist/Tests/UI/Components/FilePicker.test.js +2 -2
  313. package/build/dist/Tests/UI/Components/FilePicker.test.js.map +1 -1
  314. package/build/dist/Tests/Utils/API.test.js +8 -7
  315. package/build/dist/Tests/Utils/API.test.js.map +1 -1
  316. package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js +5 -3
  317. package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js.map +1 -1
  318. package/build/dist/Types/Html.js +5 -3
  319. package/build/dist/Types/Html.js.map +1 -1
  320. package/build/dist/Types/JSONFunctions.js +5 -5
  321. package/build/dist/Types/JSONFunctions.js.map +1 -1
  322. package/build/dist/Types/Monitor/MonitorType.js +8 -6
  323. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  324. package/build/dist/Types/OnCallDutyPolicy/Layer.js +29 -17
  325. package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
  326. package/build/dist/Types/Phone.js +5 -3
  327. package/build/dist/Types/Phone.js.map +1 -1
  328. package/build/dist/Types/Workspace/WorkspaceType.js +9 -0
  329. package/build/dist/Types/Workspace/WorkspaceType.js.map +1 -1
  330. package/build/dist/UI/Components/Charts/Utils/DataPoint.js +8 -6
  331. package/build/dist/UI/Components/Charts/Utils/DataPoint.js.map +1 -1
  332. package/build/dist/UI/Components/Detail/Detail.js +4 -1
  333. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  334. package/build/dist/UI/Components/FilePicker/FilePicker.js +1 -1
  335. package/build/dist/UI/Components/FilePicker/FilePicker.js.map +1 -1
  336. package/build/dist/UI/Components/Image/Image.js +1 -1
  337. package/build/dist/UI/Components/Image/Image.js.map +1 -1
  338. package/build/dist/UI/Components/JSONTable/JSONTable.js.map +1 -1
  339. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  340. package/build/dist/UI/Components/SideMenu/SideMenu.js +4 -2
  341. package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
  342. package/build/dist/UI/Components/SideMenu/SideMenuItem.js +62 -38
  343. package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
  344. package/build/dist/UI/Config.js +1 -0
  345. package/build/dist/UI/Config.js.map +1 -1
  346. package/build/dist/UI/Utils/API/API.js +5 -3
  347. package/build/dist/UI/Utils/API/API.js.map +1 -1
  348. package/build/dist/UI/Utils/Countries.js.map +1 -1
  349. package/build/dist/UI/Utils/Login.js +6 -1
  350. package/build/dist/UI/Utils/Login.js.map +1 -1
  351. package/build/dist/Utils/Base64.js +12 -0
  352. package/build/dist/Utils/Base64.js.map +1 -0
  353. package/build/dist/Utils/Schema/ModelSchema.js +4 -2
  354. package/build/dist/Utils/Schema/ModelSchema.js.map +1 -1
  355. package/package.json +5 -1
  356. package/build/dist/Models/DatabaseModels/UserTwoFactorAuth.js.map +0 -1
  357. package/build/dist/Server/API/UserTwoFactorAuthAPI.js.map +0 -1
  358. package/build/dist/Server/Services/UserTwoFactorAuthService.js.map +0 -1
  359. package/build/dist/Server/Utils/TwoFactorAuth.js.map +0 -1
@@ -0,0 +1,959 @@
1
+ import { ExpressRequest, ExpressResponse } from "../../../Express";
2
+ import Response from "../../../Response";
3
+ import MicrosoftTeamsAuthAction, {
4
+ MicrosoftTeamsAction,
5
+ MicrosoftTeamsRequest,
6
+ } from "./Auth";
7
+ import { MicrosoftTeamsScheduledMaintenanceActionType } from "./ActionTypes";
8
+ import logger from "../../../Logger";
9
+ import CaptureSpan from "../../../Telemetry/CaptureSpan";
10
+ import { TurnContext } from "botbuilder";
11
+ import { JSONObject } from "../../../../../Types/JSON";
12
+ import ObjectID from "../../../../../Types/ObjectID";
13
+ import ScheduledMaintenanceService from "../../../../Services/ScheduledMaintenanceService";
14
+ import ScheduledMaintenance from "../../../../../Models/DatabaseModels/ScheduledMaintenance";
15
+ import ScheduledMaintenanceState from "../../../../../Models/DatabaseModels/ScheduledMaintenanceState";
16
+ import ScheduledMaintenanceInternalNoteService from "../../../../Services/ScheduledMaintenanceInternalNoteService";
17
+ import ScheduledMaintenancePublicNoteService from "../../../../Services/ScheduledMaintenancePublicNoteService";
18
+ import ScheduledMaintenanceStateService from "../../../../Services/ScheduledMaintenanceStateService";
19
+ import MonitorService from "../../../../Services/MonitorService";
20
+ import Monitor from "../../../../../Models/DatabaseModels/Monitor";
21
+ import MonitorStatusService from "../../../../Services/MonitorStatusService";
22
+ import MonitorStatus from "../../../../../Models/DatabaseModels/MonitorStatus";
23
+ import LabelService from "../../../../Services/LabelService";
24
+ import Label from "../../../../../Models/DatabaseModels/Label";
25
+ import SortOrder from "../../../../../Types/BaseDatabase/SortOrder";
26
+ import { LIMIT_PER_PROJECT } from "../../../../../Types/Database/LimitMax";
27
+ import BadDataException from "../../../../../Types/Exception/BadDataException";
28
+ import OneUptimeDate from "../../../../../Types/Date";
29
+ import URL from "../../../../../Types/API/URL";
30
+
31
+ export default class MicrosoftTeamsScheduledMaintenanceActions {
32
+ @CaptureSpan()
33
+ public static isScheduledMaintenanceAction(data: {
34
+ actionType: string;
35
+ }): boolean {
36
+ return (
37
+ data.actionType.includes("scheduled-maintenance") ||
38
+ data.actionType ===
39
+ MicrosoftTeamsScheduledMaintenanceActionType.ViewScheduledMaintenance ||
40
+ data.actionType ===
41
+ MicrosoftTeamsScheduledMaintenanceActionType.MarkAsOngoing ||
42
+ data.actionType ===
43
+ MicrosoftTeamsScheduledMaintenanceActionType.MarkAsComplete ||
44
+ data.actionType ===
45
+ MicrosoftTeamsScheduledMaintenanceActionType.ViewAddScheduledMaintenanceNote ||
46
+ data.actionType ===
47
+ MicrosoftTeamsScheduledMaintenanceActionType.SubmitScheduledMaintenanceNote ||
48
+ data.actionType ===
49
+ MicrosoftTeamsScheduledMaintenanceActionType.ViewChangeScheduledMaintenanceState ||
50
+ data.actionType ===
51
+ MicrosoftTeamsScheduledMaintenanceActionType.SubmitChangeScheduledMaintenanceState ||
52
+ data.actionType ===
53
+ MicrosoftTeamsScheduledMaintenanceActionType.NewScheduledMaintenance ||
54
+ data.actionType ===
55
+ MicrosoftTeamsScheduledMaintenanceActionType.SubmitNewScheduledMaintenance
56
+ );
57
+ }
58
+
59
+ @CaptureSpan()
60
+ public static async handleScheduledMaintenanceAction(data: {
61
+ teamsRequest: MicrosoftTeamsRequest;
62
+ action: MicrosoftTeamsAction;
63
+ req: ExpressRequest;
64
+ res: ExpressResponse;
65
+ }): Promise<void> {
66
+ const { action } = data;
67
+
68
+ logger.debug("Handling Microsoft Teams scheduled maintenance action:");
69
+ logger.debug(action);
70
+
71
+ try {
72
+ switch (action.actionType) {
73
+ case MicrosoftTeamsScheduledMaintenanceActionType.ViewScheduledMaintenance:
74
+ // This is handled by opening the URL directly
75
+ break;
76
+
77
+ case MicrosoftTeamsScheduledMaintenanceActionType.NewScheduledMaintenance:
78
+ return await this.showNewScheduledMaintenanceCard(data);
79
+
80
+ case MicrosoftTeamsScheduledMaintenanceActionType.SubmitNewScheduledMaintenance:
81
+ /*
82
+ * This is handled by handleBotScheduledMaintenanceAction through bot framework
83
+ * Don't process it here to avoid duplicate messages
84
+ */
85
+ break;
86
+
87
+ default:
88
+ logger.debug(
89
+ `Unhandled scheduled maintenance action: ${action.actionType}`,
90
+ );
91
+ break;
92
+ }
93
+ } catch (error) {
94
+ logger.error(
95
+ "Error handling Microsoft Teams scheduled maintenance action:",
96
+ );
97
+ logger.error(error);
98
+ }
99
+
100
+ Response.sendTextResponse(data.req, data.res, "");
101
+ }
102
+
103
+ @CaptureSpan()
104
+ public static async handleBotScheduledMaintenanceAction(
105
+ actionType: MicrosoftTeamsScheduledMaintenanceActionType,
106
+ turnContext: TurnContext,
107
+ actionPayload: JSONObject,
108
+ request: MicrosoftTeamsRequest,
109
+ ): Promise<void> {
110
+ try {
111
+ // Handle new scheduled maintenance creation separately (doesn't need existing ID)
112
+ if (
113
+ actionType ===
114
+ MicrosoftTeamsScheduledMaintenanceActionType.SubmitNewScheduledMaintenance
115
+ ) {
116
+ // Handle new scheduled maintenance submission
117
+ const title: string =
118
+ (actionPayload["scheduledMaintenanceTitle"] as string) || "";
119
+ const description: string =
120
+ (actionPayload["scheduledMaintenanceDescription"] as string) || "";
121
+ const startDate: string = (actionPayload["startDate"] as string) || "";
122
+ const startTime: string = (actionPayload["startTime"] as string) || "";
123
+ const endDate: string = (actionPayload["endDate"] as string) || "";
124
+ const endTime: string = (actionPayload["endTime"] as string) || "";
125
+ const monitorIds: string =
126
+ (actionPayload["scheduledMaintenanceMonitors"] as string) || "";
127
+ const monitorStatusId: string =
128
+ (actionPayload["monitorStatus"] as string) || "";
129
+ const labelIds: string = (actionPayload["labels"] as string) || "";
130
+
131
+ if (
132
+ !title ||
133
+ !description ||
134
+ !startDate ||
135
+ !startTime ||
136
+ !endDate ||
137
+ !endTime
138
+ ) {
139
+ await turnContext.sendActivity(
140
+ "Unable to create scheduled maintenance: missing required fields (title, description, start date/time, or end date/time).",
141
+ );
142
+ return;
143
+ }
144
+
145
+ if (!request.userId || !request.projectId) {
146
+ await turnContext.sendActivity(
147
+ "Unable to create scheduled maintenance: missing user or project information.",
148
+ );
149
+ return;
150
+ }
151
+
152
+ try {
153
+ // Create the scheduled maintenance
154
+ const scheduledMaintenanceObj: ScheduledMaintenance =
155
+ new ScheduledMaintenance();
156
+ scheduledMaintenanceObj.title = title;
157
+ scheduledMaintenanceObj.description = description;
158
+ scheduledMaintenanceObj.projectId = request.projectId;
159
+ scheduledMaintenanceObj.createdByUserId = new ObjectID(
160
+ request.userId,
161
+ );
162
+
163
+ // Combine date and time for start and end
164
+ const startDateTime: string = `${startDate}T${startTime}`;
165
+ const endDateTime: string = `${endDate}T${endTime}`;
166
+
167
+ scheduledMaintenanceObj.startsAt =
168
+ OneUptimeDate.fromString(startDateTime);
169
+ scheduledMaintenanceObj.endsAt =
170
+ OneUptimeDate.fromString(endDateTime);
171
+
172
+ // Parse monitors
173
+ if (monitorIds) {
174
+ const monitorIdArray: Array<string> = monitorIds
175
+ .split(",")
176
+ .map((id: string) => {
177
+ return id.trim();
178
+ })
179
+ .filter((id: string) => {
180
+ return id;
181
+ });
182
+ if (monitorIdArray.length > 0) {
183
+ scheduledMaintenanceObj.monitors = monitorIdArray.map(
184
+ (id: string) => {
185
+ const monitor: Monitor = new Monitor();
186
+ monitor.id = new ObjectID(id);
187
+ return monitor;
188
+ },
189
+ );
190
+ }
191
+ }
192
+
193
+ // Parse labels
194
+ if (labelIds) {
195
+ const labelIdArray: Array<string> = labelIds
196
+ .split(",")
197
+ .map((id: string) => {
198
+ return id.trim();
199
+ })
200
+ .filter((id: string) => {
201
+ return id;
202
+ });
203
+ if (labelIdArray.length > 0) {
204
+ scheduledMaintenanceObj.labels = labelIdArray.map(
205
+ (id: string) => {
206
+ const label: Label = new Label();
207
+ label.id = new ObjectID(id);
208
+ return label;
209
+ },
210
+ );
211
+ }
212
+ }
213
+
214
+ // Save the scheduled maintenance
215
+ const createdScheduledMaintenance: ScheduledMaintenance =
216
+ await ScheduledMaintenanceService.create({
217
+ data: scheduledMaintenanceObj,
218
+ props: {
219
+ isRoot: true,
220
+ },
221
+ });
222
+
223
+ logger.debug(
224
+ "Scheduled maintenance created successfully: " +
225
+ createdScheduledMaintenance.id?.toString(),
226
+ );
227
+
228
+ // Update monitor status if specified
229
+ if (monitorStatusId && monitorIds) {
230
+ const monitorIdArray: Array<string> = monitorIds
231
+ .split(",")
232
+ .map((id: string) => {
233
+ return id.trim();
234
+ })
235
+ .filter((id: string) => {
236
+ return id;
237
+ });
238
+ for (const monitorId of monitorIdArray) {
239
+ await MonitorService.updateOneById({
240
+ id: new ObjectID(monitorId),
241
+ data: {
242
+ currentMonitorStatusId: new ObjectID(monitorStatusId),
243
+ },
244
+ props: {
245
+ isRoot: true,
246
+ },
247
+ });
248
+ }
249
+ }
250
+
251
+ // Hide the form card by deleting it first
252
+ if (turnContext.activity.replyToId) {
253
+ await turnContext.deleteActivity(turnContext.activity.replyToId);
254
+ }
255
+
256
+ // Get the scheduled maintenance link
257
+ const maintenanceLink: URL =
258
+ await ScheduledMaintenanceService.getScheduledMaintenanceLinkInDashboard(
259
+ createdScheduledMaintenance.projectId!,
260
+ createdScheduledMaintenance.id!,
261
+ );
262
+
263
+ // Send confirmation message as a new message in the thread
264
+ await turnContext.sendActivity(
265
+ `✅ Scheduled maintenance created successfully!\n\nView scheduled maintenance: ${maintenanceLink.toString()}`,
266
+ );
267
+
268
+ return;
269
+ } catch (error) {
270
+ logger.error(
271
+ "Error creating scheduled maintenance from Microsoft Teams:",
272
+ );
273
+ logger.error(error);
274
+ await turnContext.sendActivity(
275
+ "❌ Failed to create scheduled maintenance. Please try again.",
276
+ );
277
+ return;
278
+ }
279
+ }
280
+
281
+ // For all other actions, we need an existing scheduled maintenance ID
282
+ const scheduledMaintenanceId: ObjectID = actionPayload[
283
+ "scheduledMaintenanceId"
284
+ ] as ObjectID;
285
+
286
+ if (!scheduledMaintenanceId) {
287
+ logger.error("ScheduledMaintenance ID is required");
288
+ await turnContext.sendActivity("ScheduledMaintenance ID is required");
289
+ return;
290
+ }
291
+
292
+ const scheduledMaintenance: ScheduledMaintenance | null =
293
+ await ScheduledMaintenanceService.findOneById({
294
+ id: scheduledMaintenanceId,
295
+ select: {
296
+ _id: true,
297
+ title: true,
298
+ description: true,
299
+ startsAt: true,
300
+ endsAt: true,
301
+ currentScheduledMaintenanceState: {
302
+ name: true,
303
+ },
304
+ projectId: true,
305
+ },
306
+ props: {
307
+ isRoot: true,
308
+ },
309
+ });
310
+
311
+ if (!scheduledMaintenance) {
312
+ logger.error("ScheduledMaintenance not found");
313
+ await turnContext.sendActivity("ScheduledMaintenance not found");
314
+ return;
315
+ }
316
+
317
+ switch (actionType) {
318
+ case MicrosoftTeamsScheduledMaintenanceActionType.ViewScheduledMaintenance:
319
+ await turnContext.sendActivity(
320
+ `**${scheduledMaintenance.title}**\n\n${scheduledMaintenance.description}\n\nStarts: ${scheduledMaintenance.startsAt}\nEnds: ${scheduledMaintenance.endsAt}\nStatus: ${scheduledMaintenance.currentScheduledMaintenanceState?.name}`,
321
+ );
322
+ break;
323
+
324
+ case MicrosoftTeamsScheduledMaintenanceActionType.MarkAsOngoing: {
325
+ const ongoingState: ScheduledMaintenanceState =
326
+ await ScheduledMaintenanceStateService.getOngoingScheduledMaintenanceState(
327
+ {
328
+ projectId: scheduledMaintenance.projectId!,
329
+ props: {
330
+ isRoot: true,
331
+ },
332
+ },
333
+ );
334
+ await ScheduledMaintenanceService.updateOneById({
335
+ id: scheduledMaintenanceId,
336
+ data: {
337
+ currentScheduledMaintenanceStateId: ongoingState.id!,
338
+ },
339
+ props: {
340
+ isRoot: true,
341
+ },
342
+ });
343
+ await turnContext.sendActivity(
344
+ "ScheduledMaintenance marked as ongoing",
345
+ );
346
+ break;
347
+ }
348
+
349
+ case MicrosoftTeamsScheduledMaintenanceActionType.MarkAsComplete: {
350
+ const completedState: ScheduledMaintenanceState =
351
+ await ScheduledMaintenanceStateService.getCompletedScheduledMaintenanceState(
352
+ {
353
+ projectId: scheduledMaintenance.projectId!,
354
+ props: {
355
+ isRoot: true,
356
+ },
357
+ },
358
+ );
359
+ await ScheduledMaintenanceService.updateOneById({
360
+ id: scheduledMaintenanceId,
361
+ data: {
362
+ currentScheduledMaintenanceStateId: completedState.id!,
363
+ },
364
+ props: {
365
+ isRoot: true,
366
+ },
367
+ });
368
+ await turnContext.sendActivity(
369
+ "ScheduledMaintenance marked as complete",
370
+ );
371
+ break;
372
+ }
373
+
374
+ case MicrosoftTeamsScheduledMaintenanceActionType.ViewAddScheduledMaintenanceNote:
375
+ await turnContext.sendActivity({
376
+ attachments: [
377
+ {
378
+ contentType: "application/vnd.microsoft.card.adaptive",
379
+ content: this.buildAddScheduledMaintenanceNoteCard(
380
+ scheduledMaintenanceId,
381
+ ),
382
+ },
383
+ ],
384
+ });
385
+ break;
386
+
387
+ case MicrosoftTeamsScheduledMaintenanceActionType.SubmitScheduledMaintenanceNote: {
388
+ const note: string = actionPayload["note"] as string;
389
+ const isPublic: boolean = actionPayload["isPublic"] as boolean;
390
+
391
+ if (!request.userId) {
392
+ await turnContext.sendActivity("User ID is required to add notes");
393
+ return;
394
+ }
395
+
396
+ if (isPublic) {
397
+ await ScheduledMaintenancePublicNoteService.addNote({
398
+ scheduledMaintenanceId: scheduledMaintenanceId,
399
+ note: note,
400
+ projectId: scheduledMaintenance.projectId!,
401
+ userId: new ObjectID(request.userId),
402
+ });
403
+ } else {
404
+ await ScheduledMaintenanceInternalNoteService.addNote({
405
+ scheduledMaintenanceId: scheduledMaintenanceId,
406
+ note: note,
407
+ projectId: scheduledMaintenance.projectId!,
408
+ userId: new ObjectID(request.userId),
409
+ });
410
+ }
411
+
412
+ await turnContext.sendActivity("Note added successfully");
413
+
414
+ // Hide the form card by deleting it
415
+ if (turnContext.activity.replyToId) {
416
+ await turnContext.deleteActivity(turnContext.activity.replyToId);
417
+ }
418
+
419
+ break;
420
+ }
421
+
422
+ case MicrosoftTeamsScheduledMaintenanceActionType.ViewChangeScheduledMaintenanceState:
423
+ await turnContext.sendActivity({
424
+ attachments: [
425
+ {
426
+ contentType: "application/vnd.microsoft.card.adaptive",
427
+ content: await this.buildChangeScheduledMaintenanceStateCard(
428
+ scheduledMaintenanceId,
429
+ scheduledMaintenance.projectId!,
430
+ ),
431
+ },
432
+ ],
433
+ });
434
+ break;
435
+
436
+ case MicrosoftTeamsScheduledMaintenanceActionType.SubmitChangeScheduledMaintenanceState: {
437
+ const stateId: ObjectID = actionPayload["stateId"] as ObjectID;
438
+
439
+ await ScheduledMaintenanceService.updateOneById({
440
+ id: scheduledMaintenanceId,
441
+ data: {
442
+ currentScheduledMaintenanceStateId: stateId,
443
+ },
444
+ props: {
445
+ isRoot: true,
446
+ },
447
+ });
448
+
449
+ await turnContext.sendActivity(
450
+ "ScheduledMaintenance state changed successfully",
451
+ );
452
+
453
+ // Hide the form card by deleting it
454
+ if (turnContext.activity.replyToId) {
455
+ await turnContext.deleteActivity(turnContext.activity.replyToId);
456
+ }
457
+
458
+ break;
459
+ }
460
+
461
+ default:
462
+ logger.error(`Unknown action type: ${actionType}`);
463
+ await turnContext.sendActivity("Unknown action type");
464
+ break;
465
+ }
466
+ } catch (error) {
467
+ logger.error(`Error handling scheduled maintenance action: ${error}`);
468
+ await turnContext.sendActivity(
469
+ "An error occurred while processing the action",
470
+ );
471
+ }
472
+ }
473
+
474
+ private static buildAddScheduledMaintenanceNoteCard(
475
+ scheduledMaintenanceId: ObjectID,
476
+ ): JSONObject {
477
+ return {
478
+ type: "AdaptiveCard",
479
+ $schema: "http://adaptivecards.io/schemas/adaptive-card.json",
480
+ version: "1.5",
481
+ body: [
482
+ {
483
+ type: "TextBlock",
484
+ text: "Add Scheduled Maintenance Note",
485
+ size: "Large",
486
+ weight: "Bolder",
487
+ },
488
+ {
489
+ type: "Input.ChoiceSet",
490
+ id: "noteType",
491
+ label: "Note Type",
492
+ style: "compact",
493
+ value: "public",
494
+ choices: [
495
+ {
496
+ title: "Public Note (Will be posted on Status Page)",
497
+ value: "public",
498
+ },
499
+ {
500
+ title: "Private Note (Only visible to team members)",
501
+ value: "private",
502
+ },
503
+ ],
504
+ },
505
+ {
506
+ type: "Input.Text",
507
+ id: "note",
508
+ label: "Note",
509
+ isMultiline: true,
510
+ placeholder: "Please type in plain text or markdown.",
511
+ },
512
+ ],
513
+ actions: [
514
+ {
515
+ type: "Action.Submit",
516
+ title: "Submit",
517
+ data: {
518
+ action:
519
+ MicrosoftTeamsScheduledMaintenanceActionType.SubmitScheduledMaintenanceNote,
520
+ scheduledMaintenanceId: scheduledMaintenanceId.toString(),
521
+ },
522
+ },
523
+ ],
524
+ };
525
+ }
526
+
527
+ private static async buildChangeScheduledMaintenanceStateCard(
528
+ scheduledMaintenanceId: ObjectID,
529
+ projectId: ObjectID,
530
+ ): Promise<JSONObject> {
531
+ const scheduledMaintenanceStates: Array<ScheduledMaintenanceState> =
532
+ await ScheduledMaintenanceStateService.getAllScheduledMaintenanceStates({
533
+ projectId: projectId,
534
+ props: {
535
+ isRoot: true,
536
+ },
537
+ });
538
+
539
+ const choices: Array<{ title: string; value: string }> =
540
+ scheduledMaintenanceStates
541
+ .map((state: ScheduledMaintenanceState) => {
542
+ return {
543
+ title: state.name || "",
544
+ value: state._id?.toString() || "",
545
+ };
546
+ })
547
+ .filter((choice: { title: string; value: string }) => {
548
+ return choice.title && choice.value;
549
+ });
550
+
551
+ return {
552
+ type: "AdaptiveCard",
553
+ $schema: "http://adaptivecards.io/schemas/adaptive-card.json",
554
+ version: "1.5",
555
+ body: [
556
+ {
557
+ type: "TextBlock",
558
+ text: "Change Scheduled Maintenance State",
559
+ size: "Large",
560
+ weight: "Bolder",
561
+ },
562
+ {
563
+ type: "Input.ChoiceSet",
564
+ id: "stateId",
565
+ label: "Scheduled Maintenance State",
566
+ style: "compact",
567
+ choices: choices,
568
+ },
569
+ ],
570
+ actions: [
571
+ {
572
+ type: "Action.Submit",
573
+ title: "Change",
574
+ data: {
575
+ action:
576
+ MicrosoftTeamsScheduledMaintenanceActionType.SubmitChangeScheduledMaintenanceState,
577
+ scheduledMaintenanceId: scheduledMaintenanceId.toString(),
578
+ },
579
+ },
580
+ ],
581
+ };
582
+ }
583
+
584
+ @CaptureSpan()
585
+ public static async showNewScheduledMaintenanceCard(data: {
586
+ teamsRequest: MicrosoftTeamsRequest;
587
+ action: MicrosoftTeamsAction;
588
+ req: ExpressRequest;
589
+ res: ExpressResponse;
590
+ }): Promise<void> {
591
+ const { teamsRequest, req, res } = data;
592
+
593
+ logger.debug("Showing new scheduled maintenance card for Microsoft Teams");
594
+
595
+ // Send empty response first
596
+ Response.sendTextResponse(req, res, "");
597
+
598
+ if (!teamsRequest.projectId) {
599
+ logger.error("Project ID not found in Teams request");
600
+ return;
601
+ }
602
+
603
+ // Build the adaptive card with form fields
604
+ const card: JSONObject = await this.buildNewScheduledMaintenanceCard(
605
+ teamsRequest.projectId,
606
+ );
607
+
608
+ /*
609
+ * Send card as a message (note: in real Teams bot, this would be sent via TurnContext)
610
+ * For now, we'll just log it. The actual sending will be done through the bot framework
611
+ */
612
+ logger.debug("New scheduled maintenance card built:");
613
+ logger.debug(JSON.stringify(card, null, 2));
614
+ }
615
+
616
+ @CaptureSpan()
617
+ public static async submitNewScheduledMaintenance(data: {
618
+ teamsRequest: MicrosoftTeamsRequest;
619
+ action: MicrosoftTeamsAction;
620
+ req: ExpressRequest;
621
+ res: ExpressResponse;
622
+ }): Promise<void> {
623
+ const { teamsRequest, req, res } = data;
624
+ const { userId, projectId } = teamsRequest;
625
+
626
+ logger.debug("Submitting new scheduled maintenance from Microsoft Teams");
627
+
628
+ if (!projectId) {
629
+ return Response.sendErrorResponse(
630
+ req,
631
+ res,
632
+ new BadDataException("Invalid Project ID"),
633
+ );
634
+ }
635
+
636
+ if (!userId) {
637
+ return Response.sendErrorResponse(
638
+ req,
639
+ res,
640
+ new BadDataException("Invalid User ID"),
641
+ );
642
+ }
643
+
644
+ // Send early response
645
+ Response.sendTextResponse(req, res, "");
646
+
647
+ // Extract form data from the payload
648
+ const payload: JSONObject = teamsRequest.payload || {};
649
+ const value: JSONObject = (payload["value"] as JSONObject) || {};
650
+
651
+ const title: string = (value["scheduledMaintenanceTitle"] as string) || "";
652
+ const description: string =
653
+ (value["scheduledMaintenanceDescription"] as string) || "";
654
+ const startDate: string = (value["startDate"] as string) || "";
655
+ const endDate: string = (value["endDate"] as string) || "";
656
+ const monitorIds: string =
657
+ (value["scheduledMaintenanceMonitors"] as string) || "";
658
+ const monitorStatusId: string = (value["monitorStatus"] as string) || "";
659
+ const labelIds: string = (value["labels"] as string) || "";
660
+
661
+ if (!title || !description || !startDate || !endDate) {
662
+ logger.error(
663
+ "Missing required fields for scheduled maintenance creation",
664
+ );
665
+ return;
666
+ }
667
+
668
+ try {
669
+ // Get OneUptime user ID
670
+ const oneUptimeUserId: ObjectID =
671
+ await MicrosoftTeamsAuthAction.getOneUptimeUserIdFromTeamsUserId({
672
+ teamsUserId: userId,
673
+ projectId: projectId,
674
+ });
675
+
676
+ // Create the scheduled maintenance
677
+ const scheduledMaintenance: ScheduledMaintenance =
678
+ new ScheduledMaintenance();
679
+ scheduledMaintenance.title = title;
680
+ scheduledMaintenance.description = description;
681
+ scheduledMaintenance.projectId = projectId;
682
+ scheduledMaintenance.createdByUserId = oneUptimeUserId;
683
+ scheduledMaintenance.startsAt = OneUptimeDate.fromString(startDate);
684
+ scheduledMaintenance.endsAt = OneUptimeDate.fromString(endDate);
685
+
686
+ // Parse monitors
687
+ if (monitorIds) {
688
+ const monitorIdArray: Array<string> = monitorIds
689
+ .split(",")
690
+ .map((id: string) => {
691
+ return id.trim();
692
+ })
693
+ .filter((id: string) => {
694
+ return id;
695
+ });
696
+ if (monitorIdArray.length > 0) {
697
+ scheduledMaintenance.monitors = monitorIdArray.map((id: string) => {
698
+ const monitor: Monitor = new Monitor();
699
+ monitor.id = new ObjectID(id);
700
+ return monitor;
701
+ });
702
+ }
703
+ }
704
+
705
+ // Parse labels
706
+ if (labelIds) {
707
+ const labelIdArray: Array<string> = labelIds
708
+ .split(",")
709
+ .map((id: string) => {
710
+ return id.trim();
711
+ })
712
+ .filter((id: string) => {
713
+ return id;
714
+ });
715
+ if (labelIdArray.length > 0) {
716
+ scheduledMaintenance.labels = labelIdArray.map((id: string) => {
717
+ const label: Label = new Label();
718
+ label.id = new ObjectID(id);
719
+ return label;
720
+ });
721
+ }
722
+ }
723
+
724
+ // Save the scheduled maintenance
725
+ const createdScheduledMaintenance: ScheduledMaintenance =
726
+ await ScheduledMaintenanceService.create({
727
+ data: scheduledMaintenance,
728
+ props: {
729
+ isRoot: true,
730
+ },
731
+ });
732
+
733
+ logger.debug(
734
+ "Scheduled maintenance created successfully: " +
735
+ createdScheduledMaintenance.id?.toString(),
736
+ );
737
+
738
+ // Update monitor status if specified
739
+ if (monitorStatusId && monitorIds) {
740
+ const monitorIdArray: Array<string> = monitorIds
741
+ .split(",")
742
+ .map((id: string) => {
743
+ return id.trim();
744
+ })
745
+ .filter((id: string) => {
746
+ return id;
747
+ });
748
+ for (const monitorId of monitorIdArray) {
749
+ await MonitorService.updateOneById({
750
+ id: new ObjectID(monitorId),
751
+ data: {
752
+ currentMonitorStatusId: new ObjectID(monitorStatusId),
753
+ },
754
+ props: {
755
+ isRoot: true,
756
+ },
757
+ });
758
+ }
759
+ }
760
+
761
+ logger.debug(
762
+ "New scheduled maintenance created from Microsoft Teams successfully",
763
+ );
764
+ } catch (error) {
765
+ logger.error(
766
+ "Error creating scheduled maintenance from Microsoft Teams:",
767
+ );
768
+ logger.error(error);
769
+ }
770
+ }
771
+
772
+ public static async buildNewScheduledMaintenanceCard(
773
+ projectId: ObjectID,
774
+ ): Promise<JSONObject> {
775
+ // Fetch monitors
776
+ const monitors: Array<Monitor> = await MonitorService.findBy({
777
+ query: {
778
+ projectId: projectId,
779
+ },
780
+ select: {
781
+ name: true,
782
+ },
783
+ props: {
784
+ isRoot: true,
785
+ },
786
+ limit: LIMIT_PER_PROJECT,
787
+ skip: 0,
788
+ });
789
+
790
+ const monitorChoices: Array<{ title: string; value: string }> = monitors
791
+ .map((monitor: Monitor) => {
792
+ return {
793
+ title: monitor.name || "",
794
+ value: monitor._id?.toString() || "",
795
+ };
796
+ })
797
+ .filter((choice: { title: string; value: string }) => {
798
+ return choice.title && choice.value;
799
+ });
800
+
801
+ // Fetch monitor statuses
802
+ const monitorStatuses: Array<MonitorStatus> =
803
+ await MonitorStatusService.findBy({
804
+ query: {
805
+ projectId: projectId,
806
+ },
807
+ select: {
808
+ name: true,
809
+ },
810
+ props: {
811
+ isRoot: true,
812
+ },
813
+ sort: {
814
+ priority: SortOrder.Ascending,
815
+ },
816
+ limit: LIMIT_PER_PROJECT,
817
+ skip: 0,
818
+ });
819
+
820
+ const monitorStatusChoices: Array<{ title: string; value: string }> =
821
+ monitorStatuses
822
+ .map((status: MonitorStatus) => {
823
+ return {
824
+ title: status.name || "",
825
+ value: status._id?.toString() || "",
826
+ };
827
+ })
828
+ .filter((choice: { title: string; value: string }) => {
829
+ return choice.title && choice.value;
830
+ });
831
+
832
+ // Fetch labels
833
+ const labels: Array<Label> = await LabelService.findBy({
834
+ query: {
835
+ projectId: projectId,
836
+ },
837
+ select: {
838
+ name: true,
839
+ },
840
+ props: {
841
+ isRoot: true,
842
+ },
843
+ limit: LIMIT_PER_PROJECT,
844
+ skip: 0,
845
+ });
846
+
847
+ const labelChoices: Array<{ title: string; value: string }> = labels
848
+ .map((label: Label) => {
849
+ return {
850
+ title: label.name || "",
851
+ value: label._id?.toString() || "",
852
+ };
853
+ })
854
+ .filter((choice: { title: string; value: string }) => {
855
+ return choice.title && choice.value;
856
+ });
857
+
858
+ // Build the card
859
+ const bodyElements: Array<JSONObject> = [
860
+ {
861
+ type: "TextBlock",
862
+ text: "Create New Scheduled Maintenance",
863
+ size: "Large",
864
+ weight: "Bolder",
865
+ },
866
+ {
867
+ type: "Input.Text",
868
+ id: "scheduledMaintenanceTitle",
869
+ label: "Event Title",
870
+ placeholder: "Enter maintenance event title",
871
+ isRequired: true,
872
+ },
873
+ {
874
+ type: "Input.Text",
875
+ id: "scheduledMaintenanceDescription",
876
+ label: "Event Description",
877
+ placeholder: "Enter maintenance event description",
878
+ isMultiline: true,
879
+ isRequired: true,
880
+ },
881
+ {
882
+ type: "Input.Date",
883
+ id: "startDate",
884
+ label: "Start Date",
885
+ isRequired: true,
886
+ },
887
+ {
888
+ type: "Input.Time",
889
+ id: "startTime",
890
+ label: "Start Time",
891
+ isRequired: true,
892
+ },
893
+ {
894
+ type: "Input.Date",
895
+ id: "endDate",
896
+ label: "End Date",
897
+ isRequired: true,
898
+ },
899
+ {
900
+ type: "Input.Time",
901
+ id: "endTime",
902
+ label: "End Time",
903
+ isRequired: true,
904
+ },
905
+ ];
906
+
907
+ // Add monitor multi-select if we have monitors
908
+ if (monitorChoices.length > 0) {
909
+ bodyElements.push({
910
+ type: "Input.ChoiceSet",
911
+ id: "scheduledMaintenanceMonitors",
912
+ label: "Affected Monitors (Optional)",
913
+ style: "compact",
914
+ isMultiSelect: true,
915
+ choices: monitorChoices,
916
+ });
917
+ }
918
+
919
+ // Add monitor status dropdown if we have statuses and monitors
920
+ if (monitorStatusChoices.length > 0 && monitorChoices.length > 0) {
921
+ bodyElements.push({
922
+ type: "Input.ChoiceSet",
923
+ id: "monitorStatus",
924
+ label: "Change Monitor Status To (Optional)",
925
+ style: "compact",
926
+ choices: monitorStatusChoices,
927
+ });
928
+ }
929
+
930
+ // Add labels multi-select if we have labels
931
+ if (labelChoices.length > 0) {
932
+ bodyElements.push({
933
+ type: "Input.ChoiceSet",
934
+ id: "labels",
935
+ label: "Labels (Optional)",
936
+ style: "compact",
937
+ isMultiSelect: true,
938
+ choices: labelChoices,
939
+ });
940
+ }
941
+
942
+ return {
943
+ type: "AdaptiveCard",
944
+ $schema: "http://adaptivecards.io/schemas/adaptive-card.json",
945
+ version: "1.5",
946
+ body: bodyElements,
947
+ actions: [
948
+ {
949
+ type: "Action.Submit",
950
+ title: "Create Maintenance Event",
951
+ data: {
952
+ action:
953
+ MicrosoftTeamsScheduledMaintenanceActionType.SubmitNewScheduledMaintenance,
954
+ },
955
+ },
956
+ ],
957
+ };
958
+ }
959
+ }