@sync-in/server 1.4.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +2 -1
  3. package/package.json +5 -5
  4. package/server/applications/comments/comments.controller.spec.js +103 -4
  5. package/server/applications/comments/comments.controller.spec.js.map +1 -1
  6. package/server/applications/comments/services/comments-manager.service.spec.js +409 -9
  7. package/server/applications/comments/services/comments-manager.service.spec.js.map +1 -1
  8. package/server/applications/files/adapters/files-indexer-mysql.service.spec.js +333 -0
  9. package/server/applications/files/adapters/files-indexer-mysql.service.spec.js.map +1 -0
  10. package/server/applications/files/constants/routes.js +6 -1
  11. package/server/applications/files/constants/routes.js.map +1 -1
  12. package/server/applications/files/files-only-office.controller.js +11 -0
  13. package/server/applications/files/files-only-office.controller.js.map +1 -1
  14. package/server/applications/files/files-only-office.controller.spec.js +97 -3
  15. package/server/applications/files/files-only-office.controller.spec.js.map +1 -1
  16. package/server/applications/files/files-tasks.controller.spec.js +91 -1
  17. package/server/applications/files/files-tasks.controller.spec.js.map +1 -1
  18. package/server/applications/files/files.controller.spec.js +268 -46
  19. package/server/applications/files/files.controller.spec.js.map +1 -1
  20. package/server/applications/files/guards/files-only-office.guard.spec.js +77 -1
  21. package/server/applications/files/guards/files-only-office.guard.spec.js.map +1 -1
  22. package/server/applications/files/services/files-only-office-manager.service.js +5 -0
  23. package/server/applications/files/services/files-only-office-manager.service.js.map +1 -1
  24. package/server/applications/links/links.controller.spec.js +91 -58
  25. package/server/applications/links/links.controller.spec.js.map +1 -1
  26. package/server/applications/links/services/links-manager.service.js +4 -6
  27. package/server/applications/links/services/links-manager.service.js.map +1 -1
  28. package/server/applications/links/services/links-manager.service.spec.js +378 -14
  29. package/server/applications/links/services/links-manager.service.spec.js.map +1 -1
  30. package/server/applications/links/services/links-queries.service.js +1 -1
  31. package/server/applications/links/services/links-queries.service.js.map +1 -1
  32. package/server/applications/notifications/notifications.controller.spec.js +56 -1
  33. package/server/applications/notifications/notifications.controller.spec.js.map +1 -1
  34. package/server/applications/notifications/services/notifications-manager.service.spec.js +461 -5
  35. package/server/applications/notifications/services/notifications-manager.service.spec.js.map +1 -1
  36. package/server/applications/shares/services/shares-manager.service.spec.js +590 -14
  37. package/server/applications/shares/services/shares-manager.service.spec.js.map +1 -1
  38. package/server/applications/sync/interceptors/sync-diff-gzip-body.interceptor.spec.js +120 -0
  39. package/server/applications/sync/interceptors/sync-diff-gzip-body.interceptor.spec.js.map +1 -0
  40. package/server/applications/sync/services/sync-clients-manager.service.spec.js +548 -8
  41. package/server/applications/sync/services/sync-clients-manager.service.spec.js.map +1 -1
  42. package/server/applications/sync/services/sync-manager.service.spec.js +837 -5
  43. package/server/applications/sync/services/sync-manager.service.spec.js.map +1 -1
  44. package/server/applications/sync/services/sync-paths-manager.service.spec.js +900 -7
  45. package/server/applications/sync/services/sync-paths-manager.service.spec.js.map +1 -1
  46. package/server/applications/users/services/admin-users-manager.service.js +22 -24
  47. package/server/applications/users/services/admin-users-manager.service.js.map +1 -1
  48. package/server/applications/users/services/admin-users-manager.service.spec.js +763 -17
  49. package/server/applications/users/services/admin-users-manager.service.spec.js.map +1 -1
  50. package/server/applications/users/services/users-manager.service.js +1 -1
  51. package/server/applications/users/services/users-manager.service.js.map +1 -1
  52. package/server/applications/users/services/users-manager.service.spec.js +938 -49
  53. package/server/applications/users/services/users-manager.service.spec.js.map +1 -1
  54. package/server/applications/webdav/decorators/if-header.decorator.js +4 -1
  55. package/server/applications/webdav/decorators/if-header.decorator.js.map +1 -1
  56. package/server/applications/webdav/filters/webdav.filter.spec.js +77 -0
  57. package/server/applications/webdav/filters/webdav.filter.spec.js.map +1 -0
  58. package/server/applications/webdav/guards/webdav-protocol.guard.js +3 -7
  59. package/server/applications/webdav/guards/webdav-protocol.guard.js.map +1 -1
  60. package/server/applications/webdav/guards/webdav-protocol.guard.spec.js +580 -0
  61. package/server/applications/webdav/guards/webdav-protocol.guard.spec.js.map +1 -0
  62. package/server/applications/webdav/services/webdav-methods.service.spec.js +1582 -3
  63. package/server/applications/webdav/services/webdav-methods.service.spec.js.map +1 -1
  64. package/server/applications/webdav/services/webdav-spaces.service.spec.js +390 -2
  65. package/server/applications/webdav/services/webdav-spaces.service.spec.js.map +1 -1
  66. package/server/applications/webdav/webdav.controller.js +2 -2
  67. package/server/applications/webdav/webdav.controller.js.map +1 -1
  68. package/server/authentication/guards/auth-basic.guard.js.map +1 -1
  69. package/server/authentication/guards/auth-digest.guard.js +1 -2
  70. package/server/authentication/guards/auth-digest.guard.js.map +1 -1
  71. package/server/authentication/guards/auth-local.guard.js.map +1 -1
  72. package/server/infrastructure/context/interceptors/context.interceptor.spec.js +135 -0
  73. package/server/infrastructure/context/interceptors/context.interceptor.spec.js.map +1 -0
  74. package/static/3rdpartylicenses.txt +26 -26
  75. package/static/assets/pdfjs/build/pdf.mjs +1177 -255
  76. package/static/assets/pdfjs/build/pdf.mjs.map +1 -1
  77. package/static/assets/pdfjs/build/pdf.sandbox.mjs +25 -2
  78. package/static/assets/pdfjs/build/pdf.sandbox.mjs.map +1 -1
  79. package/static/assets/pdfjs/build/pdf.worker.mjs +140 -16
  80. package/static/assets/pdfjs/build/pdf.worker.mjs.map +1 -1
  81. package/static/assets/pdfjs/version +1 -1
  82. package/static/assets/pdfjs/web/debugger.css +31 -0
  83. package/static/assets/pdfjs/web/debugger.mjs +144 -2
  84. package/static/assets/pdfjs/web/images/comment-editButton.svg +6 -1
  85. package/static/assets/pdfjs/web/locale/ach/viewer.ftl +0 -63
  86. package/static/assets/pdfjs/web/locale/af/viewer.ftl +0 -71
  87. package/static/assets/pdfjs/web/locale/an/viewer.ftl +0 -63
  88. package/static/assets/pdfjs/web/locale/ast/viewer.ftl +0 -60
  89. package/static/assets/pdfjs/web/locale/az/viewer.ftl +0 -63
  90. package/static/assets/pdfjs/web/locale/be/viewer.ftl +38 -0
  91. package/static/assets/pdfjs/web/locale/bg/viewer.ftl +0 -37
  92. package/static/assets/pdfjs/web/locale/bn/viewer.ftl +0 -63
  93. package/static/assets/pdfjs/web/locale/bo/viewer.ftl +0 -63
  94. package/static/assets/pdfjs/web/locale/br/viewer.ftl +0 -37
  95. package/static/assets/pdfjs/web/locale/brx/viewer.ftl +0 -63
  96. package/static/assets/pdfjs/web/locale/bs/viewer.ftl +22 -0
  97. package/static/assets/pdfjs/web/locale/ca/viewer.ftl +0 -54
  98. package/static/assets/pdfjs/web/locale/cak/viewer.ftl +0 -54
  99. package/static/assets/pdfjs/web/locale/ckb/viewer.ftl +0 -63
  100. package/static/assets/pdfjs/web/locale/cs/viewer.ftl +38 -0
  101. package/static/assets/pdfjs/web/locale/cy/viewer.ftl +38 -0
  102. package/static/assets/pdfjs/web/locale/da/viewer.ftl +38 -0
  103. package/static/assets/pdfjs/web/locale/de/viewer.ftl +38 -0
  104. package/static/assets/pdfjs/web/locale/dsb/viewer.ftl +38 -0
  105. package/static/assets/pdfjs/web/locale/el/viewer.ftl +38 -0
  106. package/static/assets/pdfjs/web/locale/en-CA/viewer.ftl +38 -0
  107. package/static/assets/pdfjs/web/locale/en-GB/viewer.ftl +38 -0
  108. package/static/assets/pdfjs/web/locale/en-US/viewer.ftl +25 -0
  109. package/static/assets/pdfjs/web/locale/eo/viewer.ftl +38 -0
  110. package/static/assets/pdfjs/web/locale/es-AR/viewer.ftl +38 -0
  111. package/static/assets/pdfjs/web/locale/es-CL/viewer.ftl +38 -0
  112. package/static/assets/pdfjs/web/locale/es-MX/viewer.ftl +0 -6
  113. package/static/assets/pdfjs/web/locale/et/viewer.ftl +0 -57
  114. package/static/assets/pdfjs/web/locale/fa/viewer.ftl +0 -37
  115. package/static/assets/pdfjs/web/locale/ff/viewer.ftl +0 -63
  116. package/static/assets/pdfjs/web/locale/fi/viewer.ftl +38 -0
  117. package/static/assets/pdfjs/web/locale/fr/viewer.ftl +38 -0
  118. package/static/assets/pdfjs/web/locale/fy-NL/viewer.ftl +38 -0
  119. package/static/assets/pdfjs/web/locale/ga-IE/viewer.ftl +0 -71
  120. package/static/assets/pdfjs/web/locale/gd/viewer.ftl +0 -54
  121. package/static/assets/pdfjs/web/locale/gl/viewer.ftl +8 -0
  122. package/static/assets/pdfjs/web/locale/gn/viewer.ftl +38 -0
  123. package/static/assets/pdfjs/web/locale/gu-IN/viewer.ftl +0 -63
  124. package/static/assets/pdfjs/web/locale/he/viewer.ftl +38 -0
  125. package/static/assets/pdfjs/web/locale/hi-IN/viewer.ftl +0 -60
  126. package/static/assets/pdfjs/web/locale/hsb/viewer.ftl +38 -0
  127. package/static/assets/pdfjs/web/locale/hu/viewer.ftl +38 -0
  128. package/static/assets/pdfjs/web/locale/hy-AM/viewer.ftl +0 -49
  129. package/static/assets/pdfjs/web/locale/hye/viewer.ftl +0 -60
  130. package/static/assets/pdfjs/web/locale/ia/viewer.ftl +38 -0
  131. package/static/assets/pdfjs/web/locale/is/viewer.ftl +0 -3
  132. package/static/assets/pdfjs/web/locale/it/viewer.ftl +31 -0
  133. package/static/assets/pdfjs/web/locale/ja/viewer.ftl +8 -0
  134. package/static/assets/pdfjs/web/locale/ka/viewer.ftl +48 -10
  135. package/static/assets/pdfjs/web/locale/kab/viewer.ftl +5 -0
  136. package/static/assets/pdfjs/web/locale/kk/viewer.ftl +8 -0
  137. package/static/assets/pdfjs/web/locale/km/viewer.ftl +0 -63
  138. package/static/assets/pdfjs/web/locale/kn/viewer.ftl +0 -71
  139. package/static/assets/pdfjs/web/locale/ko/viewer.ftl +38 -0
  140. package/static/assets/pdfjs/web/locale/lij/viewer.ftl +0 -63
  141. package/static/assets/pdfjs/web/locale/lo/viewer.ftl +0 -54
  142. package/static/assets/pdfjs/web/locale/lt/viewer.ftl +0 -60
  143. package/static/assets/pdfjs/web/locale/ltg/viewer.ftl +0 -63
  144. package/static/assets/pdfjs/web/locale/lv/viewer.ftl +0 -63
  145. package/static/assets/pdfjs/web/locale/meh/viewer.ftl +0 -75
  146. package/static/assets/pdfjs/web/locale/mk/viewer.ftl +0 -63
  147. package/static/assets/pdfjs/web/locale/ml/viewer.ftl +0 -3
  148. package/static/assets/pdfjs/web/locale/mr/viewer.ftl +0 -63
  149. package/static/assets/pdfjs/web/locale/ms/viewer.ftl +0 -63
  150. package/static/assets/pdfjs/web/locale/my/viewer.ftl +0 -71
  151. package/static/assets/pdfjs/web/locale/nb-NO/viewer.ftl +44 -6
  152. package/static/assets/pdfjs/web/locale/ne-NP/viewer.ftl +0 -71
  153. package/static/assets/pdfjs/web/locale/nl/viewer.ftl +38 -0
  154. package/static/assets/pdfjs/web/locale/nn-NO/viewer.ftl +45 -1
  155. package/static/assets/pdfjs/web/locale/oc/viewer.ftl +0 -31
  156. package/static/assets/pdfjs/web/locale/pa-IN/viewer.ftl +38 -0
  157. package/static/assets/pdfjs/web/locale/pl/viewer.ftl +39 -1
  158. package/static/assets/pdfjs/web/locale/pt-BR/viewer.ftl +38 -0
  159. package/static/assets/pdfjs/web/locale/ro/viewer.ftl +355 -1
  160. package/static/assets/pdfjs/web/locale/ru/viewer.ftl +38 -0
  161. package/static/assets/pdfjs/web/locale/sat/viewer.ftl +0 -54
  162. package/static/assets/pdfjs/web/locale/sc/viewer.ftl +0 -38
  163. package/static/assets/pdfjs/web/locale/scn/viewer.ftl +0 -92
  164. package/static/assets/pdfjs/web/locale/sco/viewer.ftl +0 -60
  165. package/static/assets/pdfjs/web/locale/si/viewer.ftl +0 -51
  166. package/static/assets/pdfjs/web/locale/sk/viewer.ftl +38 -0
  167. package/static/assets/pdfjs/web/locale/skr/viewer.ftl +0 -27
  168. package/static/assets/pdfjs/web/locale/sl/viewer.ftl +8 -0
  169. package/static/assets/pdfjs/web/locale/son/viewer.ftl +0 -71
  170. package/static/assets/pdfjs/web/locale/sr/viewer.ftl +0 -33
  171. package/static/assets/pdfjs/web/locale/sv-SE/viewer.ftl +38 -0
  172. package/static/assets/pdfjs/web/locale/szl/viewer.ftl +0 -63
  173. package/static/assets/pdfjs/web/locale/ta/viewer.ftl +0 -63
  174. package/static/assets/pdfjs/web/locale/te/viewer.ftl +0 -60
  175. package/static/assets/pdfjs/web/locale/tg/viewer.ftl +38 -0
  176. package/static/assets/pdfjs/web/locale/tl/viewer.ftl +0 -63
  177. package/static/assets/pdfjs/web/locale/tr/viewer.ftl +40 -2
  178. package/static/assets/pdfjs/web/locale/trs/viewer.ftl +0 -72
  179. package/static/assets/pdfjs/web/locale/ur/viewer.ftl +0 -60
  180. package/static/assets/pdfjs/web/locale/uz/viewer.ftl +0 -71
  181. package/static/assets/pdfjs/web/locale/vi/viewer.ftl +38 -0
  182. package/static/assets/pdfjs/web/locale/wo/viewer.ftl +0 -77
  183. package/static/assets/pdfjs/web/locale/xh/viewer.ftl +0 -71
  184. package/static/assets/pdfjs/web/locale/zh-CN/viewer.ftl +38 -0
  185. package/static/assets/pdfjs/web/locale/zh-TW/viewer.ftl +38 -0
  186. package/static/assets/pdfjs/web/viewer.css +649 -120
  187. package/static/assets/pdfjs/web/viewer.html +19 -0
  188. package/static/assets/pdfjs/web/viewer.mjs +489 -38
  189. package/static/assets/pdfjs/web/viewer.mjs.map +1 -1
  190. package/static/chunk-22EANI6R.js +1 -0
  191. package/static/{chunk-N2LYWNTC.js → chunk-2456KVFZ.js} +1 -1
  192. package/static/{chunk-YCINY2YI.js → chunk-2LVCLKCK.js} +1 -1
  193. package/static/{chunk-5YKWZT33.js → chunk-2V5S7DWD.js} +1 -1
  194. package/static/{chunk-3GC2BQZD.js → chunk-44YDXGNZ.js} +1 -1
  195. package/static/{chunk-W3QXNDI5.js → chunk-4LSJLWYV.js} +1 -1
  196. package/static/{chunk-T55FAU2O.js → chunk-4UT5VH7R.js} +1 -1
  197. package/static/{chunk-VMQMD36Z.js → chunk-5GOMMRRE.js} +1 -1
  198. package/static/{chunk-TXPODW5Q.js → chunk-5J4VRDKB.js} +1 -1
  199. package/static/{chunk-FQ4AFNGE.js → chunk-6PVKNZ7Q.js} +1 -1
  200. package/static/{chunk-XE5YHU5J.js → chunk-BIUNUYZ5.js} +1 -1
  201. package/static/{chunk-X43VWRFP.js → chunk-DFQKHCDR.js} +1 -1
  202. package/static/{chunk-TDQAEVZN.js → chunk-EE2TDTY4.js} +1 -1
  203. package/static/{chunk-MOVWEZ7J.js → chunk-ESNDJ5T6.js} +1 -1
  204. package/static/{chunk-TCFKH6K6.js → chunk-GDKKLLEU.js} +1 -1
  205. package/static/{chunk-VHYIXL7R.js → chunk-GSR2MCQG.js} +1 -1
  206. package/static/{chunk-LJIGRUEF.js → chunk-HR7KS5BR.js} +1 -1
  207. package/static/chunk-HW2H3ISM.js +559 -0
  208. package/static/{chunk-HZA7R43P.js → chunk-IMB3C547.js} +1 -1
  209. package/static/{chunk-B2Y2RNFP.js → chunk-J4ALHUDX.js} +1 -1
  210. package/static/{chunk-PF4K7MVG.js → chunk-KP6LSQTK.js} +1 -1
  211. package/static/{chunk-C23BPTJZ.js → chunk-LUZCOHFN.js} +1 -1
  212. package/static/{chunk-GBCYYDCI.js → chunk-MHSCCXVL.js} +1 -1
  213. package/static/{chunk-PY3BGNJN.js → chunk-OMRQYBXV.js} +1 -1
  214. package/static/chunk-P7CTJ5BG.js +27 -0
  215. package/static/{chunk-Y2CDUS4J.js → chunk-P7PX67IR.js} +4 -4
  216. package/static/{chunk-VMUOUCEI.js → chunk-PPO7DBVO.js} +1 -1
  217. package/static/{chunk-TTQ37MUV.js → chunk-RSS6GYNE.js} +1 -1
  218. package/static/{chunk-WWIC7UW3.js → chunk-SLGGINMR.js} +1 -1
  219. package/static/{chunk-KZQCFEPT.js → chunk-UHD5XD3G.js} +1 -1
  220. package/static/{chunk-TNW2CGK6.js → chunk-UPYYAJCJ.js} +1 -1
  221. package/static/{chunk-6F55D74O.js → chunk-VHYPQ3D4.js} +1 -1
  222. package/static/{chunk-DGVNNICG.js → chunk-YQSDS6BO.js} +1 -1
  223. package/static/{chunk-MTRNPGS4.js → chunk-ZC5NIT55.js} +1 -1
  224. package/static/index.html +1 -1
  225. package/static/main-FYD34UEC.js +7 -0
  226. package/static/chunk-RSNLYAN6.js +0 -560
  227. package/static/chunk-WHMS3PJ3.js +0 -24
  228. package/static/chunk-ZZ3LHYOY.js +0 -1
  229. package/static/main-7LDKYVXO.js +0 -10
@@ -6,19 +6,129 @@
6
6
  Object.defineProperty(exports, "__esModule", {
7
7
  value: true
8
8
  });
9
+ const _common = require("@nestjs/common");
9
10
  const _testing = require("@nestjs/testing");
10
- const _cacheservice = require("../../../infrastructure/cache/services/cache.service");
11
+ const _functions = /*#__PURE__*/ _interop_require_wildcard(require("../../../common/functions"));
11
12
  const _contextmanagerservice = require("../../../infrastructure/context/services/context-manager.service");
12
13
  const _constants = require("../../../infrastructure/database/constants");
13
- const _filesqueriesservice = require("../../files/services/files-queries.service");
14
+ const _links = require("../../links/constants/links");
14
15
  const _linksqueriesservice = require("../../links/services/links-queries.service");
15
16
  const _notificationsmanagerservice = require("../../notifications/services/notifications-manager.service");
16
17
  const _spacesqueriesservice = require("../../spaces/services/spaces-queries.service");
18
+ const _permissions = /*#__PURE__*/ _interop_require_wildcard(require("../../spaces/utils/permissions"));
19
+ const _user = require("../../users/constants/user");
17
20
  const _usersqueriesservice = require("../../users/services/users-queries.service");
21
+ const _shares = require("../constants/shares");
18
22
  const _sharesmanagerservice = require("./shares-manager.service");
19
23
  const _sharesqueriesservice = require("./shares-queries.service");
24
+ function _getRequireWildcardCache(nodeInterop) {
25
+ if (typeof WeakMap !== "function") return null;
26
+ var cacheBabelInterop = new WeakMap();
27
+ var cacheNodeInterop = new WeakMap();
28
+ return (_getRequireWildcardCache = function(nodeInterop) {
29
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
30
+ })(nodeInterop);
31
+ }
32
+ function _interop_require_wildcard(obj, nodeInterop) {
33
+ if (!nodeInterop && obj && obj.__esModule) {
34
+ return obj;
35
+ }
36
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
37
+ return {
38
+ default: obj
39
+ };
40
+ }
41
+ var cache = _getRequireWildcardCache(nodeInterop);
42
+ if (cache && cache.has(obj)) {
43
+ return cache.get(obj);
44
+ }
45
+ var newObj = {
46
+ __proto__: null
47
+ };
48
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
49
+ for(var key in obj){
50
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
51
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
52
+ if (desc && (desc.get || desc.set)) {
53
+ Object.defineProperty(newObj, key, desc);
54
+ } else {
55
+ newObj[key] = obj[key];
56
+ }
57
+ }
58
+ }
59
+ newObj.default = obj;
60
+ if (cache) {
61
+ cache.set(obj, newObj);
62
+ }
63
+ return newObj;
64
+ }
65
+ // Mock classes and utility modules used by SharesManager
66
+ jest.mock('../../spaces/models/space-env.model', ()=>({
67
+ SpaceEnv: jest.fn().mockImplementation(()=>({
68
+ setPermissions: jest.fn(),
69
+ envPermissions: 'ENV_PERMS'
70
+ }))
71
+ }));
72
+ jest.mock('../../spaces/utils/permissions', ()=>({
73
+ havePermission: jest.fn(),
74
+ haveSpacePermission: jest.fn(),
75
+ removePermissions: jest.fn(()=>'trimmed')
76
+ }));
77
+ jest.mock('../../../common/functions', ()=>{
78
+ const actual = jest.requireActual('../../../common/functions');
79
+ return {
80
+ ...actual,
81
+ generateShortUUID: jest.fn(),
82
+ hashPassword: jest.fn(),
83
+ intersectPermissions: jest.fn()
84
+ };
85
+ });
20
86
  describe(_sharesmanagerservice.SharesManager.name, ()=>{
21
87
  let service;
88
+ // Mocks
89
+ const contextManagerMock = {
90
+ get: jest.fn()
91
+ };
92
+ const notificationsManagerMock = {
93
+ create: jest.fn().mockResolvedValue(undefined),
94
+ sendEmailNotification: jest.fn().mockResolvedValue(undefined)
95
+ };
96
+ const spacesQueriesMock = {
97
+ permissions: jest.fn()
98
+ };
99
+ const usersQueriesMock = {
100
+ createUserOrGuest: jest.fn(),
101
+ deleteGuestLink: jest.fn(),
102
+ usersWhitelist: jest.fn().mockResolvedValue([]),
103
+ groupsWhitelist: jest.fn().mockResolvedValue([]),
104
+ allUserIdsFromGroupsAndSubGroups: jest.fn().mockResolvedValue([])
105
+ };
106
+ const linksQueriesMock = {
107
+ isUniqueUUID: jest.fn(),
108
+ isReservedUUID: jest.fn(),
109
+ allLinksFromSpaceOrShare: jest.fn(),
110
+ createLinkToSpaceOrShare: jest.fn(),
111
+ updateLinkFromSpaceOrShare: jest.fn(),
112
+ linkFromShare: jest.fn(),
113
+ linkFromSpace: jest.fn()
114
+ };
115
+ const sharesQueriesMock = {
116
+ permissions: jest.fn(),
117
+ listShareLinks: jest.fn(),
118
+ getShareWithMembers: jest.fn(),
119
+ createShare: jest.fn(),
120
+ updateShare: jest.fn(),
121
+ selectShares: jest.fn(),
122
+ deleteShare: jest.fn(),
123
+ updateMember: jest.fn(),
124
+ updateMembers: jest.fn(),
125
+ shareExistsForOwner: jest.fn(),
126
+ childExistsForShareOwner: jest.fn()
127
+ };
128
+ const user = {
129
+ id: 1,
130
+ isAdmin: false
131
+ };
22
132
  beforeAll(async ()=>{
23
133
  const module = await _testing.Test.createTestingModule({
24
134
  providers: [
@@ -26,31 +136,497 @@ describe(_sharesmanagerservice.SharesManager.name, ()=>{
26
136
  provide: _constants.DB_TOKEN_PROVIDER,
27
137
  useValue: {}
28
138
  },
29
- {
30
- provide: _cacheservice.Cache,
31
- useValue: {}
32
- },
33
139
  {
34
140
  provide: _contextmanagerservice.ContextManager,
35
- useValue: {}
141
+ useValue: contextManagerMock
36
142
  },
37
143
  {
38
144
  provide: _notificationsmanagerservice.NotificationsManager,
39
- useValue: {}
145
+ useValue: notificationsManagerMock
146
+ },
147
+ {
148
+ provide: _spacesqueriesservice.SpacesQueries,
149
+ useValue: spacesQueriesMock
150
+ },
151
+ {
152
+ provide: _usersqueriesservice.UsersQueries,
153
+ useValue: usersQueriesMock
154
+ },
155
+ {
156
+ provide: _linksqueriesservice.LinksQueries,
157
+ useValue: linksQueriesMock
158
+ },
159
+ {
160
+ provide: _sharesqueriesservice.SharesQueries,
161
+ useValue: sharesQueriesMock
40
162
  },
41
- _spacesqueriesservice.SpacesQueries,
42
- _filesqueriesservice.FilesQueries,
43
- _usersqueriesservice.UsersQueries,
44
- _sharesmanagerservice.SharesManager,
45
- _sharesqueriesservice.SharesQueries,
46
- _linksqueriesservice.LinksQueries
163
+ _sharesmanagerservice.SharesManager
47
164
  ]
48
165
  }).compile();
166
+ module.useLogger([
167
+ 'fatal'
168
+ ]);
49
169
  service = module.get(_sharesmanagerservice.SharesManager);
50
170
  });
171
+ beforeEach(()=>{
172
+ jest.clearAllMocks();
173
+ });
51
174
  it('should be defined', ()=>{
52
175
  expect(service).toBeDefined();
53
176
  });
177
+ describe('setAllowedPermissions', ()=>{
178
+ it('sets all operations when the user is the file owner (personal space case)', async ()=>{
179
+ const share = {
180
+ file: {
181
+ ownerId: user.id,
182
+ permissions: ''
183
+ }
184
+ };
185
+ await service.setAllowedPermissions(user, share);
186
+ expect(share.file.permissions).toBe(_shares.SHARE_ALL_OPERATIONS);
187
+ });
188
+ it('uses space permissions when file has a space alias', async ()=>{
189
+ spacesQueriesMock.permissions.mockResolvedValueOnce({
190
+ any: 'thing'
191
+ });
192
+ const share = {
193
+ file: {
194
+ ownerId: 999,
195
+ space: {
196
+ alias: 'space-1',
197
+ root: {
198
+ alias: 'root'
199
+ }
200
+ },
201
+ permissions: undefined
202
+ }
203
+ };
204
+ await service.setAllowedPermissions(user, share);
205
+ expect(spacesQueriesMock.permissions).toHaveBeenCalledWith(user.id, 'space-1', 'root');
206
+ expect(share.file.ownerId).toBeNull();
207
+ expect(share.file.permissions).toBe('ENV_PERMS');
208
+ });
209
+ it('uses parent share permissions when parent alias is present', async ()=>{
210
+ sharesQueriesMock.permissions.mockResolvedValueOnce({
211
+ permissions: 'PARENT_PERMS'
212
+ });
213
+ const share = {
214
+ ownerId: 77,
215
+ parent: {
216
+ alias: 'parent-share'
217
+ },
218
+ file: {
219
+ permissions: undefined
220
+ }
221
+ };
222
+ await service.setAllowedPermissions(user, share);
223
+ expect(sharesQueriesMock.permissions).toHaveBeenCalledWith(user.id, 'parent-share', +user.isAdmin);
224
+ expect(share.file.permissions).toBe('PARENT_PERMS');
225
+ });
226
+ it('throws Bad Request when missing required information', async ()=>{
227
+ const share = {
228
+ file: {},
229
+ parent: {}
230
+ };
231
+ await expect(service.setAllowedPermissions(user, share)).rejects.toEqual(new _common.HttpException('Missing information', _common.HttpStatus.BAD_REQUEST));
232
+ });
233
+ });
234
+ describe('getShareWithMembers', ()=>{
235
+ it('returns the share and calls setAllowedPermissions', async ()=>{
236
+ const share = {
237
+ id: 10,
238
+ file: {}
239
+ };
240
+ sharesQueriesMock.getShareWithMembers.mockResolvedValueOnce(share);
241
+ const spy = jest.spyOn(service, 'setAllowedPermissions').mockResolvedValueOnce(void 0);
242
+ const result = await service.getShareWithMembers(user, 10, true);
243
+ expect(result).toBe(share);
244
+ expect(spy).toHaveBeenCalledWith(user, share, true);
245
+ });
246
+ it('throws Forbidden when share is not found or not authorized', async ()=>{
247
+ sharesQueriesMock.getShareWithMembers.mockResolvedValueOnce(null);
248
+ await expect(service.getShareWithMembers(user, 99, false)).rejects.toEqual(new _common.HttpException('Not authorized', _common.HttpStatus.FORBIDDEN));
249
+ });
250
+ });
251
+ describe('generateLinkUUID', ()=>{
252
+ it('loops until a unique UUID is found', async ()=>{
253
+ ;
254
+ _functions.generateShortUUID.mockReturnValueOnce('aaa').mockReturnValueOnce('bbb');
255
+ linksQueriesMock.isUniqueUUID.mockResolvedValueOnce(false).mockResolvedValueOnce(true);
256
+ const { uuid } = await service.generateLinkUUID(user.id);
257
+ expect(linksQueriesMock.isUniqueUUID).toHaveBeenCalledTimes(2);
258
+ expect(linksQueriesMock.isUniqueUUID).toHaveBeenNthCalledWith(1, user.id, 'aaa');
259
+ expect(linksQueriesMock.isUniqueUUID).toHaveBeenNthCalledWith(2, user.id, 'bbb');
260
+ expect(uuid).toBe('bbb');
261
+ });
262
+ });
263
+ describe('getShareLink', ()=>{
264
+ it('returns the share link and trims unsupported permissions', async ()=>{
265
+ const shareLink = {
266
+ id: 5,
267
+ file: {
268
+ permissions: 'ORIG'
269
+ }
270
+ };
271
+ sharesQueriesMock.listShareLinks.mockResolvedValueOnce(shareLink);
272
+ const spy = jest.spyOn(service, 'setAllowedPermissions').mockResolvedValueOnce(void 0);
273
+ const result = await service.getShareLink(user, 5);
274
+ expect(spy).toHaveBeenCalledWith(user, shareLink);
275
+ expect(result).toBe(shareLink);
276
+ expect(result.file.permissions).toBe('trimmed');
277
+ expect(_permissions.removePermissions.mock.calls[0][0]).toBe('ORIG');
278
+ });
279
+ it('throws Forbidden when link is not found', async ()=>{
280
+ sharesQueriesMock.listShareLinks.mockResolvedValueOnce(null);
281
+ await expect(service.getShareLink(user, 123)).rejects.toEqual(new _common.HttpException('Not authorized', _common.HttpStatus.FORBIDDEN));
282
+ });
283
+ });
284
+ describe('updateLinkFromSpaceOrShare (from API)', ()=>{
285
+ it('intersects permissions and returns updated link object', async ()=>{
286
+ const baseLink = {
287
+ id: 42,
288
+ name: 'old',
289
+ email: 'x@x',
290
+ requireAuth: false,
291
+ limitAccess: null,
292
+ expiresAt: null,
293
+ permissions: 'OLD',
294
+ shareName: 'OldShare',
295
+ shareDescription: 'OldDesc'
296
+ };
297
+ jest.spyOn(service, 'getLinkFromSpaceOrShare').mockResolvedValueOnce(baseLink);
298
+ jest.spyOn(service, 'getShareLink').mockResolvedValueOnce({
299
+ file: {
300
+ permissions: 'SHARE_PERMS'
301
+ }
302
+ });
303
+ _functions.intersectPermissions.mockReturnValue('INTERSECTED');
304
+ linksQueriesMock.updateLinkFromSpaceOrShare.mockResolvedValueOnce(undefined);
305
+ const dto = {
306
+ permissions: 'NEW_PERMS',
307
+ language: 'fr',
308
+ isActive: false
309
+ };
310
+ const result = await service.updateLinkFromSpaceOrShare(user, 7, 55, 1, dto, true);
311
+ expect(linksQueriesMock.updateLinkFromSpaceOrShare).toHaveBeenCalled();
312
+ expect(result.permissions).toBe('INTERSECTED');
313
+ expect(result.language).toBe('fr');
314
+ expect(result.isActive).toBe(false);
315
+ });
316
+ });
317
+ describe('createGuestLink', ()=>{
318
+ it('creates guest link with hashed password and returns created user info', async ()=>{
319
+ ;
320
+ _functions.hashPassword.mockResolvedValue('HASHED');
321
+ _functions.generateShortUUID.mockReturnValue('RANDOMSEQ');
322
+ usersQueriesMock.createUserOrGuest.mockResolvedValueOnce(99);
323
+ const guest = await service.createGuestLink(_user.GUEST_PERMISSION.SHARES, 'plaintext', 'en', true);
324
+ expect(usersQueriesMock.createUserOrGuest).toHaveBeenCalled();
325
+ expect(guest.id).toBe(99);
326
+ expect(guest.password).toBe('HASHED');
327
+ expect(guest.role).toBeDefined();
328
+ expect(guest.permissions).toBe(_user.GUEST_PERMISSION.SHARES);
329
+ expect(guest.language).toBe('en');
330
+ expect(guest.isActive).toBe(true);
331
+ });
332
+ it('generates a random password and defaults isActive when not provided', async ()=>{
333
+ ;
334
+ _functions.hashPassword.mockResolvedValue('HASHED-RAND');
335
+ _functions.generateShortUUID.mockReturnValueOnce('RANDOMSEQ');
336
+ usersQueriesMock.createUserOrGuest.mockResolvedValueOnce(123);
337
+ const guest = await service.createGuestLink(_user.GUEST_PERMISSION.SPACES);
338
+ expect(_functions.hashPassword).toHaveBeenCalled();
339
+ expect(guest.id).toBe(123);
340
+ expect(guest.isActive).toBe(true);
341
+ expect(guest.language).toBeNull();
342
+ });
343
+ });
344
+ describe('getLinkFromSpaceOrShare', ()=>{
345
+ it('returns a link guest for SPACE type', async ()=>{
346
+ const lg = {
347
+ id: 1
348
+ };
349
+ linksQueriesMock.linkFromSpace.mockResolvedValueOnce(lg);
350
+ const res = await service.getLinkFromSpaceOrShare(user, 11, 22, _links.LINK_TYPE.SPACE);
351
+ expect(res).toBe(lg);
352
+ expect(linksQueriesMock.linkFromSpace).toHaveBeenCalledWith(user.id, 11, 22);
353
+ expect(linksQueriesMock.linkFromShare).not.toHaveBeenCalled();
354
+ });
355
+ it('returns a link guest for SHARE type', async ()=>{
356
+ const lg = {
357
+ id: 2
358
+ };
359
+ linksQueriesMock.linkFromShare.mockResolvedValueOnce(lg);
360
+ const res = await service.getLinkFromSpaceOrShare(user, 33, 44, _links.LINK_TYPE.SHARE);
361
+ expect(res).toBe(lg);
362
+ expect(linksQueriesMock.linkFromShare).toHaveBeenCalledWith(user.id, 33, 44, +user.isAdmin);
363
+ expect(linksQueriesMock.linkFromSpace).not.toHaveBeenCalled();
364
+ });
365
+ it('throws when link not found', async ()=>{
366
+ linksQueriesMock.linkFromSpace.mockResolvedValueOnce(null);
367
+ await expect(service.getLinkFromSpaceOrShare(user, 55, 66, _links.LINK_TYPE.SPACE)).rejects.toEqual(new _common.HttpException('Link not found', _common.HttpStatus.NOT_FOUND));
368
+ });
369
+ });
370
+ describe('updateLinkFromSpaceOrShare (additional branches)', ()=>{
371
+ it('returns null when no diff and not from API', async ()=>{
372
+ const link = {
373
+ id: 1,
374
+ name: 'n',
375
+ email: 'e',
376
+ requireAuth: false,
377
+ limitAccess: null,
378
+ expiresAt: null
379
+ };
380
+ jest.spyOn(service, 'getLinkFromSpaceOrShare').mockResolvedValueOnce(link);
381
+ const result = await service.updateLinkFromSpaceOrShare(user, 1, 2, _links.LINK_TYPE.SHARE, {}, false);
382
+ expect(result).toBeNull();
383
+ expect(linksQueriesMock.updateLinkFromSpaceOrShare).not.toHaveBeenCalled();
384
+ });
385
+ it('hashes password and does not leak it when fromAPI is true', async ()=>{
386
+ const link = {
387
+ id: 1
388
+ };
389
+ jest.spyOn(service, 'getLinkFromSpaceOrShare').mockResolvedValueOnce(link);
390
+ _functions.hashPassword.mockResolvedValueOnce('HASHED');
391
+ linksQueriesMock.updateLinkFromSpaceOrShare.mockImplementation(async (_link, _spaceOrShareId, updateUser)=>{
392
+ // Assert at call time before the service deletes the password
393
+ expect(updateUser).toMatchObject({
394
+ password: 'HASHED'
395
+ });
396
+ return;
397
+ });
398
+ const result = await service.updateLinkFromSpaceOrShare(user, 1, 2, _links.LINK_TYPE.SHARE, {
399
+ password: 'secret'
400
+ }, true);
401
+ expect(linksQueriesMock.updateLinkFromSpaceOrShare).toHaveBeenCalled();
402
+ // The returned link must not leak password
403
+ expect(result).toBe(link);
404
+ expect(result.password).toBeUndefined();
405
+ });
406
+ it('updates multiple link/user fields and ignores equal expiresAt', async ()=>{
407
+ const base = {
408
+ id: 9,
409
+ name: 'a',
410
+ email: 'b',
411
+ requireAuth: false,
412
+ limitAccess: null,
413
+ expiresAt: {
414
+ date: '2025-01-01'
415
+ }
416
+ };
417
+ jest.spyOn(service, 'getLinkFromSpaceOrShare').mockResolvedValueOnce(base);
418
+ linksQueriesMock.updateLinkFromSpaceOrShare.mockResolvedValueOnce(undefined);
419
+ const dto = {
420
+ name: 'a2',
421
+ email: 'b2',
422
+ requireAuth: true,
423
+ limitAccess: 5,
424
+ expiresAt: {
425
+ date: '2025-01-01'
426
+ } // equal, should be ignored
427
+ };
428
+ await service.updateLinkFromSpaceOrShare(user, 9, 99, _links.LINK_TYPE.SHARE, dto, false);
429
+ const [, , , updateLink] = linksQueriesMock.updateLinkFromSpaceOrShare.mock.calls[0].slice(0, 5);
430
+ expect(updateLink).toMatchObject({
431
+ name: 'a2',
432
+ email: 'b2',
433
+ requireAuth: true,
434
+ limitAccess: 5
435
+ });
436
+ expect(updateLink.expiresAt).toBeUndefined();
437
+ });
438
+ });
439
+ describe('setAllowedPermissions (additional branches)', ()=>{
440
+ it('sets all operations when share has externalPath and user is admin', async ()=>{
441
+ const admin = {
442
+ id: 10,
443
+ isAdmin: true
444
+ };
445
+ const share = {
446
+ externalPath: '/ext',
447
+ file: {}
448
+ };
449
+ await service.setAllowedPermissions(admin, share);
450
+ expect(share.file.permissions).toBe(_shares.SHARE_ALL_OPERATIONS);
451
+ });
452
+ it('throws NOT_FOUND when space permissions are missing', async ()=>{
453
+ spacesQueriesMock.permissions.mockResolvedValueOnce(null);
454
+ const share = {
455
+ file: {
456
+ space: {
457
+ alias: 'space-x',
458
+ root: {
459
+ alias: 'r'
460
+ }
461
+ }
462
+ }
463
+ };
464
+ await expect(service.setAllowedPermissions(user, share)).rejects.toEqual(new _common.HttpException('Space not found', _common.HttpStatus.NOT_FOUND));
465
+ });
466
+ it('throws NOT_FOUND when parent share permissions are missing', async ()=>{
467
+ sharesQueriesMock.permissions.mockResolvedValueOnce(null);
468
+ const share = {
469
+ ownerId: 42,
470
+ parent: {
471
+ alias: 'parent'
472
+ },
473
+ file: {}
474
+ };
475
+ await expect(service.setAllowedPermissions(user, share)).rejects.toEqual(new _common.HttpException('Share not found', _common.HttpStatus.NOT_FOUND));
476
+ });
477
+ it('uses owner permissions when asAdmin is true', async ()=>{
478
+ const asAdminUser = {
479
+ id: 3,
480
+ isAdmin: false
481
+ };
482
+ sharesQueriesMock.permissions.mockResolvedValueOnce({
483
+ permissions: 'ADMIN_PARENT'
484
+ });
485
+ const share = {
486
+ ownerId: 77,
487
+ parent: {
488
+ alias: 'pa'
489
+ },
490
+ file: {}
491
+ };
492
+ await service.setAllowedPermissions(asAdminUser, share, true);
493
+ expect(sharesQueriesMock.permissions).toHaveBeenCalledWith(77, 'pa', +asAdminUser.isAdmin);
494
+ expect(share.file.permissions).toBe('ADMIN_PARENT');
495
+ });
496
+ });
497
+ describe('getShareLink (additional branch)', ()=>{
498
+ it('does not trim permissions if file.permissions is falsy', async ()=>{
499
+ const shareLink = {
500
+ id: 7,
501
+ file: {}
502
+ };
503
+ sharesQueriesMock.listShareLinks.mockResolvedValueOnce(shareLink);
504
+ const spy = jest.spyOn(service, 'setAllowedPermissions').mockResolvedValueOnce(void 0);
505
+ const res = await service.getShareLink(user, 7);
506
+ expect(spy).toHaveBeenCalled();
507
+ expect(res).toBe(shareLink);
508
+ expect(_permissions.removePermissions).not.toHaveBeenCalled();
509
+ });
510
+ });
511
+ describe('deleteShare', ()=>{
512
+ it('throws Forbidden when user is not admin and not owner', async ()=>{
513
+ sharesQueriesMock.shareExistsForOwner.mockResolvedValueOnce(false);
514
+ await expect(service.deleteShare({
515
+ id: 2,
516
+ isAdmin: false
517
+ }, 123)).rejects.toEqual(new _common.HttpException('Not authorized', _common.HttpStatus.FORBIDDEN));
518
+ });
519
+ it('deletes links and removes shares when authorized (asAdmin)', async ()=>{
520
+ const deleteLinksSpy = jest.spyOn(service, 'deleteAllLinkMembers').mockResolvedValue(void 0);
521
+ const removeSpy = jest.spyOn(service, 'removeShareFromOwners').mockResolvedValue(void 0);
522
+ await service.deleteShare(user, 456, true);
523
+ expect(deleteLinksSpy).toHaveBeenCalledWith(456, expect.anything());
524
+ expect(removeSpy).toHaveBeenCalledWith(456, 'all', false, user.id);
525
+ });
526
+ });
527
+ describe('child share wrappers', ()=>{
528
+ it('getChildShare returns share link when isLink = true', async ()=>{
529
+ sharesQueriesMock.childExistsForShareOwner.mockResolvedValueOnce(99);
530
+ const getShareLinkSpy = jest.spyOn(service, 'getShareLink').mockResolvedValueOnce({
531
+ id: 99
532
+ });
533
+ const res = await service.getChildShare(user, 1, 99, true);
534
+ expect(res).toEqual({
535
+ id: 99
536
+ });
537
+ expect(getShareLinkSpy).toHaveBeenCalledWith(user, 99, true);
538
+ });
539
+ it('getChildShare returns child share when isLink = false', async ()=>{
540
+ sharesQueriesMock.childExistsForShareOwner.mockResolvedValueOnce(100);
541
+ const getShareSpy = jest.spyOn(service, 'getShareWithMembers').mockResolvedValueOnce({
542
+ id: 100
543
+ });
544
+ const res = await service.getChildShare(user, 1, 100, false);
545
+ expect(res).toEqual({
546
+ id: 100
547
+ });
548
+ expect(getShareSpy).toHaveBeenCalledWith(user, 100, true);
549
+ });
550
+ it('updateChildShare forwards update and deleteChildShare forwards delete', async ()=>{
551
+ sharesQueriesMock.childExistsForShareOwner.mockResolvedValue(200);
552
+ const updateSpy = jest.spyOn(service, 'updateShare').mockResolvedValueOnce({
553
+ id: 200
554
+ });
555
+ const deleteSpy = jest.spyOn(service, 'deleteShare').mockResolvedValueOnce(void 0);
556
+ await service.updateChildShare(user, 1, 200, {});
557
+ expect(updateSpy).toHaveBeenCalledWith(user, 200, {}, true);
558
+ await service.deleteChildShare(user, 1, 200);
559
+ expect(deleteSpy).toHaveBeenCalledWith(user, 200, true);
560
+ });
561
+ it('throws Forbidden when not allowed to manage child share', async ()=>{
562
+ sharesQueriesMock.childExistsForShareOwner.mockResolvedValueOnce(null);
563
+ await expect(service.getChildShare(user, 1, 2, false)).rejects.toEqual(new _common.HttpException('Not authorized', _common.HttpStatus.FORBIDDEN));
564
+ });
565
+ });
566
+ describe('createOrUpdateLinksAsMembers', ()=>{
567
+ it('creates new links for id < 0 and notifies guest', async ()=>{
568
+ const createLinkSpy = jest.spyOn(service, 'createLinkFromSpaceOrShare').mockResolvedValue(void 0);
569
+ const notifySpy = jest.spyOn(service, 'notifyGuestLink').mockResolvedValue(void 0);
570
+ const links = [
571
+ {
572
+ id: -1,
573
+ linkSettings: {
574
+ uuid: 'u',
575
+ email: 'e',
576
+ permissions: 'p'
577
+ },
578
+ permissions: 'p'
579
+ }
580
+ ];
581
+ const res = await service.createOrUpdateLinksAsMembers(user, {
582
+ id: 1,
583
+ name: 'S'
584
+ }, _links.LINK_TYPE.SHARE, links);
585
+ expect(res).toEqual([]);
586
+ expect(createLinkSpy).toHaveBeenCalled();
587
+ expect(notifySpy).toHaveBeenCalled();
588
+ });
589
+ it('updates modified links and returns them along with unmodified ones', async ()=>{
590
+ const updateLinkSpy = jest.spyOn(service, 'updateLinkFromSpaceOrShare').mockResolvedValue(void 0);
591
+ const members = await service.createOrUpdateLinksAsMembers(user, {
592
+ id: 1,
593
+ name: 'S'
594
+ }, _links.LINK_TYPE.SHARE, [
595
+ {
596
+ id: 2,
597
+ linkId: 2,
598
+ permissions: 'p',
599
+ linkSettings: {
600
+ name: 'new'
601
+ }
602
+ },
603
+ {
604
+ id: 3,
605
+ linkId: 3,
606
+ permissions: 'q'
607
+ } // unmodified
608
+ ]);
609
+ expect(updateLinkSpy).toHaveBeenCalledWith(user, 2, 1, _links.LINK_TYPE.SHARE, {
610
+ name: 'new'
611
+ });
612
+ expect(members).toHaveLength(2);
613
+ expect(members.map((m)=>m.id)).toEqual([
614
+ 2,
615
+ 3
616
+ ]);
617
+ });
618
+ });
619
+ describe('generateLinkUUID (additional)', ()=>{
620
+ it('returns immediately when the first UUID is unique', async ()=>{
621
+ ;
622
+ _functions.generateShortUUID.mockReturnValueOnce('only-one');
623
+ linksQueriesMock.isUniqueUUID.mockResolvedValueOnce(true);
624
+ const { uuid } = await service.generateLinkUUID(user.id);
625
+ expect(uuid).toBe('only-one');
626
+ expect(linksQueriesMock.isUniqueUUID).toHaveBeenCalledTimes(1);
627
+ expect(linksQueriesMock.isUniqueUUID).toHaveBeenCalledWith(user.id, 'only-one');
628
+ });
629
+ });
54
630
  });
55
631
 
56
632
  //# sourceMappingURL=shares-manager.service.spec.js.map