@sync-in/server 1.9.6 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (367) hide show
  1. package/CHANGELOG.md +38 -4
  2. package/README.md +2 -2
  3. package/environment/environment.dist.yaml +15 -5
  4. package/package.json +14 -16
  5. package/server/app.bootstrap.js +4 -23
  6. package/server/app.bootstrap.js.map +1 -1
  7. package/server/app.constants.js +3 -2
  8. package/server/app.constants.js.map +1 -1
  9. package/server/applications/comments/services/comments-queries.service.js +5 -9
  10. package/server/applications/comments/services/comments-queries.service.js.map +1 -1
  11. package/server/applications/files/constants/cache.js +2 -5
  12. package/server/applications/files/constants/cache.js.map +1 -1
  13. package/server/applications/files/constants/files.js +4 -0
  14. package/server/applications/files/constants/files.js.map +1 -1
  15. package/server/applications/files/constants/operations.js +4 -0
  16. package/server/applications/files/constants/operations.js.map +1 -1
  17. package/server/applications/files/constants/routes.js +1 -26
  18. package/server/applications/files/constants/routes.js.map +1 -1
  19. package/server/applications/files/files.config.js +15 -39
  20. package/server/applications/files/files.config.js.map +1 -1
  21. package/server/applications/files/files.controller.js +4 -4
  22. package/server/applications/files/files.controller.js.map +1 -1
  23. package/server/applications/files/files.module.js +12 -9
  24. package/server/applications/files/files.module.js.map +1 -1
  25. package/server/applications/files/interfaces/file-lock.interface.js.map +1 -1
  26. package/server/applications/files/interfaces/file-props.interface.js.map +1 -1
  27. package/server/applications/files/modules/collabora-online/collabora-online-environment.decorator.js +32 -0
  28. package/server/applications/files/modules/collabora-online/collabora-online-environment.decorator.js.map +1 -0
  29. package/server/applications/files/modules/collabora-online/collabora-online-manager.service.js +280 -0
  30. package/server/applications/files/modules/collabora-online/collabora-online-manager.service.js.map +1 -0
  31. package/server/applications/files/modules/collabora-online/collabora-online-manager.service.spec.js +552 -0
  32. package/server/applications/files/modules/collabora-online/collabora-online-manager.service.spec.js.map +1 -0
  33. package/server/applications/files/modules/collabora-online/collabora-online.config.js +40 -0
  34. package/server/applications/files/modules/collabora-online/collabora-online.config.js.map +1 -0
  35. package/server/applications/files/modules/collabora-online/collabora-online.constants.js +110 -0
  36. package/server/applications/files/modules/collabora-online/collabora-online.constants.js.map +1 -0
  37. package/server/applications/files/modules/collabora-online/collabora-online.controller.js +128 -0
  38. package/server/applications/files/modules/collabora-online/collabora-online.controller.js.map +1 -0
  39. package/server/applications/files/modules/collabora-online/collabora-online.controller.spec.js +47 -0
  40. package/server/applications/files/modules/collabora-online/collabora-online.controller.spec.js.map +1 -0
  41. package/server/applications/files/{interfaces/only-office-config.interface.js → modules/collabora-online/collabora-online.dtos.js} +1 -1
  42. package/server/applications/files/modules/collabora-online/collabora-online.dtos.js.map +1 -0
  43. package/server/applications/files/{guards/files-only-office.guard.js → modules/collabora-online/collabora-online.guard.js} +7 -21
  44. package/server/applications/files/modules/collabora-online/collabora-online.guard.js.map +1 -0
  45. package/server/applications/files/modules/collabora-online/collabora-online.guard.spec.js +86 -0
  46. package/server/applications/files/modules/collabora-online/collabora-online.guard.spec.js.map +1 -0
  47. package/server/applications/files/modules/collabora-online/collabora-online.interface.js +10 -0
  48. package/server/applications/files/modules/collabora-online/collabora-online.interface.js.map +1 -0
  49. package/server/applications/files/modules/collabora-online/collabora-online.module.js +41 -0
  50. package/server/applications/files/modules/collabora-online/collabora-online.module.js.map +1 -0
  51. package/server/applications/files/modules/collabora-online/collabora-online.routes.js +35 -0
  52. package/server/applications/files/modules/collabora-online/collabora-online.routes.js.map +1 -0
  53. package/server/applications/files/modules/collabora-online/collabora-online.strategy.js +59 -0
  54. package/server/applications/files/modules/collabora-online/collabora-online.strategy.js.map +1 -0
  55. package/server/applications/files/modules/collabora-online/collabora-online.utils.js +28 -0
  56. package/server/applications/files/modules/collabora-online/collabora-online.utils.js.map +1 -0
  57. package/server/applications/files/{decorators → modules/only-office}/only-office-environment.decorator.js +5 -5
  58. package/server/applications/files/modules/only-office/only-office-environment.decorator.js.map +1 -0
  59. package/server/applications/files/{services/files-only-office-manager.service.js → modules/only-office/only-office-manager.service.js} +101 -97
  60. package/server/applications/files/modules/only-office/only-office-manager.service.js.map +1 -0
  61. package/server/applications/files/modules/only-office/only-office-manager.service.spec.js +477 -0
  62. package/server/applications/files/modules/only-office/only-office-manager.service.spec.js.map +1 -0
  63. package/server/applications/files/modules/only-office/only-office.config.js +51 -0
  64. package/server/applications/files/modules/only-office/only-office.config.js.map +1 -0
  65. package/server/applications/files/modules/only-office/only-office.constants.js +417 -0
  66. package/server/applications/files/modules/only-office/only-office.constants.js.map +1 -0
  67. package/server/applications/files/{files-only-office.controller.js → modules/only-office/only-office.controller.js} +35 -52
  68. package/server/applications/files/modules/only-office/only-office.controller.js.map +1 -0
  69. package/server/applications/files/{files-only-office.controller.spec.js → modules/only-office/only-office.controller.spec.js} +24 -21
  70. package/server/applications/files/modules/only-office/only-office.controller.spec.js.map +1 -0
  71. package/server/applications/files/modules/only-office/only-office.dtos.js +10 -0
  72. package/server/applications/files/modules/only-office/only-office.dtos.js.map +1 -0
  73. package/server/applications/files/modules/only-office/only-office.guard.js +40 -0
  74. package/server/applications/files/modules/only-office/only-office.guard.js.map +1 -0
  75. package/server/applications/files/{guards/files-only-office.guard.spec.js → modules/only-office/only-office.guard.spec.js} +15 -21
  76. package/server/applications/files/modules/only-office/only-office.guard.spec.js.map +1 -0
  77. package/server/applications/files/modules/only-office/only-office.interface.js +10 -0
  78. package/server/applications/files/modules/only-office/only-office.interface.js.map +1 -0
  79. package/server/applications/files/modules/only-office/only-office.module.js +41 -0
  80. package/server/applications/files/modules/only-office/only-office.module.js.map +1 -0
  81. package/server/applications/files/modules/only-office/only-office.routes.js +45 -0
  82. package/server/applications/files/modules/only-office/only-office.routes.js.map +1 -0
  83. package/server/applications/files/{guards/files-only-office.strategy.js → modules/only-office/only-office.strategy.js} +11 -11
  84. package/server/applications/files/modules/only-office/only-office.strategy.js.map +1 -0
  85. package/server/applications/files/services/files-lock-manager.service.js +25 -33
  86. package/server/applications/files/services/files-lock-manager.service.js.map +1 -1
  87. package/server/applications/files/services/files-manager.service.js +17 -16
  88. package/server/applications/files/services/files-manager.service.js.map +1 -1
  89. package/server/applications/files/services/files-methods.service.js +2 -2
  90. package/server/applications/files/services/files-methods.service.js.map +1 -1
  91. package/server/applications/files/services/files-methods.service.spec.js +3 -1
  92. package/server/applications/files/services/files-methods.service.spec.js.map +1 -1
  93. package/server/applications/files/services/files-scheduler.service.js +2 -2
  94. package/server/applications/files/services/files-scheduler.service.js.map +1 -1
  95. package/server/applications/files/utils/files.js +10 -2
  96. package/server/applications/files/utils/files.js.map +1 -1
  97. package/server/applications/links/constants/routes.js +5 -0
  98. package/server/applications/links/constants/routes.js.map +1 -1
  99. package/server/applications/links/interfaces/link-space.interface.js.map +1 -1
  100. package/server/applications/links/links.controller.js +25 -5
  101. package/server/applications/links/links.controller.js.map +1 -1
  102. package/server/applications/links/services/links-manager.service.js +43 -21
  103. package/server/applications/links/services/links-manager.service.js.map +1 -1
  104. package/server/applications/links/services/links-manager.service.spec.js +4 -3
  105. package/server/applications/links/services/links-manager.service.spec.js.map +1 -1
  106. package/server/applications/links/services/links-queries.service.js +9 -2
  107. package/server/applications/links/services/links-queries.service.js.map +1 -1
  108. package/server/applications/shares/interfaces/share-link.interface.js.map +1 -1
  109. package/server/applications/shares/services/shares-manager.service.js +3 -0
  110. package/server/applications/shares/services/shares-manager.service.js.map +1 -1
  111. package/server/applications/shares/services/shares-manager.service.spec.js +2 -1
  112. package/server/applications/shares/services/shares-manager.service.spec.js.map +1 -1
  113. package/server/applications/shares/services/shares-queries.service.js +1 -0
  114. package/server/applications/shares/services/shares-queries.service.js.map +1 -1
  115. package/server/applications/spaces/constants/spaces.js +2 -2
  116. package/server/applications/spaces/constants/spaces.js.map +1 -1
  117. package/server/applications/spaces/decorators/space-override-permission.decorator.js +18 -0
  118. package/server/applications/spaces/decorators/space-override-permission.decorator.js.map +1 -0
  119. package/server/applications/spaces/guards/space.guard.js +40 -33
  120. package/server/applications/spaces/guards/space.guard.js.map +1 -1
  121. package/server/applications/spaces/guards/space.guard.spec.js +10 -15
  122. package/server/applications/spaces/guards/space.guard.spec.js.map +1 -1
  123. package/server/applications/users/users.e2e-spec.js +0 -1
  124. package/server/applications/users/users.e2e-spec.js.map +1 -1
  125. package/server/applications/webdav/constants/webdav.js +11 -0
  126. package/server/applications/webdav/constants/webdav.js.map +1 -1
  127. package/server/applications/webdav/guards/webdav-protocol.guard.js +9 -8
  128. package/server/applications/webdav/guards/webdav-protocol.guard.js.map +1 -1
  129. package/server/applications/webdav/guards/webdav-protocol.guard.spec.js +1 -1
  130. package/server/applications/webdav/guards/webdav-protocol.guard.spec.js.map +1 -1
  131. package/server/applications/webdav/interfaces/webdav.interface.js.map +1 -1
  132. package/server/applications/webdav/services/webdav-methods.service.js +40 -17
  133. package/server/applications/webdav/services/webdav-methods.service.js.map +1 -1
  134. package/server/applications/webdav/services/webdav-methods.service.spec.js +2157 -1289
  135. package/server/applications/webdav/services/webdav-methods.service.spec.js.map +1 -1
  136. package/server/applications/webdav/utils/bootstrap.js +45 -0
  137. package/server/applications/webdav/utils/bootstrap.js.map +1 -0
  138. package/server/applications/webdav/utils/webdav.js +8 -4
  139. package/server/applications/webdav/utils/webdav.js.map +1 -1
  140. package/server/applications/webdav/webdav.controller.js +5 -5
  141. package/server/applications/webdav/webdav.controller.js.map +1 -1
  142. package/server/applications/webdav/webdav.e2e-spec.js +131 -2
  143. package/server/applications/webdav/webdav.e2e-spec.js.map +1 -1
  144. package/server/authentication/auth.e2e-spec.js +12 -6
  145. package/server/authentication/auth.e2e-spec.js.map +1 -1
  146. package/server/authentication/guards/auth-basic.guard.spec.js +23 -0
  147. package/server/authentication/guards/auth-basic.guard.spec.js.map +1 -1
  148. package/server/authentication/guards/auth-basic.strategy.js +3 -3
  149. package/server/authentication/guards/auth-basic.strategy.js.map +1 -1
  150. package/server/authentication/guards/auth-digest.strategy.js +32 -11
  151. package/server/authentication/guards/auth-digest.strategy.js.map +1 -1
  152. package/server/authentication/guards/auth-token-access.guard.js +8 -3
  153. package/server/authentication/guards/auth-token-access.guard.js.map +1 -1
  154. package/server/authentication/guards/implementations/http-basic.strategy.js +76 -0
  155. package/server/authentication/guards/implementations/http-basic.strategy.js.map +1 -0
  156. package/server/authentication/guards/implementations/http-digest.strategy.js +155 -0
  157. package/server/authentication/guards/implementations/http-digest.strategy.js.map +1 -0
  158. package/server/authentication/services/auth-manager.service.js +1 -2
  159. package/server/authentication/services/auth-manager.service.js.map +1 -1
  160. package/server/authentication/services/auth-methods/auth-method-two-fa.service.js +1 -1
  161. package/server/authentication/services/auth-methods/auth-method-two-fa.service.js.map +1 -1
  162. package/server/authentication/services/auth-methods/auth-method-two-fa.service.spec.js +350 -4
  163. package/server/authentication/services/auth-methods/auth-method-two-fa.service.spec.js.map +1 -1
  164. package/server/configuration/config.environment.js +5 -1
  165. package/server/configuration/config.environment.js.map +1 -1
  166. package/server/configuration/config.interfaces.js.map +1 -1
  167. package/static/3rdpartylicenses.txt +507 -507
  168. package/static/assets/pdfjs/build/pdf.mjs +93 -33
  169. package/static/assets/pdfjs/build/pdf.mjs.map +1 -1
  170. package/static/assets/pdfjs/build/pdf.sandbox.mjs +3 -3
  171. package/static/assets/pdfjs/build/pdf.sandbox.mjs.map +1 -1
  172. package/static/assets/pdfjs/build/pdf.worker.mjs +166 -54
  173. package/static/assets/pdfjs/build/pdf.worker.mjs.map +1 -1
  174. package/static/assets/pdfjs/version +1 -1
  175. package/static/assets/pdfjs/web/images/checkmark.svg +5 -0
  176. package/static/assets/pdfjs/web/images/pages_closeButton.svg +3 -0
  177. package/static/assets/pdfjs/web/images/pages_selected.svg +7 -0
  178. package/static/assets/pdfjs/web/images/pages_viewArrow.svg +3 -0
  179. package/static/assets/pdfjs/web/images/pages_viewButton.svg +3 -0
  180. package/static/assets/pdfjs/web/locale/be/viewer.ftl +0 -2
  181. package/static/assets/pdfjs/web/locale/bs/viewer.ftl +0 -5
  182. package/static/assets/pdfjs/web/locale/cs/viewer.ftl +4 -6
  183. package/static/assets/pdfjs/web/locale/cy/viewer.ftl +0 -2
  184. package/static/assets/pdfjs/web/locale/da/viewer.ftl +0 -2
  185. package/static/assets/pdfjs/web/locale/de/viewer.ftl +0 -2
  186. package/static/assets/pdfjs/web/locale/dsb/viewer.ftl +0 -2
  187. package/static/assets/pdfjs/web/locale/el/viewer.ftl +0 -2
  188. package/static/assets/pdfjs/web/locale/en-CA/viewer.ftl +6 -2
  189. package/static/assets/pdfjs/web/locale/en-GB/viewer.ftl +0 -2
  190. package/static/assets/pdfjs/web/locale/en-US/viewer.ftl +82 -17
  191. package/static/assets/pdfjs/web/locale/eo/viewer.ftl +0 -2
  192. package/static/assets/pdfjs/web/locale/es-AR/viewer.ftl +0 -2
  193. package/static/assets/pdfjs/web/locale/es-CL/viewer.ftl +0 -2
  194. package/static/assets/pdfjs/web/locale/es-ES/viewer.ftl +0 -2
  195. package/static/assets/pdfjs/web/locale/es-MX/viewer.ftl +0 -2
  196. package/static/assets/pdfjs/web/locale/eu/viewer.ftl +0 -2
  197. package/static/assets/pdfjs/web/locale/fi/viewer.ftl +0 -2
  198. package/static/assets/pdfjs/web/locale/fr/viewer.ftl +0 -2
  199. package/static/assets/pdfjs/web/locale/fur/viewer.ftl +0 -5
  200. package/static/assets/pdfjs/web/locale/fy-NL/viewer.ftl +3 -5
  201. package/static/assets/pdfjs/web/locale/gn/viewer.ftl +0 -2
  202. package/static/assets/pdfjs/web/locale/he/viewer.ftl +0 -2
  203. package/static/assets/pdfjs/web/locale/hr/viewer.ftl +66 -0
  204. package/static/assets/pdfjs/web/locale/hsb/viewer.ftl +0 -2
  205. package/static/assets/pdfjs/web/locale/hu/viewer.ftl +0 -2
  206. package/static/assets/pdfjs/web/locale/hy-AM/viewer.ftl +3 -8
  207. package/static/assets/pdfjs/web/locale/ia/viewer.ftl +0 -2
  208. package/static/assets/pdfjs/web/locale/id/viewer.ftl +0 -5
  209. package/static/assets/pdfjs/web/locale/is/viewer.ftl +0 -5
  210. package/static/assets/pdfjs/web/locale/it/viewer.ftl +0 -2
  211. package/static/assets/pdfjs/web/locale/ja/viewer.ftl +0 -14
  212. package/static/assets/pdfjs/web/locale/ka/viewer.ftl +4 -6
  213. package/static/assets/pdfjs/web/locale/kab/viewer.ftl +0 -5
  214. package/static/assets/pdfjs/web/locale/kk/viewer.ftl +0 -2
  215. package/static/assets/pdfjs/web/locale/ko/viewer.ftl +0 -2
  216. package/static/assets/pdfjs/web/locale/nb-NO/viewer.ftl +1 -3
  217. package/static/assets/pdfjs/web/locale/nl/viewer.ftl +0 -2
  218. package/static/assets/pdfjs/web/locale/nn-NO/viewer.ftl +4 -2
  219. package/static/assets/pdfjs/web/locale/pa-IN/viewer.ftl +0 -2
  220. package/static/assets/pdfjs/web/locale/pl/viewer.ftl +0 -2
  221. package/static/assets/pdfjs/web/locale/pt-BR/viewer.ftl +0 -2
  222. package/static/assets/pdfjs/web/locale/pt-PT/viewer.ftl +35 -0
  223. package/static/assets/pdfjs/web/locale/rm/viewer.ftl +0 -5
  224. package/static/assets/pdfjs/web/locale/ro/viewer.ftl +4 -6
  225. package/static/assets/pdfjs/web/locale/ru/viewer.ftl +3 -5
  226. package/static/assets/pdfjs/web/locale/sk/viewer.ftl +0 -2
  227. package/static/assets/pdfjs/web/locale/sl/viewer.ftl +0 -2
  228. package/static/assets/pdfjs/web/locale/sq/viewer.ftl +0 -2
  229. package/static/assets/pdfjs/web/locale/sv-SE/viewer.ftl +0 -2
  230. package/static/assets/pdfjs/web/locale/tg/viewer.ftl +0 -2
  231. package/static/assets/pdfjs/web/locale/th/viewer.ftl +2 -2
  232. package/static/assets/pdfjs/web/locale/tr/viewer.ftl +0 -2
  233. package/static/assets/pdfjs/web/locale/vi/viewer.ftl +0 -2
  234. package/static/assets/pdfjs/web/locale/zh-CN/viewer.ftl +0 -2
  235. package/static/assets/pdfjs/web/locale/zh-TW/viewer.ftl +0 -2
  236. package/static/assets/pdfjs/web/viewer.css +1778 -835
  237. package/static/assets/pdfjs/web/viewer.html +167 -86
  238. package/static/assets/pdfjs/web/viewer.mjs +1106 -801
  239. package/static/assets/pdfjs/web/viewer.mjs.map +1 -1
  240. package/static/chunk-27V66YJV.js +2 -0
  241. package/static/{chunk-2F42MZQ5.js → chunk-2GXOVGTD.js} +1 -1
  242. package/static/{chunk-HLKZCMKV.js → chunk-2RWLNKZH.js} +1 -1
  243. package/static/chunk-2YQ4SX3A.js +13 -0
  244. package/static/{chunk-LFAQLJZK.js → chunk-3MVPXC3U.js} +1 -1
  245. package/static/chunk-3QTROEHV.js +1 -0
  246. package/static/{chunk-JYHTSSKW.js → chunk-3VRUIWQG.js} +1 -1
  247. package/static/{chunk-2CAAJBRO.js → chunk-3ZBAQTHJ.js} +1 -1
  248. package/static/chunk-3ZLBVUCX.js +2 -0
  249. package/static/chunk-46TJLPJY.js +1 -0
  250. package/static/chunk-4NIYCYRS.js +2 -0
  251. package/static/chunk-6OEOADR6.js +1 -0
  252. package/static/{chunk-BJARRIS6.js → chunk-76M3BMK6.js} +11 -11
  253. package/static/{chunk-ANH4VNOS.js → chunk-76REYAEA.js} +1 -1
  254. package/static/{chunk-7HL5Z6PF.js → chunk-7HJFIMNF.js} +1 -1
  255. package/static/{chunk-XIQXRSZ2.js → chunk-7KAYOR3A.js} +1 -1
  256. package/static/chunk-AALPWGPB.js +3 -0
  257. package/static/{chunk-Z2KBIZ5D.js → chunk-ARS47O5X.js} +1 -1
  258. package/static/chunk-BCN4T5DO.js +2 -0
  259. package/static/{chunk-DU4Q4RWJ.js → chunk-CMNMPG6Z.js} +1 -1
  260. package/static/{chunk-UO7ATVQG.js → chunk-CN5YVRFT.js} +1 -1
  261. package/static/{chunk-BX3QZ7IL.js → chunk-CSVPAZHK.js} +1 -1
  262. package/static/chunk-CVXLHSO5.js +1 -0
  263. package/static/{chunk-O233BXWK.js → chunk-D2MLAO5N.js} +1 -1
  264. package/static/{chunk-NHMYAVJK.js → chunk-D5FQ72R4.js} +1 -1
  265. package/static/{chunk-IBC7CFBQ.js → chunk-DVCN3P7Q.js} +1 -1
  266. package/static/{chunk-25PWAXTJ.js → chunk-EKWB5W72.js} +1 -1
  267. package/static/{chunk-ZCOEP4O2.js → chunk-FTFEQDWH.js} +1 -1
  268. package/static/{chunk-EPDWJEPD.js → chunk-FWQJ4ZCD.js} +1 -1
  269. package/static/chunk-G7RZN7HN.js +1 -0
  270. package/static/{chunk-X5UDV4ZB.js → chunk-HZAB6F4Q.js} +1 -1
  271. package/static/{chunk-FEQUP26G.js → chunk-IHS5LSJJ.js} +1 -1
  272. package/static/{chunk-DQAQUSVW.js → chunk-IMFO2MI7.js} +1 -1
  273. package/static/{chunk-ODAQRAPO.js → chunk-J7474P3L.js} +1 -1
  274. package/static/{chunk-DK2LAJEL.js → chunk-JAJ7VXMB.js} +1 -1
  275. package/static/{chunk-AYYJZMBE.js → chunk-JNTNMIUH.js} +1 -1
  276. package/static/chunk-JRXG43AA.js +2 -0
  277. package/static/{chunk-3AR5VNJE.js → chunk-KAUCN24H.js} +1 -1
  278. package/static/{chunk-3WS72A6C.js → chunk-KDUAB76O.js} +1 -1
  279. package/static/chunk-KEZNIIFH.js +1 -0
  280. package/static/chunk-LTJNLOX2.js +1 -0
  281. package/static/chunk-LWSCODLD.js +1 -0
  282. package/static/{chunk-GRV44RYI.js → chunk-LZUHREOF.js} +1 -1
  283. package/static/chunk-NIKNG2FX.js +1 -0
  284. package/static/chunk-NNZWSNAW.js +1 -0
  285. package/static/chunk-NWKBB7J4.js +1 -0
  286. package/static/{chunk-B4TDS6AQ.js → chunk-PDG7DOEF.js} +1 -1
  287. package/static/{chunk-NQCKX2AD.js → chunk-PPJCVBJH.js} +1 -1
  288. package/static/chunk-PVYVY3GD.js +1 -0
  289. package/static/chunk-Q5X5TPAG.js +1 -0
  290. package/static/chunk-QGHNJVJ6.js +1 -0
  291. package/static/{chunk-5HYSNQR4.js → chunk-QJ22N76V.js} +1 -1
  292. package/static/{chunk-TOCCCZP2.js → chunk-QTPIEEZW.js} +1 -1
  293. package/static/{chunk-D6QWQHWE.js → chunk-R4VMWCM5.js} +1 -1
  294. package/static/{chunk-7H5O4BLV.js → chunk-R4VYKZVJ.js} +1 -1
  295. package/static/{chunk-QKMN3S4M.js → chunk-RBTLSPYJ.js} +1 -1
  296. package/static/chunk-RJULB733.js +1 -0
  297. package/static/{chunk-E5C4QRNQ.js → chunk-RNVPQQKT.js} +5 -5
  298. package/static/chunk-RTNEBRKJ.js +1 -0
  299. package/static/{chunk-IIKL33TV.js → chunk-S44QIK3G.js} +1 -1
  300. package/static/{chunk-SF6Q6VRC.js → chunk-S6H2ELRY.js} +1 -1
  301. package/static/{chunk-4GBA6EJ4.js → chunk-SDJNZULP.js} +1 -1
  302. package/static/chunk-SNOOCDJD.js +1 -0
  303. package/static/chunk-SPQH3ATC.js +5 -0
  304. package/static/{chunk-5KVI243T.js → chunk-TNCKNU6I.js} +1 -1
  305. package/static/{chunk-7QYALK5T.js → chunk-TTWMFWEC.js} +1 -1
  306. package/static/{chunk-OVUMPMVM.js → chunk-U5E5H2DD.js} +1 -1
  307. package/static/{chunk-5NFH4E2B.js → chunk-UOK3LKSX.js} +1 -1
  308. package/static/{chunk-5ATJIR5S.js → chunk-VBTZDHZ3.js} +1 -1
  309. package/static/{chunk-CHMDM2ZW.js → chunk-VD5JHSDS.js} +1 -1
  310. package/static/chunk-VZFZUI6D.js +1 -0
  311. package/static/{chunk-GYYJ4FWN.js → chunk-WFMEUST4.js} +1 -1
  312. package/static/{chunk-BVKDW5XO.js → chunk-WRK2FTKU.js} +1 -1
  313. package/static/{chunk-GLPKRULI.js → chunk-WZPF4LS2.js} +1 -1
  314. package/static/chunk-X7NHX5C7.js +1 -0
  315. package/static/{chunk-FSGT46LM.js → chunk-XSURUW7C.js} +1 -1
  316. package/static/{chunk-KAAFVHYE.js → chunk-XX3JPJUM.js} +1 -1
  317. package/static/{chunk-C5T7RZSD.js → chunk-XZHWESIY.js} +1 -1
  318. package/static/chunk-ZCSHU3D7.js +1 -0
  319. package/static/{chunk-QUUQOBTF.js → chunk-ZEJLIGAY.js} +1 -1
  320. package/static/{chunk-GENTF6JM.js → chunk-ZHUBWKA2.js} +1 -1
  321. package/static/chunk-ZOMRIN3G.js +2 -0
  322. package/static/{chunk-2U5VKTML.js → chunk-ZU5MQTFN.js} +1 -1
  323. package/static/index.html +2 -2
  324. package/static/main-5O3KLGIR.js +11 -0
  325. package/static/{styles-S5HVK4H5.css → styles-XLLEY5Y3.css} +1 -1
  326. package/server/applications/files/constants/only-office.js +0 -531
  327. package/server/applications/files/constants/only-office.js.map +0 -1
  328. package/server/applications/files/decorators/only-office-environment.decorator.js.map +0 -1
  329. package/server/applications/files/files-only-office.controller.js.map +0 -1
  330. package/server/applications/files/files-only-office.controller.spec.js.map +0 -1
  331. package/server/applications/files/guards/files-only-office.guard.js.map +0 -1
  332. package/server/applications/files/guards/files-only-office.guard.spec.js.map +0 -1
  333. package/server/applications/files/guards/files-only-office.strategy.js.map +0 -1
  334. package/server/applications/files/interfaces/only-office-config.interface.js.map +0 -1
  335. package/server/applications/files/services/files-only-office-manager.service.js.map +0 -1
  336. package/server/applications/files/services/files-only-office-manager.service.spec.js +0 -58
  337. package/server/applications/files/services/files-only-office-manager.service.spec.js.map +0 -1
  338. package/static/chunk-42L6C5MT.js +0 -1
  339. package/static/chunk-4ZKAVMB4.js +0 -1
  340. package/static/chunk-5GIWZKNS.js +0 -1
  341. package/static/chunk-5WCQBTXW.js +0 -1
  342. package/static/chunk-B2A4HNDC.js +0 -1
  343. package/static/chunk-BSB4VROD.js +0 -2
  344. package/static/chunk-CUC7R6C2.js +0 -1
  345. package/static/chunk-DHFQIFOF.js +0 -1
  346. package/static/chunk-DRHPEERW.js +0 -2
  347. package/static/chunk-FCGTI42I.js +0 -1
  348. package/static/chunk-FCR5AEHR.js +0 -3
  349. package/static/chunk-HB5DC7RJ.js +0 -1
  350. package/static/chunk-ITVA26X2.js +0 -2
  351. package/static/chunk-KWKZN53T.js +0 -1
  352. package/static/chunk-LBXOAKBD.js +0 -1
  353. package/static/chunk-LZKI5P5T.js +0 -1
  354. package/static/chunk-MGMDT4VN.js +0 -1
  355. package/static/chunk-MWUUM2NK.js +0 -13
  356. package/static/chunk-MYM43ENO.js +0 -1
  357. package/static/chunk-NAH4V2R6.js +0 -2
  358. package/static/chunk-PCFH5HCI.js +0 -2
  359. package/static/chunk-Q6B4OVER.js +0 -5
  360. package/static/chunk-QV5LQKTS.js +0 -1
  361. package/static/chunk-S4UTSOPV.js +0 -1
  362. package/static/chunk-SRBOO7AO.js +0 -1
  363. package/static/chunk-VZPCXSRG.js +0 -2
  364. package/static/chunk-XKEBQNQJ.js +0 -1
  365. package/static/chunk-YYTDPI5S.js +0 -1
  366. package/static/main-ODUA232E.js +0 -11
  367. /package/static/assets/pdfjs/web/images/{toolbarButton-sidebarToggle.svg → toolbarButton-viewsManagerToggle.svg} +0 -0
@@ -123,15 +123,15 @@ function LOCK_DISCOVERY(locks) {
123
123
  [`${_webdav.NS_PREFIX}:write`]: null
124
124
  },
125
125
  [`${_webdav.NS_PREFIX}:lockscope`]: {
126
- [`${_webdav.NS_PREFIX}:${lock.davLock?.lockscope || _webdav.LOCK_SCOPE.EXCLUSIVE}`]: null
126
+ [`${_webdav.NS_PREFIX}:${lock.options?.lockScope || _webdav.LOCK_SCOPE.EXCLUSIVE}`]: null
127
127
  },
128
128
  [`${_webdav.NS_PREFIX}:locktoken`]: {
129
- [`${_webdav.NS_PREFIX}:href`]: lock.davLock?.locktoken || _shared.SERVER_NAME
129
+ [`${_webdav.NS_PREFIX}:href`]: lock.options?.lockToken || _shared.SERVER_NAME
130
130
  },
131
131
  [`${_webdav.NS_PREFIX}:lockroot`]: {
132
- [`${_webdav.NS_PREFIX}:href`]: (0, _shared.encodeUrl)(lock.davLock?.lockroot || lock.dbFilePath)
132
+ [`${_webdav.NS_PREFIX}:href`]: (0, _shared.encodeUrl)(lock.options?.lockRoot || lock.dbFilePath)
133
133
  },
134
- [`${_webdav.NS_PREFIX}:owner`]: lock.davLock?.owner || 'WebDAV',
134
+ [`${_webdav.NS_PREFIX}:owner`]: formatLockOwner(lock),
135
135
  [`${_webdav.NS_PREFIX}:timeout`]: `Second-${Math.floor(lock.expiration - (0, _shared.currentTimeStamp)())}`,
136
136
  [`${_webdav.NS_PREFIX}:depth`]: lock.depth
137
137
  }
@@ -162,5 +162,9 @@ function DAV_ERROR(error, href) {
162
162
  function DAV_ERROR_RES(code, error, res, href) {
163
163
  return res.status(code).type(_webdav.XML_CONTENT_TYPE).send(DAV_ERROR(error, href));
164
164
  }
165
+ function formatLockOwner(lock) {
166
+ const lockInfo = `${lock.options.lockInfo ? `${lock.options.lockInfo}` : ''}${lock.app ? ` ${lock.app}` : ''}`;
167
+ return `${lock.owner.fullName} (${lock.owner.email})${lockInfo ? ` - ${lockInfo}` : ''}`;
168
+ }
165
169
 
166
170
  //# sourceMappingURL=webdav.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/webdav/utils/webdav.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 http from 'node:http'\nimport { currentTimeStamp, encodeUrl, SERVER_NAME } from '../../../common/shared'\nimport { FileLock } from '../../files/interfaces/file-lock.interface'\nimport { LOCK_SCOPE, NS_DAV, NS_PREFIX, PROPSTAT, XML_CONTENT_TYPE } from '../constants/webdav'\nimport { XML_NS, xmlBuild } from './xml'\n\nexport const XML_DAV_NS = { [`${XML_NS}:${NS_PREFIX}`]: `${NS_DAV}` }\nexport const PROPFIND_COLLECTION = { [`${NS_PREFIX}:collection`]: null }\nexport const PROPFIND_ALL_PROP = {\n [`${NS_PREFIX}:propfind`]: {\n [`${NS_PREFIX}:${PROPSTAT.ALLPROP}`]: null,\n ...XML_DAV_NS\n }\n}\n\nexport const SUPPORTED_LOCKS = {\n [`${NS_PREFIX}:lockentry`]: [\n {\n [`${NS_PREFIX}:lockscope`]: {\n [`${NS_PREFIX}:exclusive`]: null\n },\n [`${NS_PREFIX}:locktype`]: {\n [`${NS_PREFIX}:write`]: null\n }\n },\n {\n [`${NS_PREFIX}:lockscope`]: {\n [`${NS_PREFIX}:shared`]: null\n },\n [`${NS_PREFIX}:locktype`]: {\n [`${NS_PREFIX}:write`]: null\n }\n }\n ]\n}\n\nexport function PROP(prop: any, httpVersion: string, httpStatus: number, description?: string) {\n return {\n [`${NS_PREFIX}:prop`]: prop,\n [`${NS_PREFIX}:status`]: `${httpVersion} ${httpStatus} ${http.STATUS_CODES[httpStatus]}`,\n [`${NS_PREFIX}:responsedescription`]: description ? { [`${NS_PREFIX}:error`]: { [`${NS_PREFIX}:${description}`]: null } } : undefined\n }\n}\n\nexport function PROP_STAT(href: string, props: any) {\n return {\n [`${NS_PREFIX}:href`]: href,\n [`${NS_PREFIX}:propstat`]: props\n }\n}\n\nexport function MULTI_STATUS(content: any) {\n return {\n [`${NS_PREFIX}:multistatus`]: { [`${NS_PREFIX}:response`]: content, ...XML_DAV_NS }\n }\n}\n\nexport function LOCK_DISCOVERY(locks: FileLock[]) {\n // only locktype write is currently implemented in RFC\n const activeLocks = []\n for (const lock of locks) {\n activeLocks.push({\n [`${NS_PREFIX}:activelock`]: {\n [`${NS_PREFIX}:locktype`]: { [`${NS_PREFIX}:write`]: null },\n [`${NS_PREFIX}:lockscope`]: { [`${NS_PREFIX}:${lock.davLock?.lockscope || LOCK_SCOPE.EXCLUSIVE}`]: null },\n [`${NS_PREFIX}:locktoken`]: { [`${NS_PREFIX}:href`]: lock.davLock?.locktoken || SERVER_NAME },\n [`${NS_PREFIX}:lockroot`]: { [`${NS_PREFIX}:href`]: encodeUrl(lock.davLock?.lockroot || lock.dbFilePath) },\n [`${NS_PREFIX}:owner`]: lock.davLock?.owner || 'WebDAV',\n [`${NS_PREFIX}:timeout`]: `Second-${Math.floor(lock.expiration - currentTimeStamp())}`,\n [`${NS_PREFIX}:depth`]: lock.depth\n }\n })\n }\n return activeLocks\n}\n\nexport function LOCK_PROP(locks: FileLock[]) {\n return { [`${NS_PREFIX}:prop`]: { [`${NS_PREFIX}:lockdiscovery`]: LOCK_DISCOVERY(locks), ...XML_DAV_NS } }\n}\n\nexport function DAV_ERROR(error: string, href?: string): string {\n return xmlBuild({\n 'ns0:error': { [`ns0:${error}`]: href ? [{ 'ns0:href': encodeUrl(href) }] : '', [`${XML_NS}:ns0`]: `${NS_DAV}` }\n })\n}\n\nexport function DAV_ERROR_RES(code: number, error: string, res: FastifyReply, href?: string): FastifyReply {\n return res.status(code).type(XML_CONTENT_TYPE).send(DAV_ERROR(error, href))\n}\n"],"names":["DAV_ERROR","DAV_ERROR_RES","LOCK_DISCOVERY","LOCK_PROP","MULTI_STATUS","PROP","PROPFIND_ALL_PROP","PROPFIND_COLLECTION","PROP_STAT","SUPPORTED_LOCKS","XML_DAV_NS","XML_NS","NS_PREFIX","NS_DAV","PROPSTAT","ALLPROP","prop","httpVersion","httpStatus","description","http","STATUS_CODES","undefined","href","props","content","locks","activeLocks","lock","push","davLock","lockscope","LOCK_SCOPE","EXCLUSIVE","locktoken","SERVER_NAME","encodeUrl","lockroot","dbFilePath","owner","Math","floor","expiration","currentTimeStamp","depth","error","xmlBuild","code","res","status","type","XML_CONTENT_TYPE","send"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/webdav/utils/webdav.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 http from 'node:http'\nimport { currentTimeStamp, encodeUrl, SERVER_NAME } from '../../../common/shared'\nimport { FileLock } from '../../files/interfaces/file-lock.interface'\nimport { LOCK_SCOPE, NS_DAV, NS_PREFIX, PROPSTAT, XML_CONTENT_TYPE } from '../constants/webdav'\nimport { XML_NS, xmlBuild } from './xml'\n\nexport const XML_DAV_NS = { [`${XML_NS}:${NS_PREFIX}`]: `${NS_DAV}` }\nexport const PROPFIND_COLLECTION = { [`${NS_PREFIX}:collection`]: null }\nexport const PROPFIND_ALL_PROP = {\n [`${NS_PREFIX}:propfind`]: {\n [`${NS_PREFIX}:${PROPSTAT.ALLPROP}`]: null,\n ...XML_DAV_NS\n }\n}\n\nexport const SUPPORTED_LOCKS = {\n [`${NS_PREFIX}:lockentry`]: [\n {\n [`${NS_PREFIX}:lockscope`]: {\n [`${NS_PREFIX}:exclusive`]: null\n },\n [`${NS_PREFIX}:locktype`]: {\n [`${NS_PREFIX}:write`]: null\n }\n },\n {\n [`${NS_PREFIX}:lockscope`]: {\n [`${NS_PREFIX}:shared`]: null\n },\n [`${NS_PREFIX}:locktype`]: {\n [`${NS_PREFIX}:write`]: null\n }\n }\n ]\n}\n\nexport function PROP(prop: any, httpVersion: string, httpStatus: number, description?: string) {\n return {\n [`${NS_PREFIX}:prop`]: prop,\n [`${NS_PREFIX}:status`]: `${httpVersion} ${httpStatus} ${http.STATUS_CODES[httpStatus]}`,\n [`${NS_PREFIX}:responsedescription`]: description ? { [`${NS_PREFIX}:error`]: { [`${NS_PREFIX}:${description}`]: null } } : undefined\n }\n}\n\nexport function PROP_STAT(href: string, props: any) {\n return {\n [`${NS_PREFIX}:href`]: href,\n [`${NS_PREFIX}:propstat`]: props\n }\n}\n\nexport function MULTI_STATUS(content: any) {\n return {\n [`${NS_PREFIX}:multistatus`]: { [`${NS_PREFIX}:response`]: content, ...XML_DAV_NS }\n }\n}\n\nexport function LOCK_DISCOVERY(locks: FileLock[]) {\n // only locktype write is currently implemented in RFC\n const activeLocks = []\n for (const lock of locks) {\n activeLocks.push({\n [`${NS_PREFIX}:activelock`]: {\n [`${NS_PREFIX}:locktype`]: { [`${NS_PREFIX}:write`]: null },\n [`${NS_PREFIX}:lockscope`]: { [`${NS_PREFIX}:${lock.options?.lockScope || LOCK_SCOPE.EXCLUSIVE}`]: null },\n [`${NS_PREFIX}:locktoken`]: { [`${NS_PREFIX}:href`]: lock.options?.lockToken || SERVER_NAME },\n [`${NS_PREFIX}:lockroot`]: { [`${NS_PREFIX}:href`]: encodeUrl(lock.options?.lockRoot || lock.dbFilePath) },\n [`${NS_PREFIX}:owner`]: formatLockOwner(lock),\n [`${NS_PREFIX}:timeout`]: `Second-${Math.floor(lock.expiration - currentTimeStamp())}`,\n [`${NS_PREFIX}:depth`]: lock.depth\n }\n })\n }\n return activeLocks\n}\n\nexport function LOCK_PROP(locks: FileLock[]) {\n return { [`${NS_PREFIX}:prop`]: { [`${NS_PREFIX}:lockdiscovery`]: LOCK_DISCOVERY(locks), ...XML_DAV_NS } }\n}\n\nexport function DAV_ERROR(error: string, href?: string): string {\n return xmlBuild({\n 'ns0:error': { [`ns0:${error}`]: href ? [{ 'ns0:href': encodeUrl(href) }] : '', [`${XML_NS}:ns0`]: `${NS_DAV}` }\n })\n}\n\nexport function DAV_ERROR_RES(code: number, error: string, res: FastifyReply, href?: string): FastifyReply {\n return res.status(code).type(XML_CONTENT_TYPE).send(DAV_ERROR(error, href))\n}\n\nfunction formatLockOwner(lock: FileLock) {\n const lockInfo = `${lock.options.lockInfo ? `${lock.options.lockInfo}` : ''}${lock.app ? ` ${lock.app}` : ''}`\n return `${lock.owner.fullName} (${lock.owner.email})${lockInfo ? ` - ${lockInfo}` : ''}`\n}\n"],"names":["DAV_ERROR","DAV_ERROR_RES","LOCK_DISCOVERY","LOCK_PROP","MULTI_STATUS","PROP","PROPFIND_ALL_PROP","PROPFIND_COLLECTION","PROP_STAT","SUPPORTED_LOCKS","XML_DAV_NS","XML_NS","NS_PREFIX","NS_DAV","PROPSTAT","ALLPROP","prop","httpVersion","httpStatus","description","http","STATUS_CODES","undefined","href","props","content","locks","activeLocks","lock","push","options","lockScope","LOCK_SCOPE","EXCLUSIVE","lockToken","SERVER_NAME","encodeUrl","lockRoot","dbFilePath","formatLockOwner","Math","floor","expiration","currentTimeStamp","depth","error","xmlBuild","code","res","status","type","XML_CONTENT_TYPE","send","lockInfo","app","owner","fullName","email"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QAmFeA;eAAAA;;QAMAC;eAAAA;;QA7BAC;eAAAA;;QAmBAC;eAAAA;;QAzBAC;eAAAA;;QAfAC;eAAAA;;QA5BHC;eAAAA;;QADAC;eAAAA;;QAqCGC;eAAAA;;QA7BHC;eAAAA;;QATAC;eAAAA;;;iEANI;wBACwC;wBAEiB;qBACzC;;;;;;AAE1B,MAAMA,aAAa;IAAE,CAAC,GAAGC,WAAM,CAAC,CAAC,EAAEC,iBAAS,EAAE,CAAC,EAAE,GAAGC,cAAM,EAAE;AAAC;AAC7D,MAAMN,sBAAsB;IAAE,CAAC,GAAGK,iBAAS,CAAC,WAAW,CAAC,CAAC,EAAE;AAAK;AAChE,MAAMN,oBAAoB;IAC/B,CAAC,GAAGM,iBAAS,CAAC,SAAS,CAAC,CAAC,EAAE;QACzB,CAAC,GAAGA,iBAAS,CAAC,CAAC,EAAEE,gBAAQ,CAACC,OAAO,EAAE,CAAC,EAAE;QACtC,GAAGL,UAAU;IACf;AACF;AAEO,MAAMD,kBAAkB;IAC7B,CAAC,GAAGG,iBAAS,CAAC,UAAU,CAAC,CAAC,EAAE;QAC1B;YACE,CAAC,GAAGA,iBAAS,CAAC,UAAU,CAAC,CAAC,EAAE;gBAC1B,CAAC,GAAGA,iBAAS,CAAC,UAAU,CAAC,CAAC,EAAE;YAC9B;YACA,CAAC,GAAGA,iBAAS,CAAC,SAAS,CAAC,CAAC,EAAE;gBACzB,CAAC,GAAGA,iBAAS,CAAC,MAAM,CAAC,CAAC,EAAE;YAC1B;QACF;QACA;YACE,CAAC,GAAGA,iBAAS,CAAC,UAAU,CAAC,CAAC,EAAE;gBAC1B,CAAC,GAAGA,iBAAS,CAAC,OAAO,CAAC,CAAC,EAAE;YAC3B;YACA,CAAC,GAAGA,iBAAS,CAAC,SAAS,CAAC,CAAC,EAAE;gBACzB,CAAC,GAAGA,iBAAS,CAAC,MAAM,CAAC,CAAC,EAAE;YAC1B;QACF;KACD;AACH;AAEO,SAASP,KAAKW,IAAS,EAAEC,WAAmB,EAAEC,UAAkB,EAAEC,WAAoB;IAC3F,OAAO;QACL,CAAC,GAAGP,iBAAS,CAAC,KAAK,CAAC,CAAC,EAAEI;QACvB,CAAC,GAAGJ,iBAAS,CAAC,OAAO,CAAC,CAAC,EAAE,GAAGK,YAAY,CAAC,EAAEC,WAAW,CAAC,EAAEE,iBAAI,CAACC,YAAY,CAACH,WAAW,EAAE;QACxF,CAAC,GAAGN,iBAAS,CAAC,oBAAoB,CAAC,CAAC,EAAEO,cAAc;YAAE,CAAC,GAAGP,iBAAS,CAAC,MAAM,CAAC,CAAC,EAAE;gBAAE,CAAC,GAAGA,iBAAS,CAAC,CAAC,EAAEO,aAAa,CAAC,EAAE;YAAK;QAAE,IAAIG;IAC9H;AACF;AAEO,SAASd,UAAUe,IAAY,EAAEC,KAAU;IAChD,OAAO;QACL,CAAC,GAAGZ,iBAAS,CAAC,KAAK,CAAC,CAAC,EAAEW;QACvB,CAAC,GAAGX,iBAAS,CAAC,SAAS,CAAC,CAAC,EAAEY;IAC7B;AACF;AAEO,SAASpB,aAAaqB,OAAY;IACvC,OAAO;QACL,CAAC,GAAGb,iBAAS,CAAC,YAAY,CAAC,CAAC,EAAE;YAAE,CAAC,GAAGA,iBAAS,CAAC,SAAS,CAAC,CAAC,EAAEa;YAAS,GAAGf,UAAU;QAAC;IACpF;AACF;AAEO,SAASR,eAAewB,KAAiB;IAC9C,sDAAsD;IACtD,MAAMC,cAAc,EAAE;IACtB,KAAK,MAAMC,QAAQF,MAAO;QACxBC,YAAYE,IAAI,CAAC;YACf,CAAC,GAAGjB,iBAAS,CAAC,WAAW,CAAC,CAAC,EAAE;gBAC3B,CAAC,GAAGA,iBAAS,CAAC,SAAS,CAAC,CAAC,EAAE;oBAAE,CAAC,GAAGA,iBAAS,CAAC,MAAM,CAAC,CAAC,EAAE;gBAAK;gBAC1D,CAAC,GAAGA,iBAAS,CAAC,UAAU,CAAC,CAAC,EAAE;oBAAE,CAAC,GAAGA,iBAAS,CAAC,CAAC,EAAEgB,KAAKE,OAAO,EAAEC,aAAaC,kBAAU,CAACC,SAAS,EAAE,CAAC,EAAE;gBAAK;gBACxG,CAAC,GAAGrB,iBAAS,CAAC,UAAU,CAAC,CAAC,EAAE;oBAAE,CAAC,GAAGA,iBAAS,CAAC,KAAK,CAAC,CAAC,EAAEgB,KAAKE,OAAO,EAAEI,aAAaC,mBAAW;gBAAC;gBAC5F,CAAC,GAAGvB,iBAAS,CAAC,SAAS,CAAC,CAAC,EAAE;oBAAE,CAAC,GAAGA,iBAAS,CAAC,KAAK,CAAC,CAAC,EAAEwB,IAAAA,iBAAS,EAACR,KAAKE,OAAO,EAAEO,YAAYT,KAAKU,UAAU;gBAAE;gBACzG,CAAC,GAAG1B,iBAAS,CAAC,MAAM,CAAC,CAAC,EAAE2B,gBAAgBX;gBACxC,CAAC,GAAGhB,iBAAS,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE4B,KAAKC,KAAK,CAACb,KAAKc,UAAU,GAAGC,IAAAA,wBAAgB,MAAK;gBACtF,CAAC,GAAG/B,iBAAS,CAAC,MAAM,CAAC,CAAC,EAAEgB,KAAKgB,KAAK;YACpC;QACF;IACF;IACA,OAAOjB;AACT;AAEO,SAASxB,UAAUuB,KAAiB;IACzC,OAAO;QAAE,CAAC,GAAGd,iBAAS,CAAC,KAAK,CAAC,CAAC,EAAE;YAAE,CAAC,GAAGA,iBAAS,CAAC,cAAc,CAAC,CAAC,EAAEV,eAAewB;YAAQ,GAAGhB,UAAU;QAAC;IAAE;AAC3G;AAEO,SAASV,UAAU6C,KAAa,EAAEtB,IAAa;IACpD,OAAOuB,IAAAA,aAAQ,EAAC;QACd,aAAa;YAAE,CAAC,CAAC,IAAI,EAAED,OAAO,CAAC,EAAEtB,OAAO;gBAAC;oBAAE,YAAYa,IAAAA,iBAAS,EAACb;gBAAM;aAAE,GAAG;YAAI,CAAC,GAAGZ,WAAM,CAAC,IAAI,CAAC,CAAC,EAAE,GAAGE,cAAM,EAAE;QAAC;IACjH;AACF;AAEO,SAASZ,cAAc8C,IAAY,EAAEF,KAAa,EAAEG,GAAiB,EAAEzB,IAAa;IACzF,OAAOyB,IAAIC,MAAM,CAACF,MAAMG,IAAI,CAACC,wBAAgB,EAAEC,IAAI,CAACpD,UAAU6C,OAAOtB;AACvE;AAEA,SAASgB,gBAAgBX,IAAc;IACrC,MAAMyB,WAAW,GAAGzB,KAAKE,OAAO,CAACuB,QAAQ,GAAG,GAAGzB,KAAKE,OAAO,CAACuB,QAAQ,EAAE,GAAG,KAAKzB,KAAK0B,GAAG,GAAG,CAAC,CAAC,EAAE1B,KAAK0B,GAAG,EAAE,GAAG,IAAI;IAC9G,OAAO,GAAG1B,KAAK2B,KAAK,CAACC,QAAQ,CAAC,EAAE,EAAE5B,KAAK2B,KAAK,CAACE,KAAK,CAAC,CAAC,EAAEJ,WAAW,CAAC,GAAG,EAAEA,UAAU,GAAG,IAAI;AAC1F"}
@@ -37,28 +37,28 @@ function _ts_param(paramIndex, decorator) {
37
37
  }
38
38
  let WebDAVController = class WebDAVController {
39
39
  serverOptions() {
40
- // OPTIONS method is handled in the `DavProtocolGuard`, return empty response with headers
40
+ // OPTIONS method is handled in the `WebDAVProtocolGuard`, return empty response with headers
41
41
  return;
42
42
  }
43
43
  serverPropFind(req, res) {
44
44
  return this.webdavMethods.propfind(req, res, _routes.WEBDAV_NS.SERVER);
45
45
  }
46
46
  webdavOptions() {
47
- // OPTIONS method is handled in the `DavProtocolGuard`, return empty response with headers
47
+ // OPTIONS method is handled in the `WebDAVProtocolGuard`, return empty response with headers
48
48
  return;
49
49
  }
50
50
  async webdavPropfind(req, res) {
51
51
  return this.webdavMethods.propfind(req, res, _routes.WEBDAV_NS.WEBDAV);
52
52
  }
53
53
  repositoriesOptions() {
54
- // OPTIONS method is handled in the `DavProtocolGuard`
54
+ // OPTIONS method is handled in the `WebDAVProtocolGuard`
55
55
  return;
56
56
  }
57
57
  async repositoriesPropfind(req, res, repository) {
58
58
  return this.webdavMethods.propfind(req, res, repository);
59
59
  }
60
60
  async files(req, res) {
61
- // OPTIONS method is handled in the `DavProtocolGuard`
61
+ // OPTIONS method is handled in the `WebDAVProtocolGuard`
62
62
  switch(req.method){
63
63
  case _applicationsconstants.HTTP_METHOD.PROPFIND:
64
64
  return this.webdavMethods.propfind(req, res, _spaces.SPACE_REPOSITORY.FILES);
@@ -105,7 +105,7 @@ _ts_decorate([
105
105
  typeof _webdavinterface.FastifyDAVRequest === "undefined" ? Object : _webdavinterface.FastifyDAVRequest,
106
106
  typeof _fastify.FastifyReply === "undefined" ? Object : _fastify.FastifyReply
107
107
  ]),
108
- _ts_metadata("design:returntype", void 0)
108
+ _ts_metadata("design:returntype", typeof Promise === "undefined" ? Object : Promise)
109
109
  ], WebDAVController.prototype, "serverPropFind", null);
110
110
  _ts_decorate([
111
111
  (0, _common.Options)(_routes.WEBDAV_BASE_PATH),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../backend/src/applications/webdav/webdav.controller.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 { All, Controller, HttpStatus, Options, Param, Propfind, Req, Res, UseGuards } from '@nestjs/common'\nimport { FastifyReply } from 'fastify'\nimport { HTTP_METHOD } from '../applications.constants'\nimport { SPACE_REPOSITORY } from '../spaces/constants/spaces'\nimport { SpaceGuard } from '../spaces/guards/space.guard'\nimport { WEBDAV_BASE_PATH, WEBDAV_NS } from './constants/routes'\nimport { WebDAVEnvironment } from './decorators/webdav-context.decorator'\nimport { FastifyDAVRequest } from './interfaces/webdav.interface'\nimport { WebDAVMethods } from './services/webdav-methods.service'\n\n@Controller()\n@WebDAVEnvironment()\nexport class WebDAVController {\n constructor(private readonly webdavMethods: WebDAVMethods) {}\n\n @Options()\n serverOptions() {\n // OPTIONS method is handled in the `DavProtocolGuard`, return empty response with headers\n return\n }\n\n @Propfind()\n serverPropFind(@Req() req: FastifyDAVRequest, @Res({ passthrough: true }) res: FastifyReply) {\n return this.webdavMethods.propfind(req, res, WEBDAV_NS.SERVER)\n }\n\n @Options(WEBDAV_BASE_PATH)\n webdavOptions() {\n // OPTIONS method is handled in the `DavProtocolGuard`, return empty response with headers\n return\n }\n\n @Propfind(WEBDAV_BASE_PATH)\n async webdavPropfind(@Req() req: FastifyDAVRequest, @Res({ passthrough: true }) res: FastifyReply) {\n return this.webdavMethods.propfind(req, res, WEBDAV_NS.WEBDAV)\n }\n\n @Options(`${WEBDAV_BASE_PATH}/:repository(^(${WEBDAV_NS.SPACES}|${WEBDAV_NS.TRASH})$)`)\n repositoriesOptions() {\n // OPTIONS method is handled in the `DavProtocolGuard`\n return\n }\n\n @Propfind(`${WEBDAV_BASE_PATH}/:repository(^(${WEBDAV_NS.SPACES}|${WEBDAV_NS.TRASH})$)`)\n async repositoriesPropfind(@Req() req: FastifyDAVRequest, @Res({ passthrough: true }) res: FastifyReply, @Param('repository') repository: string) {\n return this.webdavMethods.propfind(req, res, repository)\n }\n\n @All(`${WEBDAV_BASE_PATH}/*`)\n @UseGuards(SpaceGuard)\n async files(@Req() req: FastifyDAVRequest, @Res({ passthrough: true }) res: FastifyReply) {\n // OPTIONS method is handled in the `DavProtocolGuard`\n switch (req.method) {\n case HTTP_METHOD.PROPFIND:\n return this.webdavMethods.propfind(req, res, SPACE_REPOSITORY.FILES)\n case HTTP_METHOD.HEAD:\n case HTTP_METHOD.GET:\n return this.webdavMethods.headOrGet(req, res, SPACE_REPOSITORY.FILES)\n case HTTP_METHOD.PUT:\n return this.webdavMethods.put(req, res)\n case HTTP_METHOD.DELETE:\n return this.webdavMethods.delete(req, res)\n case HTTP_METHOD.LOCK:\n return this.webdavMethods.lock(req, res)\n case HTTP_METHOD.UNLOCK:\n return this.webdavMethods.unlock(req, res)\n case HTTP_METHOD.PROPPATCH:\n return this.webdavMethods.proppatch(req, res)\n case HTTP_METHOD.MKCOL:\n return this.webdavMethods.mkcol(req, res)\n case HTTP_METHOD.COPY:\n case HTTP_METHOD.MOVE:\n return this.webdavMethods.copyMove(req, res)\n default:\n return res.status(HttpStatus.METHOD_NOT_ALLOWED).send()\n }\n }\n}\n"],"names":["WebDAVController","serverOptions","serverPropFind","req","res","webdavMethods","propfind","WEBDAV_NS","SERVER","webdavOptions","webdavPropfind","WEBDAV","repositoriesOptions","repositoriesPropfind","repository","files","method","HTTP_METHOD","PROPFIND","SPACE_REPOSITORY","FILES","HEAD","GET","headOrGet","PUT","put","DELETE","delete","LOCK","lock","UNLOCK","unlock","PROPPATCH","proppatch","MKCOL","mkcol","COPY","MOVE","copyMove","status","HttpStatus","METHOD_NOT_ALLOWED","send","passthrough","WEBDAV_BASE_PATH","SPACES","TRASH"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../backend/src/applications/webdav/webdav.controller.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 { All, Controller, HttpStatus, Options, Param, Propfind, Req, Res, StreamableFile, UseGuards } from '@nestjs/common'\nimport { FastifyReply } from 'fastify'\nimport { HTTP_METHOD } from '../applications.constants'\nimport { SPACE_REPOSITORY } from '../spaces/constants/spaces'\nimport { SpaceGuard } from '../spaces/guards/space.guard'\nimport { WEBDAV_BASE_PATH, WEBDAV_NS } from './constants/routes'\nimport { WebDAVEnvironment } from './decorators/webdav-context.decorator'\nimport { FastifyDAVRequest } from './interfaces/webdav.interface'\nimport { WebDAVMethods } from './services/webdav-methods.service'\n\n@Controller()\n@WebDAVEnvironment()\nexport class WebDAVController {\n constructor(private readonly webdavMethods: WebDAVMethods) {}\n\n @Options()\n serverOptions(): void {\n // OPTIONS method is handled in the `WebDAVProtocolGuard`, return empty response with headers\n return\n }\n\n @Propfind()\n serverPropFind(@Req() req: FastifyDAVRequest, @Res({ passthrough: true }) res: FastifyReply): Promise<string> {\n return this.webdavMethods.propfind(req, res, WEBDAV_NS.SERVER)\n }\n\n @Options(WEBDAV_BASE_PATH)\n webdavOptions(): void {\n // OPTIONS method is handled in the `WebDAVProtocolGuard`, return empty response with headers\n return\n }\n\n @Propfind(WEBDAV_BASE_PATH)\n async webdavPropfind(@Req() req: FastifyDAVRequest, @Res({ passthrough: true }) res: FastifyReply): Promise<string> {\n return this.webdavMethods.propfind(req, res, WEBDAV_NS.WEBDAV)\n }\n\n @Options(`${WEBDAV_BASE_PATH}/:repository(^(${WEBDAV_NS.SPACES}|${WEBDAV_NS.TRASH})$)`)\n repositoriesOptions(): void {\n // OPTIONS method is handled in the `WebDAVProtocolGuard`\n return\n }\n\n @Propfind(`${WEBDAV_BASE_PATH}/:repository(^(${WEBDAV_NS.SPACES}|${WEBDAV_NS.TRASH})$)`)\n async repositoriesPropfind(\n @Req() req: FastifyDAVRequest,\n @Res({ passthrough: true }) res: FastifyReply,\n @Param('repository') repository: string\n ): Promise<string> {\n return this.webdavMethods.propfind(req, res, repository)\n }\n\n @All(`${WEBDAV_BASE_PATH}/*`)\n @UseGuards(SpaceGuard)\n async files(@Req() req: FastifyDAVRequest, @Res({ passthrough: true }) res: FastifyReply): Promise<string | StreamableFile> {\n // OPTIONS method is handled in the `WebDAVProtocolGuard`\n switch (req.method) {\n case HTTP_METHOD.PROPFIND:\n return this.webdavMethods.propfind(req, res, SPACE_REPOSITORY.FILES)\n case HTTP_METHOD.HEAD:\n case HTTP_METHOD.GET:\n return this.webdavMethods.headOrGet(req, res, SPACE_REPOSITORY.FILES)\n case HTTP_METHOD.PUT:\n return this.webdavMethods.put(req, res)\n case HTTP_METHOD.DELETE:\n return this.webdavMethods.delete(req, res)\n case HTTP_METHOD.LOCK:\n return this.webdavMethods.lock(req, res)\n case HTTP_METHOD.UNLOCK:\n return this.webdavMethods.unlock(req, res)\n case HTTP_METHOD.PROPPATCH:\n return this.webdavMethods.proppatch(req, res)\n case HTTP_METHOD.MKCOL:\n return this.webdavMethods.mkcol(req, res)\n case HTTP_METHOD.COPY:\n case HTTP_METHOD.MOVE:\n return this.webdavMethods.copyMove(req, res)\n default:\n return res.status(HttpStatus.METHOD_NOT_ALLOWED).send()\n }\n }\n}\n"],"names":["WebDAVController","serverOptions","serverPropFind","req","res","webdavMethods","propfind","WEBDAV_NS","SERVER","webdavOptions","webdavPropfind","WEBDAV","repositoriesOptions","repositoriesPropfind","repository","files","method","HTTP_METHOD","PROPFIND","SPACE_REPOSITORY","FILES","HEAD","GET","headOrGet","PUT","put","DELETE","delete","LOCK","lock","UNLOCK","unlock","PROPPATCH","proppatch","MKCOL","mkcol","COPY","MOVE","copyMove","status","HttpStatus","METHOD_NOT_ALLOWED","send","passthrough","WEBDAV_BASE_PATH","SPACES","TRASH"],"mappings":"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"}
@@ -7,7 +7,6 @@ Object.defineProperty(exports, "__esModule", {
7
7
  value: true
8
8
  });
9
9
  const _appbootstrap = require("../../app.bootstrap");
10
- const _utils = require("../../infrastructure/database/utils");
11
10
  const _webdav = require("./constants/webdav");
12
11
  const XML_VERSION_STR = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>';
13
12
  describe('WebDAV (e2e)', ()=>{
@@ -18,7 +17,6 @@ describe('WebDAV (e2e)', ()=>{
18
17
  await app.getHttpAdapter().getInstance().ready();
19
18
  });
20
19
  afterAll(async ()=>{
21
- await (0, _utils.dbCloseConnection)(app);
22
20
  await app.close();
23
21
  });
24
22
  it('should be defined', ()=>{
@@ -64,6 +62,137 @@ describe('WebDAV (e2e)', ()=>{
64
62
  });
65
63
  expect(res.statusCode).toEqual(207);
66
64
  });
65
+ describe('PUT with non-XML Content-Types (stream preservation)', ()=>{
66
+ const testFilePath = '/webdav/personal/test-content-type.txt';
67
+ const auth = 'Basic am86cGFzc3dvcmQ=';
68
+ afterEach(async ()=>{
69
+ // Cleanup: delete the test file if it exists
70
+ await app.inject({
71
+ method: 'DELETE',
72
+ url: testFilePath,
73
+ headers: {
74
+ authorization: auth
75
+ }
76
+ });
77
+ });
78
+ it('PUT with application/json should preserve stream and create file with content', async ()=>{
79
+ const jsonContent = '{"key":"value","number":42}';
80
+ const putRes = await app.inject({
81
+ method: 'PUT',
82
+ url: testFilePath,
83
+ headers: {
84
+ authorization: auth,
85
+ 'content-type': 'application/json'
86
+ },
87
+ body: jsonContent
88
+ });
89
+ expect([
90
+ 201,
91
+ 204
92
+ ]).toContain(putRes.statusCode);
93
+ // Verify the file was created with the correct content
94
+ const getRes = await app.inject({
95
+ method: 'GET',
96
+ url: testFilePath,
97
+ headers: {
98
+ authorization: auth
99
+ }
100
+ });
101
+ expect(getRes.statusCode).toEqual(200);
102
+ expect(getRes.body).toEqual(jsonContent);
103
+ expect(getRes.headers['content-length']).toEqual(String(jsonContent.length));
104
+ });
105
+ it('PUT with text/plain should preserve stream and create file with content', async ()=>{
106
+ const textContent = 'This is plain text content with special chars: éàù';
107
+ const putRes = await app.inject({
108
+ method: 'PUT',
109
+ url: testFilePath,
110
+ headers: {
111
+ authorization: auth,
112
+ 'content-type': 'text/plain'
113
+ },
114
+ body: textContent
115
+ });
116
+ expect([
117
+ 201,
118
+ 204
119
+ ]).toContain(putRes.statusCode);
120
+ // Verify the file was created with the correct content
121
+ const getRes = await app.inject({
122
+ method: 'GET',
123
+ url: testFilePath,
124
+ headers: {
125
+ authorization: auth
126
+ }
127
+ });
128
+ expect(getRes.statusCode).toEqual(200);
129
+ expect(getRes.body).toEqual(textContent);
130
+ expect(getRes.headers['content-length']).toEqual(String(Buffer.byteLength(textContent, 'utf8')));
131
+ });
132
+ it('PUT with text/plain; charset=utf-8 should preserve stream and create file with content', async ()=>{
133
+ const textContent = 'Text with charset and emoji: 🚀 ✅';
134
+ const putRes = await app.inject({
135
+ method: 'PUT',
136
+ url: testFilePath,
137
+ headers: {
138
+ authorization: auth,
139
+ 'content-type': 'text/plain; charset=utf-8'
140
+ },
141
+ body: textContent
142
+ });
143
+ expect([
144
+ 201,
145
+ 204
146
+ ]).toContain(putRes.statusCode);
147
+ // Verify the file was created with the correct content
148
+ const getRes = await app.inject({
149
+ method: 'GET',
150
+ url: testFilePath,
151
+ headers: {
152
+ authorization: auth
153
+ }
154
+ });
155
+ expect(getRes.statusCode).toEqual(200);
156
+ expect(getRes.body).toEqual(textContent);
157
+ expect(getRes.headers['content-length']).toEqual(String(Buffer.byteLength(textContent, 'utf8')));
158
+ });
159
+ it('PUT with application/octet-stream should work as expected', async ()=>{
160
+ const binaryContent = Buffer.from([
161
+ 0x89,
162
+ 0x50,
163
+ 0x4e,
164
+ 0x47,
165
+ 0x0d,
166
+ 0x0a,
167
+ 0x1a,
168
+ 0x0a
169
+ ]);
170
+ const putRes = await app.inject({
171
+ method: 'PUT',
172
+ url: testFilePath,
173
+ headers: {
174
+ authorization: auth,
175
+ 'content-type': 'application/octet-stream'
176
+ },
177
+ body: binaryContent
178
+ });
179
+ expect([
180
+ 201,
181
+ 204
182
+ ]).toContain(putRes.statusCode);
183
+ // Verify the file was created with the correct content
184
+ const getRes = await app.inject({
185
+ method: 'GET',
186
+ url: testFilePath,
187
+ headers: {
188
+ authorization: auth
189
+ }
190
+ });
191
+ expect(getRes.statusCode).toEqual(200);
192
+ expect(Buffer.from(getRes.rawPayload)).toEqual(binaryContent);
193
+ expect(getRes.headers['content-length']).toEqual(String(binaryContent.length));
194
+ });
195
+ });
67
196
  });
68
197
 
69
198
  //# sourceMappingURL=webdav.e2e-spec.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../backend/src/applications/webdav/webdav.e2e-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 { NestFastifyApplication } from '@nestjs/platform-fastify'\nimport { appBootstrap } from '../../app.bootstrap'\nimport { dbCloseConnection } from '../../infrastructure/database/utils'\nimport { XML_CONTENT_TYPE } from './constants/webdav'\n\nconst XML_VERSION_STR = '<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>'\n\ndescribe('WebDAV (e2e)', () => {\n let app: NestFastifyApplication\n\n beforeAll(async () => {\n app = await appBootstrap()\n await app.init()\n await app.getHttpAdapter().getInstance().ready()\n })\n\n afterAll(async () => {\n await dbCloseConnection(app)\n await app.close()\n })\n\n it('should be defined', () => {\n expect(app).toBeDefined()\n })\n\n it('PROPFIND ALLPROP /webdav => 207', async () => {\n const res = await app.inject({\n method: 'PROPFIND',\n url: '/webdav',\n headers: { authorization: 'Basic am86cGFzc3dvcmQ=', 'content-type': XML_CONTENT_TYPE, Depth: '1' },\n body: `${XML_VERSION_STR}\n <propfind xmlns:D=\"DAV:\">\n <allprop/>\n </propfind>`\n } as any)\n expect(res.statusCode).toEqual(207)\n })\n\n it('PROPFIND PROP /webdav => 207', async () => {\n const res = await app.inject({\n method: 'PROPFIND',\n url: '/webdav',\n headers: { authorization: 'Basic am86cGFzc3dvcmQ=', 'content-type': XML_CONTENT_TYPE, Depth: '1' },\n body: `${XML_VERSION_STR}\n <D:propfind xmlns:D=\"DAV:\">\n <D:prop>\n <D:creationdate/>\n <D:displayname/>\n <D:getcontentlength/>\n <D:getcontenttype/>\n <D:getetag/>\n <D:getlastmodified/>\n <D:resourcetype/>\n </D:prop>\n </D:propfind>`\n } as any)\n expect(res.statusCode).toEqual(207)\n })\n})\n"],"names":["XML_VERSION_STR","describe","app","beforeAll","appBootstrap","init","getHttpAdapter","getInstance","ready","afterAll","dbCloseConnection","close","it","expect","toBeDefined","res","inject","method","url","headers","authorization","XML_CONTENT_TYPE","Depth","body","statusCode","toEqual"],"mappings":"AAAA;;;;CAIC;;;;8BAG4B;uBACK;wBACD;AAEjC,MAAMA,kBAAkB;AAExBC,SAAS,gBAAgB;IACvB,IAAIC;IAEJC,UAAU;QACRD,MAAM,MAAME,IAAAA,0BAAY;QACxB,MAAMF,IAAIG,IAAI;QACd,MAAMH,IAAII,cAAc,GAAGC,WAAW,GAAGC,KAAK;IAChD;IAEAC,SAAS;QACP,MAAMC,IAAAA,wBAAiB,EAACR;QACxB,MAAMA,IAAIS,KAAK;IACjB;IAEAC,GAAG,qBAAqB;QACtBC,OAAOX,KAAKY,WAAW;IACzB;IAEAF,GAAG,mCAAmC;QACpC,MAAMG,MAAM,MAAMb,IAAIc,MAAM,CAAC;YAC3BC,QAAQ;YACRC,KAAK;YACLC,SAAS;gBAAEC,eAAe;gBAA0B,gBAAgBC,wBAAgB;gBAAEC,OAAO;YAAI;YACjGC,MAAM,GAAGvB,gBAAgB;;;kBAGb,CAAC;QACf;QACAa,OAAOE,IAAIS,UAAU,EAAEC,OAAO,CAAC;IACjC;IAEAb,GAAG,gCAAgC;QACjC,MAAMG,MAAM,MAAMb,IAAIc,MAAM,CAAC;YAC3BC,QAAQ;YACRC,KAAK;YACLC,SAAS;gBAAEC,eAAe;gBAA0B,gBAAgBC,wBAAgB;gBAAEC,OAAO;YAAI;YACjGC,MAAM,GAAGvB,gBAAgB;;;;;;;;;;;oBAWX,CAAC;QACjB;QACAa,OAAOE,IAAIS,UAAU,EAAEC,OAAO,CAAC;IACjC;AACF"}
1
+ {"version":3,"sources":["../../../../backend/src/applications/webdav/webdav.e2e-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 { NestFastifyApplication } from '@nestjs/platform-fastify'\nimport { appBootstrap } from '../../app.bootstrap'\nimport { XML_CONTENT_TYPE } from './constants/webdav'\n\nconst XML_VERSION_STR = '<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>'\n\ndescribe('WebDAV (e2e)', () => {\n let app: NestFastifyApplication\n\n beforeAll(async () => {\n app = await appBootstrap()\n await app.init()\n await app.getHttpAdapter().getInstance().ready()\n })\n\n afterAll(async () => {\n await app.close()\n })\n\n it('should be defined', () => {\n expect(app).toBeDefined()\n })\n\n it('PROPFIND ALLPROP /webdav => 207', async () => {\n const res = await app.inject({\n method: 'PROPFIND',\n url: '/webdav',\n headers: { authorization: 'Basic am86cGFzc3dvcmQ=', 'content-type': XML_CONTENT_TYPE, Depth: '1' },\n body: `${XML_VERSION_STR}\n <propfind xmlns:D=\"DAV:\">\n <allprop/>\n </propfind>`\n } as any)\n expect(res.statusCode).toEqual(207)\n })\n\n it('PROPFIND PROP /webdav => 207', async () => {\n const res = await app.inject({\n method: 'PROPFIND',\n url: '/webdav',\n headers: { authorization: 'Basic am86cGFzc3dvcmQ=', 'content-type': XML_CONTENT_TYPE, Depth: '1' },\n body: `${XML_VERSION_STR}\n <D:propfind xmlns:D=\"DAV:\">\n <D:prop>\n <D:creationdate/>\n <D:displayname/>\n <D:getcontentlength/>\n <D:getcontenttype/>\n <D:getetag/>\n <D:getlastmodified/>\n <D:resourcetype/>\n </D:prop>\n </D:propfind>`\n } as any)\n expect(res.statusCode).toEqual(207)\n })\n\n describe('PUT with non-XML Content-Types (stream preservation)', () => {\n const testFilePath = '/webdav/personal/test-content-type.txt'\n const auth = 'Basic am86cGFzc3dvcmQ='\n\n afterEach(async () => {\n // Cleanup: delete the test file if it exists\n await app.inject({\n method: 'DELETE',\n url: testFilePath,\n headers: { authorization: auth }\n } as any)\n })\n\n it('PUT with application/json should preserve stream and create file with content', async () => {\n const jsonContent = '{\"key\":\"value\",\"number\":42}'\n\n const putRes = await app.inject({\n method: 'PUT',\n url: testFilePath,\n headers: {\n authorization: auth,\n 'content-type': 'application/json'\n },\n body: jsonContent\n } as any)\n\n expect([201, 204]).toContain(putRes.statusCode)\n\n // Verify the file was created with the correct content\n const getRes = await app.inject({\n method: 'GET',\n url: testFilePath,\n headers: { authorization: auth }\n } as any)\n\n expect(getRes.statusCode).toEqual(200)\n expect(getRes.body).toEqual(jsonContent)\n expect(getRes.headers['content-length']).toEqual(String(jsonContent.length))\n })\n\n it('PUT with text/plain should preserve stream and create file with content', async () => {\n const textContent = 'This is plain text content with special chars: éàù'\n\n const putRes = await app.inject({\n method: 'PUT',\n url: testFilePath,\n headers: {\n authorization: auth,\n 'content-type': 'text/plain'\n },\n body: textContent\n } as any)\n\n expect([201, 204]).toContain(putRes.statusCode)\n\n // Verify the file was created with the correct content\n const getRes = await app.inject({\n method: 'GET',\n url: testFilePath,\n headers: { authorization: auth }\n } as any)\n\n expect(getRes.statusCode).toEqual(200)\n expect(getRes.body).toEqual(textContent)\n expect(getRes.headers['content-length']).toEqual(String(Buffer.byteLength(textContent, 'utf8')))\n })\n\n it('PUT with text/plain; charset=utf-8 should preserve stream and create file with content', async () => {\n const textContent = 'Text with charset and emoji: 🚀 ✅'\n\n const putRes = await app.inject({\n method: 'PUT',\n url: testFilePath,\n headers: {\n authorization: auth,\n 'content-type': 'text/plain; charset=utf-8'\n },\n body: textContent\n } as any)\n\n expect([201, 204]).toContain(putRes.statusCode)\n\n // Verify the file was created with the correct content\n const getRes = await app.inject({\n method: 'GET',\n url: testFilePath,\n headers: { authorization: auth }\n } as any)\n\n expect(getRes.statusCode).toEqual(200)\n expect(getRes.body).toEqual(textContent)\n expect(getRes.headers['content-length']).toEqual(String(Buffer.byteLength(textContent, 'utf8')))\n })\n\n it('PUT with application/octet-stream should work as expected', async () => {\n const binaryContent = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])\n\n const putRes = await app.inject({\n method: 'PUT',\n url: testFilePath,\n headers: {\n authorization: auth,\n 'content-type': 'application/octet-stream'\n },\n body: binaryContent\n } as any)\n\n expect([201, 204]).toContain(putRes.statusCode)\n\n // Verify the file was created with the correct content\n const getRes = await app.inject({\n method: 'GET',\n url: testFilePath,\n headers: { authorization: auth }\n } as any)\n\n expect(getRes.statusCode).toEqual(200)\n expect(Buffer.from(getRes.rawPayload)).toEqual(binaryContent)\n expect(getRes.headers['content-length']).toEqual(String(binaryContent.length))\n })\n })\n})\n"],"names":["XML_VERSION_STR","describe","app","beforeAll","appBootstrap","init","getHttpAdapter","getInstance","ready","afterAll","close","it","expect","toBeDefined","res","inject","method","url","headers","authorization","XML_CONTENT_TYPE","Depth","body","statusCode","toEqual","testFilePath","auth","afterEach","jsonContent","putRes","toContain","getRes","String","length","textContent","Buffer","byteLength","binaryContent","from","rawPayload"],"mappings":"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"}
@@ -42,7 +42,6 @@ describe('Auth (e2e)', ()=>{
42
42
  deleteSpace: true,
43
43
  isGuest: false
44
44
  })).resolves.not.toThrow();
45
- await (0, _utils.dbCloseConnection)(app);
46
45
  await app.close();
47
46
  });
48
47
  it('should be defined', ()=>{
@@ -149,9 +148,8 @@ describe('Auth (e2e)', ()=>{
149
148
  body: null
150
149
  });
151
150
  expect(res.statusCode).toEqual(201);
152
- expect(res.headers['set-cookie']).toHaveLength(4);
153
- const cookies = getCookies(res.headers['set-cookie']);
154
- /* Access cookie
151
+ expect(res.headers['set-cookie']).toHaveLength(5);
152
+ /* Access cookie
155
153
  [
156
154
  'sync-in-access=',
157
155
  'Max-Age=0',
@@ -187,12 +185,20 @@ describe('Auth (e2e)', ()=>{
187
185
  'Max-Age=0',
188
186
  'Path=/api/auth/refresh',
189
187
  'Expires=Thu, 01 Jan 1970 00:00:00 GMT',
188
+ 'Secure',
189
+ 'SameSite=Strict'
190
+ ]
191
+ */ /* Access cookie 2FA
192
+ [
193
+ 'sync-in-access=',
194
+ 'Max-Age=0',
195
+ 'Path=/api/auth/2fa/login/verify',
196
+ 'Expires=Thu, 01 Jan 1970 00:00:00 GMT',
190
197
  'HttpOnly',
191
198
  'Secure',
192
199
  'SameSite=Strict'
193
200
  ]
194
- */ cookiesChecks(cookies, true);
195
- });
201
+ */ });
196
202
  it(`POST ${_routes.API_AUTH_REFRESH} => 201`, async ()=>{
197
203
  const res = await app.inject({
198
204
  method: 'POST',
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../backend/src/authentication/auth.e2e-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 { ConfigService } from '@nestjs/config'\nimport { JwtService } from '@nestjs/jwt'\nimport { NestFastifyApplication } from '@nestjs/platform-fastify'\nimport { appBootstrap } from '../app.bootstrap'\nimport { USER_ROLE } from '../applications/users/constants/user'\nimport { DeleteUserDto } from '../applications/users/dto/delete-user.dto'\nimport { UserModel } from '../applications/users/models/user.model'\nimport { AdminUsersManager } from '../applications/users/services/admin-users-manager.service'\nimport { generateUserTest } from '../applications/users/utils/test'\nimport { convertHumanTimeToSeconds, transformAndValidate } from '../common/functions'\nimport { currentTimeStamp, decodeUrl } from '../common/shared'\nimport { dbCheckConnection, dbCloseConnection } from '../infrastructure/database/utils'\nimport { AuthConfig } from './auth.config'\nimport { CSRF_ERROR, TOKEN_PATHS, TOKEN_TYPES } from './constants/auth'\nimport { API_AUTH_LOGIN, API_AUTH_LOGOUT, API_AUTH_REFRESH, API_AUTH_TOKEN, API_AUTH_TOKEN_REFRESH } from './constants/routes'\nimport { TokenResponseDto } from './dto/token-response.dto'\nimport { JwtPayload } from './interfaces/jwt-payload.interface'\nimport { TOKEN_TYPE } from './interfaces/token.interface'\n\ndescribe('Auth (e2e)', () => {\n let app: NestFastifyApplication\n let authConfig: AuthConfig\n let jwtService: JwtService\n let adminUsersManager: AdminUsersManager\n let userTest: UserModel\n let refreshToken: string\n let csrfToken: string\n\n beforeAll(async () => {\n app = await appBootstrap()\n await app.init()\n await app.getHttpAdapter().getInstance().ready()\n authConfig = app.get<ConfigService>(ConfigService).get<AuthConfig>('auth')\n jwtService = app.get<JwtService>(JwtService)\n adminUsersManager = app.get<AdminUsersManager>(AdminUsersManager)\n userTest = new UserModel(generateUserTest(false), false)\n })\n\n afterAll(async () => {\n await expect(\n adminUsersManager.deleteUserOrGuest(userTest.id, userTest.login, { deleteSpace: true, isGuest: false } satisfies DeleteUserDto)\n ).resolves.not.toThrow()\n await dbCloseConnection(app)\n await app.close()\n })\n\n it('should be defined', () => {\n expect(authConfig).toBeDefined()\n expect(jwtService).toBeDefined()\n expect(adminUsersManager).toBeDefined()\n expect(userTest).toBeDefined()\n })\n\n it('should get the database connection', async () => {\n expect(await dbCheckConnection(app)).toBe(true)\n })\n\n it(`POST ${API_AUTH_LOGIN} => 401`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_LOGIN,\n body: { login: userTest.login, password: userTest.password }\n })\n expect(res.statusCode).toEqual(401)\n })\n\n it(`POST ${API_AUTH_LOGIN} => 201`, async () => {\n const userId = (await adminUsersManager.createUserOrGuest({ ...userTest }, USER_ROLE.USER)).id\n expect(userId).toBeDefined()\n userTest.id = userId\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_LOGIN,\n body: { login: userTest.login, password: userTest.password }\n })\n expect(res.statusCode).toEqual(201)\n expect(Object.keys(res.json())).toEqual(expect.arrayContaining(['user', 'token']))\n expect(res.headers['set-cookie']).toHaveLength(4)\n const cookies: { type: TOKEN_TYPE; content: string[] }[] = getCookies(res.headers['set-cookie'] as string[])\n /* Access cookie\n [\n 'sync-in-access=value,\n 'Max-Age=3600',\n 'Path=/',\n 'HttpOnly',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n /* Refresh cookie\n [\n 'sync-in-refresh=value,\n 'Max-Age=14400',\n 'Path=/api/auth/refresh',\n 'HttpOnly',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n /* WS cookie\n [\n 'sync-in-ws=value,\n 'Max-Age=14400',\n 'Path=/socket.io',\n 'HttpOnly',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n /* CSRF cookie\n [\n 'sync-in-csrf=value,\n 'Max-Age=14400',\n 'Path=/',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n cookiesChecks(cookies)\n // Verify token\n for (const cookie of cookies) {\n const token = cookie.content[0].substring(cookie.content[0].indexOf('=') + 1)\n if (cookie.type === TOKEN_TYPE.CSRF) {\n // needed for the following tests\n csrfToken = decodeUrl(token)\n continue\n }\n const decodedToken: JwtPayload = await jwtService.verifyAsync(token, {\n secret: authConfig.token[cookie.type].secret\n })\n expect(decodedToken.iat).toBeCloseTo(currentTimeStamp(), -1)\n expect(decodedToken.exp).toBeCloseTo(currentTimeStamp() + convertHumanTimeToSeconds(authConfig.token[cookie.type].expiration), -1)\n expect(decodedToken.identity.id).toBe(userTest.id)\n if (cookie.type === TOKEN_TYPE.REFRESH) {\n // needed for the following tests\n refreshToken = token\n }\n }\n })\n\n it(`POST ${API_AUTH_LOGOUT} => 201`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_LOGOUT,\n body: null\n })\n expect(res.statusCode).toEqual(201)\n expect(res.headers['set-cookie']).toHaveLength(4)\n const cookies: { type: TOKEN_TYPE; content: string[] }[] = getCookies(res.headers['set-cookie'] as string[])\n /* Access cookie\n [\n 'sync-in-access=',\n 'Max-Age=0',\n 'Path=/',\n 'Expires=Thu, 01 Jan 1970 00:00:00 GMT',\n 'HttpOnly',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n /* Refresh cookie\n [\n 'sync-in-refresh=',\n 'Max-Age=0',\n 'Path=/api/auth/refresh',\n 'Expires=Thu, 01 Jan 1970 00:00:00 GMT',\n 'HttpOnly',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n /* WS cookie\n [\n 'sync-in-ws=',\n 'Max-Age=0',\n 'Path=/socket.io',\n 'Expires=Thu, 01 Jan 1970 00:00:00 GMT',\n 'HttpOnly',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n /* CSRF cookie\n [\n 'sync-in-csrf=',\n 'Max-Age=0',\n 'Path=/api/auth/refresh',\n 'Expires=Thu, 01 Jan 1970 00:00:00 GMT',\n 'HttpOnly',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n cookiesChecks(cookies, true)\n })\n\n it(`POST ${API_AUTH_REFRESH} => 201`, async () => {\n const res = await app.inject({\n method: 'POST',\n headers: { [authConfig.token.csrf.name]: csrfToken },\n url: API_AUTH_REFRESH,\n cookies: { [authConfig.token.refresh.name]: refreshToken }\n })\n expect(res.statusCode).toEqual(201)\n const cookies: { type: TOKEN_TYPE; content: string[] }[] = getCookies(res.headers['set-cookie'] as string[])\n cookiesChecks(cookies)\n })\n\n it(`POST ${API_AUTH_REFRESH} => 401 (with CSRF)`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_REFRESH,\n headers: { [authConfig.token.csrf.name]: csrfToken },\n cookies: { [authConfig.token.refresh.name]: 'bar' }\n })\n expect(res.statusCode).toEqual(401)\n })\n\n it(`POST ${API_AUTH_REFRESH} => 403 (without CSRF)`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_REFRESH,\n cookies: { [authConfig.token.refresh.name]: refreshToken }\n })\n expect(res.statusCode).toEqual(403)\n expect(res.json().message).toEqual(CSRF_ERROR.MISSING_HEADERS)\n })\n\n it(`POST ${API_AUTH_TOKEN} => 401`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_TOKEN,\n body: { login: userTest.login, password: 'bar' }\n })\n expect(res.statusCode).toEqual(401)\n })\n\n it(`POST ${API_AUTH_TOKEN} => 201`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_TOKEN,\n body: { login: userTest.login, password: userTest.password }\n })\n expect(res.statusCode).toEqual(201)\n const content = res.json()\n expect(() => transformAndValidate(TokenResponseDto, content)).not.toThrow()\n for (const type of TOKEN_TYPES.filter((p) => p === TOKEN_TYPE.ACCESS || p === TOKEN_TYPE.REFRESH)) {\n expect(content[type]).toBeDefined()\n expect(content[`${type}_expiration`]).toBeCloseTo(currentTimeStamp() + convertHumanTimeToSeconds(authConfig.token[type].expiration), -1)\n }\n })\n\n it(`POST ${API_AUTH_TOKEN_REFRESH} => 401`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_TOKEN_REFRESH,\n headers: { authorization: 'Bearer bar' }\n })\n expect(res.statusCode).toEqual(401)\n })\n\n it(`POST ${API_AUTH_TOKEN_REFRESH} => 201`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_TOKEN_REFRESH,\n headers: { authorization: `Bearer ${refreshToken}` }\n })\n expect(res.statusCode).toEqual(201)\n expect(() => transformAndValidate(TokenResponseDto, res.json())).not.toThrow()\n })\n\n function getCookies(setCookie: string[]): { type: TOKEN_TYPE; content: string[] }[] {\n const cookies: { type: TOKEN_TYPE; content: string[] }[] = []\n for (const c of setCookie) {\n const cookieName = c.split('=')[0]\n const cookieValues = c.split('; ')\n switch (cookieName) {\n case authConfig.token.access.name:\n cookies.push({ type: TOKEN_TYPE.ACCESS, content: cookieValues })\n break\n case authConfig.token.refresh.name:\n cookies.push({ type: TOKEN_TYPE.REFRESH, content: cookieValues })\n break\n case authConfig.token.ws.name:\n cookies.push({ type: TOKEN_TYPE.WS, content: cookieValues })\n break\n case authConfig.token.csrf.name:\n cookies.push({ type: TOKEN_TYPE.CSRF, content: cookieValues })\n break\n }\n }\n return cookies\n }\n\n function cookiesChecks(cookies: { type: TOKEN_TYPE; content: string[] }[], clear = false) {\n for (const cookie of cookies) {\n expect(cookie.content[0].split('=')[0]).toBe(authConfig.token[cookie.type].name)\n expect(cookie.content[2].split('=')[1]).toBe(TOKEN_PATHS[cookie.type])\n if (cookie.type === TOKEN_TYPE.CSRF) {\n expect(cookie.content).not.toContain('HttpOnly')\n } else {\n expect(cookie.content).toContain('HttpOnly')\n }\n expect(cookie.content).not.toContain('Secure')\n expect(cookie.content[cookie.content.length - 1].split('=')[1].toLowerCase()).toBe(authConfig.cookieSameSite)\n if (clear) {\n expect(cookie.content[0].split('=')[1]).toBe('')\n expect(cookie.content[1].split('=')[1]).toBe('0')\n expect(cookie.content[3].split('=')[1]).toBe('Thu, 01 Jan 1970 00:00:00 GMT')\n } else {\n expect(parseInt(cookie.content[1].split('=')[1])).toBeCloseTo(convertHumanTimeToSeconds(authConfig.token[cookie.type].expiration), -1)\n expect(cookie.content[0].split('=')[1]).not.toBe('')\n }\n }\n }\n})\n"],"names":["describe","app","authConfig","jwtService","adminUsersManager","userTest","refreshToken","csrfToken","beforeAll","appBootstrap","init","getHttpAdapter","getInstance","ready","get","ConfigService","JwtService","AdminUsersManager","UserModel","generateUserTest","afterAll","expect","deleteUserOrGuest","id","login","deleteSpace","isGuest","resolves","not","toThrow","dbCloseConnection","close","it","toBeDefined","dbCheckConnection","toBe","API_AUTH_LOGIN","res","inject","method","url","body","password","statusCode","toEqual","userId","createUserOrGuest","USER_ROLE","USER","Object","keys","json","arrayContaining","headers","toHaveLength","cookies","getCookies","cookiesChecks","cookie","token","content","substring","indexOf","type","TOKEN_TYPE","CSRF","decodeUrl","decodedToken","verifyAsync","secret","iat","toBeCloseTo","currentTimeStamp","exp","convertHumanTimeToSeconds","expiration","identity","REFRESH","API_AUTH_LOGOUT","API_AUTH_REFRESH","csrf","name","refresh","message","CSRF_ERROR","MISSING_HEADERS","API_AUTH_TOKEN","transformAndValidate","TokenResponseDto","TOKEN_TYPES","filter","p","ACCESS","API_AUTH_TOKEN_REFRESH","authorization","setCookie","c","cookieName","split","cookieValues","access","push","ws","WS","clear","TOKEN_PATHS","toContain","length","toLowerCase","cookieSameSite","parseInt"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../backend/src/authentication/auth.e2e-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 { ConfigService } from '@nestjs/config'\nimport { JwtService } from '@nestjs/jwt'\nimport { NestFastifyApplication } from '@nestjs/platform-fastify'\nimport { appBootstrap } from '../app.bootstrap'\nimport { USER_ROLE } from '../applications/users/constants/user'\nimport { DeleteUserDto } from '../applications/users/dto/delete-user.dto'\nimport { UserModel } from '../applications/users/models/user.model'\nimport { AdminUsersManager } from '../applications/users/services/admin-users-manager.service'\nimport { generateUserTest } from '../applications/users/utils/test'\nimport { convertHumanTimeToSeconds, transformAndValidate } from '../common/functions'\nimport { currentTimeStamp, decodeUrl } from '../common/shared'\nimport { dbCheckConnection } from '../infrastructure/database/utils'\nimport { AuthConfig } from './auth.config'\nimport { CSRF_ERROR, TOKEN_PATHS, TOKEN_TYPES } from './constants/auth'\nimport { API_AUTH_LOGIN, API_AUTH_LOGOUT, API_AUTH_REFRESH, API_AUTH_TOKEN, API_AUTH_TOKEN_REFRESH } from './constants/routes'\nimport { TokenResponseDto } from './dto/token-response.dto'\nimport { JwtPayload } from './interfaces/jwt-payload.interface'\nimport { TOKEN_TYPE } from './interfaces/token.interface'\n\ndescribe('Auth (e2e)', () => {\n let app: NestFastifyApplication\n let authConfig: AuthConfig\n let jwtService: JwtService\n let adminUsersManager: AdminUsersManager\n let userTest: UserModel\n let refreshToken: string\n let csrfToken: string\n\n beforeAll(async () => {\n app = await appBootstrap()\n await app.init()\n await app.getHttpAdapter().getInstance().ready()\n authConfig = app.get<ConfigService>(ConfigService).get<AuthConfig>('auth')\n jwtService = app.get<JwtService>(JwtService)\n adminUsersManager = app.get<AdminUsersManager>(AdminUsersManager)\n userTest = new UserModel(generateUserTest(false), false)\n })\n\n afterAll(async () => {\n await expect(\n adminUsersManager.deleteUserOrGuest(userTest.id, userTest.login, { deleteSpace: true, isGuest: false } satisfies DeleteUserDto)\n ).resolves.not.toThrow()\n await app.close()\n })\n\n it('should be defined', () => {\n expect(authConfig).toBeDefined()\n expect(jwtService).toBeDefined()\n expect(adminUsersManager).toBeDefined()\n expect(userTest).toBeDefined()\n })\n\n it('should get the database connection', async () => {\n expect(await dbCheckConnection(app)).toBe(true)\n })\n\n it(`POST ${API_AUTH_LOGIN} => 401`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_LOGIN,\n body: { login: userTest.login, password: userTest.password }\n })\n expect(res.statusCode).toEqual(401)\n })\n\n it(`POST ${API_AUTH_LOGIN} => 201`, async () => {\n const userId = (await adminUsersManager.createUserOrGuest({ ...userTest }, USER_ROLE.USER)).id\n expect(userId).toBeDefined()\n userTest.id = userId\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_LOGIN,\n body: { login: userTest.login, password: userTest.password }\n })\n expect(res.statusCode).toEqual(201)\n expect(Object.keys(res.json())).toEqual(expect.arrayContaining(['user', 'token']))\n expect(res.headers['set-cookie']).toHaveLength(4)\n const cookies: { type: TOKEN_TYPE; content: string[] }[] = getCookies(res.headers['set-cookie'] as string[])\n /* Access cookie\n [\n 'sync-in-access=value,\n 'Max-Age=3600',\n 'Path=/',\n 'HttpOnly',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n /* Refresh cookie\n [\n 'sync-in-refresh=value,\n 'Max-Age=14400',\n 'Path=/api/auth/refresh',\n 'HttpOnly',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n /* WS cookie\n [\n 'sync-in-ws=value,\n 'Max-Age=14400',\n 'Path=/socket.io',\n 'HttpOnly',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n /* CSRF cookie\n [\n 'sync-in-csrf=value,\n 'Max-Age=14400',\n 'Path=/',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n cookiesChecks(cookies)\n // Verify token\n for (const cookie of cookies) {\n const token = cookie.content[0].substring(cookie.content[0].indexOf('=') + 1)\n if (cookie.type === TOKEN_TYPE.CSRF) {\n // needed for the following tests\n csrfToken = decodeUrl(token)\n continue\n }\n const decodedToken: JwtPayload = await jwtService.verifyAsync(token, {\n secret: authConfig.token[cookie.type].secret\n })\n expect(decodedToken.iat).toBeCloseTo(currentTimeStamp(), -1)\n expect(decodedToken.exp).toBeCloseTo(currentTimeStamp() + convertHumanTimeToSeconds(authConfig.token[cookie.type].expiration), -1)\n expect(decodedToken.identity.id).toBe(userTest.id)\n if (cookie.type === TOKEN_TYPE.REFRESH) {\n // needed for the following tests\n refreshToken = token\n }\n }\n })\n\n it(`POST ${API_AUTH_LOGOUT} => 201`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_LOGOUT,\n body: null\n })\n expect(res.statusCode).toEqual(201)\n expect(res.headers['set-cookie']).toHaveLength(5)\n /* Access cookie\n [\n 'sync-in-access=',\n 'Max-Age=0',\n 'Path=/',\n 'Expires=Thu, 01 Jan 1970 00:00:00 GMT',\n 'HttpOnly',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n /* Refresh cookie\n [\n 'sync-in-refresh=',\n 'Max-Age=0',\n 'Path=/api/auth/refresh',\n 'Expires=Thu, 01 Jan 1970 00:00:00 GMT',\n 'HttpOnly',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n /* WS cookie\n [\n 'sync-in-ws=',\n 'Max-Age=0',\n 'Path=/socket.io',\n 'Expires=Thu, 01 Jan 1970 00:00:00 GMT',\n 'HttpOnly',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n /* CSRF cookie\n [\n 'sync-in-csrf=',\n 'Max-Age=0',\n 'Path=/api/auth/refresh',\n 'Expires=Thu, 01 Jan 1970 00:00:00 GMT',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n /* Access cookie 2FA\n [\n 'sync-in-access=',\n 'Max-Age=0',\n 'Path=/api/auth/2fa/login/verify',\n 'Expires=Thu, 01 Jan 1970 00:00:00 GMT',\n 'HttpOnly',\n 'Secure',\n 'SameSite=Strict'\n ]\n */\n })\n\n it(`POST ${API_AUTH_REFRESH} => 201`, async () => {\n const res = await app.inject({\n method: 'POST',\n headers: { [authConfig.token.csrf.name]: csrfToken },\n url: API_AUTH_REFRESH,\n cookies: { [authConfig.token.refresh.name]: refreshToken }\n })\n expect(res.statusCode).toEqual(201)\n const cookies: { type: TOKEN_TYPE; content: string[] }[] = getCookies(res.headers['set-cookie'] as string[])\n cookiesChecks(cookies)\n })\n\n it(`POST ${API_AUTH_REFRESH} => 401 (with CSRF)`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_REFRESH,\n headers: { [authConfig.token.csrf.name]: csrfToken },\n cookies: { [authConfig.token.refresh.name]: 'bar' }\n })\n expect(res.statusCode).toEqual(401)\n })\n\n it(`POST ${API_AUTH_REFRESH} => 403 (without CSRF)`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_REFRESH,\n cookies: { [authConfig.token.refresh.name]: refreshToken }\n })\n expect(res.statusCode).toEqual(403)\n expect(res.json().message).toEqual(CSRF_ERROR.MISSING_HEADERS)\n })\n\n it(`POST ${API_AUTH_TOKEN} => 401`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_TOKEN,\n body: { login: userTest.login, password: 'bar' }\n })\n expect(res.statusCode).toEqual(401)\n })\n\n it(`POST ${API_AUTH_TOKEN} => 201`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_TOKEN,\n body: { login: userTest.login, password: userTest.password }\n })\n expect(res.statusCode).toEqual(201)\n const content = res.json()\n expect(() => transformAndValidate(TokenResponseDto, content)).not.toThrow()\n for (const type of TOKEN_TYPES.filter((p) => p === TOKEN_TYPE.ACCESS || p === TOKEN_TYPE.REFRESH)) {\n expect(content[type]).toBeDefined()\n expect(content[`${type}_expiration`]).toBeCloseTo(currentTimeStamp() + convertHumanTimeToSeconds(authConfig.token[type].expiration), -1)\n }\n })\n\n it(`POST ${API_AUTH_TOKEN_REFRESH} => 401`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_TOKEN_REFRESH,\n headers: { authorization: 'Bearer bar' }\n })\n expect(res.statusCode).toEqual(401)\n })\n\n it(`POST ${API_AUTH_TOKEN_REFRESH} => 201`, async () => {\n const res = await app.inject({\n method: 'POST',\n url: API_AUTH_TOKEN_REFRESH,\n headers: { authorization: `Bearer ${refreshToken}` }\n })\n expect(res.statusCode).toEqual(201)\n expect(() => transformAndValidate(TokenResponseDto, res.json())).not.toThrow()\n })\n\n function getCookies(setCookie: string[]): { type: TOKEN_TYPE; content: string[] }[] {\n const cookies: { type: TOKEN_TYPE; content: string[] }[] = []\n for (const c of setCookie) {\n const cookieName = c.split('=')[0]\n const cookieValues = c.split('; ')\n switch (cookieName) {\n case authConfig.token.access.name:\n cookies.push({ type: TOKEN_TYPE.ACCESS, content: cookieValues })\n break\n case authConfig.token.refresh.name:\n cookies.push({ type: TOKEN_TYPE.REFRESH, content: cookieValues })\n break\n case authConfig.token.ws.name:\n cookies.push({ type: TOKEN_TYPE.WS, content: cookieValues })\n break\n case authConfig.token.csrf.name:\n cookies.push({ type: TOKEN_TYPE.CSRF, content: cookieValues })\n break\n }\n }\n return cookies\n }\n\n function cookiesChecks(cookies: { type: TOKEN_TYPE; content: string[] }[], clear = false) {\n for (const cookie of cookies) {\n expect(cookie.content[0].split('=')[0]).toBe(authConfig.token[cookie.type].name)\n expect(cookie.content[2].split('=')[1]).toBe(TOKEN_PATHS[cookie.type])\n if (cookie.type === TOKEN_TYPE.CSRF) {\n expect(cookie.content).not.toContain('HttpOnly')\n } else {\n expect(cookie.content).toContain('HttpOnly')\n }\n expect(cookie.content).not.toContain('Secure')\n expect(cookie.content[cookie.content.length - 1].split('=')[1].toLowerCase()).toBe(authConfig.cookieSameSite)\n if (clear) {\n expect(cookie.content[0].split('=')[1]).toBe('')\n expect(cookie.content[1].split('=')[1]).toBe('0')\n expect(cookie.content[3].split('=')[1]).toBe('Thu, 01 Jan 1970 00:00:00 GMT')\n } else {\n expect(parseInt(cookie.content[1].split('=')[1])).toBeCloseTo(convertHumanTimeToSeconds(authConfig.token[cookie.type].expiration), -1)\n expect(cookie.content[0].split('=')[1]).not.toBe('')\n }\n }\n }\n})\n"],"names":["describe","app","authConfig","jwtService","adminUsersManager","userTest","refreshToken","csrfToken","beforeAll","appBootstrap","init","getHttpAdapter","getInstance","ready","get","ConfigService","JwtService","AdminUsersManager","UserModel","generateUserTest","afterAll","expect","deleteUserOrGuest","id","login","deleteSpace","isGuest","resolves","not","toThrow","close","it","toBeDefined","dbCheckConnection","toBe","API_AUTH_LOGIN","res","inject","method","url","body","password","statusCode","toEqual","userId","createUserOrGuest","USER_ROLE","USER","Object","keys","json","arrayContaining","headers","toHaveLength","cookies","getCookies","cookiesChecks","cookie","token","content","substring","indexOf","type","TOKEN_TYPE","CSRF","decodeUrl","decodedToken","verifyAsync","secret","iat","toBeCloseTo","currentTimeStamp","exp","convertHumanTimeToSeconds","expiration","identity","REFRESH","API_AUTH_LOGOUT","API_AUTH_REFRESH","csrf","name","refresh","message","CSRF_ERROR","MISSING_HEADERS","API_AUTH_TOKEN","transformAndValidate","TokenResponseDto","TOKEN_TYPES","filter","p","ACCESS","API_AUTH_TOKEN_REFRESH","authorization","setCookie","c","cookieName","split","cookieValues","access","push","ws","WS","clear","TOKEN_PATHS","toContain","length","toLowerCase","cookieSameSite","parseInt"],"mappings":"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"}
@@ -82,6 +82,29 @@ describe(_authbasicguard.AuthBasicGuard.name, ()=>{
82
82
  expect(await authBasicGuard.canActivate(context)).toBe(true);
83
83
  expect(userTest.password).toBeUndefined();
84
84
  });
85
+ it('should validate the user authentication with password containing colon', async ()=>{
86
+ const passwordWithColon = 'pass:word:123';
87
+ const userWithColonPassword = new _usermodel.UserModel({
88
+ ...(0, _test.generateUserTest)(),
89
+ password: passwordWithColon
90
+ }, false);
91
+ const encodedAuthWithColon = Buffer.from(`${userWithColonPassword.login}:${passwordWithColon}`).toString('base64');
92
+ authMethod.validateUser = jest.fn().mockImplementation((login, password)=>{
93
+ expect(login).toBe(userWithColonPassword.login);
94
+ expect(password).toBe(passwordWithColon);
95
+ return userWithColonPassword;
96
+ });
97
+ context.switchToHttp().getRequest.mockReturnValue({
98
+ raw: {
99
+ user: ''
100
+ },
101
+ headers: {
102
+ authorization: `Basic ${encodedAuthWithColon}`
103
+ }
104
+ });
105
+ expect(await authBasicGuard.canActivate(context)).toBe(true);
106
+ expect(userWithColonPassword.password).toBeUndefined();
107
+ });
85
108
  it('should validate the user authentication with cache', async ()=>{
86
109
  cache.get = jest.fn().mockReturnValueOnce(userTest);
87
110
  context.switchToHttp().getRequest.mockReturnValue({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../backend/src/authentication/guards/auth-basic.guard.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 { createMock, DeepMocked } from '@golevelup/ts-jest'\nimport { ExecutionContext } from '@nestjs/common'\nimport { Test, TestingModule } from '@nestjs/testing'\nimport { PinoLogger } from 'nestjs-pino'\nimport { UserModel } from '../../applications/users/models/user.model'\nimport { generateUserTest } from '../../applications/users/utils/test'\nimport { WEBDAV_BASE_PATH } from '../../applications/webdav/constants/routes'\nimport { Cache } from '../../infrastructure/cache/services/cache.service'\nimport { AuthMethod } from '../models/auth-method'\nimport { AuthBasicGuard } from './auth-basic.guard'\nimport { AuthBasicStrategy } from './auth-basic.strategy'\n\ndescribe(AuthBasicGuard.name, () => {\n let authBasicGuard: AuthBasicGuard\n let authBasicStrategy: AuthBasicStrategy\n let authMethod: AuthMethod\n let cache: Cache\n let userTest: UserModel\n let encodedAuth: string\n let context: DeepMocked<ExecutionContext>\n\n beforeAll(async () => {\n const module: TestingModule = await Test.createTestingModule({\n providers: [\n AuthBasicGuard,\n AuthBasicStrategy,\n {\n provide: AuthMethod,\n useValue: {\n validateUser: async () => null\n }\n },\n {\n provide: PinoLogger,\n useValue: {\n assign: () => undefined,\n error: jest.fn()\n }\n },\n {\n provide: Cache,\n useValue: {\n get: (_key: string) => undefined,\n set: async (_key: string, _value: string, _ttl: number) => undefined,\n genSlugKey: () => 'test'\n }\n }\n ]\n }).compile()\n\n authBasicGuard = module.get<AuthBasicGuard>(AuthBasicGuard)\n authBasicStrategy = module.get<AuthBasicStrategy>(AuthBasicStrategy)\n authMethod = module.get<AuthMethod>(AuthMethod)\n cache = module.get<Cache>(Cache)\n userTest = new UserModel(generateUserTest(), false)\n encodedAuth = Buffer.from(`${userTest.login}:${userTest.password}`).toString('base64')\n context = createMock<ExecutionContext>()\n })\n\n it('should be defined', () => {\n expect(authBasicGuard).toBeDefined()\n expect(authBasicStrategy).toBeDefined()\n expect(authMethod).toBeDefined()\n expect(cache).toBeDefined()\n expect(encodedAuth).toBeDefined()\n expect(userTest).toBeDefined()\n expect(userTest.password).toBeDefined()\n })\n\n it('should validate the user authentication', async () => {\n authMethod.validateUser = jest.fn().mockReturnValueOnce(userTest)\n context.switchToHttp().getRequest.mockReturnValue({\n raw: { user: '' },\n headers: { authorization: `Basic ${encodedAuth}` }\n })\n expect(await authBasicGuard.canActivate(context)).toBe(true)\n expect(userTest.password).toBeUndefined()\n })\n\n it('should validate the user authentication with cache', async () => {\n cache.get = jest.fn().mockReturnValueOnce(userTest)\n context.switchToHttp().getRequest.mockReturnValue({\n raw: { user: '' },\n headers: { authorization: `Basic ${encodedAuth}` }\n })\n expect(await authBasicGuard.canActivate(context)).toBe(true)\n })\n\n it('should not validate the user authentication when cache returns null (explicitly unauthorized)', async () => {\n cache.get = jest.fn().mockReturnValueOnce(null)\n context.switchToHttp().getRequest.mockReturnValue({\n raw: { user: '' },\n headers: { authorization: `Basic ${encodedAuth}` }\n })\n await expect(authBasicGuard.canActivate(context)).rejects.toThrow()\n })\n\n it('should not validate the user authentication when cache returns undefined and database return null', async () => {\n cache.get = jest.fn().mockReturnValueOnce(undefined)\n authMethod.validateUser = jest.fn().mockReturnValueOnce(null)\n jest.spyOn(cache, 'set').mockRejectedValueOnce(new Error('cache failed'))\n context.switchToHttp().getRequest.mockReturnValue({\n raw: { user: '' },\n headers: { authorization: `Basic ${encodedAuth}` }\n })\n const loggerSpy = jest\n .spyOn(authBasicStrategy['logger'], 'error') // <-- spy the SAME instance used in the class\n .mockImplementation(() => undefined)\n await expect(authBasicGuard.canActivate(context)).rejects.toThrow()\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls[0][0]).toEqual(expect.stringContaining('cache failed'))\n })\n\n it('should not validate the user authentication', async () => {\n context.switchToHttp().getRequest.mockReturnValue({\n raw: { user: '' },\n headers: { authorization: `Basic ${encodedAuth}` }\n })\n await expect(authBasicGuard.canActivate(context)).rejects.toThrow()\n })\n\n it('should throw error due to malformed authorization header', async () => {\n // headers with capitals not working\n context.switchToHttp().getRequest.mockReturnValueOnce({\n raw: { user: '' },\n headers: { AUTHORIZATION: 'Basic foo' }\n })\n await expect(authBasicGuard.canActivate(context)).rejects.toThrow()\n context.switchToHttp().getRequest.mockReturnValueOnce({\n raw: { user: '' }\n })\n await expect(authBasicGuard.canActivate(context)).rejects.toThrow()\n })\n\n it(`should valid OPTIONS method without authentication header on \"/\" and \"/${WEBDAV_BASE_PATH}/*\" paths `, async () => {\n for (const url of ['', `/${WEBDAV_BASE_PATH}`, `/${WEBDAV_BASE_PATH}/foo/bar`]) {\n context.switchToHttp().getRequest.mockReturnValueOnce({\n method: 'OPTIONS',\n originalUrl: url,\n raw: { user: '' }\n })\n expect(await authBasicGuard.canActivate(context)).toBe(true)\n }\n })\n\n it('should not valid OPTIONS method with other paths', async () => {\n context.switchToHttp().getRequest.mockReturnValueOnce({\n method: 'OPTIONS',\n originalUrl: '/foo',\n raw: { user: '' }\n })\n await expect(authBasicGuard.canActivate(context)).rejects.toThrow()\n })\n})\n"],"names":["describe","AuthBasicGuard","name","authBasicGuard","authBasicStrategy","authMethod","cache","userTest","encodedAuth","context","beforeAll","module","Test","createTestingModule","providers","AuthBasicStrategy","provide","AuthMethod","useValue","validateUser","PinoLogger","assign","undefined","error","jest","fn","Cache","get","_key","set","_value","_ttl","genSlugKey","compile","UserModel","generateUserTest","Buffer","from","login","password","toString","createMock","it","expect","toBeDefined","mockReturnValueOnce","switchToHttp","getRequest","mockReturnValue","raw","user","headers","authorization","canActivate","toBe","toBeUndefined","rejects","toThrow","spyOn","mockRejectedValueOnce","Error","loggerSpy","mockImplementation","toHaveBeenCalled","mock","calls","toEqual","stringContaining","AUTHORIZATION","WEBDAV_BASE_PATH","url","method","originalUrl"],"mappings":"AAAA;;;;CAIC;;;;wBAEsC;yBAEH;4BACT;2BACD;sBACO;wBACA;8BACX;4BACK;gCACI;mCACG;AAElCA,SAASC,8BAAc,CAACC,IAAI,EAAE;IAC5B,IAAIC;IACJ,IAAIC;IACJ,IAAIC;IACJ,IAAIC;IACJ,IAAIC;IACJ,IAAIC;IACJ,IAAIC;IAEJC,UAAU;QACR,MAAMC,SAAwB,MAAMC,aAAI,CAACC,mBAAmB,CAAC;YAC3DC,WAAW;gBACTb,8BAAc;gBACdc,oCAAiB;gBACjB;oBACEC,SAASC,sBAAU;oBACnBC,UAAU;wBACRC,cAAc,UAAY;oBAC5B;gBACF;gBACA;oBACEH,SAASI,sBAAU;oBACnBF,UAAU;wBACRG,QAAQ,IAAMC;wBACdC,OAAOC,KAAKC,EAAE;oBAChB;gBACF;gBACA;oBACET,SAASU,mBAAK;oBACdR,UAAU;wBACRS,KAAK,CAACC,OAAiBN;wBACvBO,KAAK,OAAOD,MAAcE,QAAgBC,OAAiBT;wBAC3DU,YAAY,IAAM;oBACpB;gBACF;aACD;QACH,GAAGC,OAAO;QAEV9B,iBAAiBQ,OAAOgB,GAAG,CAAiB1B,8BAAc;QAC1DG,oBAAoBO,OAAOgB,GAAG,CAAoBZ,oCAAiB;QACnEV,aAAaM,OAAOgB,GAAG,CAAaV,sBAAU;QAC9CX,QAAQK,OAAOgB,GAAG,CAAQD,mBAAK;QAC/BnB,WAAW,IAAI2B,oBAAS,CAACC,IAAAA,sBAAgB,KAAI;QAC7C3B,cAAc4B,OAAOC,IAAI,CAAC,GAAG9B,SAAS+B,KAAK,CAAC,CAAC,EAAE/B,SAASgC,QAAQ,EAAE,EAAEC,QAAQ,CAAC;QAC7E/B,UAAUgC,IAAAA,kBAAU;IACtB;IAEAC,GAAG,qBAAqB;QACtBC,OAAOxC,gBAAgByC,WAAW;QAClCD,OAAOvC,mBAAmBwC,WAAW;QACrCD,OAAOtC,YAAYuC,WAAW;QAC9BD,OAAOrC,OAAOsC,WAAW;QACzBD,OAAOnC,aAAaoC,WAAW;QAC/BD,OAAOpC,UAAUqC,WAAW;QAC5BD,OAAOpC,SAASgC,QAAQ,EAAEK,WAAW;IACvC;IAEAF,GAAG,2CAA2C;QAC5CrC,WAAWc,YAAY,GAAGK,KAAKC,EAAE,GAAGoB,mBAAmB,CAACtC;QACxDE,QAAQqC,YAAY,GAAGC,UAAU,CAACC,eAAe,CAAC;YAChDC,KAAK;gBAAEC,MAAM;YAAG;YAChBC,SAAS;gBAAEC,eAAe,CAAC,MAAM,EAAE5C,aAAa;YAAC;QACnD;QACAmC,OAAO,MAAMxC,eAAekD,WAAW,CAAC5C,UAAU6C,IAAI,CAAC;QACvDX,OAAOpC,SAASgC,QAAQ,EAAEgB,aAAa;IACzC;IAEAb,GAAG,sDAAsD;QACvDpC,MAAMqB,GAAG,GAAGH,KAAKC,EAAE,GAAGoB,mBAAmB,CAACtC;QAC1CE,QAAQqC,YAAY,GAAGC,UAAU,CAACC,eAAe,CAAC;YAChDC,KAAK;gBAAEC,MAAM;YAAG;YAChBC,SAAS;gBAAEC,eAAe,CAAC,MAAM,EAAE5C,aAAa;YAAC;QACnD;QACAmC,OAAO,MAAMxC,eAAekD,WAAW,CAAC5C,UAAU6C,IAAI,CAAC;IACzD;IAEAZ,GAAG,iGAAiG;QAClGpC,MAAMqB,GAAG,GAAGH,KAAKC,EAAE,GAAGoB,mBAAmB,CAAC;QAC1CpC,QAAQqC,YAAY,GAAGC,UAAU,CAACC,eAAe,CAAC;YAChDC,KAAK;gBAAEC,MAAM;YAAG;YAChBC,SAAS;gBAAEC,eAAe,CAAC,MAAM,EAAE5C,aAAa;YAAC;QACnD;QACA,MAAMmC,OAAOxC,eAAekD,WAAW,CAAC5C,UAAU+C,OAAO,CAACC,OAAO;IACnE;IAEAf,GAAG,qGAAqG;QACtGpC,MAAMqB,GAAG,GAAGH,KAAKC,EAAE,GAAGoB,mBAAmB,CAACvB;QAC1CjB,WAAWc,YAAY,GAAGK,KAAKC,EAAE,GAAGoB,mBAAmB,CAAC;QACxDrB,KAAKkC,KAAK,CAACpD,OAAO,OAAOqD,qBAAqB,CAAC,IAAIC,MAAM;QACzDnD,QAAQqC,YAAY,GAAGC,UAAU,CAACC,eAAe,CAAC;YAChDC,KAAK;gBAAEC,MAAM;YAAG;YAChBC,SAAS;gBAAEC,eAAe,CAAC,MAAM,EAAE5C,aAAa;YAAC;QACnD;QACA,MAAMqD,YAAYrC,KACfkC,KAAK,CAACtD,iBAAiB,CAAC,SAAS,EAAE,SAAS,8CAA8C;SAC1F0D,kBAAkB,CAAC,IAAMxC;QAC5B,MAAMqB,OAAOxC,eAAekD,WAAW,CAAC5C,UAAU+C,OAAO,CAACC,OAAO;QACjEd,OAAOkB,WAAWE,gBAAgB;QAClCpB,OAAOkB,UAAUG,IAAI,CAACC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAEC,OAAO,CAACvB,OAAOwB,gBAAgB,CAAC;IACrE;IAEAzB,GAAG,+CAA+C;QAChDjC,QAAQqC,YAAY,GAAGC,UAAU,CAACC,eAAe,CAAC;YAChDC,KAAK;gBAAEC,MAAM;YAAG;YAChBC,SAAS;gBAAEC,eAAe,CAAC,MAAM,EAAE5C,aAAa;YAAC;QACnD;QACA,MAAMmC,OAAOxC,eAAekD,WAAW,CAAC5C,UAAU+C,OAAO,CAACC,OAAO;IACnE;IAEAf,GAAG,4DAA4D;QAC7D,oCAAoC;QACpCjC,QAAQqC,YAAY,GAAGC,UAAU,CAACF,mBAAmB,CAAC;YACpDI,KAAK;gBAAEC,MAAM;YAAG;YAChBC,SAAS;gBAAEiB,eAAe;YAAY;QACxC;QACA,MAAMzB,OAAOxC,eAAekD,WAAW,CAAC5C,UAAU+C,OAAO,CAACC,OAAO;QACjEhD,QAAQqC,YAAY,GAAGC,UAAU,CAACF,mBAAmB,CAAC;YACpDI,KAAK;gBAAEC,MAAM;YAAG;QAClB;QACA,MAAMP,OAAOxC,eAAekD,WAAW,CAAC5C,UAAU+C,OAAO,CAACC,OAAO;IACnE;IAEAf,GAAG,CAAC,uEAAuE,EAAE2B,wBAAgB,CAAC,UAAU,CAAC,EAAE;QACzG,KAAK,MAAMC,OAAO;YAAC;YAAI,CAAC,CAAC,EAAED,wBAAgB,EAAE;YAAE,CAAC,CAAC,EAAEA,wBAAgB,CAAC,QAAQ,CAAC;SAAC,CAAE;YAC9E5D,QAAQqC,YAAY,GAAGC,UAAU,CAACF,mBAAmB,CAAC;gBACpD0B,QAAQ;gBACRC,aAAaF;gBACbrB,KAAK;oBAAEC,MAAM;gBAAG;YAClB;YACAP,OAAO,MAAMxC,eAAekD,WAAW,CAAC5C,UAAU6C,IAAI,CAAC;QACzD;IACF;IAEAZ,GAAG,oDAAoD;QACrDjC,QAAQqC,YAAY,GAAGC,UAAU,CAACF,mBAAmB,CAAC;YACpD0B,QAAQ;YACRC,aAAa;YACbvB,KAAK;gBAAEC,MAAM;YAAG;QAClB;QACA,MAAMP,OAAOxC,eAAekD,WAAW,CAAC5C,UAAU+C,OAAO,CAACC,OAAO;IACnE;AACF"}
1
+ {"version":3,"sources":["../../../../backend/src/authentication/guards/auth-basic.guard.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 { createMock, DeepMocked } from '@golevelup/ts-jest'\nimport { ExecutionContext } from '@nestjs/common'\nimport { Test, TestingModule } from '@nestjs/testing'\nimport { PinoLogger } from 'nestjs-pino'\nimport { UserModel } from '../../applications/users/models/user.model'\nimport { generateUserTest } from '../../applications/users/utils/test'\nimport { WEBDAV_BASE_PATH } from '../../applications/webdav/constants/routes'\nimport { Cache } from '../../infrastructure/cache/services/cache.service'\nimport { AuthMethod } from '../models/auth-method'\nimport { AuthBasicGuard } from './auth-basic.guard'\nimport { AuthBasicStrategy } from './auth-basic.strategy'\n\ndescribe(AuthBasicGuard.name, () => {\n let authBasicGuard: AuthBasicGuard\n let authBasicStrategy: AuthBasicStrategy\n let authMethod: AuthMethod\n let cache: Cache\n let userTest: UserModel\n let encodedAuth: string\n let context: DeepMocked<ExecutionContext>\n\n beforeAll(async () => {\n const module: TestingModule = await Test.createTestingModule({\n providers: [\n AuthBasicGuard,\n AuthBasicStrategy,\n {\n provide: AuthMethod,\n useValue: {\n validateUser: async () => null\n }\n },\n {\n provide: PinoLogger,\n useValue: {\n assign: () => undefined,\n error: jest.fn()\n }\n },\n {\n provide: Cache,\n useValue: {\n get: (_key: string) => undefined,\n set: async (_key: string, _value: string, _ttl: number) => undefined,\n genSlugKey: () => 'test'\n }\n }\n ]\n }).compile()\n\n authBasicGuard = module.get<AuthBasicGuard>(AuthBasicGuard)\n authBasicStrategy = module.get<AuthBasicStrategy>(AuthBasicStrategy)\n authMethod = module.get<AuthMethod>(AuthMethod)\n cache = module.get<Cache>(Cache)\n userTest = new UserModel(generateUserTest(), false)\n encodedAuth = Buffer.from(`${userTest.login}:${userTest.password}`).toString('base64')\n context = createMock<ExecutionContext>()\n })\n\n it('should be defined', () => {\n expect(authBasicGuard).toBeDefined()\n expect(authBasicStrategy).toBeDefined()\n expect(authMethod).toBeDefined()\n expect(cache).toBeDefined()\n expect(encodedAuth).toBeDefined()\n expect(userTest).toBeDefined()\n expect(userTest.password).toBeDefined()\n })\n\n it('should validate the user authentication', async () => {\n authMethod.validateUser = jest.fn().mockReturnValueOnce(userTest)\n context.switchToHttp().getRequest.mockReturnValue({\n raw: { user: '' },\n headers: { authorization: `Basic ${encodedAuth}` }\n })\n expect(await authBasicGuard.canActivate(context)).toBe(true)\n expect(userTest.password).toBeUndefined()\n })\n\n it('should validate the user authentication with password containing colon', async () => {\n const passwordWithColon = 'pass:word:123'\n const userWithColonPassword = new UserModel({ ...generateUserTest(), password: passwordWithColon }, false)\n const encodedAuthWithColon = Buffer.from(`${userWithColonPassword.login}:${passwordWithColon}`).toString('base64')\n\n authMethod.validateUser = jest.fn().mockImplementation((login: string, password: string) => {\n expect(login).toBe(userWithColonPassword.login)\n expect(password).toBe(passwordWithColon)\n return userWithColonPassword\n })\n context.switchToHttp().getRequest.mockReturnValue({\n raw: { user: '' },\n headers: { authorization: `Basic ${encodedAuthWithColon}` }\n })\n expect(await authBasicGuard.canActivate(context)).toBe(true)\n expect(userWithColonPassword.password).toBeUndefined()\n })\n\n it('should validate the user authentication with cache', async () => {\n cache.get = jest.fn().mockReturnValueOnce(userTest)\n context.switchToHttp().getRequest.mockReturnValue({\n raw: { user: '' },\n headers: { authorization: `Basic ${encodedAuth}` }\n })\n expect(await authBasicGuard.canActivate(context)).toBe(true)\n })\n\n it('should not validate the user authentication when cache returns null (explicitly unauthorized)', async () => {\n cache.get = jest.fn().mockReturnValueOnce(null)\n context.switchToHttp().getRequest.mockReturnValue({\n raw: { user: '' },\n headers: { authorization: `Basic ${encodedAuth}` }\n })\n await expect(authBasicGuard.canActivate(context)).rejects.toThrow()\n })\n\n it('should not validate the user authentication when cache returns undefined and database return null', async () => {\n cache.get = jest.fn().mockReturnValueOnce(undefined)\n authMethod.validateUser = jest.fn().mockReturnValueOnce(null)\n jest.spyOn(cache, 'set').mockRejectedValueOnce(new Error('cache failed'))\n context.switchToHttp().getRequest.mockReturnValue({\n raw: { user: '' },\n headers: { authorization: `Basic ${encodedAuth}` }\n })\n const loggerSpy = jest\n .spyOn(authBasicStrategy['logger'], 'error') // <-- spy the SAME instance used in the class\n .mockImplementation(() => undefined)\n await expect(authBasicGuard.canActivate(context)).rejects.toThrow()\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls[0][0]).toEqual(expect.stringContaining('cache failed'))\n })\n\n it('should not validate the user authentication', async () => {\n context.switchToHttp().getRequest.mockReturnValue({\n raw: { user: '' },\n headers: { authorization: `Basic ${encodedAuth}` }\n })\n await expect(authBasicGuard.canActivate(context)).rejects.toThrow()\n })\n\n it('should throw error due to malformed authorization header', async () => {\n // headers with capitals not working\n context.switchToHttp().getRequest.mockReturnValueOnce({\n raw: { user: '' },\n headers: { AUTHORIZATION: 'Basic foo' }\n })\n await expect(authBasicGuard.canActivate(context)).rejects.toThrow()\n context.switchToHttp().getRequest.mockReturnValueOnce({\n raw: { user: '' }\n })\n await expect(authBasicGuard.canActivate(context)).rejects.toThrow()\n })\n\n it(`should valid OPTIONS method without authentication header on \"/\" and \"/${WEBDAV_BASE_PATH}/*\" paths `, async () => {\n for (const url of ['', `/${WEBDAV_BASE_PATH}`, `/${WEBDAV_BASE_PATH}/foo/bar`]) {\n context.switchToHttp().getRequest.mockReturnValueOnce({\n method: 'OPTIONS',\n originalUrl: url,\n raw: { user: '' }\n })\n expect(await authBasicGuard.canActivate(context)).toBe(true)\n }\n })\n\n it('should not valid OPTIONS method with other paths', async () => {\n context.switchToHttp().getRequest.mockReturnValueOnce({\n method: 'OPTIONS',\n originalUrl: '/foo',\n raw: { user: '' }\n })\n await expect(authBasicGuard.canActivate(context)).rejects.toThrow()\n })\n})\n"],"names":["describe","AuthBasicGuard","name","authBasicGuard","authBasicStrategy","authMethod","cache","userTest","encodedAuth","context","beforeAll","module","Test","createTestingModule","providers","AuthBasicStrategy","provide","AuthMethod","useValue","validateUser","PinoLogger","assign","undefined","error","jest","fn","Cache","get","_key","set","_value","_ttl","genSlugKey","compile","UserModel","generateUserTest","Buffer","from","login","password","toString","createMock","it","expect","toBeDefined","mockReturnValueOnce","switchToHttp","getRequest","mockReturnValue","raw","user","headers","authorization","canActivate","toBe","toBeUndefined","passwordWithColon","userWithColonPassword","encodedAuthWithColon","mockImplementation","rejects","toThrow","spyOn","mockRejectedValueOnce","Error","loggerSpy","toHaveBeenCalled","mock","calls","toEqual","stringContaining","AUTHORIZATION","WEBDAV_BASE_PATH","url","method","originalUrl"],"mappings":"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"}
@@ -16,12 +16,12 @@ const _common = require("@nestjs/common");
16
16
  const _passport = require("@nestjs/passport");
17
17
  const _classtransformer = require("class-transformer");
18
18
  const _nestjspino = require("nestjs-pino");
19
- const _passporthttp = require("passport-http");
20
19
  const _usermodel = require("../../applications/users/models/user.model");
21
20
  const _shared = require("../../common/shared");
22
21
  const _cacheservice = require("../../infrastructure/cache/services/cache.service");
23
22
  const _scope = require("../constants/scope");
24
23
  const _authmethod = require("../models/auth-method");
24
+ const _httpbasicstrategy = require("./implementations/http-basic.strategy");
25
25
  function _ts_decorate(decorators, target, key, desc) {
26
26
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
27
27
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -31,7 +31,7 @@ function _ts_decorate(decorators, target, key, desc) {
31
31
  function _ts_metadata(k, v) {
32
32
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
33
33
  }
34
- let AuthBasicStrategy = class AuthBasicStrategy extends (0, _passport.PassportStrategy)(_passporthttp.BasicStrategy, 'basic') {
34
+ let AuthBasicStrategy = class AuthBasicStrategy extends (0, _passport.PassportStrategy)(_httpbasicstrategy.HttpBasicStrategy, 'basic') {
35
35
  async validate(req, loginOrEmail, password) {
36
36
  loginOrEmail = loginOrEmail.trim();
37
37
  password = password.trim();
@@ -46,7 +46,7 @@ let AuthBasicStrategy = class AuthBasicStrategy extends (0, _passport.PassportSt
46
46
  }
47
47
  if (userFromCache !== undefined) {
48
48
  // cached
49
- // warning: plainToInstance do not use constructor to instantiate class
49
+ // warning: plainToInstance do not use constructor to instantiate the class
50
50
  return (0, _classtransformer.plainToInstance)(_usermodel.UserModel, userFromCache);
51
51
  }
52
52
  const userFromDB = await this.authMethod.validateUser(loginOrEmail, password, req.ip, _scope.AUTH_SCOPE.WEBDAV);