@sync-in/server 1.8.1 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (605) hide show
  1. package/CHANGELOG.md +57 -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.functions.js +42 -0
  7. package/server/app.functions.js.map +1 -0
  8. package/server/app.module.js +4 -0
  9. package/server/app.module.js.map +1 -1
  10. package/server/applications/admin/admin.module.js +6 -1
  11. package/server/applications/admin/admin.module.js.map +1 -1
  12. package/server/applications/{notifications/interfaces/user-mail-notification.js → admin/interfaces/check-update.interfaces.js} +1 -1
  13. package/server/applications/admin/interfaces/check-update.interfaces.js.map +1 -0
  14. package/server/applications/admin/services/admin-scheduler.service.js +53 -0
  15. package/server/applications/admin/services/admin-scheduler.service.js.map +1 -0
  16. package/server/applications/admin/services/admin.service.js +102 -0
  17. package/server/applications/admin/services/admin.service.js.map +1 -0
  18. package/server/applications/admin/services/admin.service.spec.js +46 -0
  19. package/server/applications/admin/services/admin.service.spec.js.map +1 -0
  20. package/server/applications/admin/utils/check-update.js +28 -0
  21. package/server/applications/admin/utils/check-update.js.map +1 -0
  22. package/server/applications/comments/services/comments-manager.service.js +1 -1
  23. package/server/applications/comments/services/comments-manager.service.js.map +1 -1
  24. package/server/applications/comments/services/comments-manager.service.spec.js +1 -1
  25. package/server/applications/comments/services/comments-manager.service.spec.js.map +1 -1
  26. package/server/applications/comments/services/comments-queries.service.js.map +1 -1
  27. package/server/applications/files/constants/cache.js +10 -1
  28. package/server/applications/files/constants/cache.js.map +1 -1
  29. package/server/applications/files/constants/only-office.js +0 -25
  30. package/server/applications/files/constants/only-office.js.map +1 -1
  31. package/server/applications/files/constants/operations.js +20 -3
  32. package/server/applications/files/constants/operations.js.map +1 -1
  33. package/server/applications/files/dto/file-operations.dto.js +7 -0
  34. package/server/applications/files/dto/file-operations.dto.js.map +1 -1
  35. package/server/applications/files/files-only-office.controller.js +3 -2
  36. package/server/applications/files/files-only-office.controller.js.map +1 -1
  37. package/server/applications/files/files-only-office.controller.spec.js +6 -5
  38. package/server/applications/files/files-only-office.controller.spec.js.map +1 -1
  39. package/server/applications/files/files.controller.js +88 -8
  40. package/server/applications/files/files.controller.js.map +1 -1
  41. package/server/applications/files/files.controller.spec.js +11 -4
  42. package/server/applications/files/files.controller.spec.js.map +1 -1
  43. package/server/applications/files/guards/files-only-office.guard.js +6 -0
  44. package/server/applications/files/guards/files-only-office.guard.js.map +1 -1
  45. package/server/applications/files/interfaces/file-db-props.interface.js.map +1 -1
  46. package/server/applications/files/interfaces/file-props.interface.js.map +1 -1
  47. package/server/applications/files/interfaces/only-office-config.interface.js.map +1 -1
  48. package/server/applications/files/services/files-content-manager.service.js +3 -3
  49. package/server/applications/files/services/files-content-manager.service.js.map +1 -1
  50. package/server/applications/files/services/files-lock-manager.service.js +61 -22
  51. package/server/applications/files/services/files-lock-manager.service.js.map +1 -1
  52. package/server/applications/files/services/files-manager.service.js +122 -24
  53. package/server/applications/files/services/files-manager.service.js.map +1 -1
  54. package/server/applications/files/services/files-manager.service.spec.js +15 -0
  55. package/server/applications/files/services/files-manager.service.spec.js.map +1 -1
  56. package/server/applications/files/services/files-methods.service.js +38 -8
  57. package/server/applications/files/services/files-methods.service.js.map +1 -1
  58. package/server/applications/files/services/files-only-office-manager.service.js +12 -12
  59. package/server/applications/files/services/files-only-office-manager.service.js.map +1 -1
  60. package/server/applications/files/services/files-parser.service.js +1 -1
  61. package/server/applications/files/services/files-parser.service.js.map +1 -1
  62. package/server/applications/files/services/files-queries.service.js +10 -0
  63. package/server/applications/files/services/files-queries.service.js.map +1 -1
  64. package/server/applications/files/utils/files.js +1 -1
  65. package/server/applications/files/utils/files.js.map +1 -1
  66. package/server/applications/files/utils/send-file.js +3 -2
  67. package/server/applications/files/utils/send-file.js.map +1 -1
  68. package/server/applications/links/services/links-queries.service.js +1 -1
  69. package/server/applications/links/services/links-queries.service.js.map +1 -1
  70. package/server/applications/notifications/constants/notifications.js +5 -1
  71. package/server/applications/notifications/constants/notifications.js.map +1 -1
  72. package/server/applications/notifications/i18n/de.js +8 -2
  73. package/server/applications/notifications/i18n/de.js.map +1 -1
  74. package/server/applications/notifications/i18n/es.js +8 -2
  75. package/server/applications/notifications/i18n/es.js.map +1 -1
  76. package/server/applications/notifications/i18n/fr.js +8 -2
  77. package/server/applications/notifications/i18n/fr.js.map +1 -1
  78. package/server/applications/notifications/i18n/hi.js +8 -2
  79. package/server/applications/notifications/i18n/hi.js.map +1 -1
  80. package/server/applications/notifications/i18n/it.js +8 -2
  81. package/server/applications/notifications/i18n/it.js.map +1 -1
  82. package/server/applications/notifications/i18n/ja.js +8 -2
  83. package/server/applications/notifications/i18n/ja.js.map +1 -1
  84. package/server/applications/notifications/i18n/ko.js +8 -2
  85. package/server/applications/notifications/i18n/ko.js.map +1 -1
  86. package/server/applications/notifications/i18n/pl.js +8 -2
  87. package/server/applications/notifications/i18n/pl.js.map +1 -1
  88. package/server/applications/notifications/i18n/pt.js +8 -2
  89. package/server/applications/notifications/i18n/pt.js.map +1 -1
  90. package/server/applications/notifications/i18n/pt_br.js +8 -2
  91. package/server/applications/notifications/i18n/pt_br.js.map +1 -1
  92. package/server/applications/notifications/i18n/ru.js +8 -2
  93. package/server/applications/notifications/i18n/ru.js.map +1 -1
  94. package/server/applications/notifications/i18n/tr.js +8 -2
  95. package/server/applications/notifications/i18n/tr.js.map +1 -1
  96. package/server/applications/notifications/i18n/zh.js +8 -2
  97. package/server/applications/notifications/i18n/zh.js.map +1 -1
  98. package/server/applications/notifications/interfaces/notification-properties.interface.js.map +1 -1
  99. package/server/applications/notifications/interfaces/user-mail-notification.interface.js +10 -0
  100. package/server/applications/notifications/interfaces/user-mail-notification.interface.js.map +1 -0
  101. package/server/applications/notifications/mails/models.js +38 -3
  102. package/server/applications/notifications/mails/models.js.map +1 -1
  103. package/server/applications/notifications/mails/templates.js +1 -1
  104. package/server/applications/notifications/mails/templates.js.map +1 -1
  105. package/server/applications/notifications/services/notifications-manager.service.js +8 -1
  106. package/server/applications/notifications/services/notifications-manager.service.js.map +1 -1
  107. package/server/applications/notifications/services/notifications-queries.service.js.map +1 -1
  108. package/server/applications/shares/services/shares-manager.service.js +17 -10
  109. package/server/applications/shares/services/shares-manager.service.js.map +1 -1
  110. package/server/applications/shares/services/shares-manager.service.spec.js +10 -3
  111. package/server/applications/shares/services/shares-manager.service.spec.js.map +1 -1
  112. package/server/applications/shares/services/shares-queries.service.js +11 -1
  113. package/server/applications/shares/services/shares-queries.service.js.map +1 -1
  114. package/server/applications/spaces/guards/space.guard.spec.js +2 -2
  115. package/server/applications/spaces/guards/space.guard.spec.js.map +1 -1
  116. package/server/applications/spaces/services/spaces-browser.service.js +31 -11
  117. package/server/applications/spaces/services/spaces-browser.service.js.map +1 -1
  118. package/server/applications/spaces/services/spaces-manager.service.js +2 -2
  119. package/server/applications/spaces/services/spaces-manager.service.js.map +1 -1
  120. package/server/applications/spaces/services/spaces-queries.service.js +6 -2
  121. package/server/applications/spaces/services/spaces-queries.service.js.map +1 -1
  122. package/server/applications/spaces/utils/permissions.js +2 -2
  123. package/server/applications/spaces/utils/permissions.js.map +1 -1
  124. package/server/applications/sync/services/sync-manager.service.js +1 -0
  125. package/server/applications/sync/services/sync-manager.service.js.map +1 -1
  126. package/server/applications/sync/services/sync-paths-manager.service.js +1 -1
  127. package/server/applications/sync/services/sync-paths-manager.service.js.map +1 -1
  128. package/server/applications/sync/services/sync-paths-manager.service.spec.js +1 -1
  129. package/server/applications/sync/services/sync-paths-manager.service.spec.js.map +1 -1
  130. package/server/applications/users/constants/user.js +1 -1
  131. package/server/applications/users/constants/user.js.map +1 -1
  132. package/server/applications/users/services/admin-users-queries.service.js +8 -0
  133. package/server/applications/users/services/admin-users-queries.service.js.map +1 -1
  134. package/server/applications/users/services/users-queries.service.js +67 -68
  135. package/server/applications/users/services/users-queries.service.js.map +1 -1
  136. package/server/applications/users/users.module.js +2 -1
  137. package/server/applications/users/users.module.js.map +1 -1
  138. package/server/applications/webdav/guards/webdav-protocol.guard.js +4 -4
  139. package/server/applications/webdav/guards/webdav-protocol.guard.js.map +1 -1
  140. package/server/applications/webdav/guards/webdav-protocol.guard.spec.js +6 -6
  141. package/server/applications/webdav/guards/webdav-protocol.guard.spec.js.map +1 -1
  142. package/server/applications/webdav/services/webdav-methods.service.js +3 -2
  143. package/server/applications/webdav/services/webdav-methods.service.js.map +1 -1
  144. package/server/applications/webdav/services/webdav-methods.service.spec.js +2 -2
  145. package/server/applications/webdav/services/webdav-methods.service.spec.js.map +1 -1
  146. package/server/authentication/constants/auth-ldap.js +2 -0
  147. package/server/authentication/constants/auth-ldap.js.map +1 -1
  148. package/server/authentication/services/auth-methods/auth-method-ldap.service.js +34 -21
  149. package/server/authentication/services/auth-methods/auth-method-ldap.service.js.map +1 -1
  150. package/server/common/functions.js +0 -8
  151. package/server/common/functions.js.map +1 -1
  152. package/server/common/image.js +1 -0
  153. package/server/common/image.js.map +1 -1
  154. package/server/common/shared.js +18 -1
  155. package/server/common/shared.js.map +1 -1
  156. package/server/infrastructure/context/services/context-manager.service.js +3 -0
  157. package/server/infrastructure/context/services/context-manager.service.js.map +1 -1
  158. package/server/infrastructure/websocket/adapters/cluster.adapter.js +4 -4
  159. package/server/infrastructure/websocket/adapters/cluster.adapter.js.map +1 -1
  160. package/static/3rdpartylicenses.txt +1393 -44
  161. package/static/assets/favicon.svg +2 -25
  162. package/static/assets/logo-dark.svg +2 -32
  163. package/static/assets/logo.svg +2 -32
  164. package/static/assets/mimes/application-sql.svg +29 -1
  165. package/static/assets/mimes/application-x-sql.svg +29 -0
  166. package/static/assets/mimes/image-bmp.svg +12 -0
  167. package/static/assets/pdfjs/build/pdf.mjs +4869 -4454
  168. package/static/assets/pdfjs/build/pdf.mjs.map +1 -1
  169. package/static/assets/pdfjs/build/pdf.sandbox.mjs +3 -3
  170. package/static/assets/pdfjs/build/pdf.sandbox.mjs.map +1 -1
  171. package/static/assets/pdfjs/build/pdf.worker.mjs +885 -596
  172. package/static/assets/pdfjs/build/pdf.worker.mjs.map +1 -1
  173. package/static/assets/pdfjs/version +1 -1
  174. package/static/assets/pdfjs/web/locale/be/viewer.ftl +40 -0
  175. package/static/assets/pdfjs/web/locale/bg/viewer.ftl +2 -0
  176. package/static/assets/pdfjs/web/locale/cs/viewer.ftl +41 -0
  177. package/static/assets/pdfjs/web/locale/cy/viewer.ftl +43 -0
  178. package/static/assets/pdfjs/web/locale/da/viewer.ftl +39 -0
  179. package/static/assets/pdfjs/web/locale/de/viewer.ftl +41 -0
  180. package/static/assets/pdfjs/web/locale/dsb/viewer.ftl +43 -0
  181. package/static/assets/pdfjs/web/locale/el/viewer.ftl +39 -0
  182. package/static/assets/pdfjs/web/locale/en-CA/viewer.ftl +35 -0
  183. package/static/assets/pdfjs/web/locale/en-GB/viewer.ftl +41 -0
  184. package/static/assets/pdfjs/web/locale/en-US/viewer.ftl +2 -2
  185. package/static/assets/pdfjs/web/locale/eo/viewer.ftl +39 -0
  186. package/static/assets/pdfjs/web/locale/es-AR/viewer.ftl +41 -0
  187. package/static/assets/pdfjs/web/locale/es-CL/viewer.ftl +39 -0
  188. package/static/assets/pdfjs/web/locale/es-ES/viewer.ftl +72 -0
  189. package/static/assets/pdfjs/web/locale/es-MX/viewer.ftl +120 -0
  190. package/static/assets/pdfjs/web/locale/eu/viewer.ftl +41 -0
  191. package/static/assets/pdfjs/web/locale/fi/viewer.ftl +41 -0
  192. package/static/assets/pdfjs/web/locale/fr/viewer.ftl +41 -0
  193. package/static/assets/pdfjs/web/locale/fur/viewer.ftl +77 -0
  194. package/static/assets/pdfjs/web/locale/fy-NL/viewer.ftl +41 -0
  195. package/static/assets/pdfjs/web/locale/gn/viewer.ftl +39 -0
  196. package/static/assets/pdfjs/web/locale/he/viewer.ftl +41 -0
  197. package/static/assets/pdfjs/web/locale/hsb/viewer.ftl +43 -0
  198. package/static/assets/pdfjs/web/locale/hu/viewer.ftl +41 -0
  199. package/static/assets/pdfjs/web/locale/hy-AM/viewer.ftl +1 -1
  200. package/static/assets/pdfjs/web/locale/ia/viewer.ftl +41 -0
  201. package/static/assets/pdfjs/web/locale/it/viewer.ftl +41 -0
  202. package/static/assets/pdfjs/web/locale/ja/viewer.ftl +32 -0
  203. package/static/assets/pdfjs/web/locale/ka/viewer.ftl +41 -0
  204. package/static/assets/pdfjs/web/locale/kab/viewer.ftl +73 -0
  205. package/static/assets/pdfjs/web/locale/kk/viewer.ftl +21 -0
  206. package/static/assets/pdfjs/web/locale/ko/viewer.ftl +38 -1
  207. package/static/assets/pdfjs/web/locale/nb-NO/viewer.ftl +39 -0
  208. package/static/assets/pdfjs/web/locale/nl/viewer.ftl +41 -0
  209. package/static/assets/pdfjs/web/locale/nn-NO/viewer.ftl +37 -0
  210. package/static/assets/pdfjs/web/locale/pa-IN/viewer.ftl +37 -0
  211. package/static/assets/pdfjs/web/locale/pl/viewer.ftl +39 -0
  212. package/static/assets/pdfjs/web/locale/pt-BR/viewer.ftl +39 -0
  213. package/static/assets/pdfjs/web/locale/rm/viewer.ftl +73 -0
  214. package/static/assets/pdfjs/web/locale/ro/viewer.ftl +41 -0
  215. package/static/assets/pdfjs/web/locale/ru/viewer.ftl +42 -0
  216. package/static/assets/pdfjs/web/locale/sc/viewer.ftl +6 -0
  217. package/static/assets/pdfjs/web/locale/sk/viewer.ftl +43 -0
  218. package/static/assets/pdfjs/web/locale/sl/viewer.ftl +42 -1
  219. package/static/assets/pdfjs/web/locale/sq/viewer.ftl +77 -0
  220. package/static/assets/pdfjs/web/locale/sv-SE/viewer.ftl +41 -0
  221. package/static/assets/pdfjs/web/locale/tg/viewer.ftl +39 -0
  222. package/static/assets/pdfjs/web/locale/th/viewer.ftl +35 -0
  223. package/static/assets/pdfjs/web/locale/tr/viewer.ftl +39 -0
  224. package/static/assets/pdfjs/web/locale/vi/viewer.ftl +42 -5
  225. package/static/assets/pdfjs/web/locale/zh-CN/viewer.ftl +35 -0
  226. package/static/assets/pdfjs/web/locale/zh-TW/viewer.ftl +37 -0
  227. package/static/assets/pdfjs/web/viewer.css +141 -110
  228. package/static/assets/pdfjs/web/viewer.html +7 -7
  229. package/static/assets/pdfjs/web/viewer.mjs +97 -14
  230. package/static/assets/pdfjs/web/viewer.mjs.map +1 -1
  231. package/static/chunk-22DWHRCL.js +1 -0
  232. package/static/chunk-23UUFZSR.js +1 -0
  233. package/static/chunk-25QTY2GI.js +1 -0
  234. package/static/chunk-2E7IJZLL.js +1 -0
  235. package/static/chunk-2FC5EKS5.js +1 -0
  236. package/static/chunk-2TB2INBF.js +1 -0
  237. package/static/chunk-32L7RG2G.js +1 -0
  238. package/static/chunk-3OHSTP3R.js +1 -0
  239. package/static/chunk-3WLBVJ2S.js +1 -0
  240. package/static/{chunk-MTVSJTIW.js → chunk-3YDYZLF7.js} +1 -1
  241. package/static/chunk-42L6C5MT.js +1 -0
  242. package/static/chunk-4AGQL5GV.js +1 -0
  243. package/static/chunk-4BPSQMI2.js +1 -0
  244. package/static/chunk-4FDRWZWT.js +1 -0
  245. package/static/chunk-4GCCF6PF.js +1 -0
  246. package/static/chunk-4ORP3SBY.js +1 -0
  247. package/static/chunk-4PZPHJ7L.js +1 -0
  248. package/static/chunk-4QBOHIC3.js +1 -0
  249. package/static/chunk-4YT6K5KY.js +1 -0
  250. package/static/chunk-556I6YIW.js +1 -0
  251. package/static/chunk-5DPIGJU4.js +1 -0
  252. package/static/chunk-5E3TYOL3.js +1 -0
  253. package/static/chunk-5IL7C45D.js +1 -0
  254. package/static/chunk-5KJXGMKR.js +1 -0
  255. package/static/chunk-5S6KPQRA.js +1 -0
  256. package/static/chunk-5SPGSHKL.js +1 -0
  257. package/static/chunk-5WCQBTXW.js +1 -0
  258. package/static/chunk-5XUIPWOH.js +1 -0
  259. package/static/chunk-62WT7PI3.js +1 -0
  260. package/static/chunk-6B3GGAV3.js +4 -0
  261. package/static/chunk-6F6OMQ5H.js +1 -0
  262. package/static/chunk-6I5BGQHT.js +1 -0
  263. package/static/chunk-6NEBGCAZ.js +1 -0
  264. package/static/chunk-6NOS45DG.js +1 -0
  265. package/static/chunk-6OKLPRCD.js +1 -0
  266. package/static/chunk-6VEJCG43.js +1 -0
  267. package/static/chunk-77SS36Z2.js +1 -0
  268. package/static/chunk-7AXEPO3G.js +1 -0
  269. package/static/chunk-7CKHC72R.js +1 -0
  270. package/static/chunk-7DUTYOJG.js +1 -0
  271. package/static/chunk-7HKFYRPF.js +1 -0
  272. package/static/chunk-7NZJZATZ.js +1 -0
  273. package/static/chunk-AADK5D2H.js +1 -0
  274. package/static/chunk-ACUF7IKP.js +1 -0
  275. package/static/chunk-AGREZPV4.js +1 -0
  276. package/static/chunk-ATBJWFA3.js +1 -0
  277. package/static/chunk-ATXLZN2B.js +1 -0
  278. package/static/chunk-AZ5TF5Y3.js +1 -0
  279. package/static/chunk-BBHYIURC.js +1 -0
  280. package/static/chunk-BHZEPHRI.js +13 -0
  281. package/static/chunk-BODMMLVB.js +7 -0
  282. package/static/chunk-BSB4VROD.js +2 -0
  283. package/static/chunk-BU4ZICZR.js +1 -0
  284. package/static/chunk-C3AAEQKW.js +1 -0
  285. package/static/chunk-CFTKW432.js +1 -0
  286. package/static/chunk-CNOVT6KU.js +1 -0
  287. package/static/chunk-D56H3XE2.js +1 -0
  288. package/static/chunk-DFOOSIIA.js +1 -0
  289. package/static/chunk-DHFQIFOF.js +1 -0
  290. package/static/{chunk-3GMLWAFZ.js → chunk-DIC2MVRI.js} +1 -1
  291. package/static/chunk-DJDRX53V.js +2 -0
  292. package/static/chunk-DKGXUMLT.js +1 -0
  293. package/static/chunk-DQ3GEMPM.js +1 -0
  294. package/static/chunk-DRHPEERW.js +2 -0
  295. package/static/chunk-DWYP6ZGG.js +1 -0
  296. package/static/chunk-EDJAISWO.js +13 -0
  297. package/static/chunk-EIYRBM4J.js +1 -0
  298. package/static/chunk-EL6QL4TP.js +1 -0
  299. package/static/chunk-ERDZ7IVF.js +1 -0
  300. package/static/chunk-EVQKKVUZ.js +1 -0
  301. package/static/chunk-F2XG7EWI.js +1 -0
  302. package/static/chunk-F672FY5I.js +1 -0
  303. package/static/chunk-F6V37MKG.js +1 -0
  304. package/static/chunk-FCGTI42I.js +1 -0
  305. package/static/chunk-FNOTGWRW.js +1 -0
  306. package/static/chunk-FQHOSSCO.js +1 -0
  307. package/static/chunk-GAGHHYLF.js +1 -0
  308. package/static/chunk-GNZPP2VO.js +1 -0
  309. package/static/{chunk-JPT5WEAT.js → chunk-GOJYWL2M.js} +1 -1
  310. package/static/chunk-GRLHFXGB.js +1 -0
  311. package/static/chunk-H6WOTGQ5.js +1 -0
  312. package/static/{chunk-CHJ64RJM.js → chunk-H6ZXFINQ.js} +1 -1
  313. package/static/chunk-HC7F57NA.js +1 -0
  314. package/static/chunk-HCSWO7BO.js +7 -0
  315. package/static/chunk-HHWXIK2M.js +7 -0
  316. package/static/chunk-HKRGIRKB.js +3 -0
  317. package/static/chunk-HMOB6XC5.js +1 -0
  318. package/static/chunk-HNMGPG72.js +1 -0
  319. package/static/chunk-HS4S6BV3.js +1 -0
  320. package/static/chunk-I2S3XPC5.js +3 -0
  321. package/static/chunk-IJ7K7ATQ.js +1 -0
  322. package/static/chunk-IOIBQGHN.js +562 -0
  323. package/static/chunk-ITVA26X2.js +2 -0
  324. package/static/chunk-J6YSFHLZ.js +1 -0
  325. package/static/chunk-JAEJ6IMV.js +1 -0
  326. package/static/chunk-JB5R6V33.js +1 -0
  327. package/static/chunk-JF6WIV6M.js +1 -0
  328. package/static/chunk-JGB4LLUT.js +1 -0
  329. package/static/chunk-JGXVTKLG.js +1 -0
  330. package/static/chunk-JMYAD7E2.js +1 -0
  331. package/static/chunk-JSE63Q5X.js +1 -0
  332. package/static/chunk-JVV3ZL6L.js +1 -0
  333. package/static/chunk-JWPXQOS3.js +5 -0
  334. package/static/chunk-JXZCNFW7.js +1 -0
  335. package/static/chunk-JY2I3HGL.js +1 -0
  336. package/static/chunk-K657XPXA.js +1 -0
  337. package/static/chunk-KAVP6UXH.js +1 -0
  338. package/static/{chunk-3R74L4UU.js → chunk-KDEEERWZ.js} +1 -1
  339. package/static/chunk-KLOUBIO4.js +1 -0
  340. package/static/chunk-KMF3ZRAO.js +1 -0
  341. package/static/chunk-KT3TWCST.js +1 -0
  342. package/static/chunk-L6SYG23T.js +1 -0
  343. package/static/{chunk-LNTUR3GU.js → chunk-LRDKG274.js} +1 -1
  344. package/static/chunk-LRQSPCYZ.js +1 -0
  345. package/static/chunk-LUSVISM6.js +1 -0
  346. package/static/{chunk-LVSNIS5P.js → chunk-LYZGJZNP.js} +1 -1
  347. package/static/chunk-LZKI5P5T.js +1 -0
  348. package/static/chunk-M4XL3JN5.js +6 -0
  349. package/static/{chunk-UNCPXHHT.js → chunk-MGWG7OD7.js} +1 -1
  350. package/static/chunk-MIA5YBOI.js +1 -0
  351. package/static/chunk-MKUUWY6Y.js +1 -0
  352. package/static/chunk-MR3U7TKQ.js +1 -0
  353. package/static/chunk-MYM43ENO.js +1 -0
  354. package/static/chunk-NAH4V2R6.js +2 -0
  355. package/static/chunk-NBBDVVUF.js +1 -0
  356. package/static/chunk-NKGKBQBX.js +1 -0
  357. package/static/chunk-NMF2ZFBE.js +1 -0
  358. package/static/chunk-NN4ONTOT.js +1 -0
  359. package/static/chunk-NOPACN4F.js +1 -0
  360. package/static/chunk-NYJPOP4L.js +1 -0
  361. package/static/chunk-OQRWXCLY.js +1 -0
  362. package/static/chunk-PCFH5HCI.js +2 -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-PXRT4L57.js +1 -0
  367. package/static/chunk-PZGLDZZM.js +1 -0
  368. package/static/chunk-Q4VNZGFI.js +1 -0
  369. package/static/chunk-Q556XB3S.js +1 -0
  370. package/static/{chunk-PB4AIT7O.js → chunk-Q7IXRPOO.js} +1 -1
  371. package/static/chunk-Q7U2VPIS.js +1 -0
  372. package/static/chunk-QM6CQMEX.js +1 -0
  373. package/static/chunk-QMHUIHSR.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-RDNTK4YH.js +1 -0
  380. package/static/{chunk-VJTXJ43D.js → chunk-RK2ONYTL.js} +1 -1
  381. package/static/chunk-RK7XRDNB.js +1 -0
  382. package/static/chunk-RO7SAOLK.js +1 -0
  383. package/static/chunk-RQUUINHV.js +1 -0
  384. package/static/chunk-RUN556VW.js +1 -0
  385. package/static/chunk-S2VBGI6Q.js +1 -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-TAL3RTTQ.js +1 -0
  393. package/static/chunk-TGLJFALR.js +1 -0
  394. package/static/chunk-TJZKTNNS.js +1 -0
  395. package/static/chunk-U4RW6XG5.js +1 -0
  396. package/static/chunk-UJTFWZEC.js +1 -0
  397. package/static/chunk-UPGVU5LG.js +1 -0
  398. package/static/chunk-UQ6O3I6W.js +1 -0
  399. package/static/{chunk-5NMSIIQB.js → chunk-V43RGNXA.js} +1 -1
  400. package/static/chunk-V6FA5QY4.js +1 -0
  401. package/static/chunk-VK7XMFVE.js +1 -0
  402. package/static/chunk-VQJYCYWI.js +1 -0
  403. package/static/chunk-VWIRXLNE.js +1 -0
  404. package/static/chunk-VZMVGIVW.js +1 -0
  405. package/static/chunk-VZPCXSRG.js +2 -0
  406. package/static/chunk-WR3MA3L3.js +1 -0
  407. package/static/chunk-XCLK7NJL.js +1 -0
  408. package/static/{chunk-DSWEWLXJ.js → chunk-XCPDPB5G.js} +1 -1
  409. package/static/chunk-XEGHEUP5.js +1 -0
  410. package/static/chunk-XKEBQNQJ.js +1 -0
  411. package/static/chunk-XOF4UW3S.js +1 -0
  412. package/static/chunk-XQGPSNQB.js +1 -0
  413. package/static/{chunk-QO6BTONN.js → chunk-Y4MAPE2C.js} +1 -1
  414. package/static/chunk-Y5RLD72B.js +1 -0
  415. package/static/{chunk-DPUVSXRB.js → chunk-Y5XTRCFK.js} +1 -1
  416. package/static/chunk-Y63UUJGJ.js +1 -0
  417. package/static/chunk-YBNAC7QM.js +1 -0
  418. package/static/chunk-YCTCESL4.js +1 -0
  419. package/static/chunk-YMAN4LIU.js +1 -0
  420. package/static/chunk-YTDE6SXT.js +1 -0
  421. package/static/chunk-YZPIUJB3.js +1 -0
  422. package/static/chunk-ZCOWBVOT.js +1 -0
  423. package/static/chunk-ZHRYYMYE.js +1 -0
  424. package/static/chunk-ZNXTOQFG.js +1 -0
  425. package/static/{chunk-URHTCJ7G.js → chunk-ZQLBPLXI.js} +1 -1
  426. package/static/chunk-ZXXHFBGL.js +1 -0
  427. package/static/favicon.ico +0 -0
  428. package/static/index.html +2 -2
  429. package/static/main-56PZQ6TJ.js +11 -0
  430. package/static/styles-Q4OZOSSK.css +1 -0
  431. package/server/applications/notifications/interfaces/user-mail-notification.js.map +0 -1
  432. package/static/assets/codemirror/mode/apl/apl.js +0 -174
  433. package/static/assets/codemirror/mode/asciiarmor/asciiarmor.js +0 -74
  434. package/static/assets/codemirror/mode/asn.1/asn.1.js +0 -204
  435. package/static/assets/codemirror/mode/asterisk/asterisk.js +0 -220
  436. package/static/assets/codemirror/mode/brainfuck/brainfuck.js +0 -85
  437. package/static/assets/codemirror/mode/clike/clike.js +0 -942
  438. package/static/assets/codemirror/mode/clojure/clojure.js +0 -293
  439. package/static/assets/codemirror/mode/cmake/cmake.js +0 -97
  440. package/static/assets/codemirror/mode/cobol/cobol.js +0 -255
  441. package/static/assets/codemirror/mode/coffeescript/coffeescript.js +0 -359
  442. package/static/assets/codemirror/mode/commonlisp/commonlisp.js +0 -125
  443. package/static/assets/codemirror/mode/crystal/crystal.js +0 -433
  444. package/static/assets/codemirror/mode/css/css.js +0 -862
  445. package/static/assets/codemirror/mode/cypher/cypher.js +0 -152
  446. package/static/assets/codemirror/mode/d/d.js +0 -223
  447. package/static/assets/codemirror/mode/dart/dart.js +0 -168
  448. package/static/assets/codemirror/mode/diff/diff.js +0 -47
  449. package/static/assets/codemirror/mode/django/django.js +0 -356
  450. package/static/assets/codemirror/mode/dockerfile/dockerfile.js +0 -211
  451. package/static/assets/codemirror/mode/dtd/dtd.js +0 -142
  452. package/static/assets/codemirror/mode/dylan/dylan.js +0 -352
  453. package/static/assets/codemirror/mode/ebnf/ebnf.js +0 -195
  454. package/static/assets/codemirror/mode/ecl/ecl.js +0 -206
  455. package/static/assets/codemirror/mode/eiffel/eiffel.js +0 -160
  456. package/static/assets/codemirror/mode/elm/elm.js +0 -245
  457. package/static/assets/codemirror/mode/erlang/erlang.js +0 -619
  458. package/static/assets/codemirror/mode/factor/factor.js +0 -85
  459. package/static/assets/codemirror/mode/fcl/fcl.js +0 -173
  460. package/static/assets/codemirror/mode/forth/forth.js +0 -180
  461. package/static/assets/codemirror/mode/fortran/fortran.js +0 -188
  462. package/static/assets/codemirror/mode/gas/gas.js +0 -355
  463. package/static/assets/codemirror/mode/gfm/gfm.js +0 -129
  464. package/static/assets/codemirror/mode/gherkin/gherkin.js +0 -194
  465. package/static/assets/codemirror/mode/go/go.js +0 -187
  466. package/static/assets/codemirror/mode/groovy/groovy.js +0 -245
  467. package/static/assets/codemirror/mode/haml/haml.js +0 -161
  468. package/static/assets/codemirror/mode/handlebars/handlebars.js +0 -70
  469. package/static/assets/codemirror/mode/haskell/haskell.js +0 -268
  470. package/static/assets/codemirror/mode/haskell-literate/haskell-literate.js +0 -43
  471. package/static/assets/codemirror/mode/haxe/haxe.js +0 -515
  472. package/static/assets/codemirror/mode/htmlembedded/htmlembedded.js +0 -37
  473. package/static/assets/codemirror/mode/htmlmixed/htmlmixed.js +0 -153
  474. package/static/assets/codemirror/mode/http/http.js +0 -113
  475. package/static/assets/codemirror/mode/idl/idl.js +0 -290
  476. package/static/assets/codemirror/mode/javascript/javascript.js +0 -960
  477. package/static/assets/codemirror/mode/jinja2/jinja2.js +0 -193
  478. package/static/assets/codemirror/mode/jsx/jsx.js +0 -149
  479. package/static/assets/codemirror/mode/julia/julia.js +0 -390
  480. package/static/assets/codemirror/mode/livescript/livescript.js +0 -280
  481. package/static/assets/codemirror/mode/lua/lua.js +0 -160
  482. package/static/assets/codemirror/mode/markdown/markdown.js +0 -886
  483. package/static/assets/codemirror/mode/mathematica/mathematica.js +0 -176
  484. package/static/assets/codemirror/mode/mbox/mbox.js +0 -129
  485. package/static/assets/codemirror/mode/meta.js +0 -221
  486. package/static/assets/codemirror/mode/mirc/mirc.js +0 -193
  487. package/static/assets/codemirror/mode/mllike/mllike.js +0 -359
  488. package/static/assets/codemirror/mode/modelica/modelica.js +0 -245
  489. package/static/assets/codemirror/mode/mscgen/mscgen.js +0 -175
  490. package/static/assets/codemirror/mode/mumps/mumps.js +0 -148
  491. package/static/assets/codemirror/mode/nginx/nginx.js +0 -178
  492. package/static/assets/codemirror/mode/nsis/nsis.js +0 -95
  493. package/static/assets/codemirror/mode/ntriples/ntriples.js +0 -195
  494. package/static/assets/codemirror/mode/octave/octave.js +0 -139
  495. package/static/assets/codemirror/mode/oz/oz.js +0 -252
  496. package/static/assets/codemirror/mode/pascal/pascal.js +0 -136
  497. package/static/assets/codemirror/mode/pegjs/pegjs.js +0 -111
  498. package/static/assets/codemirror/mode/perl/perl.js +0 -836
  499. package/static/assets/codemirror/mode/php/php.js +0 -234
  500. package/static/assets/codemirror/mode/pig/pig.js +0 -178
  501. package/static/assets/codemirror/mode/powershell/powershell.js +0 -398
  502. package/static/assets/codemirror/mode/properties/properties.js +0 -78
  503. package/static/assets/codemirror/mode/protobuf/protobuf.js +0 -72
  504. package/static/assets/codemirror/mode/pug/pug.js +0 -591
  505. package/static/assets/codemirror/mode/puppet/puppet.js +0 -220
  506. package/static/assets/codemirror/mode/python/python.js +0 -402
  507. package/static/assets/codemirror/mode/q/q.js +0 -139
  508. package/static/assets/codemirror/mode/r/r.js +0 -190
  509. package/static/assets/codemirror/mode/rpm/changes/index.html +0 -66
  510. package/static/assets/codemirror/mode/rpm/rpm.js +0 -109
  511. package/static/assets/codemirror/mode/rst/rst.js +0 -557
  512. package/static/assets/codemirror/mode/ruby/ruby.js +0 -303
  513. package/static/assets/codemirror/mode/rust/rust.js +0 -72
  514. package/static/assets/codemirror/mode/sas/sas.js +0 -303
  515. package/static/assets/codemirror/mode/sass/sass.js +0 -459
  516. package/static/assets/codemirror/mode/scheme/scheme.js +0 -284
  517. package/static/assets/codemirror/mode/shell/shell.js +0 -168
  518. package/static/assets/codemirror/mode/sieve/sieve.js +0 -193
  519. package/static/assets/codemirror/mode/slim/slim.js +0 -575
  520. package/static/assets/codemirror/mode/smalltalk/smalltalk.js +0 -168
  521. package/static/assets/codemirror/mode/smarty/smarty.js +0 -225
  522. package/static/assets/codemirror/mode/solr/solr.js +0 -104
  523. package/static/assets/codemirror/mode/soy/soy.js +0 -665
  524. package/static/assets/codemirror/mode/sparql/sparql.js +0 -184
  525. package/static/assets/codemirror/mode/spreadsheet/spreadsheet.js +0 -112
  526. package/static/assets/codemirror/mode/sql/sql.js +0 -529
  527. package/static/assets/codemirror/mode/stex/stex.js +0 -264
  528. package/static/assets/codemirror/mode/stylus/stylus.js +0 -775
  529. package/static/assets/codemirror/mode/swift/swift.js +0 -221
  530. package/static/assets/codemirror/mode/tcl/tcl.js +0 -140
  531. package/static/assets/codemirror/mode/textile/textile.js +0 -469
  532. package/static/assets/codemirror/mode/tiddlywiki/tiddlywiki.css +0 -14
  533. package/static/assets/codemirror/mode/tiddlywiki/tiddlywiki.js +0 -308
  534. package/static/assets/codemirror/mode/tiki/tiki.css +0 -26
  535. package/static/assets/codemirror/mode/tiki/tiki.js +0 -312
  536. package/static/assets/codemirror/mode/toml/toml.js +0 -88
  537. package/static/assets/codemirror/mode/tornado/tornado.js +0 -68
  538. package/static/assets/codemirror/mode/troff/troff.js +0 -84
  539. package/static/assets/codemirror/mode/ttcn/ttcn.js +0 -283
  540. package/static/assets/codemirror/mode/ttcn-cfg/ttcn-cfg.js +0 -214
  541. package/static/assets/codemirror/mode/turtle/turtle.js +0 -162
  542. package/static/assets/codemirror/mode/twig/twig.js +0 -141
  543. package/static/assets/codemirror/mode/vb/vb.js +0 -275
  544. package/static/assets/codemirror/mode/vbscript/vbscript.js +0 -350
  545. package/static/assets/codemirror/mode/velocity/velocity.js +0 -202
  546. package/static/assets/codemirror/mode/verilog/verilog.js +0 -781
  547. package/static/assets/codemirror/mode/vhdl/vhdl.js +0 -189
  548. package/static/assets/codemirror/mode/vue/vue.js +0 -77
  549. package/static/assets/codemirror/mode/wast/wast.js +0 -132
  550. package/static/assets/codemirror/mode/webidl/webidl.js +0 -195
  551. package/static/assets/codemirror/mode/xml/xml.js +0 -417
  552. package/static/assets/codemirror/mode/xquery/xquery.js +0 -448
  553. package/static/assets/codemirror/mode/yacas/yacas.js +0 -204
  554. package/static/assets/codemirror/mode/yaml/yaml.js +0 -120
  555. package/static/assets/codemirror/mode/yaml-frontmatter/yaml-frontmatter.js +0 -72
  556. package/static/assets/codemirror/mode/z80/z80.js +0 -116
  557. package/static/chunk-2KLC4T2Z.js +0 -1
  558. package/static/chunk-2VMSXRCB.js +0 -12
  559. package/static/chunk-3OHSRRKH.js +0 -4
  560. package/static/chunk-3R4WKOHQ.js +0 -1
  561. package/static/chunk-3XVM35O2.js +0 -1
  562. package/static/chunk-3YVRP3VM.js +0 -2
  563. package/static/chunk-5UKZLU5H.js +0 -1
  564. package/static/chunk-AF24EYXU.js +0 -1
  565. package/static/chunk-AKQVEHO6.js +0 -2
  566. package/static/chunk-BCVX464U.js +0 -2
  567. package/static/chunk-BQV4FRM6.js +0 -1
  568. package/static/chunk-CETH7UYS.js +0 -1
  569. package/static/chunk-DIT6W7VM.js +0 -562
  570. package/static/chunk-DKSEQTMX.js +0 -1
  571. package/static/chunk-FZ3JPGYZ.js +0 -1
  572. package/static/chunk-IQSKQXC3.js +0 -1
  573. package/static/chunk-ITUFI2BJ.js +0 -1
  574. package/static/chunk-LCTZJ537.js +0 -1
  575. package/static/chunk-LK2UCQJ6.js +0 -1
  576. package/static/chunk-LP5TBXEN.js +0 -7
  577. package/static/chunk-N3U6637P.js +0 -1
  578. package/static/chunk-NNV4OXSB.js +0 -1
  579. package/static/chunk-O6FYXVHI.js +0 -1
  580. package/static/chunk-OOGP4WSH.js +0 -2
  581. package/static/chunk-PCWDQPOM.js +0 -2
  582. package/static/chunk-PNR6M34W.js +0 -1
  583. package/static/chunk-Q5KM7LTX.js +0 -1
  584. package/static/chunk-QHC6ZPQ4.js +0 -1
  585. package/static/chunk-QMRBZHE4.js +0 -1
  586. package/static/chunk-QSJRY3TF.js +0 -1
  587. package/static/chunk-QUUIRSYT.js +0 -1
  588. package/static/chunk-RFH46UW3.js +0 -1
  589. package/static/chunk-RSXHRKM5.js +0 -1
  590. package/static/chunk-RV3VZJPZ.js +0 -1
  591. package/static/chunk-S7HNXVRB.js +0 -1
  592. package/static/chunk-SBZ572Q4.js +0 -2
  593. package/static/chunk-SJR5R3Y4.js +0 -1
  594. package/static/chunk-SLHTEGRU.js +0 -1
  595. package/static/chunk-SSFF27P2.js +0 -24
  596. package/static/chunk-V3LHHZYN.js +0 -1
  597. package/static/chunk-VQQKMY2C.js +0 -1
  598. package/static/chunk-WSSU2HXE.js +0 -1
  599. package/static/chunk-XDZGW64M.js +0 -3
  600. package/static/chunk-XTRDKGKG.js +0 -1
  601. package/static/chunk-YLWTEC3X.js +0 -1
  602. package/static/chunk-Z5J5F5SX.js +0 -1
  603. package/static/main-4H5BJY3J.js +0 -9
  604. package/static/scripts-WRDOQIU5.js +0 -24
  605. package/static/styles-2C2UNCNB.css +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/sync/services/sync-paths-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 { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'\nimport { ACTION } from '../../../common/constants'\nimport { currentTimeStamp } from '../../../common/shared'\nimport { ContextManager } from '../../../infrastructure/context/services/context-manager.service'\nimport type { FileProps } from '../../files/interfaces/file-props.interface'\nimport { FilesQueries } from '../../files/services/files-queries.service'\nimport { getProps, isPathExists, isPathIsDir } from '../../files/utils/files'\nimport { NOTIFICATION_APP, NOTIFICATION_APP_EVENT } from '../../notifications/constants/notifications'\nimport { NotificationContent } from '../../notifications/interfaces/notification-properties.interface'\nimport { NotificationsManager } from '../../notifications/services/notifications-manager.service'\nimport { FastifySpaceRequest } from '../../spaces/interfaces/space-request.interface'\nimport { SpaceEnv } from '../../spaces/models/space-env.model'\nimport { SpacesManager } from '../../spaces/services/spaces-manager.service'\nimport { getEnvPermissions } from '../../spaces/utils/permissions'\nimport { UserModel } from '../../users/models/user.model'\nimport { SYNC_PATH_REPOSITORY } from '../constants/sync'\nimport { SyncPathDto, SyncPathUpdateDto } from '../dtos/sync-path.dto'\nimport { SyncDBProps, SyncPathSettings } from '../interfaces/sync-path.interface'\nimport { SyncClient } from '../schemas/sync-client.interface'\nimport { SYNC_PATH_TO_SPACE_SEGMENTS } from '../utils/routes'\nimport { SyncQueries } from './sync-queries.service'\n\n@Injectable()\nexport class SyncPathsManager {\n private readonly logger = new Logger(SyncPathsManager.name)\n\n constructor(\n private readonly contextManager: ContextManager,\n private readonly spacesManager: SpacesManager,\n private readonly filesQueries: FilesQueries,\n private readonly syncQueries: SyncQueries,\n private readonly notificationsManager: NotificationsManager\n ) {}\n\n async createPath(req: FastifySpaceRequest, syncPathDto: SyncPathDto): Promise<{ id: number; permissions: string }> {\n if (!req.user.clientId) {\n throw new HttpException('Client id is missing', HttpStatus.BAD_REQUEST)\n }\n if (req.space.quotaIsExceeded) {\n throw new HttpException('Storage quota exceeded', HttpStatus.INSUFFICIENT_STORAGE)\n }\n if (!(await isPathExists(req.space.realPath))) {\n throw new HttpException(`Remote path not found : ${syncPathDto.remotePath}`, HttpStatus.NOT_FOUND)\n }\n if (!(await isPathIsDir(req.space.realPath))) {\n throw new HttpException('Remote path must be a directory', HttpStatus.BAD_REQUEST)\n }\n const client: SyncClient = await this.syncQueries.getClient(req.user.clientId, req.user.id)\n if (!client) {\n throw new HttpException('Client not found', HttpStatus.NOT_FOUND)\n }\n const syncDBProps: SyncDBProps = await this.getDBProps(req.space)\n\n // important : ensures the right remote path is used and stored\n syncPathDto.remotePath = req.params['*']\n // add permissions (skip end point protection using getEnvPermission)\n syncPathDto.permissions = getEnvPermissions(req.space, req.space.root)\n const pathId = await this.syncQueries.createPath(client.id, syncDBProps, syncPathDto)\n return { id: pathId, permissions: syncPathDto.permissions }\n }\n\n async deletePath(user: UserModel, pathId: number, clientId?: string): Promise<void> {\n clientId = user.clientId || clientId\n if (!clientId) {\n throw new HttpException('Client id is missing', HttpStatus.BAD_REQUEST)\n }\n if (!(await this.syncQueries.clientExistsForOwner(user.id, clientId))) {\n throw new HttpException('You are not allowed to do this action', HttpStatus.FORBIDDEN)\n }\n try {\n await this.syncQueries.deletePath(clientId, pathId)\n } catch (e) {\n this.logger.error(`${this.deletePath.name} - ${e}`)\n throw new HttpException('Unable to remove path', HttpStatus.BAD_REQUEST)\n }\n }\n\n async updatePath(user: UserModel, clientId: string, pathId: number, syncPathUpdateDto: SyncPathUpdateDto): Promise<SyncPathSettings> {\n if (!(await this.syncQueries.clientExistsForOwner(user.id, clientId))) {\n throw new HttpException('You are not allowed to do this action', HttpStatus.FORBIDDEN)\n }\n const syncPathSettings: SyncPathSettings = await this.syncQueries.getPathSettings(clientId, pathId)\n if (!syncPathSettings) {\n throw new HttpException('Sync path not found', HttpStatus.NOT_FOUND)\n }\n // delete possible id\n delete syncPathUpdateDto.id\n // update current path settings\n Object.assign(syncPathSettings, syncPathUpdateDto)\n syncPathSettings.timestamp = currentTimeStamp()\n try {\n await this.syncQueries.updatePathSettings(clientId, pathId, syncPathSettings)\n } catch (e) {\n this.logger.error(`${this.updatePath.name} - ${e}`)\n throw new HttpException('Unable to update path', HttpStatus.INTERNAL_SERVER_ERROR)\n } finally {\n // clear cache\n this.syncQueries.clearCachePathSettings(clientId, pathId)\n }\n return syncPathSettings\n }\n\n async updatePaths(\n user: UserModel,\n syncPathsDto: SyncPathDto[]\n ): Promise<{\n add: SyncPathSettings[]\n update: Partial<Record<keyof SyncPathSettings, any>>[]\n delete: number[]\n }> {\n /* Update the client or server paths */\n if (!user.clientId) {\n throw new HttpException('Client id is missing', HttpStatus.BAD_REQUEST)\n }\n if (!(await this.syncQueries.clientExistsForOwner(user.id, user.clientId))) {\n throw new HttpException('You are not allowed to do this action', HttpStatus.FORBIDDEN)\n }\n const clientPathIds: number[] = syncPathsDto.map((p) => p.id)\n const serverPathIds: number[] = []\n\n const clientDiff: { add: SyncPathSettings[]; update: Partial<Record<keyof SyncPathSettings, any>>[]; delete: number[] } = {\n add: [],\n update: [],\n delete: []\n }\n const serverPaths: { id: number; settings: SyncPathSettings; remotePath: string }[] = await this.syncQueries.getPaths(user.clientId)\n for (const serverPath of serverPaths) {\n if (!serverPath.remotePath) {\n // unable to determine path, will be stored as deleted\n continue\n }\n let space: SpaceEnv\n try {\n space = await this.spacesManager.spaceEnv(user, SYNC_PATH_TO_SPACE_SEGMENTS(serverPath.remotePath), true)\n } catch (e) {\n throw new HttpException(e.message, HttpStatus.BAD_REQUEST)\n }\n if (!space) {\n // removed or inaccessible space, the path will be stored as deleted\n continue\n }\n serverPathIds.push(serverPath.id)\n if (clientPathIds.indexOf(serverPath.id) === -1) {\n // path exists on server but not on client, add it to client\n clientDiff.add.push({ ...serverPath.settings, id: serverPath.id, remotePath: serverPath.remotePath, permissions: space.envPermissions })\n continue\n }\n\n // path exists on both server and client side\n const clientPath: SyncPathDto = syncPathsDto.find((p) => p.id === serverPath.id)\n // remotePath and permissions settings are only managed by server\n const updateClientInfo: { remotePath?: string; permissions?: string } = {\n ...(serverPath.remotePath !== clientPath.remotePath && { remotePath: serverPath.remotePath }),\n ...(space.envPermissions !== clientPath.permissions && { permissions: space.envPermissions })\n }\n const clientNewer = clientPath.timestamp > serverPath.settings.timestamp\n const serverNewer = clientPath.timestamp < serverPath.settings.timestamp\n const hasUpdates = Object.keys(updateClientInfo).length > 0\n\n let updatedSettings: SyncPathSettings = { ...serverPath.settings, ...updateClientInfo }\n\n if (clientNewer) {\n updatedSettings = { ...clientPath, ...updateClientInfo }\n } else if (serverNewer) {\n clientDiff.update.push({ id: clientPath.id, ...serverPath.settings, ...updateClientInfo })\n }\n\n if (clientNewer || hasUpdates || serverPath.settings.lastSync !== clientPath.lastSync) {\n this.syncQueries\n .updatePathSettings(user.clientId, clientPath.id, { ...updatedSettings, lastSync: clientPath.lastSync })\n .catch((e: Error) => this.logger.error(`${this.updatePaths.name} - ${e}`))\n }\n\n if (!clientNewer && hasUpdates) {\n clientDiff.update.push({ id: clientPath.id, ...updateClientInfo })\n }\n }\n // path does not exist on server side\n clientDiff.delete = clientPathIds.filter((cid) => serverPathIds.indexOf(cid) === -1)\n for (const cPathId of clientDiff.delete) {\n const cPath: SyncPathDto = syncPathsDto.find((p) => p.id === cPathId)\n this.notify(user.id, ACTION.DELETE, cPath.remotePath).catch((e: Error) => this.logger.error(`${this.updatePaths.name} - ${e}`))\n }\n // clear cache\n clientDiff.update.forEach((path) => this.syncQueries.clearCachePathSettings(user.clientId, path.id))\n return clientDiff\n }\n\n private async getDBProps(space: SpaceEnv): Promise<SyncDBProps> {\n if (space.inSharesList) {\n throw new HttpException('Sync all shares is not supported, you must select a sub-directory', HttpStatus.BAD_REQUEST)\n } else if (space.inPersonalSpace) {\n if (space.paths.length) {\n return { ownerId: space.dbFile.ownerId, fileId: await this.getOrCreateFileId(space) }\n } else {\n return { ownerId: space.dbFile.ownerId }\n }\n } else if (space.inFilesRepository) {\n if (!space?.root?.alias) {\n // The synchronization direction should be adapted for each root depending on the permissions, this is not yet supported\n throw new HttpException('Sync all space is not yet supported, you must select a sub-directory', HttpStatus.BAD_REQUEST)\n }\n if (space.root.id && !space.paths.length) {\n return { spaceId: space.id, spaceRootId: space.root.id }\n } else {\n return { spaceId: space.id, spaceRootId: space?.root?.id || null, fileId: await this.getOrCreateFileId(space) }\n }\n } else if (space.inSharesRepository) {\n if (space.paths.length) {\n return { shareId: space.id, fileId: await this.getOrCreateFileId(space) }\n } else {\n return { shareId: space.id }\n }\n }\n }\n\n private async getOrCreateFileId(space: SpaceEnv): Promise<number> {\n const fileProps: FileProps = await getProps(space.realPath, space.dbFile.path)\n let fileId: number = await this.filesQueries.getSpaceFileId(fileProps, space.dbFile)\n if (!fileId) {\n fileId = await this.filesQueries.getOrCreateSpaceFile(fileId, { ...fileProps, id: undefined }, space.dbFile)\n }\n return fileId\n }\n\n private async notify(userId: number, action: ACTION, remotePath: string) {\n const notification: NotificationContent = {\n app: NOTIFICATION_APP.SYNC,\n event: NOTIFICATION_APP_EVENT.SYNC[action],\n element: remotePath,\n url: [...SYNC_PATH_REPOSITORY[remotePath.split('/').at(0)], ...remotePath.split('/').slice(1, -1)].join('/')\n }\n this.notificationsManager\n .create([userId], notification, {\n currentUrl: this.contextManager.get('headerOriginUrl'),\n action: action\n })\n .catch((e: Error) => this.logger.error(`${this.notify.name} - ${e}`))\n }\n}\n"],"names":["SyncPathsManager","createPath","req","syncPathDto","user","clientId","HttpException","HttpStatus","BAD_REQUEST","space","quotaIsExceeded","INSUFFICIENT_STORAGE","isPathExists","realPath","remotePath","NOT_FOUND","isPathIsDir","client","syncQueries","getClient","id","syncDBProps","getDBProps","params","permissions","getEnvPermissions","root","pathId","deletePath","clientExistsForOwner","FORBIDDEN","e","logger","error","name","updatePath","syncPathUpdateDto","syncPathSettings","getPathSettings","Object","assign","timestamp","currentTimeStamp","updatePathSettings","INTERNAL_SERVER_ERROR","clearCachePathSettings","updatePaths","syncPathsDto","clientPathIds","map","p","serverPathIds","clientDiff","add","update","delete","serverPaths","getPaths","serverPath","spacesManager","spaceEnv","SYNC_PATH_TO_SPACE_SEGMENTS","message","push","indexOf","settings","envPermissions","clientPath","find","updateClientInfo","clientNewer","serverNewer","hasUpdates","keys","length","updatedSettings","lastSync","catch","filter","cid","cPathId","cPath","notify","ACTION","DELETE","forEach","path","inSharesList","inPersonalSpace","paths","ownerId","dbFile","fileId","getOrCreateFileId","inFilesRepository","alias","spaceId","spaceRootId","inSharesRepository","shareId","fileProps","getProps","filesQueries","getSpaceFileId","getOrCreateSpaceFile","undefined","userId","action","notification","app","NOTIFICATION_APP","SYNC","event","NOTIFICATION_APP_EVENT","element","url","SYNC_PATH_REPOSITORY","split","at","slice","join","notificationsManager","create","currentUrl","contextManager","get","Logger"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/sync/services/sync-paths-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 { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'\nimport { ACTION } from '../../../common/constants'\nimport { currentTimeStamp } from '../../../common/shared'\nimport { ContextManager } from '../../../infrastructure/context/services/context-manager.service'\nimport type { FileProps } from '../../files/interfaces/file-props.interface'\nimport { FilesQueries } from '../../files/services/files-queries.service'\nimport { getProps, isPathExists, isPathIsDir } from '../../files/utils/files'\nimport { NOTIFICATION_APP, NOTIFICATION_APP_EVENT } from '../../notifications/constants/notifications'\nimport { NotificationContent } from '../../notifications/interfaces/notification-properties.interface'\nimport { NotificationsManager } from '../../notifications/services/notifications-manager.service'\nimport { FastifySpaceRequest } from '../../spaces/interfaces/space-request.interface'\nimport { SpaceEnv } from '../../spaces/models/space-env.model'\nimport { SpacesManager } from '../../spaces/services/spaces-manager.service'\nimport { getEnvPermissions } from '../../spaces/utils/permissions'\nimport { UserModel } from '../../users/models/user.model'\nimport { SYNC_PATH_REPOSITORY } from '../constants/sync'\nimport { SyncPathDto, SyncPathUpdateDto } from '../dtos/sync-path.dto'\nimport { SyncDBProps, SyncPathSettings } from '../interfaces/sync-path.interface'\nimport { SyncClient } from '../schemas/sync-client.interface'\nimport { SYNC_PATH_TO_SPACE_SEGMENTS } from '../utils/routes'\nimport { SyncQueries } from './sync-queries.service'\n\n@Injectable()\nexport class SyncPathsManager {\n private readonly logger = new Logger(SyncPathsManager.name)\n\n constructor(\n private readonly contextManager: ContextManager,\n private readonly spacesManager: SpacesManager,\n private readonly filesQueries: FilesQueries,\n private readonly syncQueries: SyncQueries,\n private readonly notificationsManager: NotificationsManager\n ) {}\n\n async createPath(req: FastifySpaceRequest, syncPathDto: SyncPathDto): Promise<{ id: number; permissions: string }> {\n if (!req.user.clientId) {\n throw new HttpException('Client id is missing', HttpStatus.BAD_REQUEST)\n }\n if (req.space.quotaIsExceeded) {\n throw new HttpException('Storage quota exceeded', HttpStatus.INSUFFICIENT_STORAGE)\n }\n if (!(await isPathExists(req.space.realPath))) {\n throw new HttpException(`Remote path not found : ${syncPathDto.remotePath}`, HttpStatus.NOT_FOUND)\n }\n if (!(await isPathIsDir(req.space.realPath))) {\n throw new HttpException('Remote path must be a directory', HttpStatus.BAD_REQUEST)\n }\n const client: SyncClient = await this.syncQueries.getClient(req.user.clientId, req.user.id)\n if (!client) {\n throw new HttpException('Client not found', HttpStatus.NOT_FOUND)\n }\n const syncDBProps: SyncDBProps = await this.getDBProps(req.space)\n\n // important : ensures the right remote path is used and stored\n syncPathDto.remotePath = req.params['*']\n // add permissions (skip end point protection using getEnvPermission)\n syncPathDto.permissions = getEnvPermissions(req.space, req.space.root)\n const pathId = await this.syncQueries.createPath(client.id, syncDBProps, syncPathDto)\n return { id: pathId, permissions: syncPathDto.permissions }\n }\n\n async deletePath(user: UserModel, pathId: number, clientId?: string): Promise<void> {\n clientId = user.clientId || clientId\n if (!clientId) {\n throw new HttpException('Client id is missing', HttpStatus.BAD_REQUEST)\n }\n if (!(await this.syncQueries.clientExistsForOwner(user.id, clientId))) {\n throw new HttpException('You are not allowed to do this action', HttpStatus.FORBIDDEN)\n }\n try {\n await this.syncQueries.deletePath(clientId, pathId)\n } catch (e) {\n this.logger.error(`${this.deletePath.name} - ${e}`)\n throw new HttpException('Unable to remove path', HttpStatus.BAD_REQUEST)\n }\n }\n\n async updatePath(user: UserModel, clientId: string, pathId: number, syncPathUpdateDto: SyncPathUpdateDto): Promise<SyncPathSettings> {\n if (!(await this.syncQueries.clientExistsForOwner(user.id, clientId))) {\n throw new HttpException('You are not allowed to do this action', HttpStatus.FORBIDDEN)\n }\n const syncPathSettings: SyncPathSettings = await this.syncQueries.getPathSettings(clientId, pathId)\n if (!syncPathSettings) {\n throw new HttpException('Sync path not found', HttpStatus.NOT_FOUND)\n }\n // delete possible id\n delete syncPathUpdateDto.id\n // update current path settings\n Object.assign(syncPathSettings, syncPathUpdateDto)\n syncPathSettings.timestamp = currentTimeStamp()\n try {\n await this.syncQueries.updatePathSettings(clientId, pathId, syncPathSettings)\n } catch (e) {\n this.logger.error(`${this.updatePath.name} - ${e}`)\n throw new HttpException('Unable to update path', HttpStatus.INTERNAL_SERVER_ERROR)\n } finally {\n // clear cache\n this.syncQueries.clearCachePathSettings(clientId, pathId)\n }\n return syncPathSettings\n }\n\n async updatePaths(\n user: UserModel,\n syncPathsDto: SyncPathDto[]\n ): Promise<{\n add: SyncPathSettings[]\n update: Partial<Record<keyof SyncPathSettings, any>>[]\n delete: number[]\n }> {\n /* Update the client or server paths */\n if (!user.clientId) {\n throw new HttpException('Client id is missing', HttpStatus.BAD_REQUEST)\n }\n if (!(await this.syncQueries.clientExistsForOwner(user.id, user.clientId))) {\n throw new HttpException('You are not allowed to do this action', HttpStatus.FORBIDDEN)\n }\n const clientPathIds: number[] = syncPathsDto.map((p) => p.id)\n const serverPathIds: number[] = []\n\n const clientDiff: { add: SyncPathSettings[]; update: Partial<Record<keyof SyncPathSettings, any>>[]; delete: number[] } = {\n add: [],\n update: [],\n delete: []\n }\n const serverPaths: { id: number; settings: SyncPathSettings; remotePath: string }[] = await this.syncQueries.getPaths(user.clientId)\n for (const serverPath of serverPaths) {\n if (!serverPath.remotePath) {\n // unable to determine path, will be stored as deleted\n continue\n }\n let space: SpaceEnv\n try {\n space = await this.spacesManager.spaceEnv(user, SYNC_PATH_TO_SPACE_SEGMENTS(serverPath.remotePath), true)\n } catch (e) {\n throw new HttpException(e.message, HttpStatus.BAD_REQUEST)\n }\n if (!space) {\n // removed or inaccessible space, the path will be stored as deleted\n continue\n }\n serverPathIds.push(serverPath.id)\n if (clientPathIds.indexOf(serverPath.id) === -1) {\n // path exists on server but not on client, add it to client\n clientDiff.add.push({ ...serverPath.settings, id: serverPath.id, remotePath: serverPath.remotePath, permissions: space.envPermissions })\n continue\n }\n\n // path exists on both server and client side\n const clientPath: SyncPathDto = syncPathsDto.find((p) => p.id === serverPath.id)\n // remotePath and permissions settings are only managed by server\n const updateClientInfo: { remotePath?: string; permissions?: string } = {\n ...(serverPath.remotePath !== clientPath.remotePath && { remotePath: serverPath.remotePath }),\n ...(space.envPermissions !== clientPath.permissions && { permissions: space.envPermissions })\n }\n const clientNewer = clientPath.timestamp > serverPath.settings.timestamp\n const serverNewer = clientPath.timestamp < serverPath.settings.timestamp\n const hasUpdates = Object.keys(updateClientInfo).length > 0\n\n let updatedSettings: SyncPathSettings = { ...serverPath.settings, ...updateClientInfo }\n\n if (clientNewer) {\n updatedSettings = { ...clientPath, ...updateClientInfo }\n } else if (serverNewer) {\n clientDiff.update.push({ id: clientPath.id, ...serverPath.settings, ...updateClientInfo })\n }\n\n if (clientNewer || hasUpdates || serverPath.settings.lastSync !== clientPath.lastSync) {\n this.syncQueries\n .updatePathSettings(user.clientId, clientPath.id, { ...updatedSettings, lastSync: clientPath.lastSync })\n .catch((e: Error) => this.logger.error(`${this.updatePaths.name} - ${e}`))\n }\n\n if (!clientNewer && hasUpdates) {\n clientDiff.update.push({ id: clientPath.id, ...updateClientInfo })\n }\n }\n // path does not exist on server side\n clientDiff.delete = clientPathIds.filter((cid) => serverPathIds.indexOf(cid) === -1)\n for (const cPathId of clientDiff.delete) {\n const cPath: SyncPathDto = syncPathsDto.find((p) => p.id === cPathId)\n this.notify(user.id, ACTION.DELETE, cPath.remotePath).catch((e: Error) => this.logger.error(`${this.updatePaths.name} - ${e}`))\n }\n // clear cache\n clientDiff.update.forEach((path) => this.syncQueries.clearCachePathSettings(user.clientId, path.id))\n return clientDiff\n }\n\n private async getDBProps(space: SpaceEnv): Promise<SyncDBProps> {\n if (space.inSharesList) {\n throw new HttpException('Sync all shares is not supported, you must select a sub-directory', HttpStatus.BAD_REQUEST)\n } else if (space.inPersonalSpace) {\n if (space.paths.length) {\n return { ownerId: space.dbFile.ownerId, fileId: await this.getOrCreateFileId(space) }\n } else {\n return { ownerId: space.dbFile.ownerId }\n }\n } else if (space.inFilesRepository) {\n if (!space?.root?.alias) {\n // The synchronization direction should be adapted for each root depending on the permissions, this is not yet supported\n throw new HttpException('Sync all space is not yet supported, you must select a sub-directory', HttpStatus.BAD_REQUEST)\n }\n if (space.root.id && !space.paths.length) {\n return { spaceId: space.id, spaceRootId: space.root.id }\n } else {\n return { spaceId: space.id, spaceRootId: space?.root?.id || null, fileId: await this.getOrCreateFileId(space) }\n }\n } else if (space.inSharesRepository) {\n if (space.paths.length) {\n return { shareId: space.id, fileId: await this.getOrCreateFileId(space) }\n } else {\n return { shareId: space.id }\n }\n }\n }\n\n private async getOrCreateFileId(space: SpaceEnv): Promise<number> {\n const fileProps: FileProps = await getProps(space.realPath, space.dbFile.path)\n let fileId: number = await this.filesQueries.getSpaceFileId(fileProps, space.dbFile)\n if (!fileId) {\n fileId = await this.filesQueries.getOrCreateSpaceFile(fileId, { ...fileProps, id: undefined }, space.dbFile)\n }\n return fileId\n }\n\n private async notify(userId: number, action: ACTION, remotePath: string) {\n const notification: NotificationContent = {\n app: NOTIFICATION_APP.SYNC,\n event: NOTIFICATION_APP_EVENT.SYNC[action],\n element: remotePath,\n url: [...SYNC_PATH_REPOSITORY[remotePath.split('/').at(0)], ...remotePath.split('/').slice(1, -1)].join('/')\n }\n this.notificationsManager\n .create([userId], notification, {\n currentUrl: this.contextManager.headerOriginUrl(),\n action: action\n })\n .catch((e: Error) => this.logger.error(`${this.notify.name} - ${e}`))\n }\n}\n"],"names":["SyncPathsManager","createPath","req","syncPathDto","user","clientId","HttpException","HttpStatus","BAD_REQUEST","space","quotaIsExceeded","INSUFFICIENT_STORAGE","isPathExists","realPath","remotePath","NOT_FOUND","isPathIsDir","client","syncQueries","getClient","id","syncDBProps","getDBProps","params","permissions","getEnvPermissions","root","pathId","deletePath","clientExistsForOwner","FORBIDDEN","e","logger","error","name","updatePath","syncPathUpdateDto","syncPathSettings","getPathSettings","Object","assign","timestamp","currentTimeStamp","updatePathSettings","INTERNAL_SERVER_ERROR","clearCachePathSettings","updatePaths","syncPathsDto","clientPathIds","map","p","serverPathIds","clientDiff","add","update","delete","serverPaths","getPaths","serverPath","spacesManager","spaceEnv","SYNC_PATH_TO_SPACE_SEGMENTS","message","push","indexOf","settings","envPermissions","clientPath","find","updateClientInfo","clientNewer","serverNewer","hasUpdates","keys","length","updatedSettings","lastSync","catch","filter","cid","cPathId","cPath","notify","ACTION","DELETE","forEach","path","inSharesList","inPersonalSpace","paths","ownerId","dbFile","fileId","getOrCreateFileId","inFilesRepository","alias","spaceId","spaceRootId","inSharesRepository","shareId","fileProps","getProps","filesQueries","getSpaceFileId","getOrCreateSpaceFile","undefined","userId","action","notification","app","NOTIFICATION_APP","SYNC","event","NOTIFICATION_APP_EVENT","element","url","SYNC_PATH_REPOSITORY","split","at","slice","join","notificationsManager","create","currentUrl","contextManager","headerOriginUrl","Logger"],"mappings":"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"}
@@ -71,7 +71,7 @@ describe(_syncpathsmanagerservice.SyncPathsManager.name, ()=>{
71
71
  const flush = ()=>new Promise((r)=>setImmediate(r));
72
72
  beforeEach(async ()=>{
73
73
  contextManager = {
74
- get: jest.fn(()=>'http://origin.local')
74
+ headerOriginUrl: jest.fn(()=>'http://origin.local')
75
75
  };
76
76
  spacesManager = {
77
77
  spaceEnv: jest.fn()
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/sync/services/sync-paths-manager.service.spec.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 { HttpStatus } from '@nestjs/common'\nimport { Test, TestingModule } from '@nestjs/testing'\nimport { currentTimeStamp } from '../../../common/shared'\nimport { ContextManager } from '../../../infrastructure/context/services/context-manager.service'\nimport { FilesQueries } from '../../files/services/files-queries.service'\nimport { getProps, isPathExists, isPathIsDir } from '../../files/utils/files'\nimport { NotificationsManager } from '../../notifications/services/notifications-manager.service'\nimport { SpacesManager } from '../../spaces/services/spaces-manager.service'\nimport { getEnvPermissions } from '../../spaces/utils/permissions'\nimport { UsersQueries } from '../../users/services/users-queries.service'\nimport { SyncPathsManager } from './sync-paths-manager.service'\nimport { SyncQueries } from './sync-queries.service'\n\n// Mock modules used directly inside SyncPathsManager\njest.mock('../../../common/shared', () => ({\n currentTimeStamp: jest.fn(() => 1000)\n}))\njest.mock('../../files/utils/files', () => ({\n isPathExists: jest.fn(),\n isPathIsDir: jest.fn(),\n getProps: jest.fn(),\n sanitizePath: jest.fn((p: string) => p)\n}))\njest.mock('../../spaces/utils/permissions', () => ({\n getEnvPermissions: jest.fn(() => 'server-perms')\n}))\njest.mock('../constants/sync', () => ({\n SYNC_PATH_REPOSITORY: {\n SPACES: ['spaces'],\n PERSONAL: ['personal'],\n SHARES: ['shares']\n }\n}))\njest.mock('../../notifications/constants/notifications', () => ({\n NOTIFICATION_APP: { SYNC: 'SYNC' },\n NOTIFICATION_APP_EVENT: { SYNC: { DELETE: 'DELETE', CREATE: 'CREATE', UPDATE: 'UPDATE' } }\n}))\n\ndescribe(SyncPathsManager.name, () => {\n let service: SyncPathsManager\n let contextManager: { get: jest.Mock }\n let spacesManager: { spaceEnv: jest.Mock }\n let usersQueries: Record<string, jest.Mock>\n let filesQueries: { getSpaceFileId: jest.Mock; getOrCreateSpaceFile: jest.Mock }\n let notificationsManager: { create: jest.Mock }\n let syncQueries: {\n getClient: jest.Mock\n clientExistsForOwner: jest.Mock\n createPath: jest.Mock\n deletePath: jest.Mock\n getPaths: jest.Mock\n getPathSettings: jest.Mock\n updatePathSettings: jest.Mock\n clearCachePathSettings: jest.Mock\n }\n\n const userWith = (clientId?: string) => ({ id: 1, clientId })\n const flush = () => new Promise((r) => setImmediate(r))\n\n beforeEach(async () => {\n contextManager = { get: jest.fn(() => 'http://origin.local') }\n spacesManager = { spaceEnv: jest.fn() }\n usersQueries = {}\n filesQueries = {\n getSpaceFileId: jest.fn(),\n getOrCreateSpaceFile: jest.fn()\n }\n notificationsManager = {\n create: jest.fn().mockResolvedValue(undefined)\n }\n syncQueries = {\n getClient: jest.fn(),\n clientExistsForOwner: jest.fn(),\n createPath: jest.fn(),\n deletePath: jest.fn(),\n getPaths: jest.fn(),\n getPathSettings: jest.fn(),\n updatePathSettings: jest.fn().mockResolvedValue(undefined),\n clearCachePathSettings: jest.fn()\n }\n ;(isPathExists as jest.Mock).mockReset()\n ;(isPathIsDir as jest.Mock).mockReset()\n ;(getProps as jest.Mock).mockReset()\n ;(getEnvPermissions as jest.Mock).mockReset().mockReturnValue('server-perms')\n ;(currentTimeStamp as jest.Mock).mockReset().mockReturnValue(1000)\n\n const module: TestingModule = await Test.createTestingModule({\n providers: [\n SyncPathsManager,\n { provide: ContextManager, useValue: contextManager },\n { provide: SpacesManager, useValue: spacesManager },\n { provide: UsersQueries, useValue: usersQueries },\n { provide: FilesQueries, useValue: filesQueries },\n { provide: NotificationsManager, useValue: notificationsManager },\n { provide: SyncQueries, useValue: syncQueries }\n ]\n }).compile()\n\n module.useLogger(['fatal'])\n service = module.get<SyncPathsManager>(SyncPathsManager)\n })\n\n it('should be defined', () => {\n expect(service).toBeDefined()\n })\n\n describe('createPath', () => {\n const baseReq = () =>\n ({\n user: { id: 1, clientId: 'client-1' },\n params: { '*': 'SPACES/alias/sub' },\n space: {\n realPath: '/real/path',\n quotaIsExceeded: false,\n root: { id: 1, alias: 'alias' },\n inFilesRepository: true,\n paths: ['sub'],\n dbFile: { ownerId: 1, path: '.' },\n id: 10\n }\n }) as any\n\n it('should throw BAD_REQUEST when client id is missing', async () => {\n const req = baseReq()\n req.user.clientId = undefined\n await expect(service.createPath(req, { remotePath: 'x' } as any)).rejects.toMatchObject({\n status: HttpStatus.BAD_REQUEST,\n message: 'Client id is missing'\n })\n })\n\n it('should throw INSUFFICIENT_STORAGE when storage quota is exceeded', async () => {\n const req = baseReq()\n req.space.quotaIsExceeded = true\n await expect(service.createPath(req, { remotePath: 'x' } as any)).rejects.toMatchObject({\n status: HttpStatus.INSUFFICIENT_STORAGE\n })\n })\n\n it.each([\n {\n title: 'NOT_FOUND when remote path does not exist',\n setup: () => (isPathExists as jest.Mock).mockResolvedValue(false),\n expected: { status: HttpStatus.NOT_FOUND, message: 'Remote path not found : client/remote' }\n },\n {\n title: 'BAD_REQUEST when remote path is not a directory',\n setup: () => ((isPathExists as jest.Mock).mockResolvedValue(true), (isPathIsDir as jest.Mock).mockResolvedValue(false)),\n expected: { status: HttpStatus.BAD_REQUEST, message: 'Remote path must be a directory' }\n },\n {\n title: 'NOT_FOUND when client is not found',\n setup: () => (\n (isPathExists as jest.Mock).mockResolvedValue(true),\n (isPathIsDir as jest.Mock).mockResolvedValue(true),\n syncQueries.getClient.mockResolvedValue(null)\n ),\n expected: { status: HttpStatus.NOT_FOUND, message: 'Client not found' }\n }\n ])('should throw $title', async ({ setup, expected }) => {\n const req = baseReq()\n setup()\n await expect(service.createPath(req, { remotePath: 'client/remote' } as any)).rejects.toMatchObject(expected)\n })\n\n it('should create path and return id and permissions, overriding remotePath and permissions', async () => {\n const req = baseReq()\n ;(isPathExists as jest.Mock).mockResolvedValue(true)\n ;(isPathIsDir as jest.Mock).mockResolvedValue(true)\n ;(getEnvPermissions as jest.Mock).mockReturnValue('env-perms')\n syncQueries.getClient.mockResolvedValue({ id: 'client-1' })\n // Spy on private getDBProps to simplify\n const getDBPropsSpy = jest.spyOn<any, any>(service as any, 'getDBProps').mockResolvedValue({ ownerId: 1 })\n syncQueries.createPath.mockResolvedValue(123)\n\n const res = await service.createPath(req, { remotePath: 'client/remote', permissions: 'client-perms' } as any)\n expect(res).toEqual({ id: 123, permissions: 'env-perms' })\n expect(syncQueries.createPath).toHaveBeenCalledWith(\n 'client-1',\n { ownerId: 1 },\n expect.objectContaining({ remotePath: 'SPACES/alias/sub', permissions: 'env-perms' })\n )\n\n getDBPropsSpy.mockRestore()\n })\n })\n\n describe('deletePath', () => {\n it.each([\n { user: { id: 1, clientId: undefined } as any, id: 10, status: HttpStatus.BAD_REQUEST, msg: 'Client id is missing' },\n { user: { id: 1, clientId: 'c1' } as any, id: 10, status: HttpStatus.FORBIDDEN }\n ])('should handle errors (status=$status)', async ({ user, id, status, msg }) => {\n if (status === HttpStatus.FORBIDDEN) syncQueries.clientExistsForOwner.mockResolvedValue(false)\n await expect(service.deletePath(user, id)).rejects.toMatchObject(msg ? { status, message: msg } : { status })\n })\n\n it('should catch errors from deletePath and throw BAD_REQUEST', async () => {\n const user: any = { id: 1, clientId: 'c1' }\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.deletePath.mockRejectedValue(new Error('db'))\n await expect(service.deletePath(user, 10)).rejects.toMatchObject({\n status: HttpStatus.BAD_REQUEST,\n message: 'Unable to remove path'\n })\n expect(syncQueries.deletePath).toHaveBeenCalledWith('c1', 10)\n })\n\n it('should delete path successfully when allowed', async () => {\n const user: any = { id: 1, clientId: undefined }\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.deletePath.mockResolvedValue(undefined)\n await expect(service.deletePath(user, 10, 'cX')).resolves.toBeUndefined()\n expect(syncQueries.deletePath).toHaveBeenCalledWith('cX', 10)\n })\n })\n\n describe('updatePath', () => {\n it('should throw FORBIDDEN when client does not belong to owner', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(false)\n await expect(service.updatePath({ id: 1 } as any, 'c1', 5, {} as any)).rejects.toMatchObject({\n status: HttpStatus.FORBIDDEN\n })\n })\n\n it('should throw NOT_FOUND when path settings do not exist', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPathSettings.mockResolvedValue(null)\n await expect(service.updatePath({ id: 1 } as any, 'c1', 5, {} as any)).rejects.toMatchObject({\n status: HttpStatus.NOT_FOUND,\n message: 'Sync path not found'\n })\n })\n\n it('should update path settings, set new timestamp, clear cache and return updated settings', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPathSettings.mockResolvedValue({ id: 5, timestamp: 500, lastSync: 1, remotePath: '/a', permissions: 'p' })\n syncQueries.updatePathSettings.mockResolvedValue(undefined)\n ;(currentTimeStamp as jest.Mock).mockReturnValue(4242)\n\n const out = await service.updatePath({ id: 1 } as any, 'c1', 5, { id: 666, lastSync: 3, permissions: 'new' } as any)\n expect(syncQueries.updatePathSettings).toHaveBeenCalledWith(\n 'c1',\n 5,\n expect.objectContaining({ id: 5, lastSync: 3, timestamp: 4242, permissions: 'new' })\n )\n expect(syncQueries.clearCachePathSettings).toHaveBeenCalledWith('c1', 5)\n expect(out).toEqual(expect.objectContaining({ id: 5, lastSync: 3, timestamp: 4242, permissions: 'new' }))\n })\n\n it('should clear cache and throw INTERNAL_SERVER_ERROR when update fails', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPathSettings.mockResolvedValue({ id: 5, timestamp: 500, lastSync: 1 })\n syncQueries.updatePathSettings.mockRejectedValue(new Error('db'))\n await expect(service.updatePath({ id: 1 } as any, 'c1', 5, {} as any)).rejects.toMatchObject({\n status: HttpStatus.INTERNAL_SERVER_ERROR,\n message: 'Unable to update path'\n })\n expect(syncQueries.clearCachePathSettings).toHaveBeenCalledWith('c1', 5)\n })\n })\n\n describe('updatePaths', () => {\n beforeEach(() => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'p' })\n })\n\n it('should throw when client id is missing', async () => {\n await expect(service.updatePaths(userWith(undefined) as any, [])).rejects.toMatchObject({\n status: HttpStatus.BAD_REQUEST,\n message: 'Client id is missing'\n })\n })\n\n it('should throw FORBIDDEN when client does not belong to owner', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(false)\n await expect(service.updatePaths(userWith('c1') as any, [])).rejects.toMatchObject({\n status: HttpStatus.FORBIDDEN\n })\n })\n\n it('should mark client paths as deleted and notify when no corresponding server paths (server remotePath undefined)', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 2, settings: { timestamp: 1, lastSync: 1 }, remotePath: undefined }])\n const clientPaths = [{ id: 1, remotePath: 'SPACES/a', timestamp: 1, lastSync: 1, permissions: 'p' } as any]\n\n const res = await service.updatePaths(userWith('c1') as any, clientPaths)\n expect(res.delete).toEqual([1])\n expect(notificationsManager.create).toHaveBeenCalledTimes(1)\n })\n\n it('should propagate spaceEnv errors as BAD_REQUEST', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 1, settings: { timestamp: 1, lastSync: 1 }, remotePath: 'SPACES/x' }])\n spacesManager.spaceEnv.mockRejectedValue(new Error('boom'))\n await expect(\n service.updatePaths(userWith('c1') as any, [{ id: 1, remotePath: 'SPACES/x', timestamp: 1, lastSync: 1, permissions: 'p' } as any])\n ).rejects.toMatchObject({\n status: HttpStatus.BAD_REQUEST,\n message: 'boom'\n })\n })\n\n it('should skip server path when space is null and mark client item as deleted', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 2, settings: { timestamp: 1, lastSync: 1 }, remotePath: 'SPACES/x' }])\n spacesManager.spaceEnv.mockResolvedValue(null)\n const res = await service.updatePaths(userWith('c1') as any, [\n { id: 2, remotePath: 'SPACES/x', timestamp: 1, lastSync: 1, permissions: 'p' } as any\n ])\n expect(res.delete).toEqual([2])\n expect(notificationsManager.create).toHaveBeenCalledTimes(1)\n })\n\n it('should add server-only path to client with server permissions', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 3, settings: { timestamp: 1, lastSync: 1 }, remotePath: 'SPACES/x' }])\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'perm-xyz' })\n const res = await service.updatePaths(userWith('c1') as any, [])\n expect(res.add).toHaveLength(1)\n expect(res.add[0]).toEqual(expect.objectContaining({ id: 3, remotePath: 'SPACES/x', permissions: 'perm-xyz' }))\n })\n\n it('should update server settings from client when client is newer (no hasUpdates)', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 5, settings: { timestamp: 1, lastSync: 1, foo: 'server' }, remotePath: 'SPACES/x' }])\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'p' })\n\n const client = [{ id: 5, timestamp: 10, lastSync: 2, remotePath: 'SPACES/x', permissions: 'p', foo: 'client' } as any]\n await service.updatePaths(userWith('c1') as any, client)\n\n expect(syncQueries.updatePathSettings).toHaveBeenCalledWith('c1', 5, expect.objectContaining({ foo: 'client', lastSync: 2 }))\n // No client update instructions because hasUpdates=false and serverNewer=false\n })\n\n it('should push server-newer updates to client and also remotePath/permissions corrections', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 7, settings: { timestamp: 20, lastSync: 5, srv: true }, remotePath: 'SPACES/correct' }])\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'permX' })\n\n const client = [{ id: 7, timestamp: 10, lastSync: 5, remotePath: 'SPACES/wrong', permissions: 'old' } as any]\n const res = await service.updatePaths(userWith('c1') as any, client)\n\n // Should have two client updates: one full server settings + corrections, and one corrections-only\n expect(res.update).toEqual(\n expect.arrayContaining([\n expect.objectContaining({ id: 7, srv: true, remotePath: 'SPACES/correct', permissions: 'permX' }),\n expect.objectContaining({ id: 7, remotePath: 'SPACES/correct', permissions: 'permX' })\n ])\n )\n expect(syncQueries.updatePathSettings).toHaveBeenCalledWith('c1', 7, expect.objectContaining({ lastSync: 5 }))\n // clear cache called for each update instruction\n expect(syncQueries.clearCachePathSettings).toHaveBeenCalledTimes(res.update.length)\n for (const u of res.update) {\n expect(syncQueries.clearCachePathSettings).toHaveBeenCalledWith('c1', u.id)\n }\n })\n\n it('should trigger update when lastSync differs even if timestamps and settings match', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 9, settings: { timestamp: 10, lastSync: 1, flag: 'S' }, remotePath: 'SPACES/x' }])\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'p' })\n\n const client = [{ id: 9, timestamp: 10, lastSync: 2, remotePath: 'SPACES/x', permissions: 'p', flag: 'S' } as any]\n await service.updatePaths(userWith('c1') as any, client)\n expect(syncQueries.updatePathSettings).toHaveBeenCalledWith('c1', 9, expect.objectContaining({ lastSync: 2 }))\n })\n\n it('should perform no changes when client and server are identical (no-op branch)', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 12, settings: { timestamp: 5, lastSync: 7, flag: 'A' }, remotePath: 'SPACES/x' }])\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'p' })\n\n const client = [{ id: 12, timestamp: 5, lastSync: 7, remotePath: 'SPACES/x', permissions: 'p', flag: 'A' } as any]\n const res = await service.updatePaths(userWith('c1') as any, client)\n\n expect(res).toEqual({ add: [], update: [], delete: [] })\n expect(syncQueries.updatePathSettings).not.toHaveBeenCalled()\n })\n\n it('should correct client info while keeping server settings when timestamps are equal (hasUpdates=true)', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n // Server has srv='S', client has wrong remotePath/permissions and extra clientOnly flag\n syncQueries.getPaths.mockResolvedValue([{ id: 13, settings: { timestamp: 5, lastSync: 1, srv: 'S' }, remotePath: 'SPACES/correct' }])\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'permX' })\n\n const client = [{ id: 13, timestamp: 5, lastSync: 1, remotePath: 'SPACES/wrong', permissions: 'old', clientOnly: 'C' } as any]\n const res = await service.updatePaths(userWith('c1') as any, client)\n\n // Server uses its own settings base (srv: 'S') with corrections applied\n expect(syncQueries.updatePathSettings).toHaveBeenCalledWith(\n 'c1',\n 13,\n expect.objectContaining({ srv: 'S', lastSync: 1, remotePath: 'SPACES/correct', permissions: 'permX' })\n )\n // Client should receive corrections for remotePath and permissions\n expect(res.update).toEqual(expect.arrayContaining([expect.objectContaining({ id: 13, remotePath: 'SPACES/correct', permissions: 'permX' })]))\n })\n\n it('should log error when updatePathSettings rejects inside updatePaths', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 11, settings: { timestamp: 1, lastSync: 1 }, remotePath: 'SPACES/x' }])\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'p' })\n // Force client newer to trigger updatePathSettings\n const client = [{ id: 11, timestamp: 10, lastSync: 2, remotePath: 'SPACES/x', permissions: 'p' } as any]\n syncQueries.updatePathSettings.mockRejectedValueOnce(new Error('db-fail'))\n const loggerSpy = jest.spyOn((service as any).logger, 'error').mockImplementation(() => undefined)\n\n await service.updatePaths(userWith('c1') as any, client)\n // wait for microtasks to ensure .catch executed\n await flush()\n\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls.some(([msg]) => String(msg).includes('updatePaths'))).toBe(true)\n })\n\n it('should catch notify failure at updatePaths level when building notification fails', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n // No server paths: will mark client path as deleted and call notify\n syncQueries.getPaths.mockResolvedValue([])\n const loggerSpy = jest.spyOn((service as any).logger, 'error').mockImplementation(() => undefined)\n // BAD first segment to make notify fail while building URL (before notificationsManager.create)\n const client = [{ id: 1, remotePath: 'BAD/a/b', timestamp: 1, lastSync: 1, permissions: 'p' } as any]\n\n const res = await service.updatePaths(userWith('c1') as any, client)\n await flush()\n\n expect(res.delete).toEqual([1])\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls.some(([msg]) => String(msg).includes('updatePaths'))).toBe(true)\n // create not called because we failed before reaching it\n expect(notificationsManager.create).not.toHaveBeenCalled()\n })\n\n it('should catch error inside notify when notifications creation fails', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([])\n // Valid remotePath to build URL correctly\n const client = [{ id: 2, remotePath: 'SPACES/a', timestamp: 1, lastSync: 1, permissions: 'p' } as any]\n const loggerSpy = jest.spyOn((service as any).logger, 'error').mockImplementation(() => undefined)\n notificationsManager.create.mockRejectedValueOnce(new Error('notify-fail'))\n\n const res = await service.updatePaths(userWith('c1') as any, client)\n await flush()\n\n expect(res.delete).toEqual([2])\n expect(loggerSpy).toHaveBeenCalled()\n // error comes from notify() catch\n expect(loggerSpy.mock.calls.some(([msg]) => String(msg).includes('notify'))).toBe(true)\n })\n })\n\n describe('getDBProps (private) branches', () => {\n it('should throw BAD_REQUEST for shares list selection', async () => {\n await expect((service as any).getDBProps({ inSharesList: true } as any)).rejects.toMatchObject({\n status: HttpStatus.BAD_REQUEST,\n message: 'Sync all shares is not supported, you must select a sub-directory'\n })\n })\n\n it('should return ownerId only for personal space at root', async () => {\n const res = await (service as any).getDBProps({\n inSharesList: false,\n inPersonalSpace: true,\n paths: [],\n dbFile: { ownerId: 42 }\n } as any)\n expect(res).toEqual({ ownerId: 42 })\n })\n\n it('should return ownerId and fileId for personal space subdir', async () => {\n const getOrCreateFileIdSpy = jest.spyOn<any, any>(service as any, 'getOrCreateFileId').mockResolvedValue(77)\n const res = await (service as any).getDBProps({\n inPersonalSpace: true,\n paths: ['sub'],\n dbFile: { ownerId: 42 }\n } as any)\n expect(res).toEqual({ ownerId: 42, fileId: 77 })\n getOrCreateFileIdSpy.mockRestore()\n })\n\n it('should throw BAD_REQUEST for whole files repository without alias', async () => {\n await expect((service as any).getDBProps({ inFilesRepository: true, root: { alias: null }, paths: [] } as any)).rejects.toMatchObject({\n status: HttpStatus.BAD_REQUEST,\n message: 'Sync all space is not yet supported, you must select a sub-directory'\n })\n })\n\n it('should return spaceId and rootId for files repository root selection', async () => {\n const res = await (service as any).getDBProps({\n inFilesRepository: true,\n id: 5,\n root: { id: 3, alias: 'x' },\n paths: []\n } as any)\n expect(res).toEqual({ spaceId: 5, spaceRootId: 3 })\n })\n\n it('should return spaceId, rootId and fileId for files repository subdir or null root', async () => {\n const getOrCreateFileIdSpy = jest.spyOn<any, any>(service as any, 'getOrCreateFileId').mockResolvedValue(88)\n const res = await (service as any).getDBProps({\n inFilesRepository: true,\n id: 5,\n root: { id: 3, alias: 'x' },\n paths: ['sub']\n } as any)\n expect(res).toEqual({ spaceId: 5, spaceRootId: 3, fileId: 88 })\n getOrCreateFileIdSpy.mockRestore()\n })\n\n it('should return spaceId and null spaceRootId plus fileId when files repository root has no id', async () => {\n const getOrCreateFileIdSpy = jest.spyOn<any, any>(service as any, 'getOrCreateFileId').mockResolvedValue(90)\n const res = await (service as any).getDBProps({\n inFilesRepository: true,\n id: 6,\n root: { id: undefined, alias: 'x' },\n paths: []\n } as any)\n expect(res).toEqual({ spaceId: 6, spaceRootId: null, fileId: 90 })\n getOrCreateFileIdSpy.mockRestore()\n })\n\n it('should return shareId only for shares repository root', async () => {\n const res = await (service as any).getDBProps({\n inSharesList: false,\n inPersonalSpace: false,\n inFilesRepository: false,\n inSharesRepository: true,\n id: 9,\n paths: []\n } as any)\n expect(res).toEqual({ shareId: 9 })\n })\n\n it('should return shareId and fileId for shares repository subdir', async () => {\n const getOrCreateFileIdSpy = jest.spyOn<any, any>(service as any, 'getOrCreateFileId').mockResolvedValue(55)\n const res = await (service as any).getDBProps({\n inSharesList: false,\n inPersonalSpace: false,\n inFilesRepository: false,\n inSharesRepository: true,\n id: 9,\n paths: ['sub']\n } as any)\n expect(res).toEqual({ shareId: 9, fileId: 55 })\n getOrCreateFileIdSpy.mockRestore()\n })\n\n it('should return undefined when no space flags match (no branch taken)', async () => {\n const res = await (service as any).getDBProps({\n inSharesList: false,\n inPersonalSpace: false,\n inFilesRepository: false,\n inSharesRepository: false,\n paths: []\n } as any)\n expect(res).toBeUndefined()\n })\n })\n\n describe('getOrCreateFileId (private) branches', () => {\n it('should return existing file id without creation', async () => {\n ;(getProps as jest.Mock).mockResolvedValue({ name: 'file' })\n filesQueries.getSpaceFileId.mockResolvedValue(101)\n const id = await (service as any).getOrCreateFileId({\n realPath: '/rp',\n dbFile: { path: '.' }\n })\n expect(id).toBe(101)\n expect(filesQueries.getOrCreateSpaceFile).not.toHaveBeenCalled()\n })\n\n it('should create file when not exists and return its id', async () => {\n ;(getProps as jest.Mock).mockResolvedValue({ id: 999, name: 'file' })\n filesQueries.getSpaceFileId.mockResolvedValue(0)\n filesQueries.getOrCreateSpaceFile.mockResolvedValue(202)\n const id = await (service as any).getOrCreateFileId({\n realPath: '/rp',\n dbFile: { path: '.' }\n })\n expect(id).toBe(202)\n expect(filesQueries.getOrCreateSpaceFile).toHaveBeenCalledWith(0, expect.objectContaining({ id: undefined }), { path: '.' })\n })\n })\n})\n"],"names":["jest","mock","currentTimeStamp","fn","isPathExists","isPathIsDir","getProps","sanitizePath","p","getEnvPermissions","SYNC_PATH_REPOSITORY","SPACES","PERSONAL","SHARES","NOTIFICATION_APP","SYNC","NOTIFICATION_APP_EVENT","DELETE","CREATE","UPDATE","describe","SyncPathsManager","name","service","contextManager","spacesManager","usersQueries","filesQueries","notificationsManager","syncQueries","userWith","clientId","id","flush","Promise","r","setImmediate","beforeEach","get","spaceEnv","getSpaceFileId","getOrCreateSpaceFile","create","mockResolvedValue","undefined","getClient","clientExistsForOwner","createPath","deletePath","getPaths","getPathSettings","updatePathSettings","clearCachePathSettings","mockReset","mockReturnValue","module","Test","createTestingModule","providers","provide","ContextManager","useValue","SpacesManager","UsersQueries","FilesQueries","NotificationsManager","SyncQueries","compile","useLogger","it","expect","toBeDefined","baseReq","user","params","space","realPath","quotaIsExceeded","root","alias","inFilesRepository","paths","dbFile","ownerId","path","req","remotePath","rejects","toMatchObject","status","HttpStatus","BAD_REQUEST","message","INSUFFICIENT_STORAGE","each","title","setup","expected","NOT_FOUND","getDBPropsSpy","spyOn","res","permissions","toEqual","toHaveBeenCalledWith","objectContaining","mockRestore","msg","FORBIDDEN","mockRejectedValue","Error","resolves","toBeUndefined","updatePath","timestamp","lastSync","out","INTERNAL_SERVER_ERROR","envPermissions","updatePaths","settings","clientPaths","delete","toHaveBeenCalledTimes","add","toHaveLength","foo","client","srv","update","arrayContaining","length","u","flag","not","toHaveBeenCalled","clientOnly","mockRejectedValueOnce","loggerSpy","logger","mockImplementation","calls","some","String","includes","toBe","getDBProps","inSharesList","inPersonalSpace","getOrCreateFileIdSpy","fileId","spaceId","spaceRootId","inSharesRepository","shareId","getOrCreateFileId"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/sync/services/sync-paths-manager.service.spec.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 { HttpStatus } from '@nestjs/common'\nimport { Test, TestingModule } from '@nestjs/testing'\nimport { currentTimeStamp } from '../../../common/shared'\nimport { ContextManager } from '../../../infrastructure/context/services/context-manager.service'\nimport { FilesQueries } from '../../files/services/files-queries.service'\nimport { getProps, isPathExists, isPathIsDir } from '../../files/utils/files'\nimport { NotificationsManager } from '../../notifications/services/notifications-manager.service'\nimport { SpacesManager } from '../../spaces/services/spaces-manager.service'\nimport { getEnvPermissions } from '../../spaces/utils/permissions'\nimport { UsersQueries } from '../../users/services/users-queries.service'\nimport { SyncPathsManager } from './sync-paths-manager.service'\nimport { SyncQueries } from './sync-queries.service'\n\n// Mock modules used directly inside SyncPathsManager\njest.mock('../../../common/shared', () => ({\n currentTimeStamp: jest.fn(() => 1000)\n}))\njest.mock('../../files/utils/files', () => ({\n isPathExists: jest.fn(),\n isPathIsDir: jest.fn(),\n getProps: jest.fn(),\n sanitizePath: jest.fn((p: string) => p)\n}))\njest.mock('../../spaces/utils/permissions', () => ({\n getEnvPermissions: jest.fn(() => 'server-perms')\n}))\njest.mock('../constants/sync', () => ({\n SYNC_PATH_REPOSITORY: {\n SPACES: ['spaces'],\n PERSONAL: ['personal'],\n SHARES: ['shares']\n }\n}))\njest.mock('../../notifications/constants/notifications', () => ({\n NOTIFICATION_APP: { SYNC: 'SYNC' },\n NOTIFICATION_APP_EVENT: { SYNC: { DELETE: 'DELETE', CREATE: 'CREATE', UPDATE: 'UPDATE' } }\n}))\n\ndescribe(SyncPathsManager.name, () => {\n let service: SyncPathsManager\n let contextManager: { headerOriginUrl: jest.Mock }\n let spacesManager: { spaceEnv: jest.Mock }\n let usersQueries: Record<string, jest.Mock>\n let filesQueries: { getSpaceFileId: jest.Mock; getOrCreateSpaceFile: jest.Mock }\n let notificationsManager: { create: jest.Mock }\n let syncQueries: {\n getClient: jest.Mock\n clientExistsForOwner: jest.Mock\n createPath: jest.Mock\n deletePath: jest.Mock\n getPaths: jest.Mock\n getPathSettings: jest.Mock\n updatePathSettings: jest.Mock\n clearCachePathSettings: jest.Mock\n }\n\n const userWith = (clientId?: string) => ({ id: 1, clientId })\n const flush = () => new Promise((r) => setImmediate(r))\n\n beforeEach(async () => {\n contextManager = { headerOriginUrl: jest.fn(() => 'http://origin.local') }\n spacesManager = { spaceEnv: jest.fn() }\n usersQueries = {}\n filesQueries = {\n getSpaceFileId: jest.fn(),\n getOrCreateSpaceFile: jest.fn()\n }\n notificationsManager = {\n create: jest.fn().mockResolvedValue(undefined)\n }\n syncQueries = {\n getClient: jest.fn(),\n clientExistsForOwner: jest.fn(),\n createPath: jest.fn(),\n deletePath: jest.fn(),\n getPaths: jest.fn(),\n getPathSettings: jest.fn(),\n updatePathSettings: jest.fn().mockResolvedValue(undefined),\n clearCachePathSettings: jest.fn()\n }\n ;(isPathExists as jest.Mock).mockReset()\n ;(isPathIsDir as jest.Mock).mockReset()\n ;(getProps as jest.Mock).mockReset()\n ;(getEnvPermissions as jest.Mock).mockReset().mockReturnValue('server-perms')\n ;(currentTimeStamp as jest.Mock).mockReset().mockReturnValue(1000)\n\n const module: TestingModule = await Test.createTestingModule({\n providers: [\n SyncPathsManager,\n { provide: ContextManager, useValue: contextManager },\n { provide: SpacesManager, useValue: spacesManager },\n { provide: UsersQueries, useValue: usersQueries },\n { provide: FilesQueries, useValue: filesQueries },\n { provide: NotificationsManager, useValue: notificationsManager },\n { provide: SyncQueries, useValue: syncQueries }\n ]\n }).compile()\n\n module.useLogger(['fatal'])\n service = module.get<SyncPathsManager>(SyncPathsManager)\n })\n\n it('should be defined', () => {\n expect(service).toBeDefined()\n })\n\n describe('createPath', () => {\n const baseReq = () =>\n ({\n user: { id: 1, clientId: 'client-1' },\n params: { '*': 'SPACES/alias/sub' },\n space: {\n realPath: '/real/path',\n quotaIsExceeded: false,\n root: { id: 1, alias: 'alias' },\n inFilesRepository: true,\n paths: ['sub'],\n dbFile: { ownerId: 1, path: '.' },\n id: 10\n }\n }) as any\n\n it('should throw BAD_REQUEST when client id is missing', async () => {\n const req = baseReq()\n req.user.clientId = undefined\n await expect(service.createPath(req, { remotePath: 'x' } as any)).rejects.toMatchObject({\n status: HttpStatus.BAD_REQUEST,\n message: 'Client id is missing'\n })\n })\n\n it('should throw INSUFFICIENT_STORAGE when storage quota is exceeded', async () => {\n const req = baseReq()\n req.space.quotaIsExceeded = true\n await expect(service.createPath(req, { remotePath: 'x' } as any)).rejects.toMatchObject({\n status: HttpStatus.INSUFFICIENT_STORAGE\n })\n })\n\n it.each([\n {\n title: 'NOT_FOUND when remote path does not exist',\n setup: () => (isPathExists as jest.Mock).mockResolvedValue(false),\n expected: { status: HttpStatus.NOT_FOUND, message: 'Remote path not found : client/remote' }\n },\n {\n title: 'BAD_REQUEST when remote path is not a directory',\n setup: () => ((isPathExists as jest.Mock).mockResolvedValue(true), (isPathIsDir as jest.Mock).mockResolvedValue(false)),\n expected: { status: HttpStatus.BAD_REQUEST, message: 'Remote path must be a directory' }\n },\n {\n title: 'NOT_FOUND when client is not found',\n setup: () => (\n (isPathExists as jest.Mock).mockResolvedValue(true),\n (isPathIsDir as jest.Mock).mockResolvedValue(true),\n syncQueries.getClient.mockResolvedValue(null)\n ),\n expected: { status: HttpStatus.NOT_FOUND, message: 'Client not found' }\n }\n ])('should throw $title', async ({ setup, expected }) => {\n const req = baseReq()\n setup()\n await expect(service.createPath(req, { remotePath: 'client/remote' } as any)).rejects.toMatchObject(expected)\n })\n\n it('should create path and return id and permissions, overriding remotePath and permissions', async () => {\n const req = baseReq()\n ;(isPathExists as jest.Mock).mockResolvedValue(true)\n ;(isPathIsDir as jest.Mock).mockResolvedValue(true)\n ;(getEnvPermissions as jest.Mock).mockReturnValue('env-perms')\n syncQueries.getClient.mockResolvedValue({ id: 'client-1' })\n // Spy on private getDBProps to simplify\n const getDBPropsSpy = jest.spyOn<any, any>(service as any, 'getDBProps').mockResolvedValue({ ownerId: 1 })\n syncQueries.createPath.mockResolvedValue(123)\n\n const res = await service.createPath(req, { remotePath: 'client/remote', permissions: 'client-perms' } as any)\n expect(res).toEqual({ id: 123, permissions: 'env-perms' })\n expect(syncQueries.createPath).toHaveBeenCalledWith(\n 'client-1',\n { ownerId: 1 },\n expect.objectContaining({ remotePath: 'SPACES/alias/sub', permissions: 'env-perms' })\n )\n\n getDBPropsSpy.mockRestore()\n })\n })\n\n describe('deletePath', () => {\n it.each([\n { user: { id: 1, clientId: undefined } as any, id: 10, status: HttpStatus.BAD_REQUEST, msg: 'Client id is missing' },\n { user: { id: 1, clientId: 'c1' } as any, id: 10, status: HttpStatus.FORBIDDEN }\n ])('should handle errors (status=$status)', async ({ user, id, status, msg }) => {\n if (status === HttpStatus.FORBIDDEN) syncQueries.clientExistsForOwner.mockResolvedValue(false)\n await expect(service.deletePath(user, id)).rejects.toMatchObject(msg ? { status, message: msg } : { status })\n })\n\n it('should catch errors from deletePath and throw BAD_REQUEST', async () => {\n const user: any = { id: 1, clientId: 'c1' }\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.deletePath.mockRejectedValue(new Error('db'))\n await expect(service.deletePath(user, 10)).rejects.toMatchObject({\n status: HttpStatus.BAD_REQUEST,\n message: 'Unable to remove path'\n })\n expect(syncQueries.deletePath).toHaveBeenCalledWith('c1', 10)\n })\n\n it('should delete path successfully when allowed', async () => {\n const user: any = { id: 1, clientId: undefined }\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.deletePath.mockResolvedValue(undefined)\n await expect(service.deletePath(user, 10, 'cX')).resolves.toBeUndefined()\n expect(syncQueries.deletePath).toHaveBeenCalledWith('cX', 10)\n })\n })\n\n describe('updatePath', () => {\n it('should throw FORBIDDEN when client does not belong to owner', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(false)\n await expect(service.updatePath({ id: 1 } as any, 'c1', 5, {} as any)).rejects.toMatchObject({\n status: HttpStatus.FORBIDDEN\n })\n })\n\n it('should throw NOT_FOUND when path settings do not exist', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPathSettings.mockResolvedValue(null)\n await expect(service.updatePath({ id: 1 } as any, 'c1', 5, {} as any)).rejects.toMatchObject({\n status: HttpStatus.NOT_FOUND,\n message: 'Sync path not found'\n })\n })\n\n it('should update path settings, set new timestamp, clear cache and return updated settings', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPathSettings.mockResolvedValue({ id: 5, timestamp: 500, lastSync: 1, remotePath: '/a', permissions: 'p' })\n syncQueries.updatePathSettings.mockResolvedValue(undefined)\n ;(currentTimeStamp as jest.Mock).mockReturnValue(4242)\n\n const out = await service.updatePath({ id: 1 } as any, 'c1', 5, { id: 666, lastSync: 3, permissions: 'new' } as any)\n expect(syncQueries.updatePathSettings).toHaveBeenCalledWith(\n 'c1',\n 5,\n expect.objectContaining({ id: 5, lastSync: 3, timestamp: 4242, permissions: 'new' })\n )\n expect(syncQueries.clearCachePathSettings).toHaveBeenCalledWith('c1', 5)\n expect(out).toEqual(expect.objectContaining({ id: 5, lastSync: 3, timestamp: 4242, permissions: 'new' }))\n })\n\n it('should clear cache and throw INTERNAL_SERVER_ERROR when update fails', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPathSettings.mockResolvedValue({ id: 5, timestamp: 500, lastSync: 1 })\n syncQueries.updatePathSettings.mockRejectedValue(new Error('db'))\n await expect(service.updatePath({ id: 1 } as any, 'c1', 5, {} as any)).rejects.toMatchObject({\n status: HttpStatus.INTERNAL_SERVER_ERROR,\n message: 'Unable to update path'\n })\n expect(syncQueries.clearCachePathSettings).toHaveBeenCalledWith('c1', 5)\n })\n })\n\n describe('updatePaths', () => {\n beforeEach(() => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'p' })\n })\n\n it('should throw when client id is missing', async () => {\n await expect(service.updatePaths(userWith(undefined) as any, [])).rejects.toMatchObject({\n status: HttpStatus.BAD_REQUEST,\n message: 'Client id is missing'\n })\n })\n\n it('should throw FORBIDDEN when client does not belong to owner', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(false)\n await expect(service.updatePaths(userWith('c1') as any, [])).rejects.toMatchObject({\n status: HttpStatus.FORBIDDEN\n })\n })\n\n it('should mark client paths as deleted and notify when no corresponding server paths (server remotePath undefined)', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 2, settings: { timestamp: 1, lastSync: 1 }, remotePath: undefined }])\n const clientPaths = [{ id: 1, remotePath: 'SPACES/a', timestamp: 1, lastSync: 1, permissions: 'p' } as any]\n\n const res = await service.updatePaths(userWith('c1') as any, clientPaths)\n expect(res.delete).toEqual([1])\n expect(notificationsManager.create).toHaveBeenCalledTimes(1)\n })\n\n it('should propagate spaceEnv errors as BAD_REQUEST', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 1, settings: { timestamp: 1, lastSync: 1 }, remotePath: 'SPACES/x' }])\n spacesManager.spaceEnv.mockRejectedValue(new Error('boom'))\n await expect(\n service.updatePaths(userWith('c1') as any, [{ id: 1, remotePath: 'SPACES/x', timestamp: 1, lastSync: 1, permissions: 'p' } as any])\n ).rejects.toMatchObject({\n status: HttpStatus.BAD_REQUEST,\n message: 'boom'\n })\n })\n\n it('should skip server path when space is null and mark client item as deleted', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 2, settings: { timestamp: 1, lastSync: 1 }, remotePath: 'SPACES/x' }])\n spacesManager.spaceEnv.mockResolvedValue(null)\n const res = await service.updatePaths(userWith('c1') as any, [\n { id: 2, remotePath: 'SPACES/x', timestamp: 1, lastSync: 1, permissions: 'p' } as any\n ])\n expect(res.delete).toEqual([2])\n expect(notificationsManager.create).toHaveBeenCalledTimes(1)\n })\n\n it('should add server-only path to client with server permissions', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 3, settings: { timestamp: 1, lastSync: 1 }, remotePath: 'SPACES/x' }])\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'perm-xyz' })\n const res = await service.updatePaths(userWith('c1') as any, [])\n expect(res.add).toHaveLength(1)\n expect(res.add[0]).toEqual(expect.objectContaining({ id: 3, remotePath: 'SPACES/x', permissions: 'perm-xyz' }))\n })\n\n it('should update server settings from client when client is newer (no hasUpdates)', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 5, settings: { timestamp: 1, lastSync: 1, foo: 'server' }, remotePath: 'SPACES/x' }])\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'p' })\n\n const client = [{ id: 5, timestamp: 10, lastSync: 2, remotePath: 'SPACES/x', permissions: 'p', foo: 'client' } as any]\n await service.updatePaths(userWith('c1') as any, client)\n\n expect(syncQueries.updatePathSettings).toHaveBeenCalledWith('c1', 5, expect.objectContaining({ foo: 'client', lastSync: 2 }))\n // No client update instructions because hasUpdates=false and serverNewer=false\n })\n\n it('should push server-newer updates to client and also remotePath/permissions corrections', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 7, settings: { timestamp: 20, lastSync: 5, srv: true }, remotePath: 'SPACES/correct' }])\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'permX' })\n\n const client = [{ id: 7, timestamp: 10, lastSync: 5, remotePath: 'SPACES/wrong', permissions: 'old' } as any]\n const res = await service.updatePaths(userWith('c1') as any, client)\n\n // Should have two client updates: one full server settings + corrections, and one corrections-only\n expect(res.update).toEqual(\n expect.arrayContaining([\n expect.objectContaining({ id: 7, srv: true, remotePath: 'SPACES/correct', permissions: 'permX' }),\n expect.objectContaining({ id: 7, remotePath: 'SPACES/correct', permissions: 'permX' })\n ])\n )\n expect(syncQueries.updatePathSettings).toHaveBeenCalledWith('c1', 7, expect.objectContaining({ lastSync: 5 }))\n // clear cache called for each update instruction\n expect(syncQueries.clearCachePathSettings).toHaveBeenCalledTimes(res.update.length)\n for (const u of res.update) {\n expect(syncQueries.clearCachePathSettings).toHaveBeenCalledWith('c1', u.id)\n }\n })\n\n it('should trigger update when lastSync differs even if timestamps and settings match', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 9, settings: { timestamp: 10, lastSync: 1, flag: 'S' }, remotePath: 'SPACES/x' }])\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'p' })\n\n const client = [{ id: 9, timestamp: 10, lastSync: 2, remotePath: 'SPACES/x', permissions: 'p', flag: 'S' } as any]\n await service.updatePaths(userWith('c1') as any, client)\n expect(syncQueries.updatePathSettings).toHaveBeenCalledWith('c1', 9, expect.objectContaining({ lastSync: 2 }))\n })\n\n it('should perform no changes when client and server are identical (no-op branch)', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 12, settings: { timestamp: 5, lastSync: 7, flag: 'A' }, remotePath: 'SPACES/x' }])\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'p' })\n\n const client = [{ id: 12, timestamp: 5, lastSync: 7, remotePath: 'SPACES/x', permissions: 'p', flag: 'A' } as any]\n const res = await service.updatePaths(userWith('c1') as any, client)\n\n expect(res).toEqual({ add: [], update: [], delete: [] })\n expect(syncQueries.updatePathSettings).not.toHaveBeenCalled()\n })\n\n it('should correct client info while keeping server settings when timestamps are equal (hasUpdates=true)', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n // Server has srv='S', client has wrong remotePath/permissions and extra clientOnly flag\n syncQueries.getPaths.mockResolvedValue([{ id: 13, settings: { timestamp: 5, lastSync: 1, srv: 'S' }, remotePath: 'SPACES/correct' }])\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'permX' })\n\n const client = [{ id: 13, timestamp: 5, lastSync: 1, remotePath: 'SPACES/wrong', permissions: 'old', clientOnly: 'C' } as any]\n const res = await service.updatePaths(userWith('c1') as any, client)\n\n // Server uses its own settings base (srv: 'S') with corrections applied\n expect(syncQueries.updatePathSettings).toHaveBeenCalledWith(\n 'c1',\n 13,\n expect.objectContaining({ srv: 'S', lastSync: 1, remotePath: 'SPACES/correct', permissions: 'permX' })\n )\n // Client should receive corrections for remotePath and permissions\n expect(res.update).toEqual(expect.arrayContaining([expect.objectContaining({ id: 13, remotePath: 'SPACES/correct', permissions: 'permX' })]))\n })\n\n it('should log error when updatePathSettings rejects inside updatePaths', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([{ id: 11, settings: { timestamp: 1, lastSync: 1 }, remotePath: 'SPACES/x' }])\n spacesManager.spaceEnv.mockResolvedValue({ envPermissions: 'p' })\n // Force client newer to trigger updatePathSettings\n const client = [{ id: 11, timestamp: 10, lastSync: 2, remotePath: 'SPACES/x', permissions: 'p' } as any]\n syncQueries.updatePathSettings.mockRejectedValueOnce(new Error('db-fail'))\n const loggerSpy = jest.spyOn((service as any).logger, 'error').mockImplementation(() => undefined)\n\n await service.updatePaths(userWith('c1') as any, client)\n // wait for microtasks to ensure .catch executed\n await flush()\n\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls.some(([msg]) => String(msg).includes('updatePaths'))).toBe(true)\n })\n\n it('should catch notify failure at updatePaths level when building notification fails', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n // No server paths: will mark client path as deleted and call notify\n syncQueries.getPaths.mockResolvedValue([])\n const loggerSpy = jest.spyOn((service as any).logger, 'error').mockImplementation(() => undefined)\n // BAD first segment to make notify fail while building URL (before notificationsManager.create)\n const client = [{ id: 1, remotePath: 'BAD/a/b', timestamp: 1, lastSync: 1, permissions: 'p' } as any]\n\n const res = await service.updatePaths(userWith('c1') as any, client)\n await flush()\n\n expect(res.delete).toEqual([1])\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls.some(([msg]) => String(msg).includes('updatePaths'))).toBe(true)\n // create not called because we failed before reaching it\n expect(notificationsManager.create).not.toHaveBeenCalled()\n })\n\n it('should catch error inside notify when notifications creation fails', async () => {\n syncQueries.clientExistsForOwner.mockResolvedValue(true)\n syncQueries.getPaths.mockResolvedValue([])\n // Valid remotePath to build URL correctly\n const client = [{ id: 2, remotePath: 'SPACES/a', timestamp: 1, lastSync: 1, permissions: 'p' } as any]\n const loggerSpy = jest.spyOn((service as any).logger, 'error').mockImplementation(() => undefined)\n notificationsManager.create.mockRejectedValueOnce(new Error('notify-fail'))\n\n const res = await service.updatePaths(userWith('c1') as any, client)\n await flush()\n\n expect(res.delete).toEqual([2])\n expect(loggerSpy).toHaveBeenCalled()\n // error comes from notify() catch\n expect(loggerSpy.mock.calls.some(([msg]) => String(msg).includes('notify'))).toBe(true)\n })\n })\n\n describe('getDBProps (private) branches', () => {\n it('should throw BAD_REQUEST for shares list selection', async () => {\n await expect((service as any).getDBProps({ inSharesList: true } as any)).rejects.toMatchObject({\n status: HttpStatus.BAD_REQUEST,\n message: 'Sync all shares is not supported, you must select a sub-directory'\n })\n })\n\n it('should return ownerId only for personal space at root', async () => {\n const res = await (service as any).getDBProps({\n inSharesList: false,\n inPersonalSpace: true,\n paths: [],\n dbFile: { ownerId: 42 }\n } as any)\n expect(res).toEqual({ ownerId: 42 })\n })\n\n it('should return ownerId and fileId for personal space subdir', async () => {\n const getOrCreateFileIdSpy = jest.spyOn<any, any>(service as any, 'getOrCreateFileId').mockResolvedValue(77)\n const res = await (service as any).getDBProps({\n inPersonalSpace: true,\n paths: ['sub'],\n dbFile: { ownerId: 42 }\n } as any)\n expect(res).toEqual({ ownerId: 42, fileId: 77 })\n getOrCreateFileIdSpy.mockRestore()\n })\n\n it('should throw BAD_REQUEST for whole files repository without alias', async () => {\n await expect((service as any).getDBProps({ inFilesRepository: true, root: { alias: null }, paths: [] } as any)).rejects.toMatchObject({\n status: HttpStatus.BAD_REQUEST,\n message: 'Sync all space is not yet supported, you must select a sub-directory'\n })\n })\n\n it('should return spaceId and rootId for files repository root selection', async () => {\n const res = await (service as any).getDBProps({\n inFilesRepository: true,\n id: 5,\n root: { id: 3, alias: 'x' },\n paths: []\n } as any)\n expect(res).toEqual({ spaceId: 5, spaceRootId: 3 })\n })\n\n it('should return spaceId, rootId and fileId for files repository subdir or null root', async () => {\n const getOrCreateFileIdSpy = jest.spyOn<any, any>(service as any, 'getOrCreateFileId').mockResolvedValue(88)\n const res = await (service as any).getDBProps({\n inFilesRepository: true,\n id: 5,\n root: { id: 3, alias: 'x' },\n paths: ['sub']\n } as any)\n expect(res).toEqual({ spaceId: 5, spaceRootId: 3, fileId: 88 })\n getOrCreateFileIdSpy.mockRestore()\n })\n\n it('should return spaceId and null spaceRootId plus fileId when files repository root has no id', async () => {\n const getOrCreateFileIdSpy = jest.spyOn<any, any>(service as any, 'getOrCreateFileId').mockResolvedValue(90)\n const res = await (service as any).getDBProps({\n inFilesRepository: true,\n id: 6,\n root: { id: undefined, alias: 'x' },\n paths: []\n } as any)\n expect(res).toEqual({ spaceId: 6, spaceRootId: null, fileId: 90 })\n getOrCreateFileIdSpy.mockRestore()\n })\n\n it('should return shareId only for shares repository root', async () => {\n const res = await (service as any).getDBProps({\n inSharesList: false,\n inPersonalSpace: false,\n inFilesRepository: false,\n inSharesRepository: true,\n id: 9,\n paths: []\n } as any)\n expect(res).toEqual({ shareId: 9 })\n })\n\n it('should return shareId and fileId for shares repository subdir', async () => {\n const getOrCreateFileIdSpy = jest.spyOn<any, any>(service as any, 'getOrCreateFileId').mockResolvedValue(55)\n const res = await (service as any).getDBProps({\n inSharesList: false,\n inPersonalSpace: false,\n inFilesRepository: false,\n inSharesRepository: true,\n id: 9,\n paths: ['sub']\n } as any)\n expect(res).toEqual({ shareId: 9, fileId: 55 })\n getOrCreateFileIdSpy.mockRestore()\n })\n\n it('should return undefined when no space flags match (no branch taken)', async () => {\n const res = await (service as any).getDBProps({\n inSharesList: false,\n inPersonalSpace: false,\n inFilesRepository: false,\n inSharesRepository: false,\n paths: []\n } as any)\n expect(res).toBeUndefined()\n })\n })\n\n describe('getOrCreateFileId (private) branches', () => {\n it('should return existing file id without creation', async () => {\n ;(getProps as jest.Mock).mockResolvedValue({ name: 'file' })\n filesQueries.getSpaceFileId.mockResolvedValue(101)\n const id = await (service as any).getOrCreateFileId({\n realPath: '/rp',\n dbFile: { path: '.' }\n })\n expect(id).toBe(101)\n expect(filesQueries.getOrCreateSpaceFile).not.toHaveBeenCalled()\n })\n\n it('should create file when not exists and return its id', async () => {\n ;(getProps as jest.Mock).mockResolvedValue({ id: 999, name: 'file' })\n filesQueries.getSpaceFileId.mockResolvedValue(0)\n filesQueries.getOrCreateSpaceFile.mockResolvedValue(202)\n const id = await (service as any).getOrCreateFileId({\n realPath: '/rp',\n dbFile: { path: '.' }\n })\n expect(id).toBe(202)\n expect(filesQueries.getOrCreateSpaceFile).toHaveBeenCalledWith(0, expect.objectContaining({ id: undefined }), { path: '.' })\n })\n })\n})\n"],"names":["jest","mock","currentTimeStamp","fn","isPathExists","isPathIsDir","getProps","sanitizePath","p","getEnvPermissions","SYNC_PATH_REPOSITORY","SPACES","PERSONAL","SHARES","NOTIFICATION_APP","SYNC","NOTIFICATION_APP_EVENT","DELETE","CREATE","UPDATE","describe","SyncPathsManager","name","service","contextManager","spacesManager","usersQueries","filesQueries","notificationsManager","syncQueries","userWith","clientId","id","flush","Promise","r","setImmediate","beforeEach","headerOriginUrl","spaceEnv","getSpaceFileId","getOrCreateSpaceFile","create","mockResolvedValue","undefined","getClient","clientExistsForOwner","createPath","deletePath","getPaths","getPathSettings","updatePathSettings","clearCachePathSettings","mockReset","mockReturnValue","module","Test","createTestingModule","providers","provide","ContextManager","useValue","SpacesManager","UsersQueries","FilesQueries","NotificationsManager","SyncQueries","compile","useLogger","get","it","expect","toBeDefined","baseReq","user","params","space","realPath","quotaIsExceeded","root","alias","inFilesRepository","paths","dbFile","ownerId","path","req","remotePath","rejects","toMatchObject","status","HttpStatus","BAD_REQUEST","message","INSUFFICIENT_STORAGE","each","title","setup","expected","NOT_FOUND","getDBPropsSpy","spyOn","res","permissions","toEqual","toHaveBeenCalledWith","objectContaining","mockRestore","msg","FORBIDDEN","mockRejectedValue","Error","resolves","toBeUndefined","updatePath","timestamp","lastSync","out","INTERNAL_SERVER_ERROR","envPermissions","updatePaths","settings","clientPaths","delete","toHaveBeenCalledTimes","add","toHaveLength","foo","client","srv","update","arrayContaining","length","u","flag","not","toHaveBeenCalled","clientOnly","mockRejectedValueOnce","loggerSpy","logger","mockImplementation","calls","some","String","includes","toBe","getDBProps","inSharesList","inPersonalSpace","getOrCreateFileIdSpy","fileId","spaceId","spaceRootId","inSharesRepository","shareId","getOrCreateFileId"],"mappings":"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"}
@@ -52,7 +52,7 @@ _export(exports, {
52
52
  });
53
53
  const USER_PASSWORD_MIN_LENGTH = 8;
54
54
  const USER_MAX_PASSWORD_ATTEMPTS = 10;
55
- const USER_LOGIN_VALIDATION = /^[a-zA-Z0-9\-\\._]{2,255}$/;
55
+ const USER_LOGIN_VALIDATION = /^(?! )(?!.* $)[a-zA-Z0-9@\-\\._ ]{2,255}$/;
56
56
  const USER_PATH = {
57
57
  TMP: 'tmp',
58
58
  TASKS: 'tasks'
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/users/constants/user.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 USER_PASSWORD_MIN_LENGTH = 8\nexport const USER_MAX_PASSWORD_ATTEMPTS = 10\nexport const USER_LOGIN_VALIDATION = /^[a-zA-Z0-9\\-\\\\._]{2,255}$/\n\nexport const USER_PATH = {\n TMP: 'tmp',\n TASKS: 'tasks'\n} as const\n\nexport enum USER_ROLE {\n ADMINISTRATOR,\n USER,\n GUEST,\n LINK\n}\n\nexport enum USER_GROUP_ROLE {\n MEMBER,\n MANAGER\n}\n\nexport const USER_PERMS_SEP = ','\n\nexport enum USER_PERMISSION {\n PERSONAL_SPACE = 'personal_space',\n SPACES = 'spaces_access',\n SPACES_ADMIN = 'spaces_admin',\n SHARES = 'shares_access',\n SHARES_ADMIN = 'shares_admin',\n GUESTS_ADMIN = 'guests_admin',\n PERSONAL_GROUPS_ADMIN = 'personal_groups_admin',\n DESKTOP_APP = 'desktop_app_access',\n DESKTOP_APP_SYNC = 'desktop_app_sync',\n WEBDAV = 'webdav_access'\n}\n\nexport enum GUEST_PERMISSION {\n SPACES = USER_PERMISSION.SPACES,\n SHARES = USER_PERMISSION.SHARES,\n WEBDAV = USER_PERMISSION.WEBDAV\n}\n\nexport enum USER_ONLINE_STATUS {\n AVAILABLE,\n BUSY,\n ABSENT,\n OFFLINE\n}\n\nexport enum USER_NOTIFICATION {\n APPLICATION,\n APPLICATION_EMAIL\n}\n\nexport const USER_SECRET = {\n TWO_FA_SECRET: 'twoFaSecret',\n RECOVERY_CODES: 'recoveryCodes',\n APP_PASSWORDS: 'appPasswords'\n} as const\n"],"names":["GUEST_PERMISSION","USER_GROUP_ROLE","USER_LOGIN_VALIDATION","USER_MAX_PASSWORD_ATTEMPTS","USER_NOTIFICATION","USER_ONLINE_STATUS","USER_PASSWORD_MIN_LENGTH","USER_PATH","USER_PERMISSION","USER_PERMS_SEP","USER_ROLE","USER_SECRET","TMP","TASKS","TWO_FA_SECRET","RECOVERY_CODES","APP_PASSWORDS"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QAsCWA;eAAAA;;QApBAC;eAAAA;;QAdCC;eAAAA;;QADAC;eAAAA;;QAgDDC;eAAAA;;QAPAC;eAAAA;;QA1CCC;eAAAA;;QAIAC;eAAAA;;QAmBDC;eAAAA;;QAFCC;eAAAA;;QAZDC;eAAAA;;QA6CCC;eAAAA;;;AAtDN,MAAML,2BAA2B;AACjC,MAAMH,6BAA6B;AACnC,MAAMD,wBAAwB;AAE9B,MAAMK,YAAY;IACvBK,KAAK;IACLC,OAAO;AACT;AAEO,IAAA,AAAKH,mCAAAA;;;;;WAAAA;;AAOL,IAAA,AAAKT,yCAAAA;;;WAAAA;;AAKL,MAAMQ,iBAAiB;AAEvB,IAAA,AAAKD,yCAAAA;;;;;;;;;;;WAAAA;;AAaL,IAAA,AAAKR,0CAAAA;;;;WAAAA;;AAML,IAAA,AAAKK,4CAAAA;;;;;WAAAA;;AAOL,IAAA,AAAKD,2CAAAA;;;WAAAA;;AAKL,MAAMO,cAAc;IACzBG,eAAe;IACfC,gBAAgB;IAChBC,eAAe;AACjB"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/users/constants/user.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 USER_PASSWORD_MIN_LENGTH = 8\nexport const USER_MAX_PASSWORD_ATTEMPTS = 10\nexport const USER_LOGIN_VALIDATION = /^(?! )(?!.* $)[a-zA-Z0-9@\\-\\\\._ ]{2,255}$/\n\nexport const USER_PATH = {\n TMP: 'tmp',\n TASKS: 'tasks'\n} as const\n\nexport enum USER_ROLE {\n ADMINISTRATOR,\n USER,\n GUEST,\n LINK\n}\n\nexport enum USER_GROUP_ROLE {\n MEMBER,\n MANAGER\n}\n\nexport const USER_PERMS_SEP = ','\n\nexport enum USER_PERMISSION {\n PERSONAL_SPACE = 'personal_space',\n SPACES = 'spaces_access',\n SPACES_ADMIN = 'spaces_admin',\n SHARES = 'shares_access',\n SHARES_ADMIN = 'shares_admin',\n GUESTS_ADMIN = 'guests_admin',\n PERSONAL_GROUPS_ADMIN = 'personal_groups_admin',\n DESKTOP_APP = 'desktop_app_access',\n DESKTOP_APP_SYNC = 'desktop_app_sync',\n WEBDAV = 'webdav_access'\n}\n\nexport enum GUEST_PERMISSION {\n SPACES = USER_PERMISSION.SPACES,\n SHARES = USER_PERMISSION.SHARES,\n WEBDAV = USER_PERMISSION.WEBDAV\n}\n\nexport enum USER_ONLINE_STATUS {\n AVAILABLE,\n BUSY,\n ABSENT,\n OFFLINE\n}\n\nexport enum USER_NOTIFICATION {\n APPLICATION,\n APPLICATION_EMAIL\n}\n\nexport const USER_SECRET = {\n TWO_FA_SECRET: 'twoFaSecret',\n RECOVERY_CODES: 'recoveryCodes',\n APP_PASSWORDS: 'appPasswords'\n} as const\n"],"names":["GUEST_PERMISSION","USER_GROUP_ROLE","USER_LOGIN_VALIDATION","USER_MAX_PASSWORD_ATTEMPTS","USER_NOTIFICATION","USER_ONLINE_STATUS","USER_PASSWORD_MIN_LENGTH","USER_PATH","USER_PERMISSION","USER_PERMS_SEP","USER_ROLE","USER_SECRET","TMP","TASKS","TWO_FA_SECRET","RECOVERY_CODES","APP_PASSWORDS"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QAsCWA;eAAAA;;QApBAC;eAAAA;;QAdCC;eAAAA;;QADAC;eAAAA;;QAgDDC;eAAAA;;QAPAC;eAAAA;;QA1CCC;eAAAA;;QAIAC;eAAAA;;QAmBDC;eAAAA;;QAFCC;eAAAA;;QAZDC;eAAAA;;QA6CCC;eAAAA;;;AAtDN,MAAML,2BAA2B;AACjC,MAAMH,6BAA6B;AACnC,MAAMD,wBAAwB;AAE9B,MAAMK,YAAY;IACvBK,KAAK;IACLC,OAAO;AACT;AAEO,IAAA,AAAKH,mCAAAA;;;;;WAAAA;;AAOL,IAAA,AAAKT,yCAAAA;;;WAAAA;;AAKL,MAAMQ,iBAAiB;AAEvB,IAAA,AAAKD,yCAAAA;;;;;;;;;;;WAAAA;;AAaL,IAAA,AAAKR,0CAAAA;;;;WAAAA;;AAML,IAAA,AAAKK,4CAAAA;;;;;WAAAA;;AAOL,IAAA,AAAKD,2CAAAA;;;WAAAA;;AAKL,MAAMO,cAAc;IACzBG,eAAe;IACfC,gBAAgB;IAChBC,eAAe;AACjB"}
@@ -92,6 +92,14 @@ let AdminUsersQueries = class AdminUsersQueries {
92
92
  }
93
93
  return rs;
94
94
  }
95
+ async listAdminsToNotify() {
96
+ return this.db.select({
97
+ id: _usersschema.users.id,
98
+ email: _usersschema.users.email,
99
+ language: _usersschema.users.language,
100
+ notification: _usersschema.users.notification
101
+ }).from(_usersschema.users).where((0, _drizzleorm.eq)(_usersschema.users.role, _user.USER_ROLE.ADMINISTRATOR));
102
+ }
95
103
  async groupFromId(groupId) {
96
104
  const groupParent = (0, _mysqlcore.alias)(_groupsschema.groups, 'groupParent');
97
105
  const [group] = await this.db.select({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/users/services/admin-users-queries.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 { Inject, Injectable, Logger } from '@nestjs/common'\nimport { and, count, countDistinct, eq, inArray, isNotNull, isNull, lte, SelectedFields, SQL, sql } from 'drizzle-orm'\nimport { alias, union } from 'drizzle-orm/mysql-core'\nimport { DB_TOKEN_PROVIDER } from '../../../infrastructure/database/constants'\nimport { DBSchema } from '../../../infrastructure/database/interfaces/database.interface'\nimport { concatDistinctObjectsInArray, dateTimeUTC, dbCheckAffectedRows, dbGetInsertedId } from '../../../infrastructure/database/utils'\nimport { GROUP_TYPE } from '../constants/group'\nimport { MEMBER_TYPE } from '../constants/member'\nimport { USER_GROUP_ROLE, USER_ROLE, USER_SECRET } from '../constants/user'\nimport { CreateOrUpdateGroupDto } from '../dto/create-or-update-group.dto'\nimport type { AdminGroup } from '../interfaces/admin-group.interface'\nimport type { AdminUser } from '../interfaces/admin-user.interface'\nimport { Member } from '../interfaces/member.interface'\nimport type { Group } from '../schemas/group.interface'\nimport { groups } from '../schemas/groups.schema'\nimport { UserGroup } from '../schemas/user-group.interface'\nimport { usersGroups } from '../schemas/users-groups.schema'\nimport { usersGuests } from '../schemas/users-guests.schema'\nimport { userFullNameSQL, users } from '../schemas/users.schema'\nimport { UsersQueries } from './users-queries.service'\n\n@Injectable()\nexport class AdminUsersQueries {\n private readonly logger = new Logger(AdminUsersQueries.name)\n\n constructor(\n @Inject(DB_TOKEN_PROVIDER) private readonly db: DBSchema,\n public readonly usersQueries: UsersQueries\n ) {}\n\n async listUsers(): Promise<AdminUser[]>\n async listUsers(userId: number): Promise<AdminUser>\n async listUsers(userId?: number): Promise<AdminUser | AdminUser[]> {\n const where: SQL[] = [lte(users.role, USER_ROLE.USER), ...(userId ? [eq(users.id, userId)] : [])]\n const q = this.db\n .select({\n id: users.id,\n login: users.login,\n email: users.email,\n role: users.role,\n fullName: userFullNameSQL(users),\n isActive: users.isActive,\n ...(userId && {\n firstName: users.firstName,\n lastName: users.lastName,\n notification: users.notification,\n permissions: users.permissions,\n twoFaEnabled:\n sql<boolean>`JSON_UNQUOTE(JSON_EXTRACT(${users.secrets}, ${sql.raw(`'$.${USER_SECRET.TWO_FA_SECRET}'`)})) IS NOT NULL`.mapWith(Boolean),\n groups: concatDistinctObjectsInArray(groups.id, {\n id: groups.id,\n name: groups.name,\n description: groups.description,\n type: sql.raw(`'${MEMBER_TYPE.GROUP}'`),\n permissions: groups.permissions,\n createdAt: dateTimeUTC(usersGroups.createdAt)\n } satisfies Record<keyof Pick<Member, 'id' | 'name' | 'description' | 'type' | 'permissions' | 'createdAt'>, any>)\n }),\n language: users.language,\n passwordAttempts: users.passwordAttempts,\n storageUsage: users.storageUsage,\n storageQuota: users.storageQuota,\n currentIp: users.currentIp,\n lastIp: users.lastIp,\n currentAccess: users.currentAccess,\n lastAccess: users.lastAccess,\n createdAt: users.createdAt\n } satisfies AdminUser | SelectedFields<any, any>)\n .from(users)\n if (userId) {\n q.leftJoin(usersGroups, eq(usersGroups.userId, users.id))\n q.leftJoin(groups, and(eq(groups.id, usersGroups.groupId), eq(groups.type, GROUP_TYPE.USER)))\n q.limit(1)\n }\n q.where(and(...where)).groupBy(users.id)\n const rs: AdminUser[] = await q\n if (userId) {\n return rs.length ? rs[0] : null\n }\n return rs\n }\n\n async groupFromId(groupId: number): Promise<AdminGroup> {\n const groupParent = alias(groups, 'groupParent')\n const [group] = await this.db\n .select({\n id: groups.id,\n name: groups.name,\n type: groups.type,\n description: groups.description,\n permissions: groups.permissions,\n visibility: groups.visibility,\n createdAt: groups.createdAt,\n modifiedAt: groups.modifiedAt,\n parent: { id: groupParent.id, name: groupParent.name }\n } satisfies AdminGroup | SelectedFields<any, any>)\n .from(groups)\n .leftJoin(groupParent, eq(groupParent.id, groups.parentId))\n .where(eq(groups.id, groupId))\n .limit(1)\n return group\n }\n\n async deleteUser(userId: number, userLogin: string): Promise<boolean> {\n return dbCheckAffectedRows(await this.db.delete(users).where(and(eq(users.id, userId), eq(users.login, userLogin))), 1, false)\n }\n\n async groupFromName(groupName: string): Promise<Pick<Group, 'id' | 'name' | 'type'>> {\n const [group] = await this.db\n .select({\n id: groups.id,\n name: groups.name,\n type: groups.type\n } satisfies Pick<Group, 'id' | 'name' | 'type'> | SelectedFields<any, any>)\n .from(groups)\n .where(eq(groups.name, groupName))\n .limit(1)\n return group\n }\n\n async browseRootGroupMembers(type: GROUP_TYPE = GROUP_TYPE.USER): Promise<Member[]> {\n const childGroups = alias(groups, 'childGroups')\n return this.db\n .select({\n id: groups.id,\n name: groups.name,\n description: groups.description,\n createdAt: groups.createdAt,\n modifiedAt: groups.modifiedAt,\n type: sql<MEMBER_TYPE>`IF(${groups.type} = ${GROUP_TYPE.USER}, ${MEMBER_TYPE.GROUP}, ${MEMBER_TYPE.PGROUP})`,\n counts: { users: count(usersGroups.userId), groups: countDistinct(childGroups.id) }\n } satisfies Member | SelectedFields<any, any>)\n .from(groups)\n .leftJoin(usersGroups, eq(usersGroups.groupId, groups.id))\n .leftJoin(childGroups, eq(childGroups.parentId, groups.id))\n .where(and(isNull(groups.parentId), eq(groups.type, type)))\n .groupBy(groups.id)\n }\n\n async browseGroupMembers(groupId: number, type: GROUP_TYPE = GROUP_TYPE.USER): Promise<Member[]> {\n const childGroups = alias(groups, 'childGroups')\n const childGroupMembers = alias(usersGroups, 'childGroupMembers')\n const subChildGroups = alias(groups, 'subChildGroups')\n const userMembers = this.db\n .select({\n id: users.id,\n login: users.login,\n name: userFullNameSQL(users).as('name'),\n description: users.email,\n createdAt: usersGroups.createdAt,\n modifiedAt: sql<Date>`NULL`,\n type: sql<MEMBER_TYPE>`${MEMBER_TYPE.USER}`,\n groupRole: sql<USER_GROUP_ROLE>`${usersGroups.role}`.mapWith(Number),\n counts: { users: sql<number>`0`, groups: sql<number>`0` }\n } satisfies Member | SelectedFields<any, any>)\n .from(groups)\n .innerJoin(usersGroups, eq(usersGroups.groupId, groups.id))\n .leftJoin(users, eq(users.id, usersGroups.userId))\n .where(and(eq(groups.id, groupId), eq(groups.type, type), isNotNull(users.id)))\n .groupBy(users.id)\n if (type === GROUP_TYPE.PERSONAL) {\n return userMembers\n }\n const groupMembers: any = this.db\n .select({\n id: childGroups.id,\n login: sql`NULL`,\n name: childGroups.name,\n description: childGroups.description,\n createdAt: childGroups.createdAt,\n modifiedAt: childGroups.modifiedAt,\n type: sql<MEMBER_TYPE>`${MEMBER_TYPE.GROUP}`,\n groupRole: sql<USER_GROUP_ROLE>`null`,\n counts: { users: count(usersGroups.userId), groups: count(subChildGroups.id) }\n } satisfies Member | SelectedFields<any, any>)\n .from(groups)\n .innerJoin(childGroups, eq(childGroups.parentId, groups.id))\n .leftJoin(usersGroups, eq(usersGroups.groupId, childGroups.id))\n .leftJoin(childGroupMembers, eq(childGroupMembers.groupId, childGroups.id))\n .leftJoin(subChildGroups, eq(subChildGroups.parentId, childGroups.id))\n .where(and(eq(groups.id, groupId), eq(groups.type, type), isNotNull(childGroups.id)))\n .groupBy(childGroups.id)\n return union(userMembers, groupMembers)\n }\n\n async updateUserGroups(userId: number, groups: { add: number[]; delete: number[] }): Promise<void> {\n if (groups.add.length) {\n try {\n dbCheckAffectedRows(\n await this.db.insert(usersGroups).values(\n groups.add.map((gid: number) => ({\n userId: userId,\n groupId: gid\n }))\n ),\n groups.add.length\n )\n this.logger.log(`${this.updateUserGroups.name} - user (${userId}) groups ${JSON.stringify(groups.add)} was added`)\n this.usersQueries.clearWhiteListCaches([userId])\n } catch (e) {\n this.logger.error(`${this.updateUserGroups.name} - user (${userId}) groups ${JSON.stringify(groups.add)} was not added: ${e}`)\n throw new Error('User groups was not added')\n }\n }\n if (groups.delete.length) {\n try {\n dbCheckAffectedRows(\n await this.db.delete(usersGroups).where(and(eq(usersGroups.userId, userId), inArray(usersGroups.groupId, groups.delete))),\n groups.delete.length\n )\n this.logger.log(`${this.updateUserGroups.name} - user (${userId}) groups ${JSON.stringify(groups.delete)} was deleted`)\n this.usersQueries.clearWhiteListCaches([userId])\n } catch (e) {\n this.logger.error(`${this.updateUserGroups.name} - user (${userId}) groups ${JSON.stringify(groups.delete)} was not deleted: ${e}`)\n throw new Error('User groups was not deleted')\n }\n }\n }\n\n async createGroup(createGroupDto: CreateOrUpdateGroupDto): Promise<Group['id']> {\n return dbGetInsertedId(await this.db.insert(groups).values({ ...createGroupDto, type: GROUP_TYPE.USER } as Group))\n }\n\n async updateGroup(groupId: number, set: Partial<Record<keyof Group, any>>): Promise<boolean> {\n try {\n dbCheckAffectedRows(await this.db.update(groups).set(set).where(eq(groups.id, groupId)), 1)\n this.logger.log(`${this.updateGroup.name} - group (${groupId}) was updated : ${JSON.stringify(set)}`)\n return true\n } catch (e) {\n this.logger.error(`${this.updateGroup.name} - group (${groupId}) was not updated : ${JSON.stringify(set)} : ${e}`)\n return false\n }\n }\n\n async deleteGroup(groupId: number): Promise<boolean> {\n const [parent] = await this.db.select({ id: groups.parentId }).from(groups).where(eq(groups.id, groupId)).limit(1)\n const parentId = parent?.id\n if (parentId) {\n // attach child groups to current parent\n await this.db\n .update(groups)\n .set({ parentId: parentId } as Partial<Group>)\n .where(eq(groups.parentId, groupId))\n }\n return dbCheckAffectedRows(await this.db.delete(groups).where(eq(groups.id, groupId)).limit(1), 1, false)\n }\n\n async addUsersToGroup(groupId: number, userIds: number[], lowerOrEqualUserRole: USER_ROLE = USER_ROLE.GUEST): Promise<void> {\n const userIdsWithRequiredRole = await this.db\n .select({ id: users.id })\n .from(users)\n .where(and(inArray(users.id, userIds), lte(users.role, lowerOrEqualUserRole)))\n userIds = userIdsWithRequiredRole.map((u) => u.id)\n if (userIds.length === 0) {\n throw new Error('No users to add to group')\n }\n try {\n dbCheckAffectedRows(\n await this.db.insert(usersGroups).values(\n userIdsWithRequiredRole.map((u) => ({\n groupId: groupId,\n userId: u.id\n }))\n ),\n userIdsWithRequiredRole.length\n )\n this.logger.log(`${this.addUsersToGroup.name} - users (${userIds}) was added to group (${groupId})`)\n this.usersQueries.clearWhiteListCaches(userIds)\n } catch (e) {\n this.logger.error(`${this.addUsersToGroup.name} - unable to add users (${userIds}) to group (${groupId}) : ${e}`)\n throw new Error('Unable to add users to group')\n }\n }\n\n async updateUserFromGroup(groupId: number, userId: number, role: USER_GROUP_ROLE): Promise<void> {\n try {\n dbCheckAffectedRows(\n await this.db\n .update(usersGroups)\n .set({ role: role } as UserGroup)\n .where(and(eq(usersGroups.groupId, groupId), eq(usersGroups.userId, userId)))\n .limit(1),\n 1\n )\n this.logger.log(`${this.updateUserFromGroup.name} - user (${userId}) was updated on group (${groupId}) as ${USER_GROUP_ROLE[role]}`)\n } catch (e) {\n this.logger.error(\n `${this.updateUserFromGroup.name} - user (${userId}) was not updated on group (${groupId}) as ${USER_GROUP_ROLE[role]} : ${e}`\n )\n throw new Error('Unable to update user from group')\n }\n }\n\n async removeUserFromGroup(groupId: number, userId: number): Promise<void> {\n try {\n dbCheckAffectedRows(\n await this.db\n .delete(usersGroups)\n .where(and(eq(usersGroups.groupId, groupId), eq(usersGroups.userId, userId)))\n .limit(1),\n 1\n )\n this.logger.log(`${this.removeUserFromGroup.name} - user (${userId}) was removed from group (${groupId})`)\n this.usersQueries.clearWhiteListCaches([userId])\n } catch (e) {\n this.logger.error(`${this.removeUserFromGroup.name} - user (${userId}) or group (${groupId}) does not exist : ${e}`)\n throw new Error('Unable to remove user from group')\n }\n }\n\n async updateGuestManagers(guestId: number, managers: { add: number[]; delete: number[] }): Promise<void> {\n if (managers.add.length) {\n try {\n dbCheckAffectedRows(\n await this.db.insert(usersGuests).values(\n managers.add.map((uid: number) => ({\n userId: uid,\n guestId: guestId\n }))\n ),\n managers.add.length\n )\n this.logger.log(`${this.updateGuestManagers.name} - guest (${guestId}) managers ${JSON.stringify(managers.add)} was added`)\n } catch (e) {\n this.logger.error(`${this.updateGuestManagers.name} - guest (${guestId}) managers ${JSON.stringify(managers.add)} was not added: ${e}`)\n throw new Error('Guest managers was not added')\n }\n }\n if (managers.delete.length) {\n try {\n dbCheckAffectedRows(\n await this.db.delete(usersGuests).where(and(eq(usersGuests.guestId, guestId), inArray(usersGuests.userId, managers.delete))),\n managers.delete.length\n )\n this.logger.log(`${this.updateGuestManagers.name} - guest (${guestId}) managers ${JSON.stringify(managers.delete)} was deleted`)\n } catch (e) {\n this.logger.error(`${this.updateGuestManagers.name} - guest (${guestId}) managers ${JSON.stringify(managers.delete)} was not deleted: ${e}`)\n throw new Error('Guest managers was not deleted')\n }\n }\n }\n}\n"],"names":["AdminUsersQueries","listUsers","userId","where","lte","users","role","USER_ROLE","USER","eq","id","q","db","select","login","email","fullName","userFullNameSQL","isActive","firstName","lastName","notification","permissions","twoFaEnabled","sql","secrets","raw","USER_SECRET","TWO_FA_SECRET","mapWith","Boolean","groups","concatDistinctObjectsInArray","name","description","type","MEMBER_TYPE","GROUP","createdAt","dateTimeUTC","usersGroups","language","passwordAttempts","storageUsage","storageQuota","currentIp","lastIp","currentAccess","lastAccess","from","leftJoin","and","groupId","GROUP_TYPE","limit","groupBy","rs","length","groupFromId","groupParent","alias","group","visibility","modifiedAt","parent","parentId","deleteUser","userLogin","dbCheckAffectedRows","delete","groupFromName","groupName","browseRootGroupMembers","childGroups","PGROUP","counts","count","countDistinct","isNull","browseGroupMembers","childGroupMembers","subChildGroups","userMembers","as","groupRole","Number","innerJoin","isNotNull","PERSONAL","groupMembers","union","updateUserGroups","add","insert","values","map","gid","logger","log","JSON","stringify","usersQueries","clearWhiteListCaches","e","error","Error","inArray","createGroup","createGroupDto","dbGetInsertedId","updateGroup","set","update","deleteGroup","addUsersToGroup","userIds","lowerOrEqualUserRole","GUEST","userIdsWithRequiredRole","u","updateUserFromGroup","USER_GROUP_ROLE","removeUserFromGroup","updateGuestManagers","guestId","managers","usersGuests","uid","Logger"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/users/services/admin-users-queries.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 { Inject, Injectable, Logger } from '@nestjs/common'\nimport { and, count, countDistinct, eq, inArray, isNotNull, isNull, lte, SelectedFields, SQL, sql } from 'drizzle-orm'\nimport { alias, union } from 'drizzle-orm/mysql-core'\nimport { DB_TOKEN_PROVIDER } from '../../../infrastructure/database/constants'\nimport { DBSchema } from '../../../infrastructure/database/interfaces/database.interface'\nimport { concatDistinctObjectsInArray, dateTimeUTC, dbCheckAffectedRows, dbGetInsertedId } from '../../../infrastructure/database/utils'\nimport { UserMailNotification } from '../../notifications/interfaces/user-mail-notification.interface'\nimport { GROUP_TYPE } from '../constants/group'\nimport { MEMBER_TYPE } from '../constants/member'\nimport { USER_GROUP_ROLE, USER_ROLE, USER_SECRET } from '../constants/user'\nimport { CreateOrUpdateGroupDto } from '../dto/create-or-update-group.dto'\nimport type { AdminGroup } from '../interfaces/admin-group.interface'\nimport type { AdminUser } from '../interfaces/admin-user.interface'\nimport { Member } from '../interfaces/member.interface'\nimport type { Group } from '../schemas/group.interface'\nimport { groups } from '../schemas/groups.schema'\nimport { UserGroup } from '../schemas/user-group.interface'\nimport { usersGroups } from '../schemas/users-groups.schema'\nimport { usersGuests } from '../schemas/users-guests.schema'\nimport { userFullNameSQL, users } from '../schemas/users.schema'\nimport { UsersQueries } from './users-queries.service'\n\n@Injectable()\nexport class AdminUsersQueries {\n private readonly logger = new Logger(AdminUsersQueries.name)\n\n constructor(\n @Inject(DB_TOKEN_PROVIDER) private readonly db: DBSchema,\n public readonly usersQueries: UsersQueries\n ) {}\n\n async listUsers(): Promise<AdminUser[]>\n async listUsers(userId: number): Promise<AdminUser>\n async listUsers(userId?: number): Promise<AdminUser | AdminUser[]> {\n const where: SQL[] = [lte(users.role, USER_ROLE.USER), ...(userId ? [eq(users.id, userId)] : [])]\n const q = this.db\n .select({\n id: users.id,\n login: users.login,\n email: users.email,\n role: users.role,\n fullName: userFullNameSQL(users),\n isActive: users.isActive,\n ...(userId && {\n firstName: users.firstName,\n lastName: users.lastName,\n notification: users.notification,\n permissions: users.permissions,\n twoFaEnabled:\n sql<boolean>`JSON_UNQUOTE(JSON_EXTRACT(${users.secrets}, ${sql.raw(`'$.${USER_SECRET.TWO_FA_SECRET}'`)})) IS NOT NULL`.mapWith(Boolean),\n groups: concatDistinctObjectsInArray(groups.id, {\n id: groups.id,\n name: groups.name,\n description: groups.description,\n type: sql.raw(`'${MEMBER_TYPE.GROUP}'`),\n permissions: groups.permissions,\n createdAt: dateTimeUTC(usersGroups.createdAt)\n } satisfies Record<keyof Pick<Member, 'id' | 'name' | 'description' | 'type' | 'permissions' | 'createdAt'>, any>)\n }),\n language: users.language,\n passwordAttempts: users.passwordAttempts,\n storageUsage: users.storageUsage,\n storageQuota: users.storageQuota,\n currentIp: users.currentIp,\n lastIp: users.lastIp,\n currentAccess: users.currentAccess,\n lastAccess: users.lastAccess,\n createdAt: users.createdAt\n } satisfies AdminUser | SelectedFields<any, any>)\n .from(users)\n if (userId) {\n q.leftJoin(usersGroups, eq(usersGroups.userId, users.id))\n q.leftJoin(groups, and(eq(groups.id, usersGroups.groupId), eq(groups.type, GROUP_TYPE.USER)))\n q.limit(1)\n }\n q.where(and(...where)).groupBy(users.id)\n const rs: AdminUser[] = await q\n if (userId) {\n return rs.length ? rs[0] : null\n }\n return rs\n }\n\n async listAdminsToNotify(): Promise<UserMailNotification[]> {\n return this.db\n .select({ id: users.id, email: users.email, language: users.language, notification: users.notification })\n .from(users)\n .where(eq(users.role, USER_ROLE.ADMINISTRATOR))\n }\n\n async groupFromId(groupId: number): Promise<AdminGroup> {\n const groupParent = alias(groups, 'groupParent')\n const [group] = await this.db\n .select({\n id: groups.id,\n name: groups.name,\n type: groups.type,\n description: groups.description,\n permissions: groups.permissions,\n visibility: groups.visibility,\n createdAt: groups.createdAt,\n modifiedAt: groups.modifiedAt,\n parent: { id: groupParent.id, name: groupParent.name }\n } satisfies AdminGroup | SelectedFields<any, any>)\n .from(groups)\n .leftJoin(groupParent, eq(groupParent.id, groups.parentId))\n .where(eq(groups.id, groupId))\n .limit(1)\n return group\n }\n\n async deleteUser(userId: number, userLogin: string): Promise<boolean> {\n return dbCheckAffectedRows(await this.db.delete(users).where(and(eq(users.id, userId), eq(users.login, userLogin))), 1, false)\n }\n\n async groupFromName(groupName: string): Promise<Pick<Group, 'id' | 'name' | 'type'>> {\n const [group] = await this.db\n .select({\n id: groups.id,\n name: groups.name,\n type: groups.type\n } satisfies Pick<Group, 'id' | 'name' | 'type'> | SelectedFields<any, any>)\n .from(groups)\n .where(eq(groups.name, groupName))\n .limit(1)\n return group\n }\n\n async browseRootGroupMembers(type: GROUP_TYPE = GROUP_TYPE.USER): Promise<Member[]> {\n const childGroups = alias(groups, 'childGroups')\n return this.db\n .select({\n id: groups.id,\n name: groups.name,\n description: groups.description,\n createdAt: groups.createdAt,\n modifiedAt: groups.modifiedAt,\n type: sql<MEMBER_TYPE>`IF(${groups.type} = ${GROUP_TYPE.USER}, ${MEMBER_TYPE.GROUP}, ${MEMBER_TYPE.PGROUP})`,\n counts: { users: count(usersGroups.userId), groups: countDistinct(childGroups.id) }\n } satisfies Member | SelectedFields<any, any>)\n .from(groups)\n .leftJoin(usersGroups, eq(usersGroups.groupId, groups.id))\n .leftJoin(childGroups, eq(childGroups.parentId, groups.id))\n .where(and(isNull(groups.parentId), eq(groups.type, type)))\n .groupBy(groups.id)\n }\n\n async browseGroupMembers(groupId: number, type: GROUP_TYPE = GROUP_TYPE.USER): Promise<Member[]> {\n const childGroups = alias(groups, 'childGroups')\n const childGroupMembers = alias(usersGroups, 'childGroupMembers')\n const subChildGroups = alias(groups, 'subChildGroups')\n const userMembers = this.db\n .select({\n id: users.id,\n login: users.login,\n name: userFullNameSQL(users).as('name'),\n description: users.email,\n createdAt: usersGroups.createdAt,\n modifiedAt: sql<Date>`NULL`,\n type: sql<MEMBER_TYPE>`${MEMBER_TYPE.USER}`,\n groupRole: sql<USER_GROUP_ROLE>`${usersGroups.role}`.mapWith(Number),\n counts: { users: sql<number>`0`, groups: sql<number>`0` }\n } satisfies Member | SelectedFields<any, any>)\n .from(groups)\n .innerJoin(usersGroups, eq(usersGroups.groupId, groups.id))\n .leftJoin(users, eq(users.id, usersGroups.userId))\n .where(and(eq(groups.id, groupId), eq(groups.type, type), isNotNull(users.id)))\n .groupBy(users.id)\n if (type === GROUP_TYPE.PERSONAL) {\n return userMembers\n }\n const groupMembers: any = this.db\n .select({\n id: childGroups.id,\n login: sql`NULL`,\n name: childGroups.name,\n description: childGroups.description,\n createdAt: childGroups.createdAt,\n modifiedAt: childGroups.modifiedAt,\n type: sql<MEMBER_TYPE>`${MEMBER_TYPE.GROUP}`,\n groupRole: sql<USER_GROUP_ROLE>`null`,\n counts: { users: count(usersGroups.userId), groups: count(subChildGroups.id) }\n } satisfies Member | SelectedFields<any, any>)\n .from(groups)\n .innerJoin(childGroups, eq(childGroups.parentId, groups.id))\n .leftJoin(usersGroups, eq(usersGroups.groupId, childGroups.id))\n .leftJoin(childGroupMembers, eq(childGroupMembers.groupId, childGroups.id))\n .leftJoin(subChildGroups, eq(subChildGroups.parentId, childGroups.id))\n .where(and(eq(groups.id, groupId), eq(groups.type, type), isNotNull(childGroups.id)))\n .groupBy(childGroups.id)\n return union(userMembers, groupMembers)\n }\n\n async updateUserGroups(userId: number, groups: { add: number[]; delete: number[] }): Promise<void> {\n if (groups.add.length) {\n try {\n dbCheckAffectedRows(\n await this.db.insert(usersGroups).values(\n groups.add.map((gid: number) => ({\n userId: userId,\n groupId: gid\n }))\n ),\n groups.add.length\n )\n this.logger.log(`${this.updateUserGroups.name} - user (${userId}) groups ${JSON.stringify(groups.add)} was added`)\n this.usersQueries.clearWhiteListCaches([userId])\n } catch (e) {\n this.logger.error(`${this.updateUserGroups.name} - user (${userId}) groups ${JSON.stringify(groups.add)} was not added: ${e}`)\n throw new Error('User groups was not added')\n }\n }\n if (groups.delete.length) {\n try {\n dbCheckAffectedRows(\n await this.db.delete(usersGroups).where(and(eq(usersGroups.userId, userId), inArray(usersGroups.groupId, groups.delete))),\n groups.delete.length\n )\n this.logger.log(`${this.updateUserGroups.name} - user (${userId}) groups ${JSON.stringify(groups.delete)} was deleted`)\n this.usersQueries.clearWhiteListCaches([userId])\n } catch (e) {\n this.logger.error(`${this.updateUserGroups.name} - user (${userId}) groups ${JSON.stringify(groups.delete)} was not deleted: ${e}`)\n throw new Error('User groups was not deleted')\n }\n }\n }\n\n async createGroup(createGroupDto: CreateOrUpdateGroupDto): Promise<Group['id']> {\n return dbGetInsertedId(await this.db.insert(groups).values({ ...createGroupDto, type: GROUP_TYPE.USER } as Group))\n }\n\n async updateGroup(groupId: number, set: Partial<Record<keyof Group, any>>): Promise<boolean> {\n try {\n dbCheckAffectedRows(await this.db.update(groups).set(set).where(eq(groups.id, groupId)), 1)\n this.logger.log(`${this.updateGroup.name} - group (${groupId}) was updated : ${JSON.stringify(set)}`)\n return true\n } catch (e) {\n this.logger.error(`${this.updateGroup.name} - group (${groupId}) was not updated : ${JSON.stringify(set)} : ${e}`)\n return false\n }\n }\n\n async deleteGroup(groupId: number): Promise<boolean> {\n const [parent] = await this.db.select({ id: groups.parentId }).from(groups).where(eq(groups.id, groupId)).limit(1)\n const parentId = parent?.id\n if (parentId) {\n // attach child groups to current parent\n await this.db\n .update(groups)\n .set({ parentId: parentId } as Partial<Group>)\n .where(eq(groups.parentId, groupId))\n }\n return dbCheckAffectedRows(await this.db.delete(groups).where(eq(groups.id, groupId)).limit(1), 1, false)\n }\n\n async addUsersToGroup(groupId: number, userIds: number[], lowerOrEqualUserRole: USER_ROLE = USER_ROLE.GUEST): Promise<void> {\n const userIdsWithRequiredRole = await this.db\n .select({ id: users.id })\n .from(users)\n .where(and(inArray(users.id, userIds), lte(users.role, lowerOrEqualUserRole)))\n userIds = userIdsWithRequiredRole.map((u) => u.id)\n if (userIds.length === 0) {\n throw new Error('No users to add to group')\n }\n try {\n dbCheckAffectedRows(\n await this.db.insert(usersGroups).values(\n userIdsWithRequiredRole.map((u) => ({\n groupId: groupId,\n userId: u.id\n }))\n ),\n userIdsWithRequiredRole.length\n )\n this.logger.log(`${this.addUsersToGroup.name} - users (${userIds}) was added to group (${groupId})`)\n this.usersQueries.clearWhiteListCaches(userIds)\n } catch (e) {\n this.logger.error(`${this.addUsersToGroup.name} - unable to add users (${userIds}) to group (${groupId}) : ${e}`)\n throw new Error('Unable to add users to group')\n }\n }\n\n async updateUserFromGroup(groupId: number, userId: number, role: USER_GROUP_ROLE): Promise<void> {\n try {\n dbCheckAffectedRows(\n await this.db\n .update(usersGroups)\n .set({ role: role } as UserGroup)\n .where(and(eq(usersGroups.groupId, groupId), eq(usersGroups.userId, userId)))\n .limit(1),\n 1\n )\n this.logger.log(`${this.updateUserFromGroup.name} - user (${userId}) was updated on group (${groupId}) as ${USER_GROUP_ROLE[role]}`)\n } catch (e) {\n this.logger.error(\n `${this.updateUserFromGroup.name} - user (${userId}) was not updated on group (${groupId}) as ${USER_GROUP_ROLE[role]} : ${e}`\n )\n throw new Error('Unable to update user from group')\n }\n }\n\n async removeUserFromGroup(groupId: number, userId: number): Promise<void> {\n try {\n dbCheckAffectedRows(\n await this.db\n .delete(usersGroups)\n .where(and(eq(usersGroups.groupId, groupId), eq(usersGroups.userId, userId)))\n .limit(1),\n 1\n )\n this.logger.log(`${this.removeUserFromGroup.name} - user (${userId}) was removed from group (${groupId})`)\n this.usersQueries.clearWhiteListCaches([userId])\n } catch (e) {\n this.logger.error(`${this.removeUserFromGroup.name} - user (${userId}) or group (${groupId}) does not exist : ${e}`)\n throw new Error('Unable to remove user from group')\n }\n }\n\n async updateGuestManagers(guestId: number, managers: { add: number[]; delete: number[] }): Promise<void> {\n if (managers.add.length) {\n try {\n dbCheckAffectedRows(\n await this.db.insert(usersGuests).values(\n managers.add.map((uid: number) => ({\n userId: uid,\n guestId: guestId\n }))\n ),\n managers.add.length\n )\n this.logger.log(`${this.updateGuestManagers.name} - guest (${guestId}) managers ${JSON.stringify(managers.add)} was added`)\n } catch (e) {\n this.logger.error(`${this.updateGuestManagers.name} - guest (${guestId}) managers ${JSON.stringify(managers.add)} was not added: ${e}`)\n throw new Error('Guest managers was not added')\n }\n }\n if (managers.delete.length) {\n try {\n dbCheckAffectedRows(\n await this.db.delete(usersGuests).where(and(eq(usersGuests.guestId, guestId), inArray(usersGuests.userId, managers.delete))),\n managers.delete.length\n )\n this.logger.log(`${this.updateGuestManagers.name} - guest (${guestId}) managers ${JSON.stringify(managers.delete)} was deleted`)\n } catch (e) {\n this.logger.error(`${this.updateGuestManagers.name} - guest (${guestId}) managers ${JSON.stringify(managers.delete)} was not deleted: ${e}`)\n throw new Error('Guest managers was not deleted')\n }\n }\n }\n}\n"],"names":["AdminUsersQueries","listUsers","userId","where","lte","users","role","USER_ROLE","USER","eq","id","q","db","select","login","email","fullName","userFullNameSQL","isActive","firstName","lastName","notification","permissions","twoFaEnabled","sql","secrets","raw","USER_SECRET","TWO_FA_SECRET","mapWith","Boolean","groups","concatDistinctObjectsInArray","name","description","type","MEMBER_TYPE","GROUP","createdAt","dateTimeUTC","usersGroups","language","passwordAttempts","storageUsage","storageQuota","currentIp","lastIp","currentAccess","lastAccess","from","leftJoin","and","groupId","GROUP_TYPE","limit","groupBy","rs","length","listAdminsToNotify","ADMINISTRATOR","groupFromId","groupParent","alias","group","visibility","modifiedAt","parent","parentId","deleteUser","userLogin","dbCheckAffectedRows","delete","groupFromName","groupName","browseRootGroupMembers","childGroups","PGROUP","counts","count","countDistinct","isNull","browseGroupMembers","childGroupMembers","subChildGroups","userMembers","as","groupRole","Number","innerJoin","isNotNull","PERSONAL","groupMembers","union","updateUserGroups","add","insert","values","map","gid","logger","log","JSON","stringify","usersQueries","clearWhiteListCaches","e","error","Error","inArray","createGroup","createGroupDto","dbGetInsertedId","updateGroup","set","update","deleteGroup","addUsersToGroup","userIds","lowerOrEqualUserRole","GUEST","userIdsWithRequiredRole","u","updateUserFromGroup","USER_GROUP_ROLE","removeUserFromGroup","updateGuestManagers","guestId","managers","usersGuests","uid","Logger"],"mappings":"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"}