@sync-in/server 1.8.1 → 1.9.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 (603) hide show
  1. package/CHANGELOG.md +56 -11
  2. package/environment/environment.dist.yaml +29 -26
  3. package/package.json +15 -15
  4. package/server/app.constants.js +9 -0
  5. package/server/app.constants.js.map +1 -1
  6. package/server/app.module.js +4 -0
  7. package/server/app.module.js.map +1 -1
  8. package/server/applications/admin/admin.module.js +6 -1
  9. package/server/applications/admin/admin.module.js.map +1 -1
  10. package/server/applications/{notifications/interfaces/user-mail-notification.js → admin/interfaces/check-update.interfaces.js} +1 -1
  11. package/server/applications/admin/interfaces/check-update.interfaces.js.map +1 -0
  12. package/server/applications/admin/services/admin-scheduler.service.js +53 -0
  13. package/server/applications/admin/services/admin-scheduler.service.js.map +1 -0
  14. package/server/applications/admin/services/admin.service.js +102 -0
  15. package/server/applications/admin/services/admin.service.js.map +1 -0
  16. package/server/applications/admin/services/admin.service.spec.js +46 -0
  17. package/server/applications/admin/services/admin.service.spec.js.map +1 -0
  18. package/server/applications/admin/utils/check-update.js +28 -0
  19. package/server/applications/admin/utils/check-update.js.map +1 -0
  20. package/server/applications/comments/services/comments-manager.service.js +1 -1
  21. package/server/applications/comments/services/comments-manager.service.js.map +1 -1
  22. package/server/applications/comments/services/comments-manager.service.spec.js +1 -1
  23. package/server/applications/comments/services/comments-manager.service.spec.js.map +1 -1
  24. package/server/applications/comments/services/comments-queries.service.js.map +1 -1
  25. package/server/applications/files/constants/cache.js +10 -1
  26. package/server/applications/files/constants/cache.js.map +1 -1
  27. package/server/applications/files/constants/only-office.js +0 -25
  28. package/server/applications/files/constants/only-office.js.map +1 -1
  29. package/server/applications/files/constants/operations.js +20 -3
  30. package/server/applications/files/constants/operations.js.map +1 -1
  31. package/server/applications/files/dto/file-operations.dto.js +7 -0
  32. package/server/applications/files/dto/file-operations.dto.js.map +1 -1
  33. package/server/applications/files/files-only-office.controller.js +3 -2
  34. package/server/applications/files/files-only-office.controller.js.map +1 -1
  35. package/server/applications/files/files-only-office.controller.spec.js +6 -5
  36. package/server/applications/files/files-only-office.controller.spec.js.map +1 -1
  37. package/server/applications/files/files.controller.js +88 -8
  38. package/server/applications/files/files.controller.js.map +1 -1
  39. package/server/applications/files/files.controller.spec.js +11 -4
  40. package/server/applications/files/files.controller.spec.js.map +1 -1
  41. package/server/applications/files/guards/files-only-office.guard.js +6 -0
  42. package/server/applications/files/guards/files-only-office.guard.js.map +1 -1
  43. package/server/applications/files/interfaces/file-db-props.interface.js.map +1 -1
  44. package/server/applications/files/interfaces/file-props.interface.js.map +1 -1
  45. package/server/applications/files/interfaces/only-office-config.interface.js.map +1 -1
  46. package/server/applications/files/services/files-content-manager.service.js +3 -3
  47. package/server/applications/files/services/files-content-manager.service.js.map +1 -1
  48. package/server/applications/files/services/files-lock-manager.service.js +61 -22
  49. package/server/applications/files/services/files-lock-manager.service.js.map +1 -1
  50. package/server/applications/files/services/files-manager.service.js +122 -24
  51. package/server/applications/files/services/files-manager.service.js.map +1 -1
  52. package/server/applications/files/services/files-manager.service.spec.js +15 -0
  53. package/server/applications/files/services/files-manager.service.spec.js.map +1 -1
  54. package/server/applications/files/services/files-methods.service.js +38 -8
  55. package/server/applications/files/services/files-methods.service.js.map +1 -1
  56. package/server/applications/files/services/files-only-office-manager.service.js +12 -12
  57. package/server/applications/files/services/files-only-office-manager.service.js.map +1 -1
  58. package/server/applications/files/services/files-parser.service.js +1 -1
  59. package/server/applications/files/services/files-parser.service.js.map +1 -1
  60. package/server/applications/files/services/files-queries.service.js +10 -0
  61. package/server/applications/files/services/files-queries.service.js.map +1 -1
  62. package/server/applications/files/utils/files.js +1 -1
  63. package/server/applications/files/utils/files.js.map +1 -1
  64. package/server/applications/files/utils/send-file.js +3 -2
  65. package/server/applications/files/utils/send-file.js.map +1 -1
  66. package/server/applications/links/services/links-queries.service.js +1 -1
  67. package/server/applications/links/services/links-queries.service.js.map +1 -1
  68. package/server/applications/notifications/constants/notifications.js +5 -1
  69. package/server/applications/notifications/constants/notifications.js.map +1 -1
  70. package/server/applications/notifications/i18n/de.js +8 -2
  71. package/server/applications/notifications/i18n/de.js.map +1 -1
  72. package/server/applications/notifications/i18n/es.js +8 -2
  73. package/server/applications/notifications/i18n/es.js.map +1 -1
  74. package/server/applications/notifications/i18n/fr.js +8 -2
  75. package/server/applications/notifications/i18n/fr.js.map +1 -1
  76. package/server/applications/notifications/i18n/hi.js +8 -2
  77. package/server/applications/notifications/i18n/hi.js.map +1 -1
  78. package/server/applications/notifications/i18n/it.js +8 -2
  79. package/server/applications/notifications/i18n/it.js.map +1 -1
  80. package/server/applications/notifications/i18n/ja.js +8 -2
  81. package/server/applications/notifications/i18n/ja.js.map +1 -1
  82. package/server/applications/notifications/i18n/ko.js +8 -2
  83. package/server/applications/notifications/i18n/ko.js.map +1 -1
  84. package/server/applications/notifications/i18n/pl.js +8 -2
  85. package/server/applications/notifications/i18n/pl.js.map +1 -1
  86. package/server/applications/notifications/i18n/pt.js +8 -2
  87. package/server/applications/notifications/i18n/pt.js.map +1 -1
  88. package/server/applications/notifications/i18n/pt_br.js +8 -2
  89. package/server/applications/notifications/i18n/pt_br.js.map +1 -1
  90. package/server/applications/notifications/i18n/ru.js +8 -2
  91. package/server/applications/notifications/i18n/ru.js.map +1 -1
  92. package/server/applications/notifications/i18n/tr.js +8 -2
  93. package/server/applications/notifications/i18n/tr.js.map +1 -1
  94. package/server/applications/notifications/i18n/zh.js +8 -2
  95. package/server/applications/notifications/i18n/zh.js.map +1 -1
  96. package/server/applications/notifications/interfaces/notification-properties.interface.js.map +1 -1
  97. package/server/applications/notifications/interfaces/user-mail-notification.interface.js +10 -0
  98. package/server/applications/notifications/interfaces/user-mail-notification.interface.js.map +1 -0
  99. package/server/applications/notifications/mails/models.js +38 -3
  100. package/server/applications/notifications/mails/models.js.map +1 -1
  101. package/server/applications/notifications/mails/templates.js +1 -1
  102. package/server/applications/notifications/mails/templates.js.map +1 -1
  103. package/server/applications/notifications/services/notifications-manager.service.js +8 -1
  104. package/server/applications/notifications/services/notifications-manager.service.js.map +1 -1
  105. package/server/applications/notifications/services/notifications-queries.service.js.map +1 -1
  106. package/server/applications/shares/services/shares-manager.service.js +17 -10
  107. package/server/applications/shares/services/shares-manager.service.js.map +1 -1
  108. package/server/applications/shares/services/shares-manager.service.spec.js +10 -3
  109. package/server/applications/shares/services/shares-manager.service.spec.js.map +1 -1
  110. package/server/applications/shares/services/shares-queries.service.js +11 -1
  111. package/server/applications/shares/services/shares-queries.service.js.map +1 -1
  112. package/server/applications/spaces/guards/space.guard.spec.js +2 -2
  113. package/server/applications/spaces/guards/space.guard.spec.js.map +1 -1
  114. package/server/applications/spaces/services/spaces-browser.service.js +31 -11
  115. package/server/applications/spaces/services/spaces-browser.service.js.map +1 -1
  116. package/server/applications/spaces/services/spaces-manager.service.js +2 -2
  117. package/server/applications/spaces/services/spaces-manager.service.js.map +1 -1
  118. package/server/applications/spaces/services/spaces-queries.service.js +6 -2
  119. package/server/applications/spaces/services/spaces-queries.service.js.map +1 -1
  120. package/server/applications/spaces/utils/permissions.js +2 -2
  121. package/server/applications/spaces/utils/permissions.js.map +1 -1
  122. package/server/applications/sync/services/sync-manager.service.js +1 -0
  123. package/server/applications/sync/services/sync-manager.service.js.map +1 -1
  124. package/server/applications/sync/services/sync-paths-manager.service.js +1 -1
  125. package/server/applications/sync/services/sync-paths-manager.service.js.map +1 -1
  126. package/server/applications/sync/services/sync-paths-manager.service.spec.js +1 -1
  127. package/server/applications/sync/services/sync-paths-manager.service.spec.js.map +1 -1
  128. package/server/applications/users/constants/user.js +1 -1
  129. package/server/applications/users/constants/user.js.map +1 -1
  130. package/server/applications/users/services/admin-users-queries.service.js +8 -0
  131. package/server/applications/users/services/admin-users-queries.service.js.map +1 -1
  132. package/server/applications/users/services/users-queries.service.js +67 -68
  133. package/server/applications/users/services/users-queries.service.js.map +1 -1
  134. package/server/applications/users/users.module.js +2 -1
  135. package/server/applications/users/users.module.js.map +1 -1
  136. package/server/applications/webdav/guards/webdav-protocol.guard.js +4 -4
  137. package/server/applications/webdav/guards/webdav-protocol.guard.js.map +1 -1
  138. package/server/applications/webdav/guards/webdav-protocol.guard.spec.js +6 -6
  139. package/server/applications/webdav/guards/webdav-protocol.guard.spec.js.map +1 -1
  140. package/server/applications/webdav/services/webdav-methods.service.js +3 -2
  141. package/server/applications/webdav/services/webdav-methods.service.js.map +1 -1
  142. package/server/applications/webdav/services/webdav-methods.service.spec.js +2 -2
  143. package/server/applications/webdav/services/webdav-methods.service.spec.js.map +1 -1
  144. package/server/authentication/constants/auth-ldap.js +2 -0
  145. package/server/authentication/constants/auth-ldap.js.map +1 -1
  146. package/server/authentication/services/auth-methods/auth-method-ldap.service.js +34 -21
  147. package/server/authentication/services/auth-methods/auth-method-ldap.service.js.map +1 -1
  148. package/server/common/functions.js +0 -8
  149. package/server/common/functions.js.map +1 -1
  150. package/server/common/image.js +1 -0
  151. package/server/common/image.js.map +1 -1
  152. package/server/common/shared.js +18 -1
  153. package/server/common/shared.js.map +1 -1
  154. package/server/infrastructure/context/services/context-manager.service.js +3 -0
  155. package/server/infrastructure/context/services/context-manager.service.js.map +1 -1
  156. package/server/infrastructure/websocket/adapters/cluster.adapter.js +4 -4
  157. package/server/infrastructure/websocket/adapters/cluster.adapter.js.map +1 -1
  158. package/static/3rdpartylicenses.txt +1393 -44
  159. package/static/assets/favicon.svg +2 -25
  160. package/static/assets/logo-dark.svg +2 -32
  161. package/static/assets/logo.svg +2 -32
  162. package/static/assets/mimes/application-sql.svg +29 -1
  163. package/static/assets/mimes/application-x-sql.svg +29 -0
  164. package/static/assets/mimes/image-bmp.svg +12 -0
  165. package/static/assets/pdfjs/build/pdf.mjs +4869 -4454
  166. package/static/assets/pdfjs/build/pdf.mjs.map +1 -1
  167. package/static/assets/pdfjs/build/pdf.sandbox.mjs +3 -3
  168. package/static/assets/pdfjs/build/pdf.sandbox.mjs.map +1 -1
  169. package/static/assets/pdfjs/build/pdf.worker.mjs +885 -596
  170. package/static/assets/pdfjs/build/pdf.worker.mjs.map +1 -1
  171. package/static/assets/pdfjs/version +1 -1
  172. package/static/assets/pdfjs/web/locale/be/viewer.ftl +40 -0
  173. package/static/assets/pdfjs/web/locale/bg/viewer.ftl +2 -0
  174. package/static/assets/pdfjs/web/locale/cs/viewer.ftl +41 -0
  175. package/static/assets/pdfjs/web/locale/cy/viewer.ftl +43 -0
  176. package/static/assets/pdfjs/web/locale/da/viewer.ftl +39 -0
  177. package/static/assets/pdfjs/web/locale/de/viewer.ftl +41 -0
  178. package/static/assets/pdfjs/web/locale/dsb/viewer.ftl +43 -0
  179. package/static/assets/pdfjs/web/locale/el/viewer.ftl +39 -0
  180. package/static/assets/pdfjs/web/locale/en-CA/viewer.ftl +35 -0
  181. package/static/assets/pdfjs/web/locale/en-GB/viewer.ftl +41 -0
  182. package/static/assets/pdfjs/web/locale/en-US/viewer.ftl +2 -2
  183. package/static/assets/pdfjs/web/locale/eo/viewer.ftl +39 -0
  184. package/static/assets/pdfjs/web/locale/es-AR/viewer.ftl +41 -0
  185. package/static/assets/pdfjs/web/locale/es-CL/viewer.ftl +39 -0
  186. package/static/assets/pdfjs/web/locale/es-ES/viewer.ftl +72 -0
  187. package/static/assets/pdfjs/web/locale/es-MX/viewer.ftl +120 -0
  188. package/static/assets/pdfjs/web/locale/eu/viewer.ftl +41 -0
  189. package/static/assets/pdfjs/web/locale/fi/viewer.ftl +41 -0
  190. package/static/assets/pdfjs/web/locale/fr/viewer.ftl +41 -0
  191. package/static/assets/pdfjs/web/locale/fur/viewer.ftl +77 -0
  192. package/static/assets/pdfjs/web/locale/fy-NL/viewer.ftl +41 -0
  193. package/static/assets/pdfjs/web/locale/gn/viewer.ftl +39 -0
  194. package/static/assets/pdfjs/web/locale/he/viewer.ftl +41 -0
  195. package/static/assets/pdfjs/web/locale/hsb/viewer.ftl +43 -0
  196. package/static/assets/pdfjs/web/locale/hu/viewer.ftl +41 -0
  197. package/static/assets/pdfjs/web/locale/hy-AM/viewer.ftl +1 -1
  198. package/static/assets/pdfjs/web/locale/ia/viewer.ftl +41 -0
  199. package/static/assets/pdfjs/web/locale/it/viewer.ftl +41 -0
  200. package/static/assets/pdfjs/web/locale/ja/viewer.ftl +32 -0
  201. package/static/assets/pdfjs/web/locale/ka/viewer.ftl +41 -0
  202. package/static/assets/pdfjs/web/locale/kab/viewer.ftl +73 -0
  203. package/static/assets/pdfjs/web/locale/kk/viewer.ftl +21 -0
  204. package/static/assets/pdfjs/web/locale/ko/viewer.ftl +38 -1
  205. package/static/assets/pdfjs/web/locale/nb-NO/viewer.ftl +39 -0
  206. package/static/assets/pdfjs/web/locale/nl/viewer.ftl +41 -0
  207. package/static/assets/pdfjs/web/locale/nn-NO/viewer.ftl +37 -0
  208. package/static/assets/pdfjs/web/locale/pa-IN/viewer.ftl +37 -0
  209. package/static/assets/pdfjs/web/locale/pl/viewer.ftl +39 -0
  210. package/static/assets/pdfjs/web/locale/pt-BR/viewer.ftl +39 -0
  211. package/static/assets/pdfjs/web/locale/rm/viewer.ftl +73 -0
  212. package/static/assets/pdfjs/web/locale/ro/viewer.ftl +41 -0
  213. package/static/assets/pdfjs/web/locale/ru/viewer.ftl +42 -0
  214. package/static/assets/pdfjs/web/locale/sc/viewer.ftl +6 -0
  215. package/static/assets/pdfjs/web/locale/sk/viewer.ftl +43 -0
  216. package/static/assets/pdfjs/web/locale/sl/viewer.ftl +42 -1
  217. package/static/assets/pdfjs/web/locale/sq/viewer.ftl +77 -0
  218. package/static/assets/pdfjs/web/locale/sv-SE/viewer.ftl +41 -0
  219. package/static/assets/pdfjs/web/locale/tg/viewer.ftl +39 -0
  220. package/static/assets/pdfjs/web/locale/th/viewer.ftl +35 -0
  221. package/static/assets/pdfjs/web/locale/tr/viewer.ftl +39 -0
  222. package/static/assets/pdfjs/web/locale/vi/viewer.ftl +42 -5
  223. package/static/assets/pdfjs/web/locale/zh-CN/viewer.ftl +35 -0
  224. package/static/assets/pdfjs/web/locale/zh-TW/viewer.ftl +37 -0
  225. package/static/assets/pdfjs/web/viewer.css +141 -110
  226. package/static/assets/pdfjs/web/viewer.html +7 -7
  227. package/static/assets/pdfjs/web/viewer.mjs +97 -14
  228. package/static/assets/pdfjs/web/viewer.mjs.map +1 -1
  229. package/static/chunk-22DWHRCL.js +1 -0
  230. package/static/chunk-23UUFZSR.js +1 -0
  231. package/static/{chunk-MTVSJTIW.js → chunk-24Q7OUU2.js} +1 -1
  232. package/static/chunk-25QTY2GI.js +1 -0
  233. package/static/chunk-2E7IJZLL.js +1 -0
  234. package/static/chunk-2FC5EKS5.js +1 -0
  235. package/static/chunk-2FOWUJQF.js +1 -0
  236. package/static/chunk-2XPHUNYN.js +1 -0
  237. package/static/chunk-32L7RG2G.js +1 -0
  238. package/static/chunk-3IISSX63.js +1 -0
  239. package/static/chunk-3OHSTP3R.js +1 -0
  240. package/static/chunk-42L6C5MT.js +1 -0
  241. package/static/chunk-4AGQL5GV.js +1 -0
  242. package/static/chunk-4BPSQMI2.js +1 -0
  243. package/static/chunk-4FDRWZWT.js +1 -0
  244. package/static/chunk-4FJUCMEG.js +1 -0
  245. package/static/chunk-4GCCF6PF.js +1 -0
  246. package/static/chunk-4ORP3SBY.js +1 -0
  247. package/static/chunk-4QBOHIC3.js +1 -0
  248. package/static/chunk-4YT6K5KY.js +1 -0
  249. package/static/chunk-556I6YIW.js +1 -0
  250. package/static/chunk-5DPIGJU4.js +1 -0
  251. package/static/chunk-5HNQLBSW.js +3 -0
  252. package/static/chunk-5IL7C45D.js +1 -0
  253. package/static/chunk-5KJXGMKR.js +1 -0
  254. package/static/chunk-5SPGSHKL.js +1 -0
  255. package/static/chunk-5WCQBTXW.js +1 -0
  256. package/static/chunk-5XUIPWOH.js +1 -0
  257. package/static/chunk-62WT7PI3.js +1 -0
  258. package/static/chunk-6F6OMQ5H.js +1 -0
  259. package/static/chunk-6I5BGQHT.js +1 -0
  260. package/static/chunk-6NOS45DG.js +1 -0
  261. package/static/chunk-6OKLPRCD.js +1 -0
  262. package/static/chunk-6VEJCG43.js +1 -0
  263. package/static/chunk-77SS36Z2.js +1 -0
  264. package/static/chunk-7AXEPO3G.js +1 -0
  265. package/static/chunk-7CFSJ4BO.js +1 -0
  266. package/static/chunk-7CKHC72R.js +1 -0
  267. package/static/chunk-7DUTYOJG.js +1 -0
  268. package/static/chunk-7HKFYRPF.js +1 -0
  269. package/static/chunk-7NZJZATZ.js +1 -0
  270. package/static/chunk-AADK5D2H.js +1 -0
  271. package/static/chunk-ACUF7IKP.js +1 -0
  272. package/static/chunk-AGREZPV4.js +1 -0
  273. package/static/chunk-ATBJWFA3.js +1 -0
  274. package/static/chunk-ATXLZN2B.js +1 -0
  275. package/static/chunk-AZ5TF5Y3.js +1 -0
  276. package/static/chunk-BBHYIURC.js +1 -0
  277. package/static/chunk-BHZEPHRI.js +13 -0
  278. package/static/chunk-BQZWSZNN.js +1 -0
  279. package/static/chunk-BSB4VROD.js +2 -0
  280. package/static/chunk-BYWSTP3P.js +1 -0
  281. package/static/chunk-C3AAEQKW.js +1 -0
  282. package/static/chunk-CCGGCHGN.js +1 -0
  283. package/static/chunk-CFTKW432.js +1 -0
  284. package/static/chunk-CNOVT6KU.js +1 -0
  285. package/static/chunk-D56H3XE2.js +1 -0
  286. package/static/chunk-DFOOSIIA.js +1 -0
  287. package/static/chunk-DHFQIFOF.js +1 -0
  288. package/static/{chunk-3GMLWAFZ.js → chunk-DIC2MVRI.js} +1 -1
  289. package/static/chunk-DJDRX53V.js +2 -0
  290. package/static/chunk-DKGXUMLT.js +1 -0
  291. package/static/chunk-DRHPEERW.js +2 -0
  292. package/static/chunk-DWYP6ZGG.js +1 -0
  293. package/static/chunk-EDJAISWO.js +13 -0
  294. package/static/chunk-EIYRBM4J.js +1 -0
  295. package/static/chunk-EKEGRXCV.js +7 -0
  296. package/static/chunk-EL6QL4TP.js +1 -0
  297. package/static/chunk-ERDZ7IVF.js +1 -0
  298. package/static/chunk-EVQKKVUZ.js +1 -0
  299. package/static/chunk-F2XG7EWI.js +1 -0
  300. package/static/chunk-F672FY5I.js +1 -0
  301. package/static/chunk-F6V37MKG.js +1 -0
  302. package/static/chunk-F7TXTNZC.js +1 -0
  303. package/static/chunk-FCGTI42I.js +1 -0
  304. package/static/chunk-FQHOSSCO.js +1 -0
  305. package/static/chunk-FTSIPHMG.js +1 -0
  306. package/static/chunk-GAGHHYLF.js +1 -0
  307. package/static/{chunk-JPT5WEAT.js → chunk-GOJYWL2M.js} +1 -1
  308. package/static/chunk-H6WOTGQ5.js +1 -0
  309. package/static/{chunk-CHJ64RJM.js → chunk-H6ZXFINQ.js} +1 -1
  310. package/static/chunk-HC7F57NA.js +1 -0
  311. package/static/chunk-HHWXIK2M.js +7 -0
  312. package/static/chunk-HKRGIRKB.js +3 -0
  313. package/static/chunk-HNMGPG72.js +1 -0
  314. package/static/chunk-HS4S6BV3.js +1 -0
  315. package/static/chunk-IJ7K7ATQ.js +1 -0
  316. package/static/chunk-IOIBQGHN.js +562 -0
  317. package/static/chunk-ITVA26X2.js +2 -0
  318. package/static/chunk-J6YSFHLZ.js +1 -0
  319. package/static/chunk-JAEJ6IMV.js +1 -0
  320. package/static/chunk-JB5R6V33.js +1 -0
  321. package/static/chunk-JF6WIV6M.js +1 -0
  322. package/static/chunk-JGB4LLUT.js +1 -0
  323. package/static/chunk-JGXVTKLG.js +1 -0
  324. package/static/chunk-JMYAD7E2.js +1 -0
  325. package/static/chunk-JSE63Q5X.js +1 -0
  326. package/static/chunk-JVV3ZL6L.js +1 -0
  327. package/static/chunk-JXZCNFW7.js +1 -0
  328. package/static/chunk-KAVP6UXH.js +1 -0
  329. package/static/{chunk-3R74L4UU.js → chunk-KDEEERWZ.js} +1 -1
  330. package/static/chunk-KHRF67SG.js +1 -0
  331. package/static/chunk-KLOUBIO4.js +1 -0
  332. package/static/chunk-KMF3ZRAO.js +1 -0
  333. package/static/chunk-KNZ3AQPR.js +1 -0
  334. package/static/chunk-KT3TWCST.js +1 -0
  335. package/static/chunk-L6SYG23T.js +1 -0
  336. package/static/chunk-LJSVNPPQ.js +1 -0
  337. package/static/{chunk-LNTUR3GU.js → chunk-LRDKG274.js} +1 -1
  338. package/static/chunk-LRQSPCYZ.js +1 -0
  339. package/static/chunk-LUSVISM6.js +1 -0
  340. package/static/chunk-LXQGVNU2.js +1 -0
  341. package/static/{chunk-LVSNIS5P.js → chunk-LYZGJZNP.js} +1 -1
  342. package/static/chunk-LZKI5P5T.js +1 -0
  343. package/static/chunk-M4XL3JN5.js +6 -0
  344. package/static/{chunk-UNCPXHHT.js → chunk-MGWG7OD7.js} +1 -1
  345. package/static/chunk-MKUUWY6Y.js +1 -0
  346. package/static/{chunk-VJTXJ43D.js → chunk-MNNCSSHN.js} +1 -1
  347. package/static/chunk-MR3U7TKQ.js +1 -0
  348. package/static/chunk-MRF3CNLZ.js +1 -0
  349. package/static/chunk-MRMSMTWD.js +1 -0
  350. package/static/chunk-MVZJSG5R.js +1 -0
  351. package/static/chunk-MYM43ENO.js +1 -0
  352. package/static/chunk-N3P6P6GW.js +7 -0
  353. package/static/chunk-NAH4V2R6.js +2 -0
  354. package/static/chunk-NBBDVVUF.js +1 -0
  355. package/static/chunk-NMF2ZFBE.js +1 -0
  356. package/static/chunk-NN4ONTOT.js +1 -0
  357. package/static/chunk-NOPACN4F.js +1 -0
  358. package/static/chunk-NYJPOP4L.js +1 -0
  359. package/static/chunk-OJCAIKUK.js +1 -0
  360. package/static/chunk-OQRWXCLY.js +1 -0
  361. package/static/chunk-PCFH5HCI.js +2 -0
  362. package/static/chunk-PG54TWBO.js +4 -0
  363. package/static/chunk-PJF5XUTO.js +1 -0
  364. package/static/{chunk-FJE6BOFL.js → chunk-PSUAQBYM.js} +1 -1
  365. package/static/chunk-PTLYIUFW.js +1 -0
  366. package/static/chunk-PZGLDZZM.js +1 -0
  367. package/static/chunk-Q4VNZGFI.js +1 -0
  368. package/static/chunk-Q556XB3S.js +1 -0
  369. package/static/{chunk-PB4AIT7O.js → chunk-Q7IXRPOO.js} +1 -1
  370. package/static/chunk-Q7U2VPIS.js +1 -0
  371. package/static/chunk-QM6CQMEX.js +1 -0
  372. package/static/chunk-QMHUIHSR.js +1 -0
  373. package/static/chunk-QNFNXDSX.js +1 -0
  374. package/static/chunk-QVFPHTOH.js +1 -0
  375. package/static/chunk-R4MI25E2.js +1 -0
  376. package/static/chunk-R7JRAR3P.js +1 -0
  377. package/static/chunk-R7PNKQU2.js +1 -0
  378. package/static/chunk-RCAORRB7.js +1 -0
  379. package/static/chunk-RK7XRDNB.js +1 -0
  380. package/static/chunk-RO7SAOLK.js +1 -0
  381. package/static/chunk-RQUUINHV.js +1 -0
  382. package/static/chunk-RT3K6DZR.js +1 -0
  383. package/static/chunk-RUN556VW.js +1 -0
  384. package/static/chunk-RX3YQ67K.js +1 -0
  385. package/static/chunk-S6EVLDHA.js +5 -0
  386. package/static/chunk-S7S5M3AZ.js +1 -0
  387. package/static/chunk-SBLNYV74.js +1 -0
  388. package/static/chunk-SIZCHHUA.js +1 -0
  389. package/static/chunk-SRBOO7AO.js +1 -0
  390. package/static/{chunk-PVDHBQRM.js → chunk-STA7NTYL.js} +1 -1
  391. package/static/chunk-T3YI3BSS.js +1 -0
  392. package/static/chunk-T74SMT7I.js +1 -0
  393. package/static/chunk-TAL3RTTQ.js +1 -0
  394. package/static/chunk-TJZKTNNS.js +1 -0
  395. package/static/chunk-UJTFWZEC.js +1 -0
  396. package/static/chunk-UPGVU5LG.js +1 -0
  397. package/static/chunk-UQ6O3I6W.js +1 -0
  398. package/static/{chunk-5NMSIIQB.js → chunk-V43RGNXA.js} +1 -1
  399. package/static/chunk-VWIRXLNE.js +1 -0
  400. package/static/chunk-VZMVGIVW.js +1 -0
  401. package/static/chunk-VZPCXSRG.js +2 -0
  402. package/static/chunk-WR3MA3L3.js +1 -0
  403. package/static/chunk-XCLK7NJL.js +1 -0
  404. package/static/{chunk-DSWEWLXJ.js → chunk-XCPDPB5G.js} +1 -1
  405. package/static/chunk-XEGHEUP5.js +1 -0
  406. package/static/chunk-XKEBQNQJ.js +1 -0
  407. package/static/chunk-XOF4UW3S.js +1 -0
  408. package/static/chunk-XOTKK2NJ.js +1 -0
  409. package/static/chunk-XX7JXKA6.js +1 -0
  410. package/static/chunk-Y2I36A4K.js +1 -0
  411. package/static/chunk-Y44XDRM5.js +1 -0
  412. package/static/{chunk-QO6BTONN.js → chunk-Y4MAPE2C.js} +1 -1
  413. package/static/chunk-Y5RLD72B.js +1 -0
  414. package/static/{chunk-DPUVSXRB.js → chunk-Y5XTRCFK.js} +1 -1
  415. package/static/chunk-Y63UUJGJ.js +1 -0
  416. package/static/chunk-YBNAC7QM.js +1 -0
  417. package/static/chunk-YCTCESL4.js +1 -0
  418. package/static/chunk-YMAN4LIU.js +1 -0
  419. package/static/chunk-YTDE6SXT.js +1 -0
  420. package/static/chunk-YZPIUJB3.js +1 -0
  421. package/static/chunk-ZCOWBVOT.js +1 -0
  422. package/static/chunk-ZHRYYMYE.js +1 -0
  423. package/static/chunk-ZNXTOQFG.js +1 -0
  424. package/static/{chunk-URHTCJ7G.js → chunk-ZQLBPLXI.js} +1 -1
  425. package/static/favicon.ico +0 -0
  426. package/static/index.html +2 -2
  427. package/static/main-3PLRDZTO.js +11 -0
  428. package/static/styles-Q4OZOSSK.css +1 -0
  429. package/server/applications/notifications/interfaces/user-mail-notification.js.map +0 -1
  430. package/static/assets/codemirror/mode/apl/apl.js +0 -174
  431. package/static/assets/codemirror/mode/asciiarmor/asciiarmor.js +0 -74
  432. package/static/assets/codemirror/mode/asn.1/asn.1.js +0 -204
  433. package/static/assets/codemirror/mode/asterisk/asterisk.js +0 -220
  434. package/static/assets/codemirror/mode/brainfuck/brainfuck.js +0 -85
  435. package/static/assets/codemirror/mode/clike/clike.js +0 -942
  436. package/static/assets/codemirror/mode/clojure/clojure.js +0 -293
  437. package/static/assets/codemirror/mode/cmake/cmake.js +0 -97
  438. package/static/assets/codemirror/mode/cobol/cobol.js +0 -255
  439. package/static/assets/codemirror/mode/coffeescript/coffeescript.js +0 -359
  440. package/static/assets/codemirror/mode/commonlisp/commonlisp.js +0 -125
  441. package/static/assets/codemirror/mode/crystal/crystal.js +0 -433
  442. package/static/assets/codemirror/mode/css/css.js +0 -862
  443. package/static/assets/codemirror/mode/cypher/cypher.js +0 -152
  444. package/static/assets/codemirror/mode/d/d.js +0 -223
  445. package/static/assets/codemirror/mode/dart/dart.js +0 -168
  446. package/static/assets/codemirror/mode/diff/diff.js +0 -47
  447. package/static/assets/codemirror/mode/django/django.js +0 -356
  448. package/static/assets/codemirror/mode/dockerfile/dockerfile.js +0 -211
  449. package/static/assets/codemirror/mode/dtd/dtd.js +0 -142
  450. package/static/assets/codemirror/mode/dylan/dylan.js +0 -352
  451. package/static/assets/codemirror/mode/ebnf/ebnf.js +0 -195
  452. package/static/assets/codemirror/mode/ecl/ecl.js +0 -206
  453. package/static/assets/codemirror/mode/eiffel/eiffel.js +0 -160
  454. package/static/assets/codemirror/mode/elm/elm.js +0 -245
  455. package/static/assets/codemirror/mode/erlang/erlang.js +0 -619
  456. package/static/assets/codemirror/mode/factor/factor.js +0 -85
  457. package/static/assets/codemirror/mode/fcl/fcl.js +0 -173
  458. package/static/assets/codemirror/mode/forth/forth.js +0 -180
  459. package/static/assets/codemirror/mode/fortran/fortran.js +0 -188
  460. package/static/assets/codemirror/mode/gas/gas.js +0 -355
  461. package/static/assets/codemirror/mode/gfm/gfm.js +0 -129
  462. package/static/assets/codemirror/mode/gherkin/gherkin.js +0 -194
  463. package/static/assets/codemirror/mode/go/go.js +0 -187
  464. package/static/assets/codemirror/mode/groovy/groovy.js +0 -245
  465. package/static/assets/codemirror/mode/haml/haml.js +0 -161
  466. package/static/assets/codemirror/mode/handlebars/handlebars.js +0 -70
  467. package/static/assets/codemirror/mode/haskell/haskell.js +0 -268
  468. package/static/assets/codemirror/mode/haskell-literate/haskell-literate.js +0 -43
  469. package/static/assets/codemirror/mode/haxe/haxe.js +0 -515
  470. package/static/assets/codemirror/mode/htmlembedded/htmlembedded.js +0 -37
  471. package/static/assets/codemirror/mode/htmlmixed/htmlmixed.js +0 -153
  472. package/static/assets/codemirror/mode/http/http.js +0 -113
  473. package/static/assets/codemirror/mode/idl/idl.js +0 -290
  474. package/static/assets/codemirror/mode/javascript/javascript.js +0 -960
  475. package/static/assets/codemirror/mode/jinja2/jinja2.js +0 -193
  476. package/static/assets/codemirror/mode/jsx/jsx.js +0 -149
  477. package/static/assets/codemirror/mode/julia/julia.js +0 -390
  478. package/static/assets/codemirror/mode/livescript/livescript.js +0 -280
  479. package/static/assets/codemirror/mode/lua/lua.js +0 -160
  480. package/static/assets/codemirror/mode/markdown/markdown.js +0 -886
  481. package/static/assets/codemirror/mode/mathematica/mathematica.js +0 -176
  482. package/static/assets/codemirror/mode/mbox/mbox.js +0 -129
  483. package/static/assets/codemirror/mode/meta.js +0 -221
  484. package/static/assets/codemirror/mode/mirc/mirc.js +0 -193
  485. package/static/assets/codemirror/mode/mllike/mllike.js +0 -359
  486. package/static/assets/codemirror/mode/modelica/modelica.js +0 -245
  487. package/static/assets/codemirror/mode/mscgen/mscgen.js +0 -175
  488. package/static/assets/codemirror/mode/mumps/mumps.js +0 -148
  489. package/static/assets/codemirror/mode/nginx/nginx.js +0 -178
  490. package/static/assets/codemirror/mode/nsis/nsis.js +0 -95
  491. package/static/assets/codemirror/mode/ntriples/ntriples.js +0 -195
  492. package/static/assets/codemirror/mode/octave/octave.js +0 -139
  493. package/static/assets/codemirror/mode/oz/oz.js +0 -252
  494. package/static/assets/codemirror/mode/pascal/pascal.js +0 -136
  495. package/static/assets/codemirror/mode/pegjs/pegjs.js +0 -111
  496. package/static/assets/codemirror/mode/perl/perl.js +0 -836
  497. package/static/assets/codemirror/mode/php/php.js +0 -234
  498. package/static/assets/codemirror/mode/pig/pig.js +0 -178
  499. package/static/assets/codemirror/mode/powershell/powershell.js +0 -398
  500. package/static/assets/codemirror/mode/properties/properties.js +0 -78
  501. package/static/assets/codemirror/mode/protobuf/protobuf.js +0 -72
  502. package/static/assets/codemirror/mode/pug/pug.js +0 -591
  503. package/static/assets/codemirror/mode/puppet/puppet.js +0 -220
  504. package/static/assets/codemirror/mode/python/python.js +0 -402
  505. package/static/assets/codemirror/mode/q/q.js +0 -139
  506. package/static/assets/codemirror/mode/r/r.js +0 -190
  507. package/static/assets/codemirror/mode/rpm/changes/index.html +0 -66
  508. package/static/assets/codemirror/mode/rpm/rpm.js +0 -109
  509. package/static/assets/codemirror/mode/rst/rst.js +0 -557
  510. package/static/assets/codemirror/mode/ruby/ruby.js +0 -303
  511. package/static/assets/codemirror/mode/rust/rust.js +0 -72
  512. package/static/assets/codemirror/mode/sas/sas.js +0 -303
  513. package/static/assets/codemirror/mode/sass/sass.js +0 -459
  514. package/static/assets/codemirror/mode/scheme/scheme.js +0 -284
  515. package/static/assets/codemirror/mode/shell/shell.js +0 -168
  516. package/static/assets/codemirror/mode/sieve/sieve.js +0 -193
  517. package/static/assets/codemirror/mode/slim/slim.js +0 -575
  518. package/static/assets/codemirror/mode/smalltalk/smalltalk.js +0 -168
  519. package/static/assets/codemirror/mode/smarty/smarty.js +0 -225
  520. package/static/assets/codemirror/mode/solr/solr.js +0 -104
  521. package/static/assets/codemirror/mode/soy/soy.js +0 -665
  522. package/static/assets/codemirror/mode/sparql/sparql.js +0 -184
  523. package/static/assets/codemirror/mode/spreadsheet/spreadsheet.js +0 -112
  524. package/static/assets/codemirror/mode/sql/sql.js +0 -529
  525. package/static/assets/codemirror/mode/stex/stex.js +0 -264
  526. package/static/assets/codemirror/mode/stylus/stylus.js +0 -775
  527. package/static/assets/codemirror/mode/swift/swift.js +0 -221
  528. package/static/assets/codemirror/mode/tcl/tcl.js +0 -140
  529. package/static/assets/codemirror/mode/textile/textile.js +0 -469
  530. package/static/assets/codemirror/mode/tiddlywiki/tiddlywiki.css +0 -14
  531. package/static/assets/codemirror/mode/tiddlywiki/tiddlywiki.js +0 -308
  532. package/static/assets/codemirror/mode/tiki/tiki.css +0 -26
  533. package/static/assets/codemirror/mode/tiki/tiki.js +0 -312
  534. package/static/assets/codemirror/mode/toml/toml.js +0 -88
  535. package/static/assets/codemirror/mode/tornado/tornado.js +0 -68
  536. package/static/assets/codemirror/mode/troff/troff.js +0 -84
  537. package/static/assets/codemirror/mode/ttcn/ttcn.js +0 -283
  538. package/static/assets/codemirror/mode/ttcn-cfg/ttcn-cfg.js +0 -214
  539. package/static/assets/codemirror/mode/turtle/turtle.js +0 -162
  540. package/static/assets/codemirror/mode/twig/twig.js +0 -141
  541. package/static/assets/codemirror/mode/vb/vb.js +0 -275
  542. package/static/assets/codemirror/mode/vbscript/vbscript.js +0 -350
  543. package/static/assets/codemirror/mode/velocity/velocity.js +0 -202
  544. package/static/assets/codemirror/mode/verilog/verilog.js +0 -781
  545. package/static/assets/codemirror/mode/vhdl/vhdl.js +0 -189
  546. package/static/assets/codemirror/mode/vue/vue.js +0 -77
  547. package/static/assets/codemirror/mode/wast/wast.js +0 -132
  548. package/static/assets/codemirror/mode/webidl/webidl.js +0 -195
  549. package/static/assets/codemirror/mode/xml/xml.js +0 -417
  550. package/static/assets/codemirror/mode/xquery/xquery.js +0 -448
  551. package/static/assets/codemirror/mode/yacas/yacas.js +0 -204
  552. package/static/assets/codemirror/mode/yaml/yaml.js +0 -120
  553. package/static/assets/codemirror/mode/yaml-frontmatter/yaml-frontmatter.js +0 -72
  554. package/static/assets/codemirror/mode/z80/z80.js +0 -116
  555. package/static/chunk-2KLC4T2Z.js +0 -1
  556. package/static/chunk-2VMSXRCB.js +0 -12
  557. package/static/chunk-3OHSRRKH.js +0 -4
  558. package/static/chunk-3R4WKOHQ.js +0 -1
  559. package/static/chunk-3XVM35O2.js +0 -1
  560. package/static/chunk-3YVRP3VM.js +0 -2
  561. package/static/chunk-5UKZLU5H.js +0 -1
  562. package/static/chunk-AF24EYXU.js +0 -1
  563. package/static/chunk-AKQVEHO6.js +0 -2
  564. package/static/chunk-BCVX464U.js +0 -2
  565. package/static/chunk-BQV4FRM6.js +0 -1
  566. package/static/chunk-CETH7UYS.js +0 -1
  567. package/static/chunk-DIT6W7VM.js +0 -562
  568. package/static/chunk-DKSEQTMX.js +0 -1
  569. package/static/chunk-FZ3JPGYZ.js +0 -1
  570. package/static/chunk-IQSKQXC3.js +0 -1
  571. package/static/chunk-ITUFI2BJ.js +0 -1
  572. package/static/chunk-LCTZJ537.js +0 -1
  573. package/static/chunk-LK2UCQJ6.js +0 -1
  574. package/static/chunk-LP5TBXEN.js +0 -7
  575. package/static/chunk-N3U6637P.js +0 -1
  576. package/static/chunk-NNV4OXSB.js +0 -1
  577. package/static/chunk-O6FYXVHI.js +0 -1
  578. package/static/chunk-OOGP4WSH.js +0 -2
  579. package/static/chunk-PCWDQPOM.js +0 -2
  580. package/static/chunk-PNR6M34W.js +0 -1
  581. package/static/chunk-Q5KM7LTX.js +0 -1
  582. package/static/chunk-QHC6ZPQ4.js +0 -1
  583. package/static/chunk-QMRBZHE4.js +0 -1
  584. package/static/chunk-QSJRY3TF.js +0 -1
  585. package/static/chunk-QUUIRSYT.js +0 -1
  586. package/static/chunk-RFH46UW3.js +0 -1
  587. package/static/chunk-RSXHRKM5.js +0 -1
  588. package/static/chunk-RV3VZJPZ.js +0 -1
  589. package/static/chunk-S7HNXVRB.js +0 -1
  590. package/static/chunk-SBZ572Q4.js +0 -2
  591. package/static/chunk-SJR5R3Y4.js +0 -1
  592. package/static/chunk-SLHTEGRU.js +0 -1
  593. package/static/chunk-SSFF27P2.js +0 -24
  594. package/static/chunk-V3LHHZYN.js +0 -1
  595. package/static/chunk-VQQKMY2C.js +0 -1
  596. package/static/chunk-WSSU2HXE.js +0 -1
  597. package/static/chunk-XDZGW64M.js +0 -3
  598. package/static/chunk-XTRDKGKG.js +0 -1
  599. package/static/chunk-YLWTEC3X.js +0 -1
  600. package/static/chunk-Z5J5F5SX.js +0 -1
  601. package/static/main-4H5BJY3J.js +0 -9
  602. package/static/scripts-WRDOQIU5.js +0 -24
  603. package/static/styles-2C2UNCNB.css +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/authentication/services/auth-methods/auth-method-ldap.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'\nimport { AndFilter, Client, ClientOptions, Entry, EqualityFilter, InvalidCredentialsError, OrFilter } from 'ldapts'\nimport { CONNECT_ERROR_CODE } from '../../../app.constants'\nimport { USER_ROLE } from '../../../applications/users/constants/user'\nimport type { CreateUserDto, UpdateUserDto } from '../../../applications/users/dto/create-or-update-user.dto'\nimport { UserModel } from '../../../applications/users/models/user.model'\nimport { AdminUsersManager } from '../../../applications/users/services/admin-users-manager.service'\nimport { UsersManager } from '../../../applications/users/services/users-manager.service'\nimport { comparePassword, splitFullName } from '../../../common/functions'\nimport { configuration } from '../../../configuration/config.environment'\nimport { ALL_LDAP_ATTRIBUTES, LDAP_COMMON_ATTR, LDAP_LOGIN_ATTR } from '../../constants/auth-ldap'\nimport type { AUTH_SCOPE } from '../../constants/scope'\nimport { AuthMethod } from '../../models/auth-method'\n\ntype LdapUserEntry = Entry & Record<LDAP_LOGIN_ATTR | (typeof LDAP_COMMON_ATTR)[keyof typeof LDAP_COMMON_ATTR], string>\n\n@Injectable()\nexport class AuthMethodLdapService implements AuthMethod {\n private readonly logger = new Logger(AuthMethodLdapService.name)\n private readonly ldapConfig = configuration.auth.ldap\n private clientOptions: ClientOptions = { timeout: 6000, connectTimeout: 6000, url: '' }\n\n constructor(\n private readonly usersManager: UsersManager,\n private readonly adminUsersManager: AdminUsersManager\n ) {}\n\n async validateUser(login: string, password: string, ip?: string, scope?: AUTH_SCOPE): Promise<UserModel> {\n let user: UserModel = await this.usersManager.findUser(this.dbLogin(login), false)\n if (user) {\n if (user.isGuest) {\n // allow guests to be authenticated from db and check if the current user is defined as active\n return this.usersManager.logUser(user, password, ip)\n }\n if (!user.isActive) {\n this.logger.error(`${this.validateUser.name} - user *${user.login}* is locked`)\n throw new HttpException('Account locked', HttpStatus.FORBIDDEN)\n }\n }\n const entry: false | LdapUserEntry = await this.checkAuth(login, password)\n if (entry === false) {\n // LDAP auth failed\n if (user) {\n let authSuccess = false\n if (scope) {\n // try user app password\n authSuccess = await this.usersManager.validateAppPassword(user, password, ip, scope)\n }\n this.usersManager.updateAccesses(user, ip, authSuccess).catch((e: Error) => this.logger.error(`${this.validateUser.name} : ${e}`))\n if (authSuccess) {\n // logged with app password\n return user\n }\n }\n return null\n } else if (!entry[this.ldapConfig.attributes.login] || !entry[this.ldapConfig.attributes.email]) {\n this.logger.error(`${this.validateUser.name} - required ldap fields are missing : \n [${this.ldapConfig.attributes.login}, ${this.ldapConfig.attributes.email}] => \n (${JSON.stringify(entry)})`)\n return null\n }\n const identity = this.createIdentity(entry, password)\n user = await this.updateOrCreateUser(identity, user)\n this.usersManager.updateAccesses(user, ip, true).catch((e: Error) => this.logger.error(`${this.validateUser.name} : ${e}`))\n return user\n }\n\n private async checkAuth(login: string, password: string): Promise<LdapUserEntry | false> {\n const ldapLogin = this.buildLdapLogin(login)\n const isAD = this.ldapConfig.attributes.login === LDAP_LOGIN_ATTR.SAM || this.ldapConfig.attributes.login === LDAP_LOGIN_ATTR.UPN\n // AD: bind directly with the user input (UPN or DOMAIN\\user)\n // Generic LDAP: build DN from login attribute + baseDN\n const bindUserDN = isAD ? ldapLogin : `${this.ldapConfig.attributes.login}=${ldapLogin},${this.ldapConfig.baseDN}`\n let client: Client\n let error: any\n for (const s of this.ldapConfig.servers) {\n client = new Client({ ...this.clientOptions, url: s })\n try {\n await client.bind(bindUserDN, password)\n return await this.checkAccess(ldapLogin, client)\n } catch (e) {\n if (e.errors?.length) {\n for (const err of e.errors) {\n this.logger.warn(`${this.checkAuth.name} - ${ldapLogin} : ${err}`)\n error = err\n }\n } else {\n error = e\n this.logger.warn(`${this.checkAuth.name} - ${ldapLogin} : ${e}`)\n }\n if (error instanceof InvalidCredentialsError) {\n return false\n }\n } finally {\n await client.unbind()\n }\n }\n if (error && CONNECT_ERROR_CODE.has(error.code)) {\n throw new HttpException('Authentication service error', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n return false\n }\n\n private async checkAccess(login: string, client: Client): Promise<LdapUserEntry | false> {\n const searchFilter = this.buildUserFilter(login, this.ldapConfig.filter)\n try {\n const { searchEntries } = await client.search(this.ldapConfig.baseDN, {\n scope: 'sub',\n filter: searchFilter,\n attributes: ALL_LDAP_ATTRIBUTES\n })\n\n if (searchEntries.length === 0) {\n this.logger.debug(`${this.checkAccess.name} - search filter : ${searchFilter}`)\n this.logger.warn(`${this.checkAccess.name} - no LDAP entry found for : ${login}`)\n return false\n }\n\n if (searchEntries.length > 1) {\n this.logger.warn(`${this.checkAccess.name} - multiple LDAP entries found for : ${login}, using first one`)\n }\n\n // Always return the first valid entry\n return this.convertToLdapUserEntry(searchEntries[0])\n } catch (e) {\n this.logger.debug(`${this.checkAccess.name} - search filter : ${searchFilter}`)\n this.logger.error(`${this.checkAccess.name} - ${login} : ${e}`)\n return false\n }\n }\n\n private async updateOrCreateUser(identity: CreateUserDto, user: UserModel): Promise<UserModel> {\n if (user === null) {\n // create\n const createdUser = await this.adminUsersManager.createUserOrGuest(identity, identity.role)\n const freshUser = await this.usersManager.fromUserId(createdUser.id)\n if (!freshUser) {\n this.logger.error(`${this.updateOrCreateUser.name} - user was not found : ${createdUser.login} (${createdUser.id})`)\n throw new HttpException('User not found', HttpStatus.NOT_FOUND)\n }\n return freshUser\n }\n if (identity.login !== user.login) {\n this.logger.error(`${this.updateOrCreateUser.name} - user login mismatch : ${identity.login} !== ${user.login}`)\n throw new HttpException('Account matching error', HttpStatus.FORBIDDEN)\n }\n // update: check if user information has changed\n const identityHasChanged: UpdateUserDto = Object.fromEntries(\n (\n await Promise.all(\n Object.keys(identity).map(async (key: string) => {\n if (key === 'password') {\n const isSame = await comparePassword(identity[key], user.password)\n return isSame ? null : [key, identity[key]]\n }\n return identity[key] !== user[key] ? [key, identity[key]] : null\n })\n )\n ).filter(Boolean)\n )\n if (Object.keys(identityHasChanged).length > 0) {\n try {\n if (identityHasChanged?.role != null) {\n if (user.role === USER_ROLE.ADMINISTRATOR && !this.ldapConfig.adminGroup) {\n // Prevent removing admin role when adminGroup was removed or not defined\n delete identityHasChanged.role\n }\n }\n // Update user properties\n await this.adminUsersManager.updateUserOrGuest(user.id, identityHasChanged)\n // Extra stuff\n if (identityHasChanged?.password) {\n delete identityHasChanged.password\n }\n Object.assign(user, identityHasChanged)\n if ('lastName' in identityHasChanged || 'firstName' in identityHasChanged) {\n // force fullName update in current user model\n user.setFullName(true)\n }\n } catch (e) {\n this.logger.warn(`${this.updateOrCreateUser.name} - unable to update user *${user.login}* : ${e}`)\n }\n }\n return user\n }\n\n private convertToLdapUserEntry(entry: Entry): LdapUserEntry {\n for (const attr of ALL_LDAP_ATTRIBUTES) {\n if (attr === LDAP_COMMON_ATTR.MEMBER_OF && entry[attr]) {\n entry[attr] = (Array.isArray(entry[attr]) ? entry[attr] : entry[attr] ? [entry[attr]] : [])\n .filter((v: any) => typeof v === 'string')\n .map((v) => v.match(/cn\\s*=\\s*([^,]+)/i)?.[1]?.trim())\n .filter(Boolean)\n continue\n }\n if (Array.isArray(entry[attr])) {\n // Keep only the first value for all other attributes (e.g., email)\n entry[attr] = entry[attr].length > 0 ? entry[attr][0] : null\n }\n }\n return entry as LdapUserEntry\n }\n\n private createIdentity(entry: LdapUserEntry, password: string): CreateUserDto {\n const isAdmin =\n typeof this.ldapConfig.adminGroup === 'string' &&\n this.ldapConfig.adminGroup &&\n entry[LDAP_COMMON_ATTR.MEMBER_OF]?.includes(this.ldapConfig.adminGroup)\n return {\n login: this.dbLogin(entry[this.ldapConfig.attributes.login]),\n email: entry[this.ldapConfig.attributes.email] as string,\n password: password,\n role: isAdmin ? USER_ROLE.ADMINISTRATOR : USER_ROLE.USER,\n ...this.getFirstNameAndLastName(entry)\n } satisfies CreateUserDto\n }\n\n private getFirstNameAndLastName(entry: LdapUserEntry): { firstName: string; lastName: string } {\n // 1) Prefer structured attributes\n if (entry.sn && entry.givenName) {\n return { firstName: entry.givenName, lastName: entry.sn }\n }\n // 2) Fallback to displayName if available\n if (entry.displayName && entry.displayName.trim()) {\n return splitFullName(entry.displayName)\n }\n // 3) Fallback to cn\n if (entry.cn && entry.cn.trim()) {\n return splitFullName(entry.cn)\n }\n // 4) Nothing usable\n return { firstName: '', lastName: '' }\n }\n\n private dbLogin(login: string): string {\n if (login.includes('@')) {\n return login.split('@')[0]\n } else if (login.includes('\\\\')) {\n return login.split('\\\\').slice(-1)[0]\n }\n return login\n }\n\n private buildLdapLogin(login: string): string {\n if (this.ldapConfig.attributes.login === LDAP_LOGIN_ATTR.UPN) {\n if (this.ldapConfig.upnSuffix && !login.includes('@')) {\n return `${login}@${this.ldapConfig.upnSuffix}`\n }\n } else if (this.ldapConfig.attributes.login === LDAP_LOGIN_ATTR.SAM) {\n if (this.ldapConfig.netbiosName && !login.includes('\\\\')) {\n return `${this.ldapConfig.netbiosName}\\\\${login}`\n }\n }\n return login\n }\n\n private buildUserFilter(login: string, extraFilter?: string): string {\n // Build a safe LDAP filter to search for a user.\n // Important: - Values passed to EqualityFilter are auto-escaped by ldapts\n // - extraFilter is appended as-is (assumed trusted configuration)\n // Output: (&(|(userPrincipalName=john.doe@sync-in.com)(sAMAccountName=john.doe)(uid=john.doe))(*extraFilter*))\n\n // Handle the case where the sAMAccountName is provided in domain-qualified format (e.g., SYNC_IN\\\\user)\n // Note: sAMAccountName is always stored without the domain in Active Directory.\n const uid = this.dbLogin(login)\n\n const or = new OrFilter({\n filters: [\n new EqualityFilter({ attribute: LDAP_LOGIN_ATTR.UPN, value: login }),\n new EqualityFilter({ attribute: LDAP_LOGIN_ATTR.SAM, value: uid }),\n new EqualityFilter({ attribute: LDAP_LOGIN_ATTR.UID, value: uid })\n ]\n })\n\n // Convert to LDAP filter string\n let filterString = new AndFilter({ filters: [or] }).toString()\n\n // Optionally append an extra filter from config (trusted source)\n if (extraFilter && extraFilter.trim()) {\n filterString = `(&${filterString}${extraFilter})`\n }\n return filterString\n }\n}\n"],"names":["AuthMethodLdapService","validateUser","login","password","ip","scope","user","usersManager","findUser","dbLogin","isGuest","logUser","isActive","logger","error","name","HttpException","HttpStatus","FORBIDDEN","entry","checkAuth","authSuccess","validateAppPassword","updateAccesses","catch","e","ldapConfig","attributes","email","JSON","stringify","identity","createIdentity","updateOrCreateUser","ldapLogin","buildLdapLogin","isAD","LDAP_LOGIN_ATTR","SAM","UPN","bindUserDN","baseDN","client","s","servers","Client","clientOptions","url","bind","checkAccess","errors","length","err","warn","InvalidCredentialsError","unbind","CONNECT_ERROR_CODE","has","code","INTERNAL_SERVER_ERROR","searchFilter","buildUserFilter","filter","searchEntries","search","ALL_LDAP_ATTRIBUTES","debug","convertToLdapUserEntry","createdUser","adminUsersManager","createUserOrGuest","role","freshUser","fromUserId","id","NOT_FOUND","identityHasChanged","Object","fromEntries","Promise","all","keys","map","key","isSame","comparePassword","Boolean","USER_ROLE","ADMINISTRATOR","adminGroup","updateUserOrGuest","assign","setFullName","attr","LDAP_COMMON_ATTR","MEMBER_OF","Array","isArray","v","match","trim","isAdmin","includes","USER","getFirstNameAndLastName","sn","givenName","firstName","lastName","displayName","splitFullName","cn","split","slice","upnSuffix","netbiosName","extraFilter","uid","or","OrFilter","filters","EqualityFilter","attribute","value","UID","filterString","AndFilter","toString","Logger","configuration","auth","ldap","timeout","connectTimeout"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../backend/src/authentication/services/auth-methods/auth-method-ldap.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'\nimport { AndFilter, Client, ClientOptions, Entry, EqualityFilter, InvalidCredentialsError, OrFilter } from 'ldapts'\nimport { CONNECT_ERROR_CODE } from '../../../app.constants'\nimport { USER_ROLE } from '../../../applications/users/constants/user'\nimport type { CreateUserDto, UpdateUserDto } from '../../../applications/users/dto/create-or-update-user.dto'\nimport { UserModel } from '../../../applications/users/models/user.model'\nimport { AdminUsersManager } from '../../../applications/users/services/admin-users-manager.service'\nimport { UsersManager } from '../../../applications/users/services/users-manager.service'\nimport { comparePassword, splitFullName } from '../../../common/functions'\nimport { configuration } from '../../../configuration/config.environment'\nimport { ALL_LDAP_ATTRIBUTES, LDAP_COMMON_ATTR, LDAP_LOGIN_ATTR } from '../../constants/auth-ldap'\nimport type { AUTH_SCOPE } from '../../constants/scope'\nimport { AuthMethod } from '../../models/auth-method'\n\ntype LdapUserEntry = Entry & Record<LDAP_LOGIN_ATTR | (typeof LDAP_COMMON_ATTR)[keyof typeof LDAP_COMMON_ATTR], string>\n\n@Injectable()\nexport class AuthMethodLdapService implements AuthMethod {\n private readonly logger = new Logger(AuthMethodLdapService.name)\n private readonly ldapConfig = configuration.auth.ldap\n private readonly isAD = this.ldapConfig.attributes.login === LDAP_LOGIN_ATTR.SAM || this.ldapConfig.attributes.login === LDAP_LOGIN_ATTR.UPN\n private clientOptions: ClientOptions = { timeout: 6000, connectTimeout: 6000, url: '' }\n\n constructor(\n private readonly usersManager: UsersManager,\n private readonly adminUsersManager: AdminUsersManager\n ) {}\n\n async validateUser(login: string, password: string, ip?: string, scope?: AUTH_SCOPE): Promise<UserModel> {\n // Find user from his login or email\n let user: UserModel = await this.usersManager.findUser(this.dbLogin(login), false)\n if (user) {\n if (user.isGuest) {\n // Allow guests to be authenticated from db and check if the current user is defined as active\n return this.usersManager.logUser(user, password, ip)\n }\n if (!user.isActive) {\n this.logger.error(`${this.validateUser.name} - user *${user.login}* is locked`)\n throw new HttpException('Account locked', HttpStatus.FORBIDDEN)\n }\n }\n // If a user was found, use the stored login. This allows logging in with an email.\n const entry: false | LdapUserEntry = await this.checkAuth(user?.login || login, password)\n if (entry === false) {\n // LDAP auth failed\n if (user) {\n let authSuccess = false\n if (scope) {\n // Try user app password\n authSuccess = await this.usersManager.validateAppPassword(user, password, ip, scope)\n }\n this.usersManager.updateAccesses(user, ip, authSuccess).catch((e: Error) => this.logger.error(`${this.validateUser.name} : ${e}`))\n if (authSuccess) {\n // Logged with app password\n return user\n }\n }\n return null\n } else if (!entry[this.ldapConfig.attributes.login] || !entry[this.ldapConfig.attributes.email]) {\n this.logger.error(`${this.validateUser.name} - required ldap fields are missing : \n [${this.ldapConfig.attributes.login}, ${this.ldapConfig.attributes.email}] => \n (${JSON.stringify(entry)})`)\n return null\n }\n const identity = this.createIdentity(entry, password)\n user = await this.updateOrCreateUser(identity, user)\n this.usersManager.updateAccesses(user, ip, true).catch((e: Error) => this.logger.error(`${this.validateUser.name} : ${e}`))\n return user\n }\n\n private async checkAuth(login: string, password: string): Promise<LdapUserEntry | false> {\n const ldapLogin = this.buildLdapLogin(login)\n // AD: bind directly with the user input (UPN or DOMAIN\\user)\n // Generic LDAP: build DN from login attribute + baseDN\n const bindUserDN = this.isAD ? ldapLogin : `${this.ldapConfig.attributes.login}=${ldapLogin},${this.ldapConfig.baseDN}`\n let client: Client\n let error: any\n for (const s of this.ldapConfig.servers) {\n client = new Client({ ...this.clientOptions, url: s })\n try {\n await client.bind(bindUserDN, password)\n return await this.checkAccess(ldapLogin, client)\n } catch (e) {\n if (e.errors?.length) {\n for (const err of e.errors) {\n this.logger.warn(`${this.checkAuth.name} - ${ldapLogin} : ${err}`)\n error = err\n }\n } else {\n error = e\n this.logger.warn(`${this.checkAuth.name} - ${ldapLogin} : ${e}`)\n }\n if (error instanceof InvalidCredentialsError) {\n return false\n }\n } finally {\n await client.unbind()\n }\n }\n if (error && CONNECT_ERROR_CODE.has(error.code)) {\n throw new HttpException('Authentication service error', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n return false\n }\n\n private async checkAccess(login: string, client: Client): Promise<LdapUserEntry | false> {\n const searchFilter = this.buildUserFilter(login, this.ldapConfig.filter)\n try {\n const { searchEntries } = await client.search(this.ldapConfig.baseDN, {\n scope: 'sub',\n filter: searchFilter,\n attributes: ALL_LDAP_ATTRIBUTES\n })\n\n if (searchEntries.length === 0) {\n this.logger.debug(`${this.checkAccess.name} - search filter : ${searchFilter}`)\n this.logger.warn(`${this.checkAccess.name} - no LDAP entry found for : ${login}`)\n return false\n }\n\n if (searchEntries.length > 1) {\n this.logger.warn(`${this.checkAccess.name} - multiple LDAP entries found for : ${login}, using first one`)\n }\n\n // Always return the first valid entry\n return this.convertToLdapUserEntry(searchEntries[0])\n } catch (e) {\n this.logger.debug(`${this.checkAccess.name} - search filter : ${searchFilter}`)\n this.logger.error(`${this.checkAccess.name} - ${login} : ${e}`)\n return false\n }\n }\n\n private async updateOrCreateUser(identity: CreateUserDto, user: UserModel): Promise<UserModel> {\n if (user === null) {\n // Create\n const createdUser = await this.adminUsersManager.createUserOrGuest(identity, identity.role)\n const freshUser = await this.usersManager.fromUserId(createdUser.id)\n if (!freshUser) {\n this.logger.error(`${this.updateOrCreateUser.name} - user was not found : ${createdUser.login} (${createdUser.id})`)\n throw new HttpException('User not found', HttpStatus.NOT_FOUND)\n }\n return freshUser\n }\n if (identity.login !== user.login) {\n this.logger.error(`${this.updateOrCreateUser.name} - user login mismatch : ${identity.login} !== ${user.login}`)\n throw new HttpException('Account matching error', HttpStatus.FORBIDDEN)\n }\n // Update: check if user information has changed\n const identityHasChanged: UpdateUserDto = Object.fromEntries(\n (\n await Promise.all(\n Object.keys(identity).map(async (key: string) => {\n if (key === 'password') {\n const isSame = await comparePassword(identity[key], user.password)\n return isSame ? null : [key, identity[key]]\n }\n return identity[key] !== user[key] ? [key, identity[key]] : null\n })\n )\n ).filter(Boolean)\n )\n if (Object.keys(identityHasChanged).length > 0) {\n try {\n if (identityHasChanged?.role != null) {\n if (user.role === USER_ROLE.ADMINISTRATOR && !this.ldapConfig.adminGroup) {\n // Prevent removing the admin role when adminGroup was removed or not defined\n delete identityHasChanged.role\n }\n }\n // Update user properties\n await this.adminUsersManager.updateUserOrGuest(user.id, identityHasChanged)\n // Extra stuff\n if (identityHasChanged?.password) {\n delete identityHasChanged.password\n }\n Object.assign(user, identityHasChanged)\n if ('lastName' in identityHasChanged || 'firstName' in identityHasChanged) {\n // Force fullName update in the current user model\n user.setFullName(true)\n }\n } catch (e) {\n this.logger.warn(`${this.updateOrCreateUser.name} - unable to update user *${user.login}* : ${e}`)\n }\n }\n return user\n }\n\n private convertToLdapUserEntry(entry: Entry): LdapUserEntry {\n for (const attr of ALL_LDAP_ATTRIBUTES) {\n if (attr === LDAP_COMMON_ATTR.MEMBER_OF && entry[attr]) {\n entry[attr] = (Array.isArray(entry[attr]) ? entry[attr] : entry[attr] ? [entry[attr]] : [])\n .filter((v: any) => typeof v === 'string')\n .map((v) => v.match(/cn\\s*=\\s*([^,]+)/i)?.[1]?.trim())\n .filter(Boolean)\n continue\n }\n if (Array.isArray(entry[attr])) {\n // Keep only the first value for all other attributes (e.g., email)\n entry[attr] = entry[attr].length > 0 ? entry[attr][0] : null\n }\n }\n return entry as LdapUserEntry\n }\n\n private createIdentity(entry: LdapUserEntry, password: string): CreateUserDto {\n const isAdmin =\n typeof this.ldapConfig.adminGroup === 'string' &&\n this.ldapConfig.adminGroup &&\n entry[LDAP_COMMON_ATTR.MEMBER_OF]?.includes(this.ldapConfig.adminGroup)\n return {\n login: this.dbLogin(entry[this.ldapConfig.attributes.login]),\n email: entry[this.ldapConfig.attributes.email] as string,\n password: password,\n role: isAdmin ? USER_ROLE.ADMINISTRATOR : USER_ROLE.USER,\n ...this.getFirstNameAndLastName(entry)\n } satisfies CreateUserDto\n }\n\n private getFirstNameAndLastName(entry: LdapUserEntry): { firstName: string; lastName: string } {\n // 1) Prefer structured attributes\n if (entry.sn && entry.givenName) {\n return { firstName: entry.givenName, lastName: entry.sn }\n }\n // 2) Fallback to displayName if available\n if (entry.displayName && entry.displayName.trim()) {\n return splitFullName(entry.displayName)\n }\n // 3) Fallback to cn\n if (entry.cn && entry.cn.trim()) {\n return splitFullName(entry.cn)\n }\n // 4) Nothing usable\n return { firstName: '', lastName: '' }\n }\n\n private dbLogin(login: string): string {\n if (login.includes('\\\\')) {\n return login.split('\\\\').slice(-1)[0]\n }\n return login\n }\n\n private buildLdapLogin(login: string): string {\n if (this.ldapConfig.attributes.login === LDAP_LOGIN_ATTR.UPN) {\n if (this.ldapConfig.upnSuffix && !login.includes('@')) {\n return `${login}@${this.ldapConfig.upnSuffix}`\n }\n } else if (this.ldapConfig.attributes.login === LDAP_LOGIN_ATTR.SAM) {\n if (this.ldapConfig.netbiosName && !login.includes('\\\\')) {\n return `${this.ldapConfig.netbiosName}\\\\${login}`\n }\n }\n return login\n }\n\n private buildUserFilter(login: string, extraFilter?: string): string {\n // Build a safe LDAP filter to search for a user.\n // Important: - Values passed to EqualityFilter are auto-escaped by ldapts\n // - extraFilter is appended as-is (assumed trusted configuration)\n // Output: (&(|(userPrincipalName=john.doe@sync-in.com)(sAMAccountName=john.doe)(cn=john.doe)(uid=john.doe)(mail=john.doe@sync-in.com))(*extraFilter*))\n\n // Handle the case where the sAMAccountName is provided in domain-qualified format (e.g., SYNC_IN\\\\user)\n // Note: sAMAccountName is always stored without the domain in Active Directory.\n const dbLogin = this.dbLogin(login)\n\n const or = new OrFilter({\n filters: this.isAD\n ? [\n new EqualityFilter({ attribute: LDAP_LOGIN_ATTR.SAM, value: dbLogin }),\n new EqualityFilter({ attribute: LDAP_LOGIN_ATTR.UPN, value: dbLogin }),\n new EqualityFilter({ attribute: LDAP_LOGIN_ATTR.MAIL, value: dbLogin })\n ]\n : [\n new EqualityFilter({ attribute: LDAP_LOGIN_ATTR.UID, value: dbLogin }),\n new EqualityFilter({ attribute: LDAP_LOGIN_ATTR.CN, value: dbLogin }),\n new EqualityFilter({ attribute: LDAP_LOGIN_ATTR.MAIL, value: dbLogin })\n ]\n })\n\n // Convert to LDAP filter string\n let filterString = new AndFilter({ filters: [or] }).toString()\n\n // Optionally append an extra filter from config (trusted source)\n if (extraFilter && extraFilter.trim()) {\n filterString = `(&${filterString}${extraFilter})`\n }\n return filterString\n }\n}\n"],"names":["AuthMethodLdapService","validateUser","login","password","ip","scope","user","usersManager","findUser","dbLogin","isGuest","logUser","isActive","logger","error","name","HttpException","HttpStatus","FORBIDDEN","entry","checkAuth","authSuccess","validateAppPassword","updateAccesses","catch","e","ldapConfig","attributes","email","JSON","stringify","identity","createIdentity","updateOrCreateUser","ldapLogin","buildLdapLogin","bindUserDN","isAD","baseDN","client","s","servers","Client","clientOptions","url","bind","checkAccess","errors","length","err","warn","InvalidCredentialsError","unbind","CONNECT_ERROR_CODE","has","code","INTERNAL_SERVER_ERROR","searchFilter","buildUserFilter","filter","searchEntries","search","ALL_LDAP_ATTRIBUTES","debug","convertToLdapUserEntry","createdUser","adminUsersManager","createUserOrGuest","role","freshUser","fromUserId","id","NOT_FOUND","identityHasChanged","Object","fromEntries","Promise","all","keys","map","key","isSame","comparePassword","Boolean","USER_ROLE","ADMINISTRATOR","adminGroup","updateUserOrGuest","assign","setFullName","attr","LDAP_COMMON_ATTR","MEMBER_OF","Array","isArray","v","match","trim","isAdmin","includes","USER","getFirstNameAndLastName","sn","givenName","firstName","lastName","displayName","splitFullName","cn","split","slice","LDAP_LOGIN_ATTR","UPN","upnSuffix","SAM","netbiosName","extraFilter","or","OrFilter","filters","EqualityFilter","attribute","value","MAIL","UID","CN","filterString","AndFilter","toString","Logger","configuration","auth","ldap","timeout","connectTimeout"],"mappings":"AAAA;;;;CAIC;;;;+BAmBYA;;;eAAAA;;;wBAjBiD;wBAC6C;8BACxE;sBACT;0CAGQ;qCACL;2BACkB;mCACjB;0BACyC;;;;;;;;;;AAOhE,IAAA,AAAMA,wBAAN,MAAMA;IAWX,MAAMC,aAAaC,KAAa,EAAEC,QAAgB,EAAEC,EAAW,EAAEC,KAAkB,EAAsB;QACvG,oCAAoC;QACpC,IAAIC,OAAkB,MAAM,IAAI,CAACC,YAAY,CAACC,QAAQ,CAAC,IAAI,CAACC,OAAO,CAACP,QAAQ;QAC5E,IAAII,MAAM;YACR,IAAIA,KAAKI,OAAO,EAAE;gBAChB,8FAA8F;gBAC9F,OAAO,IAAI,CAACH,YAAY,CAACI,OAAO,CAACL,MAAMH,UAAUC;YACnD;YACA,IAAI,CAACE,KAAKM,QAAQ,EAAE;gBAClB,IAAI,CAACC,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAACb,YAAY,CAACc,IAAI,CAAC,SAAS,EAAET,KAAKJ,KAAK,CAAC,WAAW,CAAC;gBAC9E,MAAM,IAAIc,qBAAa,CAAC,kBAAkBC,kBAAU,CAACC,SAAS;YAChE;QACF;QACA,mFAAmF;QACnF,MAAMC,QAA+B,MAAM,IAAI,CAACC,SAAS,CAACd,MAAMJ,SAASA,OAAOC;QAChF,IAAIgB,UAAU,OAAO;YACnB,mBAAmB;YACnB,IAAIb,MAAM;gBACR,IAAIe,cAAc;gBAClB,IAAIhB,OAAO;oBACT,wBAAwB;oBACxBgB,cAAc,MAAM,IAAI,CAACd,YAAY,CAACe,mBAAmB,CAAChB,MAAMH,UAAUC,IAAIC;gBAChF;gBACA,IAAI,CAACE,YAAY,CAACgB,cAAc,CAACjB,MAAMF,IAAIiB,aAAaG,KAAK,CAAC,CAACC,IAAa,IAAI,CAACZ,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAACb,YAAY,CAACc,IAAI,CAAC,GAAG,EAAEU,GAAG;gBAChI,IAAIJ,aAAa;oBACf,2BAA2B;oBAC3B,OAAOf;gBACT;YACF;YACA,OAAO;QACT,OAAO,IAAI,CAACa,KAAK,CAAC,IAAI,CAACO,UAAU,CAACC,UAAU,CAACzB,KAAK,CAAC,IAAI,CAACiB,KAAK,CAAC,IAAI,CAACO,UAAU,CAACC,UAAU,CAACC,KAAK,CAAC,EAAE;YAC/F,IAAI,CAACf,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAACb,YAAY,CAACc,IAAI,CAAC;OAC3C,EAAE,IAAI,CAACW,UAAU,CAACC,UAAU,CAACzB,KAAK,CAAC,EAAE,EAAE,IAAI,CAACwB,UAAU,CAACC,UAAU,CAACC,KAAK,CAAC;OACxE,EAAEC,KAAKC,SAAS,CAACX,OAAO,CAAC,CAAC;YAC3B,OAAO;QACT;QACA,MAAMY,WAAW,IAAI,CAACC,cAAc,CAACb,OAAOhB;QAC5CG,OAAO,MAAM,IAAI,CAAC2B,kBAAkB,CAACF,UAAUzB;QAC/C,IAAI,CAACC,YAAY,CAACgB,cAAc,CAACjB,MAAMF,IAAI,MAAMoB,KAAK,CAAC,CAACC,IAAa,IAAI,CAACZ,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAACb,YAAY,CAACc,IAAI,CAAC,GAAG,EAAEU,GAAG;QACzH,OAAOnB;IACT;IAEA,MAAcc,UAAUlB,KAAa,EAAEC,QAAgB,EAAkC;QACvF,MAAM+B,YAAY,IAAI,CAACC,cAAc,CAACjC;QACtC,6DAA6D;QAC7D,uDAAuD;QACvD,MAAMkC,aAAa,IAAI,CAACC,IAAI,GAAGH,YAAY,GAAG,IAAI,CAACR,UAAU,CAACC,UAAU,CAACzB,KAAK,CAAC,CAAC,EAAEgC,UAAU,CAAC,EAAE,IAAI,CAACR,UAAU,CAACY,MAAM,EAAE;QACvH,IAAIC;QACJ,IAAIzB;QACJ,KAAK,MAAM0B,KAAK,IAAI,CAACd,UAAU,CAACe,OAAO,CAAE;YACvCF,SAAS,IAAIG,cAAM,CAAC;gBAAE,GAAG,IAAI,CAACC,aAAa;gBAAEC,KAAKJ;YAAE;YACpD,IAAI;gBACF,MAAMD,OAAOM,IAAI,CAACT,YAAYjC;gBAC9B,OAAO,MAAM,IAAI,CAAC2C,WAAW,CAACZ,WAAWK;YAC3C,EAAE,OAAOd,GAAG;gBACV,IAAIA,EAAEsB,MAAM,EAAEC,QAAQ;oBACpB,KAAK,MAAMC,OAAOxB,EAAEsB,MAAM,CAAE;wBAC1B,IAAI,CAAClC,MAAM,CAACqC,IAAI,CAAC,GAAG,IAAI,CAAC9B,SAAS,CAACL,IAAI,CAAC,GAAG,EAAEmB,UAAU,GAAG,EAAEe,KAAK;wBACjEnC,QAAQmC;oBACV;gBACF,OAAO;oBACLnC,QAAQW;oBACR,IAAI,CAACZ,MAAM,CAACqC,IAAI,CAAC,GAAG,IAAI,CAAC9B,SAAS,CAACL,IAAI,CAAC,GAAG,EAAEmB,UAAU,GAAG,EAAET,GAAG;gBACjE;gBACA,IAAIX,iBAAiBqC,+BAAuB,EAAE;oBAC5C,OAAO;gBACT;YACF,SAAU;gBACR,MAAMZ,OAAOa,MAAM;YACrB;QACF;QACA,IAAItC,SAASuC,gCAAkB,CAACC,GAAG,CAACxC,MAAMyC,IAAI,GAAG;YAC/C,MAAM,IAAIvC,qBAAa,CAAC,gCAAgCC,kBAAU,CAACuC,qBAAqB;QAC1F;QACA,OAAO;IACT;IAEA,MAAcV,YAAY5C,KAAa,EAAEqC,MAAc,EAAkC;QACvF,MAAMkB,eAAe,IAAI,CAACC,eAAe,CAACxD,OAAO,IAAI,CAACwB,UAAU,CAACiC,MAAM;QACvE,IAAI;YACF,MAAM,EAAEC,aAAa,EAAE,GAAG,MAAMrB,OAAOsB,MAAM,CAAC,IAAI,CAACnC,UAAU,CAACY,MAAM,EAAE;gBACpEjC,OAAO;gBACPsD,QAAQF;gBACR9B,YAAYmC,6BAAmB;YACjC;YAEA,IAAIF,cAAcZ,MAAM,KAAK,GAAG;gBAC9B,IAAI,CAACnC,MAAM,CAACkD,KAAK,CAAC,GAAG,IAAI,CAACjB,WAAW,CAAC/B,IAAI,CAAC,mBAAmB,EAAE0C,cAAc;gBAC9E,IAAI,CAAC5C,MAAM,CAACqC,IAAI,CAAC,GAAG,IAAI,CAACJ,WAAW,CAAC/B,IAAI,CAAC,6BAA6B,EAAEb,OAAO;gBAChF,OAAO;YACT;YAEA,IAAI0D,cAAcZ,MAAM,GAAG,GAAG;gBAC5B,IAAI,CAACnC,MAAM,CAACqC,IAAI,CAAC,GAAG,IAAI,CAACJ,WAAW,CAAC/B,IAAI,CAAC,qCAAqC,EAAEb,MAAM,iBAAiB,CAAC;YAC3G;YAEA,sCAAsC;YACtC,OAAO,IAAI,CAAC8D,sBAAsB,CAACJ,aAAa,CAAC,EAAE;QACrD,EAAE,OAAOnC,GAAG;YACV,IAAI,CAACZ,MAAM,CAACkD,KAAK,CAAC,GAAG,IAAI,CAACjB,WAAW,CAAC/B,IAAI,CAAC,mBAAmB,EAAE0C,cAAc;YAC9E,IAAI,CAAC5C,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAACgC,WAAW,CAAC/B,IAAI,CAAC,GAAG,EAAEb,MAAM,GAAG,EAAEuB,GAAG;YAC9D,OAAO;QACT;IACF;IAEA,MAAcQ,mBAAmBF,QAAuB,EAAEzB,IAAe,EAAsB;QAC7F,IAAIA,SAAS,MAAM;YACjB,SAAS;YACT,MAAM2D,cAAc,MAAM,IAAI,CAACC,iBAAiB,CAACC,iBAAiB,CAACpC,UAAUA,SAASqC,IAAI;YAC1F,MAAMC,YAAY,MAAM,IAAI,CAAC9D,YAAY,CAAC+D,UAAU,CAACL,YAAYM,EAAE;YACnE,IAAI,CAACF,WAAW;gBACd,IAAI,CAACxD,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAACmB,kBAAkB,CAAClB,IAAI,CAAC,wBAAwB,EAAEkD,YAAY/D,KAAK,CAAC,EAAE,EAAE+D,YAAYM,EAAE,CAAC,CAAC,CAAC;gBACnH,MAAM,IAAIvD,qBAAa,CAAC,kBAAkBC,kBAAU,CAACuD,SAAS;YAChE;YACA,OAAOH;QACT;QACA,IAAItC,SAAS7B,KAAK,KAAKI,KAAKJ,KAAK,EAAE;YACjC,IAAI,CAACW,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAACmB,kBAAkB,CAAClB,IAAI,CAAC,yBAAyB,EAAEgB,SAAS7B,KAAK,CAAC,KAAK,EAAEI,KAAKJ,KAAK,EAAE;YAC/G,MAAM,IAAIc,qBAAa,CAAC,0BAA0BC,kBAAU,CAACC,SAAS;QACxE;QACA,gDAAgD;QAChD,MAAMuD,qBAAoCC,OAAOC,WAAW,CAC1D,AACE,CAAA,MAAMC,QAAQC,GAAG,CACfH,OAAOI,IAAI,CAAC/C,UAAUgD,GAAG,CAAC,OAAOC;YAC/B,IAAIA,QAAQ,YAAY;gBACtB,MAAMC,SAAS,MAAMC,IAAAA,0BAAe,EAACnD,QAAQ,CAACiD,IAAI,EAAE1E,KAAKH,QAAQ;gBACjE,OAAO8E,SAAS,OAAO;oBAACD;oBAAKjD,QAAQ,CAACiD,IAAI;iBAAC;YAC7C;YACA,OAAOjD,QAAQ,CAACiD,IAAI,KAAK1E,IAAI,CAAC0E,IAAI,GAAG;gBAACA;gBAAKjD,QAAQ,CAACiD,IAAI;aAAC,GAAG;QAC9D,GACF,EACArB,MAAM,CAACwB;QAEX,IAAIT,OAAOI,IAAI,CAACL,oBAAoBzB,MAAM,GAAG,GAAG;YAC9C,IAAI;gBACF,IAAIyB,oBAAoBL,QAAQ,MAAM;oBACpC,IAAI9D,KAAK8D,IAAI,KAAKgB,eAAS,CAACC,aAAa,IAAI,CAAC,IAAI,CAAC3D,UAAU,CAAC4D,UAAU,EAAE;wBACxE,6EAA6E;wBAC7E,OAAOb,mBAAmBL,IAAI;oBAChC;gBACF;gBACA,yBAAyB;gBACzB,MAAM,IAAI,CAACF,iBAAiB,CAACqB,iBAAiB,CAACjF,KAAKiE,EAAE,EAAEE;gBACxD,cAAc;gBACd,IAAIA,oBAAoBtE,UAAU;oBAChC,OAAOsE,mBAAmBtE,QAAQ;gBACpC;gBACAuE,OAAOc,MAAM,CAAClF,MAAMmE;gBACpB,IAAI,cAAcA,sBAAsB,eAAeA,oBAAoB;oBACzE,kDAAkD;oBAClDnE,KAAKmF,WAAW,CAAC;gBACnB;YACF,EAAE,OAAOhE,GAAG;gBACV,IAAI,CAACZ,MAAM,CAACqC,IAAI,CAAC,GAAG,IAAI,CAACjB,kBAAkB,CAAClB,IAAI,CAAC,0BAA0B,EAAET,KAAKJ,KAAK,CAAC,IAAI,EAAEuB,GAAG;YACnG;QACF;QACA,OAAOnB;IACT;IAEQ0D,uBAAuB7C,KAAY,EAAiB;QAC1D,KAAK,MAAMuE,QAAQ5B,6BAAmB,CAAE;YACtC,IAAI4B,SAASC,0BAAgB,CAACC,SAAS,IAAIzE,KAAK,CAACuE,KAAK,EAAE;gBACtDvE,KAAK,CAACuE,KAAK,GAAG,AAACG,CAAAA,MAAMC,OAAO,CAAC3E,KAAK,CAACuE,KAAK,IAAIvE,KAAK,CAACuE,KAAK,GAAGvE,KAAK,CAACuE,KAAK,GAAG;oBAACvE,KAAK,CAACuE,KAAK;iBAAC,GAAG,EAAE,AAAD,EACtF/B,MAAM,CAAC,CAACoC,IAAW,OAAOA,MAAM,UAChChB,GAAG,CAAC,CAACgB,IAAMA,EAAEC,KAAK,CAAC,sBAAsB,CAAC,EAAE,EAAEC,QAC9CtC,MAAM,CAACwB;gBACV;YACF;YACA,IAAIU,MAAMC,OAAO,CAAC3E,KAAK,CAACuE,KAAK,GAAG;gBAC9B,mEAAmE;gBACnEvE,KAAK,CAACuE,KAAK,GAAGvE,KAAK,CAACuE,KAAK,CAAC1C,MAAM,GAAG,IAAI7B,KAAK,CAACuE,KAAK,CAAC,EAAE,GAAG;YAC1D;QACF;QACA,OAAOvE;IACT;IAEQa,eAAeb,KAAoB,EAAEhB,QAAgB,EAAiB;QAC5E,MAAM+F,UACJ,OAAO,IAAI,CAACxE,UAAU,CAAC4D,UAAU,KAAK,YACtC,IAAI,CAAC5D,UAAU,CAAC4D,UAAU,IAC1BnE,KAAK,CAACwE,0BAAgB,CAACC,SAAS,CAAC,EAAEO,SAAS,IAAI,CAACzE,UAAU,CAAC4D,UAAU;QACxE,OAAO;YACLpF,OAAO,IAAI,CAACO,OAAO,CAACU,KAAK,CAAC,IAAI,CAACO,UAAU,CAACC,UAAU,CAACzB,KAAK,CAAC;YAC3D0B,OAAOT,KAAK,CAAC,IAAI,CAACO,UAAU,CAACC,UAAU,CAACC,KAAK,CAAC;YAC9CzB,UAAUA;YACViE,MAAM8B,UAAUd,eAAS,CAACC,aAAa,GAAGD,eAAS,CAACgB,IAAI;YACxD,GAAG,IAAI,CAACC,uBAAuB,CAAClF,MAAM;QACxC;IACF;IAEQkF,wBAAwBlF,KAAoB,EAA2C;QAC7F,kCAAkC;QAClC,IAAIA,MAAMmF,EAAE,IAAInF,MAAMoF,SAAS,EAAE;YAC/B,OAAO;gBAAEC,WAAWrF,MAAMoF,SAAS;gBAAEE,UAAUtF,MAAMmF,EAAE;YAAC;QAC1D;QACA,0CAA0C;QAC1C,IAAInF,MAAMuF,WAAW,IAAIvF,MAAMuF,WAAW,CAACT,IAAI,IAAI;YACjD,OAAOU,IAAAA,wBAAa,EAACxF,MAAMuF,WAAW;QACxC;QACA,oBAAoB;QACpB,IAAIvF,MAAMyF,EAAE,IAAIzF,MAAMyF,EAAE,CAACX,IAAI,IAAI;YAC/B,OAAOU,IAAAA,wBAAa,EAACxF,MAAMyF,EAAE;QAC/B;QACA,oBAAoB;QACpB,OAAO;YAAEJ,WAAW;YAAIC,UAAU;QAAG;IACvC;IAEQhG,QAAQP,KAAa,EAAU;QACrC,IAAIA,MAAMiG,QAAQ,CAAC,OAAO;YACxB,OAAOjG,MAAM2G,KAAK,CAAC,MAAMC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE;QACvC;QACA,OAAO5G;IACT;IAEQiC,eAAejC,KAAa,EAAU;QAC5C,IAAI,IAAI,CAACwB,UAAU,CAACC,UAAU,CAACzB,KAAK,KAAK6G,yBAAe,CAACC,GAAG,EAAE;YAC5D,IAAI,IAAI,CAACtF,UAAU,CAACuF,SAAS,IAAI,CAAC/G,MAAMiG,QAAQ,CAAC,MAAM;gBACrD,OAAO,GAAGjG,MAAM,CAAC,EAAE,IAAI,CAACwB,UAAU,CAACuF,SAAS,EAAE;YAChD;QACF,OAAO,IAAI,IAAI,CAACvF,UAAU,CAACC,UAAU,CAACzB,KAAK,KAAK6G,yBAAe,CAACG,GAAG,EAAE;YACnE,IAAI,IAAI,CAACxF,UAAU,CAACyF,WAAW,IAAI,CAACjH,MAAMiG,QAAQ,CAAC,OAAO;gBACxD,OAAO,GAAG,IAAI,CAACzE,UAAU,CAACyF,WAAW,CAAC,EAAE,EAAEjH,OAAO;YACnD;QACF;QACA,OAAOA;IACT;IAEQwD,gBAAgBxD,KAAa,EAAEkH,WAAoB,EAAU;QACnE,iDAAiD;QACjD,0EAA0E;QAC1E,6EAA6E;QAC7E,uJAAuJ;QAEvJ,wGAAwG;QACxG,gFAAgF;QAChF,MAAM3G,UAAU,IAAI,CAACA,OAAO,CAACP;QAE7B,MAAMmH,KAAK,IAAIC,gBAAQ,CAAC;YACtBC,SAAS,IAAI,CAAClF,IAAI,GACd;gBACE,IAAImF,sBAAc,CAAC;oBAAEC,WAAWV,yBAAe,CAACG,GAAG;oBAAEQ,OAAOjH;gBAAQ;gBACpE,IAAI+G,sBAAc,CAAC;oBAAEC,WAAWV,yBAAe,CAACC,GAAG;oBAAEU,OAAOjH;gBAAQ;gBACpE,IAAI+G,sBAAc,CAAC;oBAAEC,WAAWV,yBAAe,CAACY,IAAI;oBAAED,OAAOjH;gBAAQ;aACtE,GACD;gBACE,IAAI+G,sBAAc,CAAC;oBAAEC,WAAWV,yBAAe,CAACa,GAAG;oBAAEF,OAAOjH;gBAAQ;gBACpE,IAAI+G,sBAAc,CAAC;oBAAEC,WAAWV,yBAAe,CAACc,EAAE;oBAAEH,OAAOjH;gBAAQ;gBACnE,IAAI+G,sBAAc,CAAC;oBAAEC,WAAWV,yBAAe,CAACY,IAAI;oBAAED,OAAOjH;gBAAQ;aACtE;QACP;QAEA,gCAAgC;QAChC,IAAIqH,eAAe,IAAIC,iBAAS,CAAC;YAAER,SAAS;gBAACF;aAAG;QAAC,GAAGW,QAAQ;QAE5D,iEAAiE;QACjE,IAAIZ,eAAeA,YAAYnB,IAAI,IAAI;YACrC6B,eAAe,CAAC,EAAE,EAAEA,eAAeV,YAAY,CAAC,CAAC;QACnD;QACA,OAAOU;IACT;IAzQA,YACE,AAAiBvH,YAA0B,EAC3C,AAAiB2D,iBAAoC,CACrD;aAFiB3D,eAAAA;aACA2D,oBAAAA;aAPFrD,SAAS,IAAIoH,cAAM,CAACjI,sBAAsBe,IAAI;aAC9CW,aAAawG,gCAAa,CAACC,IAAI,CAACC,IAAI;aACpC/F,OAAO,IAAI,CAACX,UAAU,CAACC,UAAU,CAACzB,KAAK,KAAK6G,yBAAe,CAACG,GAAG,IAAI,IAAI,CAACxF,UAAU,CAACC,UAAU,CAACzB,KAAK,KAAK6G,yBAAe,CAACC,GAAG;aACpIrE,gBAA+B;YAAE0F,SAAS;YAAMC,gBAAgB;YAAM1F,KAAK;QAAG;IAKnF;AAuQL"}
@@ -52,9 +52,6 @@ _export(exports, {
52
52
  get hashPassword () {
53
53
  return hashPassword;
54
54
  },
55
- get intersectPermissions () {
56
- return intersectPermissions;
57
- },
58
55
  get loadOptionalModule () {
59
56
  return loadOptionalModule;
60
57
  },
@@ -240,11 +237,6 @@ function uniquePermissions(permissions, permissionsSeparator = _spaces.SPACE_PER
240
237
  ...new Set(permissions.split(permissionsSeparator).filter((p)=>p && p !== 'null').sort())
241
238
  ].join(permissionsSeparator);
242
239
  }
243
- function intersectPermissions(aPermissions, bPermissions, permissionsSeparator = _spaces.SPACE_PERMS_SEP) {
244
- const aPerms = aPermissions.split(permissionsSeparator);
245
- const bPerms = bPermissions.split(permissionsSeparator);
246
- return aPerms.filter((p)=>p !== '' && p !== 'null' && bPerms.indexOf(p) > -1).sort().join(permissionsSeparator);
247
- }
248
240
  function differencePermissions(aPermissions, bPermissions, permissionsSeparator = _spaces.SPACE_PERMS_SEP) {
249
241
  const aPerms = aPermissions.split(permissionsSeparator);
250
242
  const bPerms = bPermissions.split(permissionsSeparator);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../backend/src/common/functions.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { parse as parseMs } from '@lukeed/ms'\nimport bcrypt from 'bcryptjs'\nimport { ClassTransformOptions, plainToInstance } from 'class-transformer'\nimport { validateSync } from 'class-validator'\nimport { ValidationError } from 'class-validator/types/validation/ValidationError'\nimport { ValidatorOptions } from 'class-validator/types/validation/ValidatorOptions'\nimport crypto from 'node:crypto'\nimport { setTimeout } from 'node:timers/promises'\nimport { SPACE_PERMS_SEP } from '../applications/spaces/constants/spaces'\n\nexport const regexpEscape = /[.*+?^${}()|[\\]\\\\]/g\nexport const regexSpecialChars = /[-[\\]{}()*+!<=:?./\\\\^$|#,]/g\nexport const regexSpecialCharsWithSpace = /[-[\\]{}()*+!<=:?./\\\\^$|#\\s,]/g\n\nexport async function loadOptionalModule(moduleName: string): Promise<any> {\n return await import(moduleName)\n}\n\nexport async function sleep(ms: number): Promise<void> {\n await setTimeout(ms)\n}\n\nexport function escapeSQLRegexp(input: string): string {\n return input.replace(regexSpecialCharsWithSpace, '\\\\\\\\$&').replaceAll(\"'\", \"''\")\n}\n\nexport function escapeString(input: string): string {\n return input.replace(regexSpecialChars, '\\\\$&')\n}\n\nexport function escapePath(path: string): string {\n return path.replace(regexpEscape, '\\\\$&')\n}\n\nexport function regExpPathPattern(path: string): RegExp {\n return new RegExp(`^${escapePath(path)}[/\\\\\\\\]`)\n}\n\nexport function convertHumanTimeToSeconds(value: string): number {\n return parseMs(value) / 1000\n}\n\nexport function convertHumanTimeToMs(value: string): number {\n return parseMs(value)\n}\n\nexport function formatDateISOString(date: Date): string {\n return date.toISOString().replaceAll('-', '.').replaceAll(':', '-').replace('T', ' ').replace('Z', '')\n}\n\nexport function urlToPath(url: string): string {\n // transform https://sync-in.com/webdav/ to /webdav/\n try {\n // transform https://sync-in.com/webdav/ to /webdav/\n return new URL(url).pathname\n } catch {\n // or allows uri like : /webdav/\n return url\n }\n}\n\nexport async function hashPassword(password: string): Promise<string> {\n return await bcrypt.hash(password, 10)\n}\n\nexport async function comparePassword(password: string, hash: string): Promise<boolean> {\n return await bcrypt.compare(password, hash)\n}\n\nexport function generateShortUUID(length: number = 32, encoding: BufferEncoding = 'base64url'): string {\n const bytes = Math.ceil((length * 3) / 4) // adapt to real length\n return crypto.randomBytes(bytes).toString(encoding)\n}\n\nexport function anonymizePassword(obj: { password?: string; secrets?: string }) {\n return { ...obj, ...(obj?.password && { password: '********' }), ...(obj?.secrets && { secrets: '********' }) }\n}\n\nexport function splitFullName(fullName?: string): { firstName: string; lastName: string } {\n if (!fullName || !fullName.trim()) return { firstName: '', lastName: '' }\n const parts = fullName.trim().split(/\\s+/)\n if (parts.length === 1) {\n return { firstName: '', lastName: parts[0] }\n }\n const lastName = parts.pop()!\n const firstName = parts.join(' ')\n return { firstName, lastName }\n}\n\nexport function transformAndValidate<T extends object>(\n schema: new () => T,\n object: any,\n transformOptions: ClassTransformOptions = {},\n validatorOptions: ValidatorOptions = {}\n): T {\n // warning: plainToInstance do not use constructor to instantiate class\n const instance: T = plainToInstance(schema, object, transformOptions)\n const errors: ValidationError[] = validateSync(instance, validatorOptions)\n if (errors.length > 0) {\n throw new Error(errors.toString())\n }\n return instance\n}\n\nexport function uniquePermissions(permissions: string, permissionsSeparator: string = SPACE_PERMS_SEP) {\n /*\n Returns unique permissions : 'c:r:w:c:r' -> 'c:r:w'\n */\n if (permissions.length === 0) return permissions\n return [\n ...new Set(\n permissions\n .split(permissionsSeparator)\n .filter((p: string) => p && p !== 'null')\n .sort()\n )\n ].join(permissionsSeparator)\n}\n\nexport function intersectPermissions(aPermissions: string, bPermissions: string, permissionsSeparator: string = SPACE_PERMS_SEP): string {\n const aPerms = aPermissions.split(permissionsSeparator)\n const bPerms = bPermissions.split(permissionsSeparator)\n return aPerms\n .filter((p: string) => p !== '' && p !== 'null' && bPerms.indexOf(p) > -1)\n .sort()\n .join(permissionsSeparator)\n}\n\nexport function differencePermissions(aPermissions: string, bPermissions: string, permissionsSeparator: string = SPACE_PERMS_SEP): string[] {\n const aPerms = aPermissions.split(permissionsSeparator)\n const bPerms = bPermissions.split(permissionsSeparator)\n return aPerms.filter((p: string) => p !== '' && bPerms.indexOf(p) === -1).sort()\n}\n\nexport function sortObjByName(a: { name: string }, b: { name: string }, asc = false): 0 | 1 | -1 {\n const aN = a.name.toLowerCase()\n const bN = b.name.toLowerCase()\n if (asc) {\n return aN < bN ? 1 : aN > bN ? -1 : 0\n } else {\n return aN < bN ? -1 : aN > bN ? 1 : 0\n }\n}\n\nfunction diffProperties(a: any, b: any, props: string[]): boolean {\n for (const p of props) {\n if (a[p] !== b[p]) {\n return false\n }\n }\n return true\n}\n\nexport function diffCollection<T>(\n curCollection: T[],\n newCollection: T[],\n updateProps: string[],\n compareProps: string[] = ['id']\n): [T[], Record<string | 'object', { old: any; new: any } | T>[], T[]] {\n const toAdd: T[] = []\n const toUpdate: Record<string | 'object', { old: any; new: any } | T>[] = []\n const toRemove: T[] = curCollection.filter((c: T) => !newCollection.find((n: T) => diffProperties(c, n, compareProps)))\n for (const n of newCollection) {\n const o = curCollection.find((c: T) => diffProperties(c, n, compareProps))\n if (o) {\n const diff: Record<string | 'object', { old: any; new: any } | T> = {}\n for (const p of updateProps.filter((p: string) => n[p] !== o[p])) {\n diff[p] = { old: o[p], new: n[p] }\n }\n if (Object.keys(diff).length) {\n diff['object'] = n\n toUpdate.push(diff)\n }\n } else {\n toAdd.push(n)\n }\n }\n return [toAdd, toUpdate, toRemove]\n}\n\nexport function convertDiffUpdate(update: Record<string | 'object', { old: any; new: any } | any>[]): Record<string | 'object', any>[] {\n // only keep the new values\n return update.map((o) => Object.fromEntries(Object.entries(o).map(([p, v]) => [p, p === 'object' ? v : v.new])))\n}\n"],"names":["anonymizePassword","comparePassword","convertDiffUpdate","convertHumanTimeToMs","convertHumanTimeToSeconds","diffCollection","differencePermissions","escapePath","escapeSQLRegexp","escapeString","formatDateISOString","generateShortUUID","hashPassword","intersectPermissions","loadOptionalModule","regExpPathPattern","regexSpecialChars","regexSpecialCharsWithSpace","regexpEscape","sleep","sortObjByName","splitFullName","transformAndValidate","uniquePermissions","urlToPath","moduleName","ms","setTimeout","input","replace","replaceAll","path","RegExp","value","parseMs","date","toISOString","url","URL","pathname","password","bcrypt","hash","compare","length","encoding","bytes","Math","ceil","crypto","randomBytes","toString","obj","secrets","fullName","trim","firstName","lastName","parts","split","pop","join","schema","object","transformOptions","validatorOptions","instance","plainToInstance","errors","validateSync","Error","permissions","permissionsSeparator","SPACE_PERMS_SEP","Set","filter","p","sort","aPermissions","bPermissions","aPerms","bPerms","indexOf","a","b","asc","aN","name","toLowerCase","bN","diffProperties","props","curCollection","newCollection","updateProps","compareProps","toAdd","toUpdate","toRemove","c","find","n","o","diff","old","new","Object","keys","push","update","map","fromEntries","entries","v"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../backend/src/common/functions.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { parse as parseMs } from '@lukeed/ms'\nimport bcrypt from 'bcryptjs'\nimport { ClassTransformOptions, plainToInstance } from 'class-transformer'\nimport { validateSync } from 'class-validator'\nimport { ValidationError } from 'class-validator/types/validation/ValidationError'\nimport { ValidatorOptions } from 'class-validator/types/validation/ValidatorOptions'\nimport crypto from 'node:crypto'\nimport { setTimeout } from 'node:timers/promises'\nimport { SPACE_PERMS_SEP } from '../applications/spaces/constants/spaces'\n\nexport const regexpEscape = /[.*+?^${}()|[\\]\\\\]/g\nexport const regexSpecialChars = /[-[\\]{}()*+!<=:?./\\\\^$|#,]/g\nexport const regexSpecialCharsWithSpace = /[-[\\]{}()*+!<=:?./\\\\^$|#\\s,]/g\n\nexport async function loadOptionalModule(moduleName: string): Promise<any> {\n return await import(moduleName)\n}\n\nexport async function sleep(ms: number): Promise<void> {\n await setTimeout(ms)\n}\n\nexport function escapeSQLRegexp(input: string): string {\n return input.replace(regexSpecialCharsWithSpace, '\\\\\\\\$&').replaceAll(\"'\", \"''\")\n}\n\nexport function escapeString(input: string): string {\n return input.replace(regexSpecialChars, '\\\\$&')\n}\n\nexport function escapePath(path: string): string {\n return path.replace(regexpEscape, '\\\\$&')\n}\n\nexport function regExpPathPattern(path: string): RegExp {\n return new RegExp(`^${escapePath(path)}[/\\\\\\\\]`)\n}\n\nexport function convertHumanTimeToSeconds(value: string): number {\n return parseMs(value) / 1000\n}\n\nexport function convertHumanTimeToMs(value: string): number {\n return parseMs(value)\n}\n\nexport function formatDateISOString(date: Date): string {\n return date.toISOString().replaceAll('-', '.').replaceAll(':', '-').replace('T', ' ').replace('Z', '')\n}\n\nexport function urlToPath(url: string): string {\n // transform https://sync-in.com/webdav/ to /webdav/\n try {\n // transform https://sync-in.com/webdav/ to /webdav/\n return new URL(url).pathname\n } catch {\n // or allows uri like : /webdav/\n return url\n }\n}\n\nexport async function hashPassword(password: string): Promise<string> {\n return await bcrypt.hash(password, 10)\n}\n\nexport async function comparePassword(password: string, hash: string): Promise<boolean> {\n return await bcrypt.compare(password, hash)\n}\n\nexport function generateShortUUID(length: number = 32, encoding: BufferEncoding = 'base64url'): string {\n const bytes = Math.ceil((length * 3) / 4) // adapt to real length\n return crypto.randomBytes(bytes).toString(encoding)\n}\n\nexport function anonymizePassword(obj: { password?: string; secrets?: string }) {\n return { ...obj, ...(obj?.password && { password: '********' }), ...(obj?.secrets && { secrets: '********' }) }\n}\n\nexport function splitFullName(fullName?: string): { firstName: string; lastName: string } {\n if (!fullName || !fullName.trim()) return { firstName: '', lastName: '' }\n const parts = fullName.trim().split(/\\s+/)\n if (parts.length === 1) {\n return { firstName: '', lastName: parts[0] }\n }\n const lastName = parts.pop()!\n const firstName = parts.join(' ')\n return { firstName, lastName }\n}\n\nexport function transformAndValidate<T extends object>(\n schema: new () => T,\n object: any,\n transformOptions: ClassTransformOptions = {},\n validatorOptions: ValidatorOptions = {}\n): T {\n // warning: plainToInstance do not use constructor to instantiate class\n const instance: T = plainToInstance(schema, object, transformOptions)\n const errors: ValidationError[] = validateSync(instance, validatorOptions)\n if (errors.length > 0) {\n throw new Error(errors.toString())\n }\n return instance\n}\n\nexport function uniquePermissions(permissions: string, permissionsSeparator: string = SPACE_PERMS_SEP) {\n /*\n Returns unique permissions : 'c:r:w:c:r' -> 'c:r:w'\n */\n if (permissions.length === 0) return permissions\n return [\n ...new Set(\n permissions\n .split(permissionsSeparator)\n .filter((p: string) => p && p !== 'null')\n .sort()\n )\n ].join(permissionsSeparator)\n}\n\nexport function differencePermissions(aPermissions: string, bPermissions: string, permissionsSeparator: string = SPACE_PERMS_SEP): string[] {\n const aPerms = aPermissions.split(permissionsSeparator)\n const bPerms = bPermissions.split(permissionsSeparator)\n return aPerms.filter((p: string) => p !== '' && bPerms.indexOf(p) === -1).sort()\n}\n\nexport function sortObjByName(a: { name: string }, b: { name: string }, asc = false): 0 | 1 | -1 {\n const aN = a.name.toLowerCase()\n const bN = b.name.toLowerCase()\n if (asc) {\n return aN < bN ? 1 : aN > bN ? -1 : 0\n } else {\n return aN < bN ? -1 : aN > bN ? 1 : 0\n }\n}\n\nfunction diffProperties(a: any, b: any, props: string[]): boolean {\n for (const p of props) {\n if (a[p] !== b[p]) {\n return false\n }\n }\n return true\n}\n\nexport function diffCollection<T>(\n curCollection: T[],\n newCollection: T[],\n updateProps: string[],\n compareProps: string[] = ['id']\n): [T[], Record<string | 'object', { old: any; new: any } | T>[], T[]] {\n const toAdd: T[] = []\n const toUpdate: Record<string | 'object', { old: any; new: any } | T>[] = []\n const toRemove: T[] = curCollection.filter((c: T) => !newCollection.find((n: T) => diffProperties(c, n, compareProps)))\n for (const n of newCollection) {\n const o = curCollection.find((c: T) => diffProperties(c, n, compareProps))\n if (o) {\n const diff: Record<string | 'object', { old: any; new: any } | T> = {}\n for (const p of updateProps.filter((p: string) => n[p] !== o[p])) {\n diff[p] = { old: o[p], new: n[p] }\n }\n if (Object.keys(diff).length) {\n diff['object'] = n\n toUpdate.push(diff)\n }\n } else {\n toAdd.push(n)\n }\n }\n return [toAdd, toUpdate, toRemove]\n}\n\nexport function convertDiffUpdate(update: Record<string | 'object', { old: any; new: any } | any>[]): Record<string | 'object', any>[] {\n // only keep the new values\n return update.map((o) => Object.fromEntries(Object.entries(o).map(([p, v]) => [p, p === 'object' ? v : v.new])))\n}\n"],"names":["anonymizePassword","comparePassword","convertDiffUpdate","convertHumanTimeToMs","convertHumanTimeToSeconds","diffCollection","differencePermissions","escapePath","escapeSQLRegexp","escapeString","formatDateISOString","generateShortUUID","hashPassword","loadOptionalModule","regExpPathPattern","regexSpecialChars","regexSpecialCharsWithSpace","regexpEscape","sleep","sortObjByName","splitFullName","transformAndValidate","uniquePermissions","urlToPath","moduleName","ms","setTimeout","input","replace","replaceAll","path","RegExp","value","parseMs","date","toISOString","url","URL","pathname","password","bcrypt","hash","compare","length","encoding","bytes","Math","ceil","crypto","randomBytes","toString","obj","secrets","fullName","trim","firstName","lastName","parts","split","pop","join","schema","object","transformOptions","validatorOptions","instance","plainToInstance","errors","validateSync","Error","permissions","permissionsSeparator","SPACE_PERMS_SEP","Set","filter","p","sort","aPermissions","bPermissions","aPerms","bPerms","indexOf","a","b","asc","aN","name","toLowerCase","bN","diffProperties","props","curCollection","newCollection","updateProps","compareProps","toAdd","toUpdate","toRemove","c","find","n","o","diff","old","new","Object","keys","push","update","map","fromEntries","entries","v"],"mappings":"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"}
@@ -56,6 +56,7 @@ const loadTextToSVG = (0, _nodeutil.promisify)(_texttosvg.default.load.bind(_tex
56
56
  let textToSvgCache = null;
57
57
  async function generateThumbnail(filePath, size) {
58
58
  return (0, _sharp.default)(filePath, {
59
+ failOn: 'none',
59
60
  sequentialRead: true,
60
61
  limitInputPixels: 268e6 // protects against extremely large images
61
62
  }).rotate().resize({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../backend/src/common/image.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport fs from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { Readable } from 'node:stream'\nimport { promisify } from 'node:util'\nimport sharp from 'sharp'\nimport TextToSVG from 'text-to-svg' // Sharp settings\n\n// Sharp settings\nsharp.cache(false)\nsharp.concurrency(Math.min(2, os.cpus()?.length || 1))\n\n// Constants\nexport const pngMimeType = 'image/png'\nexport const svgMimeType = 'image/svg+xml'\nexport const webpMimeType = 'image/webp'\nconst avatarSize = 256\nconst fontPath = path.join(__dirname, 'fonts', 'avatar.ttf')\nconst loadTextToSVG = promisify(TextToSVG.load.bind(TextToSVG))\nlet textToSvgCache: Promise<TextToSVG> | null = null\n\nexport async function generateThumbnail(filePath: string, size: number): Promise<Readable> {\n return sharp(filePath, {\n sequentialRead: true, // sequential read = more efficient I/O\n limitInputPixels: 268e6 // protects against extremely large images\n })\n .rotate()\n .resize({\n width: size,\n height: size,\n fit: 'inside',\n kernel: 'nearest',\n withoutEnlargement: true,\n fastShrinkOnLoad: true // true by default, added for clarity\n })\n .webp({ quality: 80, effort: 0, alphaQuality: 90 })\n}\n\nexport async function generateAvatar(initials: string): Promise<NodeJS.ReadableStream> {\n const tts = await getTextToSvg()\n const { backgroundColor, foregroundColor } = randomColor()\n const fontSize = fitFontSize(tts, initials, avatarSize * 0.8, 170)\n\n const d = tts.getD(initials, {\n x: avatarSize / 2,\n y: avatarSize / 2.1,\n fontSize,\n anchor: 'center middle'\n })\n\n const svg = `\n<svg width=\"${avatarSize}\" height=\"${avatarSize}\" viewBox=\"0 0 ${avatarSize} ${avatarSize}\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"100%\" height=\"100%\" fill=\"${backgroundColor}\"/>\n <path d=\"${d}\" fill=\"${foregroundColor}\" />\n</svg>`.trim()\n\n return sharp(Buffer.from(svg, 'utf8')).png()\n}\n\nexport async function convertImageToBase64(imgPath: string) {\n const base64String = await fs.readFile(imgPath, { encoding: 'base64' })\n return `data:image/png;base64,${base64String}`\n}\n\nfunction randomColor() {\n let color = ''\n while (color.length < 6) {\n /* sometimes the returned value does not have\n * the 6 digits needed, so we do it again until\n * it does\n */\n color = Math.floor(Math.random() * 16777215).toString(16)\n }\n const red = parseInt(color.substring(0, 2), 16)\n const green = parseInt(color.substring(2, 4), 16)\n const blue = parseInt(color.substring(4, 6), 16)\n const brightness = red * 0.299 + green * 0.587 + blue * 0.114\n\n return {\n backgroundColor: `#${color}`,\n foregroundColor: brightness > 180 ? '#000000' : '#ffffff'\n }\n}\n\nfunction fitFontSize(tts: TextToSVG, text: string, box: number, start = 170): number {\n // Heuristic to make the text occupy ~80% of the available width\n let size = start\n // Lower bound to prevent infinite loops when the font renders very small\n while (size > 20) {\n const m = tts.getMetrics(text, { fontSize: size, anchor: 'center middle' })\n if (m.width <= box) break\n size -= 4\n }\n return size\n}\n\nfunction getTextToSvg(): Promise<TextToSVG> {\n return (textToSvgCache ??= loadTextToSVG(fontPath) as Promise<TextToSVG>)\n}\n"],"names":["convertImageToBase64","generateAvatar","generateThumbnail","pngMimeType","svgMimeType","webpMimeType","sharp","cache","concurrency","Math","min","os","cpus","length","avatarSize","fontPath","path","join","__dirname","loadTextToSVG","promisify","TextToSVG","load","bind","textToSvgCache","filePath","size","sequentialRead","limitInputPixels","rotate","resize","width","height","fit","kernel","withoutEnlargement","fastShrinkOnLoad","webp","quality","effort","alphaQuality","initials","tts","getTextToSvg","backgroundColor","foregroundColor","randomColor","fontSize","fitFontSize","d","getD","x","y","anchor","svg","trim","Buffer","from","png","imgPath","base64String","fs","readFile","encoding","color","floor","random","toString","red","parseInt","substring","green","blue","brightness","text","box","start","m","getMetrics"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../backend/src/common/image.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport fs from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { Readable } from 'node:stream'\nimport { promisify } from 'node:util'\nimport sharp from 'sharp'\nimport TextToSVG from 'text-to-svg' // Sharp settings\n\n// Sharp settings\nsharp.cache(false)\nsharp.concurrency(Math.min(2, os.cpus()?.length || 1))\n\n// Constants\nexport const pngMimeType = 'image/png'\nexport const svgMimeType = 'image/svg+xml'\nexport const webpMimeType = 'image/webp'\nconst avatarSize = 256\nconst fontPath = path.join(__dirname, 'fonts', 'avatar.ttf')\nconst loadTextToSVG = promisify(TextToSVG.load.bind(TextToSVG))\nlet textToSvgCache: Promise<TextToSVG> | null = null\n\nexport async function generateThumbnail(filePath: string, size: number): Promise<Readable> {\n return sharp(filePath, {\n failOn: 'none',\n sequentialRead: true, // sequential read = more efficient I/O\n limitInputPixels: 268e6 // protects against extremely large images\n })\n .rotate()\n .resize({\n width: size,\n height: size,\n fit: 'inside',\n kernel: 'nearest',\n withoutEnlargement: true,\n fastShrinkOnLoad: true // true by default, added for clarity\n })\n .webp({ quality: 80, effort: 0, alphaQuality: 90 })\n}\n\nexport async function generateAvatar(initials: string): Promise<NodeJS.ReadableStream> {\n const tts = await getTextToSvg()\n const { backgroundColor, foregroundColor } = randomColor()\n const fontSize = fitFontSize(tts, initials, avatarSize * 0.8, 170)\n\n const d = tts.getD(initials, {\n x: avatarSize / 2,\n y: avatarSize / 2.1,\n fontSize,\n anchor: 'center middle'\n })\n\n const svg = `\n<svg width=\"${avatarSize}\" height=\"${avatarSize}\" viewBox=\"0 0 ${avatarSize} ${avatarSize}\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"100%\" height=\"100%\" fill=\"${backgroundColor}\"/>\n <path d=\"${d}\" fill=\"${foregroundColor}\" />\n</svg>`.trim()\n\n return sharp(Buffer.from(svg, 'utf8')).png()\n}\n\nexport async function convertImageToBase64(imgPath: string) {\n const base64String = await fs.readFile(imgPath, { encoding: 'base64' })\n return `data:image/png;base64,${base64String}`\n}\n\nfunction randomColor() {\n let color = ''\n while (color.length < 6) {\n /* sometimes the returned value does not have\n * the 6 digits needed, so we do it again until\n * it does\n */\n color = Math.floor(Math.random() * 16777215).toString(16)\n }\n const red = parseInt(color.substring(0, 2), 16)\n const green = parseInt(color.substring(2, 4), 16)\n const blue = parseInt(color.substring(4, 6), 16)\n const brightness = red * 0.299 + green * 0.587 + blue * 0.114\n\n return {\n backgroundColor: `#${color}`,\n foregroundColor: brightness > 180 ? '#000000' : '#ffffff'\n }\n}\n\nfunction fitFontSize(tts: TextToSVG, text: string, box: number, start = 170): number {\n // Heuristic to make the text occupy ~80% of the available width\n let size = start\n // Lower bound to prevent infinite loops when the font renders very small\n while (size > 20) {\n const m = tts.getMetrics(text, { fontSize: size, anchor: 'center middle' })\n if (m.width <= box) break\n size -= 4\n }\n return size\n}\n\nfunction getTextToSvg(): Promise<TextToSVG> {\n return (textToSvgCache ??= loadTextToSVG(fontPath) as Promise<TextToSVG>)\n}\n"],"names":["convertImageToBase64","generateAvatar","generateThumbnail","pngMimeType","svgMimeType","webpMimeType","sharp","cache","concurrency","Math","min","os","cpus","length","avatarSize","fontPath","path","join","__dirname","loadTextToSVG","promisify","TextToSVG","load","bind","textToSvgCache","filePath","size","failOn","sequentialRead","limitInputPixels","rotate","resize","width","height","fit","kernel","withoutEnlargement","fastShrinkOnLoad","webp","quality","effort","alphaQuality","initials","tts","getTextToSvg","backgroundColor","foregroundColor","randomColor","fontSize","fitFontSize","d","getD","x","y","anchor","svg","trim","Buffer","from","png","imgPath","base64String","fs","readFile","encoding","color","floor","random","toString","red","parseInt","substring","green","blue","brightness","text","box","start","m","getMetrics"],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>
3
3
  * This file is part of Sync-in | The open source file sync and share solution
4
4
  * See the LICENSE file for licensing details
5
- */ "use strict";
5
+ */ /* THIS FILE IS SHARED WITH THE FRONTEND PACKAGE */ "use strict";
6
6
  Object.defineProperty(exports, "__esModule", {
7
7
  value: true
8
8
  });
@@ -13,6 +13,9 @@ function _export(target, all) {
13
13
  });
14
14
  }
15
15
  _export(exports, {
16
+ get APP_URL () {
17
+ return APP_URL;
18
+ },
16
19
  get SERVER_NAME () {
17
20
  return SERVER_NAME;
18
21
  },
@@ -43,6 +46,9 @@ _export(exports, {
43
46
  get genPassword () {
44
47
  return genPassword;
45
48
  },
49
+ get intersectPermissions () {
50
+ return intersectPermissions;
51
+ },
46
52
  get isValidFileName () {
47
53
  return isValidFileName;
48
54
  },
@@ -62,7 +68,13 @@ _export(exports, {
62
68
  return regExpPreventPathTraversal;
63
69
  }
64
70
  });
71
+ const _spaces = require("../applications/spaces/constants/spaces");
65
72
  const SERVER_NAME = 'Sync-in';
73
+ const APP_URL = {
74
+ WEBSITE: 'https://sync-in.com',
75
+ RELEASES: 'https://github.com/Sync-in/server/releases',
76
+ SERVER_VERSION_MANIFEST: 'https://releases.sync-in.org/sync-in-server/latest.json'
77
+ };
66
78
  const regExpInvalidFileName = /^(?:CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])$|[<>:"/\\|?*\x00-\x1f\x80-\x9f]/;
67
79
  const regExpPreventPathTraversal = /^(\.\.(\/|\\|$))+/;
68
80
  const regExpNumberSuffix = /-\d+$/;
@@ -122,5 +134,10 @@ function objectPropertyFromString(obj, property) {
122
134
  function capitalizeString(value) {
123
135
  return value.charAt(0).toUpperCase() + value.slice(1);
124
136
  }
137
+ function intersectPermissions(aPermissions, bPermissions, permissionsSeparator = _spaces.SPACE_PERMS_SEP) {
138
+ const aPerms = aPermissions.split(permissionsSeparator);
139
+ const bPerms = bPermissions.split(permissionsSeparator);
140
+ return aPerms.filter((p)=>p !== '' && p !== 'null' && bPerms.indexOf(p) > -1).sort().join(permissionsSeparator);
141
+ }
125
142
 
126
143
  //# sourceMappingURL=shared.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../backend/src/common/shared.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nexport const SERVER_NAME = 'Sync-in' as const\n\n// eslint-disable-next-line no-control-regex\nexport const regExpInvalidFileName = /^(?:CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])$|[<>:\"/\\\\|?*\\x00-\\x1f\\x80-\\x9f]/\nexport const regExpPreventPathTraversal = /^(\\.\\.(\\/|\\\\|$))+/\nexport const regExpNumberSuffix = /-\\d+$/\nexport const forbiddenChars = '\\\\ / : * ? \" < > |'\n\nexport function isValidFileName(fileName: string) {\n if (regExpInvalidFileName.test(fileName)) {\n throw new Error('Forbidden characters')\n }\n}\n\nexport function currentTimeStamp(date?: Date, ms = false): number {\n return Math.floor((date ? date : new Date()).getTime() / (ms ? 1 : 1000))\n}\n\nexport function currentDate(value?: string): Date {\n return new Date((value ? value : new Date().toISOString()).split('T')[0])\n}\n\nexport function createSlug(input: string, replaceCount = false): string {\n const r = input\n .toLowerCase()\n .trim()\n .replace(/[\\s_-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n if (replaceCount) return r.replace(regExpNumberSuffix, '')\n return r\n}\n\nexport function createLightSlug(input: string) {\n return input\n .toLowerCase()\n .trim()\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n}\n\nexport function genPassword(length = 12) {\n const chars = '0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*()ABCDEFGHIJKLMNOPQRSTUVWXYZ'\n let password = ''\n for (let i = 0; i <= length; i++) {\n const randomNumber = Math.floor(Math.random() * chars.length)\n password += chars.substring(randomNumber, randomNumber + 1)\n }\n return password\n}\n\nexport function popFromObject(key: string, object: any): any {\n const item = object[key]\n delete object[key]\n return item\n}\n\nexport function encodeUrl(url: string): string {\n return url\n .split('/')\n .map((e) => encodeURIComponent(e))\n .join('/')\n}\n\nexport function decodeUrl(url: string): string {\n return url\n .split('/')\n .map((e) => decodeURIComponent(e))\n .join('/')\n}\n\nexport function objectPropertyFromString(obj: any, property: string): any {\n const a = property.split('.')\n let o = obj\n for (let i = 0, n = a.length; i < n; i++) {\n const k = a[i]\n if (k in o) {\n o = o[k]\n } else {\n return null\n }\n }\n return o\n}\n\nexport function capitalizeString(value: string): string {\n return value.charAt(0).toUpperCase() + value.slice(1)\n}\n"],"names":["SERVER_NAME","capitalizeString","createLightSlug","createSlug","currentDate","currentTimeStamp","decodeUrl","encodeUrl","forbiddenChars","genPassword","isValidFileName","objectPropertyFromString","popFromObject","regExpInvalidFileName","regExpNumberSuffix","regExpPreventPathTraversal","fileName","test","Error","date","ms","Math","floor","Date","getTime","value","toISOString","split","input","replaceCount","r","toLowerCase","trim","replace","normalize","length","chars","password","i","randomNumber","random","substring","key","object","item","url","map","e","encodeURIComponent","join","decodeURIComponent","obj","property","a","o","n","k","charAt","toUpperCase","slice"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QAEYA;eAAAA;;QAsFGC;eAAAA;;QApDAC;eAAAA;;QAZAC;eAAAA;;QAJAC;eAAAA;;QAJAC;eAAAA;;QAmDAC;eAAAA;;QAPAC;eAAAA;;QApDHC;eAAAA;;QAoCGC;eAAAA;;QAlCAC;eAAAA;;QAgEAC;eAAAA;;QApBAC;eAAAA;;QAjDHC;eAAAA;;QAEAC;eAAAA;;QADAC;eAAAA;;;AAJN,MAAMf,cAAc;AAGpB,MAAMa,wBAAwB;AAC9B,MAAME,6BAA6B;AACnC,MAAMD,qBAAqB;AAC3B,MAAMN,iBAAiB;AAEvB,SAASE,gBAAgBM,QAAgB;IAC9C,IAAIH,sBAAsBI,IAAI,CAACD,WAAW;QACxC,MAAM,IAAIE,MAAM;IAClB;AACF;AAEO,SAASb,iBAAiBc,IAAW,EAAEC,KAAK,KAAK;IACtD,OAAOC,KAAKC,KAAK,CAAC,AAACH,CAAAA,OAAOA,OAAO,IAAII,MAAK,EAAGC,OAAO,KAAMJ,CAAAA,KAAK,IAAI,IAAG;AACxE;AAEO,SAAShB,YAAYqB,KAAc;IACxC,OAAO,IAAIF,KAAK,AAACE,CAAAA,QAAQA,QAAQ,IAAIF,OAAOG,WAAW,EAAC,EAAGC,KAAK,CAAC,IAAI,CAAC,EAAE;AAC1E;AAEO,SAASxB,WAAWyB,KAAa,EAAEC,eAAe,KAAK;IAC5D,MAAMC,IAAIF,MACPG,WAAW,GACXC,IAAI,GACJC,OAAO,CAAC,YAAY,KACpBA,OAAO,CAAC,YAAY,IACpBC,SAAS,CAAC,OACVD,OAAO,CAAC,oBAAoB;IAC/B,IAAIJ,cAAc,OAAOC,EAAEG,OAAO,CAACnB,oBAAoB;IACvD,OAAOgB;AACT;AAEO,SAAS5B,gBAAgB0B,KAAa;IAC3C,OAAOA,MACJG,WAAW,GACXC,IAAI,GACJE,SAAS,CAAC,OACVD,OAAO,CAAC,oBAAoB;AACjC;AAEO,SAASxB,YAAY0B,SAAS,EAAE;IACrC,MAAMC,QAAQ;IACd,IAAIC,WAAW;IACf,IAAK,IAAIC,IAAI,GAAGA,KAAKH,QAAQG,IAAK;QAChC,MAAMC,eAAelB,KAAKC,KAAK,CAACD,KAAKmB,MAAM,KAAKJ,MAAMD,MAAM;QAC5DE,YAAYD,MAAMK,SAAS,CAACF,cAAcA,eAAe;IAC3D;IACA,OAAOF;AACT;AAEO,SAASzB,cAAc8B,GAAW,EAAEC,MAAW;IACpD,MAAMC,OAAOD,MAAM,CAACD,IAAI;IACxB,OAAOC,MAAM,CAACD,IAAI;IAClB,OAAOE;AACT;AAEO,SAASrC,UAAUsC,GAAW;IACnC,OAAOA,IACJlB,KAAK,CAAC,KACNmB,GAAG,CAAC,CAACC,IAAMC,mBAAmBD,IAC9BE,IAAI,CAAC;AACV;AAEO,SAAS3C,UAAUuC,GAAW;IACnC,OAAOA,IACJlB,KAAK,CAAC,KACNmB,GAAG,CAAC,CAACC,IAAMG,mBAAmBH,IAC9BE,IAAI,CAAC;AACV;AAEO,SAAStC,yBAAyBwC,GAAQ,EAAEC,QAAgB;IACjE,MAAMC,IAAID,SAASzB,KAAK,CAAC;IACzB,IAAI2B,IAAIH;IACR,IAAK,IAAIb,IAAI,GAAGiB,IAAIF,EAAElB,MAAM,EAAEG,IAAIiB,GAAGjB,IAAK;QACxC,MAAMkB,IAAIH,CAAC,CAACf,EAAE;QACd,IAAIkB,KAAKF,GAAG;YACVA,IAAIA,CAAC,CAACE,EAAE;QACV,OAAO;YACL,OAAO;QACT;IACF;IACA,OAAOF;AACT;AAEO,SAASrD,iBAAiBwB,KAAa;IAC5C,OAAOA,MAAMgC,MAAM,CAAC,GAAGC,WAAW,KAAKjC,MAAMkC,KAAK,CAAC;AACrD"}
1
+ {"version":3,"sources":["../../../backend/src/common/shared.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\n/* THIS FILE IS SHARED WITH THE FRONTEND PACKAGE */\n\nimport { SPACE_PERMS_SEP } from '../applications/spaces/constants/spaces'\n\nexport const SERVER_NAME = 'Sync-in' as const\n\nexport const APP_URL = {\n WEBSITE: 'https://sync-in.com',\n RELEASES: 'https://github.com/Sync-in/server/releases',\n SERVER_VERSION_MANIFEST: 'https://releases.sync-in.org/sync-in-server/latest.json'\n} as const\n\n// eslint-disable-next-line no-control-regex\nexport const regExpInvalidFileName = /^(?:CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])$|[<>:\"/\\\\|?*\\x00-\\x1f\\x80-\\x9f]/\nexport const regExpPreventPathTraversal = /^(\\.\\.(\\/|\\\\|$))+/\nexport const regExpNumberSuffix = /-\\d+$/\nexport const forbiddenChars = '\\\\ / : * ? \" < > |'\n\nexport function isValidFileName(fileName: string) {\n if (regExpInvalidFileName.test(fileName)) {\n throw new Error('Forbidden characters')\n }\n}\n\nexport function currentTimeStamp(date?: Date, ms = false): number {\n return Math.floor((date ? date : new Date()).getTime() / (ms ? 1 : 1000))\n}\n\nexport function currentDate(value?: string): Date {\n return new Date((value ? value : new Date().toISOString()).split('T')[0])\n}\n\nexport function createSlug(input: string, replaceCount = false): string {\n const r = input\n .toLowerCase()\n .trim()\n .replace(/[\\s_-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n if (replaceCount) return r.replace(regExpNumberSuffix, '')\n return r\n}\n\nexport function createLightSlug(input: string) {\n return input\n .toLowerCase()\n .trim()\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n}\n\nexport function genPassword(length = 12) {\n const chars = '0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*()ABCDEFGHIJKLMNOPQRSTUVWXYZ'\n let password = ''\n for (let i = 0; i <= length; i++) {\n const randomNumber = Math.floor(Math.random() * chars.length)\n password += chars.substring(randomNumber, randomNumber + 1)\n }\n return password\n}\n\nexport function popFromObject(key: string, object: any): any {\n const item = object[key]\n delete object[key]\n return item\n}\n\nexport function encodeUrl(url: string): string {\n return url\n .split('/')\n .map((e) => encodeURIComponent(e))\n .join('/')\n}\n\nexport function decodeUrl(url: string): string {\n return url\n .split('/')\n .map((e) => decodeURIComponent(e))\n .join('/')\n}\n\nexport function objectPropertyFromString(obj: any, property: string): any {\n const a = property.split('.')\n let o = obj\n for (let i = 0, n = a.length; i < n; i++) {\n const k = a[i]\n if (k in o) {\n o = o[k]\n } else {\n return null\n }\n }\n return o\n}\n\nexport function capitalizeString(value: string): string {\n return value.charAt(0).toUpperCase() + value.slice(1)\n}\n\nexport function intersectPermissions(aPermissions: string, bPermissions: string, permissionsSeparator: string = SPACE_PERMS_SEP): string {\n const aPerms = aPermissions.split(permissionsSeparator)\n const bPerms = bPermissions.split(permissionsSeparator)\n return aPerms\n .filter((p: string) => p !== '' && p !== 'null' && bPerms.indexOf(p) > -1)\n .sort()\n .join(permissionsSeparator)\n}\n"],"names":["APP_URL","SERVER_NAME","capitalizeString","createLightSlug","createSlug","currentDate","currentTimeStamp","decodeUrl","encodeUrl","forbiddenChars","genPassword","intersectPermissions","isValidFileName","objectPropertyFromString","popFromObject","regExpInvalidFileName","regExpNumberSuffix","regExpPreventPathTraversal","WEBSITE","RELEASES","SERVER_VERSION_MANIFEST","fileName","test","Error","date","ms","Math","floor","Date","getTime","value","toISOString","split","input","replaceCount","r","toLowerCase","trim","replace","normalize","length","chars","password","i","randomNumber","random","substring","key","object","item","url","map","e","encodeURIComponent","join","decodeURIComponent","obj","property","a","o","n","k","charAt","toUpperCase","slice","aPermissions","bPermissions","permissionsSeparator","SPACE_PERMS_SEP","aPerms","bPerms","filter","p","indexOf","sort"],"mappings":"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"}
@@ -24,6 +24,9 @@ function _ts_metadata(k, v) {
24
24
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
25
25
  }
26
26
  let ContextManager = class ContextManager {
27
+ headerOriginUrl() {
28
+ return this.storage.getStore() ? this.storage.getStore().headerOriginUrl : undefined;
29
+ }
27
30
  get(key) {
28
31
  return this.storage.getStore() ? this.storage.getStore()[key] : undefined;
29
32
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/infrastructure/context/services/context-manager.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { Injectable } from '@nestjs/common'\nimport { AsyncLocalStorage } from 'node:async_hooks'\nimport type { Observable } from 'rxjs'\nimport { ContextStore } from '../interfaces/context-store.interface'\n\n@Injectable()\nexport class ContextManager {\n private readonly storage: AsyncLocalStorage<ContextStore>\n\n constructor() {\n this.storage = new AsyncLocalStorage<ContextStore>()\n }\n\n get(key: keyof ContextStore): any {\n return this.storage.getStore() ? this.storage.getStore()[key] : undefined\n }\n\n run(context: ContextStore, cb: () => unknown): Observable<unknown> {\n return this.storage.run(context, cb) as Observable<unknown>\n }\n}\n"],"names":["ContextManager","get","key","storage","getStore","undefined","run","context","cb","AsyncLocalStorage"],"mappings":"AAAA;;;;CAIC;;;;+BAQYA;;;eAAAA;;;wBANc;iCACO;;;;;;;;;;AAK3B,IAAA,AAAMA,iBAAN,MAAMA;IAOXC,IAAIC,GAAuB,EAAO;QAChC,OAAO,IAAI,CAACC,OAAO,CAACC,QAAQ,KAAK,IAAI,CAACD,OAAO,CAACC,QAAQ,EAAE,CAACF,IAAI,GAAGG;IAClE;IAEAC,IAAIC,OAAqB,EAAEC,EAAiB,EAAuB;QACjE,OAAO,IAAI,CAACL,OAAO,CAACG,GAAG,CAACC,SAASC;IACnC;IAVA,aAAc;QACZ,IAAI,CAACL,OAAO,GAAG,IAAIM,kCAAiB;IACtC;AASF"}
1
+ {"version":3,"sources":["../../../../../backend/src/infrastructure/context/services/context-manager.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { Injectable } from '@nestjs/common'\nimport { AsyncLocalStorage } from 'node:async_hooks'\nimport type { Observable } from 'rxjs'\nimport { ContextStore } from '../interfaces/context-store.interface'\n\n@Injectable()\nexport class ContextManager {\n private readonly storage: AsyncLocalStorage<ContextStore>\n\n constructor() {\n this.storage = new AsyncLocalStorage<ContextStore>()\n }\n\n headerOriginUrl(): string {\n return this.storage.getStore() ? this.storage.getStore().headerOriginUrl : undefined\n }\n\n get(key: keyof ContextStore): any {\n return this.storage.getStore() ? this.storage.getStore()[key] : undefined\n }\n\n run(context: ContextStore, cb: () => unknown): Observable<unknown> {\n return this.storage.run(context, cb) as Observable<unknown>\n }\n}\n"],"names":["ContextManager","headerOriginUrl","storage","getStore","undefined","get","key","run","context","cb","AsyncLocalStorage"],"mappings":"AAAA;;;;CAIC;;;;+BAQYA;;;eAAAA;;;wBANc;iCACO;;;;;;;;;;AAK3B,IAAA,AAAMA,iBAAN,MAAMA;IAOXC,kBAA0B;QACxB,OAAO,IAAI,CAACC,OAAO,CAACC,QAAQ,KAAK,IAAI,CAACD,OAAO,CAACC,QAAQ,GAAGF,eAAe,GAAGG;IAC7E;IAEAC,IAAIC,GAAuB,EAAO;QAChC,OAAO,IAAI,CAACJ,OAAO,CAACC,QAAQ,KAAK,IAAI,CAACD,OAAO,CAACC,QAAQ,EAAE,CAACG,IAAI,GAAGF;IAClE;IAEAG,IAAIC,OAAqB,EAAEC,EAAiB,EAAuB;QACjE,OAAO,IAAI,CAACP,OAAO,CAACK,GAAG,CAACC,SAASC;IACnC;IAdA,aAAc;QACZ,IAAI,CAACP,OAAO,GAAG,IAAIQ,kCAAiB;IACtC;AAaF"}
@@ -24,12 +24,12 @@ function _ts_decorate(decorators, target, key, desc) {
24
24
  let ClusterAdapter = class ClusterAdapter extends _platformsocketio.IoAdapter {
25
25
  createIOServer(port, options) {
26
26
  const server = super.createIOServer(port, options);
27
- server.adapter(this.clusterAdapter);
27
+ // Prevent the connection from closing too early when NestJS shutdown hooks are enabled, which can cause errors on exit
28
+ server.close = ()=>void 0;
29
+ const adapter = (0, _clusteradapter.createAdapter)();
30
+ server.adapter(adapter);
28
31
  return server;
29
32
  }
30
- constructor(...args){
31
- super(...args), this.clusterAdapter = (0, _clusteradapter.createAdapter)();
32
- }
33
33
  };
34
34
  ClusterAdapter = _ts_decorate([
35
35
  (0, _common.Injectable)()
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/infrastructure/websocket/adapters/cluster.adapter.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { Injectable } from '@nestjs/common'\nimport { IoAdapter } from '@nestjs/platform-socket.io'\nimport { createAdapter } from '@socket.io/cluster-adapter'\nimport { ServerOptions } from 'socket.io'\n\n@Injectable()\nexport class ClusterAdapter extends IoAdapter {\n private readonly clusterAdapter = createAdapter()\n\n createIOServer(port: number, options?: ServerOptions): any {\n const server = super.createIOServer(port, options)\n server.adapter(this.clusterAdapter)\n return server\n }\n}\n"],"names":["ClusterAdapter","IoAdapter","createIOServer","port","options","server","adapter","clusterAdapter","createAdapter"],"mappings":"AAAA;;;;CAIC;;;;+BAQYA;;;eAAAA;;;wBANc;kCACD;gCACI;;;;;;;AAIvB,IAAA,AAAMA,iBAAN,MAAMA,uBAAuBC,2BAAS;IAG3CC,eAAeC,IAAY,EAAEC,OAAuB,EAAO;QACzD,MAAMC,SAAS,KAAK,CAACH,eAAeC,MAAMC;QAC1CC,OAAOC,OAAO,CAAC,IAAI,CAACC,cAAc;QAClC,OAAOF;IACT;;QAPK,qBACYE,iBAAiBC,IAAAA,6BAAa;;AAOjD"}
1
+ {"version":3,"sources":["../../../../../backend/src/infrastructure/websocket/adapters/cluster.adapter.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { Injectable } from '@nestjs/common'\nimport { IoAdapter } from '@nestjs/platform-socket.io'\nimport { createAdapter } from '@socket.io/cluster-adapter'\nimport { ServerOptions } from 'socket.io'\n\n@Injectable()\nexport class ClusterAdapter extends IoAdapter {\n createIOServer(port: number, options?: ServerOptions): any {\n const server = super.createIOServer(port, options)\n // Prevent the connection from closing too early when NestJS shutdown hooks are enabled, which can cause errors on exit\n server.close = () => void 0\n const adapter: ReturnType<typeof createAdapter> = createAdapter()\n server.adapter(adapter)\n return server\n }\n}\n"],"names":["ClusterAdapter","IoAdapter","createIOServer","port","options","server","close","adapter","createAdapter"],"mappings":"AAAA;;;;CAIC;;;;+BAQYA;;;eAAAA;;;wBANc;kCACD;gCACI;;;;;;;AAIvB,IAAA,AAAMA,iBAAN,MAAMA,uBAAuBC,2BAAS;IAC3CC,eAAeC,IAAY,EAAEC,OAAuB,EAAO;QACzD,MAAMC,SAAS,KAAK,CAACH,eAAeC,MAAMC;QAC1C,uHAAuH;QACvHC,OAAOC,KAAK,GAAG,IAAM,KAAK;QAC1B,MAAMC,UAA4CC,IAAAA,6BAAa;QAC/DH,OAAOE,OAAO,CAACA;QACf,OAAOF;IACT;AACF"}