@sync-in/server 1.8.1 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (603) hide show
  1. package/CHANGELOG.md +56 -11
  2. package/environment/environment.dist.yaml +29 -26
  3. package/package.json +15 -15
  4. package/server/app.constants.js +9 -0
  5. package/server/app.constants.js.map +1 -1
  6. package/server/app.module.js +4 -0
  7. package/server/app.module.js.map +1 -1
  8. package/server/applications/admin/admin.module.js +6 -1
  9. package/server/applications/admin/admin.module.js.map +1 -1
  10. package/server/applications/{notifications/interfaces/user-mail-notification.js → admin/interfaces/check-update.interfaces.js} +1 -1
  11. package/server/applications/admin/interfaces/check-update.interfaces.js.map +1 -0
  12. package/server/applications/admin/services/admin-scheduler.service.js +53 -0
  13. package/server/applications/admin/services/admin-scheduler.service.js.map +1 -0
  14. package/server/applications/admin/services/admin.service.js +102 -0
  15. package/server/applications/admin/services/admin.service.js.map +1 -0
  16. package/server/applications/admin/services/admin.service.spec.js +46 -0
  17. package/server/applications/admin/services/admin.service.spec.js.map +1 -0
  18. package/server/applications/admin/utils/check-update.js +28 -0
  19. package/server/applications/admin/utils/check-update.js.map +1 -0
  20. package/server/applications/comments/services/comments-manager.service.js +1 -1
  21. package/server/applications/comments/services/comments-manager.service.js.map +1 -1
  22. package/server/applications/comments/services/comments-manager.service.spec.js +1 -1
  23. package/server/applications/comments/services/comments-manager.service.spec.js.map +1 -1
  24. package/server/applications/comments/services/comments-queries.service.js.map +1 -1
  25. package/server/applications/files/constants/cache.js +10 -1
  26. package/server/applications/files/constants/cache.js.map +1 -1
  27. package/server/applications/files/constants/only-office.js +0 -25
  28. package/server/applications/files/constants/only-office.js.map +1 -1
  29. package/server/applications/files/constants/operations.js +20 -3
  30. package/server/applications/files/constants/operations.js.map +1 -1
  31. package/server/applications/files/dto/file-operations.dto.js +7 -0
  32. package/server/applications/files/dto/file-operations.dto.js.map +1 -1
  33. package/server/applications/files/files-only-office.controller.js +3 -2
  34. package/server/applications/files/files-only-office.controller.js.map +1 -1
  35. package/server/applications/files/files-only-office.controller.spec.js +6 -5
  36. package/server/applications/files/files-only-office.controller.spec.js.map +1 -1
  37. package/server/applications/files/files.controller.js +88 -8
  38. package/server/applications/files/files.controller.js.map +1 -1
  39. package/server/applications/files/files.controller.spec.js +11 -4
  40. package/server/applications/files/files.controller.spec.js.map +1 -1
  41. package/server/applications/files/guards/files-only-office.guard.js +6 -0
  42. package/server/applications/files/guards/files-only-office.guard.js.map +1 -1
  43. package/server/applications/files/interfaces/file-db-props.interface.js.map +1 -1
  44. package/server/applications/files/interfaces/file-props.interface.js.map +1 -1
  45. package/server/applications/files/interfaces/only-office-config.interface.js.map +1 -1
  46. package/server/applications/files/services/files-content-manager.service.js +3 -3
  47. package/server/applications/files/services/files-content-manager.service.js.map +1 -1
  48. package/server/applications/files/services/files-lock-manager.service.js +61 -22
  49. package/server/applications/files/services/files-lock-manager.service.js.map +1 -1
  50. package/server/applications/files/services/files-manager.service.js +122 -24
  51. package/server/applications/files/services/files-manager.service.js.map +1 -1
  52. package/server/applications/files/services/files-manager.service.spec.js +15 -0
  53. package/server/applications/files/services/files-manager.service.spec.js.map +1 -1
  54. package/server/applications/files/services/files-methods.service.js +38 -8
  55. package/server/applications/files/services/files-methods.service.js.map +1 -1
  56. package/server/applications/files/services/files-only-office-manager.service.js +12 -12
  57. package/server/applications/files/services/files-only-office-manager.service.js.map +1 -1
  58. package/server/applications/files/services/files-parser.service.js +1 -1
  59. package/server/applications/files/services/files-parser.service.js.map +1 -1
  60. package/server/applications/files/services/files-queries.service.js +10 -0
  61. package/server/applications/files/services/files-queries.service.js.map +1 -1
  62. package/server/applications/files/utils/files.js +1 -1
  63. package/server/applications/files/utils/files.js.map +1 -1
  64. package/server/applications/files/utils/send-file.js +3 -2
  65. package/server/applications/files/utils/send-file.js.map +1 -1
  66. package/server/applications/links/services/links-queries.service.js +1 -1
  67. package/server/applications/links/services/links-queries.service.js.map +1 -1
  68. package/server/applications/notifications/constants/notifications.js +5 -1
  69. package/server/applications/notifications/constants/notifications.js.map +1 -1
  70. package/server/applications/notifications/i18n/de.js +8 -2
  71. package/server/applications/notifications/i18n/de.js.map +1 -1
  72. package/server/applications/notifications/i18n/es.js +8 -2
  73. package/server/applications/notifications/i18n/es.js.map +1 -1
  74. package/server/applications/notifications/i18n/fr.js +8 -2
  75. package/server/applications/notifications/i18n/fr.js.map +1 -1
  76. package/server/applications/notifications/i18n/hi.js +8 -2
  77. package/server/applications/notifications/i18n/hi.js.map +1 -1
  78. package/server/applications/notifications/i18n/it.js +8 -2
  79. package/server/applications/notifications/i18n/it.js.map +1 -1
  80. package/server/applications/notifications/i18n/ja.js +8 -2
  81. package/server/applications/notifications/i18n/ja.js.map +1 -1
  82. package/server/applications/notifications/i18n/ko.js +8 -2
  83. package/server/applications/notifications/i18n/ko.js.map +1 -1
  84. package/server/applications/notifications/i18n/pl.js +8 -2
  85. package/server/applications/notifications/i18n/pl.js.map +1 -1
  86. package/server/applications/notifications/i18n/pt.js +8 -2
  87. package/server/applications/notifications/i18n/pt.js.map +1 -1
  88. package/server/applications/notifications/i18n/pt_br.js +8 -2
  89. package/server/applications/notifications/i18n/pt_br.js.map +1 -1
  90. package/server/applications/notifications/i18n/ru.js +8 -2
  91. package/server/applications/notifications/i18n/ru.js.map +1 -1
  92. package/server/applications/notifications/i18n/tr.js +8 -2
  93. package/server/applications/notifications/i18n/tr.js.map +1 -1
  94. package/server/applications/notifications/i18n/zh.js +8 -2
  95. package/server/applications/notifications/i18n/zh.js.map +1 -1
  96. package/server/applications/notifications/interfaces/notification-properties.interface.js.map +1 -1
  97. package/server/applications/notifications/interfaces/user-mail-notification.interface.js +10 -0
  98. package/server/applications/notifications/interfaces/user-mail-notification.interface.js.map +1 -0
  99. package/server/applications/notifications/mails/models.js +38 -3
  100. package/server/applications/notifications/mails/models.js.map +1 -1
  101. package/server/applications/notifications/mails/templates.js +1 -1
  102. package/server/applications/notifications/mails/templates.js.map +1 -1
  103. package/server/applications/notifications/services/notifications-manager.service.js +8 -1
  104. package/server/applications/notifications/services/notifications-manager.service.js.map +1 -1
  105. package/server/applications/notifications/services/notifications-queries.service.js.map +1 -1
  106. package/server/applications/shares/services/shares-manager.service.js +17 -10
  107. package/server/applications/shares/services/shares-manager.service.js.map +1 -1
  108. package/server/applications/shares/services/shares-manager.service.spec.js +10 -3
  109. package/server/applications/shares/services/shares-manager.service.spec.js.map +1 -1
  110. package/server/applications/shares/services/shares-queries.service.js +11 -1
  111. package/server/applications/shares/services/shares-queries.service.js.map +1 -1
  112. package/server/applications/spaces/guards/space.guard.spec.js +2 -2
  113. package/server/applications/spaces/guards/space.guard.spec.js.map +1 -1
  114. package/server/applications/spaces/services/spaces-browser.service.js +31 -11
  115. package/server/applications/spaces/services/spaces-browser.service.js.map +1 -1
  116. package/server/applications/spaces/services/spaces-manager.service.js +2 -2
  117. package/server/applications/spaces/services/spaces-manager.service.js.map +1 -1
  118. package/server/applications/spaces/services/spaces-queries.service.js +6 -2
  119. package/server/applications/spaces/services/spaces-queries.service.js.map +1 -1
  120. package/server/applications/spaces/utils/permissions.js +2 -2
  121. package/server/applications/spaces/utils/permissions.js.map +1 -1
  122. package/server/applications/sync/services/sync-manager.service.js +1 -0
  123. package/server/applications/sync/services/sync-manager.service.js.map +1 -1
  124. package/server/applications/sync/services/sync-paths-manager.service.js +1 -1
  125. package/server/applications/sync/services/sync-paths-manager.service.js.map +1 -1
  126. package/server/applications/sync/services/sync-paths-manager.service.spec.js +1 -1
  127. package/server/applications/sync/services/sync-paths-manager.service.spec.js.map +1 -1
  128. package/server/applications/users/constants/user.js +1 -1
  129. package/server/applications/users/constants/user.js.map +1 -1
  130. package/server/applications/users/services/admin-users-queries.service.js +8 -0
  131. package/server/applications/users/services/admin-users-queries.service.js.map +1 -1
  132. package/server/applications/users/services/users-queries.service.js +67 -68
  133. package/server/applications/users/services/users-queries.service.js.map +1 -1
  134. package/server/applications/users/users.module.js +2 -1
  135. package/server/applications/users/users.module.js.map +1 -1
  136. package/server/applications/webdav/guards/webdav-protocol.guard.js +4 -4
  137. package/server/applications/webdav/guards/webdav-protocol.guard.js.map +1 -1
  138. package/server/applications/webdav/guards/webdav-protocol.guard.spec.js +6 -6
  139. package/server/applications/webdav/guards/webdav-protocol.guard.spec.js.map +1 -1
  140. package/server/applications/webdav/services/webdav-methods.service.js +3 -2
  141. package/server/applications/webdav/services/webdav-methods.service.js.map +1 -1
  142. package/server/applications/webdav/services/webdav-methods.service.spec.js +2 -2
  143. package/server/applications/webdav/services/webdav-methods.service.spec.js.map +1 -1
  144. package/server/authentication/constants/auth-ldap.js +2 -0
  145. package/server/authentication/constants/auth-ldap.js.map +1 -1
  146. package/server/authentication/services/auth-methods/auth-method-ldap.service.js +34 -21
  147. package/server/authentication/services/auth-methods/auth-method-ldap.service.js.map +1 -1
  148. package/server/common/functions.js +0 -8
  149. package/server/common/functions.js.map +1 -1
  150. package/server/common/image.js +1 -0
  151. package/server/common/image.js.map +1 -1
  152. package/server/common/shared.js +18 -1
  153. package/server/common/shared.js.map +1 -1
  154. package/server/infrastructure/context/services/context-manager.service.js +3 -0
  155. package/server/infrastructure/context/services/context-manager.service.js.map +1 -1
  156. package/server/infrastructure/websocket/adapters/cluster.adapter.js +4 -4
  157. package/server/infrastructure/websocket/adapters/cluster.adapter.js.map +1 -1
  158. package/static/3rdpartylicenses.txt +1393 -44
  159. package/static/assets/favicon.svg +2 -25
  160. package/static/assets/logo-dark.svg +2 -32
  161. package/static/assets/logo.svg +2 -32
  162. package/static/assets/mimes/application-sql.svg +29 -1
  163. package/static/assets/mimes/application-x-sql.svg +29 -0
  164. package/static/assets/mimes/image-bmp.svg +12 -0
  165. package/static/assets/pdfjs/build/pdf.mjs +4869 -4454
  166. package/static/assets/pdfjs/build/pdf.mjs.map +1 -1
  167. package/static/assets/pdfjs/build/pdf.sandbox.mjs +3 -3
  168. package/static/assets/pdfjs/build/pdf.sandbox.mjs.map +1 -1
  169. package/static/assets/pdfjs/build/pdf.worker.mjs +885 -596
  170. package/static/assets/pdfjs/build/pdf.worker.mjs.map +1 -1
  171. package/static/assets/pdfjs/version +1 -1
  172. package/static/assets/pdfjs/web/locale/be/viewer.ftl +40 -0
  173. package/static/assets/pdfjs/web/locale/bg/viewer.ftl +2 -0
  174. package/static/assets/pdfjs/web/locale/cs/viewer.ftl +41 -0
  175. package/static/assets/pdfjs/web/locale/cy/viewer.ftl +43 -0
  176. package/static/assets/pdfjs/web/locale/da/viewer.ftl +39 -0
  177. package/static/assets/pdfjs/web/locale/de/viewer.ftl +41 -0
  178. package/static/assets/pdfjs/web/locale/dsb/viewer.ftl +43 -0
  179. package/static/assets/pdfjs/web/locale/el/viewer.ftl +39 -0
  180. package/static/assets/pdfjs/web/locale/en-CA/viewer.ftl +35 -0
  181. package/static/assets/pdfjs/web/locale/en-GB/viewer.ftl +41 -0
  182. package/static/assets/pdfjs/web/locale/en-US/viewer.ftl +2 -2
  183. package/static/assets/pdfjs/web/locale/eo/viewer.ftl +39 -0
  184. package/static/assets/pdfjs/web/locale/es-AR/viewer.ftl +41 -0
  185. package/static/assets/pdfjs/web/locale/es-CL/viewer.ftl +39 -0
  186. package/static/assets/pdfjs/web/locale/es-ES/viewer.ftl +72 -0
  187. package/static/assets/pdfjs/web/locale/es-MX/viewer.ftl +120 -0
  188. package/static/assets/pdfjs/web/locale/eu/viewer.ftl +41 -0
  189. package/static/assets/pdfjs/web/locale/fi/viewer.ftl +41 -0
  190. package/static/assets/pdfjs/web/locale/fr/viewer.ftl +41 -0
  191. package/static/assets/pdfjs/web/locale/fur/viewer.ftl +77 -0
  192. package/static/assets/pdfjs/web/locale/fy-NL/viewer.ftl +41 -0
  193. package/static/assets/pdfjs/web/locale/gn/viewer.ftl +39 -0
  194. package/static/assets/pdfjs/web/locale/he/viewer.ftl +41 -0
  195. package/static/assets/pdfjs/web/locale/hsb/viewer.ftl +43 -0
  196. package/static/assets/pdfjs/web/locale/hu/viewer.ftl +41 -0
  197. package/static/assets/pdfjs/web/locale/hy-AM/viewer.ftl +1 -1
  198. package/static/assets/pdfjs/web/locale/ia/viewer.ftl +41 -0
  199. package/static/assets/pdfjs/web/locale/it/viewer.ftl +41 -0
  200. package/static/assets/pdfjs/web/locale/ja/viewer.ftl +32 -0
  201. package/static/assets/pdfjs/web/locale/ka/viewer.ftl +41 -0
  202. package/static/assets/pdfjs/web/locale/kab/viewer.ftl +73 -0
  203. package/static/assets/pdfjs/web/locale/kk/viewer.ftl +21 -0
  204. package/static/assets/pdfjs/web/locale/ko/viewer.ftl +38 -1
  205. package/static/assets/pdfjs/web/locale/nb-NO/viewer.ftl +39 -0
  206. package/static/assets/pdfjs/web/locale/nl/viewer.ftl +41 -0
  207. package/static/assets/pdfjs/web/locale/nn-NO/viewer.ftl +37 -0
  208. package/static/assets/pdfjs/web/locale/pa-IN/viewer.ftl +37 -0
  209. package/static/assets/pdfjs/web/locale/pl/viewer.ftl +39 -0
  210. package/static/assets/pdfjs/web/locale/pt-BR/viewer.ftl +39 -0
  211. package/static/assets/pdfjs/web/locale/rm/viewer.ftl +73 -0
  212. package/static/assets/pdfjs/web/locale/ro/viewer.ftl +41 -0
  213. package/static/assets/pdfjs/web/locale/ru/viewer.ftl +42 -0
  214. package/static/assets/pdfjs/web/locale/sc/viewer.ftl +6 -0
  215. package/static/assets/pdfjs/web/locale/sk/viewer.ftl +43 -0
  216. package/static/assets/pdfjs/web/locale/sl/viewer.ftl +42 -1
  217. package/static/assets/pdfjs/web/locale/sq/viewer.ftl +77 -0
  218. package/static/assets/pdfjs/web/locale/sv-SE/viewer.ftl +41 -0
  219. package/static/assets/pdfjs/web/locale/tg/viewer.ftl +39 -0
  220. package/static/assets/pdfjs/web/locale/th/viewer.ftl +35 -0
  221. package/static/assets/pdfjs/web/locale/tr/viewer.ftl +39 -0
  222. package/static/assets/pdfjs/web/locale/vi/viewer.ftl +42 -5
  223. package/static/assets/pdfjs/web/locale/zh-CN/viewer.ftl +35 -0
  224. package/static/assets/pdfjs/web/locale/zh-TW/viewer.ftl +37 -0
  225. package/static/assets/pdfjs/web/viewer.css +141 -110
  226. package/static/assets/pdfjs/web/viewer.html +7 -7
  227. package/static/assets/pdfjs/web/viewer.mjs +97 -14
  228. package/static/assets/pdfjs/web/viewer.mjs.map +1 -1
  229. package/static/chunk-22DWHRCL.js +1 -0
  230. package/static/chunk-23UUFZSR.js +1 -0
  231. package/static/{chunk-MTVSJTIW.js → chunk-24Q7OUU2.js} +1 -1
  232. package/static/chunk-25QTY2GI.js +1 -0
  233. package/static/chunk-2E7IJZLL.js +1 -0
  234. package/static/chunk-2FC5EKS5.js +1 -0
  235. package/static/chunk-2FOWUJQF.js +1 -0
  236. package/static/chunk-2XPHUNYN.js +1 -0
  237. package/static/chunk-32L7RG2G.js +1 -0
  238. package/static/chunk-3IISSX63.js +1 -0
  239. package/static/chunk-3OHSTP3R.js +1 -0
  240. package/static/chunk-42L6C5MT.js +1 -0
  241. package/static/chunk-4AGQL5GV.js +1 -0
  242. package/static/chunk-4BPSQMI2.js +1 -0
  243. package/static/chunk-4FDRWZWT.js +1 -0
  244. package/static/chunk-4FJUCMEG.js +1 -0
  245. package/static/chunk-4GCCF6PF.js +1 -0
  246. package/static/chunk-4ORP3SBY.js +1 -0
  247. package/static/chunk-4QBOHIC3.js +1 -0
  248. package/static/chunk-4YT6K5KY.js +1 -0
  249. package/static/chunk-556I6YIW.js +1 -0
  250. package/static/chunk-5DPIGJU4.js +1 -0
  251. package/static/chunk-5HNQLBSW.js +3 -0
  252. package/static/chunk-5IL7C45D.js +1 -0
  253. package/static/chunk-5KJXGMKR.js +1 -0
  254. package/static/chunk-5SPGSHKL.js +1 -0
  255. package/static/chunk-5WCQBTXW.js +1 -0
  256. package/static/chunk-5XUIPWOH.js +1 -0
  257. package/static/chunk-62WT7PI3.js +1 -0
  258. package/static/chunk-6F6OMQ5H.js +1 -0
  259. package/static/chunk-6I5BGQHT.js +1 -0
  260. package/static/chunk-6NOS45DG.js +1 -0
  261. package/static/chunk-6OKLPRCD.js +1 -0
  262. package/static/chunk-6VEJCG43.js +1 -0
  263. package/static/chunk-77SS36Z2.js +1 -0
  264. package/static/chunk-7AXEPO3G.js +1 -0
  265. package/static/chunk-7CFSJ4BO.js +1 -0
  266. package/static/chunk-7CKHC72R.js +1 -0
  267. package/static/chunk-7DUTYOJG.js +1 -0
  268. package/static/chunk-7HKFYRPF.js +1 -0
  269. package/static/chunk-7NZJZATZ.js +1 -0
  270. package/static/chunk-AADK5D2H.js +1 -0
  271. package/static/chunk-ACUF7IKP.js +1 -0
  272. package/static/chunk-AGREZPV4.js +1 -0
  273. package/static/chunk-ATBJWFA3.js +1 -0
  274. package/static/chunk-ATXLZN2B.js +1 -0
  275. package/static/chunk-AZ5TF5Y3.js +1 -0
  276. package/static/chunk-BBHYIURC.js +1 -0
  277. package/static/chunk-BHZEPHRI.js +13 -0
  278. package/static/chunk-BQZWSZNN.js +1 -0
  279. package/static/chunk-BSB4VROD.js +2 -0
  280. package/static/chunk-BYWSTP3P.js +1 -0
  281. package/static/chunk-C3AAEQKW.js +1 -0
  282. package/static/chunk-CCGGCHGN.js +1 -0
  283. package/static/chunk-CFTKW432.js +1 -0
  284. package/static/chunk-CNOVT6KU.js +1 -0
  285. package/static/chunk-D56H3XE2.js +1 -0
  286. package/static/chunk-DFOOSIIA.js +1 -0
  287. package/static/chunk-DHFQIFOF.js +1 -0
  288. package/static/{chunk-3GMLWAFZ.js → chunk-DIC2MVRI.js} +1 -1
  289. package/static/chunk-DJDRX53V.js +2 -0
  290. package/static/chunk-DKGXUMLT.js +1 -0
  291. package/static/chunk-DRHPEERW.js +2 -0
  292. package/static/chunk-DWYP6ZGG.js +1 -0
  293. package/static/chunk-EDJAISWO.js +13 -0
  294. package/static/chunk-EIYRBM4J.js +1 -0
  295. package/static/chunk-EKEGRXCV.js +7 -0
  296. package/static/chunk-EL6QL4TP.js +1 -0
  297. package/static/chunk-ERDZ7IVF.js +1 -0
  298. package/static/chunk-EVQKKVUZ.js +1 -0
  299. package/static/chunk-F2XG7EWI.js +1 -0
  300. package/static/chunk-F672FY5I.js +1 -0
  301. package/static/chunk-F6V37MKG.js +1 -0
  302. package/static/chunk-F7TXTNZC.js +1 -0
  303. package/static/chunk-FCGTI42I.js +1 -0
  304. package/static/chunk-FQHOSSCO.js +1 -0
  305. package/static/chunk-FTSIPHMG.js +1 -0
  306. package/static/chunk-GAGHHYLF.js +1 -0
  307. package/static/{chunk-JPT5WEAT.js → chunk-GOJYWL2M.js} +1 -1
  308. package/static/chunk-H6WOTGQ5.js +1 -0
  309. package/static/{chunk-CHJ64RJM.js → chunk-H6ZXFINQ.js} +1 -1
  310. package/static/chunk-HC7F57NA.js +1 -0
  311. package/static/chunk-HHWXIK2M.js +7 -0
  312. package/static/chunk-HKRGIRKB.js +3 -0
  313. package/static/chunk-HNMGPG72.js +1 -0
  314. package/static/chunk-HS4S6BV3.js +1 -0
  315. package/static/chunk-IJ7K7ATQ.js +1 -0
  316. package/static/chunk-IOIBQGHN.js +562 -0
  317. package/static/chunk-ITVA26X2.js +2 -0
  318. package/static/chunk-J6YSFHLZ.js +1 -0
  319. package/static/chunk-JAEJ6IMV.js +1 -0
  320. package/static/chunk-JB5R6V33.js +1 -0
  321. package/static/chunk-JF6WIV6M.js +1 -0
  322. package/static/chunk-JGB4LLUT.js +1 -0
  323. package/static/chunk-JGXVTKLG.js +1 -0
  324. package/static/chunk-JMYAD7E2.js +1 -0
  325. package/static/chunk-JSE63Q5X.js +1 -0
  326. package/static/chunk-JVV3ZL6L.js +1 -0
  327. package/static/chunk-JXZCNFW7.js +1 -0
  328. package/static/chunk-KAVP6UXH.js +1 -0
  329. package/static/{chunk-3R74L4UU.js → chunk-KDEEERWZ.js} +1 -1
  330. package/static/chunk-KHRF67SG.js +1 -0
  331. package/static/chunk-KLOUBIO4.js +1 -0
  332. package/static/chunk-KMF3ZRAO.js +1 -0
  333. package/static/chunk-KNZ3AQPR.js +1 -0
  334. package/static/chunk-KT3TWCST.js +1 -0
  335. package/static/chunk-L6SYG23T.js +1 -0
  336. package/static/chunk-LJSVNPPQ.js +1 -0
  337. package/static/{chunk-LNTUR3GU.js → chunk-LRDKG274.js} +1 -1
  338. package/static/chunk-LRQSPCYZ.js +1 -0
  339. package/static/chunk-LUSVISM6.js +1 -0
  340. package/static/chunk-LXQGVNU2.js +1 -0
  341. package/static/{chunk-LVSNIS5P.js → chunk-LYZGJZNP.js} +1 -1
  342. package/static/chunk-LZKI5P5T.js +1 -0
  343. package/static/chunk-M4XL3JN5.js +6 -0
  344. package/static/{chunk-UNCPXHHT.js → chunk-MGWG7OD7.js} +1 -1
  345. package/static/chunk-MKUUWY6Y.js +1 -0
  346. package/static/{chunk-VJTXJ43D.js → chunk-MNNCSSHN.js} +1 -1
  347. package/static/chunk-MR3U7TKQ.js +1 -0
  348. package/static/chunk-MRF3CNLZ.js +1 -0
  349. package/static/chunk-MRMSMTWD.js +1 -0
  350. package/static/chunk-MVZJSG5R.js +1 -0
  351. package/static/chunk-MYM43ENO.js +1 -0
  352. package/static/chunk-N3P6P6GW.js +7 -0
  353. package/static/chunk-NAH4V2R6.js +2 -0
  354. package/static/chunk-NBBDVVUF.js +1 -0
  355. package/static/chunk-NMF2ZFBE.js +1 -0
  356. package/static/chunk-NN4ONTOT.js +1 -0
  357. package/static/chunk-NOPACN4F.js +1 -0
  358. package/static/chunk-NYJPOP4L.js +1 -0
  359. package/static/chunk-OJCAIKUK.js +1 -0
  360. package/static/chunk-OQRWXCLY.js +1 -0
  361. package/static/chunk-PCFH5HCI.js +2 -0
  362. package/static/chunk-PG54TWBO.js +4 -0
  363. package/static/chunk-PJF5XUTO.js +1 -0
  364. package/static/{chunk-FJE6BOFL.js → chunk-PSUAQBYM.js} +1 -1
  365. package/static/chunk-PTLYIUFW.js +1 -0
  366. package/static/chunk-PZGLDZZM.js +1 -0
  367. package/static/chunk-Q4VNZGFI.js +1 -0
  368. package/static/chunk-Q556XB3S.js +1 -0
  369. package/static/{chunk-PB4AIT7O.js → chunk-Q7IXRPOO.js} +1 -1
  370. package/static/chunk-Q7U2VPIS.js +1 -0
  371. package/static/chunk-QM6CQMEX.js +1 -0
  372. package/static/chunk-QMHUIHSR.js +1 -0
  373. package/static/chunk-QNFNXDSX.js +1 -0
  374. package/static/chunk-QVFPHTOH.js +1 -0
  375. package/static/chunk-R4MI25E2.js +1 -0
  376. package/static/chunk-R7JRAR3P.js +1 -0
  377. package/static/chunk-R7PNKQU2.js +1 -0
  378. package/static/chunk-RCAORRB7.js +1 -0
  379. package/static/chunk-RK7XRDNB.js +1 -0
  380. package/static/chunk-RO7SAOLK.js +1 -0
  381. package/static/chunk-RQUUINHV.js +1 -0
  382. package/static/chunk-RT3K6DZR.js +1 -0
  383. package/static/chunk-RUN556VW.js +1 -0
  384. package/static/chunk-RX3YQ67K.js +1 -0
  385. package/static/chunk-S6EVLDHA.js +5 -0
  386. package/static/chunk-S7S5M3AZ.js +1 -0
  387. package/static/chunk-SBLNYV74.js +1 -0
  388. package/static/chunk-SIZCHHUA.js +1 -0
  389. package/static/chunk-SRBOO7AO.js +1 -0
  390. package/static/{chunk-PVDHBQRM.js → chunk-STA7NTYL.js} +1 -1
  391. package/static/chunk-T3YI3BSS.js +1 -0
  392. package/static/chunk-T74SMT7I.js +1 -0
  393. package/static/chunk-TAL3RTTQ.js +1 -0
  394. package/static/chunk-TJZKTNNS.js +1 -0
  395. package/static/chunk-UJTFWZEC.js +1 -0
  396. package/static/chunk-UPGVU5LG.js +1 -0
  397. package/static/chunk-UQ6O3I6W.js +1 -0
  398. package/static/{chunk-5NMSIIQB.js → chunk-V43RGNXA.js} +1 -1
  399. package/static/chunk-VWIRXLNE.js +1 -0
  400. package/static/chunk-VZMVGIVW.js +1 -0
  401. package/static/chunk-VZPCXSRG.js +2 -0
  402. package/static/chunk-WR3MA3L3.js +1 -0
  403. package/static/chunk-XCLK7NJL.js +1 -0
  404. package/static/{chunk-DSWEWLXJ.js → chunk-XCPDPB5G.js} +1 -1
  405. package/static/chunk-XEGHEUP5.js +1 -0
  406. package/static/chunk-XKEBQNQJ.js +1 -0
  407. package/static/chunk-XOF4UW3S.js +1 -0
  408. package/static/chunk-XOTKK2NJ.js +1 -0
  409. package/static/chunk-XX7JXKA6.js +1 -0
  410. package/static/chunk-Y2I36A4K.js +1 -0
  411. package/static/chunk-Y44XDRM5.js +1 -0
  412. package/static/{chunk-QO6BTONN.js → chunk-Y4MAPE2C.js} +1 -1
  413. package/static/chunk-Y5RLD72B.js +1 -0
  414. package/static/{chunk-DPUVSXRB.js → chunk-Y5XTRCFK.js} +1 -1
  415. package/static/chunk-Y63UUJGJ.js +1 -0
  416. package/static/chunk-YBNAC7QM.js +1 -0
  417. package/static/chunk-YCTCESL4.js +1 -0
  418. package/static/chunk-YMAN4LIU.js +1 -0
  419. package/static/chunk-YTDE6SXT.js +1 -0
  420. package/static/chunk-YZPIUJB3.js +1 -0
  421. package/static/chunk-ZCOWBVOT.js +1 -0
  422. package/static/chunk-ZHRYYMYE.js +1 -0
  423. package/static/chunk-ZNXTOQFG.js +1 -0
  424. package/static/{chunk-URHTCJ7G.js → chunk-ZQLBPLXI.js} +1 -1
  425. package/static/favicon.ico +0 -0
  426. package/static/index.html +2 -2
  427. package/static/main-3PLRDZTO.js +11 -0
  428. package/static/styles-Q4OZOSSK.css +1 -0
  429. package/server/applications/notifications/interfaces/user-mail-notification.js.map +0 -1
  430. package/static/assets/codemirror/mode/apl/apl.js +0 -174
  431. package/static/assets/codemirror/mode/asciiarmor/asciiarmor.js +0 -74
  432. package/static/assets/codemirror/mode/asn.1/asn.1.js +0 -204
  433. package/static/assets/codemirror/mode/asterisk/asterisk.js +0 -220
  434. package/static/assets/codemirror/mode/brainfuck/brainfuck.js +0 -85
  435. package/static/assets/codemirror/mode/clike/clike.js +0 -942
  436. package/static/assets/codemirror/mode/clojure/clojure.js +0 -293
  437. package/static/assets/codemirror/mode/cmake/cmake.js +0 -97
  438. package/static/assets/codemirror/mode/cobol/cobol.js +0 -255
  439. package/static/assets/codemirror/mode/coffeescript/coffeescript.js +0 -359
  440. package/static/assets/codemirror/mode/commonlisp/commonlisp.js +0 -125
  441. package/static/assets/codemirror/mode/crystal/crystal.js +0 -433
  442. package/static/assets/codemirror/mode/css/css.js +0 -862
  443. package/static/assets/codemirror/mode/cypher/cypher.js +0 -152
  444. package/static/assets/codemirror/mode/d/d.js +0 -223
  445. package/static/assets/codemirror/mode/dart/dart.js +0 -168
  446. package/static/assets/codemirror/mode/diff/diff.js +0 -47
  447. package/static/assets/codemirror/mode/django/django.js +0 -356
  448. package/static/assets/codemirror/mode/dockerfile/dockerfile.js +0 -211
  449. package/static/assets/codemirror/mode/dtd/dtd.js +0 -142
  450. package/static/assets/codemirror/mode/dylan/dylan.js +0 -352
  451. package/static/assets/codemirror/mode/ebnf/ebnf.js +0 -195
  452. package/static/assets/codemirror/mode/ecl/ecl.js +0 -206
  453. package/static/assets/codemirror/mode/eiffel/eiffel.js +0 -160
  454. package/static/assets/codemirror/mode/elm/elm.js +0 -245
  455. package/static/assets/codemirror/mode/erlang/erlang.js +0 -619
  456. package/static/assets/codemirror/mode/factor/factor.js +0 -85
  457. package/static/assets/codemirror/mode/fcl/fcl.js +0 -173
  458. package/static/assets/codemirror/mode/forth/forth.js +0 -180
  459. package/static/assets/codemirror/mode/fortran/fortran.js +0 -188
  460. package/static/assets/codemirror/mode/gas/gas.js +0 -355
  461. package/static/assets/codemirror/mode/gfm/gfm.js +0 -129
  462. package/static/assets/codemirror/mode/gherkin/gherkin.js +0 -194
  463. package/static/assets/codemirror/mode/go/go.js +0 -187
  464. package/static/assets/codemirror/mode/groovy/groovy.js +0 -245
  465. package/static/assets/codemirror/mode/haml/haml.js +0 -161
  466. package/static/assets/codemirror/mode/handlebars/handlebars.js +0 -70
  467. package/static/assets/codemirror/mode/haskell/haskell.js +0 -268
  468. package/static/assets/codemirror/mode/haskell-literate/haskell-literate.js +0 -43
  469. package/static/assets/codemirror/mode/haxe/haxe.js +0 -515
  470. package/static/assets/codemirror/mode/htmlembedded/htmlembedded.js +0 -37
  471. package/static/assets/codemirror/mode/htmlmixed/htmlmixed.js +0 -153
  472. package/static/assets/codemirror/mode/http/http.js +0 -113
  473. package/static/assets/codemirror/mode/idl/idl.js +0 -290
  474. package/static/assets/codemirror/mode/javascript/javascript.js +0 -960
  475. package/static/assets/codemirror/mode/jinja2/jinja2.js +0 -193
  476. package/static/assets/codemirror/mode/jsx/jsx.js +0 -149
  477. package/static/assets/codemirror/mode/julia/julia.js +0 -390
  478. package/static/assets/codemirror/mode/livescript/livescript.js +0 -280
  479. package/static/assets/codemirror/mode/lua/lua.js +0 -160
  480. package/static/assets/codemirror/mode/markdown/markdown.js +0 -886
  481. package/static/assets/codemirror/mode/mathematica/mathematica.js +0 -176
  482. package/static/assets/codemirror/mode/mbox/mbox.js +0 -129
  483. package/static/assets/codemirror/mode/meta.js +0 -221
  484. package/static/assets/codemirror/mode/mirc/mirc.js +0 -193
  485. package/static/assets/codemirror/mode/mllike/mllike.js +0 -359
  486. package/static/assets/codemirror/mode/modelica/modelica.js +0 -245
  487. package/static/assets/codemirror/mode/mscgen/mscgen.js +0 -175
  488. package/static/assets/codemirror/mode/mumps/mumps.js +0 -148
  489. package/static/assets/codemirror/mode/nginx/nginx.js +0 -178
  490. package/static/assets/codemirror/mode/nsis/nsis.js +0 -95
  491. package/static/assets/codemirror/mode/ntriples/ntriples.js +0 -195
  492. package/static/assets/codemirror/mode/octave/octave.js +0 -139
  493. package/static/assets/codemirror/mode/oz/oz.js +0 -252
  494. package/static/assets/codemirror/mode/pascal/pascal.js +0 -136
  495. package/static/assets/codemirror/mode/pegjs/pegjs.js +0 -111
  496. package/static/assets/codemirror/mode/perl/perl.js +0 -836
  497. package/static/assets/codemirror/mode/php/php.js +0 -234
  498. package/static/assets/codemirror/mode/pig/pig.js +0 -178
  499. package/static/assets/codemirror/mode/powershell/powershell.js +0 -398
  500. package/static/assets/codemirror/mode/properties/properties.js +0 -78
  501. package/static/assets/codemirror/mode/protobuf/protobuf.js +0 -72
  502. package/static/assets/codemirror/mode/pug/pug.js +0 -591
  503. package/static/assets/codemirror/mode/puppet/puppet.js +0 -220
  504. package/static/assets/codemirror/mode/python/python.js +0 -402
  505. package/static/assets/codemirror/mode/q/q.js +0 -139
  506. package/static/assets/codemirror/mode/r/r.js +0 -190
  507. package/static/assets/codemirror/mode/rpm/changes/index.html +0 -66
  508. package/static/assets/codemirror/mode/rpm/rpm.js +0 -109
  509. package/static/assets/codemirror/mode/rst/rst.js +0 -557
  510. package/static/assets/codemirror/mode/ruby/ruby.js +0 -303
  511. package/static/assets/codemirror/mode/rust/rust.js +0 -72
  512. package/static/assets/codemirror/mode/sas/sas.js +0 -303
  513. package/static/assets/codemirror/mode/sass/sass.js +0 -459
  514. package/static/assets/codemirror/mode/scheme/scheme.js +0 -284
  515. package/static/assets/codemirror/mode/shell/shell.js +0 -168
  516. package/static/assets/codemirror/mode/sieve/sieve.js +0 -193
  517. package/static/assets/codemirror/mode/slim/slim.js +0 -575
  518. package/static/assets/codemirror/mode/smalltalk/smalltalk.js +0 -168
  519. package/static/assets/codemirror/mode/smarty/smarty.js +0 -225
  520. package/static/assets/codemirror/mode/solr/solr.js +0 -104
  521. package/static/assets/codemirror/mode/soy/soy.js +0 -665
  522. package/static/assets/codemirror/mode/sparql/sparql.js +0 -184
  523. package/static/assets/codemirror/mode/spreadsheet/spreadsheet.js +0 -112
  524. package/static/assets/codemirror/mode/sql/sql.js +0 -529
  525. package/static/assets/codemirror/mode/stex/stex.js +0 -264
  526. package/static/assets/codemirror/mode/stylus/stylus.js +0 -775
  527. package/static/assets/codemirror/mode/swift/swift.js +0 -221
  528. package/static/assets/codemirror/mode/tcl/tcl.js +0 -140
  529. package/static/assets/codemirror/mode/textile/textile.js +0 -469
  530. package/static/assets/codemirror/mode/tiddlywiki/tiddlywiki.css +0 -14
  531. package/static/assets/codemirror/mode/tiddlywiki/tiddlywiki.js +0 -308
  532. package/static/assets/codemirror/mode/tiki/tiki.css +0 -26
  533. package/static/assets/codemirror/mode/tiki/tiki.js +0 -312
  534. package/static/assets/codemirror/mode/toml/toml.js +0 -88
  535. package/static/assets/codemirror/mode/tornado/tornado.js +0 -68
  536. package/static/assets/codemirror/mode/troff/troff.js +0 -84
  537. package/static/assets/codemirror/mode/ttcn/ttcn.js +0 -283
  538. package/static/assets/codemirror/mode/ttcn-cfg/ttcn-cfg.js +0 -214
  539. package/static/assets/codemirror/mode/turtle/turtle.js +0 -162
  540. package/static/assets/codemirror/mode/twig/twig.js +0 -141
  541. package/static/assets/codemirror/mode/vb/vb.js +0 -275
  542. package/static/assets/codemirror/mode/vbscript/vbscript.js +0 -350
  543. package/static/assets/codemirror/mode/velocity/velocity.js +0 -202
  544. package/static/assets/codemirror/mode/verilog/verilog.js +0 -781
  545. package/static/assets/codemirror/mode/vhdl/vhdl.js +0 -189
  546. package/static/assets/codemirror/mode/vue/vue.js +0 -77
  547. package/static/assets/codemirror/mode/wast/wast.js +0 -132
  548. package/static/assets/codemirror/mode/webidl/webidl.js +0 -195
  549. package/static/assets/codemirror/mode/xml/xml.js +0 -417
  550. package/static/assets/codemirror/mode/xquery/xquery.js +0 -448
  551. package/static/assets/codemirror/mode/yacas/yacas.js +0 -204
  552. package/static/assets/codemirror/mode/yaml/yaml.js +0 -120
  553. package/static/assets/codemirror/mode/yaml-frontmatter/yaml-frontmatter.js +0 -72
  554. package/static/assets/codemirror/mode/z80/z80.js +0 -116
  555. package/static/chunk-2KLC4T2Z.js +0 -1
  556. package/static/chunk-2VMSXRCB.js +0 -12
  557. package/static/chunk-3OHSRRKH.js +0 -4
  558. package/static/chunk-3R4WKOHQ.js +0 -1
  559. package/static/chunk-3XVM35O2.js +0 -1
  560. package/static/chunk-3YVRP3VM.js +0 -2
  561. package/static/chunk-5UKZLU5H.js +0 -1
  562. package/static/chunk-AF24EYXU.js +0 -1
  563. package/static/chunk-AKQVEHO6.js +0 -2
  564. package/static/chunk-BCVX464U.js +0 -2
  565. package/static/chunk-BQV4FRM6.js +0 -1
  566. package/static/chunk-CETH7UYS.js +0 -1
  567. package/static/chunk-DIT6W7VM.js +0 -562
  568. package/static/chunk-DKSEQTMX.js +0 -1
  569. package/static/chunk-FZ3JPGYZ.js +0 -1
  570. package/static/chunk-IQSKQXC3.js +0 -1
  571. package/static/chunk-ITUFI2BJ.js +0 -1
  572. package/static/chunk-LCTZJ537.js +0 -1
  573. package/static/chunk-LK2UCQJ6.js +0 -1
  574. package/static/chunk-LP5TBXEN.js +0 -7
  575. package/static/chunk-N3U6637P.js +0 -1
  576. package/static/chunk-NNV4OXSB.js +0 -1
  577. package/static/chunk-O6FYXVHI.js +0 -1
  578. package/static/chunk-OOGP4WSH.js +0 -2
  579. package/static/chunk-PCWDQPOM.js +0 -2
  580. package/static/chunk-PNR6M34W.js +0 -1
  581. package/static/chunk-Q5KM7LTX.js +0 -1
  582. package/static/chunk-QHC6ZPQ4.js +0 -1
  583. package/static/chunk-QMRBZHE4.js +0 -1
  584. package/static/chunk-QSJRY3TF.js +0 -1
  585. package/static/chunk-QUUIRSYT.js +0 -1
  586. package/static/chunk-RFH46UW3.js +0 -1
  587. package/static/chunk-RSXHRKM5.js +0 -1
  588. package/static/chunk-RV3VZJPZ.js +0 -1
  589. package/static/chunk-S7HNXVRB.js +0 -1
  590. package/static/chunk-SBZ572Q4.js +0 -2
  591. package/static/chunk-SJR5R3Y4.js +0 -1
  592. package/static/chunk-SLHTEGRU.js +0 -1
  593. package/static/chunk-SSFF27P2.js +0 -24
  594. package/static/chunk-V3LHHZYN.js +0 -1
  595. package/static/chunk-VQQKMY2C.js +0 -1
  596. package/static/chunk-WSSU2HXE.js +0 -1
  597. package/static/chunk-XDZGW64M.js +0 -3
  598. package/static/chunk-XTRDKGKG.js +0 -1
  599. package/static/chunk-YLWTEC3X.js +0 -1
  600. package/static/chunk-Z5J5F5SX.js +0 -1
  601. package/static/main-4H5BJY3J.js +0 -9
  602. package/static/scripts-WRDOQIU5.js +0 -24
  603. package/static/styles-2C2UNCNB.css +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/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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"}