@sync-in/server 1.3.9 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (294) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +5 -3
  3. package/environment/environment.dist.yaml +2 -0
  4. package/package.json +6 -6
  5. package/server/app.bootstrap.js +9 -0
  6. package/server/app.bootstrap.js.map +1 -1
  7. package/server/app.service.spec.js +44 -19
  8. package/server/app.service.spec.js.map +1 -1
  9. package/server/applications/comments/comments.controller.spec.js +103 -4
  10. package/server/applications/comments/comments.controller.spec.js.map +1 -1
  11. package/server/applications/comments/services/comments-manager.service.spec.js +409 -9
  12. package/server/applications/comments/services/comments-manager.service.spec.js.map +1 -1
  13. package/server/applications/files/adapters/files-indexer-mysql.service.spec.js +333 -0
  14. package/server/applications/files/adapters/files-indexer-mysql.service.spec.js.map +1 -0
  15. package/server/applications/files/constants/files.js +0 -23
  16. package/server/applications/files/constants/files.js.map +1 -1
  17. package/server/applications/files/constants/only-office.js +8 -0
  18. package/server/applications/files/constants/only-office.js.map +1 -1
  19. package/server/applications/files/constants/routes.js +6 -1
  20. package/server/applications/files/constants/routes.js.map +1 -1
  21. package/server/applications/files/files-only-office.controller.js +11 -0
  22. package/server/applications/files/files-only-office.controller.js.map +1 -1
  23. package/server/applications/files/files-only-office.controller.spec.js +97 -3
  24. package/server/applications/files/files-only-office.controller.spec.js.map +1 -1
  25. package/server/applications/files/files-tasks.controller.spec.js +91 -1
  26. package/server/applications/files/files-tasks.controller.spec.js.map +1 -1
  27. package/server/applications/files/files.config.js +5 -0
  28. package/server/applications/files/files.config.js.map +1 -1
  29. package/server/applications/files/files.controller.spec.js +268 -46
  30. package/server/applications/files/files.controller.spec.js.map +1 -1
  31. package/server/applications/files/guards/files-only-office.guard.spec.js +77 -1
  32. package/server/applications/files/guards/files-only-office.guard.spec.js.map +1 -1
  33. package/server/applications/files/guards/files-only-office.strategy.js +0 -1
  34. package/server/applications/files/guards/files-only-office.strategy.js.map +1 -1
  35. package/server/applications/files/services/files-only-office-manager.service.js +5 -0
  36. package/server/applications/files/services/files-only-office-manager.service.js.map +1 -1
  37. package/server/applications/links/links.controller.spec.js +91 -58
  38. package/server/applications/links/links.controller.spec.js.map +1 -1
  39. package/server/applications/links/services/links-manager.service.js +4 -6
  40. package/server/applications/links/services/links-manager.service.js.map +1 -1
  41. package/server/applications/links/services/links-manager.service.spec.js +378 -14
  42. package/server/applications/links/services/links-manager.service.spec.js.map +1 -1
  43. package/server/applications/links/services/links-queries.service.js +1 -1
  44. package/server/applications/links/services/links-queries.service.js.map +1 -1
  45. package/server/applications/notifications/notifications.controller.spec.js +56 -1
  46. package/server/applications/notifications/notifications.controller.spec.js.map +1 -1
  47. package/server/applications/notifications/services/notifications-manager.service.spec.js +461 -5
  48. package/server/applications/notifications/services/notifications-manager.service.spec.js.map +1 -1
  49. package/server/applications/shares/services/shares-manager.service.spec.js +590 -14
  50. package/server/applications/shares/services/shares-manager.service.spec.js.map +1 -1
  51. package/server/applications/spaces/guards/space.guard.spec.js +153 -18
  52. package/server/applications/spaces/guards/space.guard.spec.js.map +1 -1
  53. package/server/applications/spaces/services/spaces-browser.service.js +7 -7
  54. package/server/applications/spaces/services/spaces-browser.service.js.map +1 -1
  55. package/server/applications/spaces/services/spaces-manager.service.js +17 -17
  56. package/server/applications/spaces/services/spaces-manager.service.js.map +1 -1
  57. package/server/applications/sync/interceptors/sync-diff-gzip-body.interceptor.spec.js +120 -0
  58. package/server/applications/sync/interceptors/sync-diff-gzip-body.interceptor.spec.js.map +1 -0
  59. package/server/applications/sync/services/sync-clients-manager.service.spec.js +548 -8
  60. package/server/applications/sync/services/sync-clients-manager.service.spec.js.map +1 -1
  61. package/server/applications/sync/services/sync-manager.service.spec.js +837 -5
  62. package/server/applications/sync/services/sync-manager.service.spec.js.map +1 -1
  63. package/server/applications/sync/services/sync-paths-manager.service.spec.js +900 -7
  64. package/server/applications/sync/services/sync-paths-manager.service.spec.js.map +1 -1
  65. package/server/applications/sync/utils/routes.js +1 -1
  66. package/server/applications/sync/utils/routes.js.map +1 -1
  67. package/server/applications/users/guards/permissions.guard.js +4 -4
  68. package/server/applications/users/guards/permissions.guard.js.map +1 -1
  69. package/server/applications/users/guards/permissions.guard.spec.js +6 -6
  70. package/server/applications/users/guards/permissions.guard.spec.js.map +1 -1
  71. package/server/applications/users/guards/roles.guard.js +1 -1
  72. package/server/applications/users/guards/roles.guard.js.map +1 -1
  73. package/server/applications/users/models/user.model.js +1 -1
  74. package/server/applications/users/models/user.model.js.map +1 -1
  75. package/server/applications/users/services/admin-users-manager.service.js +22 -24
  76. package/server/applications/users/services/admin-users-manager.service.js.map +1 -1
  77. package/server/applications/users/services/admin-users-manager.service.spec.js +763 -17
  78. package/server/applications/users/services/admin-users-manager.service.spec.js.map +1 -1
  79. package/server/applications/users/services/users-manager.service.js +1 -1
  80. package/server/applications/users/services/users-manager.service.js.map +1 -1
  81. package/server/applications/users/services/users-manager.service.spec.js +938 -49
  82. package/server/applications/users/services/users-manager.service.spec.js.map +1 -1
  83. package/server/applications/webdav/decorators/if-header.decorator.js +4 -1
  84. package/server/applications/webdav/decorators/if-header.decorator.js.map +1 -1
  85. package/server/applications/webdav/filters/webdav.filter.spec.js +77 -0
  86. package/server/applications/webdav/filters/webdav.filter.spec.js.map +1 -0
  87. package/server/applications/webdav/guards/webdav-protocol.guard.js +3 -7
  88. package/server/applications/webdav/guards/webdav-protocol.guard.js.map +1 -1
  89. package/server/applications/webdav/guards/webdav-protocol.guard.spec.js +580 -0
  90. package/server/applications/webdav/guards/webdav-protocol.guard.spec.js.map +1 -0
  91. package/server/applications/webdav/services/webdav-methods.service.spec.js +1582 -3
  92. package/server/applications/webdav/services/webdav-methods.service.spec.js.map +1 -1
  93. package/server/applications/webdav/services/webdav-spaces.service.spec.js +390 -2
  94. package/server/applications/webdav/services/webdav-spaces.service.spec.js.map +1 -1
  95. package/server/applications/webdav/webdav.controller.js +2 -2
  96. package/server/applications/webdav/webdav.controller.js.map +1 -1
  97. package/server/authentication/guards/auth-basic.guard.js.map +1 -1
  98. package/server/authentication/guards/auth-basic.guard.spec.js +38 -2
  99. package/server/authentication/guards/auth-basic.guard.spec.js.map +1 -1
  100. package/server/authentication/guards/auth-basic.strategy.js +0 -1
  101. package/server/authentication/guards/auth-basic.strategy.js.map +1 -1
  102. package/server/authentication/guards/auth-digest.guard.js +1 -2
  103. package/server/authentication/guards/auth-digest.guard.js.map +1 -1
  104. package/server/authentication/guards/auth-local.guard.js.map +1 -1
  105. package/server/authentication/guards/auth-local.guard.spec.js +7 -5
  106. package/server/authentication/guards/auth-local.guard.spec.js.map +1 -1
  107. package/server/authentication/guards/auth-local.strategy.js +0 -1
  108. package/server/authentication/guards/auth-local.strategy.js.map +1 -1
  109. package/server/authentication/guards/auth-token-access.guard.spec.js +30 -0
  110. package/server/authentication/guards/auth-token-access.guard.spec.js.map +1 -1
  111. package/server/authentication/guards/auth-token-access.strategy.js +0 -1
  112. package/server/authentication/guards/auth-token-access.strategy.js.map +1 -1
  113. package/server/authentication/guards/auth-token-refresh.strategy.js +0 -1
  114. package/server/authentication/guards/auth-token-refresh.strategy.js.map +1 -1
  115. package/server/authentication/services/auth-methods/auth-method-database.service.js +1 -1
  116. package/server/authentication/services/auth-methods/auth-method-database.service.js.map +1 -1
  117. package/server/authentication/services/auth-methods/auth-method-database.service.spec.js +8 -6
  118. package/server/authentication/services/auth-methods/auth-method-database.service.spec.js.map +1 -1
  119. package/server/authentication/services/auth-methods/auth-method-ldap.service.js +2 -2
  120. package/server/authentication/services/auth-methods/auth-method-ldap.service.js.map +1 -1
  121. package/server/authentication/services/auth-methods/auth-method-ldap.service.spec.js +500 -5
  122. package/server/authentication/services/auth-methods/auth-method-ldap.service.spec.js.map +1 -1
  123. package/server/configuration/config.loader.js +0 -3
  124. package/server/configuration/config.loader.js.map +1 -1
  125. package/server/infrastructure/context/interceptors/context.interceptor.spec.js +135 -0
  126. package/server/infrastructure/context/interceptors/context.interceptor.spec.js.map +1 -0
  127. package/server/infrastructure/context/services/context-manager.service.spec.js +98 -0
  128. package/server/infrastructure/context/services/context-manager.service.spec.js.map +1 -0
  129. package/server/infrastructure/database/constants.js +0 -1
  130. package/server/infrastructure/database/constants.js.map +1 -1
  131. package/server/infrastructure/database/scripts/seed/usersgroups.js +3 -3
  132. package/server/infrastructure/database/scripts/seed/usersgroups.js.map +1 -1
  133. package/server/infrastructure/mailer/mailer.service.js +20 -19
  134. package/server/infrastructure/mailer/mailer.service.js.map +1 -1
  135. package/server/infrastructure/mailer/mailer.service.spec.js +176 -0
  136. package/server/infrastructure/mailer/mailer.service.spec.js.map +1 -0
  137. package/static/3rdpartylicenses.txt +26 -26
  138. package/static/assets/pdfjs/build/pdf.mjs +1177 -255
  139. package/static/assets/pdfjs/build/pdf.mjs.map +1 -1
  140. package/static/assets/pdfjs/build/pdf.sandbox.mjs +25 -2
  141. package/static/assets/pdfjs/build/pdf.sandbox.mjs.map +1 -1
  142. package/static/assets/pdfjs/build/pdf.worker.mjs +140 -16
  143. package/static/assets/pdfjs/build/pdf.worker.mjs.map +1 -1
  144. package/static/assets/pdfjs/version +1 -1
  145. package/static/assets/pdfjs/web/debugger.css +31 -0
  146. package/static/assets/pdfjs/web/debugger.mjs +144 -2
  147. package/static/assets/pdfjs/web/images/comment-editButton.svg +6 -1
  148. package/static/assets/pdfjs/web/locale/ach/viewer.ftl +0 -63
  149. package/static/assets/pdfjs/web/locale/af/viewer.ftl +0 -71
  150. package/static/assets/pdfjs/web/locale/an/viewer.ftl +0 -63
  151. package/static/assets/pdfjs/web/locale/ast/viewer.ftl +0 -60
  152. package/static/assets/pdfjs/web/locale/az/viewer.ftl +0 -63
  153. package/static/assets/pdfjs/web/locale/be/viewer.ftl +38 -0
  154. package/static/assets/pdfjs/web/locale/bg/viewer.ftl +0 -37
  155. package/static/assets/pdfjs/web/locale/bn/viewer.ftl +0 -63
  156. package/static/assets/pdfjs/web/locale/bo/viewer.ftl +0 -63
  157. package/static/assets/pdfjs/web/locale/br/viewer.ftl +0 -37
  158. package/static/assets/pdfjs/web/locale/brx/viewer.ftl +0 -63
  159. package/static/assets/pdfjs/web/locale/bs/viewer.ftl +22 -0
  160. package/static/assets/pdfjs/web/locale/ca/viewer.ftl +0 -54
  161. package/static/assets/pdfjs/web/locale/cak/viewer.ftl +0 -54
  162. package/static/assets/pdfjs/web/locale/ckb/viewer.ftl +0 -63
  163. package/static/assets/pdfjs/web/locale/cs/viewer.ftl +38 -0
  164. package/static/assets/pdfjs/web/locale/cy/viewer.ftl +38 -0
  165. package/static/assets/pdfjs/web/locale/da/viewer.ftl +38 -0
  166. package/static/assets/pdfjs/web/locale/de/viewer.ftl +38 -0
  167. package/static/assets/pdfjs/web/locale/dsb/viewer.ftl +38 -0
  168. package/static/assets/pdfjs/web/locale/el/viewer.ftl +38 -0
  169. package/static/assets/pdfjs/web/locale/en-CA/viewer.ftl +38 -0
  170. package/static/assets/pdfjs/web/locale/en-GB/viewer.ftl +38 -0
  171. package/static/assets/pdfjs/web/locale/en-US/viewer.ftl +25 -0
  172. package/static/assets/pdfjs/web/locale/eo/viewer.ftl +38 -0
  173. package/static/assets/pdfjs/web/locale/es-AR/viewer.ftl +38 -0
  174. package/static/assets/pdfjs/web/locale/es-CL/viewer.ftl +38 -0
  175. package/static/assets/pdfjs/web/locale/es-MX/viewer.ftl +0 -6
  176. package/static/assets/pdfjs/web/locale/et/viewer.ftl +0 -57
  177. package/static/assets/pdfjs/web/locale/fa/viewer.ftl +0 -37
  178. package/static/assets/pdfjs/web/locale/ff/viewer.ftl +0 -63
  179. package/static/assets/pdfjs/web/locale/fi/viewer.ftl +38 -0
  180. package/static/assets/pdfjs/web/locale/fr/viewer.ftl +38 -0
  181. package/static/assets/pdfjs/web/locale/fy-NL/viewer.ftl +38 -0
  182. package/static/assets/pdfjs/web/locale/ga-IE/viewer.ftl +0 -71
  183. package/static/assets/pdfjs/web/locale/gd/viewer.ftl +0 -54
  184. package/static/assets/pdfjs/web/locale/gl/viewer.ftl +8 -0
  185. package/static/assets/pdfjs/web/locale/gn/viewer.ftl +38 -0
  186. package/static/assets/pdfjs/web/locale/gu-IN/viewer.ftl +0 -63
  187. package/static/assets/pdfjs/web/locale/he/viewer.ftl +38 -0
  188. package/static/assets/pdfjs/web/locale/hi-IN/viewer.ftl +0 -60
  189. package/static/assets/pdfjs/web/locale/hsb/viewer.ftl +38 -0
  190. package/static/assets/pdfjs/web/locale/hu/viewer.ftl +38 -0
  191. package/static/assets/pdfjs/web/locale/hy-AM/viewer.ftl +0 -49
  192. package/static/assets/pdfjs/web/locale/hye/viewer.ftl +0 -60
  193. package/static/assets/pdfjs/web/locale/ia/viewer.ftl +38 -0
  194. package/static/assets/pdfjs/web/locale/is/viewer.ftl +0 -3
  195. package/static/assets/pdfjs/web/locale/it/viewer.ftl +31 -0
  196. package/static/assets/pdfjs/web/locale/ja/viewer.ftl +8 -0
  197. package/static/assets/pdfjs/web/locale/ka/viewer.ftl +48 -10
  198. package/static/assets/pdfjs/web/locale/kab/viewer.ftl +5 -0
  199. package/static/assets/pdfjs/web/locale/kk/viewer.ftl +8 -0
  200. package/static/assets/pdfjs/web/locale/km/viewer.ftl +0 -63
  201. package/static/assets/pdfjs/web/locale/kn/viewer.ftl +0 -71
  202. package/static/assets/pdfjs/web/locale/ko/viewer.ftl +38 -0
  203. package/static/assets/pdfjs/web/locale/lij/viewer.ftl +0 -63
  204. package/static/assets/pdfjs/web/locale/lo/viewer.ftl +0 -54
  205. package/static/assets/pdfjs/web/locale/lt/viewer.ftl +0 -60
  206. package/static/assets/pdfjs/web/locale/ltg/viewer.ftl +0 -63
  207. package/static/assets/pdfjs/web/locale/lv/viewer.ftl +0 -63
  208. package/static/assets/pdfjs/web/locale/meh/viewer.ftl +0 -75
  209. package/static/assets/pdfjs/web/locale/mk/viewer.ftl +0 -63
  210. package/static/assets/pdfjs/web/locale/ml/viewer.ftl +0 -3
  211. package/static/assets/pdfjs/web/locale/mr/viewer.ftl +0 -63
  212. package/static/assets/pdfjs/web/locale/ms/viewer.ftl +0 -63
  213. package/static/assets/pdfjs/web/locale/my/viewer.ftl +0 -71
  214. package/static/assets/pdfjs/web/locale/nb-NO/viewer.ftl +44 -6
  215. package/static/assets/pdfjs/web/locale/ne-NP/viewer.ftl +0 -71
  216. package/static/assets/pdfjs/web/locale/nl/viewer.ftl +38 -0
  217. package/static/assets/pdfjs/web/locale/nn-NO/viewer.ftl +45 -1
  218. package/static/assets/pdfjs/web/locale/oc/viewer.ftl +0 -31
  219. package/static/assets/pdfjs/web/locale/pa-IN/viewer.ftl +38 -0
  220. package/static/assets/pdfjs/web/locale/pl/viewer.ftl +39 -1
  221. package/static/assets/pdfjs/web/locale/pt-BR/viewer.ftl +38 -0
  222. package/static/assets/pdfjs/web/locale/ro/viewer.ftl +355 -1
  223. package/static/assets/pdfjs/web/locale/ru/viewer.ftl +38 -0
  224. package/static/assets/pdfjs/web/locale/sat/viewer.ftl +0 -54
  225. package/static/assets/pdfjs/web/locale/sc/viewer.ftl +0 -38
  226. package/static/assets/pdfjs/web/locale/scn/viewer.ftl +0 -92
  227. package/static/assets/pdfjs/web/locale/sco/viewer.ftl +0 -60
  228. package/static/assets/pdfjs/web/locale/si/viewer.ftl +0 -51
  229. package/static/assets/pdfjs/web/locale/sk/viewer.ftl +38 -0
  230. package/static/assets/pdfjs/web/locale/skr/viewer.ftl +0 -27
  231. package/static/assets/pdfjs/web/locale/sl/viewer.ftl +8 -0
  232. package/static/assets/pdfjs/web/locale/son/viewer.ftl +0 -71
  233. package/static/assets/pdfjs/web/locale/sr/viewer.ftl +0 -33
  234. package/static/assets/pdfjs/web/locale/sv-SE/viewer.ftl +38 -0
  235. package/static/assets/pdfjs/web/locale/szl/viewer.ftl +0 -63
  236. package/static/assets/pdfjs/web/locale/ta/viewer.ftl +0 -63
  237. package/static/assets/pdfjs/web/locale/te/viewer.ftl +0 -60
  238. package/static/assets/pdfjs/web/locale/tg/viewer.ftl +38 -0
  239. package/static/assets/pdfjs/web/locale/tl/viewer.ftl +0 -63
  240. package/static/assets/pdfjs/web/locale/tr/viewer.ftl +40 -2
  241. package/static/assets/pdfjs/web/locale/trs/viewer.ftl +0 -72
  242. package/static/assets/pdfjs/web/locale/ur/viewer.ftl +0 -60
  243. package/static/assets/pdfjs/web/locale/uz/viewer.ftl +0 -71
  244. package/static/assets/pdfjs/web/locale/vi/viewer.ftl +38 -0
  245. package/static/assets/pdfjs/web/locale/wo/viewer.ftl +0 -77
  246. package/static/assets/pdfjs/web/locale/xh/viewer.ftl +0 -71
  247. package/static/assets/pdfjs/web/locale/zh-CN/viewer.ftl +38 -0
  248. package/static/assets/pdfjs/web/locale/zh-TW/viewer.ftl +38 -0
  249. package/static/assets/pdfjs/web/viewer.css +649 -120
  250. package/static/assets/pdfjs/web/viewer.html +19 -0
  251. package/static/assets/pdfjs/web/viewer.mjs +489 -38
  252. package/static/assets/pdfjs/web/viewer.mjs.map +1 -1
  253. package/static/chunk-22EANI6R.js +1 -0
  254. package/static/{chunk-KFM544CA.js → chunk-2UWN7IQF.js} +1 -1
  255. package/static/{chunk-N3T57OCA.js → chunk-2VSPDSJS.js} +1 -1
  256. package/static/{chunk-HUWQHCUX.js → chunk-34UZ7SYI.js} +1 -1
  257. package/static/{chunk-MWFRZBJD.js → chunk-45UQJGGY.js} +1 -1
  258. package/static/{chunk-LYTD6AJE.js → chunk-5TEXH3LJ.js} +1 -1
  259. package/static/{chunk-4KESSWTF.js → chunk-66FMKVJX.js} +1 -1
  260. package/static/{chunk-XE5YHU5J.js → chunk-BIUNUYZ5.js} +1 -1
  261. package/static/chunk-CK4BY2NX.js +27 -0
  262. package/static/{chunk-QTW62OKJ.js → chunk-CSBDAY77.js} +1 -1
  263. package/static/{chunk-XUZSYWRF.js → chunk-CXXPLBDZ.js} +1 -1
  264. package/static/{chunk-ZTXJC5IC.js → chunk-EILQG525.js} +1 -1
  265. package/static/{chunk-FJFNDK67.js → chunk-ENWABUR4.js} +1 -1
  266. package/static/{chunk-WL65GYD5.js → chunk-FR4AOLYL.js} +4 -4
  267. package/static/chunk-HW2H3ISM.js +559 -0
  268. package/static/{chunk-BW5PQAKK.js → chunk-HYMDGBZL.js} +1 -1
  269. package/static/{chunk-WLPYIJFI.js → chunk-IML5UYQG.js} +1 -1
  270. package/static/{chunk-Z5X7LVMZ.js → chunk-IPSMJHMQ.js} +1 -1
  271. package/static/{chunk-3S4WNZ2T.js → chunk-JVCWYSNP.js} +1 -1
  272. package/static/{chunk-CLSVDV7J.js → chunk-KGPCIUD2.js} +1 -1
  273. package/static/{chunk-O4AQBQBF.js → chunk-KQZJSEM3.js} +1 -1
  274. package/static/{chunk-MK7WZG3F.js → chunk-NPEMJJIU.js} +1 -1
  275. package/static/{chunk-4TEHM3AS.js → chunk-OEFBC4GG.js} +1 -1
  276. package/static/{chunk-O67RFAWU.js → chunk-P734A3XZ.js} +1 -1
  277. package/static/{chunk-SRLMFJ7C.js → chunk-RASR4CK6.js} +1 -1
  278. package/static/{chunk-S5WXHO6D.js → chunk-RFMOUC22.js} +1 -1
  279. package/static/{chunk-TTQ37MUV.js → chunk-RSS6GYNE.js} +1 -1
  280. package/static/{chunk-3FX6ISDY.js → chunk-SBOQGGZX.js} +1 -1
  281. package/static/{chunk-NV2MEIWP.js → chunk-SJAFPXQV.js} +1 -1
  282. package/static/{chunk-PYSFXLMV.js → chunk-XTYGMF2V.js} +1 -1
  283. package/static/{chunk-ZFKCGL6X.js → chunk-YCWMV2YR.js} +1 -1
  284. package/static/{chunk-LB7B5RIV.js → chunk-YGD22MWQ.js} +1 -1
  285. package/static/{chunk-MTRNPGS4.js → chunk-ZC5NIT55.js} +1 -1
  286. package/static/{chunk-SKDQM65G.js → chunk-ZVY37DKS.js} +1 -1
  287. package/static/index.html +2 -2
  288. package/static/main-N5CZRHAO.js +7 -0
  289. package/static/styles-FYUSO6OJ.css +1 -0
  290. package/static/chunk-AY2GOSJ2.js +0 -24
  291. package/static/chunk-RSNLYAN6.js +0 -560
  292. package/static/chunk-ZZ3LHYOY.js +0 -1
  293. package/static/main-RREKR34B.js +0 -10
  294. package/static/styles-3DONJ2Z4.css +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/files/services/files-only-office-manager.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpService } from '@nestjs/axios'\nimport { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'\nimport { JwtService } from '@nestjs/jwt'\nimport { AxiosResponse } from 'axios'\nimport https from 'https'\nimport crypto from 'node:crypto'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { SERVER_NAME } from '../../../app.constants'\nimport { JwtIdentityPayload } from '../../../authentication/interfaces/jwt-payload.interface'\nimport { convertHumanTimeToSeconds, generateShortUUID } from '../../../common/functions'\nimport { configuration } from '../../../configuration/config.environment'\nimport { Cache } from '../../../infrastructure/cache/services/cache.service'\nimport { ContextManager } from '../../../infrastructure/context/services/context-manager.service'\nimport { HTTP_METHOD } from '../../applications.constants'\nimport { SPACE_OPERATION } from '../../spaces/constants/spaces'\nimport { FastifySpaceRequest } from '../../spaces/interfaces/space-request.interface'\nimport type { SpaceEnv } from '../../spaces/models/space-env.model'\nimport { haveSpaceEnvPermissions } from '../../spaces/utils/permissions'\nimport type { UserModel } from '../../users/models/user.model'\nimport { UsersManager } from '../../users/services/users-manager.service'\nimport { DEPTH, LOCK_SCOPE } from '../../webdav/constants/webdav'\nimport { CACHE_ONLY_OFFICE } from '../constants/cache'\nimport {\n ONLY_OFFICE_CONVERT_ERROR,\n ONLY_OFFICE_CONVERT_EXTENSIONS,\n ONLY_OFFICE_EXTENSIONS,\n ONLY_OFFICE_INTERNAL_URI,\n ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME\n} from '../constants/only-office'\nimport { API_FILES_ONLY_OFFICE_CALLBACK, API_FILES_ONLY_OFFICE_DOCUMENT } from '../constants/routes'\nimport type { FileProps } from '../interfaces/file-props.interface'\nimport { OnlyOfficeCallBack, OnlyOfficeConfig, OnlyOfficeConvertForm, OnlyOfficeReqConfig } from '../interfaces/only-office-config.interface'\nimport { copyFileContent, fileSize, getProps, isPathExists, isPathIsDir, removeFiles, uniqueFilePathFromDir, writeFromStream } from '../utils/files'\nimport { FilesLockManager } from './files-lock-manager.service'\nimport { FilesQueries } from './files-queries.service'\n\n@Injectable()\nexport class FilesOnlyOfficeManager {\n private logger = new Logger(FilesOnlyOfficeManager.name)\n private readonly externalOnlyOfficeServer = configuration.applications.files.onlyoffice.externalServer || null\n private readonly rejectUnauthorized: boolean = !configuration.applications.files.onlyoffice?.verifySSL\n private readonly convertUrl = this.externalOnlyOfficeServer ? `${this.externalOnlyOfficeServer}/ConvertService.ashx` : null\n private readonly expiration = convertHumanTimeToSeconds(configuration.auth.token.refresh.expiration)\n private readonly mobileRegex: RegExp = /android|webos|iphone|ipad|ipod|blackberry|windows phone|opera mini|iemobile|mobile/i\n\n constructor(\n private readonly http: HttpService,\n private readonly contextManager: ContextManager,\n private readonly cache: Cache,\n private readonly jwt: JwtService,\n private readonly usersManager: UsersManager,\n private readonly filesLockManager: FilesLockManager,\n private readonly filesQueries: FilesQueries\n ) {}\n\n async getSettings(user: UserModel, space: SpaceEnv, mode: 'edit' | 'view', req: FastifySpaceRequest): Promise<OnlyOfficeReqConfig> {\n if (!(await isPathExists(space.realPath))) {\n throw new HttpException('Document not found', HttpStatus.NOT_FOUND)\n }\n if (await isPathIsDir(space.realPath)) {\n throw new HttpException('Document must be a file', HttpStatus.BAD_REQUEST)\n }\n const fileExtension = path.extname(space.realPath).slice(1)\n if (!ONLY_OFFICE_EXTENSIONS.VIEWABLE.has(fileExtension) && !ONLY_OFFICE_EXTENSIONS.EDITABLE.has(fileExtension)) {\n throw new HttpException('Document not supported', HttpStatus.BAD_REQUEST)\n }\n if (mode === 'edit' && (!ONLY_OFFICE_EXTENSIONS.EDITABLE.has(fileExtension) || !haveSpaceEnvPermissions(space, SPACE_OPERATION.MODIFY))) {\n mode = 'view'\n }\n if (mode === 'edit') {\n // check lock conflicts\n try {\n await this.filesLockManager.checkConflicts(space.dbFile, DEPTH.RESOURCE, { userId: user.id, lockScope: LOCK_SCOPE.SHARED })\n } catch {\n throw new HttpException('The file is locked', HttpStatus.LOCKED)\n }\n }\n const isMobile: boolean = this.mobileRegex.test(req.headers['user-agent'])\n const fileProps: FileProps = await getProps(space.realPath, space.dbFile.path)\n const fileId: string = ((await this.filesQueries.getSpaceFileId(fileProps, space.dbFile)) || fileProps.id).toString()\n const userToken: string = await this.genUserToken(user)\n const fileUrl = this.getDocumentUrl(space, userToken)\n const callBackUrl = this.getCallBackUrl(space, userToken, fileId)\n const config: OnlyOfficeReqConfig = await this.genConfiguration(user, space, mode, fileId, fileUrl, fileExtension, callBackUrl, isMobile)\n config.config.token = await this.genPayloadToken(config.config)\n return config\n }\n\n async callBack(user: UserModel, space: SpaceEnv, token: string, fileId: string) {\n const callBackData: OnlyOfficeCallBack = await this.jwt.verifyAsync(token, { secret: configuration.applications.files.onlyoffice.secret })\n try {\n switch (callBackData.status) {\n case 1:\n await this.checkFileLock(user, space, callBackData)\n this.logger.debug(`document is being edited : ${space.url}`)\n break\n case 2:\n await this.checkFileLock(user, space, callBackData)\n if (callBackData.notmodified) {\n this.logger.debug(`document was edited but closed with no changes : ${space.url}`)\n } else {\n this.logger.debug(`document was edited but not saved (let's do it) : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n }\n await this.removeDocumentKey(fileId, space)\n break\n case 3:\n this.logger.error(`document cannot be saved, an error has occurred (try to save it) : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n break\n case 4:\n await this.removeFileLock(user.id, space)\n await this.removeDocumentKey(fileId, space)\n this.logger.debug(`document was closed with no changes : ${space.url}`)\n break\n case 6:\n this.logger.debug(`document is edited but save was requested : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n break\n case 7:\n this.logger.error(`document cannot be force saved, an error has occurred (try to save it) : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n break\n default:\n this.logger.error('unhandled case')\n }\n } catch (e) {\n this.logger.error(`${this.callBack.name} - ${e.message} : ${space.url}`)\n return { error: e.message }\n }\n return { error: 0 }\n }\n\n private async genConfiguration(\n user: UserModel,\n space: SpaceEnv,\n mode: 'edit' | 'view',\n fileId: string,\n fileUrl: string,\n fileExtension: string,\n callBackUrl: string,\n isMobile: boolean\n ): Promise<OnlyOfficeReqConfig> {\n const documentType = ONLY_OFFICE_EXTENSIONS.EDITABLE.get(fileExtension) || ONLY_OFFICE_EXTENSIONS.VIEWABLE.get(fileExtension)\n return {\n documentServerUrl: this.externalOnlyOfficeServer || `${this.contextManager.get('headerOriginUrl')}${ONLY_OFFICE_INTERNAL_URI}`,\n config: {\n type: isMobile ? 'mobile' : 'desktop',\n height: '100%',\n width: '100%',\n documentType: documentType,\n document: {\n title: path.basename(space.relativeUrl),\n fileType: fileExtension,\n key: await this.getDocumentKey(fileId),\n permissions: {\n download: true,\n edit: mode === 'edit',\n changeHistory: false,\n comment: true,\n fillForms: true,\n print: true,\n review: mode === 'edit'\n },\n url: fileUrl\n },\n editorConfig: {\n mode: mode,\n lang: 'en',\n region: 'en',\n callbackUrl: callBackUrl,\n user: { id: user.id.toString(), name: `${user.fullName} (${user.email})`, image: await this.usersManager.getAvatarBase64(user.login) },\n coEditing: {\n mode: 'fast',\n change: true\n },\n embedded: {\n embedUrl: fileUrl,\n saveUrl: fileUrl,\n shareUrl: fileUrl,\n toolbarDocked: 'top'\n },\n customization: {\n about: false,\n autosave: false,\n forcesave: true,\n zoom: documentType === 'slide' ? 60 : 90,\n help: false,\n features: { featuresTips: false },\n plugins: false\n }\n }\n }\n }\n }\n\n private getDocumentUrl(space: SpaceEnv, token: string): string {\n // user refresh token is used here for long session\n return `${this.contextManager.get('headerOriginUrl')}${API_FILES_ONLY_OFFICE_DOCUMENT}/${space.url}?${ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME}=${token}`\n }\n\n private getCallBackUrl(space: SpaceEnv, token: string, fileId: string): string {\n // user refresh token is used here for long session\n return `${this.contextManager.get('headerOriginUrl')}${API_FILES_ONLY_OFFICE_CALLBACK}/${space.url}?fid=${fileId}&${ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME}=${token}`\n }\n\n private genPayloadToken(payload: OnlyOfficeConfig | OnlyOfficeConvertForm): Promise<string> {\n return this.jwt.signAsync(payload, { secret: configuration.applications.files.onlyoffice.secret, expiresIn: 60 })\n }\n\n private genUserToken(user: UserModel): Promise<string> {\n // use refresh expiration to allow long session\n return this.jwt.signAsync(\n {\n identity: {\n id: user.id,\n login: user.login,\n email: user.email,\n fullName: user.fullName,\n role: user.role,\n applications: user.applications\n } satisfies JwtIdentityPayload\n },\n {\n secret: configuration.auth.token.access.secret,\n expiresIn: this.expiration\n }\n )\n }\n\n private async checkFileLock(user: UserModel, space: SpaceEnv, callBackData: OnlyOfficeCallBack) {\n for (const action of callBackData.actions) {\n if (action.type === 0) {\n // disconnect\n await this.removeFileLock(parseInt(action.userid), space)\n } else if (action.type === 1) {\n // connect\n await this.genFileLock(user, space)\n }\n }\n }\n\n private async genFileLock(user: UserModel, space: SpaceEnv): Promise<void> {\n const [ok, _fileLock] = await this.filesLockManager.create(user, space.dbFile, DEPTH.RESOURCE, this.expiration, {\n lockroot: null,\n locktoken: null,\n lockscope: LOCK_SCOPE.SHARED,\n owner: `${SERVER_NAME} - ${user.fullName} (${user.email})`\n })\n if (!ok) {\n throw new Error('document is locked')\n }\n }\n\n private async removeFileLock(userId: number, space: SpaceEnv): Promise<void> {\n for (const lock of await this.filesLockManager.getLocksByPath(space.dbFile)) {\n if (lock.owner.id === userId) {\n await this.filesLockManager.removeLock(lock.key)\n }\n }\n }\n\n private async removeDocumentKey(fileId: string, space: SpaceEnv): Promise<void> {\n if (!(await this.filesLockManager.isPathLocked(space.dbFile))) {\n const cacheKey = this.getCacheKey(fileId)\n const r = await this.cache.del(cacheKey)\n this.logger.debug(`${this.removeDocumentKey.name} - ${cacheKey} ${r ? '' : 'not'} removed`)\n }\n }\n\n private async getDocumentKey(fileId: string): Promise<string> {\n const cacheKey = this.getCacheKey(fileId)\n const existingDocKey: string = await this.cache.get(cacheKey)\n if (existingDocKey) {\n return existingDocKey\n }\n const docKey = generateShortUUID(16)\n await this.cache.set(cacheKey, docKey, this.expiration)\n this.logger.debug(`${this.getDocumentKey.name} - ${cacheKey} (${docKey}) created`)\n return docKey\n }\n\n private async saveDocument(space: SpaceEnv, url: string): Promise<void> {\n /* url format:\n https://onlyoffice-server.com/cache/files/data/-33120641_7158/output.pptx/output.pptx\n ?md5=duFHKC-5d47s-RRcYn3hAw&expires=1739400549&shardkey=-33120641&filename=output.pptx\n */\n const urlParams = new URLSearchParams(url.split('?').at(-1))\n // it is not the md5 of the file but a md5 generated by the combination of the elements of the url\n const md5: string = urlParams.get('md5')\n const tmpFilePath = await uniqueFilePathFromDir(path.join(os.tmpdir(), `${md5}-${urlParams.get('filename')}`))\n\n // convert remote file to the local file with the current extension if these extensions aren't equal\n const localExtension = path.extname(space.realPath).slice(1)\n const remoteExtension = path.extname(urlParams.get('filename')).slice(1)\n\n let downloadUrl: string\n if (localExtension !== remoteExtension && !ONLY_OFFICE_CONVERT_EXTENSIONS.ALLOW_AUTO.has(localExtension)) {\n if (ONLY_OFFICE_CONVERT_EXTENSIONS.FROM.has(remoteExtension) && ONLY_OFFICE_CONVERT_EXTENSIONS.TO.has(localExtension)) {\n downloadUrl = await this.convertDocument(urlParams.get('shardkey'), url, remoteExtension, localExtension, space.url)\n } else {\n throw new Error(`document cannot be converted from ${remoteExtension} -> ${localExtension} : ${space.url}`)\n }\n } else {\n downloadUrl = url\n }\n\n // download file\n let res: AxiosResponse\n try {\n res = await this.http.axiosRef({\n method: HTTP_METHOD.GET,\n url: downloadUrl,\n responseType: 'stream',\n httpsAgent: new https.Agent({ rejectUnauthorized: this.rejectUnauthorized })\n })\n await writeFromStream(tmpFilePath, res.data)\n } catch (e) {\n throw new Error(`unable to get document : ${e.message}`)\n }\n\n // try to verify the downloaded size\n const contentLength = parseInt(res.headers['content-length'], 10)\n if (!isNaN(contentLength)) {\n if (contentLength === 0) {\n this.logger.debug(`${this.saveDocument.name} - content length is 0 : ${space.url}`)\n return\n }\n const tmpFileSize = await fileSize(tmpFilePath)\n if (tmpFileSize !== contentLength) {\n throw new Error(`document size differs (${tmpFileSize} != ${contentLength})`)\n }\n }\n // copy contents to avoid inode changes (fileId in some cases)\n try {\n await copyFileContent(tmpFilePath, space.realPath)\n await removeFiles(tmpFilePath)\n } catch (e) {\n throw new Error(`unable to save document : ${e.message}`)\n }\n }\n\n private async convertDocument(id: string, url: string, fileType: string, outputType: string, spaceUrl: string): Promise<string> {\n const key: string = `${id}-${crypto.randomBytes(20).toString('hex')}`.slice(0, 20).replace('-', '_')\n const payload: OnlyOfficeConvertForm = {\n key: key,\n url: url,\n filetype: fileType,\n outputtype: outputType,\n async: false\n }\n payload.token = await this.genPayloadToken(payload)\n let result: { fileUrl?: string; fileType?: string; endConvert?: boolean; error?: number }\n try {\n const res: AxiosResponse = await this.http.axiosRef({\n method: HTTP_METHOD.POST,\n url: this.convertUrl,\n data: payload,\n httpsAgent: new https.Agent({ rejectUnauthorized: this.rejectUnauthorized })\n })\n result = res.data\n } catch (e) {\n throw new Error(`convert failed with status : ${e.response.status}`)\n }\n if (result.error) {\n throw new Error(`convert failed with reason : ${ONLY_OFFICE_CONVERT_ERROR.get(result.error)}`)\n }\n if (result.endConvert) {\n this.logger.log(`${this.convertDocument.name} - ${fileType} -> ${outputType} : ${spaceUrl}`)\n return result.fileUrl\n }\n }\n\n private getCacheKey(fileId: string): string {\n return `${CACHE_ONLY_OFFICE}|${fileId}`\n }\n}\n"],"names":["FilesOnlyOfficeManager","getSettings","user","space","mode","req","isPathExists","realPath","HttpException","HttpStatus","NOT_FOUND","isPathIsDir","BAD_REQUEST","fileExtension","path","extname","slice","ONLY_OFFICE_EXTENSIONS","VIEWABLE","has","EDITABLE","haveSpaceEnvPermissions","SPACE_OPERATION","MODIFY","filesLockManager","checkConflicts","dbFile","DEPTH","RESOURCE","userId","id","lockScope","LOCK_SCOPE","SHARED","LOCKED","isMobile","mobileRegex","test","headers","fileProps","getProps","fileId","filesQueries","getSpaceFileId","toString","userToken","genUserToken","fileUrl","getDocumentUrl","callBackUrl","getCallBackUrl","config","genConfiguration","token","genPayloadToken","callBack","callBackData","jwt","verifyAsync","secret","configuration","applications","files","onlyoffice","status","checkFileLock","logger","debug","url","notmodified","saveDocument","removeDocumentKey","error","removeFileLock","e","name","message","documentType","get","documentServerUrl","externalOnlyOfficeServer","contextManager","ONLY_OFFICE_INTERNAL_URI","type","height","width","document","title","basename","relativeUrl","fileType","key","getDocumentKey","permissions","download","edit","changeHistory","comment","fillForms","print","review","editorConfig","lang","region","callbackUrl","fullName","email","image","usersManager","getAvatarBase64","login","coEditing","change","embedded","embedUrl","saveUrl","shareUrl","toolbarDocked","customization","about","autosave","forcesave","zoom","help","features","featuresTips","plugins","API_FILES_ONLY_OFFICE_DOCUMENT","ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME","API_FILES_ONLY_OFFICE_CALLBACK","payload","signAsync","expiresIn","identity","role","auth","access","expiration","action","actions","parseInt","userid","genFileLock","ok","_fileLock","create","lockroot","locktoken","lockscope","owner","SERVER_NAME","Error","lock","getLocksByPath","removeLock","isPathLocked","cacheKey","getCacheKey","r","cache","del","existingDocKey","docKey","generateShortUUID","set","urlParams","URLSearchParams","split","at","md5","tmpFilePath","uniqueFilePathFromDir","join","os","tmpdir","localExtension","remoteExtension","downloadUrl","ONLY_OFFICE_CONVERT_EXTENSIONS","ALLOW_AUTO","FROM","TO","convertDocument","res","http","axiosRef","method","HTTP_METHOD","GET","responseType","httpsAgent","https","Agent","rejectUnauthorized","writeFromStream","data","contentLength","isNaN","tmpFileSize","fileSize","copyFileContent","removeFiles","outputType","spaceUrl","crypto","randomBytes","replace","filetype","outputtype","async","result","POST","convertUrl","response","ONLY_OFFICE_CONVERT_ERROR","endConvert","log","CACHE_ONLY_OFFICE","Logger","externalServer","verifySSL","convertHumanTimeToSeconds","refresh"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/files/services/files-only-office-manager.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpService } from '@nestjs/axios'\nimport { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'\nimport { JwtService } from '@nestjs/jwt'\nimport { AxiosResponse } from 'axios'\nimport https from 'https'\nimport crypto from 'node:crypto'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { SERVER_NAME } from '../../../app.constants'\nimport { JwtIdentityPayload } from '../../../authentication/interfaces/jwt-payload.interface'\nimport { convertHumanTimeToSeconds, generateShortUUID } from '../../../common/functions'\nimport { configuration } from '../../../configuration/config.environment'\nimport { Cache } from '../../../infrastructure/cache/services/cache.service'\nimport { ContextManager } from '../../../infrastructure/context/services/context-manager.service'\nimport { HTTP_METHOD } from '../../applications.constants'\nimport { SPACE_OPERATION } from '../../spaces/constants/spaces'\nimport { FastifySpaceRequest } from '../../spaces/interfaces/space-request.interface'\nimport type { SpaceEnv } from '../../spaces/models/space-env.model'\nimport { haveSpaceEnvPermissions } from '../../spaces/utils/permissions'\nimport type { UserModel } from '../../users/models/user.model'\nimport { UsersManager } from '../../users/services/users-manager.service'\nimport { DEPTH, LOCK_SCOPE } from '../../webdav/constants/webdav'\nimport { CACHE_ONLY_OFFICE } from '../constants/cache'\nimport {\n ONLY_OFFICE_CONVERT_ERROR,\n ONLY_OFFICE_CONVERT_EXTENSIONS,\n ONLY_OFFICE_EXTENSIONS,\n ONLY_OFFICE_INTERNAL_URI,\n ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME\n} from '../constants/only-office'\nimport { API_FILES_ONLY_OFFICE_CALLBACK, API_FILES_ONLY_OFFICE_DOCUMENT } from '../constants/routes'\nimport type { FileProps } from '../interfaces/file-props.interface'\nimport { OnlyOfficeCallBack, OnlyOfficeConfig, OnlyOfficeConvertForm, OnlyOfficeReqConfig } from '../interfaces/only-office-config.interface'\nimport { copyFileContent, fileSize, getProps, isPathExists, isPathIsDir, removeFiles, uniqueFilePathFromDir, writeFromStream } from '../utils/files'\nimport { FilesLockManager } from './files-lock-manager.service'\nimport { FilesQueries } from './files-queries.service'\n\n@Injectable()\nexport class FilesOnlyOfficeManager {\n private logger = new Logger(FilesOnlyOfficeManager.name)\n private readonly externalOnlyOfficeServer = configuration.applications.files.onlyoffice.externalServer || null\n private readonly rejectUnauthorized: boolean = !configuration.applications.files.onlyoffice?.verifySSL\n private readonly convertUrl = this.externalOnlyOfficeServer ? `${this.externalOnlyOfficeServer}/ConvertService.ashx` : null\n private readonly expiration = convertHumanTimeToSeconds(configuration.auth.token.refresh.expiration)\n private readonly mobileRegex: RegExp = /android|webos|iphone|ipad|ipod|blackberry|windows phone|opera mini|iemobile|mobile/i\n\n constructor(\n private readonly http: HttpService,\n private readonly contextManager: ContextManager,\n private readonly cache: Cache,\n private readonly jwt: JwtService,\n private readonly usersManager: UsersManager,\n private readonly filesLockManager: FilesLockManager,\n private readonly filesQueries: FilesQueries\n ) {}\n\n getStatus(): { enabled: boolean } {\n return { enabled: configuration.applications.files.onlyoffice.enabled }\n }\n\n async getSettings(user: UserModel, space: SpaceEnv, mode: 'edit' | 'view', req: FastifySpaceRequest): Promise<OnlyOfficeReqConfig> {\n if (!(await isPathExists(space.realPath))) {\n throw new HttpException('Document not found', HttpStatus.NOT_FOUND)\n }\n if (await isPathIsDir(space.realPath)) {\n throw new HttpException('Document must be a file', HttpStatus.BAD_REQUEST)\n }\n const fileExtension = path.extname(space.realPath).slice(1)\n if (!ONLY_OFFICE_EXTENSIONS.VIEWABLE.has(fileExtension) && !ONLY_OFFICE_EXTENSIONS.EDITABLE.has(fileExtension)) {\n throw new HttpException('Document not supported', HttpStatus.BAD_REQUEST)\n }\n if (mode === 'edit' && (!ONLY_OFFICE_EXTENSIONS.EDITABLE.has(fileExtension) || !haveSpaceEnvPermissions(space, SPACE_OPERATION.MODIFY))) {\n mode = 'view'\n }\n if (mode === 'edit') {\n // check lock conflicts\n try {\n await this.filesLockManager.checkConflicts(space.dbFile, DEPTH.RESOURCE, { userId: user.id, lockScope: LOCK_SCOPE.SHARED })\n } catch {\n throw new HttpException('The file is locked', HttpStatus.LOCKED)\n }\n }\n const isMobile: boolean = this.mobileRegex.test(req.headers['user-agent'])\n const fileProps: FileProps = await getProps(space.realPath, space.dbFile.path)\n const fileId: string = ((await this.filesQueries.getSpaceFileId(fileProps, space.dbFile)) || fileProps.id).toString()\n const userToken: string = await this.genUserToken(user)\n const fileUrl = this.getDocumentUrl(space, userToken)\n const callBackUrl = this.getCallBackUrl(space, userToken, fileId)\n const config: OnlyOfficeReqConfig = await this.genConfiguration(user, space, mode, fileId, fileUrl, fileExtension, callBackUrl, isMobile)\n config.config.token = await this.genPayloadToken(config.config)\n return config\n }\n\n async callBack(user: UserModel, space: SpaceEnv, token: string, fileId: string) {\n const callBackData: OnlyOfficeCallBack = await this.jwt.verifyAsync(token, { secret: configuration.applications.files.onlyoffice.secret })\n try {\n switch (callBackData.status) {\n case 1:\n await this.checkFileLock(user, space, callBackData)\n this.logger.debug(`document is being edited : ${space.url}`)\n break\n case 2:\n await this.checkFileLock(user, space, callBackData)\n if (callBackData.notmodified) {\n this.logger.debug(`document was edited but closed with no changes : ${space.url}`)\n } else {\n this.logger.debug(`document was edited but not saved (let's do it) : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n }\n await this.removeDocumentKey(fileId, space)\n break\n case 3:\n this.logger.error(`document cannot be saved, an error has occurred (try to save it) : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n break\n case 4:\n await this.removeFileLock(user.id, space)\n await this.removeDocumentKey(fileId, space)\n this.logger.debug(`document was closed with no changes : ${space.url}`)\n break\n case 6:\n this.logger.debug(`document is edited but save was requested : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n break\n case 7:\n this.logger.error(`document cannot be force saved, an error has occurred (try to save it) : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n break\n default:\n this.logger.error('unhandled case')\n }\n } catch (e) {\n this.logger.error(`${this.callBack.name} - ${e.message} : ${space.url}`)\n return { error: e.message }\n }\n return { error: 0 }\n }\n\n private async genConfiguration(\n user: UserModel,\n space: SpaceEnv,\n mode: 'edit' | 'view',\n fileId: string,\n fileUrl: string,\n fileExtension: string,\n callBackUrl: string,\n isMobile: boolean\n ): Promise<OnlyOfficeReqConfig> {\n const documentType = ONLY_OFFICE_EXTENSIONS.EDITABLE.get(fileExtension) || ONLY_OFFICE_EXTENSIONS.VIEWABLE.get(fileExtension)\n return {\n documentServerUrl: this.externalOnlyOfficeServer || `${this.contextManager.get('headerOriginUrl')}${ONLY_OFFICE_INTERNAL_URI}`,\n config: {\n type: isMobile ? 'mobile' : 'desktop',\n height: '100%',\n width: '100%',\n documentType: documentType,\n document: {\n title: path.basename(space.relativeUrl),\n fileType: fileExtension,\n key: await this.getDocumentKey(fileId),\n permissions: {\n download: true,\n edit: mode === 'edit',\n changeHistory: false,\n comment: true,\n fillForms: true,\n print: true,\n review: mode === 'edit'\n },\n url: fileUrl\n },\n editorConfig: {\n mode: mode,\n lang: 'en',\n region: 'en',\n callbackUrl: callBackUrl,\n user: { id: user.id.toString(), name: `${user.fullName} (${user.email})`, image: await this.usersManager.getAvatarBase64(user.login) },\n coEditing: {\n mode: 'fast',\n change: true\n },\n embedded: {\n embedUrl: fileUrl,\n saveUrl: fileUrl,\n shareUrl: fileUrl,\n toolbarDocked: 'top'\n },\n customization: {\n about: false,\n autosave: false,\n forcesave: true,\n zoom: documentType === 'slide' ? 60 : 90,\n help: false,\n features: { featuresTips: false },\n plugins: false\n }\n }\n }\n }\n }\n\n private getDocumentUrl(space: SpaceEnv, token: string): string {\n // user refresh token is used here for long session\n return `${this.contextManager.get('headerOriginUrl')}${API_FILES_ONLY_OFFICE_DOCUMENT}/${space.url}?${ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME}=${token}`\n }\n\n private getCallBackUrl(space: SpaceEnv, token: string, fileId: string): string {\n // user refresh token is used here for long session\n return `${this.contextManager.get('headerOriginUrl')}${API_FILES_ONLY_OFFICE_CALLBACK}/${space.url}?fid=${fileId}&${ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME}=${token}`\n }\n\n private genPayloadToken(payload: OnlyOfficeConfig | OnlyOfficeConvertForm): Promise<string> {\n return this.jwt.signAsync(payload, { secret: configuration.applications.files.onlyoffice.secret, expiresIn: 60 })\n }\n\n private genUserToken(user: UserModel): Promise<string> {\n // use refresh expiration to allow long session\n return this.jwt.signAsync(\n {\n identity: {\n id: user.id,\n login: user.login,\n email: user.email,\n fullName: user.fullName,\n role: user.role,\n applications: user.applications\n } satisfies JwtIdentityPayload\n },\n {\n secret: configuration.auth.token.access.secret,\n expiresIn: this.expiration\n }\n )\n }\n\n private async checkFileLock(user: UserModel, space: SpaceEnv, callBackData: OnlyOfficeCallBack) {\n for (const action of callBackData.actions) {\n if (action.type === 0) {\n // disconnect\n await this.removeFileLock(parseInt(action.userid), space)\n } else if (action.type === 1) {\n // connect\n await this.genFileLock(user, space)\n }\n }\n }\n\n private async genFileLock(user: UserModel, space: SpaceEnv): Promise<void> {\n const [ok, _fileLock] = await this.filesLockManager.create(user, space.dbFile, DEPTH.RESOURCE, this.expiration, {\n lockroot: null,\n locktoken: null,\n lockscope: LOCK_SCOPE.SHARED,\n owner: `${SERVER_NAME} - ${user.fullName} (${user.email})`\n })\n if (!ok) {\n throw new Error('document is locked')\n }\n }\n\n private async removeFileLock(userId: number, space: SpaceEnv): Promise<void> {\n for (const lock of await this.filesLockManager.getLocksByPath(space.dbFile)) {\n if (lock.owner.id === userId) {\n await this.filesLockManager.removeLock(lock.key)\n }\n }\n }\n\n private async removeDocumentKey(fileId: string, space: SpaceEnv): Promise<void> {\n if (!(await this.filesLockManager.isPathLocked(space.dbFile))) {\n const cacheKey = this.getCacheKey(fileId)\n const r = await this.cache.del(cacheKey)\n this.logger.debug(`${this.removeDocumentKey.name} - ${cacheKey} ${r ? '' : 'not'} removed`)\n }\n }\n\n private async getDocumentKey(fileId: string): Promise<string> {\n const cacheKey = this.getCacheKey(fileId)\n const existingDocKey: string = await this.cache.get(cacheKey)\n if (existingDocKey) {\n return existingDocKey\n }\n const docKey = generateShortUUID(16)\n await this.cache.set(cacheKey, docKey, this.expiration)\n this.logger.debug(`${this.getDocumentKey.name} - ${cacheKey} (${docKey}) created`)\n return docKey\n }\n\n private async saveDocument(space: SpaceEnv, url: string): Promise<void> {\n /* url format:\n https://onlyoffice-server.com/cache/files/data/-33120641_7158/output.pptx/output.pptx\n ?md5=duFHKC-5d47s-RRcYn3hAw&expires=1739400549&shardkey=-33120641&filename=output.pptx\n */\n const urlParams = new URLSearchParams(url.split('?').at(-1))\n // it is not the md5 of the file but a md5 generated by the combination of the elements of the url\n const md5: string = urlParams.get('md5')\n const tmpFilePath = await uniqueFilePathFromDir(path.join(os.tmpdir(), `${md5}-${urlParams.get('filename')}`))\n\n // convert remote file to the local file with the current extension if these extensions aren't equal\n const localExtension = path.extname(space.realPath).slice(1)\n const remoteExtension = path.extname(urlParams.get('filename')).slice(1)\n\n let downloadUrl: string\n if (localExtension !== remoteExtension && !ONLY_OFFICE_CONVERT_EXTENSIONS.ALLOW_AUTO.has(localExtension)) {\n if (ONLY_OFFICE_CONVERT_EXTENSIONS.FROM.has(remoteExtension) && ONLY_OFFICE_CONVERT_EXTENSIONS.TO.has(localExtension)) {\n downloadUrl = await this.convertDocument(urlParams.get('shardkey'), url, remoteExtension, localExtension, space.url)\n } else {\n throw new Error(`document cannot be converted from ${remoteExtension} -> ${localExtension} : ${space.url}`)\n }\n } else {\n downloadUrl = url\n }\n\n // download file\n let res: AxiosResponse\n try {\n res = await this.http.axiosRef({\n method: HTTP_METHOD.GET,\n url: downloadUrl,\n responseType: 'stream',\n httpsAgent: new https.Agent({ rejectUnauthorized: this.rejectUnauthorized })\n })\n await writeFromStream(tmpFilePath, res.data)\n } catch (e) {\n throw new Error(`unable to get document : ${e.message}`)\n }\n\n // try to verify the downloaded size\n const contentLength = parseInt(res.headers['content-length'], 10)\n if (!isNaN(contentLength)) {\n if (contentLength === 0) {\n this.logger.debug(`${this.saveDocument.name} - content length is 0 : ${space.url}`)\n return\n }\n const tmpFileSize = await fileSize(tmpFilePath)\n if (tmpFileSize !== contentLength) {\n throw new Error(`document size differs (${tmpFileSize} != ${contentLength})`)\n }\n }\n // copy contents to avoid inode changes (fileId in some cases)\n try {\n await copyFileContent(tmpFilePath, space.realPath)\n await removeFiles(tmpFilePath)\n } catch (e) {\n throw new Error(`unable to save document : ${e.message}`)\n }\n }\n\n private async convertDocument(id: string, url: string, fileType: string, outputType: string, spaceUrl: string): Promise<string> {\n const key: string = `${id}-${crypto.randomBytes(20).toString('hex')}`.slice(0, 20).replace('-', '_')\n const payload: OnlyOfficeConvertForm = {\n key: key,\n url: url,\n filetype: fileType,\n outputtype: outputType,\n async: false\n }\n payload.token = await this.genPayloadToken(payload)\n let result: { fileUrl?: string; fileType?: string; endConvert?: boolean; error?: number }\n try {\n const res: AxiosResponse = await this.http.axiosRef({\n method: HTTP_METHOD.POST,\n url: this.convertUrl,\n data: payload,\n httpsAgent: new https.Agent({ rejectUnauthorized: this.rejectUnauthorized })\n })\n result = res.data\n } catch (e) {\n throw new Error(`convert failed with status : ${e.response.status}`)\n }\n if (result.error) {\n throw new Error(`convert failed with reason : ${ONLY_OFFICE_CONVERT_ERROR.get(result.error)}`)\n }\n if (result.endConvert) {\n this.logger.log(`${this.convertDocument.name} - ${fileType} -> ${outputType} : ${spaceUrl}`)\n return result.fileUrl\n }\n }\n\n private getCacheKey(fileId: string): string {\n return `${CACHE_ONLY_OFFICE}|${fileId}`\n }\n}\n"],"names":["FilesOnlyOfficeManager","getStatus","enabled","configuration","applications","files","onlyoffice","getSettings","user","space","mode","req","isPathExists","realPath","HttpException","HttpStatus","NOT_FOUND","isPathIsDir","BAD_REQUEST","fileExtension","path","extname","slice","ONLY_OFFICE_EXTENSIONS","VIEWABLE","has","EDITABLE","haveSpaceEnvPermissions","SPACE_OPERATION","MODIFY","filesLockManager","checkConflicts","dbFile","DEPTH","RESOURCE","userId","id","lockScope","LOCK_SCOPE","SHARED","LOCKED","isMobile","mobileRegex","test","headers","fileProps","getProps","fileId","filesQueries","getSpaceFileId","toString","userToken","genUserToken","fileUrl","getDocumentUrl","callBackUrl","getCallBackUrl","config","genConfiguration","token","genPayloadToken","callBack","callBackData","jwt","verifyAsync","secret","status","checkFileLock","logger","debug","url","notmodified","saveDocument","removeDocumentKey","error","removeFileLock","e","name","message","documentType","get","documentServerUrl","externalOnlyOfficeServer","contextManager","ONLY_OFFICE_INTERNAL_URI","type","height","width","document","title","basename","relativeUrl","fileType","key","getDocumentKey","permissions","download","edit","changeHistory","comment","fillForms","print","review","editorConfig","lang","region","callbackUrl","fullName","email","image","usersManager","getAvatarBase64","login","coEditing","change","embedded","embedUrl","saveUrl","shareUrl","toolbarDocked","customization","about","autosave","forcesave","zoom","help","features","featuresTips","plugins","API_FILES_ONLY_OFFICE_DOCUMENT","ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME","API_FILES_ONLY_OFFICE_CALLBACK","payload","signAsync","expiresIn","identity","role","auth","access","expiration","action","actions","parseInt","userid","genFileLock","ok","_fileLock","create","lockroot","locktoken","lockscope","owner","SERVER_NAME","Error","lock","getLocksByPath","removeLock","isPathLocked","cacheKey","getCacheKey","r","cache","del","existingDocKey","docKey","generateShortUUID","set","urlParams","URLSearchParams","split","at","md5","tmpFilePath","uniqueFilePathFromDir","join","os","tmpdir","localExtension","remoteExtension","downloadUrl","ONLY_OFFICE_CONVERT_EXTENSIONS","ALLOW_AUTO","FROM","TO","convertDocument","res","http","axiosRef","method","HTTP_METHOD","GET","responseType","httpsAgent","https","Agent","rejectUnauthorized","writeFromStream","data","contentLength","isNaN","tmpFileSize","fileSize","copyFileContent","removeFiles","outputType","spaceUrl","crypto","randomBytes","replace","filetype","outputtype","async","result","POST","convertUrl","response","ONLY_OFFICE_CONVERT_ERROR","endConvert","log","CACHE_ONLY_OFFICE","Logger","externalServer","verifySSL","convertHumanTimeToSeconds","refresh"],"mappings":"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"}
@@ -6,83 +6,116 @@
6
6
  Object.defineProperty(exports, "__esModule", {
7
7
  value: true
8
8
  });
9
- const _axios = require("@nestjs/axios");
10
- const _config = require("@nestjs/config");
11
- const _jwt = require("@nestjs/jwt");
9
+ const _common = require("@nestjs/common");
12
10
  const _testing = require("@nestjs/testing");
13
- const _authmanagerservice = require("../../authentication/services/auth-manager.service");
14
- const _cacheservice = require("../../infrastructure/cache/services/cache.service");
15
- const _contextmanagerservice = require("../../infrastructure/context/services/context-manager.service");
16
- const _constants = require("../../infrastructure/database/constants");
17
- const _fileslockmanagerservice = require("../files/services/files-lock-manager.service");
18
- const _filesmanagerservice = require("../files/services/files-manager.service");
19
- const _filesqueriesservice = require("../files/services/files-queries.service");
20
- const _notificationsmanagerservice = require("../notifications/services/notifications-manager.service");
21
- const _sharesmanagerservice = require("../shares/services/shares-manager.service");
22
- const _sharesqueriesservice = require("../shares/services/shares-queries.service");
23
- const _spacesmanagerservice = require("../spaces/services/spaces-manager.service");
24
- const _spacesqueriesservice = require("../spaces/services/spaces-queries.service");
25
- const _adminusersmanagerservice = require("../users/services/admin-users-manager.service");
26
- const _adminusersqueriesservice = require("../users/services/admin-users-queries.service");
27
- const _usersmanagerservice = require("../users/services/users-manager.service");
28
- const _usersqueriesservice = require("../users/services/users-queries.service");
29
11
  const _linkscontroller = require("./links.controller");
30
12
  const _linksmanagerservice = require("./services/links-manager.service");
31
- const _linksqueriesservice = require("./services/links-queries.service");
32
13
  describe(_linkscontroller.LinksController.name, ()=>{
33
14
  let controller;
15
+ let linksManager;
34
16
  beforeAll(async ()=>{
17
+ linksManager = {
18
+ linkValidation: jest.fn(),
19
+ linkAccess: jest.fn(),
20
+ linkAuthentication: jest.fn()
21
+ };
35
22
  const module = await _testing.Test.createTestingModule({
36
23
  controllers: [
37
24
  _linkscontroller.LinksController
38
25
  ],
39
26
  providers: [
40
27
  {
41
- provide: _constants.DB_TOKEN_PROVIDER,
42
- useValue: {}
43
- },
44
- {
45
- provide: _cacheservice.Cache,
46
- useValue: {}
47
- },
48
- {
49
- provide: _contextmanagerservice.ContextManager,
50
- useValue: {}
51
- },
52
- {
53
- provide: _notificationsmanagerservice.NotificationsManager,
54
- useValue: {}
55
- },
56
- {
57
- provide: _axios.HttpService,
58
- useValue: {}
59
- },
60
- {
61
- provide: _fileslockmanagerservice.FilesLockManager,
62
- useValue: {}
63
- },
64
- _config.ConfigService,
65
- _jwt.JwtService,
66
- _authmanagerservice.AuthManager,
67
- _linksmanagerservice.LinksManager,
68
- _linksqueriesservice.LinksQueries,
69
- _usersmanagerservice.UsersManager,
70
- _usersqueriesservice.UsersQueries,
71
- _adminusersmanagerservice.AdminUsersManager,
72
- _adminusersqueriesservice.AdminUsersQueries,
73
- _spacesmanagerservice.SpacesManager,
74
- _spacesqueriesservice.SpacesQueries,
75
- _filesmanagerservice.FilesManager,
76
- _filesqueriesservice.FilesQueries,
77
- _sharesmanagerservice.SharesManager,
78
- _sharesqueriesservice.SharesQueries
28
+ provide: _linksmanagerservice.LinksManager,
29
+ useValue: linksManager
30
+ }
79
31
  ]
80
32
  }).compile();
81
33
  controller = module.get(_linkscontroller.LinksController);
82
34
  });
35
+ beforeEach(()=>{
36
+ jest.clearAllMocks();
37
+ });
83
38
  it('should be defined', ()=>{
84
39
  expect(controller).toBeDefined();
85
40
  });
41
+ describe('linkValidation', ()=>{
42
+ it('should call LinksManager.linkValidation with provided user and uuid and return its result', async ()=>{
43
+ const user = {
44
+ id: 123,
45
+ login: 'john'
46
+ };
47
+ const uuid = 'test-uuid-1';
48
+ const expected = {
49
+ error: true,
50
+ ok: true,
51
+ link: {
52
+ id: 1,
53
+ uuid,
54
+ name: 'My Link'
55
+ }
56
+ };
57
+ linksManager.linkValidation.mockResolvedValue(expected);
58
+ const result = await controller.linkValidation(user, uuid);
59
+ expect(linksManager.linkValidation).toHaveBeenCalledTimes(1);
60
+ expect(linksManager.linkValidation).toHaveBeenCalledWith(user, uuid);
61
+ expect(result).toBe(expected);
62
+ });
63
+ });
64
+ describe('linkAccess', ()=>{
65
+ it('should forward to LinksManager.linkAccess and return a StreamableFile', async ()=>{
66
+ const user = {
67
+ id: 42
68
+ };
69
+ const uuid = 'test-uuid-2';
70
+ const req = {};
71
+ const res = {};
72
+ const file = new _common.StreamableFile(Buffer.from('data'));
73
+ linksManager.linkAccess.mockResolvedValue(file);
74
+ const result = await controller.linkAccess(user, uuid, req, res);
75
+ expect(linksManager.linkAccess).toHaveBeenCalledTimes(1);
76
+ expect(linksManager.linkAccess).toHaveBeenCalledWith(user, uuid, req, res);
77
+ expect(result).toBe(file);
78
+ });
79
+ it('should forward to LinksManager.linkAccess and return a LoginResponseDto', async ()=>{
80
+ const user = {
81
+ id: 43
82
+ };
83
+ const uuid = 'test-uuid-3';
84
+ const req = {};
85
+ const res = {};
86
+ const loginResponse = {
87
+ accessToken: 'token',
88
+ refreshToken: 'refresh'
89
+ };
90
+ linksManager.linkAccess.mockResolvedValue(loginResponse);
91
+ const result = await controller.linkAccess(user, uuid, req, res);
92
+ expect(linksManager.linkAccess).toHaveBeenCalledTimes(1);
93
+ expect(linksManager.linkAccess).toHaveBeenCalledWith(user, uuid, req, res);
94
+ expect(result).toBe(loginResponse);
95
+ });
96
+ });
97
+ describe('linkAuthentication', ()=>{
98
+ it('should call LinksManager.linkAuthentication with provided params and return its result', async ()=>{
99
+ const user = {
100
+ id: 7
101
+ };
102
+ const uuid = 'test-uuid-4';
103
+ const body = {
104
+ password: 'secret'
105
+ };
106
+ const req = {};
107
+ const res = {};
108
+ const expectedLogin = {
109
+ accessToken: 'acc',
110
+ refreshToken: 'ref'
111
+ };
112
+ linksManager.linkAuthentication.mockResolvedValue(expectedLogin);
113
+ const result = await controller.linkAuthentication(user, uuid, body, req, res);
114
+ expect(linksManager.linkAuthentication).toHaveBeenCalledTimes(1);
115
+ expect(linksManager.linkAuthentication).toHaveBeenCalledWith(user, uuid, body, req, res);
116
+ expect(result).toBe(expectedLogin);
117
+ });
118
+ });
86
119
  });
87
120
 
88
121
  //# sourceMappingURL=links.controller.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../backend/src/applications/links/links.controller.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 { HttpService } from '@nestjs/axios'\nimport { ConfigService } from '@nestjs/config'\nimport { JwtService } from '@nestjs/jwt'\nimport { Test, TestingModule } from '@nestjs/testing'\nimport { AuthManager } from '../../authentication/services/auth-manager.service'\nimport { Cache } from '../../infrastructure/cache/services/cache.service'\nimport { ContextManager } from '../../infrastructure/context/services/context-manager.service'\nimport { DB_TOKEN_PROVIDER } from '../../infrastructure/database/constants'\nimport { FilesLockManager } from '../files/services/files-lock-manager.service'\nimport { FilesManager } from '../files/services/files-manager.service'\nimport { FilesQueries } from '../files/services/files-queries.service'\nimport { NotificationsManager } from '../notifications/services/notifications-manager.service'\nimport { SharesManager } from '../shares/services/shares-manager.service'\nimport { SharesQueries } from '../shares/services/shares-queries.service'\nimport { SpacesManager } from '../spaces/services/spaces-manager.service'\nimport { SpacesQueries } from '../spaces/services/spaces-queries.service'\nimport { AdminUsersManager } from '../users/services/admin-users-manager.service'\nimport { AdminUsersQueries } from '../users/services/admin-users-queries.service'\nimport { UsersManager } from '../users/services/users-manager.service'\nimport { UsersQueries } from '../users/services/users-queries.service'\nimport { LinksController } from './links.controller'\nimport { LinksManager } from './services/links-manager.service'\nimport { LinksQueries } from './services/links-queries.service'\n\ndescribe(LinksController.name, () => {\n let controller: LinksController\n\n beforeAll(async () => {\n const module: TestingModule = await Test.createTestingModule({\n controllers: [LinksController],\n providers: [\n { provide: DB_TOKEN_PROVIDER, useValue: {} },\n {\n provide: Cache,\n useValue: {}\n },\n { provide: ContextManager, useValue: {} },\n {\n provide: NotificationsManager,\n useValue: {}\n },\n { provide: HttpService, useValue: {} },\n { provide: FilesLockManager, useValue: {} },\n ConfigService,\n JwtService,\n AuthManager,\n LinksManager,\n LinksQueries,\n UsersManager,\n UsersQueries,\n AdminUsersManager,\n AdminUsersQueries,\n SpacesManager,\n SpacesQueries,\n FilesManager,\n FilesQueries,\n SharesManager,\n SharesQueries\n ]\n }).compile()\n\n controller = module.get<LinksController>(LinksController)\n })\n\n it('should be defined', () => {\n expect(controller).toBeDefined()\n })\n})\n"],"names":["describe","LinksController","name","controller","beforeAll","module","Test","createTestingModule","controllers","providers","provide","DB_TOKEN_PROVIDER","useValue","Cache","ContextManager","NotificationsManager","HttpService","FilesLockManager","ConfigService","JwtService","AuthManager","LinksManager","LinksQueries","UsersManager","UsersQueries","AdminUsersManager","AdminUsersQueries","SpacesManager","SpacesQueries","FilesManager","FilesQueries","SharesManager","SharesQueries","compile","get","it","expect","toBeDefined"],"mappings":"AAAA;;;;CAIC;;;;uBAE2B;wBACE;qBACH;yBACS;oCACR;8BACN;uCACS;2BACG;yCACD;qCACJ;qCACA;6CACQ;sCACP;sCACA;sCACA;sCACA;0CACI;0CACA;qCACL;qCACA;iCACG;qCACH;qCACA;AAE7BA,SAASC,gCAAe,CAACC,IAAI,EAAE;IAC7B,IAAIC;IAEJC,UAAU;QACR,MAAMC,SAAwB,MAAMC,aAAI,CAACC,mBAAmB,CAAC;YAC3DC,aAAa;gBAACP,gCAAe;aAAC;YAC9BQ,WAAW;gBACT;oBAAEC,SAASC,4BAAiB;oBAAEC,UAAU,CAAC;gBAAE;gBAC3C;oBACEF,SAASG,mBAAK;oBACdD,UAAU,CAAC;gBACb;gBACA;oBAAEF,SAASI,qCAAc;oBAAEF,UAAU,CAAC;gBAAE;gBACxC;oBACEF,SAASK,iDAAoB;oBAC7BH,UAAU,CAAC;gBACb;gBACA;oBAAEF,SAASM,kBAAW;oBAAEJ,UAAU,CAAC;gBAAE;gBACrC;oBAAEF,SAASO,yCAAgB;oBAAEL,UAAU,CAAC;gBAAE;gBAC1CM,qBAAa;gBACbC,eAAU;gBACVC,+BAAW;gBACXC,iCAAY;gBACZC,iCAAY;gBACZC,iCAAY;gBACZC,iCAAY;gBACZC,2CAAiB;gBACjBC,2CAAiB;gBACjBC,mCAAa;gBACbC,mCAAa;gBACbC,iCAAY;gBACZC,iCAAY;gBACZC,mCAAa;gBACbC,mCAAa;aACd;QACH,GAAGC,OAAO;QAEV9B,aAAaE,OAAO6B,GAAG,CAAkBjC,gCAAe;IAC1D;IAEAkC,GAAG,qBAAqB;QACtBC,OAAOjC,YAAYkC,WAAW;IAChC;AACF"}
1
+ {"version":3,"sources":["../../../../backend/src/applications/links/links.controller.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 { StreamableFile } from '@nestjs/common'\nimport { Test, TestingModule } from '@nestjs/testing'\nimport { LinksController } from './links.controller'\nimport { LinksManager } from './services/links-manager.service'\n\ndescribe(LinksController.name, () => {\n let controller: LinksController\n let linksManager: {\n linkValidation: jest.Mock\n linkAccess: jest.Mock\n linkAuthentication: jest.Mock\n }\n\n beforeAll(async () => {\n linksManager = {\n linkValidation: jest.fn(),\n linkAccess: jest.fn(),\n linkAuthentication: jest.fn()\n }\n\n const module: TestingModule = await Test.createTestingModule({\n controllers: [LinksController],\n providers: [{ provide: LinksManager, useValue: linksManager }]\n }).compile()\n\n controller = module.get<LinksController>(LinksController)\n })\n\n beforeEach(() => {\n jest.clearAllMocks()\n })\n\n it('should be defined', () => {\n expect(controller).toBeDefined()\n })\n\n describe('linkValidation', () => {\n it('should call LinksManager.linkValidation with provided user and uuid and return its result', async () => {\n const user = { id: 123, login: 'john' } as any\n const uuid = 'test-uuid-1'\n const expected = {\n error: true,\n ok: true,\n link: { id: 1, uuid, name: 'My Link' }\n } as any\n\n linksManager.linkValidation.mockResolvedValue(expected)\n\n const result = await controller.linkValidation(user, uuid)\n\n expect(linksManager.linkValidation).toHaveBeenCalledTimes(1)\n expect(linksManager.linkValidation).toHaveBeenCalledWith(user, uuid)\n expect(result).toBe(expected)\n })\n })\n\n describe('linkAccess', () => {\n it('should forward to LinksManager.linkAccess and return a StreamableFile', async () => {\n const user = { id: 42 } as any\n const uuid = 'test-uuid-2'\n const req = {} as any\n const res = {} as any\n const file = new StreamableFile(Buffer.from('data'))\n\n linksManager.linkAccess.mockResolvedValue(file)\n\n const result = await controller.linkAccess(user, uuid, req, res)\n\n expect(linksManager.linkAccess).toHaveBeenCalledTimes(1)\n expect(linksManager.linkAccess).toHaveBeenCalledWith(user, uuid, req, res)\n expect(result).toBe(file)\n })\n\n it('should forward to LinksManager.linkAccess and return a LoginResponseDto', async () => {\n const user = { id: 43 } as any\n const uuid = 'test-uuid-3'\n const req = {} as any\n const res = {} as any\n const loginResponse = { accessToken: 'token', refreshToken: 'refresh' } as any\n\n linksManager.linkAccess.mockResolvedValue(loginResponse)\n\n const result = await controller.linkAccess(user, uuid, req, res)\n\n expect(linksManager.linkAccess).toHaveBeenCalledTimes(1)\n expect(linksManager.linkAccess).toHaveBeenCalledWith(user, uuid, req, res)\n expect(result).toBe(loginResponse)\n })\n })\n\n describe('linkAuthentication', () => {\n it('should call LinksManager.linkAuthentication with provided params and return its result', async () => {\n const user = { id: 7 } as any\n const uuid = 'test-uuid-4'\n const body = { password: 'secret' } as any\n const req = {} as any\n const res = {} as any\n const expectedLogin = { accessToken: 'acc', refreshToken: 'ref' } as any\n\n linksManager.linkAuthentication.mockResolvedValue(expectedLogin)\n\n const result = await controller.linkAuthentication(user, uuid, body, req, res)\n\n expect(linksManager.linkAuthentication).toHaveBeenCalledTimes(1)\n expect(linksManager.linkAuthentication).toHaveBeenCalledWith(user, uuid, body, req, res)\n expect(result).toBe(expectedLogin)\n })\n })\n})\n"],"names":["describe","LinksController","name","controller","linksManager","beforeAll","linkValidation","jest","fn","linkAccess","linkAuthentication","module","Test","createTestingModule","controllers","providers","provide","LinksManager","useValue","compile","get","beforeEach","clearAllMocks","it","expect","toBeDefined","user","id","login","uuid","expected","error","ok","link","mockResolvedValue","result","toHaveBeenCalledTimes","toHaveBeenCalledWith","toBe","req","res","file","StreamableFile","Buffer","from","loginResponse","accessToken","refreshToken","body","password","expectedLogin"],"mappings":"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"}
@@ -59,7 +59,7 @@ let LinksManager = class LinksManager {
59
59
  if (!spaceLink.space && !spaceLink.share.isDir) {
60
60
  // download the file (authentication has been verified before)
61
61
  this.logger.log(`${this.linkAccess.name} - *${user.login}* (${user.id}) downloading ${spaceLink.share.name}`);
62
- this.incrementLinkAccess(link);
62
+ this.incrementLinkNbAccess(link);
63
63
  const spaceEnv = await this.spaceEnvFromLink(user, spaceLink);
64
64
  const sendFile = this.filesManager.sendFileFromSpace(spaceEnv, true, spaceLink.share.name);
65
65
  try {
@@ -72,7 +72,7 @@ let LinksManager = class LinksManager {
72
72
  } else if (link.user.id !== identity.id) {
73
73
  // authenticate user to allow access to the directory
74
74
  this.logger.log(`${this.linkAccess.name} - *${user.login}* (${user.id}) is logged`);
75
- this.incrementLinkAccess(link);
75
+ this.incrementLinkNbAccess(link);
76
76
  this.usersManager.updateAccesses(user, req.ip, true).catch((e)=>this.logger.error(`${this.linkAccess.name} - ${e}`));
77
77
  return this.authManager.setCookies(user, res);
78
78
  }
@@ -129,10 +129,8 @@ let LinksManager = class LinksManager {
129
129
  }
130
130
  return true;
131
131
  }
132
- incrementLinkAccess(link) {
133
- if (link.limitAccess !== null) {
134
- this.linksQueries.incrementLinkAccess(link.uuid).catch((e)=>this.logger.error(`${this.incrementLinkAccess.name} - ${e}`));
135
- }
132
+ incrementLinkNbAccess(link) {
133
+ this.linksQueries.incrementLinkNbAccess(link.uuid).catch((e)=>this.logger.error(`${this.incrementLinkNbAccess.name} - ${e}`));
136
134
  }
137
135
  constructor(authManager, usersManager, filesManager, spacesManager, linksQueries){
138
136
  this.authManager = authManager;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/links/services/links-manager.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpException, HttpStatus, Injectable, Logger, StreamableFile } from '@nestjs/common'\nimport { FastifyReply, FastifyRequest } from 'fastify'\nimport { LoginResponseDto } from '../../../authentication/dto/login-response.dto'\nimport { JwtIdentityPayload } from '../../../authentication/interfaces/jwt-payload.interface'\nimport { AuthManager } from '../../../authentication/services/auth-manager.service'\nimport { FilesManager } from '../../files/services/files-manager.service'\nimport { SendFile } from '../../files/utils/send-file'\nimport { SPACE_REPOSITORY } from '../../spaces/constants/spaces'\nimport { SpaceEnv } from '../../spaces/models/space-env.model'\nimport { SpacesManager } from '../../spaces/services/spaces-manager.service'\nimport { UserPasswordDto } from '../../users/dto/user-password.dto'\nimport { UserModel } from '../../users/models/user.model'\nimport { UsersManager } from '../../users/services/users-manager.service'\nimport { LINK_ERROR } from '../constants/links'\nimport { LinkAsUser } from '../interfaces/link-guest.interface'\nimport { SpaceLink } from '../interfaces/link-space.interface'\nimport { LinksQueries } from './links-queries.service'\n\n@Injectable()\nexport class LinksManager {\n private logger = new Logger(LinksManager.name)\n\n constructor(\n private readonly authManager: AuthManager,\n private readonly usersManager: UsersManager,\n private readonly filesManager: FilesManager,\n private readonly spacesManager: SpacesManager,\n private readonly linksQueries: LinksQueries\n ) {}\n\n async linkValidation(identity: JwtIdentityPayload, uuid: string): Promise<{ ok: boolean; error: string | true; link: SpaceLink }> {\n const [_link, check, ok] = await this.linkEnv(identity, uuid)\n if (!ok) {\n this.logger.warn(`${this.linkValidation.name} - ${uuid} : ${check}`)\n }\n const spaceLink: SpaceLink = ok ? await this.linksQueries.spaceLink(uuid) : null\n if (spaceLink?.owner?.login) {\n spaceLink.owner.avatar = await this.usersManager.getAvatarBase64(spaceLink.owner.login)\n // for security reasons\n delete spaceLink.owner.login\n }\n return { ok: ok, error: ok ? null : check, link: spaceLink }\n }\n\n async linkAccess(identity: JwtIdentityPayload, uuid: string, req: FastifyRequest, res: FastifyReply): Promise<StreamableFile | LoginResponseDto> {\n const [link, check, ok] = await this.linkEnv(identity, uuid)\n if (!ok) {\n this.logger.warn(`${this.linkAccess.name} - *${link.user.login}* (${link.user.id}) : ${check}`)\n throw new HttpException(check as string, HttpStatus.BAD_REQUEST)\n }\n const user = new UserModel(link.user)\n const spaceLink: SpaceLink = await this.linksQueries.spaceLink(uuid)\n if (!spaceLink.space && !spaceLink.share.isDir) {\n // download the file (authentication has been verified before)\n this.logger.log(`${this.linkAccess.name} - *${user.login}* (${user.id}) downloading ${spaceLink.share.name}`)\n this.incrementLinkAccess(link)\n const spaceEnv: SpaceEnv = await this.spaceEnvFromLink(user, spaceLink)\n const sendFile: SendFile = this.filesManager.sendFileFromSpace(spaceEnv, true, spaceLink.share.name)\n try {\n await sendFile.checks()\n return await sendFile.stream(req, res)\n } catch (e) {\n this.logger.error(`${this.linkAccess.name} - unable to send file : ${e}`)\n throw new HttpException('Unable to download file', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n } else if (link.user.id !== identity.id) {\n // authenticate user to allow access to the directory\n this.logger.log(`${this.linkAccess.name} - *${user.login}* (${user.id}) is logged`)\n this.incrementLinkAccess(link)\n this.usersManager.updateAccesses(user, req.ip, true).catch((e: Error) => this.logger.error(`${this.linkAccess.name} - ${e}`))\n return this.authManager.setCookies(user, res)\n }\n // already authenticated\n }\n\n async linkAuthentication(identity: JwtIdentityPayload, uuid: string, linkPasswordDto: UserPasswordDto, req: FastifyRequest, res: FastifyReply) {\n const [link, check, ok] = await this.linkEnv(identity, uuid, true)\n if (!ok) {\n this.logger.warn(`${this.linkAuthentication.name} - *${link.user.login}* (${link.user.id}) : ${check}`)\n throw new HttpException(check as string, HttpStatus.BAD_REQUEST)\n }\n const authSuccess: boolean = await this.usersManager.compareUserPassword(link.user.id, linkPasswordDto.password)\n const user = new UserModel(link.user)\n this.usersManager.updateAccesses(user, req.ip, authSuccess).catch((e: Error) => this.logger.error(`${this.linkAuthentication.name} - ${e}`))\n if (!authSuccess) {\n this.logger.warn(`${this.linkAuthentication.name} - *${user.login}* (${user.id}) : auth failed`)\n throw new HttpException(LINK_ERROR.UNAUTHORIZED, HttpStatus.FORBIDDEN)\n }\n // authenticate user to allow access\n this.logger.log(`${this.linkAuthentication.name} - *${user.login}* (${user.id}) is logged`)\n return this.authManager.setCookies(user, res)\n }\n\n private spaceEnvFromLink(user: UserModel, link: SpaceLink): Promise<SpaceEnv> {\n return this.spacesManager.spaceEnv(user, [\n link.space ? SPACE_REPOSITORY.FILES : SPACE_REPOSITORY.SHARES,\n link.space ? link.space.alias : link.share.alias\n ])\n }\n\n private async linkEnv(identity: JwtIdentityPayload, uuid: string, ignoreAuth: boolean = false): Promise<[LinkAsUser, string | true, boolean]> {\n const link: LinkAsUser = await this.linksQueries.linkFromUUID(uuid)\n const check: string | true = this.checkLink(identity, link, ignoreAuth)\n const ok: boolean = check === true\n return [link, check, ok]\n }\n\n private checkLink(identity: JwtIdentityPayload, link: LinkAsUser, ignoreAuth: boolean = false): string | true {\n if (!link) {\n return LINK_ERROR.NOT_FOUND\n }\n if (!link.user.isActive) {\n return LINK_ERROR.DISABLED\n }\n if (link.limitAccess !== 0 && link.nbAccess >= link.limitAccess) {\n return LINK_ERROR.EXCEEDED\n }\n if (link.expiresAt && new Date() >= link.expiresAt) {\n return LINK_ERROR.EXPIRED\n }\n if (!ignoreAuth && link.requireAuth && link.user.id !== identity.id) {\n return LINK_ERROR.UNAUTHORIZED\n }\n return true\n }\n\n private incrementLinkAccess(link: LinkAsUser) {\n if (link.limitAccess !== null) {\n this.linksQueries.incrementLinkAccess(link.uuid).catch((e: Error) => this.logger.error(`${this.incrementLinkAccess.name} - ${e}`))\n }\n }\n}\n"],"names":["LinksManager","linkValidation","identity","uuid","_link","check","ok","linkEnv","logger","warn","name","spaceLink","linksQueries","owner","login","avatar","usersManager","getAvatarBase64","error","link","linkAccess","req","res","user","id","HttpException","HttpStatus","BAD_REQUEST","UserModel","space","share","isDir","log","incrementLinkAccess","spaceEnv","spaceEnvFromLink","sendFile","filesManager","sendFileFromSpace","checks","stream","e","INTERNAL_SERVER_ERROR","updateAccesses","ip","catch","authManager","setCookies","linkAuthentication","linkPasswordDto","authSuccess","compareUserPassword","password","LINK_ERROR","UNAUTHORIZED","FORBIDDEN","spacesManager","SPACE_REPOSITORY","FILES","SHARES","alias","ignoreAuth","linkFromUUID","checkLink","NOT_FOUND","isActive","DISABLED","limitAccess","nbAccess","EXCEEDED","expiresAt","Date","EXPIRED","requireAuth","Logger"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/links/services/links-manager.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpException, HttpStatus, Injectable, Logger, StreamableFile } from '@nestjs/common'\nimport { FastifyReply, FastifyRequest } from 'fastify'\nimport { LoginResponseDto } from '../../../authentication/dto/login-response.dto'\nimport { JwtIdentityPayload } from '../../../authentication/interfaces/jwt-payload.interface'\nimport { AuthManager } from '../../../authentication/services/auth-manager.service'\nimport { FilesManager } from '../../files/services/files-manager.service'\nimport { SendFile } from '../../files/utils/send-file'\nimport { SPACE_REPOSITORY } from '../../spaces/constants/spaces'\nimport { SpaceEnv } from '../../spaces/models/space-env.model'\nimport { SpacesManager } from '../../spaces/services/spaces-manager.service'\nimport { UserPasswordDto } from '../../users/dto/user-password.dto'\nimport { UserModel } from '../../users/models/user.model'\nimport { UsersManager } from '../../users/services/users-manager.service'\nimport { LINK_ERROR } from '../constants/links'\nimport { LinkAsUser } from '../interfaces/link-guest.interface'\nimport { SpaceLink } from '../interfaces/link-space.interface'\nimport { LinksQueries } from './links-queries.service'\n\n@Injectable()\nexport class LinksManager {\n private logger = new Logger(LinksManager.name)\n\n constructor(\n private readonly authManager: AuthManager,\n private readonly usersManager: UsersManager,\n private readonly filesManager: FilesManager,\n private readonly spacesManager: SpacesManager,\n private readonly linksQueries: LinksQueries\n ) {}\n\n async linkValidation(identity: JwtIdentityPayload, uuid: string): Promise<{ ok: boolean; error: string | true; link: SpaceLink }> {\n const [_link, check, ok] = await this.linkEnv(identity, uuid)\n if (!ok) {\n this.logger.warn(`${this.linkValidation.name} - ${uuid} : ${check}`)\n }\n const spaceLink: SpaceLink = ok ? await this.linksQueries.spaceLink(uuid) : null\n if (spaceLink?.owner?.login) {\n spaceLink.owner.avatar = await this.usersManager.getAvatarBase64(spaceLink.owner.login)\n // for security reasons\n delete spaceLink.owner.login\n }\n return { ok: ok, error: ok ? null : check, link: spaceLink }\n }\n\n async linkAccess(identity: JwtIdentityPayload, uuid: string, req: FastifyRequest, res: FastifyReply): Promise<StreamableFile | LoginResponseDto> {\n const [link, check, ok] = await this.linkEnv(identity, uuid)\n if (!ok) {\n this.logger.warn(`${this.linkAccess.name} - *${link.user.login}* (${link.user.id}) : ${check}`)\n throw new HttpException(check as string, HttpStatus.BAD_REQUEST)\n }\n const user = new UserModel(link.user)\n const spaceLink: SpaceLink = await this.linksQueries.spaceLink(uuid)\n if (!spaceLink.space && !spaceLink.share.isDir) {\n // download the file (authentication has been verified before)\n this.logger.log(`${this.linkAccess.name} - *${user.login}* (${user.id}) downloading ${spaceLink.share.name}`)\n this.incrementLinkNbAccess(link)\n const spaceEnv: SpaceEnv = await this.spaceEnvFromLink(user, spaceLink)\n const sendFile: SendFile = this.filesManager.sendFileFromSpace(spaceEnv, true, spaceLink.share.name)\n try {\n await sendFile.checks()\n return await sendFile.stream(req, res)\n } catch (e) {\n this.logger.error(`${this.linkAccess.name} - unable to send file : ${e}`)\n throw new HttpException('Unable to download file', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n } else if (link.user.id !== identity.id) {\n // authenticate user to allow access to the directory\n this.logger.log(`${this.linkAccess.name} - *${user.login}* (${user.id}) is logged`)\n this.incrementLinkNbAccess(link)\n this.usersManager.updateAccesses(user, req.ip, true).catch((e: Error) => this.logger.error(`${this.linkAccess.name} - ${e}`))\n return this.authManager.setCookies(user, res)\n }\n // already authenticated\n }\n\n async linkAuthentication(identity: JwtIdentityPayload, uuid: string, linkPasswordDto: UserPasswordDto, req: FastifyRequest, res: FastifyReply) {\n const [link, check, ok] = await this.linkEnv(identity, uuid, true)\n if (!ok) {\n this.logger.warn(`${this.linkAuthentication.name} - *${link.user.login}* (${link.user.id}) : ${check}`)\n throw new HttpException(check as string, HttpStatus.BAD_REQUEST)\n }\n const authSuccess: boolean = await this.usersManager.compareUserPassword(link.user.id, linkPasswordDto.password)\n const user = new UserModel(link.user)\n this.usersManager.updateAccesses(user, req.ip, authSuccess).catch((e: Error) => this.logger.error(`${this.linkAuthentication.name} - ${e}`))\n if (!authSuccess) {\n this.logger.warn(`${this.linkAuthentication.name} - *${user.login}* (${user.id}) : auth failed`)\n throw new HttpException(LINK_ERROR.UNAUTHORIZED, HttpStatus.FORBIDDEN)\n }\n // authenticate user to allow access\n this.logger.log(`${this.linkAuthentication.name} - *${user.login}* (${user.id}) is logged`)\n return this.authManager.setCookies(user, res)\n }\n\n private spaceEnvFromLink(user: UserModel, link: SpaceLink): Promise<SpaceEnv> {\n return this.spacesManager.spaceEnv(user, [\n link.space ? SPACE_REPOSITORY.FILES : SPACE_REPOSITORY.SHARES,\n link.space ? link.space.alias : link.share.alias\n ])\n }\n\n private async linkEnv(identity: JwtIdentityPayload, uuid: string, ignoreAuth: boolean = false): Promise<[LinkAsUser, string | true, boolean]> {\n const link: LinkAsUser = await this.linksQueries.linkFromUUID(uuid)\n const check: string | true = this.checkLink(identity, link, ignoreAuth)\n const ok: boolean = check === true\n return [link, check, ok]\n }\n\n private checkLink(identity: JwtIdentityPayload, link: LinkAsUser, ignoreAuth: boolean = false): string | true {\n if (!link) {\n return LINK_ERROR.NOT_FOUND\n }\n if (!link.user.isActive) {\n return LINK_ERROR.DISABLED\n }\n if (link.limitAccess !== 0 && link.nbAccess >= link.limitAccess) {\n return LINK_ERROR.EXCEEDED\n }\n if (link.expiresAt && new Date() >= link.expiresAt) {\n return LINK_ERROR.EXPIRED\n }\n if (!ignoreAuth && link.requireAuth && link.user.id !== identity.id) {\n return LINK_ERROR.UNAUTHORIZED\n }\n return true\n }\n\n private incrementLinkNbAccess(link: LinkAsUser) {\n this.linksQueries.incrementLinkNbAccess(link.uuid).catch((e: Error) => this.logger.error(`${this.incrementLinkNbAccess.name} - ${e}`))\n }\n}\n"],"names":["LinksManager","linkValidation","identity","uuid","_link","check","ok","linkEnv","logger","warn","name","spaceLink","linksQueries","owner","login","avatar","usersManager","getAvatarBase64","error","link","linkAccess","req","res","user","id","HttpException","HttpStatus","BAD_REQUEST","UserModel","space","share","isDir","log","incrementLinkNbAccess","spaceEnv","spaceEnvFromLink","sendFile","filesManager","sendFileFromSpace","checks","stream","e","INTERNAL_SERVER_ERROR","updateAccesses","ip","catch","authManager","setCookies","linkAuthentication","linkPasswordDto","authSuccess","compareUserPassword","password","LINK_ERROR","UNAUTHORIZED","FORBIDDEN","spacesManager","SPACE_REPOSITORY","FILES","SHARES","alias","ignoreAuth","linkFromUUID","checkLink","NOT_FOUND","isActive","DISABLED","limitAccess","nbAccess","EXCEEDED","expiresAt","Date","EXPIRED","requireAuth","Logger"],"mappings":"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"}