@sync-in/server 1.4.0 → 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 (229) hide show
  1. package/CHANGELOG.md +19 -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-3GC2BQZD.js → chunk-2UWN7IQF.js} +1 -1
  192. package/static/{chunk-TCFKH6K6.js → chunk-2VSPDSJS.js} +1 -1
  193. package/static/{chunk-KZQCFEPT.js → chunk-34UZ7SYI.js} +1 -1
  194. package/static/{chunk-5YKWZT33.js → chunk-45UQJGGY.js} +1 -1
  195. package/static/{chunk-N2LYWNTC.js → chunk-5TEXH3LJ.js} +1 -1
  196. package/static/{chunk-MOVWEZ7J.js → chunk-66FMKVJX.js} +1 -1
  197. package/static/{chunk-XE5YHU5J.js → chunk-BIUNUYZ5.js} +1 -1
  198. package/static/chunk-CK4BY2NX.js +27 -0
  199. package/static/{chunk-T55FAU2O.js → chunk-CSBDAY77.js} +1 -1
  200. package/static/{chunk-6F55D74O.js → chunk-CXXPLBDZ.js} +1 -1
  201. package/static/{chunk-YCINY2YI.js → chunk-EILQG525.js} +1 -1
  202. package/static/{chunk-DGVNNICG.js → chunk-ENWABUR4.js} +1 -1
  203. package/static/{chunk-Y2CDUS4J.js → chunk-FR4AOLYL.js} +4 -4
  204. package/static/chunk-HW2H3ISM.js +559 -0
  205. package/static/{chunk-VHYIXL7R.js → chunk-HYMDGBZL.js} +1 -1
  206. package/static/{chunk-W3QXNDI5.js → chunk-IML5UYQG.js} +1 -1
  207. package/static/{chunk-GBCYYDCI.js → chunk-IPSMJHMQ.js} +1 -1
  208. package/static/{chunk-TXPODW5Q.js → chunk-JVCWYSNP.js} +1 -1
  209. package/static/{chunk-VMQMD36Z.js → chunk-KGPCIUD2.js} +1 -1
  210. package/static/{chunk-TNW2CGK6.js → chunk-KQZJSEM3.js} +1 -1
  211. package/static/{chunk-HZA7R43P.js → chunk-NPEMJJIU.js} +1 -1
  212. package/static/{chunk-WWIC7UW3.js → chunk-OEFBC4GG.js} +1 -1
  213. package/static/{chunk-VMUOUCEI.js → chunk-P734A3XZ.js} +1 -1
  214. package/static/{chunk-FQ4AFNGE.js → chunk-RASR4CK6.js} +1 -1
  215. package/static/{chunk-LJIGRUEF.js → chunk-RFMOUC22.js} +1 -1
  216. package/static/{chunk-TTQ37MUV.js → chunk-RSS6GYNE.js} +1 -1
  217. package/static/{chunk-TDQAEVZN.js → chunk-SBOQGGZX.js} +1 -1
  218. package/static/{chunk-PF4K7MVG.js → chunk-SJAFPXQV.js} +1 -1
  219. package/static/{chunk-C23BPTJZ.js → chunk-XTYGMF2V.js} +1 -1
  220. package/static/{chunk-B2Y2RNFP.js → chunk-YCWMV2YR.js} +1 -1
  221. package/static/{chunk-X43VWRFP.js → chunk-YGD22MWQ.js} +1 -1
  222. package/static/{chunk-MTRNPGS4.js → chunk-ZC5NIT55.js} +1 -1
  223. package/static/{chunk-PY3BGNJN.js → chunk-ZVY37DKS.js} +1 -1
  224. package/static/index.html +1 -1
  225. package/static/main-N5CZRHAO.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,45 +6,791 @@
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
11
  const _authmanagerservice = require("../../../authentication/services/auth-manager.service");
11
- const _cacheservice = require("../../../infrastructure/cache/services/cache.service");
12
- const _constants = require("../../../infrastructure/database/constants");
12
+ const _group = require("../constants/group");
13
+ const _user = require("../constants/user");
14
+ const _usermodel = require("../models/user.model");
13
15
  const _adminusersmanagerservice = require("./admin-users-manager.service");
14
16
  const _adminusersqueriesservice = require("./admin-users-queries.service");
15
- const _usersmanagerservice = require("./users-manager.service");
16
- const _usersqueriesservice = require("./users-queries.service");
17
+ // mock file utils used by the service (delete/rename user space)
18
+ jest.mock('../../files/utils/files', ()=>({
19
+ isPathExists: jest.fn(),
20
+ moveFiles: jest.fn(),
21
+ removeFiles: jest.fn()
22
+ }));
23
+ // mock hash/anonymize utilities (preserve other module exports)
24
+ jest.mock('../../../common/functions', ()=>{
25
+ const actual = jest.requireActual('../../../common/functions');
26
+ return {
27
+ ...actual,
28
+ hashPassword: jest.fn(async (pwd)=>`hashed:${pwd}`),
29
+ anonymizePassword: jest.fn((dto)=>({
30
+ ...dto,
31
+ password: '***'
32
+ }))
33
+ };
34
+ });
35
+ // Alias FS mocks (avoid repetitions)
36
+ const fs = jest.requireMock('../../files/utils/files');
37
+ // Helper utilities
38
+ const expectHttp = async (p)=>expect(p).rejects.toBeInstanceOf(_common.HttpException);
39
+ const spyMakePaths = ()=>jest.spyOn(_usermodel.UserModel.prototype, 'makePaths').mockResolvedValueOnce(undefined);
17
40
  describe(_adminusersmanagerservice.AdminUsersManager.name, ()=>{
18
41
  let service;
42
+ // deep mocks
43
+ let authManagerMock;
44
+ let adminQueriesMock;
45
+ const setUser = (u)=>adminQueriesMock.listUsers.mockResolvedValueOnce(u);
46
+ const setGuest = (g)=>adminQueriesMock.usersQueries.listGuests.mockResolvedValueOnce(g);
47
+ const baseUser = {
48
+ id: 10,
49
+ login: 'john',
50
+ email: 'john@example.com',
51
+ isActive: true,
52
+ role: _user.USER_ROLE.USER,
53
+ groups: [
54
+ {
55
+ id: 1
56
+ },
57
+ {
58
+ id: 3
59
+ }
60
+ ]
61
+ };
19
62
  beforeAll(async ()=>{
63
+ authManagerMock = {
64
+ setCookies: jest.fn()
65
+ };
66
+ adminQueriesMock = {
67
+ listUsers: jest.fn(),
68
+ usersQueries: {
69
+ listGuests: jest.fn(),
70
+ from: jest.fn(),
71
+ createUserOrGuest: jest.fn(),
72
+ updateUserOrGuest: jest.fn(),
73
+ deleteUser: jest.fn(),
74
+ compareUserPassword: jest.fn(),
75
+ checkGroupNameExists: jest.fn(),
76
+ checkUserExists: jest.fn(),
77
+ searchUsersOrGroups: jest.fn()
78
+ },
79
+ updateUserGroups: jest.fn(),
80
+ updateGuestManagers: jest.fn(),
81
+ deleteUser: jest.fn(),
82
+ groupFromName: jest.fn(),
83
+ browseGroupMembers: jest.fn(),
84
+ browseRootGroupMembers: jest.fn(),
85
+ groupFromId: jest.fn(),
86
+ createGroup: jest.fn(),
87
+ updateGroup: jest.fn(),
88
+ deleteGroup: jest.fn(),
89
+ addUsersToGroup: jest.fn(),
90
+ updateUserFromGroup: jest.fn(),
91
+ removeUserFromGroup: jest.fn()
92
+ };
20
93
  const module = await _testing.Test.createTestingModule({
21
94
  providers: [
22
95
  _adminusersmanagerservice.AdminUsersManager,
23
- _adminusersqueriesservice.AdminUsersQueries,
24
- _usersqueriesservice.UsersQueries,
25
96
  {
26
97
  provide: _authmanagerservice.AuthManager,
27
- useValue: {}
28
- },
29
- {
30
- provide: _usersmanagerservice.UsersManager,
31
- useValue: {}
32
- },
33
- {
34
- provide: _constants.DB_TOKEN_PROVIDER,
35
- useValue: {}
98
+ useValue: authManagerMock
36
99
  },
37
100
  {
38
- provide: _cacheservice.Cache,
39
- useValue: {}
101
+ provide: _adminusersqueriesservice.AdminUsersQueries,
102
+ useValue: adminQueriesMock
40
103
  }
41
104
  ]
42
105
  }).compile();
106
+ module.useLogger([
107
+ 'fatal'
108
+ ]);
43
109
  service = module.get(_adminusersmanagerservice.AdminUsersManager);
44
110
  });
111
+ beforeEach(()=>{
112
+ jest.clearAllMocks();
113
+ });
45
114
  it('should be defined', ()=>{
46
115
  expect(service).toBeDefined();
47
116
  });
117
+ describe('getUser / getGuest', ()=>{
118
+ it('user ok + not found + guest ok', async ()=>{
119
+ setUser(baseUser);
120
+ expect(await service.getUser(10)).toEqual(baseUser);
121
+ expect(adminQueriesMock.listUsers).toHaveBeenCalledWith(10);
122
+ setUser(null);
123
+ await expectHttp(service.getUser(999));
124
+ const guest = {
125
+ id: 22,
126
+ login: 'guest',
127
+ email: 'g@x',
128
+ managers: [],
129
+ role: _user.USER_ROLE.GUEST
130
+ };
131
+ setGuest(guest);
132
+ expect(await service.getGuest(22)).toEqual(guest);
133
+ expect(adminQueriesMock.usersQueries.listGuests).toHaveBeenCalledWith(22, 0, true);
134
+ });
135
+ });
136
+ describe('createUserOrGuest', ()=>{
137
+ it.each([
138
+ {
139
+ role: _user.USER_ROLE.USER,
140
+ asAdmin: false,
141
+ id: 101,
142
+ exp: 'UserModel'
143
+ },
144
+ {
145
+ role: _user.USER_ROLE.GUEST,
146
+ asAdmin: true,
147
+ id: 202,
148
+ exp: 'AdminGuest'
149
+ },
150
+ {
151
+ role: _user.USER_ROLE.USER,
152
+ asAdmin: true,
153
+ id: 707,
154
+ exp: 'AdminUser'
155
+ },
156
+ {
157
+ role: _user.USER_ROLE.GUEST,
158
+ asAdmin: false,
159
+ id: 808,
160
+ exp: 'UserModel'
161
+ }
162
+ ])('creation matrix ($role / asAdmin=$asAdmin)', async ({ role, asAdmin, id, exp })=>{
163
+ const dto = {
164
+ login: 'alice',
165
+ email: 'a@x',
166
+ password: 'pwd',
167
+ managers: role === _user.USER_ROLE.GUEST ? [
168
+ 1
169
+ ] : []
170
+ };
171
+ adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false);
172
+ adminQueriesMock.usersQueries.createUserOrGuest.mockResolvedValueOnce(id);
173
+ spyMakePaths();
174
+ if (exp === 'AdminUser') setUser({
175
+ id,
176
+ login: 'alice',
177
+ role
178
+ });
179
+ if (exp === 'AdminGuest') setGuest({
180
+ id,
181
+ login: 'alice',
182
+ role
183
+ });
184
+ const res = await service.createUserOrGuest(dto, role, asAdmin);
185
+ if (exp === 'UserModel') {
186
+ expect(res).toBeInstanceOf(_usermodel.UserModel);
187
+ expect(res.id).toBe(id);
188
+ } else if (exp === 'AdminUser') {
189
+ expect(adminQueriesMock.listUsers).toHaveBeenCalledWith(id);
190
+ } else {
191
+ expect(adminQueriesMock.usersQueries.listGuests).toHaveBeenCalledWith(id, 0, true);
192
+ }
193
+ expect(adminQueriesMock.usersQueries.createUserOrGuest).toHaveBeenCalledWith(expect.objectContaining({
194
+ login: 'alice',
195
+ email: 'a@x',
196
+ password: 'hashed:pwd'
197
+ }), role);
198
+ });
199
+ it('creation errors: duplication and DB error', async ()=>{
200
+ adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce({
201
+ login: 'dup',
202
+ email: 'dup@x'
203
+ });
204
+ await expectHttp(service.createUserOrGuest({
205
+ login: 'dup',
206
+ email: 'dup@x',
207
+ password: 'p',
208
+ managers: []
209
+ }, _user.USER_ROLE.USER, false));
210
+ adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false);
211
+ adminQueriesMock.usersQueries.createUserOrGuest.mockRejectedValueOnce(new Error('db fail'));
212
+ await expectHttp(service.createUserOrGuest({
213
+ login: 'bob',
214
+ email: 'b@x',
215
+ password: 'p',
216
+ managers: []
217
+ }, _user.USER_ROLE.USER, false));
218
+ });
219
+ });
220
+ describe('updateUserOrGuest - USER branch', ()=>{
221
+ it('full update + FS rename + groups diff', async ()=>{
222
+ const current = {
223
+ ...baseUser,
224
+ groups: [
225
+ {
226
+ id: 1
227
+ },
228
+ {
229
+ id: 3
230
+ }
231
+ ]
232
+ };
233
+ setUser(current);
234
+ const updated = {
235
+ ...current,
236
+ login: 'johnny',
237
+ email: 'j@new'
238
+ };
239
+ setUser(updated);
240
+ adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false);
241
+ adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false);
242
+ fs.isPathExists.mockResolvedValueOnce(true);
243
+ fs.isPathExists.mockResolvedValueOnce(false);
244
+ fs.moveFiles.mockResolvedValueOnce(undefined);
245
+ adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true);
246
+ adminQueriesMock.updateUserGroups.mockResolvedValueOnce(undefined);
247
+ const dto = {
248
+ login: 'johnny',
249
+ email: 'j@new',
250
+ isActive: true,
251
+ password: 'newpwd',
252
+ groups: [
253
+ 3,
254
+ 5
255
+ ]
256
+ };
257
+ const res = await service.updateUserOrGuest(current.id, dto);
258
+ expect(adminQueriesMock.usersQueries.updateUserOrGuest).toHaveBeenCalledWith(current.id, expect.objectContaining({
259
+ login: 'johnny',
260
+ email: 'j@new',
261
+ isActive: true,
262
+ passwordAttempts: 0,
263
+ password: 'hashed:newpwd'
264
+ }), undefined);
265
+ expect(adminQueriesMock.updateUserGroups).toHaveBeenCalledWith(current.id, {
266
+ add: [
267
+ 5
268
+ ],
269
+ delete: [
270
+ 1
271
+ ]
272
+ });
273
+ expect(res).toEqual(updated);
274
+ });
275
+ it('login/email conflict', async ()=>{
276
+ const current = {
277
+ ...baseUser
278
+ };
279
+ setUser(current);
280
+ adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(true);
281
+ await expectHttp(service.updateUserOrGuest(current.id, {
282
+ login: 'taken'
283
+ }));
284
+ setUser(current);
285
+ adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(true);
286
+ await expectHttp(service.updateUserOrGuest(current.id, {
287
+ email: 'dup@x'
288
+ }));
289
+ expect(adminQueriesMock.usersQueries.updateUserOrGuest).not.toHaveBeenCalled();
290
+ });
291
+ it('renameUserSpace impossible (new space exists)', async ()=>{
292
+ const current = {
293
+ ...baseUser
294
+ };
295
+ setUser(current);
296
+ adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false);
297
+ fs.isPathExists.mockResolvedValueOnce(true); // current
298
+ fs.isPathExists.mockResolvedValueOnce(true); // new already exists
299
+ fs.moveFiles.mockResolvedValue(undefined);
300
+ await expectHttp(service.updateUserOrGuest(current.id, {
301
+ login: 'new'
302
+ }));
303
+ });
304
+ it('DB update false => INTERNAL_SERVER_ERROR', async ()=>{
305
+ const current = {
306
+ ...baseUser
307
+ };
308
+ setUser(current);
309
+ adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(false);
310
+ await expectHttp(service.updateUserOrGuest(current.id, {
311
+ email: 'e@x'
312
+ }));
313
+ });
314
+ it('updateUserGroups fails', async ()=>{
315
+ const current = {
316
+ ...baseUser,
317
+ groups: [
318
+ {
319
+ id: 1
320
+ }
321
+ ]
322
+ };
323
+ setUser(current);
324
+ adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true);
325
+ adminQueriesMock.updateUserGroups.mockRejectedValueOnce(new Error('group error'));
326
+ await expectHttp(service.updateUserOrGuest(current.id, {
327
+ groups: [
328
+ 2
329
+ ]
330
+ }));
331
+ });
332
+ it('no change when login or email unchanged', async ()=>{
333
+ const current = {
334
+ ...baseUser
335
+ };
336
+ setUser(current);
337
+ setUser(current);
338
+ expect(await service.updateUserOrGuest(current.id, {
339
+ login: current.login
340
+ })).toEqual(current);
341
+ expect(adminQueriesMock.usersQueries.checkUserExists).not.toHaveBeenCalled();
342
+ setUser(current);
343
+ setUser(current);
344
+ expect(await service.updateUserOrGuest(current.id, {
345
+ email: current.email
346
+ })).toEqual(current);
347
+ expect(adminQueriesMock.usersQueries.updateUserOrGuest).not.toHaveBeenCalled();
348
+ });
349
+ it('default branch (unknown field)', async ()=>{
350
+ const current = {
351
+ ...baseUser
352
+ };
353
+ setUser(current);
354
+ adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true);
355
+ const updated = {
356
+ ...current,
357
+ language: 'fr'
358
+ };
359
+ setUser(updated);
360
+ const res = await service.updateUserOrGuest(current.id, {
361
+ language: 'fr'
362
+ });
363
+ expect(adminQueriesMock.usersQueries.updateUserOrGuest).toHaveBeenCalledWith(current.id, expect.objectContaining({
364
+ language: 'fr'
365
+ }), undefined);
366
+ expect(res).toEqual(updated);
367
+ });
368
+ });
369
+ describe('updateUserOrGuest - GUEST branch', ()=>{
370
+ it('update guest + managers diff', async ()=>{
371
+ const guest = {
372
+ id: 33,
373
+ login: 'g',
374
+ email: 'g@x',
375
+ managers: [
376
+ {
377
+ id: 2
378
+ },
379
+ {
380
+ id: 7
381
+ }
382
+ ],
383
+ role: _user.USER_ROLE.GUEST
384
+ };
385
+ setGuest(guest);
386
+ const updatedGuest = {
387
+ ...guest,
388
+ email: 'new@x'
389
+ };
390
+ setGuest(updatedGuest);
391
+ adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true);
392
+ adminQueriesMock.updateGuestManagers.mockResolvedValueOnce(undefined);
393
+ const res = await service.updateUserOrGuest(guest.id, {
394
+ email: 'new@x',
395
+ managers: [
396
+ 7,
397
+ 9
398
+ ]
399
+ }, _user.USER_ROLE.GUEST);
400
+ expect(adminQueriesMock.usersQueries.updateUserOrGuest).toHaveBeenCalledWith(guest.id, {
401
+ email: 'new@x'
402
+ }, _user.USER_ROLE.GUEST);
403
+ expect(adminQueriesMock.updateGuestManagers).toHaveBeenCalledWith(guest.id, {
404
+ add: [
405
+ 9
406
+ ],
407
+ delete: [
408
+ 2
409
+ ]
410
+ });
411
+ expect(res).toEqual(updatedGuest);
412
+ });
413
+ it('validations updateGuest', async ()=>{
414
+ expect(()=>service.updateGuest(1, {})).toThrow(/no changes to update/i);
415
+ expect(()=>service.updateGuest(1, {
416
+ managers: []
417
+ })).toThrow(/guest must have at least one manager/i);
418
+ });
419
+ it('updateGuestManagers échoue', async ()=>{
420
+ const guest = {
421
+ id: 33,
422
+ login: 'g',
423
+ email: 'g@x',
424
+ managers: [
425
+ {
426
+ id: 2
427
+ }
428
+ ],
429
+ role: _user.USER_ROLE.GUEST
430
+ };
431
+ setGuest(guest);
432
+ adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true);
433
+ adminQueriesMock.updateGuestManagers.mockRejectedValueOnce(new Error('mgr error'));
434
+ await expectHttp(service.updateUserOrGuest(guest.id, {
435
+ managers: [
436
+ 3
437
+ ]
438
+ }, _user.USER_ROLE.GUEST));
439
+ });
440
+ });
441
+ describe('deleteUserOrGuest / deleteGuest', ()=>{
442
+ it('delete user + optional space and errors', async ()=>{
443
+ adminQueriesMock.deleteUser.mockResolvedValueOnce(true);
444
+ fs.isPathExists.mockResolvedValueOnce(true);
445
+ fs.removeFiles.mockResolvedValueOnce(undefined);
446
+ await expect(service.deleteUserOrGuest(10, 'john', {
447
+ deleteSpace: true,
448
+ isGuest: false
449
+ })).resolves.toBeUndefined();
450
+ expect(adminQueriesMock.deleteUser).toHaveBeenCalledWith(10, 'john');
451
+ expect(fs.isPathExists).toHaveBeenCalled();
452
+ expect(fs.removeFiles).toHaveBeenCalled();
453
+ adminQueriesMock.deleteUser.mockRejectedValueOnce(new Error('db crash'));
454
+ await expectHttp(service.deleteUserOrGuest(10, 'john', {
455
+ deleteSpace: false
456
+ }));
457
+ });
458
+ it('deleteGuest -> getGuest then delete', async ()=>{
459
+ setGuest({
460
+ id: 77,
461
+ login: 'g77'
462
+ });
463
+ adminQueriesMock.deleteUser.mockResolvedValueOnce(true);
464
+ fs.isPathExists.mockResolvedValueOnce(false);
465
+ await expect(service.deleteGuest(77)).resolves.toBeUndefined();
466
+ expect(adminQueriesMock.deleteUser).toHaveBeenCalledWith(77, 'g77');
467
+ });
468
+ });
469
+ describe('deleteUserFromAdmin', ()=>{
470
+ it('admin password incorrect / deletion ok', async ()=>{
471
+ const admin = new _usermodel.UserModel({
472
+ id: 1
473
+ }, true);
474
+ adminQueriesMock.usersQueries.compareUserPassword.mockResolvedValueOnce(false);
475
+ await expectHttp(service.deleteUserFromAdmin(admin, 10, {
476
+ adminPassword: 'bad'
477
+ }));
478
+ adminQueriesMock.usersQueries.compareUserPassword.mockResolvedValueOnce(true);
479
+ adminQueriesMock.usersQueries.from.mockResolvedValueOnce({
480
+ id: 10,
481
+ login: 'to-del'
482
+ });
483
+ adminQueriesMock.deleteUser.mockResolvedValueOnce(true);
484
+ await service.deleteUserFromAdmin(admin, 10, {
485
+ adminPassword: 'ok',
486
+ deleteSpace: true
487
+ });
488
+ expect(adminQueriesMock.deleteUser).toHaveBeenCalledWith(10, 'to-del');
489
+ });
490
+ });
491
+ describe('groups', ()=>{
492
+ it('browseGroups with/without name + NOT_FOUND', async ()=>{
493
+ adminQueriesMock.groupFromName.mockResolvedValueOnce({
494
+ id: 5,
495
+ name: 'dev',
496
+ type: _group.GROUP_TYPE.USER
497
+ });
498
+ adminQueriesMock.browseGroupMembers.mockResolvedValueOnce([
499
+ {
500
+ id: 1
501
+ },
502
+ {
503
+ id: 2
504
+ }
505
+ ]);
506
+ const withName = await service.browseGroups('dev', _group.GROUP_TYPE.USER);
507
+ expect(withName.parentGroup).toEqual({
508
+ id: 5,
509
+ name: 'dev',
510
+ type: _group.GROUP_TYPE.USER
511
+ });
512
+ expect(withName.members).toHaveLength(2);
513
+ adminQueriesMock.browseRootGroupMembers.mockResolvedValueOnce([
514
+ {
515
+ id: 3
516
+ }
517
+ ]);
518
+ const root = await service.browseGroups(undefined, _group.GROUP_TYPE.USER);
519
+ expect(root.parentGroup).toBeUndefined();
520
+ expect(root.members).toEqual([
521
+ {
522
+ id: 3
523
+ }
524
+ ]);
525
+ adminQueriesMock.groupFromName.mockResolvedValueOnce(null);
526
+ await expectHttp(service.browseGroups('unknown'));
527
+ });
528
+ it('getGroup OK / NOT_FOUND', async ()=>{
529
+ adminQueriesMock.groupFromId.mockResolvedValueOnce({
530
+ id: 9
531
+ });
532
+ expect(await service.getGroup(9)).toEqual({
533
+ id: 9
534
+ });
535
+ adminQueriesMock.groupFromId.mockResolvedValueOnce(null);
536
+ await expectHttp(service.getGroup(999));
537
+ });
538
+ it('createGroup OK + validations + creation error', async ()=>{
539
+ const dto = {
540
+ name: 'team',
541
+ type: _group.GROUP_TYPE.USER
542
+ };
543
+ adminQueriesMock.usersQueries.checkGroupNameExists.mockResolvedValueOnce(false);
544
+ adminQueriesMock.createGroup.mockResolvedValueOnce(123);
545
+ adminQueriesMock.groupFromId.mockResolvedValueOnce({
546
+ id: 123,
547
+ name: 'team'
548
+ });
549
+ expect(await service.createGroup(dto)).toEqual({
550
+ id: 123,
551
+ name: 'team'
552
+ });
553
+ await expectHttp(service.createGroup({}));
554
+ adminQueriesMock.usersQueries.checkGroupNameExists.mockResolvedValueOnce(true);
555
+ await expectHttp(service.createGroup(dto));
556
+ expect(adminQueriesMock.createGroup).toHaveBeenCalledTimes(1); // only the first one OK
557
+ adminQueriesMock.usersQueries.checkGroupNameExists.mockResolvedValueOnce(false);
558
+ adminQueriesMock.createGroup.mockRejectedValueOnce(new Error('db err'));
559
+ await expectHttp(service.createGroup(dto));
560
+ });
561
+ it('updateGroup success / failure', async ()=>{
562
+ adminQueriesMock.usersQueries.checkGroupNameExists.mockResolvedValueOnce(false);
563
+ adminQueriesMock.updateGroup.mockResolvedValueOnce(true);
564
+ adminQueriesMock.groupFromId.mockResolvedValueOnce({
565
+ id: 5,
566
+ name: 'new'
567
+ });
568
+ expect(await service.updateGroup(5, {
569
+ name: 'new'
570
+ })).toEqual({
571
+ id: 5,
572
+ name: 'new'
573
+ });
574
+ adminQueriesMock.updateGroup.mockResolvedValueOnce(false);
575
+ await expectHttp(service.updateGroup(5, {}));
576
+ });
577
+ it('deleteGroup success / fail', async ()=>{
578
+ adminQueriesMock.deleteGroup.mockResolvedValueOnce(true);
579
+ await expect(service.deleteGroup(5)).resolves.toBeUndefined();
580
+ adminQueriesMock.deleteGroup.mockResolvedValueOnce(false);
581
+ await expectHttp(service.deleteGroup(6));
582
+ });
583
+ it('addUsersToGroup: NOT_FOUND + error', async ()=>{
584
+ adminQueriesMock.groupFromId.mockResolvedValueOnce(null);
585
+ await expectHttp(service.addUsersToGroup(1, [
586
+ 2,
587
+ 3
588
+ ]));
589
+ adminQueriesMock.groupFromId.mockResolvedValueOnce({
590
+ id: 1,
591
+ type: _group.GROUP_TYPE.USER
592
+ });
593
+ adminQueriesMock.addUsersToGroup.mockRejectedValueOnce(new Error('bad users'));
594
+ await expectHttp(service.addUsersToGroup(1, [
595
+ 2
596
+ ]));
597
+ });
598
+ it('updateUserFromGroup / removeUserFromGroup BAD_REQUEST errors', async ()=>{
599
+ adminQueriesMock.updateUserFromGroup.mockRejectedValueOnce(new Error('bad role'));
600
+ await expectHttp(service.updateUserFromGroup(1, 2, {
601
+ role: _user.USER_GROUP_ROLE.MEMBER
602
+ }));
603
+ adminQueriesMock.removeUserFromGroup.mockRejectedValueOnce(new Error('not member'));
604
+ await expectHttp(service.removeUserFromGroup(1, 2));
605
+ });
606
+ });
607
+ describe('searchMembers', ()=>{
608
+ it('forwards to usersQueries.searchUsersOrGroups', async ()=>{
609
+ const dto = {
610
+ search: 'jo'
611
+ };
612
+ adminQueriesMock.usersQueries.searchUsersOrGroups.mockResolvedValueOnce([
613
+ {
614
+ id: 1
615
+ }
616
+ ]);
617
+ expect(await service.searchMembers(dto)).toEqual([
618
+ {
619
+ id: 1
620
+ }
621
+ ]);
622
+ expect(adminQueriesMock.usersQueries.searchUsersOrGroups).toHaveBeenCalledWith(dto);
623
+ });
624
+ });
625
+ describe('impersonation', ()=>{
626
+ const res = {};
627
+ it('self / bad password / ok + logout (guard + non-admin + admin)', async ()=>{
628
+ const admin = new _usermodel.UserModel({
629
+ id: 5
630
+ }, true);
631
+ await expectHttp(service.impersonateUser(admin, 5, {
632
+ password: 'x'
633
+ }, res));
634
+ adminQueriesMock.usersQueries.compareUserPassword.mockResolvedValueOnce(false);
635
+ await expectHttp(service.impersonateUser(admin, 6, {
636
+ password: 'bad'
637
+ }, res));
638
+ const admin2 = new _usermodel.UserModel({
639
+ id: 5,
640
+ clientId: 'c1'
641
+ }, true);
642
+ adminQueriesMock.usersQueries.compareUserPassword.mockResolvedValueOnce(true);
643
+ adminQueriesMock.usersQueries.from.mockResolvedValueOnce({
644
+ id: 6,
645
+ login: 'user'
646
+ });
647
+ authManagerMock.setCookies.mockResolvedValueOnce({
648
+ accessToken: 't'
649
+ });
650
+ expect(await service.impersonateUser(admin2, 6, {
651
+ password: 'ok'
652
+ }, res)).toEqual({
653
+ accessToken: 't'
654
+ });
655
+ const notImpersonated = new _usermodel.UserModel({
656
+ id: 1
657
+ }, true);
658
+ await expectHttp(service.logoutImpersonateUser(notImpersonated, res));
659
+ const impersonated = new _usermodel.UserModel({
660
+ id: 2,
661
+ impersonatedFromId: 9,
662
+ impersonatedClientId: 'X'
663
+ }, true);
664
+ adminQueriesMock.usersQueries.from.mockResolvedValueOnce({
665
+ id: 9,
666
+ role: _user.USER_ROLE.USER
667
+ });
668
+ await expectHttp(service.logoutImpersonateUser(impersonated, res));
669
+ adminQueriesMock.usersQueries.from.mockResolvedValueOnce({
670
+ id: 9,
671
+ role: _user.USER_ROLE.ADMINISTRATOR
672
+ });
673
+ authManagerMock.setCookies.mockResolvedValueOnce({
674
+ accessToken: 'admin'
675
+ });
676
+ expect(await service.logoutImpersonateUser(impersonated, res)).toEqual({
677
+ accessToken: 'admin'
678
+ });
679
+ });
680
+ });
681
+ describe('listing', ()=>{
682
+ it('forwards listUsers and listGuests', async ()=>{
683
+ const users = [
684
+ {
685
+ id: 1
686
+ }
687
+ ];
688
+ adminQueriesMock.listUsers.mockResolvedValueOnce(users);
689
+ expect(await service.listUsers()).toEqual(users);
690
+ expect(adminQueriesMock.listUsers).toHaveBeenCalledWith();
691
+ const guests = [
692
+ {
693
+ id: 2
694
+ }
695
+ ];
696
+ adminQueriesMock.usersQueries.listGuests.mockResolvedValueOnce(guests);
697
+ expect(await service.listGuests()).toEqual(guests);
698
+ expect(adminQueriesMock.usersQueries.listGuests).toHaveBeenCalledWith(null, null, true);
699
+ });
700
+ });
701
+ describe('createGuest', ()=>{
702
+ it('adds the creator as default manager and returns admin guest', async ()=>{
703
+ const creator = new _usermodel.UserModel({
704
+ id: 88
705
+ }, true);
706
+ const dto = {
707
+ login: 'gg',
708
+ email: 'g@x',
709
+ password: 'pwd',
710
+ managers: []
711
+ };
712
+ adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false);
713
+ adminQueriesMock.usersQueries.createUserOrGuest.mockResolvedValueOnce(505);
714
+ spyMakePaths();
715
+ const expectedGuest = {
716
+ id: 505,
717
+ login: 'gg',
718
+ role: _user.USER_ROLE.GUEST
719
+ };
720
+ setGuest(expectedGuest);
721
+ expect(await service.createGuest(creator, dto)).toEqual(expectedGuest);
722
+ expect(adminQueriesMock.usersQueries.createUserOrGuest).toHaveBeenCalledWith(expect.objectContaining({
723
+ login: 'gg',
724
+ email: 'g@x',
725
+ managers: [
726
+ 88
727
+ ]
728
+ }), _user.USER_ROLE.GUEST);
729
+ });
730
+ });
731
+ describe('updateGuest wrapper', ()=>{
732
+ it('updateGuest() -> success', async ()=>{
733
+ const guest = {
734
+ id: 33,
735
+ login: 'g',
736
+ email: 'g@x',
737
+ managers: [
738
+ {
739
+ id: 2
740
+ }
741
+ ],
742
+ role: _user.USER_ROLE.GUEST
743
+ };
744
+ const updatedGuest = {
745
+ ...guest,
746
+ email: 'new@x'
747
+ };
748
+ setGuest(guest);
749
+ adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true);
750
+ setGuest(updatedGuest);
751
+ expect(await service.updateGuest(guest.id, {
752
+ email: 'new@x'
753
+ })).toEqual(updatedGuest);
754
+ });
755
+ });
756
+ describe('deleteUserSpace', ()=>{
757
+ it('space not existing / removeFiles failure', async ()=>{
758
+ fs.isPathExists.mockResolvedValueOnce(false);
759
+ await expect(service.deleteUserSpace('nobody')).resolves.toBeUndefined();
760
+ fs.isPathExists.mockResolvedValueOnce(true);
761
+ fs.removeFiles.mockRejectedValueOnce(new Error('fs error'));
762
+ await expectHttp(service.deleteUserSpace('bob'));
763
+ });
764
+ });
765
+ describe('renameUserSpace error handling', ()=>{
766
+ it('moveFiles throws then restore', async ()=>{
767
+ const current = {
768
+ ...baseUser
769
+ };
770
+ setUser(current);
771
+ adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false);
772
+ fs.isPathExists.mockResolvedValueOnce(true);
773
+ fs.isPathExists.mockResolvedValueOnce(false);
774
+ fs.moveFiles.mockRejectedValueOnce(new Error('io error'));
775
+ fs.moveFiles.mockResolvedValueOnce(undefined);
776
+ await expectHttp(service.updateUserOrGuest(current.id, {
777
+ login: 'new-login'
778
+ }));
779
+ expect(fs.moveFiles).toHaveBeenCalledTimes(2);
780
+ });
781
+ it('current space missing -> early return', async ()=>{
782
+ const current = {
783
+ ...baseUser
784
+ };
785
+ setUser(current);
786
+ adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false);
787
+ fs.isPathExists.mockResolvedValueOnce(false);
788
+ await expectHttp(service.updateUserOrGuest(current.id, {
789
+ login: 'new-login'
790
+ }));
791
+ expect(fs.moveFiles).not.toHaveBeenCalled();
792
+ });
793
+ });
48
794
  });
49
795
 
50
796
  //# sourceMappingURL=admin-users-manager.service.spec.js.map