@rapidmx/restapi 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (435) hide show
  1. package/LICENSE +382 -0
  2. package/README.md +50 -0
  3. package/dist/lib/blob/BlobStore.js +6 -0
  4. package/dist/lib/blob/BlobStore.js.map +1 -0
  5. package/dist/lib/blob/LocalFsBlobStore.js +101 -0
  6. package/dist/lib/blob/LocalFsBlobStore.js.map +1 -0
  7. package/dist/lib/blob/index.js +7 -0
  8. package/dist/lib/blob/index.js.map +1 -0
  9. package/dist/lib/index.js +12 -0
  10. package/dist/lib/index.js.map +1 -0
  11. package/dist/lib/jobs/AttachmentExtractionJob.js +124 -0
  12. package/dist/lib/jobs/AttachmentExtractionJob.js.map +1 -0
  13. package/dist/lib/jobs/CalendarReminderJob.js +132 -0
  14. package/dist/lib/jobs/CalendarReminderJob.js.map +1 -0
  15. package/dist/lib/jobs/EasDeviceStateCleanupJob.js +101 -0
  16. package/dist/lib/jobs/EasDeviceStateCleanupJob.js.map +1 -0
  17. package/dist/lib/jobs/ExternalShareExpirationJob.js +117 -0
  18. package/dist/lib/jobs/ExternalShareExpirationJob.js.map +1 -0
  19. package/dist/lib/jobs/MailboxQuotaRecalcJob.js +163 -0
  20. package/dist/lib/jobs/MailboxQuotaRecalcJob.js.map +1 -0
  21. package/dist/lib/jobs/MeetingSchedulingJob.js +106 -0
  22. package/dist/lib/jobs/MeetingSchedulingJob.js.map +1 -0
  23. package/dist/lib/jobs/QuarantineRetentionJob.js +97 -0
  24. package/dist/lib/jobs/QuarantineRetentionJob.js.map +1 -0
  25. package/dist/lib/jobs/ScanQueueJob.js +223 -0
  26. package/dist/lib/jobs/ScanQueueJob.js.map +1 -0
  27. package/dist/lib/jobs/SearchIndexJob.js +146 -0
  28. package/dist/lib/jobs/SearchIndexJob.js.map +1 -0
  29. package/dist/lib/jobs/index.js +10 -0
  30. package/dist/lib/jobs/index.js.map +1 -0
  31. package/dist/lib/jobs/mongo/AttachmentExtractionJobMongo.js +14 -0
  32. package/dist/lib/jobs/mongo/AttachmentExtractionJobMongo.js.map +1 -0
  33. package/dist/lib/jobs/mongo/CalendarReminderJobMongo.js +13 -0
  34. package/dist/lib/jobs/mongo/CalendarReminderJobMongo.js.map +1 -0
  35. package/dist/lib/jobs/mongo/EasDeviceStateCleanupJobMongo.js +13 -0
  36. package/dist/lib/jobs/mongo/EasDeviceStateCleanupJobMongo.js.map +1 -0
  37. package/dist/lib/jobs/mongo/ExternalShareExpirationJobMongo.js +13 -0
  38. package/dist/lib/jobs/mongo/ExternalShareExpirationJobMongo.js.map +1 -0
  39. package/dist/lib/jobs/mongo/MailboxQuotaRecalcJobMongo.js +15 -0
  40. package/dist/lib/jobs/mongo/MailboxQuotaRecalcJobMongo.js.map +1 -0
  41. package/dist/lib/jobs/mongo/MeetingSchedulingJobMongo.js +13 -0
  42. package/dist/lib/jobs/mongo/MeetingSchedulingJobMongo.js.map +1 -0
  43. package/dist/lib/jobs/mongo/QuarantineRetentionJobMongo.js +13 -0
  44. package/dist/lib/jobs/mongo/QuarantineRetentionJobMongo.js.map +1 -0
  45. package/dist/lib/jobs/mongo/ScanQueueJobMongo.js +18 -0
  46. package/dist/lib/jobs/mongo/ScanQueueJobMongo.js.map +1 -0
  47. package/dist/lib/jobs/mongo/SearchIndexJobMongo.js +14 -0
  48. package/dist/lib/jobs/mongo/SearchIndexJobMongo.js.map +1 -0
  49. package/dist/lib/jobs/mongo/index.js +10 -0
  50. package/dist/lib/jobs/mongo/index.js.map +1 -0
  51. package/dist/lib/jobs/mongo.js +2 -0
  52. package/dist/lib/jobs/mongo.js.map +1 -0
  53. package/dist/lib/jobs/sql/AttachmentExtractionJobSQL.js +14 -0
  54. package/dist/lib/jobs/sql/AttachmentExtractionJobSQL.js.map +1 -0
  55. package/dist/lib/jobs/sql/CalendarReminderJobSQL.js +13 -0
  56. package/dist/lib/jobs/sql/CalendarReminderJobSQL.js.map +1 -0
  57. package/dist/lib/jobs/sql/EasDeviceStateCleanupJobSQL.js +13 -0
  58. package/dist/lib/jobs/sql/EasDeviceStateCleanupJobSQL.js.map +1 -0
  59. package/dist/lib/jobs/sql/ExternalShareExpirationJobSQL.js +13 -0
  60. package/dist/lib/jobs/sql/ExternalShareExpirationJobSQL.js.map +1 -0
  61. package/dist/lib/jobs/sql/MailboxQuotaRecalcJobSQL.js +15 -0
  62. package/dist/lib/jobs/sql/MailboxQuotaRecalcJobSQL.js.map +1 -0
  63. package/dist/lib/jobs/sql/MeetingSchedulingJobSQL.js +13 -0
  64. package/dist/lib/jobs/sql/MeetingSchedulingJobSQL.js.map +1 -0
  65. package/dist/lib/jobs/sql/QuarantineRetentionJobSQL.js +13 -0
  66. package/dist/lib/jobs/sql/QuarantineRetentionJobSQL.js.map +1 -0
  67. package/dist/lib/jobs/sql/ScanQueueJobSQL.js +18 -0
  68. package/dist/lib/jobs/sql/ScanQueueJobSQL.js.map +1 -0
  69. package/dist/lib/jobs/sql/SearchIndexJobSQL.js +14 -0
  70. package/dist/lib/jobs/sql/SearchIndexJobSQL.js.map +1 -0
  71. package/dist/lib/jobs/sql/index.js +10 -0
  72. package/dist/lib/jobs/sql/index.js.map +1 -0
  73. package/dist/lib/jobs/sql.js +2 -0
  74. package/dist/lib/jobs/sql.js.map +1 -0
  75. package/dist/lib/models/index.js +2 -0
  76. package/dist/lib/models/index.js.map +1 -0
  77. package/dist/lib/models/mongo/AttachmentMongo.js +129 -0
  78. package/dist/lib/models/mongo/AttachmentMongo.js.map +1 -0
  79. package/dist/lib/models/mongo/CalendarEventMongo.js +172 -0
  80. package/dist/lib/models/mongo/CalendarEventMongo.js.map +1 -0
  81. package/dist/lib/models/mongo/CalendarShareLinkMongo.js +85 -0
  82. package/dist/lib/models/mongo/CalendarShareLinkMongo.js.map +1 -0
  83. package/dist/lib/models/mongo/ContactListMongo.js +60 -0
  84. package/dist/lib/models/mongo/ContactListMongo.js.map +1 -0
  85. package/dist/lib/models/mongo/ContactMongo.js +148 -0
  86. package/dist/lib/models/mongo/ContactMongo.js.map +1 -0
  87. package/dist/lib/models/mongo/DeviceSyncStateMongo.js +97 -0
  88. package/dist/lib/models/mongo/DeviceSyncStateMongo.js.map +1 -0
  89. package/dist/lib/models/mongo/FolderMongo.js +102 -0
  90. package/dist/lib/models/mongo/FolderMongo.js.map +1 -0
  91. package/dist/lib/models/mongo/IngestQueueEntryMongo.js +93 -0
  92. package/dist/lib/models/mongo/IngestQueueEntryMongo.js.map +1 -0
  93. package/dist/lib/models/mongo/MailboxMongo.js +105 -0
  94. package/dist/lib/models/mongo/MailboxMongo.js.map +1 -0
  95. package/dist/lib/models/mongo/MessageMongo.js +180 -0
  96. package/dist/lib/models/mongo/MessageMongo.js.map +1 -0
  97. package/dist/lib/models/mongo/NoteMongo.js +83 -0
  98. package/dist/lib/models/mongo/NoteMongo.js.map +1 -0
  99. package/dist/lib/models/mongo/QuarantineEntryMongo.js +99 -0
  100. package/dist/lib/models/mongo/QuarantineEntryMongo.js.map +1 -0
  101. package/dist/lib/models/mongo/ScanResultMongo.js +112 -0
  102. package/dist/lib/models/mongo/ScanResultMongo.js.map +1 -0
  103. package/dist/lib/models/mongo/SearchIndexStateMongo.js +83 -0
  104. package/dist/lib/models/mongo/SearchIndexStateMongo.js.map +1 -0
  105. package/dist/lib/models/mongo/TaskMongo.js +105 -0
  106. package/dist/lib/models/mongo/TaskMongo.js.map +1 -0
  107. package/dist/lib/models/mongo/index.js +16 -0
  108. package/dist/lib/models/mongo/index.js.map +1 -0
  109. package/dist/lib/models/mongo.js +2 -0
  110. package/dist/lib/models/mongo.js.map +1 -0
  111. package/dist/lib/models/sql/AttachmentSQL.js +129 -0
  112. package/dist/lib/models/sql/AttachmentSQL.js.map +1 -0
  113. package/dist/lib/models/sql/CalendarEventSQL.js +176 -0
  114. package/dist/lib/models/sql/CalendarEventSQL.js.map +1 -0
  115. package/dist/lib/models/sql/CalendarShareLinkSQL.js +85 -0
  116. package/dist/lib/models/sql/CalendarShareLinkSQL.js.map +1 -0
  117. package/dist/lib/models/sql/ContactListSQL.js +60 -0
  118. package/dist/lib/models/sql/ContactListSQL.js.map +1 -0
  119. package/dist/lib/models/sql/ContactSQL.js +148 -0
  120. package/dist/lib/models/sql/ContactSQL.js.map +1 -0
  121. package/dist/lib/models/sql/DeviceSyncStateSQL.js +97 -0
  122. package/dist/lib/models/sql/DeviceSyncStateSQL.js.map +1 -0
  123. package/dist/lib/models/sql/FolderSQL.js +106 -0
  124. package/dist/lib/models/sql/FolderSQL.js.map +1 -0
  125. package/dist/lib/models/sql/IngestQueueEntrySQL.js +97 -0
  126. package/dist/lib/models/sql/IngestQueueEntrySQL.js.map +1 -0
  127. package/dist/lib/models/sql/MailboxSQL.js +105 -0
  128. package/dist/lib/models/sql/MailboxSQL.js.map +1 -0
  129. package/dist/lib/models/sql/MessageSQL.js +184 -0
  130. package/dist/lib/models/sql/MessageSQL.js.map +1 -0
  131. package/dist/lib/models/sql/NoteSQL.js +83 -0
  132. package/dist/lib/models/sql/NoteSQL.js.map +1 -0
  133. package/dist/lib/models/sql/QuarantineEntrySQL.js +103 -0
  134. package/dist/lib/models/sql/QuarantineEntrySQL.js.map +1 -0
  135. package/dist/lib/models/sql/ScanResultSQL.js +116 -0
  136. package/dist/lib/models/sql/ScanResultSQL.js.map +1 -0
  137. package/dist/lib/models/sql/SearchIndexStateSQL.js +83 -0
  138. package/dist/lib/models/sql/SearchIndexStateSQL.js.map +1 -0
  139. package/dist/lib/models/sql/TaskSQL.js +109 -0
  140. package/dist/lib/models/sql/TaskSQL.js.map +1 -0
  141. package/dist/lib/models/sql/index.js +16 -0
  142. package/dist/lib/models/sql/index.js.map +1 -0
  143. package/dist/lib/models/sql.js +2 -0
  144. package/dist/lib/models/sql.js.map +1 -0
  145. package/dist/lib/models/types.js +108 -0
  146. package/dist/lib/models/types.js.map +1 -0
  147. package/dist/lib/mongo.js +8 -0
  148. package/dist/lib/mongo.js.map +1 -0
  149. package/dist/lib/push/MailPushRoute.js +42 -0
  150. package/dist/lib/push/MailPushRoute.js.map +1 -0
  151. package/dist/lib/push/index.js +6 -0
  152. package/dist/lib/push/index.js.map +1 -0
  153. package/dist/lib/routes/BaseAttachmentRoute.js +142 -0
  154. package/dist/lib/routes/BaseAttachmentRoute.js.map +1 -0
  155. package/dist/lib/routes/BaseCalendarShareLinkRoute.js +123 -0
  156. package/dist/lib/routes/BaseCalendarShareLinkRoute.js.map +1 -0
  157. package/dist/lib/routes/BaseFolderRoute.js +192 -0
  158. package/dist/lib/routes/BaseFolderRoute.js.map +1 -0
  159. package/dist/lib/routes/BaseMailIngestRoute.js +179 -0
  160. package/dist/lib/routes/BaseMailIngestRoute.js.map +1 -0
  161. package/dist/lib/routes/BaseMailboxRoute.js +187 -0
  162. package/dist/lib/routes/BaseMailboxRoute.js.map +1 -0
  163. package/dist/lib/routes/BaseMessageRoute.js +142 -0
  164. package/dist/lib/routes/BaseMessageRoute.js.map +1 -0
  165. package/dist/lib/routes/BaseScopedChildRoute.js +348 -0
  166. package/dist/lib/routes/BaseScopedChildRoute.js.map +1 -0
  167. package/dist/lib/routes/BaseSearchRoute.js +91 -0
  168. package/dist/lib/routes/BaseSearchRoute.js.map +1 -0
  169. package/dist/lib/routes/index.js +13 -0
  170. package/dist/lib/routes/index.js.map +1 -0
  171. package/dist/lib/routes/mongo/AttachmentRouteMongo.js +26 -0
  172. package/dist/lib/routes/mongo/AttachmentRouteMongo.js.map +1 -0
  173. package/dist/lib/routes/mongo/CalendarEventRouteMongo.js +27 -0
  174. package/dist/lib/routes/mongo/CalendarEventRouteMongo.js.map +1 -0
  175. package/dist/lib/routes/mongo/CalendarShareLinkRouteMongo.js +26 -0
  176. package/dist/lib/routes/mongo/CalendarShareLinkRouteMongo.js.map +1 -0
  177. package/dist/lib/routes/mongo/ContactListRouteMongo.js +26 -0
  178. package/dist/lib/routes/mongo/ContactListRouteMongo.js.map +1 -0
  179. package/dist/lib/routes/mongo/ContactRouteMongo.js +27 -0
  180. package/dist/lib/routes/mongo/ContactRouteMongo.js.map +1 -0
  181. package/dist/lib/routes/mongo/FolderRouteMongo.js +26 -0
  182. package/dist/lib/routes/mongo/FolderRouteMongo.js.map +1 -0
  183. package/dist/lib/routes/mongo/IngestQueueRouteMongo.js +33 -0
  184. package/dist/lib/routes/mongo/IngestQueueRouteMongo.js.map +1 -0
  185. package/dist/lib/routes/mongo/MailIngestRouteMongo.js +14 -0
  186. package/dist/lib/routes/mongo/MailIngestRouteMongo.js.map +1 -0
  187. package/dist/lib/routes/mongo/MailboxRouteMongo.js +39 -0
  188. package/dist/lib/routes/mongo/MailboxRouteMongo.js.map +1 -0
  189. package/dist/lib/routes/mongo/MessageRouteMongo.js +27 -0
  190. package/dist/lib/routes/mongo/MessageRouteMongo.js.map +1 -0
  191. package/dist/lib/routes/mongo/NoteRouteMongo.js +26 -0
  192. package/dist/lib/routes/mongo/NoteRouteMongo.js.map +1 -0
  193. package/dist/lib/routes/mongo/QuarantineRouteMongo.js +35 -0
  194. package/dist/lib/routes/mongo/QuarantineRouteMongo.js.map +1 -0
  195. package/dist/lib/routes/mongo/SearchRouteMongo.js +13 -0
  196. package/dist/lib/routes/mongo/SearchRouteMongo.js.map +1 -0
  197. package/dist/lib/routes/mongo/TaskRouteMongo.js +27 -0
  198. package/dist/lib/routes/mongo/TaskRouteMongo.js.map +1 -0
  199. package/dist/lib/routes/mongo/index.js +15 -0
  200. package/dist/lib/routes/mongo/index.js.map +1 -0
  201. package/dist/lib/routes/mongo.js +2 -0
  202. package/dist/lib/routes/mongo.js.map +1 -0
  203. package/dist/lib/routes/sql/AttachmentRouteSQL.js +26 -0
  204. package/dist/lib/routes/sql/AttachmentRouteSQL.js.map +1 -0
  205. package/dist/lib/routes/sql/CalendarEventRouteSQL.js +27 -0
  206. package/dist/lib/routes/sql/CalendarEventRouteSQL.js.map +1 -0
  207. package/dist/lib/routes/sql/CalendarShareLinkRouteSQL.js +26 -0
  208. package/dist/lib/routes/sql/CalendarShareLinkRouteSQL.js.map +1 -0
  209. package/dist/lib/routes/sql/ContactListRouteSQL.js +26 -0
  210. package/dist/lib/routes/sql/ContactListRouteSQL.js.map +1 -0
  211. package/dist/lib/routes/sql/ContactRouteSQL.js +27 -0
  212. package/dist/lib/routes/sql/ContactRouteSQL.js.map +1 -0
  213. package/dist/lib/routes/sql/FolderRouteSQL.js +26 -0
  214. package/dist/lib/routes/sql/FolderRouteSQL.js.map +1 -0
  215. package/dist/lib/routes/sql/IngestQueueRouteSQL.js +29 -0
  216. package/dist/lib/routes/sql/IngestQueueRouteSQL.js.map +1 -0
  217. package/dist/lib/routes/sql/MailIngestRouteSQL.js +35 -0
  218. package/dist/lib/routes/sql/MailIngestRouteSQL.js.map +1 -0
  219. package/dist/lib/routes/sql/MailboxRouteSQL.js +64 -0
  220. package/dist/lib/routes/sql/MailboxRouteSQL.js.map +1 -0
  221. package/dist/lib/routes/sql/MessageRouteSQL.js +27 -0
  222. package/dist/lib/routes/sql/MessageRouteSQL.js.map +1 -0
  223. package/dist/lib/routes/sql/NoteRouteSQL.js +26 -0
  224. package/dist/lib/routes/sql/NoteRouteSQL.js.map +1 -0
  225. package/dist/lib/routes/sql/QuarantineRouteSQL.js +29 -0
  226. package/dist/lib/routes/sql/QuarantineRouteSQL.js.map +1 -0
  227. package/dist/lib/routes/sql/SearchRouteSQL.js +13 -0
  228. package/dist/lib/routes/sql/SearchRouteSQL.js.map +1 -0
  229. package/dist/lib/routes/sql/TaskRouteSQL.js +27 -0
  230. package/dist/lib/routes/sql/TaskRouteSQL.js.map +1 -0
  231. package/dist/lib/routes/sql/index.js +15 -0
  232. package/dist/lib/routes/sql/index.js.map +1 -0
  233. package/dist/lib/routes/sql.js +2 -0
  234. package/dist/lib/routes/sql.js.map +1 -0
  235. package/dist/lib/scan/AvScanProvider.js +2 -0
  236. package/dist/lib/scan/AvScanProvider.js.map +1 -0
  237. package/dist/lib/scan/ClamAvScanProvider.js +112 -0
  238. package/dist/lib/scan/ClamAvScanProvider.js.map +1 -0
  239. package/dist/lib/scan/RspamdSpamScanProvider.js +100 -0
  240. package/dist/lib/scan/RspamdSpamScanProvider.js.map +1 -0
  241. package/dist/lib/scan/ScanPipeline.js +118 -0
  242. package/dist/lib/scan/ScanPipeline.js.map +1 -0
  243. package/dist/lib/scan/SpamScanProvider.js +2 -0
  244. package/dist/lib/scan/SpamScanProvider.js.map +1 -0
  245. package/dist/lib/scan/index.js +10 -0
  246. package/dist/lib/scan/index.js.map +1 -0
  247. package/dist/lib/search/MongoTextSearchProvider.js +116 -0
  248. package/dist/lib/search/MongoTextSearchProvider.js.map +1 -0
  249. package/dist/lib/search/OpenSearchProvider.js +156 -0
  250. package/dist/lib/search/OpenSearchProvider.js.map +1 -0
  251. package/dist/lib/search/PostgresFullTextSearchProvider.js +139 -0
  252. package/dist/lib/search/PostgresFullTextSearchProvider.js.map +1 -0
  253. package/dist/lib/search/SearchProvider.js +6 -0
  254. package/dist/lib/search/SearchProvider.js.map +1 -0
  255. package/dist/lib/search/extraction/DocxTextExtractor.js +27 -0
  256. package/dist/lib/search/extraction/DocxTextExtractor.js.map +1 -0
  257. package/dist/lib/search/extraction/ExtractorRegistry.js +82 -0
  258. package/dist/lib/search/extraction/ExtractorRegistry.js.map +1 -0
  259. package/dist/lib/search/extraction/HtmlTextExtractor.js +20 -0
  260. package/dist/lib/search/extraction/HtmlTextExtractor.js.map +1 -0
  261. package/dist/lib/search/extraction/PdfTextExtractor.js +22 -0
  262. package/dist/lib/search/extraction/PdfTextExtractor.js.map +1 -0
  263. package/dist/lib/search/extraction/PlainTextExtractor.js +14 -0
  264. package/dist/lib/search/extraction/PlainTextExtractor.js.map +1 -0
  265. package/dist/lib/search/extraction/TextExtractor.js +6 -0
  266. package/dist/lib/search/extraction/TextExtractor.js.map +1 -0
  267. package/dist/lib/search/index.js +15 -0
  268. package/dist/lib/search/index.js.map +1 -0
  269. package/dist/lib/sql.js +8 -0
  270. package/dist/lib/sql.js.map +1 -0
  271. package/dist/lib/transport/MTAIngestAdapter.js +30 -0
  272. package/dist/lib/transport/MTAIngestAdapter.js.map +1 -0
  273. package/dist/lib/transport/MailTransport.js +6 -0
  274. package/dist/lib/transport/MailTransport.js.map +1 -0
  275. package/dist/lib/transport/PostfixSendmailTransport.js +61 -0
  276. package/dist/lib/transport/PostfixSendmailTransport.js.map +1 -0
  277. package/dist/lib/transport/index.js +8 -0
  278. package/dist/lib/transport/index.js.map +1 -0
  279. package/dist/lib/util/FolderUtils.js +50 -0
  280. package/dist/lib/util/FolderUtils.js.map +1 -0
  281. package/dist/lib/util/MailSendUtils.js +36 -0
  282. package/dist/lib/util/MailSendUtils.js.map +1 -0
  283. package/dist/lib/util/MailboxScopeUtils.js +23 -0
  284. package/dist/lib/util/MailboxScopeUtils.js.map +1 -0
  285. package/dist/lib/util/OptionalDeps.js +23 -0
  286. package/dist/lib/util/OptionalDeps.js.map +1 -0
  287. package/dist/lib/util/RecoverableRepoUtils.js +42 -0
  288. package/dist/lib/util/RecoverableRepoUtils.js.map +1 -0
  289. package/dist/lib/util/index.js +17 -0
  290. package/dist/lib/util/index.js.map +1 -0
  291. package/dist/types/blob/BlobStore.d.ts +54 -0
  292. package/dist/types/blob/LocalFsBlobStore.d.ts +23 -0
  293. package/dist/types/blob/index.d.ts +2 -0
  294. package/dist/types/index.d.ts +7 -0
  295. package/dist/types/jobs/AttachmentExtractionJob.d.ts +34 -0
  296. package/dist/types/jobs/CalendarReminderJob.d.ts +37 -0
  297. package/dist/types/jobs/EasDeviceStateCleanupJob.d.ts +26 -0
  298. package/dist/types/jobs/ExternalShareExpirationJob.d.ts +34 -0
  299. package/dist/types/jobs/MailboxQuotaRecalcJob.d.ts +44 -0
  300. package/dist/types/jobs/MeetingSchedulingJob.d.ts +32 -0
  301. package/dist/types/jobs/QuarantineRetentionJob.d.ts +27 -0
  302. package/dist/types/jobs/ScanQueueJob.d.ts +41 -0
  303. package/dist/types/jobs/SearchIndexJob.d.ts +37 -0
  304. package/dist/types/jobs/index.d.ts +9 -0
  305. package/dist/types/jobs/mongo/AttachmentExtractionJobMongo.d.ts +6 -0
  306. package/dist/types/jobs/mongo/CalendarReminderJobMongo.d.ts +5 -0
  307. package/dist/types/jobs/mongo/EasDeviceStateCleanupJobMongo.d.ts +5 -0
  308. package/dist/types/jobs/mongo/ExternalShareExpirationJobMongo.d.ts +5 -0
  309. package/dist/types/jobs/mongo/MailboxQuotaRecalcJobMongo.d.ts +7 -0
  310. package/dist/types/jobs/mongo/MeetingSchedulingJobMongo.d.ts +5 -0
  311. package/dist/types/jobs/mongo/QuarantineRetentionJobMongo.d.ts +5 -0
  312. package/dist/types/jobs/mongo/ScanQueueJobMongo.d.ts +10 -0
  313. package/dist/types/jobs/mongo/SearchIndexJobMongo.d.ts +6 -0
  314. package/dist/types/jobs/mongo/index.d.ts +9 -0
  315. package/dist/types/jobs/mongo.d.ts +1 -0
  316. package/dist/types/jobs/sql/AttachmentExtractionJobSQL.d.ts +6 -0
  317. package/dist/types/jobs/sql/CalendarReminderJobSQL.d.ts +5 -0
  318. package/dist/types/jobs/sql/EasDeviceStateCleanupJobSQL.d.ts +5 -0
  319. package/dist/types/jobs/sql/ExternalShareExpirationJobSQL.d.ts +5 -0
  320. package/dist/types/jobs/sql/MailboxQuotaRecalcJobSQL.d.ts +7 -0
  321. package/dist/types/jobs/sql/MeetingSchedulingJobSQL.d.ts +5 -0
  322. package/dist/types/jobs/sql/QuarantineRetentionJobSQL.d.ts +5 -0
  323. package/dist/types/jobs/sql/ScanQueueJobSQL.d.ts +10 -0
  324. package/dist/types/jobs/sql/SearchIndexJobSQL.d.ts +6 -0
  325. package/dist/types/jobs/sql/index.d.ts +9 -0
  326. package/dist/types/jobs/sql.d.ts +1 -0
  327. package/dist/types/models/index.d.ts +1 -0
  328. package/dist/types/models/mongo/AttachmentMongo.d.ts +22 -0
  329. package/dist/types/models/mongo/CalendarEventMongo.d.ts +28 -0
  330. package/dist/types/models/mongo/CalendarShareLinkMongo.d.ts +16 -0
  331. package/dist/types/models/mongo/ContactListMongo.d.ts +13 -0
  332. package/dist/types/models/mongo/ContactMongo.d.ts +25 -0
  333. package/dist/types/models/mongo/DeviceSyncStateMongo.d.ts +18 -0
  334. package/dist/types/models/mongo/FolderMongo.d.ts +18 -0
  335. package/dist/types/models/mongo/IngestQueueEntryMongo.d.ts +17 -0
  336. package/dist/types/models/mongo/MailboxMongo.d.ts +18 -0
  337. package/dist/types/models/mongo/MessageMongo.d.ts +29 -0
  338. package/dist/types/models/mongo/NoteMongo.d.ts +16 -0
  339. package/dist/types/models/mongo/QuarantineEntryMongo.d.ts +18 -0
  340. package/dist/types/models/mongo/ScanResultMongo.d.ts +23 -0
  341. package/dist/types/models/mongo/SearchIndexStateMongo.d.ts +16 -0
  342. package/dist/types/models/mongo/TaskMongo.d.ts +19 -0
  343. package/dist/types/models/mongo/index.d.ts +15 -0
  344. package/dist/types/models/mongo.d.ts +1 -0
  345. package/dist/types/models/sql/AttachmentSQL.d.ts +22 -0
  346. package/dist/types/models/sql/CalendarEventSQL.d.ts +28 -0
  347. package/dist/types/models/sql/CalendarShareLinkSQL.d.ts +16 -0
  348. package/dist/types/models/sql/ContactListSQL.d.ts +13 -0
  349. package/dist/types/models/sql/ContactSQL.d.ts +25 -0
  350. package/dist/types/models/sql/DeviceSyncStateSQL.d.ts +18 -0
  351. package/dist/types/models/sql/FolderSQL.d.ts +18 -0
  352. package/dist/types/models/sql/IngestQueueEntrySQL.d.ts +17 -0
  353. package/dist/types/models/sql/MailboxSQL.d.ts +18 -0
  354. package/dist/types/models/sql/MessageSQL.d.ts +29 -0
  355. package/dist/types/models/sql/NoteSQL.d.ts +16 -0
  356. package/dist/types/models/sql/QuarantineEntrySQL.d.ts +18 -0
  357. package/dist/types/models/sql/ScanResultSQL.d.ts +23 -0
  358. package/dist/types/models/sql/SearchIndexStateSQL.d.ts +16 -0
  359. package/dist/types/models/sql/TaskSQL.d.ts +19 -0
  360. package/dist/types/models/sql/index.d.ts +15 -0
  361. package/dist/types/models/sql.d.ts +1 -0
  362. package/dist/types/models/types.d.ts +541 -0
  363. package/dist/types/mongo.d.ts +3 -0
  364. package/dist/types/push/MailPushRoute.d.ts +37 -0
  365. package/dist/types/push/index.d.ts +1 -0
  366. package/dist/types/routes/BaseAttachmentRoute.d.ts +24 -0
  367. package/dist/types/routes/BaseCalendarShareLinkRoute.d.ts +35 -0
  368. package/dist/types/routes/BaseFolderRoute.d.ts +58 -0
  369. package/dist/types/routes/BaseMailIngestRoute.d.ts +47 -0
  370. package/dist/types/routes/BaseMailboxRoute.d.ts +60 -0
  371. package/dist/types/routes/BaseMessageRoute.d.ts +27 -0
  372. package/dist/types/routes/BaseScopedChildRoute.d.ts +61 -0
  373. package/dist/types/routes/BaseSearchRoute.d.ts +23 -0
  374. package/dist/types/routes/index.d.ts +8 -0
  375. package/dist/types/routes/mongo/AttachmentRouteMongo.d.ts +6 -0
  376. package/dist/types/routes/mongo/CalendarEventRouteMongo.d.ts +6 -0
  377. package/dist/types/routes/mongo/CalendarShareLinkRouteMongo.d.ts +6 -0
  378. package/dist/types/routes/mongo/ContactListRouteMongo.d.ts +6 -0
  379. package/dist/types/routes/mongo/ContactRouteMongo.d.ts +6 -0
  380. package/dist/types/routes/mongo/FolderRouteMongo.d.ts +5 -0
  381. package/dist/types/routes/mongo/IngestQueueRouteMongo.d.ts +13 -0
  382. package/dist/types/routes/mongo/MailIngestRouteMongo.d.ts +6 -0
  383. package/dist/types/routes/mongo/MailboxRouteMongo.d.ts +8 -0
  384. package/dist/types/routes/mongo/MessageRouteMongo.d.ts +6 -0
  385. package/dist/types/routes/mongo/NoteRouteMongo.d.ts +6 -0
  386. package/dist/types/routes/mongo/QuarantineRouteMongo.d.ts +15 -0
  387. package/dist/types/routes/mongo/SearchRouteMongo.d.ts +5 -0
  388. package/dist/types/routes/mongo/TaskRouteMongo.d.ts +6 -0
  389. package/dist/types/routes/mongo/index.d.ts +14 -0
  390. package/dist/types/routes/mongo.d.ts +1 -0
  391. package/dist/types/routes/sql/AttachmentRouteSQL.d.ts +6 -0
  392. package/dist/types/routes/sql/CalendarEventRouteSQL.d.ts +6 -0
  393. package/dist/types/routes/sql/CalendarShareLinkRouteSQL.d.ts +6 -0
  394. package/dist/types/routes/sql/ContactListRouteSQL.d.ts +6 -0
  395. package/dist/types/routes/sql/ContactRouteSQL.d.ts +6 -0
  396. package/dist/types/routes/sql/FolderRouteSQL.d.ts +5 -0
  397. package/dist/types/routes/sql/IngestQueueRouteSQL.d.ts +9 -0
  398. package/dist/types/routes/sql/MailIngestRouteSQL.d.ts +23 -0
  399. package/dist/types/routes/sql/MailboxRouteSQL.d.ts +22 -0
  400. package/dist/types/routes/sql/MessageRouteSQL.d.ts +6 -0
  401. package/dist/types/routes/sql/NoteRouteSQL.d.ts +6 -0
  402. package/dist/types/routes/sql/QuarantineRouteSQL.d.ts +9 -0
  403. package/dist/types/routes/sql/SearchRouteSQL.d.ts +5 -0
  404. package/dist/types/routes/sql/TaskRouteSQL.d.ts +6 -0
  405. package/dist/types/routes/sql/index.d.ts +14 -0
  406. package/dist/types/routes/sql.d.ts +1 -0
  407. package/dist/types/scan/AvScanProvider.d.ts +22 -0
  408. package/dist/types/scan/ClamAvScanProvider.d.ts +17 -0
  409. package/dist/types/scan/RspamdSpamScanProvider.d.ts +16 -0
  410. package/dist/types/scan/ScanPipeline.d.ts +53 -0
  411. package/dist/types/scan/SpamScanProvider.d.ts +29 -0
  412. package/dist/types/scan/index.d.ts +5 -0
  413. package/dist/types/search/MongoTextSearchProvider.d.ts +22 -0
  414. package/dist/types/search/OpenSearchProvider.d.ts +24 -0
  415. package/dist/types/search/PostgresFullTextSearchProvider.d.ts +21 -0
  416. package/dist/types/search/SearchProvider.d.ts +62 -0
  417. package/dist/types/search/extraction/DocxTextExtractor.d.ts +14 -0
  418. package/dist/types/search/extraction/ExtractorRegistry.d.ts +19 -0
  419. package/dist/types/search/extraction/HtmlTextExtractor.d.ts +11 -0
  420. package/dist/types/search/extraction/PdfTextExtractor.d.ts +10 -0
  421. package/dist/types/search/extraction/PlainTextExtractor.d.ts +10 -0
  422. package/dist/types/search/extraction/TextExtractor.d.ts +17 -0
  423. package/dist/types/search/index.d.ts +10 -0
  424. package/dist/types/sql.d.ts +3 -0
  425. package/dist/types/transport/MTAIngestAdapter.d.ts +25 -0
  426. package/dist/types/transport/MailTransport.d.ts +29 -0
  427. package/dist/types/transport/PostfixSendmailTransport.d.ts +15 -0
  428. package/dist/types/transport/index.d.ts +3 -0
  429. package/dist/types/util/FolderUtils.d.ts +15 -0
  430. package/dist/types/util/MailSendUtils.d.ts +19 -0
  431. package/dist/types/util/MailboxScopeUtils.d.ts +19 -0
  432. package/dist/types/util/OptionalDeps.d.ts +9 -0
  433. package/dist/types/util/RecoverableRepoUtils.d.ts +24 -0
  434. package/dist/types/util/index.d.ts +12 -0
  435. package/package.json +122 -0
@@ -0,0 +1,192 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ ///////////////////////////////////////////////////////////////////////////////
14
+ // Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
15
+ // SPDX-License-Identifier: MPL-2.0
16
+ ///////////////////////////////////////////////////////////////////////////////
17
+ import { ApiError } from "@rapidrest/core";
18
+ import { ACLAction, ApiErrorMessages, ApiErrors, CRUDRoute, RouteDecorators, } from "@rapidrest/service-core";
19
+ const { Get, Head, Param, Post, Query, Request, Response, User: AuthUser } = RouteDecorators;
20
+ /**
21
+ * See the identical helper (and its rationale for being duplicated rather than shared via a `util/` module)
22
+ * on `BaseScopedChildRoute.ts`.
23
+ */
24
+ function resolveEffectiveUser(user, query) {
25
+ if (user) {
26
+ return user;
27
+ }
28
+ const shareToken = query?.shareToken;
29
+ return typeof shareToken === "string" && shareToken.length > 0
30
+ ? ({ uid: shareToken, roles: [], scopes: [] })
31
+ : undefined;
32
+ }
33
+ /**
34
+ * Extends the standard `CRUDRoute` CRUD scaffolding for `Folder` with a hybrid permission model — `Folder` is
35
+ * one of the two entities in this library with a real per-record `AccessControlList` (the other is `Mailbox`;
36
+ * see the architecture note on `Message.mailboxUid` in `models/types.ts`), so most of `CRUDRoute`'s default
37
+ * behavior already works correctly and is left untouched here:
38
+ *
39
+ * - `findById`/`update`/`delete`/`truncate` rely on `Folder`'s own record-level ACL, which by default inherits
40
+ * (via `AccessControlList.parentUid`) from its owning `Mailbox`'s ACL — so anyone the mailbox is shared with
41
+ * automatically gets the same access to its folders, while a single folder (e.g. one Calendar) can still be
42
+ * shared more narrowly by adding records directly to *that folder's own* ACL instead. `RepoUtils.findOne()`/
43
+ * `update()`/`delete()` check the record's own resolved ACL chain directly (no class-level fast-fail), so
44
+ * this works correctly once the class-level grant is denied; `truncate()` skips its class-level check
45
+ * entirely whenever `recordACL` is `true` (verified by reading its source) and relies on per-record
46
+ * filtering instead, which is equally safe here for the same reason.
47
+ * - `find`/`count`/`exists` are overridden here, for the same reason every other collection-or-fast-fail-gated
48
+ * operation in this library is: `RepoUtils.find()`/`count()`/`exists()` all check the class-level ACL as an
49
+ * unconditional first gate — before any per-record narrowing, and even that later narrowing falls back to
50
+ * the class grant for a record with no caller-specific entry — so a per-record ACL alone can't safely narrow
51
+ * them once class-level access is granted to anyone. `find`/`count` take an explicit `mailboxUid` query
52
+ * parameter and check permission against it directly; `exists` fetches the specific folder first (bypassing
53
+ * ACL) and then checks permission against *that folder's own* uid (i.e. its real resolved ACL chain), same
54
+ * as `findById` does implicitly.
55
+ * - `create` is also overridden, for a different reason: it seeds the new folder's ACL with `parentUid` set to
56
+ * the owning mailbox's ACL uid, which is what wires up the inheritance described above — this can't be done
57
+ * generically by `RepoUtils.create()`'s own default (it would parent to the `Folder` class ACL instead, which
58
+ * is deny-all and grants nothing) — and, since a folder doesn't exist yet at create time, permission is
59
+ * checked against the target `mailboxUid` from the request body instead. It also publishes a live-update
60
+ * notification (see `push/MailPushRoute.ts`) to the owning mailbox's channel, so a webmail client subscribed
61
+ * to a mailbox sees new folders appear without polling.
62
+ *
63
+ * `find`/`count`/`exists` also resolve an unauthenticated caller's `?shareToken=` query param via the local
64
+ * `resolveEffectiveUser()` helper below (see `BaseScopedChildRoute`'s doc comment for the full explanation of
65
+ * the mechanism this is one half of).
66
+ *
67
+ * KNOWN LIMITATIONS:
68
+ * - `update`/`delete` (folder rename/move/removal) do NOT publish a live-update notification, unlike every
69
+ * mutation on the folder-scoped entities in `BaseScopedChildRoute`. Overriding them here purely to add a
70
+ * notify call would mean re-implementing (and re-testing) the exact ACL-delegation behavior this class's own
71
+ * doc comment above is careful to leave untouched by relying on `CRUDRoute`'s defaults — a real gap, but a
72
+ * deliberate one given how comparatively rare and low-urgency folder structural changes are next to new-mail
73
+ * delivery, matching this library's existing "pragmatic subset, not full fidelity" scope elsewhere.
74
+ * - `findById` (also left on `CRUDRoute`'s default) does NOT resolve `?shareToken=` — a share link's token
75
+ * grants read access to the folder's *children* (e.g. its `CalendarEvent`s, via `BaseScopedChildRoute`), not
76
+ * to fetching the `Folder` record itself by id. A client wanting the calendar's display name alongside its
77
+ * events would need that carried elsewhere (e.g. denormalized onto `CalendarShareLink`), not fetched via this
78
+ * route with a token.
79
+ *
80
+ * @author Jean-Philippe Steinmetz
81
+ */
82
+ export class BaseFolderRoute extends CRUDRoute {
83
+ async count(params, query, res, user) {
84
+ if (!this.repoUtils) {
85
+ throw new ApiError(ApiErrors.INTERNAL_ERROR, 500, ApiErrorMessages.INTERNAL_ERROR);
86
+ }
87
+ const mailboxUid = query?.mailboxUid;
88
+ if (!mailboxUid) {
89
+ throw new ApiError(ApiErrors.INVALID_REQUEST, 400, ApiErrorMessages.INVALID_REQUEST);
90
+ }
91
+ if (!(await this.aclUtils.hasPermission(resolveEffectiveUser(user, query), mailboxUid, ACLAction.COUNT))) {
92
+ return res.status(200).setHeader("content-length", 0);
93
+ }
94
+ // `shareToken` is consumed above by `resolveEffectiveUser()` for permission resolution only - it names
95
+ // no field on `T`, so it must not be forwarded into the data filter below (SQL: an unknown-column
96
+ // error; Mongo: a `$match` no real document ever satisfies, silently returning zero results either way).
97
+ const { shareToken: _shareToken, ...filterQuery } = query ?? {};
98
+ const result = await this.repoUtils.count({ ...filterQuery, ...params }, { limit: query?.limit, page: query?.page, version: query?.version, user, ignoreACL: true });
99
+ return res.status(200).setHeader("content-length", result);
100
+ }
101
+ async create(obj, req, user) {
102
+ if (!this.repoUtils) {
103
+ throw new ApiError(ApiErrors.INTERNAL_ERROR, 500, ApiErrorMessages.INTERNAL_ERROR);
104
+ }
105
+ const objs = Array.isArray(obj) ? obj : [obj];
106
+ const results = [];
107
+ for (const raw of objs) {
108
+ const mailboxUid = raw.mailboxUid;
109
+ if (!mailboxUid || !(await this.aclUtils.hasPermission(user, mailboxUid, ACLAction.CREATE))) {
110
+ throw new ApiError(ApiErrors.AUTH_PERMISSION_FAILURE, 403, ApiErrorMessages.AUTH_PERMISSION_FAILURE);
111
+ }
112
+ const instance = this.repoUtils.instantiateObject(raw);
113
+ const created = await this.repoUtils.create(instance, {
114
+ user,
115
+ ignoreACL: true,
116
+ acl: { uid: instance.uid, parentUid: mailboxUid, records: [] },
117
+ });
118
+ this.notificationUtils?.sendMessage(mailboxUid, this.modelClass.name, "create", created);
119
+ results.push(created);
120
+ }
121
+ return Array.isArray(obj) ? results : results[0];
122
+ }
123
+ async find(params, query, user) {
124
+ if (!this.repoUtils) {
125
+ throw new ApiError(ApiErrors.INTERNAL_ERROR, 500, ApiErrorMessages.INTERNAL_ERROR);
126
+ }
127
+ const mailboxUid = query?.mailboxUid;
128
+ if (!mailboxUid) {
129
+ throw new ApiError(ApiErrors.INVALID_REQUEST, 400, ApiErrorMessages.INVALID_REQUEST);
130
+ }
131
+ if (!(await this.aclUtils.hasPermission(resolveEffectiveUser(user, query), mailboxUid, ACLAction.LIST))) {
132
+ return [];
133
+ }
134
+ // See the identical `shareToken` exclusion (and its rationale) in `count()` above.
135
+ const { shareToken: _shareToken, ...filterQuery } = query ?? {};
136
+ return await this.repoUtils.find({ ...filterQuery, ...params }, { limit: query?.limit, page: query?.page, version: query?.version, user, ignoreACL: true });
137
+ }
138
+ async exists(id, query, res, user) {
139
+ if (!this.repoUtils) {
140
+ throw new ApiError(ApiErrors.INTERNAL_ERROR, 500, ApiErrorMessages.INTERNAL_ERROR);
141
+ }
142
+ const existing = await this.repoUtils.findOne(id, {
143
+ version: query?.version,
144
+ includeDeleted: query?.deleted === true || query?.deleted === "true",
145
+ ignoreACL: true,
146
+ });
147
+ const permitted = existing
148
+ ? await this.aclUtils.hasPermission(resolveEffectiveUser(user, query), existing.uid, ACLAction.EXISTS)
149
+ : false;
150
+ return permitted
151
+ ? res.status(200).setHeader("content-length", 1)
152
+ : res.status(404).setHeader("content-length", 0);
153
+ }
154
+ }
155
+ __decorate([
156
+ Head(),
157
+ __param(0, Param()),
158
+ __param(1, Query()),
159
+ __param(2, Response),
160
+ __param(3, AuthUser),
161
+ __metadata("design:type", Function),
162
+ __metadata("design:paramtypes", [Object, Object, Object, Object]),
163
+ __metadata("design:returntype", Promise)
164
+ ], BaseFolderRoute.prototype, "count", null);
165
+ __decorate([
166
+ Post(),
167
+ __param(1, Request),
168
+ __param(2, AuthUser),
169
+ __metadata("design:type", Function),
170
+ __metadata("design:paramtypes", [Object, Object, Object]),
171
+ __metadata("design:returntype", Promise)
172
+ ], BaseFolderRoute.prototype, "create", null);
173
+ __decorate([
174
+ Get(),
175
+ __param(0, Param()),
176
+ __param(1, Query()),
177
+ __param(2, AuthUser),
178
+ __metadata("design:type", Function),
179
+ __metadata("design:paramtypes", [Object, Object, Object]),
180
+ __metadata("design:returntype", Promise)
181
+ ], BaseFolderRoute.prototype, "find", null);
182
+ __decorate([
183
+ Head("/:id"),
184
+ __param(0, Param("id")),
185
+ __param(1, Query()),
186
+ __param(2, Response),
187
+ __param(3, AuthUser),
188
+ __metadata("design:type", Function),
189
+ __metadata("design:paramtypes", [String, Object, Object, Object]),
190
+ __metadata("design:returntype", Promise)
191
+ ], BaseFolderRoute.prototype, "exists", null);
192
+ //# sourceMappingURL=BaseFolderRoute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseFolderRoute.js","sourceRoot":"","sources":["../../../src/routes/BaseFolderRoute.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,179 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ ///////////////////////////////////////////////////////////////////////////////
14
+ // Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
15
+ // SPDX-License-Identifier: MPL-2.0
16
+ ///////////////////////////////////////////////////////////////////////////////
17
+ import * as crypto from "crypto";
18
+ import { ApiError, ObjectDecorators } from "@rapidrest/core";
19
+ import { ApiErrorMessages, ApiErrors, DocDecorators, RepoUtils, RouteDecorators, } from "@rapidrest/service-core";
20
+ import { IngestStatus } from "../models/types.js";
21
+ const { Config, Inject, Logger } = ObjectDecorators;
22
+ const { Description, Summary } = DocDecorators;
23
+ const { Get, Post, Query, Request, Response } = RouteDecorators;
24
+ /**
25
+ * Implements the `MTAIngestAdapter` HTTP contract (see `transport/MTAIngestAdapter.ts`) that the deployment's
26
+ * MTA (Postfix, Haraka, ...) integrates against to hand accepted internet mail to this library. Both endpoints
27
+ * are internal-only — never exposed to the public internet — and gated by a shared bearer secret rather than
28
+ * ordinary user JWT auth, since the caller is the MTA process, not an end user.
29
+ *
30
+ * This class is DB-agnostic; `mailboxClass`/`ingestQueueClass` are supplied by the Mongo/SQL concrete
31
+ * subclasses (`MailIngestRouteMongo`/`MailIngestRouteSQL`), following the same pattern
32
+ * `DefaultAccounts`/`DefaultAccountsMongo` use for a background service spanning multiple entity types.
33
+ *
34
+ * !!Note!! that, like `BasePushRoute`/`BaseStatusRoute`, this class is not automatically registered with a
35
+ * server — the consuming application must apply `@Route("/internal/mta")` to its own subclass. The
36
+ * `MTAIngestAdapter` doc comment's `GET /internal/mta/resolve`/`POST /internal/mta/deliver` paths assume that
37
+ * exact base path is used; if a deployment mounts it elsewhere, its MTA content-filter/lookup configuration
38
+ * must be updated to match.
39
+ *
40
+ * @author Jean-Philippe Steinmetz
41
+ */
42
+ export class BaseMailIngestRoute {
43
+ /**
44
+ * Builds the query value used to match `Mailbox.aliasAddresses` against the given address. MongoDB's
45
+ * implicit array-element equality lets a plain value match "array contains" directly, so the default here
46
+ * is a no-op passthrough. `MailIngestRouteSQL` overrides this: the SQL backend stores `aliasAddresses` as a
47
+ * serialized `simple-json` column, where a plain equality filter compares against the whole serialized
48
+ * string and never matches a single element.
49
+ */
50
+ aliasQueryValue(address) {
51
+ return address;
52
+ }
53
+ async init() {
54
+ if (!this.mailboxRepo) {
55
+ this.mailboxRepo = await this._objectFactory.newInstance(RepoUtils, {
56
+ name: this.mailboxClass.name,
57
+ args: [this.mailboxClass],
58
+ });
59
+ }
60
+ if (!this.ingestQueueRepo) {
61
+ this.ingestQueueRepo = await this._objectFactory.newInstance(RepoUtils, {
62
+ name: this.ingestQueueClass.name,
63
+ args: [this.ingestQueueClass],
64
+ });
65
+ }
66
+ }
67
+ /**
68
+ * Verifies the caller presented the configured internal bearer secret. Deliberately not `@Auth(["jwt"])` —
69
+ * the caller is the local MTA process, not an end user with a JWT. Throws `403` if no secret is configured
70
+ * at all (fail closed, never fail open into an unauthenticated internal endpoint).
71
+ */
72
+ authorizeInternalCaller(req) {
73
+ const header = req.headers["authorization"];
74
+ const presented = (Array.isArray(header) ? header[0] : header)?.replace(/^Bearer\s+/i, "") ?? "";
75
+ const expected = this.ingestSecret ?? "";
76
+ const presentedBuf = Buffer.from(presented);
77
+ const expectedBuf = Buffer.from(expected);
78
+ const authorized = expected.length > 0 &&
79
+ presentedBuf.length === expectedBuf.length &&
80
+ crypto.timingSafeEqual(presentedBuf, expectedBuf);
81
+ if (!authorized) {
82
+ throw new ApiError(ApiErrors.AUTH_PERMISSION_FAILURE, 403, ApiErrorMessages.AUTH_PERMISSION_FAILURE);
83
+ }
84
+ }
85
+ async resolve(rcpt, req, res) {
86
+ this.authorizeInternalCaller(req);
87
+ await this.init();
88
+ if (!rcpt) {
89
+ throw new ApiError(ApiErrors.INVALID_REQUEST, 400, ApiErrorMessages.INVALID_REQUEST);
90
+ }
91
+ const address = rcpt.trim().toLowerCase();
92
+ const [byPrimary, byAlias] = await Promise.all([
93
+ this.mailboxRepo.find({ primarySmtpAddress: address }, { ignoreACL: true, limit: 1 }),
94
+ this.mailboxRepo.find({ aliasAddresses: this.aliasQueryValue(address) }, { ignoreACL: true, limit: 1 }),
95
+ ]);
96
+ return byPrimary.length > 0 || byAlias.length > 0 ? res.status(200) : res.status(404);
97
+ }
98
+ async deliver(req, res) {
99
+ this.authorizeInternalCaller(req);
100
+ await this.init();
101
+ if (!this.blobStore) {
102
+ throw new ApiError(ApiErrors.INTERNAL_ERROR, 500, ApiErrorMessages.INTERNAL_ERROR);
103
+ }
104
+ const envelopeFrom = firstHeader(req, "x-envelope-from") ?? "";
105
+ const envelopeToHeader = firstHeader(req, "x-envelope-to");
106
+ const envelopeTo = envelopeToHeader ? envelopeToHeader.split(",").map((a) => a.trim()) : [];
107
+ const raw = req.rawBody;
108
+ if (!raw || raw.length === 0 || envelopeTo.length === 0) {
109
+ throw new ApiError(ApiErrors.INVALID_REQUEST, 400, ApiErrorMessages.INVALID_REQUEST);
110
+ }
111
+ // A single SMTP transaction can carry more than one RCPT TO — resolve and stage one IngestQueueEntry
112
+ // per addressed mailbox so `ScanQueueJob` delivers independently to each, and one unknown/unresolvable
113
+ // recipient in the batch doesn't block delivery to the others.
114
+ const results = [];
115
+ for (const rcpt of envelopeTo) {
116
+ const address = rcpt.trim().toLowerCase();
117
+ const mailboxes = await this.mailboxRepo.find({ primarySmtpAddress: address }, { ignoreACL: true, limit: 1 });
118
+ const mailbox = mailboxes[0] ??
119
+ (await this.mailboxRepo.find({ aliasAddresses: this.aliasQueryValue(address) }, { ignoreACL: true, limit: 1 }))[0];
120
+ if (!mailbox) {
121
+ this.logger?.warn(`MailIngestRoute: dropping delivery for unresolvable recipient '${address}'.`);
122
+ results.push({ rcpt: address, queued: false });
123
+ continue;
124
+ }
125
+ const rawBlobKey = `ingest/${crypto.randomUUID()}`;
126
+ await this.blobStore.put(rawBlobKey, raw, { contentType: "message/rfc822" });
127
+ await this.ingestQueueRepo.create(new this.ingestQueueClass({
128
+ mailboxUid: mailbox.uid,
129
+ envelopeFrom,
130
+ envelopeTo: [address],
131
+ rawBlobKey,
132
+ status: IngestStatus.PENDING,
133
+ }), { ignoreACL: true });
134
+ results.push({ rcpt: address, queued: true });
135
+ }
136
+ res.status(202).json({ results });
137
+ return res;
138
+ }
139
+ }
140
+ __decorate([
141
+ Inject("BlobStore"),
142
+ __metadata("design:type", Object)
143
+ ], BaseMailIngestRoute.prototype, "blobStore", void 0);
144
+ __decorate([
145
+ Config("mail:transport:ingest:secret"),
146
+ __metadata("design:type", String)
147
+ ], BaseMailIngestRoute.prototype, "ingestSecret", void 0);
148
+ __decorate([
149
+ Logger,
150
+ __metadata("design:type", Object)
151
+ ], BaseMailIngestRoute.prototype, "logger", void 0);
152
+ __decorate([
153
+ Summary("Resolve recipient"),
154
+ Description("Called by the MTA's recipient-validation hook before accepting a message. Responds 200 if a mailbox " +
155
+ "exists for the given address, 404 otherwise."),
156
+ Get("/resolve"),
157
+ __param(0, Query("rcpt")),
158
+ __param(1, Request),
159
+ __param(2, Response),
160
+ __metadata("design:type", Function),
161
+ __metadata("design:paramtypes", [String, Object, Object]),
162
+ __metadata("design:returntype", Promise)
163
+ ], BaseMailIngestRoute.prototype, "resolve", null);
164
+ __decorate([
165
+ Summary("Deliver message"),
166
+ Description("Called by the MTA's content-filter once a message has been accepted. Persists the raw message and " +
167
+ "enqueues it for scanning/delivery, then returns immediately."),
168
+ Post("/deliver"),
169
+ __param(0, Request),
170
+ __param(1, Response),
171
+ __metadata("design:type", Function),
172
+ __metadata("design:paramtypes", [Object, Object]),
173
+ __metadata("design:returntype", Promise)
174
+ ], BaseMailIngestRoute.prototype, "deliver", null);
175
+ function firstHeader(req, name) {
176
+ const value = req.headers[name];
177
+ return Array.isArray(value) ? value[0] : value;
178
+ }
179
+ //# sourceMappingURL=BaseMailIngestRoute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseMailIngestRoute.js","sourceRoot":"","sources":["../../../src/routes/BaseMailIngestRoute.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,187 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ ///////////////////////////////////////////////////////////////////////////////
14
+ // Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
15
+ // SPDX-License-Identifier: MPL-2.0
16
+ ///////////////////////////////////////////////////////////////////////////////
17
+ import { ApiError, ObjectDecorators, UserUtils } from "@rapidrest/core";
18
+ import { ACLAction, ApiErrorMessages, ApiErrors, CRUDRoute, RouteDecorators } from "@rapidrest/service-core";
19
+ const { Param, Query, Request, Response, User: AuthUser } = RouteDecorators;
20
+ const { Config } = ObjectDecorators;
21
+ /**
22
+ * Extends the standard `CRUDRoute` CRUD scaffolding for `Mailbox` with ACL-driven `find`/`count` overrides,
23
+ * plus a `create` override that bypasses the ACL system entirely. `Mailbox` has a real per-record
24
+ * `AccessControlList` (`@Protect(..., true)`; see the architecture note on `Message.mailboxUid`), whose
25
+ * class-level ACL denies EVERY action to non-trusted callers, including `CREATE`.
26
+ *
27
+ * `create` is deliberately NOT gated by the class-level ACL at all (unlike every other action): provisioning a
28
+ * brand-new mailbox is a pure self-service action (any authenticated user may create their own) with no parent
29
+ * resource to check permission against — `RepoUtils.create()`'s own automatic owner-grant logic is what
30
+ * actually scopes the new mailbox to its creator, not a class-level check. A class-level `CREATE` grant to
31
+ * `.*` was tried first and found to leak: every mailbox's own ACL falls back to that SAME class ACL as its
32
+ * parent whenever a caller has no mailbox-specific record, so *any* authenticated user calling
33
+ * `ACLUtils.hasPermission(user, someOtherMailboxUid, CREATE)` (e.g. `BaseFolderRoute.create()` checking
34
+ * permission to create a folder *in* that mailbox) would incorrectly pass too. Denying `CREATE` at the class
35
+ * level entirely, and having this route check only `user` truthiness before bypassing ACL, closes that leak.
36
+ *
37
+ * A non-trusted caller's `ownerUserUid` is always forced to their own uid, discarding whatever the client
38
+ * sent — self-service creation can only ever create a mailbox *for yourself*. Only a trusted caller may create
39
+ * a mailbox with a different (or no) `ownerUserUid` — the latter is a true ownerless "shared mailbox" (the
40
+ * Exchange concept, e.g. `support@example.com`) with no single owner, only delegates added afterward via
41
+ * `BaseACLRoute` (`@rapidrest/service-core`). `RepoUtils.create()`'s automatic owner-grant is already
42
+ * conditioned on the creator lacking a trusted role, so a trusted caller creating an ownerless mailbox does
43
+ * not, on its own, leave behind a stray self-grant for the admin who happened to create it.
44
+ *
45
+ * `find`/`count` still need overriding despite the real per-record ACL: `RepoUtils.find()`/`count()` both
46
+ * check the class-level ACL as an unconditional first gate *before* any per-record narrowing, and even that
47
+ * later per-record narrowing falls back to the class grant for a record with no caller-specific entry —
48
+ * verified by reading their source. Rather than the old ownership-only (`ownerUserUid: user.uid`) scoping,
49
+ * these now query for every mailbox uid the caller has *any* ACL grant on — owned, shared-with-them as a
50
+ * delegate, or (for a trusted caller) every mailbox unfiltered — via `findAccessibleMailboxUids()`, backed by
51
+ * the exact same `AccessControlList` model `BaseACLRoute` exposes as CRUD (no new API surface). `exists`
52
+ * doesn't need this treatment: it fetches the specific record first (bypassing ACL) and then checks
53
+ * permission against *that record's own* uid via `ACLUtils.hasPermission`, which already resolves ownership,
54
+ * delegate shares, and trusted-role access correctly on its own — see `exists()` below, unchanged.
55
+ * `findById`/`update`/`delete` are unaffected for the same reason: `RepoUtils.findOne()`/`update()`/
56
+ * `delete()` check the *record's own* resolved ACL chain directly (no class-level fast-fail), so once the
57
+ * class-level grant is denied, that chain correctly resolves to "deny" for a caller with no grant and "allow"
58
+ * for the owner or any delegate — `CRUDRoute`'s default behavior for those already works correctly and is
59
+ * left untouched.
60
+ *
61
+ * @author Jean-Philippe Steinmetz
62
+ */
63
+ export class BaseMailboxRoute extends CRUDRoute {
64
+ constructor() {
65
+ super(...arguments);
66
+ this.trustedRoles = ["admin"];
67
+ }
68
+ async create(obj, req, user) {
69
+ if (!user) {
70
+ throw new ApiError(ApiErrors.AUTH_PERMISSION_FAILURE, 403, ApiErrorMessages.AUTH_PERMISSION_FAILURE);
71
+ }
72
+ const isTrusted = UserUtils.hasRoles(user, this.trustedRoles);
73
+ const objs = Array.isArray(obj) ? obj : [obj];
74
+ if (!isTrusted) {
75
+ for (const o of objs) {
76
+ o.ownerUserUid = user.uid;
77
+ }
78
+ }
79
+ if (Array.isArray(obj)) {
80
+ return await this.doBulkCreate(objs, { req, user, ignoreACL: true });
81
+ }
82
+ return await this.doCreateObject(objs[0], { req, user, ignoreACL: true });
83
+ }
84
+ async find(params, query, user) {
85
+ if (!this.repoUtils || !user) {
86
+ return [];
87
+ }
88
+ const isTrusted = UserUtils.hasRoles(user, this.trustedRoles);
89
+ let scopedQuery = { ...query, ...params };
90
+ if (!isTrusted) {
91
+ const accessibleUids = await this.findAccessibleMailboxUids(user);
92
+ // An empty array must short-circuit rather than be passed through as a query filter value: the
93
+ // underlying query builder "zips" an array filter value's *last* element onto any query branch
94
+ // past its own length, so an empty array resolves to `undefined` for that field — which TypeORM
95
+ // (and this builder) treats as "no filter on this field", not "match nothing". Passing it through
96
+ // would incorrectly return every mailbox to a caller who is entitled to see none.
97
+ if (accessibleUids.length === 0) {
98
+ return [];
99
+ }
100
+ scopedQuery = { ...scopedQuery, uid: accessibleUids };
101
+ }
102
+ return await this.repoUtils.find(scopedQuery, {
103
+ limit: query?.limit,
104
+ page: query?.page,
105
+ version: query?.version,
106
+ user,
107
+ ignoreACL: true,
108
+ });
109
+ }
110
+ async count(params, query, res, user) {
111
+ if (!this.repoUtils || !user) {
112
+ return res.status(200).setHeader("content-length", 0);
113
+ }
114
+ const isTrusted = UserUtils.hasRoles(user, this.trustedRoles);
115
+ let scopedQuery = { ...query, ...params };
116
+ if (!isTrusted) {
117
+ const accessibleUids = await this.findAccessibleMailboxUids(user);
118
+ // See the identical short-circuit (and its rationale) in `find()` above.
119
+ if (accessibleUids.length === 0) {
120
+ return res.status(200).setHeader("content-length", 0);
121
+ }
122
+ scopedQuery = { ...scopedQuery, uid: accessibleUids };
123
+ }
124
+ const result = await this.repoUtils.count(scopedQuery, {
125
+ limit: query?.limit,
126
+ page: query?.page,
127
+ version: query?.version,
128
+ user,
129
+ ignoreACL: true,
130
+ });
131
+ return res.status(200).setHeader("content-length", result);
132
+ }
133
+ async exists(id, query, res, user) {
134
+ if (!this.repoUtils) {
135
+ throw new ApiError(ApiErrors.INTERNAL_ERROR, 500, ApiErrorMessages.INTERNAL_ERROR);
136
+ }
137
+ const existing = await this.repoUtils.findOne(id, {
138
+ version: query?.version,
139
+ includeDeleted: query?.deleted === true || query?.deleted === "true",
140
+ ignoreACL: true,
141
+ });
142
+ const permitted = existing
143
+ ? await this.aclUtils.hasPermission(user, existing.uid, ACLAction.EXISTS)
144
+ : false;
145
+ return permitted
146
+ ? res.status(200).setHeader("content-length", 1)
147
+ : res.status(404).setHeader("content-length", 0);
148
+ }
149
+ }
150
+ __decorate([
151
+ Config("trusted_roles", ["admin"]),
152
+ __metadata("design:type", Array)
153
+ ], BaseMailboxRoute.prototype, "trustedRoles", void 0);
154
+ __decorate([
155
+ __param(1, Request),
156
+ __param(2, AuthUser),
157
+ __metadata("design:type", Function),
158
+ __metadata("design:paramtypes", [Object, Object, Object]),
159
+ __metadata("design:returntype", Promise)
160
+ ], BaseMailboxRoute.prototype, "create", null);
161
+ __decorate([
162
+ __param(0, Param()),
163
+ __param(1, Query()),
164
+ __param(2, AuthUser),
165
+ __metadata("design:type", Function),
166
+ __metadata("design:paramtypes", [Object, Object, Object]),
167
+ __metadata("design:returntype", Promise)
168
+ ], BaseMailboxRoute.prototype, "find", null);
169
+ __decorate([
170
+ __param(0, Param()),
171
+ __param(1, Query()),
172
+ __param(2, Response),
173
+ __param(3, AuthUser),
174
+ __metadata("design:type", Function),
175
+ __metadata("design:paramtypes", [Object, Object, Object, Object]),
176
+ __metadata("design:returntype", Promise)
177
+ ], BaseMailboxRoute.prototype, "count", null);
178
+ __decorate([
179
+ __param(0, Param("id")),
180
+ __param(1, Query()),
181
+ __param(2, Response),
182
+ __param(3, AuthUser),
183
+ __metadata("design:type", Function),
184
+ __metadata("design:paramtypes", [String, Object, Object, Object]),
185
+ __metadata("design:returntype", Promise)
186
+ ], BaseMailboxRoute.prototype, "exists", null);
187
+ //# sourceMappingURL=BaseMailboxRoute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseMailboxRoute.js","sourceRoot":"","sources":["../../../src/routes/BaseMailboxRoute.ts"],"names":[],"mappings":"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"}