@sync-in/server 1.3.9 → 1.5.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 (294) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +5 -3
  3. package/environment/environment.dist.yaml +2 -0
  4. package/package.json +6 -6
  5. package/server/app.bootstrap.js +9 -0
  6. package/server/app.bootstrap.js.map +1 -1
  7. package/server/app.service.spec.js +44 -19
  8. package/server/app.service.spec.js.map +1 -1
  9. package/server/applications/comments/comments.controller.spec.js +103 -4
  10. package/server/applications/comments/comments.controller.spec.js.map +1 -1
  11. package/server/applications/comments/services/comments-manager.service.spec.js +409 -9
  12. package/server/applications/comments/services/comments-manager.service.spec.js.map +1 -1
  13. package/server/applications/files/adapters/files-indexer-mysql.service.spec.js +333 -0
  14. package/server/applications/files/adapters/files-indexer-mysql.service.spec.js.map +1 -0
  15. package/server/applications/files/constants/files.js +0 -23
  16. package/server/applications/files/constants/files.js.map +1 -1
  17. package/server/applications/files/constants/only-office.js +8 -0
  18. package/server/applications/files/constants/only-office.js.map +1 -1
  19. package/server/applications/files/constants/routes.js +6 -1
  20. package/server/applications/files/constants/routes.js.map +1 -1
  21. package/server/applications/files/files-only-office.controller.js +11 -0
  22. package/server/applications/files/files-only-office.controller.js.map +1 -1
  23. package/server/applications/files/files-only-office.controller.spec.js +97 -3
  24. package/server/applications/files/files-only-office.controller.spec.js.map +1 -1
  25. package/server/applications/files/files-tasks.controller.spec.js +91 -1
  26. package/server/applications/files/files-tasks.controller.spec.js.map +1 -1
  27. package/server/applications/files/files.config.js +5 -0
  28. package/server/applications/files/files.config.js.map +1 -1
  29. package/server/applications/files/files.controller.spec.js +268 -46
  30. package/server/applications/files/files.controller.spec.js.map +1 -1
  31. package/server/applications/files/guards/files-only-office.guard.spec.js +77 -1
  32. package/server/applications/files/guards/files-only-office.guard.spec.js.map +1 -1
  33. package/server/applications/files/guards/files-only-office.strategy.js +0 -1
  34. package/server/applications/files/guards/files-only-office.strategy.js.map +1 -1
  35. package/server/applications/files/services/files-only-office-manager.service.js +5 -0
  36. package/server/applications/files/services/files-only-office-manager.service.js.map +1 -1
  37. package/server/applications/links/links.controller.spec.js +91 -58
  38. package/server/applications/links/links.controller.spec.js.map +1 -1
  39. package/server/applications/links/services/links-manager.service.js +4 -6
  40. package/server/applications/links/services/links-manager.service.js.map +1 -1
  41. package/server/applications/links/services/links-manager.service.spec.js +378 -14
  42. package/server/applications/links/services/links-manager.service.spec.js.map +1 -1
  43. package/server/applications/links/services/links-queries.service.js +1 -1
  44. package/server/applications/links/services/links-queries.service.js.map +1 -1
  45. package/server/applications/notifications/notifications.controller.spec.js +56 -1
  46. package/server/applications/notifications/notifications.controller.spec.js.map +1 -1
  47. package/server/applications/notifications/services/notifications-manager.service.spec.js +461 -5
  48. package/server/applications/notifications/services/notifications-manager.service.spec.js.map +1 -1
  49. package/server/applications/shares/services/shares-manager.service.spec.js +590 -14
  50. package/server/applications/shares/services/shares-manager.service.spec.js.map +1 -1
  51. package/server/applications/spaces/guards/space.guard.spec.js +153 -18
  52. package/server/applications/spaces/guards/space.guard.spec.js.map +1 -1
  53. package/server/applications/spaces/services/spaces-browser.service.js +7 -7
  54. package/server/applications/spaces/services/spaces-browser.service.js.map +1 -1
  55. package/server/applications/spaces/services/spaces-manager.service.js +17 -17
  56. package/server/applications/spaces/services/spaces-manager.service.js.map +1 -1
  57. package/server/applications/sync/interceptors/sync-diff-gzip-body.interceptor.spec.js +120 -0
  58. package/server/applications/sync/interceptors/sync-diff-gzip-body.interceptor.spec.js.map +1 -0
  59. package/server/applications/sync/services/sync-clients-manager.service.spec.js +548 -8
  60. package/server/applications/sync/services/sync-clients-manager.service.spec.js.map +1 -1
  61. package/server/applications/sync/services/sync-manager.service.spec.js +837 -5
  62. package/server/applications/sync/services/sync-manager.service.spec.js.map +1 -1
  63. package/server/applications/sync/services/sync-paths-manager.service.spec.js +900 -7
  64. package/server/applications/sync/services/sync-paths-manager.service.spec.js.map +1 -1
  65. package/server/applications/sync/utils/routes.js +1 -1
  66. package/server/applications/sync/utils/routes.js.map +1 -1
  67. package/server/applications/users/guards/permissions.guard.js +4 -4
  68. package/server/applications/users/guards/permissions.guard.js.map +1 -1
  69. package/server/applications/users/guards/permissions.guard.spec.js +6 -6
  70. package/server/applications/users/guards/permissions.guard.spec.js.map +1 -1
  71. package/server/applications/users/guards/roles.guard.js +1 -1
  72. package/server/applications/users/guards/roles.guard.js.map +1 -1
  73. package/server/applications/users/models/user.model.js +1 -1
  74. package/server/applications/users/models/user.model.js.map +1 -1
  75. package/server/applications/users/services/admin-users-manager.service.js +22 -24
  76. package/server/applications/users/services/admin-users-manager.service.js.map +1 -1
  77. package/server/applications/users/services/admin-users-manager.service.spec.js +763 -17
  78. package/server/applications/users/services/admin-users-manager.service.spec.js.map +1 -1
  79. package/server/applications/users/services/users-manager.service.js +1 -1
  80. package/server/applications/users/services/users-manager.service.js.map +1 -1
  81. package/server/applications/users/services/users-manager.service.spec.js +938 -49
  82. package/server/applications/users/services/users-manager.service.spec.js.map +1 -1
  83. package/server/applications/webdav/decorators/if-header.decorator.js +4 -1
  84. package/server/applications/webdav/decorators/if-header.decorator.js.map +1 -1
  85. package/server/applications/webdav/filters/webdav.filter.spec.js +77 -0
  86. package/server/applications/webdav/filters/webdav.filter.spec.js.map +1 -0
  87. package/server/applications/webdav/guards/webdav-protocol.guard.js +3 -7
  88. package/server/applications/webdav/guards/webdav-protocol.guard.js.map +1 -1
  89. package/server/applications/webdav/guards/webdav-protocol.guard.spec.js +580 -0
  90. package/server/applications/webdav/guards/webdav-protocol.guard.spec.js.map +1 -0
  91. package/server/applications/webdav/services/webdav-methods.service.spec.js +1582 -3
  92. package/server/applications/webdav/services/webdav-methods.service.spec.js.map +1 -1
  93. package/server/applications/webdav/services/webdav-spaces.service.spec.js +390 -2
  94. package/server/applications/webdav/services/webdav-spaces.service.spec.js.map +1 -1
  95. package/server/applications/webdav/webdav.controller.js +2 -2
  96. package/server/applications/webdav/webdav.controller.js.map +1 -1
  97. package/server/authentication/guards/auth-basic.guard.js.map +1 -1
  98. package/server/authentication/guards/auth-basic.guard.spec.js +38 -2
  99. package/server/authentication/guards/auth-basic.guard.spec.js.map +1 -1
  100. package/server/authentication/guards/auth-basic.strategy.js +0 -1
  101. package/server/authentication/guards/auth-basic.strategy.js.map +1 -1
  102. package/server/authentication/guards/auth-digest.guard.js +1 -2
  103. package/server/authentication/guards/auth-digest.guard.js.map +1 -1
  104. package/server/authentication/guards/auth-local.guard.js.map +1 -1
  105. package/server/authentication/guards/auth-local.guard.spec.js +7 -5
  106. package/server/authentication/guards/auth-local.guard.spec.js.map +1 -1
  107. package/server/authentication/guards/auth-local.strategy.js +0 -1
  108. package/server/authentication/guards/auth-local.strategy.js.map +1 -1
  109. package/server/authentication/guards/auth-token-access.guard.spec.js +30 -0
  110. package/server/authentication/guards/auth-token-access.guard.spec.js.map +1 -1
  111. package/server/authentication/guards/auth-token-access.strategy.js +0 -1
  112. package/server/authentication/guards/auth-token-access.strategy.js.map +1 -1
  113. package/server/authentication/guards/auth-token-refresh.strategy.js +0 -1
  114. package/server/authentication/guards/auth-token-refresh.strategy.js.map +1 -1
  115. package/server/authentication/services/auth-methods/auth-method-database.service.js +1 -1
  116. package/server/authentication/services/auth-methods/auth-method-database.service.js.map +1 -1
  117. package/server/authentication/services/auth-methods/auth-method-database.service.spec.js +8 -6
  118. package/server/authentication/services/auth-methods/auth-method-database.service.spec.js.map +1 -1
  119. package/server/authentication/services/auth-methods/auth-method-ldap.service.js +2 -2
  120. package/server/authentication/services/auth-methods/auth-method-ldap.service.js.map +1 -1
  121. package/server/authentication/services/auth-methods/auth-method-ldap.service.spec.js +500 -5
  122. package/server/authentication/services/auth-methods/auth-method-ldap.service.spec.js.map +1 -1
  123. package/server/configuration/config.loader.js +0 -3
  124. package/server/configuration/config.loader.js.map +1 -1
  125. package/server/infrastructure/context/interceptors/context.interceptor.spec.js +135 -0
  126. package/server/infrastructure/context/interceptors/context.interceptor.spec.js.map +1 -0
  127. package/server/infrastructure/context/services/context-manager.service.spec.js +98 -0
  128. package/server/infrastructure/context/services/context-manager.service.spec.js.map +1 -0
  129. package/server/infrastructure/database/constants.js +0 -1
  130. package/server/infrastructure/database/constants.js.map +1 -1
  131. package/server/infrastructure/database/scripts/seed/usersgroups.js +3 -3
  132. package/server/infrastructure/database/scripts/seed/usersgroups.js.map +1 -1
  133. package/server/infrastructure/mailer/mailer.service.js +20 -19
  134. package/server/infrastructure/mailer/mailer.service.js.map +1 -1
  135. package/server/infrastructure/mailer/mailer.service.spec.js +176 -0
  136. package/server/infrastructure/mailer/mailer.service.spec.js.map +1 -0
  137. package/static/3rdpartylicenses.txt +26 -26
  138. package/static/assets/pdfjs/build/pdf.mjs +1177 -255
  139. package/static/assets/pdfjs/build/pdf.mjs.map +1 -1
  140. package/static/assets/pdfjs/build/pdf.sandbox.mjs +25 -2
  141. package/static/assets/pdfjs/build/pdf.sandbox.mjs.map +1 -1
  142. package/static/assets/pdfjs/build/pdf.worker.mjs +140 -16
  143. package/static/assets/pdfjs/build/pdf.worker.mjs.map +1 -1
  144. package/static/assets/pdfjs/version +1 -1
  145. package/static/assets/pdfjs/web/debugger.css +31 -0
  146. package/static/assets/pdfjs/web/debugger.mjs +144 -2
  147. package/static/assets/pdfjs/web/images/comment-editButton.svg +6 -1
  148. package/static/assets/pdfjs/web/locale/ach/viewer.ftl +0 -63
  149. package/static/assets/pdfjs/web/locale/af/viewer.ftl +0 -71
  150. package/static/assets/pdfjs/web/locale/an/viewer.ftl +0 -63
  151. package/static/assets/pdfjs/web/locale/ast/viewer.ftl +0 -60
  152. package/static/assets/pdfjs/web/locale/az/viewer.ftl +0 -63
  153. package/static/assets/pdfjs/web/locale/be/viewer.ftl +38 -0
  154. package/static/assets/pdfjs/web/locale/bg/viewer.ftl +0 -37
  155. package/static/assets/pdfjs/web/locale/bn/viewer.ftl +0 -63
  156. package/static/assets/pdfjs/web/locale/bo/viewer.ftl +0 -63
  157. package/static/assets/pdfjs/web/locale/br/viewer.ftl +0 -37
  158. package/static/assets/pdfjs/web/locale/brx/viewer.ftl +0 -63
  159. package/static/assets/pdfjs/web/locale/bs/viewer.ftl +22 -0
  160. package/static/assets/pdfjs/web/locale/ca/viewer.ftl +0 -54
  161. package/static/assets/pdfjs/web/locale/cak/viewer.ftl +0 -54
  162. package/static/assets/pdfjs/web/locale/ckb/viewer.ftl +0 -63
  163. package/static/assets/pdfjs/web/locale/cs/viewer.ftl +38 -0
  164. package/static/assets/pdfjs/web/locale/cy/viewer.ftl +38 -0
  165. package/static/assets/pdfjs/web/locale/da/viewer.ftl +38 -0
  166. package/static/assets/pdfjs/web/locale/de/viewer.ftl +38 -0
  167. package/static/assets/pdfjs/web/locale/dsb/viewer.ftl +38 -0
  168. package/static/assets/pdfjs/web/locale/el/viewer.ftl +38 -0
  169. package/static/assets/pdfjs/web/locale/en-CA/viewer.ftl +38 -0
  170. package/static/assets/pdfjs/web/locale/en-GB/viewer.ftl +38 -0
  171. package/static/assets/pdfjs/web/locale/en-US/viewer.ftl +25 -0
  172. package/static/assets/pdfjs/web/locale/eo/viewer.ftl +38 -0
  173. package/static/assets/pdfjs/web/locale/es-AR/viewer.ftl +38 -0
  174. package/static/assets/pdfjs/web/locale/es-CL/viewer.ftl +38 -0
  175. package/static/assets/pdfjs/web/locale/es-MX/viewer.ftl +0 -6
  176. package/static/assets/pdfjs/web/locale/et/viewer.ftl +0 -57
  177. package/static/assets/pdfjs/web/locale/fa/viewer.ftl +0 -37
  178. package/static/assets/pdfjs/web/locale/ff/viewer.ftl +0 -63
  179. package/static/assets/pdfjs/web/locale/fi/viewer.ftl +38 -0
  180. package/static/assets/pdfjs/web/locale/fr/viewer.ftl +38 -0
  181. package/static/assets/pdfjs/web/locale/fy-NL/viewer.ftl +38 -0
  182. package/static/assets/pdfjs/web/locale/ga-IE/viewer.ftl +0 -71
  183. package/static/assets/pdfjs/web/locale/gd/viewer.ftl +0 -54
  184. package/static/assets/pdfjs/web/locale/gl/viewer.ftl +8 -0
  185. package/static/assets/pdfjs/web/locale/gn/viewer.ftl +38 -0
  186. package/static/assets/pdfjs/web/locale/gu-IN/viewer.ftl +0 -63
  187. package/static/assets/pdfjs/web/locale/he/viewer.ftl +38 -0
  188. package/static/assets/pdfjs/web/locale/hi-IN/viewer.ftl +0 -60
  189. package/static/assets/pdfjs/web/locale/hsb/viewer.ftl +38 -0
  190. package/static/assets/pdfjs/web/locale/hu/viewer.ftl +38 -0
  191. package/static/assets/pdfjs/web/locale/hy-AM/viewer.ftl +0 -49
  192. package/static/assets/pdfjs/web/locale/hye/viewer.ftl +0 -60
  193. package/static/assets/pdfjs/web/locale/ia/viewer.ftl +38 -0
  194. package/static/assets/pdfjs/web/locale/is/viewer.ftl +0 -3
  195. package/static/assets/pdfjs/web/locale/it/viewer.ftl +31 -0
  196. package/static/assets/pdfjs/web/locale/ja/viewer.ftl +8 -0
  197. package/static/assets/pdfjs/web/locale/ka/viewer.ftl +48 -10
  198. package/static/assets/pdfjs/web/locale/kab/viewer.ftl +5 -0
  199. package/static/assets/pdfjs/web/locale/kk/viewer.ftl +8 -0
  200. package/static/assets/pdfjs/web/locale/km/viewer.ftl +0 -63
  201. package/static/assets/pdfjs/web/locale/kn/viewer.ftl +0 -71
  202. package/static/assets/pdfjs/web/locale/ko/viewer.ftl +38 -0
  203. package/static/assets/pdfjs/web/locale/lij/viewer.ftl +0 -63
  204. package/static/assets/pdfjs/web/locale/lo/viewer.ftl +0 -54
  205. package/static/assets/pdfjs/web/locale/lt/viewer.ftl +0 -60
  206. package/static/assets/pdfjs/web/locale/ltg/viewer.ftl +0 -63
  207. package/static/assets/pdfjs/web/locale/lv/viewer.ftl +0 -63
  208. package/static/assets/pdfjs/web/locale/meh/viewer.ftl +0 -75
  209. package/static/assets/pdfjs/web/locale/mk/viewer.ftl +0 -63
  210. package/static/assets/pdfjs/web/locale/ml/viewer.ftl +0 -3
  211. package/static/assets/pdfjs/web/locale/mr/viewer.ftl +0 -63
  212. package/static/assets/pdfjs/web/locale/ms/viewer.ftl +0 -63
  213. package/static/assets/pdfjs/web/locale/my/viewer.ftl +0 -71
  214. package/static/assets/pdfjs/web/locale/nb-NO/viewer.ftl +44 -6
  215. package/static/assets/pdfjs/web/locale/ne-NP/viewer.ftl +0 -71
  216. package/static/assets/pdfjs/web/locale/nl/viewer.ftl +38 -0
  217. package/static/assets/pdfjs/web/locale/nn-NO/viewer.ftl +45 -1
  218. package/static/assets/pdfjs/web/locale/oc/viewer.ftl +0 -31
  219. package/static/assets/pdfjs/web/locale/pa-IN/viewer.ftl +38 -0
  220. package/static/assets/pdfjs/web/locale/pl/viewer.ftl +39 -1
  221. package/static/assets/pdfjs/web/locale/pt-BR/viewer.ftl +38 -0
  222. package/static/assets/pdfjs/web/locale/ro/viewer.ftl +355 -1
  223. package/static/assets/pdfjs/web/locale/ru/viewer.ftl +38 -0
  224. package/static/assets/pdfjs/web/locale/sat/viewer.ftl +0 -54
  225. package/static/assets/pdfjs/web/locale/sc/viewer.ftl +0 -38
  226. package/static/assets/pdfjs/web/locale/scn/viewer.ftl +0 -92
  227. package/static/assets/pdfjs/web/locale/sco/viewer.ftl +0 -60
  228. package/static/assets/pdfjs/web/locale/si/viewer.ftl +0 -51
  229. package/static/assets/pdfjs/web/locale/sk/viewer.ftl +38 -0
  230. package/static/assets/pdfjs/web/locale/skr/viewer.ftl +0 -27
  231. package/static/assets/pdfjs/web/locale/sl/viewer.ftl +8 -0
  232. package/static/assets/pdfjs/web/locale/son/viewer.ftl +0 -71
  233. package/static/assets/pdfjs/web/locale/sr/viewer.ftl +0 -33
  234. package/static/assets/pdfjs/web/locale/sv-SE/viewer.ftl +38 -0
  235. package/static/assets/pdfjs/web/locale/szl/viewer.ftl +0 -63
  236. package/static/assets/pdfjs/web/locale/ta/viewer.ftl +0 -63
  237. package/static/assets/pdfjs/web/locale/te/viewer.ftl +0 -60
  238. package/static/assets/pdfjs/web/locale/tg/viewer.ftl +38 -0
  239. package/static/assets/pdfjs/web/locale/tl/viewer.ftl +0 -63
  240. package/static/assets/pdfjs/web/locale/tr/viewer.ftl +40 -2
  241. package/static/assets/pdfjs/web/locale/trs/viewer.ftl +0 -72
  242. package/static/assets/pdfjs/web/locale/ur/viewer.ftl +0 -60
  243. package/static/assets/pdfjs/web/locale/uz/viewer.ftl +0 -71
  244. package/static/assets/pdfjs/web/locale/vi/viewer.ftl +38 -0
  245. package/static/assets/pdfjs/web/locale/wo/viewer.ftl +0 -77
  246. package/static/assets/pdfjs/web/locale/xh/viewer.ftl +0 -71
  247. package/static/assets/pdfjs/web/locale/zh-CN/viewer.ftl +38 -0
  248. package/static/assets/pdfjs/web/locale/zh-TW/viewer.ftl +38 -0
  249. package/static/assets/pdfjs/web/viewer.css +649 -120
  250. package/static/assets/pdfjs/web/viewer.html +19 -0
  251. package/static/assets/pdfjs/web/viewer.mjs +489 -38
  252. package/static/assets/pdfjs/web/viewer.mjs.map +1 -1
  253. package/static/chunk-22EANI6R.js +1 -0
  254. package/static/{chunk-KFM544CA.js → chunk-2UWN7IQF.js} +1 -1
  255. package/static/{chunk-N3T57OCA.js → chunk-2VSPDSJS.js} +1 -1
  256. package/static/{chunk-HUWQHCUX.js → chunk-34UZ7SYI.js} +1 -1
  257. package/static/{chunk-MWFRZBJD.js → chunk-45UQJGGY.js} +1 -1
  258. package/static/{chunk-LYTD6AJE.js → chunk-5TEXH3LJ.js} +1 -1
  259. package/static/{chunk-4KESSWTF.js → chunk-66FMKVJX.js} +1 -1
  260. package/static/{chunk-XE5YHU5J.js → chunk-BIUNUYZ5.js} +1 -1
  261. package/static/chunk-CK4BY2NX.js +27 -0
  262. package/static/{chunk-QTW62OKJ.js → chunk-CSBDAY77.js} +1 -1
  263. package/static/{chunk-XUZSYWRF.js → chunk-CXXPLBDZ.js} +1 -1
  264. package/static/{chunk-ZTXJC5IC.js → chunk-EILQG525.js} +1 -1
  265. package/static/{chunk-FJFNDK67.js → chunk-ENWABUR4.js} +1 -1
  266. package/static/{chunk-WL65GYD5.js → chunk-FR4AOLYL.js} +4 -4
  267. package/static/chunk-HW2H3ISM.js +559 -0
  268. package/static/{chunk-BW5PQAKK.js → chunk-HYMDGBZL.js} +1 -1
  269. package/static/{chunk-WLPYIJFI.js → chunk-IML5UYQG.js} +1 -1
  270. package/static/{chunk-Z5X7LVMZ.js → chunk-IPSMJHMQ.js} +1 -1
  271. package/static/{chunk-3S4WNZ2T.js → chunk-JVCWYSNP.js} +1 -1
  272. package/static/{chunk-CLSVDV7J.js → chunk-KGPCIUD2.js} +1 -1
  273. package/static/{chunk-O4AQBQBF.js → chunk-KQZJSEM3.js} +1 -1
  274. package/static/{chunk-MK7WZG3F.js → chunk-NPEMJJIU.js} +1 -1
  275. package/static/{chunk-4TEHM3AS.js → chunk-OEFBC4GG.js} +1 -1
  276. package/static/{chunk-O67RFAWU.js → chunk-P734A3XZ.js} +1 -1
  277. package/static/{chunk-SRLMFJ7C.js → chunk-RASR4CK6.js} +1 -1
  278. package/static/{chunk-S5WXHO6D.js → chunk-RFMOUC22.js} +1 -1
  279. package/static/{chunk-TTQ37MUV.js → chunk-RSS6GYNE.js} +1 -1
  280. package/static/{chunk-3FX6ISDY.js → chunk-SBOQGGZX.js} +1 -1
  281. package/static/{chunk-NV2MEIWP.js → chunk-SJAFPXQV.js} +1 -1
  282. package/static/{chunk-PYSFXLMV.js → chunk-XTYGMF2V.js} +1 -1
  283. package/static/{chunk-ZFKCGL6X.js → chunk-YCWMV2YR.js} +1 -1
  284. package/static/{chunk-LB7B5RIV.js → chunk-YGD22MWQ.js} +1 -1
  285. package/static/{chunk-MTRNPGS4.js → chunk-ZC5NIT55.js} +1 -1
  286. package/static/{chunk-SKDQM65G.js → chunk-ZVY37DKS.js} +1 -1
  287. package/static/index.html +2 -2
  288. package/static/main-N5CZRHAO.js +7 -0
  289. package/static/styles-FYUSO6OJ.css +1 -0
  290. package/static/chunk-AY2GOSJ2.js +0 -24
  291. package/static/chunk-RSNLYAN6.js +0 -560
  292. package/static/chunk-ZZ3LHYOY.js +0 -1
  293. package/static/main-RREKR34B.js +0 -10
  294. package/static/styles-3DONJ2Z4.css +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/users/services/users-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 { Test, TestingModule } from '@nestjs/testing'\nimport { AuthManager } from '../../../authentication/services/auth-manager.service'\nimport { pngMimeType, svgMimeType } from '../../../common/image'\nimport { Cache } from '../../../infrastructure/cache/services/cache.service'\nimport { DB_TOKEN_PROVIDER } from '../../../infrastructure/database/constants'\nimport { fileName, isPathExists } from '../../files/utils/files'\nimport { USER_ROLE } from '../constants/user'\nimport { CreateUserDto } from '../dto/create-or-update-user.dto'\nimport { DeleteUserDto } from '../dto/delete-user.dto'\nimport { UserModel } from '../models/user.model'\nimport { generateUserTest } from '../utils/test'\nimport { AdminUsersManager } from './admin-users-manager.service'\nimport { AdminUsersQueries } from './admin-users-queries.service'\nimport { UsersManager } from './users-manager.service'\nimport { UsersQueries } from './users-queries.service'\n\ndescribe(UsersManager.name, () => {\n let usersManager: UsersManager\n let adminUsersManager: AdminUsersManager\n let adminUsersQueries: AdminUsersQueries\n let usersQueriesService: UsersQueries\n let userTest: UserModel\n let deleteUserDto: DeleteUserDto\n\n beforeAll(async () => {\n const module: TestingModule = await Test.createTestingModule({\n providers: [\n AdminUsersManager,\n AdminUsersQueries,\n UsersManager,\n UsersQueries,\n { provide: AuthManager, useValue: {} },\n { provide: DB_TOKEN_PROVIDER, useValue: {} },\n {\n provide: Cache,\n useValue: {}\n }\n ]\n }).compile()\n\n module.useLogger(['fatal'])\n usersManager = module.get<UsersManager>(UsersManager)\n adminUsersManager = module.get<AdminUsersManager>(AdminUsersManager)\n adminUsersQueries = module.get<AdminUsersQueries>(AdminUsersQueries)\n usersQueriesService = module.get<UsersQueries>(UsersQueries)\n // mocks\n userTest = new UserModel(generateUserTest(), false)\n deleteUserDto = { deleteSpace: true } satisfies DeleteUserDto\n })\n\n afterAll(async () => {\n // clean created user path\n await expect(adminUsersManager.deleteUserSpace(userTest.login)).resolves.not.toThrow()\n })\n\n it('should be defined', () => {\n expect(usersManager).toBeDefined()\n expect(adminUsersManager).toBeDefined()\n expect(usersQueriesService).toBeDefined()\n expect(userTest).toBeDefined()\n })\n\n it('should get the user with|without password', async () => {\n usersQueriesService.from = jest.fn().mockReturnValue(userTest)\n const findUserWithoutPwd: any = await usersManager.findUser(userTest.login, true)\n expect(findUserWithoutPwd).toBeInstanceOf(UserModel)\n expect(findUserWithoutPwd.password).toBeUndefined()\n const findUserWithPwd = await usersManager.findUser(userTest.login, false)\n expect(findUserWithPwd).toBeInstanceOf(UserModel)\n expect(findUserWithPwd.password).toBeDefined()\n expect(usersQueriesService.from).toHaveBeenCalledTimes(2)\n const me: any = await usersManager.me(userTest)\n // check the default value of the findUser function\n expect(me).toBeInstanceOf(Object)\n expect(me.user.password).toBeUndefined()\n expect(await usersManager.me(userTest)).toBeInstanceOf(Object)\n usersQueriesService.from = jest.fn().mockReturnValue(null)\n await expect(usersManager.me({ id: 0 } as UserModel)).rejects.toThrow()\n expect(usersQueriesService.from).toHaveBeenCalled()\n })\n\n it('should create the user paths', async () => {\n await expect(userTest.makePaths()).resolves.not.toThrow()\n expect(await isPathExists(userTest.filesPath)).toBe(true)\n })\n\n it('should get the default user avatar', async () => {\n usersQueriesService.from = jest.fn().mockReturnValueOnce(userTest)\n const [path, mime] = await usersManager.getAvatar(userTest.login)\n expect(fileName(path)).toBe('avatar.svg')\n expect(mime).toBe(svgMimeType)\n })\n\n it('should generate the user avatar', async () => {\n usersQueriesService.from = jest.fn().mockReturnValueOnce(null)\n await expect(usersManager.getAvatar('#', true)).rejects.toThrow('does not exist')\n usersQueriesService.from = jest.fn().mockReturnValue(userTest)\n expect(await usersManager.getAvatar(userTest.login, true)).toBeUndefined()\n const [path, mime] = await usersManager.getAvatar(userTest.login)\n expect(fileName(path)).toBe('avatar.png')\n expect(mime).toBe(pngMimeType)\n })\n\n it('should create user that does not exist', async () => {\n usersQueriesService.checkUserExists = jest.fn().mockReturnValue(undefined)\n usersQueriesService.createUserOrGuest = jest.fn().mockReturnValue(888)\n const user = await adminUsersManager.createUserOrGuest(userTest satisfies CreateUserDto, USER_ROLE.USER)\n expect(user).toBeInstanceOf(UserModel)\n expect(await isPathExists(user.filesPath)).toBe(true)\n })\n\n it('should not create an existing user', async () => {\n usersQueriesService.checkUserExists = jest\n .fn()\n .mockReturnValueOnce({ login: userTest.login, email: '' })\n .mockReturnValueOnce({ login: '', email: userTest.email })\n .mockReturnValueOnce(undefined)\n await expect(adminUsersManager.createUserOrGuest(userTest satisfies CreateUserDto, USER_ROLE.USER)).rejects.toThrow()\n await expect(adminUsersManager.createUserOrGuest(userTest satisfies CreateUserDto, USER_ROLE.USER)).rejects.toThrow()\n usersQueriesService.createUserOrGuest = jest.fn().mockImplementation(() => {\n throw new Error('testing')\n })\n await expect(adminUsersManager.createUserOrGuest(userTest satisfies CreateUserDto, USER_ROLE.USER)).rejects.toThrow()\n })\n\n it('should delete user', async () => {\n adminUsersQueries.deleteUser = jest.fn().mockReturnValue(true)\n await expect(adminUsersManager.deleteUserOrGuest(userTest.id, userTest.login, deleteUserDto)).resolves.not.toThrow()\n expect(await isPathExists(userTest.filesPath)).toBe(false)\n })\n\n it('should pass even if the user does not exist', async () => {\n adminUsersQueries.deleteUser = jest.fn().mockReturnValue(false)\n await expect(adminUsersManager.deleteUserOrGuest(userTest.id, userTest.login, deleteUserDto)).resolves.not.toThrow()\n })\n\n it('should throw an error on user creation', async () => {\n adminUsersQueries.deleteUser = jest.fn().mockImplementation(() => {\n throw new Error('testing')\n })\n await expect(adminUsersManager.deleteUserOrGuest(userTest.id, userTest.login, deleteUserDto)).rejects.toThrow()\n })\n})\n"],"names":["describe","UsersManager","name","usersManager","adminUsersManager","adminUsersQueries","usersQueriesService","userTest","deleteUserDto","beforeAll","module","Test","createTestingModule","providers","AdminUsersManager","AdminUsersQueries","UsersQueries","provide","AuthManager","useValue","DB_TOKEN_PROVIDER","Cache","compile","useLogger","get","UserModel","generateUserTest","deleteSpace","afterAll","expect","deleteUserSpace","login","resolves","not","toThrow","it","toBeDefined","from","jest","fn","mockReturnValue","findUserWithoutPwd","findUser","toBeInstanceOf","password","toBeUndefined","findUserWithPwd","toHaveBeenCalledTimes","me","Object","user","id","rejects","toHaveBeenCalled","makePaths","isPathExists","filesPath","toBe","mockReturnValueOnce","path","mime","getAvatar","fileName","svgMimeType","pngMimeType","checkUserExists","undefined","createUserOrGuest","USER_ROLE","USER","email","mockImplementation","Error","deleteUser","deleteUserOrGuest"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/users/services/users-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 { Test, TestingModule } from '@nestjs/testing'\nimport bcrypt from 'bcryptjs'\nimport path from 'node:path'\nimport { Readable } from 'node:stream'\nimport { AuthManager } from '../../../authentication/services/auth-manager.service'\nimport { comparePassword } from '../../../common/functions'\nimport * as imageModule from '../../../common/image'\nimport { pngMimeType, svgMimeType } from '../../../common/image'\nimport { Cache } from '../../../infrastructure/cache/services/cache.service'\nimport { DB_TOKEN_PROVIDER } from '../../../infrastructure/database/constants'\nimport * as filesUtilsModule from '../../files/utils/files'\nimport { fileName, isPathExists } from '../../files/utils/files'\nimport { MEMBER_TYPE } from '../constants/member'\nimport { USER_GROUP_ROLE, USER_MAX_PASSWORD_ATTEMPTS, USER_ROLE } from '../constants/user'\nimport { CreateUserDto } from '../dto/create-or-update-user.dto'\nimport { DeleteUserDto } from '../dto/delete-user.dto'\nimport { UserModel } from '../models/user.model'\nimport { generateUserTest } from '../utils/test'\nimport { AdminUsersManager } from './admin-users-manager.service'\nimport { AdminUsersQueries } from './admin-users-queries.service'\nimport { UsersManager } from './users-manager.service'\nimport { UsersQueries } from './users-queries.service'\n\njest.mock('../../../common/functions', () => {\n const actual = jest.requireActual('../../../common/functions')\n return { ...actual, comparePassword: jest.fn() }\n})\njest.mock('bcryptjs', () => ({ __esModule: true, default: { hash: jest.fn(() => Promise.resolve('hashed-password')) } }))\njest.mock('../../../common/image', () => {\n const actual = jest.requireActual('../../../common/image')\n return {\n ...actual,\n generateAvatar: jest.fn(() => Readable.from([Buffer.from('PNGDATA')])),\n convertImageToBase64: jest.fn(() => Promise.resolve('BASE64_IMAGE'))\n }\n})\n\ndescribe(UsersManager.name, () => {\n let usersManager: UsersManager\n let adminUsersManager: AdminUsersManager\n let adminUsersQueries: AdminUsersQueries\n let usersQueriesService: UsersQueries\n let userTest: UserModel\n let deleteUserDto: DeleteUserDto\n const flush = () => new Promise<void>((r) => setImmediate(r))\n const okStream = (d = 'OK') => {\n const s: any = Readable.from([Buffer.from(d)])\n s.truncated = false\n return s\n }\n const errStream = (msg = 'err', truncated = false) => {\n const s: any = new Readable({\n read() {\n this.destroy(new Error(msg))\n }\n })\n s.truncated = truncated\n return s\n }\n const mkReq = (mimetype: string, stream: any, user = userTest) => ({ user, file: jest.fn().mockResolvedValue({ mimetype, file: stream }) })\n const ensurePaths = async () => {\n if (!(await isPathExists(userTest.homePath))) {\n await userTest.makePaths()\n }\n }\n\n beforeAll(async () => {\n const module: TestingModule = await Test.createTestingModule({\n providers: [\n AdminUsersManager,\n AdminUsersQueries,\n UsersManager,\n UsersQueries,\n { provide: AuthManager, useValue: {} },\n { provide: DB_TOKEN_PROVIDER, useValue: {} },\n { provide: Cache, useValue: {} }\n ]\n }).compile()\n module.useLogger(['fatal'])\n usersManager = module.get(UsersManager)\n adminUsersManager = module.get(AdminUsersManager)\n adminUsersQueries = module.get(AdminUsersQueries)\n usersQueriesService = module.get(UsersQueries)\n userTest = new UserModel(generateUserTest(), false)\n deleteUserDto = { deleteSpace: true } satisfies DeleteUserDto\n })\n\n afterEach(() => jest.restoreAllMocks())\n\n afterAll(async () => {\n await expect(adminUsersManager.deleteUserSpace(userTest.login)).resolves.not.toThrow()\n })\n\n it('instances + findUser/me/fromUserId + impersonation', async () => {\n expect(usersManager && adminUsersManager && usersQueriesService && userTest).toBeDefined()\n usersQueriesService.from = jest.fn().mockReturnValue(userTest)\n const u1: any = await usersManager.findUser(userTest.login, true)\n expect(u1).toBeInstanceOf(UserModel)\n expect(u1.password).toBeUndefined()\n const u2 = await usersManager.findUser(userTest.login, false)\n expect(u2).toBeInstanceOf(UserModel)\n expect(u2.password).toBeDefined()\n const me1: any = await usersManager.me(userTest)\n expect(me1.user.password).toBeUndefined()\n usersQueriesService.from = jest.fn().mockReturnValue(null)\n await expect(usersManager.findUser('unknown')).resolves.toBeNull()\n await expect(usersManager.me({ id: 0 } as UserModel)).rejects.toThrow()\n usersQueriesService.from = jest.fn().mockResolvedValue(null)\n await expect(usersManager.fromUserId(123)).resolves.toBeNull()\n const authUser = new UserModel({ ...generateUserTest(), id: 42, clientId: 'CID', impersonatedFromId: 1 } as any, true)\n const fromUser = new UserModel({ ...generateUserTest(), id: 42 }, true)\n usersQueriesService.from = jest.fn().mockResolvedValue(fromUser)\n const me2 = await usersManager.me(authUser)\n expect(me2.user.impersonated).toBe(true)\n expect(me2.user.clientId).toBe('CID')\n })\n\n it('paths + avatars (default/generate) + create/delete user', async () => {\n await expect(ensurePaths()).resolves.not.toThrow()\n expect(await isPathExists(userTest.filesPath)).toBe(true)\n usersQueriesService.from = jest.fn().mockReturnValueOnce(userTest)\n const [p0, m0] = await usersManager.getAvatar(userTest.login)\n expect(fileName(p0)).toBe('avatar.svg')\n expect(m0).toBe(svgMimeType)\n usersQueriesService.from = jest.fn().mockReturnValueOnce(null)\n await expect(usersManager.getAvatar('#', true)).rejects.toThrow('does not exist')\n usersQueriesService.from = jest.fn().mockReturnValue(userTest)\n expect(await usersManager.getAvatar(userTest.login, true)).toBeUndefined()\n const [p1, m1] = await usersManager.getAvatar(userTest.login)\n expect(fileName(p1)).toBe('avatar.png')\n expect(m1).toBe(pngMimeType)\n\n usersQueriesService.checkUserExists = jest.fn().mockReturnValue(undefined)\n usersQueriesService.createUserOrGuest = jest.fn().mockReturnValue(888)\n const created = await adminUsersManager.createUserOrGuest(userTest satisfies CreateUserDto, USER_ROLE.USER)\n expect(created).toBeInstanceOf(UserModel)\n expect(await isPathExists(created.filesPath)).toBe(true)\n\n usersQueriesService.checkUserExists = jest\n .fn()\n .mockReturnValueOnce({ login: userTest.login, email: '' })\n .mockReturnValueOnce({ login: '', email: userTest.email })\n .mockReturnValueOnce(undefined)\n await expect(adminUsersManager.createUserOrGuest(userTest satisfies CreateUserDto, USER_ROLE.USER)).rejects.toThrow()\n await expect(adminUsersManager.createUserOrGuest(userTest satisfies CreateUserDto, USER_ROLE.USER)).rejects.toThrow()\n usersQueriesService.createUserOrGuest = jest.fn().mockImplementation(() => {\n throw new Error('testing')\n })\n await expect(adminUsersManager.createUserOrGuest(userTest satisfies CreateUserDto, USER_ROLE.USER)).rejects.toThrow()\n\n adminUsersQueries.deleteUser = jest.fn().mockReturnValue(true)\n await expect(adminUsersManager.deleteUserOrGuest(userTest.id, userTest.login, deleteUserDto)).resolves.not.toThrow()\n expect(await isPathExists(userTest.filesPath)).toBe(false)\n adminUsersQueries.deleteUser = jest.fn().mockReturnValue(false)\n await expect(adminUsersManager.deleteUserOrGuest(userTest.id, userTest.login, deleteUserDto)).resolves.not.toThrow()\n adminUsersQueries.deleteUser = jest.fn().mockImplementation(() => {\n throw new Error('testing')\n })\n await expect(adminUsersManager.deleteUserOrGuest(userTest.id, userTest.login, deleteUserDto)).rejects.toThrow()\n })\n\n it('logUser branches: forbidden/locked/bad/good', async () => {\n const linkUser = new UserModel({ ...generateUserTest(), role: USER_ROLE.LINK }, false)\n await expect(usersManager.logUser(linkUser, 'x', '127.0.0.1')).rejects.toThrow('Account is not allowed')\n\n const uLocked = new UserModel({ ...generateUserTest(), isActive: false, passwordAttempts: 5 }, false)\n const errSpy = jest.spyOn((usersManager as any)['logger'], 'error').mockImplementation(() => undefined as any)\n const updSpy1 = jest.spyOn(usersManager, 'updateAccesses').mockRejectedValue(new Error('reject-locked'))\n await expect(usersManager.logUser(uLocked, 'pwd', 'ip')).rejects.toThrow('Account locked')\n await flush()\n expect(errSpy).toHaveBeenCalledWith(expect.stringContaining('reject-locked'))\n expect(updSpy1).toHaveBeenCalledWith(uLocked, 'ip', false)\n ;(comparePassword as jest.Mock).mockResolvedValue(false)\n const uBad = new UserModel({ ...generateUserTest(), isActive: true, passwordAttempts: 0 }, false)\n const errSpy2 = jest.spyOn((usersManager as any)['logger'], 'error').mockImplementation(() => undefined as any)\n const updSpy2 = jest.spyOn(usersManager, 'updateAccesses').mockRejectedValue(new Error('reject-auth'))\n const out = await usersManager.logUser(uBad, 'bad', '1.1.1.1')\n expect(out).toBeNull()\n await flush()\n expect(errSpy2).toHaveBeenCalledWith(expect.stringContaining('reject-auth'))\n expect(updSpy2).toHaveBeenCalledWith(uBad, '1.1.1.1', false)\n ;(comparePassword as jest.Mock).mockResolvedValue(true)\n const uGood = new UserModel({ ...generateUserTest(), isActive: true, passwordAttempts: 0 }, false)\n const updSpy3 = jest.spyOn(usersManager, 'updateAccesses').mockResolvedValue(undefined)\n const pathsSpy = jest.spyOn(uGood, 'makePaths').mockResolvedValue(undefined)\n const out2 = await usersManager.logUser(uGood, 'good', '8.8.8.8')\n expect(out2).toBe(uGood)\n expect(updSpy3).toHaveBeenCalledWith(uGood, '8.8.8.8', true)\n expect(pathsSpy).toHaveBeenCalled()\n })\n\n it('compareUserPassword + updateLanguage + updatePassword branches', async () => {\n usersQueriesService.compareUserPassword = jest.fn().mockResolvedValue(true)\n await expect(usersManager.compareUserPassword(1, 'p')).resolves.toBe(true)\n expect(usersQueriesService.compareUserPassword).toHaveBeenCalledWith(1, 'p')\n\n usersQueriesService.updateUserOrGuest = jest.fn().mockResolvedValue(false)\n await expect(usersManager.updateLanguage(userTest, { language: '' })).rejects.toThrow('Unable to update language')\n expect(usersQueriesService.updateUserOrGuest).toHaveBeenCalledWith(userTest.id, { language: null })\n usersQueriesService.updateUserOrGuest = jest.fn().mockResolvedValue(true)\n await expect(usersManager.updateLanguage(userTest, { language: 'fr' })).resolves.toBeUndefined()\n\n usersQueriesService.selectUserProperties = jest.fn().mockResolvedValue(null)\n await expect(usersManager.updatePassword(userTest, { oldPassword: 'a', newPassword: 'b' })).rejects.toThrow('Unable to check password')\n usersQueriesService.selectUserProperties = jest.fn().mockResolvedValue({ password: 'HASH' })\n ;(comparePassword as jest.Mock).mockResolvedValue(false)\n await expect(usersManager.updatePassword(userTest, { oldPassword: 'a', newPassword: 'b' })).rejects.toThrow('Password mismatch')\n ;(comparePassword as jest.Mock).mockResolvedValue(true)\n ;(bcrypt.hash as unknown as jest.Mock).mockResolvedValue('HASHED')\n usersQueriesService.updateUserOrGuest = jest.fn().mockResolvedValue(true)\n await expect(usersManager.updatePassword(userTest, { oldPassword: 'a', newPassword: 'b' })).resolves.toBeUndefined()\n expect(usersQueriesService.updateUserOrGuest).toHaveBeenCalledWith(userTest.id, { password: 'HASHED' })\n usersQueriesService.updateUserOrGuest = jest.fn().mockResolvedValue(false)\n usersQueriesService.selectUserProperties = jest.fn().mockResolvedValue({ password: 'HASH' })\n ;(comparePassword as jest.Mock).mockResolvedValue(true)\n ;(bcrypt.hash as unknown as jest.Mock).mockResolvedValue('HASHED2')\n await expect(usersManager.updatePassword(userTest, { oldPassword: 'a', newPassword: 'b' })).rejects.toThrow('Unable to update password')\n })\n\n it('updateNotification + updateAccesses branches', async () => {\n usersQueriesService.updateUserOrGuest = jest.fn().mockResolvedValue(false)\n await expect(usersManager.updateNotification(userTest, { notification: 1 })).rejects.toThrow('Unable to update notification')\n usersQueriesService.updateUserOrGuest = jest.fn().mockResolvedValue(true)\n await expect(usersManager.updateNotification(userTest, { notification: 2 })).resolves.toBeUndefined()\n\n const prevAccess1 = new Date('2021-01-01T00:00:00Z')\n const u1 = new UserModel(\n { ...generateUserTest(), isActive: true, passwordAttempts: 3, currentIp: '1.2.3.4', currentAccess: prevAccess1 } as any,\n false\n )\n usersQueriesService.updateUserOrGuest = jest.fn().mockResolvedValue(true)\n await expect(usersManager.updateAccesses(u1, '5.6.7.8', true)).resolves.toBeUndefined()\n const payload1 = (usersQueriesService.updateUserOrGuest as jest.Mock).mock.calls[0][1]\n expect(payload1).toMatchObject({ lastIp: '1.2.3.4', currentIp: '5.6.7.8', passwordAttempts: 0, isActive: true })\n expect(payload1.lastAccess).toBe(prevAccess1)\n expect(payload1.currentAccess).toBeInstanceOf(Date)\n\n const prevAccess2 = new Date('2022-02-02T00:00:00Z')\n const u2 = new UserModel(\n {\n ...generateUserTest(),\n isActive: true,\n passwordAttempts: USER_MAX_PASSWORD_ATTEMPTS - 1,\n currentIp: 'old.ip',\n currentAccess: prevAccess2\n } as any,\n false\n )\n usersQueriesService.updateUserOrGuest = jest.fn().mockResolvedValue(true)\n await expect(usersManager.updateAccesses(u2, 'new.ip', false)).resolves.toBeUndefined()\n const payload2 = (usersQueriesService.updateUserOrGuest as jest.Mock).mock.calls[0][1]\n expect(payload2.passwordAttempts).toBe(USER_MAX_PASSWORD_ATTEMPTS)\n expect(payload2.isActive).toBe(false)\n expect(payload2.lastAccess).toBe(prevAccess2)\n expect(payload2.lastIp).toBe('old.ip')\n expect(payload2.currentIp).toBe('new.ip')\n expect(payload2.currentAccess).toBeInstanceOf(Date)\n })\n\n it('avatars advanced: generateIsNotExists, failure branches, base64 fallback', async () => {\n await ensurePaths()\n usersManager.findUser = jest.fn().mockResolvedValue({ getInitials: () => 'UT' } as unknown as UserModel)\n const [p, m] = (await usersManager.getAvatar(userTest.login, false, true)) as [string, string]\n expect(fileName(p)).toBe('avatar.png')\n expect(m).toBe(pngMimeType)\n jest.spyOn(imageModule, 'generateAvatar').mockImplementation(() => errStream('gen error'))\n await expect(usersManager.getAvatar(userTest.login, true)).rejects.toThrow('Unable to create avatar')\n usersManager.findUser = jest.fn().mockResolvedValue(null)\n await expect(usersManager.getAvatar(userTest.login, true)).rejects.toThrow('avatar not found')\n const s1 = await usersManager.getAvatarBase64(userTest.login)\n expect(s1).toBe('BASE64_IMAGE')\n ;(imageModule.convertImageToBase64 as jest.Mock).mockClear()\n const s2 = await usersManager.getAvatarBase64('non-existent-login')\n expect(s2).toBe('BASE64_IMAGE')\n expect(imageModule.convertImageToBase64).toHaveBeenCalledWith(expect.stringMatching(/avatar\\.svg$/))\n })\n\n it('updateAvatar branches: mime error, stream error, truncated, move fail, success', async () => {\n await ensurePaths()\n await expect(usersManager.updateAvatar(mkReq('text/plain', okStream('X')) as any)).rejects.toThrow('Unsupported file type')\n await expect(usersManager.updateAvatar(mkReq('image/png', errStream('stream error')) as any)).rejects.toThrow('Unable to upload avatar')\n\n const t = okStream('OK')\n t.truncated = true\n const mvSpy = jest.spyOn(filesUtilsModule, 'moveFiles').mockResolvedValue(undefined)\n await expect(usersManager.updateAvatar(mkReq('image/png', t) as any)).rejects.toThrow('Image is too large (5MB max)')\n expect(mvSpy).not.toHaveBeenCalled()\n\n jest.spyOn(filesUtilsModule, 'moveFiles').mockRejectedValue(new Error('mv fail'))\n await expect(usersManager.updateAvatar(mkReq('image/png', okStream()) as any)).rejects.toThrow('Unable to create avatar')\n\n const mvSpy2 = jest.spyOn(filesUtilsModule, 'moveFiles').mockResolvedValue(undefined)\n await expect(usersManager.updateAvatar(mkReq('image/png', okStream()) as any)).resolves.toBeUndefined()\n const expectedSrc = path.join(userTest.tmpPath, 'avatar.png')\n const expectedDst = path.join(userTest.homePath, 'avatar.png')\n expect(mvSpy2).toHaveBeenCalledWith(expectedSrc, expectedDst, true)\n })\n\n it('setOnlineStatus + browseGroups + getGroup', async () => {\n usersQueriesService.setOnlineStatus = jest.fn().mockRejectedValue(new Error('boom'))\n expect(() => usersManager.setOnlineStatus({ id: 1 } as any, 1 as any)).not.toThrow()\n\n usersQueriesService.browseRootGroups = jest.fn().mockResolvedValue([{ id: 1 }])\n const root = await usersManager.browseGroups(userTest, '')\n expect(root.parentGroup).toBeUndefined()\n expect(root.members.length).toBe(1)\n usersQueriesService.groupFromName = jest.fn().mockResolvedValue(null)\n await expect(usersManager.browseGroups(userTest, 'unknown')).rejects.toThrow('Group not found')\n const group = { id: 42, name: 'Team' }\n usersQueriesService.groupFromName = jest.fn().mockResolvedValue(group)\n usersQueriesService.browseGroupMembers = jest.fn().mockResolvedValue([{ id: 7 }, { id: 8 }])\n const g2 = await usersManager.browseGroups(userTest, 'Team')\n expect(g2.parentGroup).toEqual(group)\n expect(g2.members).toEqual([{ id: 7 }, { id: 8 }])\n expect(usersQueriesService.browseGroupMembers).toHaveBeenCalledWith(42)\n\n usersQueriesService.getGroupWithMembers = jest.fn().mockResolvedValue({ id: 1, members: [] })\n await expect(usersManager.getGroup(userTest, 1)).resolves.toEqual({ id: 1, members: [] })\n usersQueriesService.getGroup = jest.fn().mockResolvedValue({ id: 2 })\n await expect(usersManager.getGroup(userTest, 2, false)).resolves.toEqual({ id: 2 })\n usersQueriesService.getGroup = jest.fn().mockResolvedValue(null)\n await expect(usersManager.getGroup(userTest, 3, false)).rejects.toThrow('You are not allowed to do this action')\n })\n\n it('create/update personal group', async () => {\n await expect(usersManager.createPersonalGroup(userTest, { name: '' } as any)).rejects.toThrow('Group name is missing')\n usersQueriesService.checkGroupNameExists = jest.fn().mockResolvedValue(true)\n await expect(usersManager.createPersonalGroup(userTest, { name: 'A' })).rejects.toThrow('Name already used')\n usersQueriesService.checkGroupNameExists = jest.fn().mockResolvedValue(false)\n usersQueriesService.createPersonalGroup = jest.fn().mockResolvedValue(10)\n usersQueriesService.clearWhiteListCaches = jest.fn()\n usersManager.getGroup = jest.fn().mockResolvedValue({ id: 10 })\n const logSpy = jest.spyOn((usersManager as any)['logger'], 'log').mockImplementation(() => undefined as any)\n await expect(usersManager.createPersonalGroup(userTest, { name: 'OK' })).resolves.toEqual({ id: 10 })\n expect(logSpy).toHaveBeenCalled()\n usersQueriesService.createPersonalGroup = jest.fn().mockRejectedValue(new Error('db down'))\n await expect(usersManager.createPersonalGroup(userTest, { name: 'OK' })).rejects.toThrow('Unable to create group')\n\n await expect(usersManager.updatePersonalGroup(userTest, 1, {} as any)).rejects.toThrow('No changes to update')\n usersManager.getGroup = jest.fn().mockResolvedValueOnce({ id: 1, type: MEMBER_TYPE.GROUP })\n await expect(usersManager.updatePersonalGroup(userTest, 1, { name: 'x' })).rejects.toThrow('You are not allowed to do this action')\n usersManager.getGroup = jest.fn().mockResolvedValue({ id: 1, type: MEMBER_TYPE.PGROUP })\n usersQueriesService.checkGroupNameExists = jest.fn().mockResolvedValue(true)\n await expect(usersManager.updatePersonalGroup(userTest, 1, { name: 'dup' })).rejects.toThrow('Name already used')\n usersQueriesService.checkGroupNameExists = jest.fn().mockResolvedValue(false)\n usersQueriesService.updateGroup = jest.fn().mockRejectedValue(new Error('oops'))\n await expect(usersManager.updatePersonalGroup(userTest, 1, { name: 'ok' })).rejects.toThrow('oops')\n usersQueriesService.updateGroup = jest.fn().mockResolvedValue(true)\n usersManager.getGroup = jest.fn().mockResolvedValue({ id: 1, type: MEMBER_TYPE.PGROUP })\n await expect(usersManager.updatePersonalGroup(userTest, 1, { name: 'ok' })).resolves.not.toThrow()\n expect(usersManager.getGroup).toHaveBeenCalledWith(userTest, 1, false, userTest.isAdmin)\n })\n\n it('addUsersToGroup (GROUP/PGROUP)', async () => {\n usersManager.getGroup = jest.fn().mockResolvedValue({ id: 1, type: MEMBER_TYPE.GROUP, members: [{ id: 2 }, { id: 3 }] })\n usersQueriesService.usersWhitelist = jest.fn().mockResolvedValue([3, 4, 5])\n await expect(usersManager.addUsersToGroup(userTest, 1, [2, 3])).rejects.toThrow('No users to add to group')\n usersQueriesService.updateGroupMembers = jest.fn().mockResolvedValue(undefined)\n await expect(usersManager.addUsersToGroup(userTest, 1, [3, 4, 5])).resolves.toBeUndefined()\n expect(usersQueriesService.updateGroupMembers).toHaveBeenCalledWith(1, {\n add: [\n { id: 4, groupRole: USER_GROUP_ROLE.MEMBER },\n { id: 5, groupRole: USER_GROUP_ROLE.MEMBER }\n ]\n })\n expect(usersQueriesService.usersWhitelist).toHaveBeenCalledWith(userTest.id, USER_ROLE.USER)\n\n usersManager.getGroup = jest.fn().mockResolvedValue({ id: 2, type: MEMBER_TYPE.PGROUP, members: [] })\n usersQueriesService.usersWhitelist = jest.fn().mockResolvedValue([10, 11])\n usersQueriesService.updateGroupMembers = jest.fn().mockResolvedValue(undefined)\n await expect(usersManager.addUsersToGroup(userTest, 2, [10, 11])).resolves.toBeUndefined()\n expect(usersQueriesService.usersWhitelist).toHaveBeenCalledWith(userTest.id, undefined)\n expect(usersQueriesService.updateGroupMembers).toHaveBeenCalledWith(2, {\n add: [\n { id: 10, groupRole: USER_GROUP_ROLE.MEMBER },\n { id: 11, groupRole: USER_GROUP_ROLE.MEMBER }\n ]\n })\n })\n\n it('updateUserFromPersonalGroup', async () => {\n usersManager.getGroup = jest.fn().mockResolvedValue({ id: 1, type: MEMBER_TYPE.GROUP, members: [] })\n await expect(usersManager.updateUserFromPersonalGroup(userTest, 1, 9, { role: 1 })).rejects.toThrow('You are not allowed to do this action')\n usersManager.getGroup = jest.fn().mockResolvedValue({ id: 1, type: MEMBER_TYPE.PGROUP, members: [] })\n await expect(usersManager.updateUserFromPersonalGroup(userTest, 1, 9, { role: 1 })).rejects.toThrow('User was not found')\n usersManager.getGroup = jest.fn().mockResolvedValue({\n id: 1,\n type: MEMBER_TYPE.PGROUP,\n members: [\n { id: 9, groupRole: USER_GROUP_ROLE.MANAGER },\n { id: 10, groupRole: USER_GROUP_ROLE.MEMBER }\n ]\n })\n await expect(usersManager.updateUserFromPersonalGroup(userTest, 1, 9, { role: USER_GROUP_ROLE.MEMBER })).rejects.toThrow(\n /group must have at least one manager/i\n )\n const spy = jest.spyOn(adminUsersManager, 'updateUserFromGroup').mockResolvedValue(undefined)\n usersManager.getGroup = jest.fn().mockResolvedValue({\n id: 1,\n type: MEMBER_TYPE.PGROUP,\n members: [\n { id: 9, groupRole: USER_GROUP_ROLE.MEMBER },\n { id: 10, groupRole: USER_GROUP_ROLE.MEMBER },\n { id: 11, groupRole: USER_GROUP_ROLE.MEMBER }\n ]\n })\n await expect(usersManager.updateUserFromPersonalGroup(userTest, 1, 9, { role: USER_GROUP_ROLE.MANAGER })).resolves.toBeUndefined()\n expect(spy).toHaveBeenCalledWith(1, 9, { role: 1 })\n usersManager.getGroup = jest.fn().mockResolvedValue({ id: 1, type: MEMBER_TYPE.PGROUP, members: [{ id: 9, groupRole: USER_GROUP_ROLE.MEMBER }] })\n await expect(usersManager.updateUserFromPersonalGroup(userTest, 1, 9, { role: USER_GROUP_ROLE.MEMBER })).resolves.toBeUndefined()\n ;(spy as jest.Mock).mockClear()\n usersManager.getGroup = jest.fn().mockResolvedValue({\n id: 1,\n type: MEMBER_TYPE.PGROUP,\n members: [\n { id: 9, groupRole: USER_GROUP_ROLE.MANAGER },\n { id: 10, groupRole: USER_GROUP_ROLE.MANAGER }\n ]\n })\n await expect(usersManager.updateUserFromPersonalGroup(userTest, 1, 9, { role: USER_GROUP_ROLE.MEMBER })).resolves.toBeUndefined()\n expect(spy).toHaveBeenCalledWith(1, 9, { role: USER_GROUP_ROLE.MEMBER })\n ;(spy as jest.Mock).mockClear()\n usersManager.getGroup = jest.fn().mockResolvedValue({\n id: 1,\n type: MEMBER_TYPE.PGROUP,\n members: [\n { id: 9, groupRole: USER_GROUP_ROLE.MANAGER },\n { id: 10, groupRole: USER_GROUP_ROLE.MANAGER }\n ]\n })\n await expect(usersManager.updateUserFromPersonalGroup(userTest, 1, 9, { role: USER_GROUP_ROLE.MANAGER })).resolves.toBeUndefined()\n expect(spy).not.toHaveBeenCalled()\n })\n\n it('removeUserFromGroup', async () => {\n usersManager.getGroup = jest.fn().mockResolvedValue({ id: 1, members: [] })\n await expect(usersManager.removeUserFromGroup(userTest, 1, 9)).rejects.toThrow('User was not found')\n usersManager.getGroup = jest.fn().mockResolvedValue({ id: 1, type: MEMBER_TYPE.GROUP, members: [{ id: 9, groupRole: USER_GROUP_ROLE.MANAGER }] })\n await expect(usersManager.removeUserFromGroup(userTest, 1, 9)).rejects.toThrow('You are not allowed to do this action')\n usersManager.getGroup = jest.fn().mockResolvedValue({ id: 1, type: MEMBER_TYPE.PGROUP, members: [{ id: 9, groupRole: USER_GROUP_ROLE.MANAGER }] })\n await expect(usersManager.removeUserFromGroup(userTest, 1, 9)).rejects.toThrow('Group must have at least one manager')\n usersQueriesService.updateGroupMembers = jest.fn().mockResolvedValue(undefined)\n usersManager.getGroup = jest.fn().mockResolvedValue({\n id: 1,\n type: MEMBER_TYPE.PGROUP,\n members: [\n { id: 9, groupRole: USER_GROUP_ROLE.MEMBER },\n { id: 10, groupRole: USER_GROUP_ROLE.MANAGER }\n ]\n })\n await expect(usersManager.removeUserFromGroup(userTest, 1, 9)).resolves.toBeUndefined()\n expect(usersQueriesService.updateGroupMembers).toHaveBeenCalledWith(1, { remove: [9] })\n usersQueriesService.updateGroupMembers = jest.fn().mockResolvedValue(undefined)\n usersManager.getGroup = jest.fn().mockResolvedValue({\n id: 1,\n type: MEMBER_TYPE.PGROUP,\n members: [\n { id: 9, groupRole: USER_GROUP_ROLE.MANAGER },\n { id: 10, groupRole: USER_GROUP_ROLE.MANAGER }\n ]\n })\n await expect(usersManager.removeUserFromGroup(userTest, 1, 9)).resolves.toBeUndefined()\n expect(usersQueriesService.updateGroupMembers).toHaveBeenCalledWith(1, { remove: [9] })\n })\n\n it('leave/delete personal group', async () => {\n usersQueriesService.getGroupWithMembers = jest.fn().mockResolvedValue(null)\n await expect(usersManager.leavePersonalGroup(userTest, 1)).rejects.toThrow('You are not allowed to do this action')\n usersQueriesService.getGroupWithMembers = jest.fn().mockResolvedValue({ id: 1, type: MEMBER_TYPE.GROUP, members: [{ id: userTest.id }] })\n await expect(usersManager.leavePersonalGroup(userTest, 1)).rejects.toThrow('You are not allowed to do this action')\n usersQueriesService.getGroupWithMembers = jest.fn().mockResolvedValue({ id: 1, type: MEMBER_TYPE.PGROUP, members: [] })\n await expect(usersManager.leavePersonalGroup(userTest, 1)).rejects.toThrow('User was not found')\n usersQueriesService.getGroupWithMembers = jest.fn().mockResolvedValue({\n id: 1,\n type: MEMBER_TYPE.PGROUP,\n members: [{ id: userTest.id, groupRole: USER_GROUP_ROLE.MANAGER }]\n })\n await expect(usersManager.leavePersonalGroup(userTest, 1)).rejects.toThrow('Group must have at least one manager')\n usersQueriesService.getGroupWithMembers = jest.fn().mockResolvedValue({\n id: 1,\n type: 2,\n members: [\n { id: userTest.id, groupRole: USER_GROUP_ROLE.MEMBER },\n { id: 9, groupRole: USER_GROUP_ROLE.MANAGER }\n ]\n })\n const lSpy = jest.spyOn((usersManager as any)['logger'], 'log').mockImplementation(() => undefined as any)\n usersQueriesService.updateGroupMembers = jest.fn().mockResolvedValue(undefined)\n await expect(usersManager.leavePersonalGroup(userTest, 1)).resolves.toBeUndefined()\n expect(lSpy).toHaveBeenCalledWith(expect.stringMatching(/has left group/))\n usersQueriesService.updateGroupMembers = jest.fn().mockRejectedValue(new Error('DB'))\n await expect(usersManager.leavePersonalGroup(userTest, 1)).rejects.toThrow('DB')\n usersQueriesService.getGroupWithMembers = jest.fn().mockResolvedValue({\n id: 1,\n type: MEMBER_TYPE.PGROUP,\n members: [\n { id: userTest.id, groupRole: USER_GROUP_ROLE.MANAGER },\n { id: 9, groupRole: USER_GROUP_ROLE.MANAGER }\n ]\n })\n usersQueriesService.updateGroupMembers = jest.fn().mockResolvedValue(undefined)\n await expect(usersManager.leavePersonalGroup(userTest, 1)).resolves.toBeUndefined()\n\n usersQueriesService.canDeletePersonalGroup = jest.fn().mockResolvedValue(false)\n await expect(usersManager.deletePersonalGroup(userTest, 7)).rejects.toThrow('You are not allowed to do this action')\n usersQueriesService.canDeletePersonalGroup = jest.fn().mockResolvedValue(true)\n const wSpy = jest.spyOn((usersManager as any)['logger'], 'warn').mockImplementation(() => undefined as any)\n usersQueriesService.deletePersonalGroup = jest.fn().mockResolvedValue(false)\n await expect(usersManager.deletePersonalGroup(userTest, 7)).rejects.toThrow('Unable to delete group')\n expect(wSpy).toHaveBeenCalledWith(expect.stringMatching(/does not exist/))\n const lgSpy = jest.spyOn((usersManager as any)['logger'], 'log').mockImplementation(() => undefined as any)\n usersQueriesService.deletePersonalGroup = jest.fn().mockResolvedValue(true)\n await expect(usersManager.deletePersonalGroup(userTest, 7)).resolves.toBeUndefined()\n expect(lgSpy).toHaveBeenCalledWith(expect.stringMatching(/was deleted/))\n })\n\n it('guests + proxies', async () => {\n usersQueriesService.listGuests = jest.fn().mockResolvedValue([{ id: 1 }])\n await expect(usersManager.listGuests(userTest)).resolves.toEqual([{ id: 1 }])\n const checkSpy = jest.spyOn(adminUsersManager, 'checkUser').mockImplementation(() => undefined)\n usersQueriesService.listGuests = jest.fn().mockResolvedValue({ id: 9 })\n await expect(usersManager.getGuest(userTest, 9)).resolves.toEqual({ id: 9 })\n expect(checkSpy).toHaveBeenCalled()\n\n usersQueriesService.usersWhitelist = jest.fn().mockResolvedValue([userTest.id, 100])\n usersQueriesService.clearWhiteListCaches = jest.fn()\n const createSpy = jest.spyOn(adminUsersManager, 'createUserOrGuest').mockResolvedValue({ id: 55 } as any)\n const dto1: CreateUserDto = { ...userTest, managers: [100], password: 'x' }\n const r = await usersManager.createGuest(userTest, dto1)\n expect(createSpy).toHaveBeenCalled()\n expect(usersQueriesService.clearWhiteListCaches).toHaveBeenCalledWith([userTest.id])\n expect(r).toEqual({ id: 55 })\n const args1 = (createSpy as jest.Mock).mock.calls[0][0]\n expect(args1.managers).toEqual(expect.arrayContaining([userTest.id]))\n ;(createSpy as jest.Mock).mockClear()\n const dto2: CreateUserDto = { ...userTest, managers: [userTest.id, 100], password: 'y' }\n await usersManager.createGuest(userTest, dto2)\n const args2 = (createSpy as jest.Mock).mock.calls[0][0]\n expect((args2.managers as number[]).filter((m: number) => m === userTest.id)).toHaveLength(1)\n\n await expect(usersManager.updateGuest(userTest, 9, {} as any)).rejects.toThrow('No changes to update')\n usersQueriesService.usersWhitelist = jest.fn().mockResolvedValue([1])\n await expect(usersManager.updateGuest(userTest, 9, { managers: [2] } as any)).rejects.toThrow('Guest must have at least one manager')\n usersQueriesService.isGuestManager = jest.fn().mockResolvedValue(false)\n await expect(usersManager.updateGuest(userTest, 9, { email: 'a' } as any)).rejects.toThrow('You are not allowed to do this action')\n usersQueriesService.isGuestManager = jest.fn().mockResolvedValue(true)\n jest.spyOn(adminUsersManager, 'updateUserOrGuest').mockResolvedValue({ managers: [{ id: 999 }] } as any)\n await expect(usersManager.updateGuest(userTest, 9, { email: 'a' } as any)).resolves.toBeNull()\n jest.spyOn(adminUsersManager, 'updateUserOrGuest').mockResolvedValue({ managers: [{ id: userTest.id }] } as any)\n await expect(usersManager.updateGuest(userTest, 9, { email: 'a' } as any)).resolves.toEqual({ managers: [{ id: userTest.id }] })\n usersQueriesService.usersWhitelist = jest.fn().mockResolvedValue([userTest.id, 77])\n usersQueriesService.isGuestManager = jest.fn().mockResolvedValue(true)\n jest.spyOn(adminUsersManager, 'updateUserOrGuest').mockResolvedValue({ managers: [{ id: userTest.id }, { id: 77 }] } as any)\n await expect(usersManager.updateGuest(userTest, 9, { managers: [userTest.id, 77] } as any)).resolves.toEqual({\n managers: [{ id: userTest.id }, { id: 77 }]\n })\n\n usersQueriesService.isGuestManager = jest.fn().mockResolvedValue(null)\n await expect(usersManager.deleteGuest(userTest, 9)).rejects.toThrow('You are not allowed to do this action')\n usersQueriesService.isGuestManager = jest.fn().mockResolvedValue({ id: 9, login: 'guest' })\n const delSpy = jest.spyOn(adminUsersManager, 'deleteUserOrGuest').mockResolvedValue(undefined)\n await expect(usersManager.deleteGuest(userTest, 9)).resolves.toBeUndefined()\n expect(delSpy).toHaveBeenCalledWith(9, 'guest', { deleteSpace: true, isGuest: true })\n\n usersQueriesService.searchUsersOrGroups = jest.fn().mockResolvedValue([{ id: 1 }])\n await expect(usersManager.searchMembers(userTest, { search: '' } as any)).resolves.toEqual([{ id: 1 }])\n\n usersQueriesService.getOnlineUsers = jest.fn().mockResolvedValue([{ id: 123 }])\n await expect(usersManager.getOnlineUsers([123])).resolves.toEqual([{ id: 123 }])\n expect(usersQueriesService.getOnlineUsers).toHaveBeenCalledWith([123])\n usersQueriesService.usersWhitelist = jest.fn().mockResolvedValue([10, 11])\n await expect(usersManager.usersWhitelist(userTest.id)).resolves.toEqual([10, 11])\n expect(usersQueriesService.usersWhitelist).toHaveBeenCalledWith(userTest.id)\n })\n})\n"],"names":["jest","mock","actual","requireActual","comparePassword","fn","__esModule","default","hash","Promise","resolve","generateAvatar","Readable","from","Buffer","convertImageToBase64","describe","UsersManager","name","usersManager","adminUsersManager","adminUsersQueries","usersQueriesService","userTest","deleteUserDto","flush","r","setImmediate","okStream","d","s","truncated","errStream","msg","read","destroy","Error","mkReq","mimetype","stream","user","file","mockResolvedValue","ensurePaths","isPathExists","homePath","makePaths","beforeAll","module","Test","createTestingModule","providers","AdminUsersManager","AdminUsersQueries","UsersQueries","provide","AuthManager","useValue","DB_TOKEN_PROVIDER","Cache","compile","useLogger","get","UserModel","generateUserTest","deleteSpace","afterEach","restoreAllMocks","afterAll","expect","deleteUserSpace","login","resolves","not","toThrow","it","toBeDefined","mockReturnValue","u1","findUser","toBeInstanceOf","password","toBeUndefined","u2","me1","me","toBeNull","id","rejects","fromUserId","authUser","clientId","impersonatedFromId","fromUser","me2","impersonated","toBe","filesPath","mockReturnValueOnce","p0","m0","getAvatar","fileName","svgMimeType","p1","m1","pngMimeType","checkUserExists","undefined","createUserOrGuest","created","USER_ROLE","USER","email","mockImplementation","deleteUser","deleteUserOrGuest","linkUser","role","LINK","logUser","uLocked","isActive","passwordAttempts","errSpy","spyOn","updSpy1","mockRejectedValue","toHaveBeenCalledWith","stringContaining","uBad","errSpy2","updSpy2","out","uGood","updSpy3","pathsSpy","out2","toHaveBeenCalled","compareUserPassword","updateUserOrGuest","updateLanguage","language","selectUserProperties","updatePassword","oldPassword","newPassword","bcrypt","updateNotification","notification","prevAccess1","Date","currentIp","currentAccess","updateAccesses","payload1","calls","toMatchObject","lastIp","lastAccess","prevAccess2","USER_MAX_PASSWORD_ATTEMPTS","payload2","getInitials","p","m","imageModule","s1","getAvatarBase64","mockClear","s2","stringMatching","updateAvatar","t","mvSpy","filesUtilsModule","mvSpy2","expectedSrc","path","join","tmpPath","expectedDst","setOnlineStatus","browseRootGroups","root","browseGroups","parentGroup","members","length","groupFromName","group","browseGroupMembers","g2","toEqual","getGroupWithMembers","getGroup","createPersonalGroup","checkGroupNameExists","clearWhiteListCaches","logSpy","updatePersonalGroup","mockResolvedValueOnce","type","MEMBER_TYPE","GROUP","PGROUP","updateGroup","isAdmin","usersWhitelist","addUsersToGroup","updateGroupMembers","add","groupRole","USER_GROUP_ROLE","MEMBER","updateUserFromPersonalGroup","MANAGER","spy","removeUserFromGroup","remove","leavePersonalGroup","lSpy","canDeletePersonalGroup","deletePersonalGroup","wSpy","lgSpy","listGuests","checkSpy","getGuest","createSpy","dto1","managers","createGuest","args1","arrayContaining","dto2","args2","filter","toHaveLength","updateGuest","isGuestManager","deleteGuest","delSpy","isGuest","searchUsersOrGroups","searchMembers","search","getOnlineUsers"],"mappings":"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"}
@@ -18,7 +18,10 @@ function IfHeaderDecorator() {
18
18
  descriptor.value = async function(...args) {
19
19
  const req = args[0];
20
20
  const res = args[1];
21
- if (!await this.evaluateIfHeaders(req, res)) return;
21
+ if (!await this.evaluateIfHeaders(req, res)) {
22
+ // if there is an error the response is generated inside the `evaluateIfHeaders` function
23
+ return;
24
+ }
22
25
  return await originalMethod.apply(this, args);
23
26
  };
24
27
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/webdav/decorators/if-header.decorator.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 { FastifyReply } from 'fastify'\nimport { FastifyDAVRequest } from '../interfaces/webdav.interface'\n\nexport function IfHeaderDecorator() {\n return (_target: any, _key?: string | symbol, descriptor?: TypedPropertyDescriptor<any>) => {\n const originalMethod = descriptor.value\n descriptor.value = async function (...args: any[]) {\n const req: FastifyDAVRequest = args[0]\n const res: FastifyReply = args[1]\n if (!(await this.evaluateIfHeaders(req, res))) return\n return await originalMethod.apply(this, args)\n }\n }\n}\n"],"names":["IfHeaderDecorator","_target","_key","descriptor","originalMethod","value","args","req","res","evaluateIfHeaders","apply"],"mappings":"AAAA;;;;CAIC;;;;+BAKeA;;;eAAAA;;;AAAT,SAASA;IACd,OAAO,CAACC,SAAcC,MAAwBC;QAC5C,MAAMC,iBAAiBD,WAAWE,KAAK;QACvCF,WAAWE,KAAK,GAAG,eAAgB,GAAGC,IAAW;YAC/C,MAAMC,MAAyBD,IAAI,CAAC,EAAE;YACtC,MAAME,MAAoBF,IAAI,CAAC,EAAE;YACjC,IAAI,CAAE,MAAM,IAAI,CAACG,iBAAiB,CAACF,KAAKC,MAAO;YAC/C,OAAO,MAAMJ,eAAeM,KAAK,CAAC,IAAI,EAAEJ;QAC1C;IACF;AACF"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/webdav/decorators/if-header.decorator.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 { FastifyReply } from 'fastify'\nimport { FastifyDAVRequest } from '../interfaces/webdav.interface'\n\nexport function IfHeaderDecorator() {\n return (_target: any, _key?: string | symbol, descriptor?: TypedPropertyDescriptor<any>) => {\n const originalMethod = descriptor.value\n descriptor.value = async function (...args: any[]) {\n const req: FastifyDAVRequest = args[0]\n const res: FastifyReply = args[1]\n if (!(await this.evaluateIfHeaders(req, res))) {\n // if there is an error the response is generated inside the `evaluateIfHeaders` function\n return\n }\n return await originalMethod.apply(this, args)\n }\n }\n}\n"],"names":["IfHeaderDecorator","_target","_key","descriptor","originalMethod","value","args","req","res","evaluateIfHeaders","apply"],"mappings":"AAAA;;;;CAIC;;;;+BAKeA;;;eAAAA;;;AAAT,SAASA;IACd,OAAO,CAACC,SAAcC,MAAwBC;QAC5C,MAAMC,iBAAiBD,WAAWE,KAAK;QACvCF,WAAWE,KAAK,GAAG,eAAgB,GAAGC,IAAW;YAC/C,MAAMC,MAAyBD,IAAI,CAAC,EAAE;YACtC,MAAME,MAAoBF,IAAI,CAAC,EAAE;YACjC,IAAI,CAAE,MAAM,IAAI,CAACG,iBAAiB,CAACF,KAAKC,MAAO;gBAC7C,yFAAyF;gBACzF;YACF;YACA,OAAO,MAAMJ,eAAeM,KAAK,CAAC,IAAI,EAAEJ;QAC1C;IACF;AACF"}
@@ -0,0 +1,77 @@
1
+ /*
2
+ * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>
3
+ * This file is part of Sync-in | The open source file sync and share solution
4
+ * See the LICENSE file for licensing details
5
+ */ "use strict";
6
+ Object.defineProperty(exports, "__esModule", {
7
+ value: true
8
+ });
9
+ const _common = require("@nestjs/common");
10
+ const _testing = require("@nestjs/testing");
11
+ const _appconstants = require("../../../app.constants");
12
+ const _webdav = require("../constants/webdav");
13
+ const _webdavfilter = require("./webdav.filter");
14
+ describe('WebDAVExceptionsFilter', ()=>{
15
+ let filter;
16
+ const createMockResponse = ()=>{
17
+ const res = {};
18
+ res.header = jest.fn().mockReturnValue(res);
19
+ res.type = jest.fn().mockReturnValue(res);
20
+ res.status = jest.fn().mockReturnValue(res);
21
+ res.send = jest.fn().mockReturnValue(res);
22
+ return res;
23
+ };
24
+ const createMockHost = (res)=>({
25
+ switchToHttp: ()=>({
26
+ getResponse: ()=>res
27
+ })
28
+ });
29
+ beforeEach(async ()=>{
30
+ const moduleRef = await _testing.Test.createTestingModule({
31
+ providers: [
32
+ _webdavfilter.WebDAVExceptionsFilter
33
+ ]
34
+ }).compile();
35
+ filter = moduleRef.get(_webdavfilter.WebDAVExceptionsFilter);
36
+ });
37
+ afterEach(()=>{
38
+ jest.clearAllMocks();
39
+ });
40
+ it('should set WWW-Authenticate header and send empty body for 401', ()=>{
41
+ const res = createMockResponse();
42
+ const host = createMockHost(res);
43
+ const exception = new _common.HttpException('Unauthorized', 401);
44
+ filter.catch(exception, host);
45
+ expect(res.header).toHaveBeenCalledWith('WWW-Authenticate', `Basic realm="${_appconstants.SERVER_NAME}"`);
46
+ expect(res.status).toHaveBeenCalledWith(401);
47
+ expect(res.type).not.toHaveBeenCalled();
48
+ expect(res.send).toHaveBeenCalled();
49
+ // Ensure no body is sent
50
+ expect(res.send.mock.calls[0][0]).toBeUndefined();
51
+ });
52
+ it('should set XML content type and forward string response for non-401', ()=>{
53
+ const res = createMockResponse();
54
+ const host = createMockHost(res);
55
+ const exception = new _common.HttpException('Internal error', 500);
56
+ filter.catch(exception, host);
57
+ expect(res.type).toHaveBeenCalledWith(_webdav.XML_CONTENT_TYPE);
58
+ expect(res.status).toHaveBeenCalledWith(500);
59
+ expect(res.send).toHaveBeenCalledWith('Internal error');
60
+ expect(res.header).not.toHaveBeenCalled();
61
+ });
62
+ it('should extract "message" from object response and send it as XML for non-401', ()=>{
63
+ const res = createMockResponse();
64
+ const host = createMockHost(res);
65
+ const payload = {
66
+ message: '<error>Bad Request</error>'
67
+ };
68
+ const exception = new _common.HttpException(payload, 400);
69
+ filter.catch(exception, host);
70
+ expect(res.type).toHaveBeenCalledWith(_webdav.XML_CONTENT_TYPE);
71
+ expect(res.status).toHaveBeenCalledWith(400);
72
+ expect(res.send).toHaveBeenCalledWith(payload.message);
73
+ expect(res.header).not.toHaveBeenCalled();
74
+ });
75
+ });
76
+
77
+ //# sourceMappingURL=webdav.filter.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../backend/src/applications/webdav/filters/webdav.filter.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 */\nimport { ArgumentsHost, HttpException } from '@nestjs/common'\nimport { Test } from '@nestjs/testing'\nimport { SERVER_NAME } from '../../../app.constants'\nimport { XML_CONTENT_TYPE } from '../constants/webdav'\nimport { WebDAVExceptionsFilter } from './webdav.filter'\n\ndescribe('WebDAVExceptionsFilter', () => {\n let filter: WebDAVExceptionsFilter\n\n const createMockResponse = () => {\n const res: any = {}\n res.header = jest.fn().mockReturnValue(res)\n res.type = jest.fn().mockReturnValue(res)\n res.status = jest.fn().mockReturnValue(res)\n res.send = jest.fn().mockReturnValue(res)\n return res\n }\n\n const createMockHost = (res: any): ArgumentsHost =>\n ({\n switchToHttp: () => ({\n getResponse: () => res\n })\n // Other methods not used by the filter\n }) as unknown as ArgumentsHost\n\n beforeEach(async () => {\n const moduleRef = await Test.createTestingModule({\n providers: [WebDAVExceptionsFilter]\n }).compile()\n\n filter = moduleRef.get(WebDAVExceptionsFilter)\n })\n\n afterEach(() => {\n jest.clearAllMocks()\n })\n\n it('should set WWW-Authenticate header and send empty body for 401', () => {\n const res = createMockResponse()\n const host = createMockHost(res)\n const exception = new HttpException('Unauthorized', 401)\n\n filter.catch(exception, host)\n\n expect(res.header).toHaveBeenCalledWith('WWW-Authenticate', `Basic realm=\"${SERVER_NAME}\"`)\n expect(res.status).toHaveBeenCalledWith(401)\n expect(res.type).not.toHaveBeenCalled()\n expect(res.send).toHaveBeenCalled()\n // Ensure no body is sent\n expect(res.send.mock.calls[0][0]).toBeUndefined()\n })\n\n it('should set XML content type and forward string response for non-401', () => {\n const res = createMockResponse()\n const host = createMockHost(res)\n const exception = new HttpException('Internal error', 500)\n\n filter.catch(exception, host)\n\n expect(res.type).toHaveBeenCalledWith(XML_CONTENT_TYPE)\n expect(res.status).toHaveBeenCalledWith(500)\n expect(res.send).toHaveBeenCalledWith('Internal error')\n expect(res.header).not.toHaveBeenCalled()\n })\n\n it('should extract \"message\" from object response and send it as XML for non-401', () => {\n const res = createMockResponse()\n const host = createMockHost(res)\n const payload = { message: '<error>Bad Request</error>' }\n const exception = new HttpException(payload, 400)\n\n filter.catch(exception, host)\n\n expect(res.type).toHaveBeenCalledWith(XML_CONTENT_TYPE)\n expect(res.status).toHaveBeenCalledWith(400)\n expect(res.send).toHaveBeenCalledWith(payload.message)\n expect(res.header).not.toHaveBeenCalled()\n })\n})\n"],"names":["describe","filter","createMockResponse","res","header","jest","fn","mockReturnValue","type","status","send","createMockHost","switchToHttp","getResponse","beforeEach","moduleRef","Test","createTestingModule","providers","WebDAVExceptionsFilter","compile","get","afterEach","clearAllMocks","it","host","exception","HttpException","catch","expect","toHaveBeenCalledWith","SERVER_NAME","not","toHaveBeenCalled","mock","calls","toBeUndefined","XML_CONTENT_TYPE","payload","message"],"mappings":"AAAA;;;;CAIC;;;;wBAC4C;yBACxB;8BACO;wBACK;8BACM;AAEvCA,SAAS,0BAA0B;IACjC,IAAIC;IAEJ,MAAMC,qBAAqB;QACzB,MAAMC,MAAW,CAAC;QAClBA,IAAIC,MAAM,GAAGC,KAAKC,EAAE,GAAGC,eAAe,CAACJ;QACvCA,IAAIK,IAAI,GAAGH,KAAKC,EAAE,GAAGC,eAAe,CAACJ;QACrCA,IAAIM,MAAM,GAAGJ,KAAKC,EAAE,GAAGC,eAAe,CAACJ;QACvCA,IAAIO,IAAI,GAAGL,KAAKC,EAAE,GAAGC,eAAe,CAACJ;QACrC,OAAOA;IACT;IAEA,MAAMQ,iBAAiB,CAACR,MACrB,CAAA;YACCS,cAAc,IAAO,CAAA;oBACnBC,aAAa,IAAMV;gBACrB,CAAA;QAEF,CAAA;IAEFW,WAAW;QACT,MAAMC,YAAY,MAAMC,aAAI,CAACC,mBAAmB,CAAC;YAC/CC,WAAW;gBAACC,oCAAsB;aAAC;QACrC,GAAGC,OAAO;QAEVnB,SAASc,UAAUM,GAAG,CAACF,oCAAsB;IAC/C;IAEAG,UAAU;QACRjB,KAAKkB,aAAa;IACpB;IAEAC,GAAG,kEAAkE;QACnE,MAAMrB,MAAMD;QACZ,MAAMuB,OAAOd,eAAeR;QAC5B,MAAMuB,YAAY,IAAIC,qBAAa,CAAC,gBAAgB;QAEpD1B,OAAO2B,KAAK,CAACF,WAAWD;QAExBI,OAAO1B,IAAIC,MAAM,EAAE0B,oBAAoB,CAAC,oBAAoB,CAAC,aAAa,EAAEC,yBAAW,CAAC,CAAC,CAAC;QAC1FF,OAAO1B,IAAIM,MAAM,EAAEqB,oBAAoB,CAAC;QACxCD,OAAO1B,IAAIK,IAAI,EAAEwB,GAAG,CAACC,gBAAgB;QACrCJ,OAAO1B,IAAIO,IAAI,EAAEuB,gBAAgB;QACjC,yBAAyB;QACzBJ,OAAO1B,IAAIO,IAAI,CAACwB,IAAI,CAACC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAEC,aAAa;IACjD;IAEAZ,GAAG,uEAAuE;QACxE,MAAMrB,MAAMD;QACZ,MAAMuB,OAAOd,eAAeR;QAC5B,MAAMuB,YAAY,IAAIC,qBAAa,CAAC,kBAAkB;QAEtD1B,OAAO2B,KAAK,CAACF,WAAWD;QAExBI,OAAO1B,IAAIK,IAAI,EAAEsB,oBAAoB,CAACO,wBAAgB;QACtDR,OAAO1B,IAAIM,MAAM,EAAEqB,oBAAoB,CAAC;QACxCD,OAAO1B,IAAIO,IAAI,EAAEoB,oBAAoB,CAAC;QACtCD,OAAO1B,IAAIC,MAAM,EAAE4B,GAAG,CAACC,gBAAgB;IACzC;IAEAT,GAAG,gFAAgF;QACjF,MAAMrB,MAAMD;QACZ,MAAMuB,OAAOd,eAAeR;QAC5B,MAAMmC,UAAU;YAAEC,SAAS;QAA6B;QACxD,MAAMb,YAAY,IAAIC,qBAAa,CAACW,SAAS;QAE7CrC,OAAO2B,KAAK,CAACF,WAAWD;QAExBI,OAAO1B,IAAIK,IAAI,EAAEsB,oBAAoB,CAACO,wBAAgB;QACtDR,OAAO1B,IAAIM,MAAM,EAAEqB,oBAAoB,CAAC;QACxCD,OAAO1B,IAAIO,IAAI,EAAEoB,oBAAoB,CAACQ,QAAQC,OAAO;QACrDV,OAAO1B,IAAIC,MAAM,EAAE4B,GAAG,CAACC,gBAAgB;IACzC;AACF"}
@@ -36,8 +36,9 @@ let WebDAVProtocolGuard = class WebDAVProtocolGuard {
36
36
  this.setDAVContext(req);
37
37
  switch(req.method){
38
38
  case _applicationsconstants.HTTP_METHOD.OPTIONS:
39
- this.optionsMethod(res);
40
- break;
39
+ // hook to stop propagation and return headers on all webdav routes
40
+ res.headers(_webdav.OPTIONS_HEADERS);
41
+ throw new _common.HttpException(null, _common.HttpStatus.OK);
41
42
  case _applicationsconstants.HTTP_METHOD.PROPFIND:
42
43
  return this.propfindMethod(req);
43
44
  case _applicationsconstants.HTTP_METHOD.LOCK:
@@ -107,11 +108,6 @@ let WebDAVProtocolGuard = class WebDAVProtocolGuard {
107
108
  if (ifHeaders.length) req.dav.ifHeaders = ifHeaders;
108
109
  }
109
110
  }
110
- optionsMethod(res) {
111
- // hook to return headers on all webdav routes
112
- res.headers(_webdav.OPTIONS_HEADERS);
113
- throw new _common.HttpException(null, _common.HttpStatus.OK);
114
- }
115
111
  propfindMethod(req) {
116
112
  req.dav.depth = req.headers[_webdav.HEADER.DEPTH]?.toLowerCase();
117
113
  if (!req.dav.depth || req.dav.depth !== _webdav.DEPTH.MEMBERS && req.dav.depth !== _webdav.DEPTH.RESOURCE) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/webdav/guards/webdav-protocol.guard.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 { CanActivate, ExecutionContext, HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'\nimport { ValidationError } from 'fast-xml-parser'\nimport { FastifyReply } from 'fastify'\nimport { urlToPath } from '../../../common/functions'\nimport { decodeUrl } from '../../../common/shared'\nimport { HTTP_METHOD } from '../../applications.constants'\nimport { FilesLockManager } from '../../files/services/files-lock-manager.service'\nimport { USER_PERMISSION } from '../../users/constants/user'\nimport {\n ALLOW_EMPTY_BODY_METHODS,\n DEPTH,\n HEADER,\n LOCK_SCOPE,\n OPTIONS_HEADERS,\n PROPPATCH_PROP_UPDATE,\n PROPSTAT,\n REGEX_BASE_PATH\n} from '../constants/webdav'\nimport { IfHeader } from '../interfaces/if-header.interface'\nimport { FastifyDAVRequest, WebDAVContext } from '../interfaces/webdav.interface'\nimport { parseIfHeader } from '../utils/if-header'\nimport { PROPFIND_ALL_PROP } from '../utils/webdav'\nimport { xmlIsValid, xmlParse } from '../utils/xml'\n\n@Injectable()\nexport class WebDAVProtocolGuard implements CanActivate {\n private readonly logger = new Logger(WebDAVProtocolGuard.name)\n\n async canActivate(ctx: ExecutionContext): Promise<boolean> {\n const req: FastifyDAVRequest = ctx.switchToHttp().getRequest()\n const res: FastifyReply = ctx.switchToHttp().getResponse()\n this.checkUserPermission(req)\n this.setDAVContext(req)\n switch (req.method) {\n case HTTP_METHOD.OPTIONS:\n this.optionsMethod(res)\n break\n case HTTP_METHOD.PROPFIND:\n return this.propfindMethod(req)\n case HTTP_METHOD.LOCK:\n return this.lockMethod(req)\n case HTTP_METHOD.UNLOCK:\n return this.unlockMethod(req)\n case HTTP_METHOD.PUT:\n return this.putMethod(req)\n case HTTP_METHOD.DELETE:\n return this.deleteMethod(req)\n case HTTP_METHOD.PROPPATCH:\n return this.proppatchMethod(req)\n case HTTP_METHOD.MKCOL:\n return this.mkcolMethod(req)\n case HTTP_METHOD.COPY:\n return this.copyMoveMethod(req)\n case HTTP_METHOD.MOVE:\n return this.copyMoveMethod(req, true)\n default:\n return true\n }\n }\n\n private checkUserPermission(req: FastifyDAVRequest) {\n if (req.method !== HTTP_METHOD.OPTIONS && !req.user.havePermission(USER_PERMISSION.WEBDAV)) {\n this.logger.warn(`does not have permission : ${USER_PERMISSION.WEBDAV}`)\n throw new HttpException('Missing permission', HttpStatus.FORBIDDEN)\n }\n }\n\n private setDAVContext(req: FastifyDAVRequest) {\n req.dav = {\n url: decodeUrl(req.originalUrl),\n depth: DEPTH.RESOURCE\n } as WebDAVContext\n }\n\n private parseBody(req: FastifyDAVRequest) {\n let body = null\n let valid: true | ValidationError\n try {\n valid = xmlIsValid(req.body.toString())\n } catch (e) {\n valid = { err: { code: e.code, msg: `Invalid body content: ${e.message}`, line: 0, col: 0 } }\n }\n if (valid === true) {\n body = xmlParse(req.body)\n } else if (valid.err.code === undefined && ALLOW_EMPTY_BODY_METHODS.indexOf(req.method) > -1) {\n body = null\n } else {\n throw new HttpException(`${valid.err.code} : ${valid.err.msg}`, HttpStatus.BAD_REQUEST)\n }\n req.dav.httpVersion = `${req.protocol.toUpperCase()}/${req.raw['httpVersion']}`\n req.dav.body = body\n return true\n }\n\n private parseIfHeader(req: FastifyDAVRequest) {\n // stores if headers, examine it later\n if (req.headers[HEADER.IF]) {\n this.logger.verbose(`If header before : ${JSON.stringify(req.headers[HEADER.IF])}`)\n const ifHeaders: IfHeader[] = parseIfHeader(req.headers[HEADER.IF] as string)\n this.logger.verbose(`If header after : ${JSON.stringify(ifHeaders)}`)\n if (ifHeaders.length) req.dav.ifHeaders = ifHeaders\n }\n }\n\n private optionsMethod(res: FastifyReply) {\n // hook to return headers on all webdav routes\n res.headers(OPTIONS_HEADERS)\n throw new HttpException(null, HttpStatus.OK)\n }\n\n private propfindMethod(req: FastifyDAVRequest) {\n req.dav.depth = (req.headers[HEADER.DEPTH] as string | undefined)?.toLowerCase()\n if (!req.dav.depth || (req.dav.depth !== DEPTH.MEMBERS && req.dav.depth !== DEPTH.RESOURCE)) {\n if (!req.dav.depth) {\n this.logger.warn('Missing propfind depth, default value 1 was set')\n } else if (req.dav.depth === DEPTH.INFINITY) {\n this.logger.warn('Infinite depth is disabled for security reasons, default value 1 was set')\n } else {\n this.logger.warn(`Invalid propfind depth header : ${req.dav.depth}, default value 1 was set`)\n }\n req.dav.depth = DEPTH.MEMBERS\n }\n if (this.parseBody(req)) {\n if (req.dav.body) {\n for (const propType in req.dav.body.propfind) {\n if (Object.values(PROPSTAT).indexOf(propType as PROPSTAT) > -1) {\n req.dav.propfindMode = propType as PROPSTAT\n break\n }\n }\n if (!req.dav.propfindMode) {\n this.logger.warn(`Invalid propfind mode : ${JSON.stringify(Object.keys(req.dav.body.propfind))}`)\n throw new HttpException('Invalid propfind mode', HttpStatus.BAD_REQUEST)\n }\n } else {\n // propfind request allow empty body\n req.dav.body = PROPFIND_ALL_PROP\n req.dav.propfindMode = PROPSTAT.ALLPROP\n }\n }\n this.parseIfHeader(req)\n return true\n }\n\n private proppatchMethod(req: FastifyDAVRequest) {\n req.dav.depth = ((req.headers[HEADER.DEPTH] as any) || DEPTH.RESOURCE).toLowerCase()\n this.parseBody(req)\n if (!req.dav.body || Object.keys(req.dav.body).indexOf(PROPPATCH_PROP_UPDATE) === -1) {\n this.logger.debug(`'${PROPPATCH_PROP_UPDATE}' is missing : ${JSON.stringify(req.dav.body)}`)\n throw new HttpException(`'${PROPPATCH_PROP_UPDATE}' is missing`, HttpStatus.BAD_REQUEST)\n }\n this.parseIfHeader(req)\n return true\n }\n\n private lockMethod(req: FastifyDAVRequest) {\n req.dav.lock = {}\n if (req.headers[HEADER.TIMEOUT]) {\n // timeout: 'Infinite, Second-4100000000' | 'Second-4100000000' | 'Infinite'\n const timeout = req.headers[HEADER.TIMEOUT] as string\n if (timeout.toLowerCase() === 'infinite') {\n req.dav.lock.timeout = FilesLockManager.defaultLockTimeoutSeconds\n } else {\n try {\n const timeoutSplit = timeout.split('-')\n const seconds = parseInt(timeoutSplit[timeoutSplit.length - 1], 10)\n req.dav.lock.timeout = seconds > FilesLockManager.defaultLockTimeoutSeconds ? FilesLockManager.defaultLockTimeoutSeconds : seconds\n } catch (e) {\n this.logger.warn(`${this.lockMethod.name} - unable to set timeout, use the default value : ${e}`)\n req.dav.lock.timeout = FilesLockManager.defaultLockTimeoutSeconds\n }\n }\n }\n this.parseBody(req)\n if (req.dav.body) {\n if (!req.dav.body['lockinfo']) {\n this.logger.warn(`Missing lockinfo : ${JSON.stringify(req.dav.body)}`)\n throw new HttpException('Missing lockinfo', HttpStatus.BAD_REQUEST)\n }\n try {\n req.dav.lock.lockscope = Object.keys(req.dav.body['lockinfo']['lockscope'])[0] as LOCK_SCOPE\n } catch (e) {\n this.logger.warn(`${this.parseBody.name} - invalid or undefined lockscope : ${JSON.stringify(req.dav.body['lockinfo'])} : ${e}`)\n throw new HttpException('Invalid or undefined lockscope', HttpStatus.BAD_REQUEST)\n }\n if (Object.values(LOCK_SCOPE).indexOf(req.dav.lock.lockscope) === -1) {\n this.logger.warn(`${this.parseBody.name} - invalid or undefined lockscope : ${JSON.stringify(req.dav.body['lockinfo'])}`)\n throw new HttpException('Invalid or undefined lockscope', HttpStatus.BAD_REQUEST)\n }\n if (req.dav.body['lockinfo']['owner'] && typeof req.dav.body['lockinfo']['owner'] === 'string') {\n req.dav.lock.owner = `${req.dav.body['lockinfo']['owner']} ${req.user.fullName} (${req.user.email})`\n } else {\n req.dav.lock.owner = `WebDAV - ${req.user.fullName} (${req.user.email})`\n }\n const depth: DEPTH = ((req.headers[HEADER.DEPTH] as any) || '').toLowerCase()\n req.dav.depth = [DEPTH.INFINITY, DEPTH.RESOURCE].indexOf(depth) === -1 ? DEPTH.INFINITY : depth\n } else {\n // must ignore depth header on lock refresh request\n req.dav.depth = null\n }\n this.parseIfHeader(req)\n return true\n }\n\n private unlockMethod(req: FastifyDAVRequest) {\n if (!req.headers[HEADER.LOCK_TOKEN]) {\n throw new HttpException('Missing lock token', HttpStatus.BAD_REQUEST)\n }\n req.dav.lock = { token: (req.headers[HEADER.LOCK_TOKEN] as string).replace('<', '').replace('>', '').trim() }\n this.parseIfHeader(req)\n return true\n }\n\n private putMethod(req: FastifyDAVRequest) {\n req.dav.depth = DEPTH.RESOURCE\n this.parseIfHeader(req)\n return true\n }\n\n private deleteMethod(req: FastifyDAVRequest) {\n this.parseIfHeader(req)\n return true\n }\n\n private mkcolMethod(req: FastifyDAVRequest) {\n if (req.headers['content-length'] && req.headers['content-length'] !== '0') {\n throw new HttpException('no body content required', HttpStatus.UNSUPPORTED_MEDIA_TYPE)\n }\n req.dav.depth = DEPTH.RESOURCE\n this.parseIfHeader(req)\n return true\n }\n\n private copyMoveMethod(req: FastifyDAVRequest, isMove = false) {\n if (!req.headers[HEADER.DESTINATION]) {\n throw new HttpException(`Missing ${HEADER.DESTINATION} header`, HttpStatus.BAD_REQUEST)\n }\n const destination = decodeUrl(urlToPath(req.headers[HEADER.DESTINATION] as string))\n if (!REGEX_BASE_PATH.test(destination)) {\n this.logger.warn(`The destination does not match the webdav base path : ${destination}`)\n throw new HttpException('The destination does not match', HttpStatus.BAD_REQUEST)\n }\n req.dav.depth = ((req.headers[HEADER.DEPTH] as any) || DEPTH.INFINITY).toLowerCase()\n req.dav.copyMove = {\n overwrite: ((req.headers[HEADER.OVERWRITE] as any) || 't').toLowerCase() === 't',\n destination: destination,\n isMove: isMove\n }\n this.parseIfHeader(req)\n return true\n }\n}\n"],"names":["WebDAVProtocolGuard","canActivate","ctx","req","switchToHttp","getRequest","res","getResponse","checkUserPermission","setDAVContext","method","HTTP_METHOD","OPTIONS","optionsMethod","PROPFIND","propfindMethod","LOCK","lockMethod","UNLOCK","unlockMethod","PUT","putMethod","DELETE","deleteMethod","PROPPATCH","proppatchMethod","MKCOL","mkcolMethod","COPY","copyMoveMethod","MOVE","user","havePermission","USER_PERMISSION","WEBDAV","logger","warn","HttpException","HttpStatus","FORBIDDEN","dav","url","decodeUrl","originalUrl","depth","DEPTH","RESOURCE","parseBody","body","valid","xmlIsValid","toString","e","err","code","msg","message","line","col","xmlParse","undefined","ALLOW_EMPTY_BODY_METHODS","indexOf","BAD_REQUEST","httpVersion","protocol","toUpperCase","raw","parseIfHeader","headers","HEADER","IF","verbose","JSON","stringify","ifHeaders","length","OPTIONS_HEADERS","OK","toLowerCase","MEMBERS","INFINITY","propType","propfind","Object","values","PROPSTAT","propfindMode","keys","PROPFIND_ALL_PROP","ALLPROP","PROPPATCH_PROP_UPDATE","debug","lock","TIMEOUT","timeout","FilesLockManager","defaultLockTimeoutSeconds","timeoutSplit","split","seconds","parseInt","name","lockscope","LOCK_SCOPE","owner","fullName","email","LOCK_TOKEN","token","replace","trim","UNSUPPORTED_MEDIA_TYPE","isMove","DESTINATION","destination","urlToPath","REGEX_BASE_PATH","test","copyMove","overwrite","OVERWRITE","Logger"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/webdav/guards/webdav-protocol.guard.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 { CanActivate, ExecutionContext, HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'\nimport { ValidationError } from 'fast-xml-parser'\nimport { FastifyReply } from 'fastify'\nimport { urlToPath } from '../../../common/functions'\nimport { decodeUrl } from '../../../common/shared'\nimport { HTTP_METHOD } from '../../applications.constants'\nimport { FilesLockManager } from '../../files/services/files-lock-manager.service'\nimport { USER_PERMISSION } from '../../users/constants/user'\nimport {\n ALLOW_EMPTY_BODY_METHODS,\n DEPTH,\n HEADER,\n LOCK_SCOPE,\n OPTIONS_HEADERS,\n PROPPATCH_PROP_UPDATE,\n PROPSTAT,\n REGEX_BASE_PATH\n} from '../constants/webdav'\nimport { IfHeader } from '../interfaces/if-header.interface'\nimport { FastifyDAVRequest, WebDAVContext } from '../interfaces/webdav.interface'\nimport { parseIfHeader } from '../utils/if-header'\nimport { PROPFIND_ALL_PROP } from '../utils/webdav'\nimport { xmlIsValid, xmlParse } from '../utils/xml'\n\n@Injectable()\nexport class WebDAVProtocolGuard implements CanActivate {\n private readonly logger = new Logger(WebDAVProtocolGuard.name)\n\n async canActivate(ctx: ExecutionContext): Promise<boolean> {\n const req: FastifyDAVRequest = ctx.switchToHttp().getRequest()\n const res: FastifyReply = ctx.switchToHttp().getResponse()\n this.checkUserPermission(req)\n this.setDAVContext(req)\n switch (req.method) {\n case HTTP_METHOD.OPTIONS:\n // hook to stop propagation and return headers on all webdav routes\n res.headers(OPTIONS_HEADERS)\n throw new HttpException(null, HttpStatus.OK)\n case HTTP_METHOD.PROPFIND:\n return this.propfindMethod(req)\n case HTTP_METHOD.LOCK:\n return this.lockMethod(req)\n case HTTP_METHOD.UNLOCK:\n return this.unlockMethod(req)\n case HTTP_METHOD.PUT:\n return this.putMethod(req)\n case HTTP_METHOD.DELETE:\n return this.deleteMethod(req)\n case HTTP_METHOD.PROPPATCH:\n return this.proppatchMethod(req)\n case HTTP_METHOD.MKCOL:\n return this.mkcolMethod(req)\n case HTTP_METHOD.COPY:\n return this.copyMoveMethod(req)\n case HTTP_METHOD.MOVE:\n return this.copyMoveMethod(req, true)\n default:\n return true\n }\n }\n\n private checkUserPermission(req: FastifyDAVRequest) {\n if (req.method !== HTTP_METHOD.OPTIONS && !req.user.havePermission(USER_PERMISSION.WEBDAV)) {\n this.logger.warn(`does not have permission : ${USER_PERMISSION.WEBDAV}`)\n throw new HttpException('Missing permission', HttpStatus.FORBIDDEN)\n }\n }\n\n private setDAVContext(req: FastifyDAVRequest) {\n req.dav = {\n url: decodeUrl(req.originalUrl),\n depth: DEPTH.RESOURCE\n } as WebDAVContext\n }\n\n private parseBody(req: FastifyDAVRequest) {\n let body = null\n let valid: true | ValidationError\n try {\n valid = xmlIsValid(req.body.toString())\n } catch (e) {\n valid = { err: { code: e.code, msg: `Invalid body content: ${e.message}`, line: 0, col: 0 } }\n }\n if (valid === true) {\n body = xmlParse(req.body)\n } else if (valid.err.code === undefined && ALLOW_EMPTY_BODY_METHODS.indexOf(req.method) > -1) {\n body = null\n } else {\n throw new HttpException(`${valid.err.code} : ${valid.err.msg}`, HttpStatus.BAD_REQUEST)\n }\n req.dav.httpVersion = `${req.protocol.toUpperCase()}/${req.raw['httpVersion']}`\n req.dav.body = body\n return true\n }\n\n private parseIfHeader(req: FastifyDAVRequest) {\n // stores if headers, examine it later\n if (req.headers[HEADER.IF]) {\n this.logger.verbose(`If header before : ${JSON.stringify(req.headers[HEADER.IF])}`)\n const ifHeaders: IfHeader[] = parseIfHeader(req.headers[HEADER.IF] as string)\n this.logger.verbose(`If header after : ${JSON.stringify(ifHeaders)}`)\n if (ifHeaders.length) req.dav.ifHeaders = ifHeaders\n }\n }\n\n private propfindMethod(req: FastifyDAVRequest) {\n req.dav.depth = (req.headers[HEADER.DEPTH] as string | undefined)?.toLowerCase()\n if (!req.dav.depth || (req.dav.depth !== DEPTH.MEMBERS && req.dav.depth !== DEPTH.RESOURCE)) {\n if (!req.dav.depth) {\n this.logger.warn('Missing propfind depth, default value 1 was set')\n } else if (req.dav.depth === DEPTH.INFINITY) {\n this.logger.warn('Infinite depth is disabled for security reasons, default value 1 was set')\n } else {\n this.logger.warn(`Invalid propfind depth header : ${req.dav.depth}, default value 1 was set`)\n }\n req.dav.depth = DEPTH.MEMBERS\n }\n if (this.parseBody(req)) {\n if (req.dav.body) {\n for (const propType in req.dav.body.propfind) {\n if (Object.values(PROPSTAT).indexOf(propType as PROPSTAT) > -1) {\n req.dav.propfindMode = propType as PROPSTAT\n break\n }\n }\n if (!req.dav.propfindMode) {\n this.logger.warn(`Invalid propfind mode : ${JSON.stringify(Object.keys(req.dav.body.propfind))}`)\n throw new HttpException('Invalid propfind mode', HttpStatus.BAD_REQUEST)\n }\n } else {\n // propfind request allow empty body\n req.dav.body = PROPFIND_ALL_PROP\n req.dav.propfindMode = PROPSTAT.ALLPROP\n }\n }\n this.parseIfHeader(req)\n return true\n }\n\n private proppatchMethod(req: FastifyDAVRequest) {\n req.dav.depth = ((req.headers[HEADER.DEPTH] as any) || DEPTH.RESOURCE).toLowerCase()\n this.parseBody(req)\n if (!req.dav.body || Object.keys(req.dav.body).indexOf(PROPPATCH_PROP_UPDATE) === -1) {\n this.logger.debug(`'${PROPPATCH_PROP_UPDATE}' is missing : ${JSON.stringify(req.dav.body)}`)\n throw new HttpException(`'${PROPPATCH_PROP_UPDATE}' is missing`, HttpStatus.BAD_REQUEST)\n }\n this.parseIfHeader(req)\n return true\n }\n\n private lockMethod(req: FastifyDAVRequest) {\n req.dav.lock = {}\n if (req.headers[HEADER.TIMEOUT]) {\n // timeout: 'Infinite, Second-4100000000' | 'Second-4100000000' | 'Infinite'\n const timeout = req.headers[HEADER.TIMEOUT] as string\n if (timeout.toLowerCase() === 'infinite') {\n req.dav.lock.timeout = FilesLockManager.defaultLockTimeoutSeconds\n } else {\n try {\n const timeoutSplit = timeout.split('-')\n const seconds = parseInt(timeoutSplit[timeoutSplit.length - 1], 10)\n req.dav.lock.timeout = seconds > FilesLockManager.defaultLockTimeoutSeconds ? FilesLockManager.defaultLockTimeoutSeconds : seconds\n } catch (e) {\n this.logger.warn(`${this.lockMethod.name} - unable to set timeout, use the default value : ${e}`)\n req.dav.lock.timeout = FilesLockManager.defaultLockTimeoutSeconds\n }\n }\n }\n this.parseBody(req)\n if (req.dav.body) {\n if (!req.dav.body['lockinfo']) {\n this.logger.warn(`Missing lockinfo : ${JSON.stringify(req.dav.body)}`)\n throw new HttpException('Missing lockinfo', HttpStatus.BAD_REQUEST)\n }\n try {\n req.dav.lock.lockscope = Object.keys(req.dav.body['lockinfo']['lockscope'])[0] as LOCK_SCOPE\n } catch (e) {\n this.logger.warn(`${this.parseBody.name} - invalid or undefined lockscope : ${JSON.stringify(req.dav.body['lockinfo'])} : ${e}`)\n throw new HttpException('Invalid or undefined lockscope', HttpStatus.BAD_REQUEST)\n }\n if (Object.values(LOCK_SCOPE).indexOf(req.dav.lock.lockscope) === -1) {\n this.logger.warn(`${this.parseBody.name} - invalid or undefined lockscope : ${JSON.stringify(req.dav.body['lockinfo'])}`)\n throw new HttpException('Invalid or undefined lockscope', HttpStatus.BAD_REQUEST)\n }\n if (req.dav.body['lockinfo']['owner'] && typeof req.dav.body['lockinfo']['owner'] === 'string') {\n req.dav.lock.owner = `${req.dav.body['lockinfo']['owner']} ${req.user.fullName} (${req.user.email})`\n } else {\n req.dav.lock.owner = `WebDAV - ${req.user.fullName} (${req.user.email})`\n }\n const depth: DEPTH = ((req.headers[HEADER.DEPTH] as any) || '').toLowerCase()\n req.dav.depth = [DEPTH.INFINITY, DEPTH.RESOURCE].indexOf(depth) === -1 ? DEPTH.INFINITY : depth\n } else {\n // must ignore depth header on lock refresh request\n req.dav.depth = null\n }\n this.parseIfHeader(req)\n return true\n }\n\n private unlockMethod(req: FastifyDAVRequest) {\n if (!req.headers[HEADER.LOCK_TOKEN]) {\n throw new HttpException('Missing lock token', HttpStatus.BAD_REQUEST)\n }\n req.dav.lock = { token: (req.headers[HEADER.LOCK_TOKEN] as string).replace('<', '').replace('>', '').trim() }\n this.parseIfHeader(req)\n return true\n }\n\n private putMethod(req: FastifyDAVRequest) {\n req.dav.depth = DEPTH.RESOURCE\n this.parseIfHeader(req)\n return true\n }\n\n private deleteMethod(req: FastifyDAVRequest) {\n this.parseIfHeader(req)\n return true\n }\n\n private mkcolMethod(req: FastifyDAVRequest) {\n if (req.headers['content-length'] && req.headers['content-length'] !== '0') {\n throw new HttpException('no body content required', HttpStatus.UNSUPPORTED_MEDIA_TYPE)\n }\n req.dav.depth = DEPTH.RESOURCE\n this.parseIfHeader(req)\n return true\n }\n\n private copyMoveMethod(req: FastifyDAVRequest, isMove = false) {\n if (!req.headers[HEADER.DESTINATION]) {\n throw new HttpException(`Missing ${HEADER.DESTINATION} header`, HttpStatus.BAD_REQUEST)\n }\n const destination = decodeUrl(urlToPath(req.headers[HEADER.DESTINATION] as string))\n if (!REGEX_BASE_PATH.test(destination)) {\n this.logger.warn(`The destination does not match the webdav base path : ${destination}`)\n throw new HttpException('The destination does not match', HttpStatus.BAD_REQUEST)\n }\n req.dav.depth = ((req.headers[HEADER.DEPTH] as any) || DEPTH.INFINITY).toLowerCase()\n req.dav.copyMove = {\n overwrite: ((req.headers[HEADER.OVERWRITE] as any) || 't').toLowerCase() === 't',\n destination: destination,\n isMove: isMove\n }\n this.parseIfHeader(req)\n return true\n }\n}\n"],"names":["WebDAVProtocolGuard","canActivate","ctx","req","switchToHttp","getRequest","res","getResponse","checkUserPermission","setDAVContext","method","HTTP_METHOD","OPTIONS","headers","OPTIONS_HEADERS","HttpException","HttpStatus","OK","PROPFIND","propfindMethod","LOCK","lockMethod","UNLOCK","unlockMethod","PUT","putMethod","DELETE","deleteMethod","PROPPATCH","proppatchMethod","MKCOL","mkcolMethod","COPY","copyMoveMethod","MOVE","user","havePermission","USER_PERMISSION","WEBDAV","logger","warn","FORBIDDEN","dav","url","decodeUrl","originalUrl","depth","DEPTH","RESOURCE","parseBody","body","valid","xmlIsValid","toString","e","err","code","msg","message","line","col","xmlParse","undefined","ALLOW_EMPTY_BODY_METHODS","indexOf","BAD_REQUEST","httpVersion","protocol","toUpperCase","raw","parseIfHeader","HEADER","IF","verbose","JSON","stringify","ifHeaders","length","toLowerCase","MEMBERS","INFINITY","propType","propfind","Object","values","PROPSTAT","propfindMode","keys","PROPFIND_ALL_PROP","ALLPROP","PROPPATCH_PROP_UPDATE","debug","lock","TIMEOUT","timeout","FilesLockManager","defaultLockTimeoutSeconds","timeoutSplit","split","seconds","parseInt","name","lockscope","LOCK_SCOPE","owner","fullName","email","LOCK_TOKEN","token","replace","trim","UNSUPPORTED_MEDIA_TYPE","isMove","DESTINATION","destination","urlToPath","REGEX_BASE_PATH","test","copyMove","overwrite","OVERWRITE","Logger"],"mappings":"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"}