@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
@@ -7,49 +7,589 @@ Object.defineProperty(exports, "__esModule", {
7
7
  value: true
8
8
  });
9
9
  const _axios = require("@nestjs/axios");
10
+ const _common = require("@nestjs/common");
10
11
  const _testing = require("@nestjs/testing");
12
+ const _nodecrypto = /*#__PURE__*/ _interop_require_default(require("node:crypto"));
13
+ const _promises = /*#__PURE__*/ _interop_require_default(require("node:fs/promises"));
11
14
  const _authmethod = require("../../../authentication/models/auth-method");
12
15
  const _authmanagerservice = require("../../../authentication/services/auth-manager.service");
16
+ const _functions = /*#__PURE__*/ _interop_require_wildcard(require("../../../common/functions"));
17
+ const _shared = /*#__PURE__*/ _interop_require_wildcard(require("../../../common/shared"));
18
+ const _configenvironment = require("../../../configuration/config.environment");
13
19
  const _cacheservice = require("../../../infrastructure/cache/services/cache.service");
20
+ const _files = require("../../files/utils/files");
14
21
  const _usersqueriesservice = require("../../users/services/users-queries.service");
22
+ const _auth = require("../constants/auth");
23
+ const _store = require("../constants/store");
24
+ const _sync = require("../constants/sync");
15
25
  const _syncclientsmanagerservice = require("./sync-clients-manager.service");
16
26
  const _syncqueriesservice = require("./sync-queries.service");
27
+ function _interop_require_default(obj) {
28
+ return obj && obj.__esModule ? obj : {
29
+ default: obj
30
+ };
31
+ }
32
+ function _getRequireWildcardCache(nodeInterop) {
33
+ if (typeof WeakMap !== "function") return null;
34
+ var cacheBabelInterop = new WeakMap();
35
+ var cacheNodeInterop = new WeakMap();
36
+ return (_getRequireWildcardCache = function(nodeInterop) {
37
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
38
+ })(nodeInterop);
39
+ }
40
+ function _interop_require_wildcard(obj, nodeInterop) {
41
+ if (!nodeInterop && obj && obj.__esModule) {
42
+ return obj;
43
+ }
44
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
45
+ return {
46
+ default: obj
47
+ };
48
+ }
49
+ var cache = _getRequireWildcardCache(nodeInterop);
50
+ if (cache && cache.has(obj)) {
51
+ return cache.get(obj);
52
+ }
53
+ var newObj = {
54
+ __proto__: null
55
+ };
56
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
57
+ for(var key in obj){
58
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
59
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
60
+ if (desc && (desc.get || desc.set)) {
61
+ Object.defineProperty(newObj, key, desc);
62
+ } else {
63
+ newObj[key] = obj[key];
64
+ }
65
+ }
66
+ }
67
+ newObj.default = obj;
68
+ if (cache) {
69
+ cache.set(obj, newObj);
70
+ }
71
+ return newObj;
72
+ }
73
+ // Pilotage permission via UserModel
74
+ let mockHavePermission = true;
75
+ jest.mock('../../users/models/user.model', ()=>({
76
+ UserModel: jest.fn().mockImplementation((props)=>({
77
+ ...props,
78
+ havePermission: ()=>mockHavePermission
79
+ }))
80
+ }));
81
+ // Mock ciblé de convertHumanTimeToSeconds
82
+ jest.mock('../../../common/functions', ()=>{
83
+ const actual = jest.requireActual('../../../common/functions');
84
+ return {
85
+ ...actual,
86
+ convertHumanTimeToSeconds: jest.fn()
87
+ };
88
+ });
89
+ // Mock currentTimeStamp
90
+ jest.mock('../../../common/shared', ()=>({
91
+ currentTimeStamp: jest.fn()
92
+ }));
93
+ // Mock FS et helper d'existence
94
+ jest.mock('node:fs/promises', ()=>({
95
+ readFile: jest.fn()
96
+ }));
97
+ jest.mock('../../files/utils/files', ()=>({
98
+ isPathExists: jest.fn()
99
+ }));
17
100
  describe(_syncclientsmanagerservice.SyncClientsManager.name, ()=>{
18
101
  let service;
102
+ // Mocks
103
+ let http;
104
+ let authManager;
105
+ let authMethod;
106
+ let usersQueries;
107
+ let syncQueries;
108
+ let cacheMock;
109
+ // Helpers
110
+ const setRepo = (repo)=>{
111
+ ;
112
+ _configenvironment.configuration.applications.appStore.repository = repo;
113
+ };
114
+ const makeClient = (overrides = {})=>({
115
+ id: 'cid',
116
+ ownerId: 1,
117
+ tokenExpiration: 2000,
118
+ enabled: true,
119
+ info: {
120
+ type: 'desktop'
121
+ },
122
+ ...overrides
123
+ });
124
+ const makeUser = (overrides = {})=>({
125
+ id: 1,
126
+ isActive: true,
127
+ login: 'u',
128
+ email: 'u@x',
129
+ firstName: 'U',
130
+ lastName: 'X',
131
+ role: 1,
132
+ permissions: 'desktop',
133
+ ...overrides
134
+ });
19
135
  beforeAll(async ()=>{
136
+ http = {
137
+ axiosRef: jest.fn()
138
+ };
139
+ authManager = {
140
+ setCookies: jest.fn(),
141
+ getTokens: jest.fn()
142
+ };
143
+ authMethod = {
144
+ validateUser: jest.fn()
145
+ };
146
+ usersQueries = {
147
+ from: jest.fn(),
148
+ updateUserOrGuest: jest.fn()
149
+ };
150
+ syncQueries = {
151
+ getOrCreateClient: jest.fn(),
152
+ deleteClient: jest.fn(),
153
+ getClient: jest.fn(),
154
+ updateClientInfo: jest.fn(),
155
+ renewClientTokenAndExpiration: jest.fn(),
156
+ getClients: jest.fn()
157
+ };
158
+ cacheMock = {
159
+ genSlugKey: jest.fn().mockReturnValue('syncclientsmanager:checkappstore'),
160
+ get: jest.fn().mockResolvedValue(undefined),
161
+ set: jest.fn().mockResolvedValue(undefined),
162
+ del: jest.fn().mockResolvedValue(undefined)
163
+ };
20
164
  const module = await _testing.Test.createTestingModule({
21
165
  providers: [
22
166
  _syncclientsmanagerservice.SyncClientsManager,
23
167
  {
24
168
  provide: _cacheservice.Cache,
25
- useValue: {}
169
+ useValue: cacheMock
26
170
  },
27
171
  {
28
172
  provide: _axios.HttpService,
29
- useValue: {}
173
+ useValue: http
30
174
  },
31
175
  {
32
176
  provide: _syncqueriesservice.SyncQueries,
33
- useValue: {}
177
+ useValue: syncQueries
34
178
  },
35
179
  {
36
180
  provide: _usersqueriesservice.UsersQueries,
37
- useValue: {}
181
+ useValue: usersQueries
38
182
  },
39
183
  {
40
184
  provide: _authmanagerservice.AuthManager,
41
- useValue: {}
185
+ useValue: authManager
42
186
  },
43
187
  {
44
188
  provide: _authmethod.AuthMethod,
45
- useValue: {}
189
+ useValue: authMethod
46
190
  }
47
191
  ]
48
192
  }).compile();
193
+ module.useLogger([
194
+ 'fatal'
195
+ ]);
49
196
  service = module.get(_syncclientsmanagerservice.SyncClientsManager);
197
+ service.cache = cacheMock;
198
+ });
199
+ beforeEach(()=>{
200
+ jest.restoreAllMocks();
201
+ jest.clearAllMocks();
202
+ mockHavePermission = true;
203
+ _shared.currentTimeStamp.mockReturnValue(1_000);
204
+ _functions.convertHumanTimeToSeconds.mockImplementation((v)=>{
205
+ if (v === '90d') return 90 * 24 * 3600;
206
+ if (v === '180d') return 180 * 24 * 3600;
207
+ if (typeof v === 'number') return v;
208
+ return 0;
209
+ });
210
+ _files.isPathExists.mockReset();
211
+ _promises.default.readFile.mockReset();
212
+ syncQueries.updateClientInfo.mockResolvedValue(undefined);
213
+ usersQueries.updateUserOrGuest.mockResolvedValue(undefined);
214
+ service.cache = cacheMock;
215
+ cacheMock.get.mockResolvedValue(undefined);
216
+ cacheMock.get.mockClear();
217
+ cacheMock.set.mockClear();
218
+ cacheMock.del.mockClear();
219
+ cacheMock.genSlugKey.mockClear();
220
+ setRepo(_store.APP_STORE_REPOSITORY.PUBLIC);
221
+ });
222
+ it('should be defined', ()=>expect(service).toBeDefined());
223
+ describe('register', ()=>{
224
+ const baseDto = {
225
+ login: 'john',
226
+ password: 'secret',
227
+ clientId: 'client-1',
228
+ info: {
229
+ type: 'desktop',
230
+ version: '1.0.0'
231
+ }
232
+ };
233
+ test.each([
234
+ [
235
+ 'Unauthorized when credentials are invalid',
236
+ null,
237
+ _common.HttpStatus.UNAUTHORIZED
238
+ ],
239
+ [
240
+ 'Forbidden when user lacks DESKTOP_APP permission',
241
+ {
242
+ id: 10,
243
+ login: 'john',
244
+ havePermission: ()=>false
245
+ },
246
+ _common.HttpStatus.FORBIDDEN
247
+ ]
248
+ ])('should throw %s', async (_label, user, status)=>{
249
+ authMethod.validateUser.mockResolvedValue(user);
250
+ await expect(service.register(baseDto, '1.2.3.4')).rejects.toMatchObject({
251
+ status
252
+ });
253
+ });
254
+ it('should return client token when registration succeeds', async ()=>{
255
+ authMethod.validateUser.mockResolvedValue({
256
+ id: 10,
257
+ login: 'john',
258
+ havePermission: ()=>true
259
+ });
260
+ syncQueries.getOrCreateClient.mockResolvedValue('token-abc');
261
+ const r = await service.register(baseDto, '1.2.3.4');
262
+ expect(r).toEqual({
263
+ clientToken: 'token-abc'
264
+ });
265
+ expect(syncQueries.getOrCreateClient).toHaveBeenCalledWith(10, 'client-1', baseDto.info, '1.2.3.4');
266
+ });
267
+ it('should throw Internal Server Error when persistence fails', async ()=>{
268
+ authMethod.validateUser.mockResolvedValue({
269
+ id: 10,
270
+ login: 'john',
271
+ havePermission: ()=>true
272
+ });
273
+ syncQueries.getOrCreateClient.mockRejectedValue(new Error('db error'));
274
+ await expect(service.register(baseDto, '1.2.3.4')).rejects.toMatchObject({
275
+ status: _common.HttpStatus.INTERNAL_SERVER_ERROR
276
+ });
277
+ });
278
+ });
279
+ describe('unregister', ()=>{
280
+ it('should delete client without error', async ()=>{
281
+ syncQueries.deleteClient.mockResolvedValue(undefined);
282
+ await expect(service.unregister({
283
+ id: 1,
284
+ clientId: 'c1'
285
+ })).resolves.toBeUndefined();
286
+ expect(syncQueries.deleteClient).toHaveBeenCalledWith(1, 'c1');
287
+ });
288
+ it('should throw Internal Server Error when deletion fails', async ()=>{
289
+ syncQueries.deleteClient.mockRejectedValue(new Error('db error'));
290
+ await expect(service.unregister({
291
+ id: 1,
292
+ clientId: 'c1'
293
+ })).rejects.toMatchObject({
294
+ status: _common.HttpStatus.INTERNAL_SERVER_ERROR
295
+ });
296
+ });
297
+ });
298
+ describe('authenticate', ()=>{
299
+ const ip = '9.9.9.9';
300
+ const dto = {
301
+ clientId: 'cid',
302
+ token: 'ctok'
303
+ };
304
+ it('should forbid when client is unknown', async ()=>{
305
+ syncQueries.getClient.mockResolvedValue(undefined);
306
+ await expect(service.authenticate(_auth.CLIENT_AUTH_TYPE.TOKEN, dto, ip, {})).rejects.toMatchObject({
307
+ status: _common.HttpStatus.FORBIDDEN,
308
+ response: 'Client is unknown'
309
+ });
310
+ });
311
+ it('should forbid when client is disabled', async ()=>{
312
+ syncQueries.getClient.mockResolvedValue(makeClient({
313
+ enabled: false,
314
+ tokenExpiration: 5000
315
+ }));
316
+ await expect(service.authenticate(_auth.CLIENT_AUTH_TYPE.TOKEN, dto, ip, {})).rejects.toMatchObject({
317
+ status: _common.HttpStatus.FORBIDDEN,
318
+ response: 'Client is disabled'
319
+ });
320
+ });
321
+ it('should forbid when client token is expired', async ()=>{
322
+ ;
323
+ _shared.currentTimeStamp.mockReturnValue(1000);
324
+ syncQueries.getClient.mockResolvedValue(makeClient({
325
+ tokenExpiration: 1000
326
+ }));
327
+ await expect(service.authenticate(_auth.CLIENT_AUTH_TYPE.TOKEN, dto, ip, {})).rejects.toMatchObject({
328
+ status: _common.HttpStatus.FORBIDDEN,
329
+ response: _auth.CLIENT_TOKEN_EXPIRED_ERROR
330
+ });
331
+ });
332
+ it('should forbid when owner user does not exist', async ()=>{
333
+ syncQueries.getClient.mockResolvedValue(makeClient());
334
+ syncQueries.updateClientInfo.mockRejectedValueOnce(new Error('update-fails')); // silence expected
335
+ usersQueries.from.mockResolvedValue(null);
336
+ await expect(service.authenticate(_auth.CLIENT_AUTH_TYPE.TOKEN, dto, ip, {})).rejects.toMatchObject({
337
+ status: _common.HttpStatus.FORBIDDEN,
338
+ response: 'User does not exist'
339
+ });
340
+ });
341
+ it('should forbid when owner account is inactive', async ()=>{
342
+ syncQueries.getClient.mockResolvedValue(makeClient());
343
+ usersQueries.from.mockResolvedValue(makeUser({
344
+ isActive: false
345
+ }));
346
+ await expect(service.authenticate(_auth.CLIENT_AUTH_TYPE.TOKEN, dto, ip, {})).rejects.toMatchObject({
347
+ status: _common.HttpStatus.FORBIDDEN,
348
+ response: 'Account suspended or not authorized'
349
+ });
350
+ });
351
+ it('should forbid when owner lacks DESKTOP_APP permission', async ()=>{
352
+ mockHavePermission = false;
353
+ syncQueries.getClient.mockResolvedValue(makeClient());
354
+ usersQueries.from.mockResolvedValue(makeUser({
355
+ permissions: '',
356
+ role: 999
357
+ }));
358
+ await expect(service.authenticate(_auth.CLIENT_AUTH_TYPE.TOKEN, dto, ip, {})).rejects.toMatchObject({
359
+ status: _common.HttpStatus.FORBIDDEN,
360
+ response: 'Missing permission'
361
+ });
362
+ });
363
+ it('should perform COOKIE authentication and renew client token when needed', async ()=>{
364
+ syncQueries.getClient.mockResolvedValue(makeClient({
365
+ ownerId: 7
366
+ }));
367
+ usersQueries.from.mockResolvedValue(makeUser({
368
+ id: 7,
369
+ login: 'john',
370
+ email: 'john@doe',
371
+ firstName: 'John',
372
+ lastName: 'Doe'
373
+ }));
374
+ usersQueries.updateUserOrGuest.mockRejectedValueOnce(new Error('update-access-fail')); // silence expected
375
+ authManager.setCookies.mockResolvedValue({
376
+ access_token: 'a',
377
+ refresh_token: 'b'
378
+ });
379
+ jest.spyOn(service, 'renewTokenAndExpiration').mockResolvedValue('new-client-token');
380
+ const reply = {};
381
+ const r = await service.authenticate(_auth.CLIENT_AUTH_TYPE.COOKIE, dto, ip, reply);
382
+ expect(authManager.setCookies).toHaveBeenCalledTimes(1);
383
+ expect(service.renewTokenAndExpiration).toHaveBeenCalledTimes(1);
384
+ expect(r.client_token_update).toBe('new-client-token');
385
+ });
386
+ it('should perform TOKEN authentication and not renew when not needed', async ()=>{
387
+ syncQueries.getClient.mockResolvedValue(makeClient({
388
+ ownerId: 8
389
+ }));
390
+ usersQueries.from.mockResolvedValue(makeUser({
391
+ id: 8,
392
+ login: 'alice',
393
+ email: 'alice@doe',
394
+ firstName: 'Alice'
395
+ }));
396
+ authManager.getTokens.mockResolvedValue({
397
+ access_token: 'x',
398
+ refresh_token: 'y'
399
+ });
400
+ jest.spyOn(service, 'renewTokenAndExpiration').mockResolvedValue(undefined);
401
+ const r = await service.authenticate(_auth.CLIENT_AUTH_TYPE.TOKEN, dto, ip, {});
402
+ expect(authManager.getTokens).toHaveBeenCalledTimes(1);
403
+ expect(r.client_token_update).toBeUndefined();
404
+ });
405
+ it('should throw when auth type is unknown (else branch)', async ()=>{
406
+ syncQueries.getClient.mockResolvedValue(makeClient({
407
+ ownerId: 9
408
+ }));
409
+ usersQueries.from.mockResolvedValue(makeUser({
410
+ id: 9,
411
+ login: 'bob',
412
+ email: 'bob@doe',
413
+ firstName: 'Bob'
414
+ }));
415
+ jest.spyOn(service, 'renewTokenAndExpiration').mockResolvedValue(undefined);
416
+ await expect(service.authenticate('unknown', {
417
+ clientId: 'cid',
418
+ token: 'ctok'
419
+ }, ip, {})).rejects.toBeInstanceOf(TypeError);
420
+ });
50
421
  });
51
- it('should be defined', ()=>{
52
- expect(service).toBeDefined();
422
+ describe('getClients', ()=>{
423
+ it('should proxy to SyncQueries.getClients', async ()=>{
424
+ const fake = [
425
+ {
426
+ id: 'c1',
427
+ paths: []
428
+ }
429
+ ];
430
+ syncQueries.getClients.mockResolvedValue(fake);
431
+ const r = await service.getClients({
432
+ id: 1,
433
+ clientId: 'c1'
434
+ });
435
+ expect(r).toBe(fake);
436
+ expect(syncQueries.getClients).toHaveBeenCalledWith({
437
+ id: 1,
438
+ clientId: 'c1'
439
+ });
440
+ });
441
+ });
442
+ describe('renewTokenAndExpiration', ()=>{
443
+ const owner = {
444
+ id: 1,
445
+ login: 'bob'
446
+ };
447
+ it('should return undefined when token expiration is far enough', async ()=>{
448
+ ;
449
+ _shared.currentTimeStamp.mockReturnValue(1_000);
450
+ _functions.convertHumanTimeToSeconds.mockImplementation((v)=>v === '90d' ? 90 * 24 * 3600 : 0);
451
+ const client = {
452
+ id: 'cid',
453
+ tokenExpiration: 1_000 + 90 * 24 * 3600 + 1
454
+ };
455
+ expect(await service.renewTokenAndExpiration(client, owner)).toBeUndefined();
456
+ });
457
+ it('should renew token and return new value when close to expiration', async ()=>{
458
+ ;
459
+ _shared.currentTimeStamp.mockReturnValue(1_000);
460
+ _functions.convertHumanTimeToSeconds.mockImplementation((v)=>v === '90d' ? 90 * 24 * 3600 : v === '180d' ? 180 * 24 * 3600 : 0);
461
+ const client = {
462
+ id: 'cid',
463
+ tokenExpiration: 1_000 + 90 * 24 * 3600 - 1
464
+ };
465
+ syncQueries.renewClientTokenAndExpiration.mockResolvedValue(undefined);
466
+ const r = await service.renewTokenAndExpiration(client, owner);
467
+ expect(typeof r).toBe('string');
468
+ expect(r).toBeTruthy();
469
+ expect(syncQueries.renewClientTokenAndExpiration).toHaveBeenCalledWith('cid', r, expect.any(Number));
470
+ });
471
+ it('should throw Bad Request when renewal persistence fails', async ()=>{
472
+ ;
473
+ _shared.currentTimeStamp.mockReturnValue(1_000);
474
+ const client = {
475
+ id: 'cid',
476
+ tokenExpiration: 1_000
477
+ };
478
+ jest.spyOn(_nodecrypto.default, 'randomUUID').mockReturnValue('uuid-err');
479
+ syncQueries.renewClientTokenAndExpiration.mockRejectedValue(new Error('db fail'));
480
+ await expect(service.renewTokenAndExpiration(client, owner)).rejects.toMatchObject({
481
+ status: _common.HttpStatus.BAD_REQUEST
482
+ });
483
+ });
484
+ });
485
+ describe('deleteClient', ()=>{
486
+ it('should delete client successfully', async ()=>{
487
+ syncQueries.deleteClient.mockResolvedValue(undefined);
488
+ await expect(service.deleteClient({
489
+ id: 5
490
+ }, 'cid')).resolves.toBeUndefined();
491
+ expect(syncQueries.deleteClient).toHaveBeenCalledWith(5, 'cid');
492
+ });
493
+ it('should throw Internal Server Error when deletion fails', async ()=>{
494
+ syncQueries.deleteClient.mockRejectedValue(new Error('db error'));
495
+ await expect(service.deleteClient({
496
+ id: 5
497
+ }, 'cid')).rejects.toMatchObject({
498
+ status: _common.HttpStatus.INTERNAL_SERVER_ERROR
499
+ });
500
+ });
501
+ });
502
+ describe('checkAppStore', ()=>{
503
+ it('should return PUBLIC manifest when HTTP fetch succeeds', async ()=>{
504
+ setRepo(_store.APP_STORE_REPOSITORY.PUBLIC);
505
+ http.axiosRef.mockResolvedValue({
506
+ data: {
507
+ platform: {
508
+ win: []
509
+ }
510
+ }
511
+ });
512
+ const manifest = await service.checkAppStore();
513
+ expect(manifest).toBeTruthy();
514
+ expect(manifest.repository).toBe(_store.APP_STORE_REPOSITORY.PUBLIC);
515
+ expect(http.axiosRef).toHaveBeenCalled();
516
+ });
517
+ it('should return null when PUBLIC manifest fetch fails', async ()=>{
518
+ setRepo(_store.APP_STORE_REPOSITORY.PUBLIC);
519
+ http.axiosRef.mockRejectedValue(new Error('network'));
520
+ expect(await service.checkAppStore()).toBeNull();
521
+ });
522
+ it('should return null when LOCAL manifest file does not exist', async ()=>{
523
+ setRepo(_store.APP_STORE_REPOSITORY.LOCAL);
524
+ _files.isPathExists.mockResolvedValue(false);
525
+ expect(await service.checkAppStore()).toBeNull();
526
+ });
527
+ it('should return LOCAL manifest with rewritten URLs when file is valid', async ()=>{
528
+ setRepo(_store.APP_STORE_REPOSITORY.LOCAL);
529
+ _files.isPathExists.mockResolvedValue(true);
530
+ const raw = {
531
+ platform: {
532
+ win: [
533
+ {
534
+ package: 'desktop-win.exe'
535
+ },
536
+ {
537
+ package: 'cli-win.zip'
538
+ }
539
+ ],
540
+ linux: [
541
+ {
542
+ package: 'desktop-linux.AppImage'
543
+ }
544
+ ]
545
+ }
546
+ };
547
+ _promises.default.readFile.mockResolvedValue(JSON.stringify(raw));
548
+ const manifest = await service.checkAppStore();
549
+ expect(manifest.repository).toBe(_store.APP_STORE_REPOSITORY.LOCAL);
550
+ expect(manifest.platform.win[0].url.startsWith(_store.APP_STORE_DIRNAME)).toBe(true);
551
+ expect(manifest.platform.win[0].url.endsWith('desktop-win.exe')).toBe(true);
552
+ expect(manifest.platform.win[1].url.startsWith(_store.APP_STORE_DIRNAME)).toBe(true);
553
+ expect(manifest.platform.win[1].url.endsWith('cli-win.zip')).toBe(true);
554
+ expect(manifest.platform.linux[0].url.startsWith(_store.APP_STORE_DIRNAME)).toBe(true);
555
+ expect(manifest.platform.linux[0].url.endsWith('desktop-linux.AppImage')).toBe(true);
556
+ });
557
+ it('should return null when LOCAL manifest cannot be parsed', async ()=>{
558
+ setRepo(_store.APP_STORE_REPOSITORY.LOCAL);
559
+ _files.isPathExists.mockResolvedValue(true);
560
+ _promises.default.readFile.mockRejectedValue(new Error('fs error'));
561
+ expect(await service.checkAppStore()).toBeNull();
562
+ });
563
+ it('should rewrite desktop packages under desktop/os when package starts with "desktop"', async ()=>{
564
+ setRepo(_store.APP_STORE_REPOSITORY.LOCAL);
565
+ _files.isPathExists.mockResolvedValue(true);
566
+ const raw = {
567
+ platform: {
568
+ win: [
569
+ {
570
+ package: `${_sync.SYNC_CLIENT_TYPE.DESKTOP}-win.exe`
571
+ }
572
+ ],
573
+ mac: [
574
+ {
575
+ package: `${_sync.SYNC_CLIENT_TYPE.DESKTOP}-mac.dmg`
576
+ }
577
+ ],
578
+ linux: [
579
+ {
580
+ package: `${_sync.SYNC_CLIENT_TYPE.DESKTOP}-linux.AppImage`
581
+ }
582
+ ]
583
+ }
584
+ };
585
+ _promises.default.readFile.mockResolvedValue(JSON.stringify(raw));
586
+ const manifest = await service.checkAppStore();
587
+ expect(manifest).toBeTruthy();
588
+ expect(manifest.repository).toBe(_store.APP_STORE_REPOSITORY.LOCAL);
589
+ expect(manifest.platform.win[0].url).toBe(`${_store.APP_STORE_DIRNAME}/${_sync.SYNC_CLIENT_TYPE.DESKTOP}/win/${_sync.SYNC_CLIENT_TYPE.DESKTOP}-win.exe`);
590
+ expect(manifest.platform.mac[0].url).toBe(`${_store.APP_STORE_DIRNAME}/${_sync.SYNC_CLIENT_TYPE.DESKTOP}/mac/${_sync.SYNC_CLIENT_TYPE.DESKTOP}-mac.dmg`);
591
+ expect(manifest.platform.linux[0].url).toBe(`${_store.APP_STORE_DIRNAME}/${_sync.SYNC_CLIENT_TYPE.DESKTOP}/linux/${_sync.SYNC_CLIENT_TYPE.DESKTOP}-linux.AppImage`);
592
+ });
53
593
  });
54
594
  });
55
595