@sync-in/server 1.6.1 → 1.8.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 (277) hide show
  1. package/CHANGELOG.md +169 -55
  2. package/environment/environment.dist.yaml +14 -5
  3. package/migrations/0003_giant_luckman.sql +6 -0
  4. package/migrations/meta/0003_snapshot.json +2463 -0
  5. package/migrations/meta/_journal.json +7 -0
  6. package/package.json +16 -15
  7. package/server/app.bootstrap.js +1 -0
  8. package/server/app.bootstrap.js.map +1 -1
  9. package/server/app.constants.js +0 -4
  10. package/server/app.constants.js.map +1 -1
  11. package/server/app.service.js +7 -6
  12. package/server/app.service.js.map +1 -1
  13. package/server/applications/files/constants/only-office.js +12 -0
  14. package/server/applications/files/constants/only-office.js.map +1 -1
  15. package/server/applications/files/files.config.js +5 -0
  16. package/server/applications/files/files.config.js.map +1 -1
  17. package/server/applications/files/services/files-content-manager.service.js +6 -6
  18. package/server/applications/files/services/files-content-manager.service.js.map +1 -1
  19. package/server/applications/files/services/files-manager.service.js +4 -4
  20. package/server/applications/files/services/files-manager.service.js.map +1 -1
  21. package/server/applications/files/services/files-methods.service.js +5 -3
  22. package/server/applications/files/services/files-methods.service.js.map +1 -1
  23. package/server/applications/files/services/files-only-office-manager.service.js +2 -2
  24. package/server/applications/files/services/files-only-office-manager.service.js.map +1 -1
  25. package/server/applications/files/services/files-parser.service.js +6 -3
  26. package/server/applications/files/services/files-parser.service.js.map +1 -1
  27. package/server/applications/files/services/files-scheduler.service.js +51 -3
  28. package/server/applications/files/services/files-scheduler.service.js.map +1 -1
  29. package/server/applications/files/services/files-search-manager.service.js +4 -0
  30. package/server/applications/files/services/files-search-manager.service.js.map +1 -1
  31. package/server/applications/files/utils/doc-textify/adapters/pdf.js +10 -1
  32. package/server/applications/files/utils/doc-textify/adapters/pdf.js.map +1 -1
  33. package/server/applications/notifications/i18n/de.js +56 -0
  34. package/server/applications/notifications/i18n/de.js.map +1 -0
  35. package/server/applications/notifications/i18n/es.js +52 -0
  36. package/server/applications/notifications/i18n/es.js.map +1 -0
  37. package/server/applications/notifications/i18n/hi.js +52 -0
  38. package/server/applications/notifications/i18n/hi.js.map +1 -0
  39. package/server/applications/notifications/i18n/index.js +73 -8
  40. package/server/applications/notifications/i18n/index.js.map +1 -1
  41. package/server/applications/notifications/i18n/it.js +52 -0
  42. package/server/applications/notifications/i18n/it.js.map +1 -0
  43. package/server/applications/notifications/i18n/ja.js +52 -0
  44. package/server/applications/notifications/i18n/ja.js.map +1 -0
  45. package/server/applications/notifications/i18n/ko.js +52 -0
  46. package/server/applications/notifications/i18n/ko.js.map +1 -0
  47. package/server/applications/notifications/i18n/pl.js +52 -0
  48. package/server/applications/notifications/i18n/pl.js.map +1 -0
  49. package/server/applications/notifications/i18n/pt.js +52 -0
  50. package/server/applications/notifications/i18n/pt.js.map +1 -0
  51. package/server/applications/notifications/i18n/pt_br.js +52 -0
  52. package/server/applications/notifications/i18n/pt_br.js.map +1 -0
  53. package/server/applications/notifications/i18n/ru.js +52 -0
  54. package/server/applications/notifications/i18n/ru.js.map +1 -0
  55. package/server/applications/notifications/i18n/tr.js +52 -0
  56. package/server/applications/notifications/i18n/tr.js.map +1 -0
  57. package/server/applications/notifications/i18n/zh.js +52 -0
  58. package/server/applications/notifications/i18n/zh.js.map +1 -0
  59. package/server/applications/notifications/mails/models.js +6 -7
  60. package/server/applications/notifications/mails/models.js.map +1 -1
  61. package/server/applications/notifications/services/notifications-manager.service.js.map +1 -1
  62. package/server/applications/shares/dto/create-or-update-share.dto.js +11 -0
  63. package/server/applications/shares/dto/create-or-update-share.dto.js.map +1 -1
  64. package/server/applications/shares/interfaces/share-props.interface.js.map +1 -1
  65. package/server/applications/shares/schemas/share.interface.js.map +1 -1
  66. package/server/applications/shares/schemas/shares.schema.js +9 -0
  67. package/server/applications/shares/schemas/shares.schema.js.map +1 -1
  68. package/server/applications/shares/services/shares-manager.service.js +46 -17
  69. package/server/applications/shares/services/shares-manager.service.js.map +1 -1
  70. package/server/applications/shares/services/shares-queries.service.js +24 -5
  71. package/server/applications/shares/services/shares-queries.service.js.map +1 -1
  72. package/server/applications/spaces/constants/cache.js +4 -0
  73. package/server/applications/spaces/constants/cache.js.map +1 -1
  74. package/server/applications/spaces/dto/create-or-update-space.dto.js +5 -0
  75. package/server/applications/spaces/dto/create-or-update-space.dto.js.map +1 -1
  76. package/server/applications/spaces/guards/space.guard.js +3 -3
  77. package/server/applications/spaces/guards/space.guard.js.map +1 -1
  78. package/server/applications/spaces/models/space-props.model.js.map +1 -1
  79. package/server/applications/spaces/models/space.model.js.map +1 -1
  80. package/server/applications/spaces/schemas/space.interface.js.map +1 -1
  81. package/server/applications/spaces/schemas/spaces.schema.js +1 -0
  82. package/server/applications/spaces/schemas/spaces.schema.js.map +1 -1
  83. package/server/applications/spaces/services/spaces-browser.service.js.map +1 -1
  84. package/server/applications/spaces/services/spaces-manager.service.js +34 -31
  85. package/server/applications/spaces/services/spaces-manager.service.js.map +1 -1
  86. package/server/applications/spaces/services/spaces-queries.service.js +23 -7
  87. package/server/applications/spaces/services/spaces-queries.service.js.map +1 -1
  88. package/server/applications/spaces/services/spaces-scheduler.service.js +21 -20
  89. package/server/applications/spaces/services/spaces-scheduler.service.js.map +1 -1
  90. package/server/applications/spaces/spaces.controller.js +4 -2
  91. package/server/applications/spaces/spaces.controller.js.map +1 -1
  92. package/server/applications/spaces/utils/paths.js +14 -16
  93. package/server/applications/spaces/utils/paths.js.map +1 -1
  94. package/server/applications/sync/services/sync-manager.service.js +4 -3
  95. package/server/applications/sync/services/sync-manager.service.js.map +1 -1
  96. package/server/applications/sync/services/sync-paths-manager.service.js +1 -1
  97. package/server/applications/sync/services/sync-paths-manager.service.js.map +1 -1
  98. package/server/applications/sync/services/sync-paths-manager.service.spec.js +1 -1
  99. package/server/applications/sync/services/sync-paths-manager.service.spec.js.map +1 -1
  100. package/server/applications/sync/sync.controller.js +2 -1
  101. package/server/applications/sync/sync.controller.js.map +1 -1
  102. package/server/applications/users/constants/routes.js +5 -0
  103. package/server/applications/users/constants/routes.js.map +1 -1
  104. package/server/applications/users/constants/user.js +0 -16
  105. package/server/applications/users/constants/user.js.map +1 -1
  106. package/server/applications/users/dto/user-properties.dto.js +10 -0
  107. package/server/applications/users/dto/user-properties.dto.js.map +1 -1
  108. package/server/applications/users/models/user.model.js.map +1 -1
  109. package/server/applications/users/schemas/user.interface.js.map +1 -1
  110. package/server/applications/users/schemas/users.schema.js +3 -2
  111. package/server/applications/users/schemas/users.schema.js.map +1 -1
  112. package/server/applications/users/services/admin-users-manager.service.js +1 -0
  113. package/server/applications/users/services/admin-users-manager.service.js.map +1 -1
  114. package/server/applications/users/services/admin-users-manager.service.spec.js +2 -1
  115. package/server/applications/users/services/admin-users-manager.service.spec.js.map +1 -1
  116. package/server/applications/users/services/users-manager.service.js +8 -2
  117. package/server/applications/users/services/users-manager.service.js.map +1 -1
  118. package/server/applications/users/services/users-manager.service.spec.js +1 -0
  119. package/server/applications/users/services/users-manager.service.spec.js.map +1 -1
  120. package/server/applications/users/services/users-queries.service.js +18 -4
  121. package/server/applications/users/services/users-queries.service.js.map +1 -1
  122. package/server/applications/users/users.controller.js +15 -0
  123. package/server/applications/users/users.controller.js.map +1 -1
  124. package/server/applications/users/utils/test.js +2 -2
  125. package/server/applications/users/utils/test.js.map +1 -1
  126. package/server/applications/webdav/constants/routes.js +2 -2
  127. package/server/applications/webdav/constants/routes.js.map +1 -1
  128. package/server/applications/webdav/constants/webdav.js +2 -2
  129. package/server/applications/webdav/constants/webdav.js.map +1 -1
  130. package/server/applications/webdav/filters/webdav.filter.js +2 -2
  131. package/server/applications/webdav/filters/webdav.filter.js.map +1 -1
  132. package/server/applications/webdav/filters/webdav.filter.spec.js +2 -2
  133. package/server/applications/webdav/filters/webdav.filter.spec.js.map +1 -1
  134. package/server/applications/webdav/services/webdav-methods.service.js +3 -2
  135. package/server/applications/webdav/services/webdav-methods.service.js.map +1 -1
  136. package/server/applications/webdav/utils/webdav.js +1 -2
  137. package/server/applications/webdav/utils/webdav.js.map +1 -1
  138. package/server/authentication/auth.config.js +17 -2
  139. package/server/authentication/auth.config.js.map +1 -1
  140. package/server/authentication/constants/auth-ldap.js +2 -1
  141. package/server/authentication/constants/auth-ldap.js.map +1 -1
  142. package/server/authentication/guards/auth-basic.strategy.js +4 -2
  143. package/server/authentication/guards/auth-basic.strategy.js.map +1 -1
  144. package/server/authentication/guards/auth-local.strategy.js +2 -0
  145. package/server/authentication/guards/auth-local.strategy.js.map +1 -1
  146. package/server/authentication/services/auth-methods/auth-method-ldap.service.js +75 -32
  147. package/server/authentication/services/auth-methods/auth-method-ldap.service.js.map +1 -1
  148. package/server/authentication/services/auth-methods/auth-method-ldap.service.spec.js +2 -1
  149. package/server/authentication/services/auth-methods/auth-method-ldap.service.spec.js.map +1 -1
  150. package/server/common/i18n.js +52 -0
  151. package/server/common/i18n.js.map +1 -0
  152. package/server/common/image.js +49 -33
  153. package/server/common/image.js.map +1 -1
  154. package/server/common/interfaces.js.map +1 -1
  155. package/server/common/shared.js +5 -2
  156. package/server/common/shared.js.map +1 -1
  157. package/server/configuration/config.validation.js +3 -3
  158. package/server/configuration/config.validation.js.map +1 -1
  159. package/server/infrastructure/cache/adapters/mysql-cache.adapter.js +8 -6
  160. package/server/infrastructure/cache/adapters/mysql-cache.adapter.js.map +1 -1
  161. package/server/infrastructure/cache/adapters/redis-cache.adapter.js +22 -17
  162. package/server/infrastructure/cache/adapters/redis-cache.adapter.js.map +1 -1
  163. package/server/infrastructure/cache/cache.e2e-spec.js +1 -0
  164. package/server/infrastructure/cache/cache.e2e-spec.js.map +1 -1
  165. package/server/infrastructure/cache/cache.module.js +1 -14
  166. package/server/infrastructure/cache/cache.module.js.map +1 -1
  167. package/server/infrastructure/cache/services/cache.service.js.map +1 -1
  168. package/server/infrastructure/database/database.module.js +20 -1
  169. package/server/infrastructure/database/database.module.js.map +1 -1
  170. package/server/infrastructure/database/utils.js +48 -0
  171. package/server/infrastructure/database/utils.js.map +1 -1
  172. package/server/infrastructure/scheduler/scheduler.module.js +1 -1
  173. package/server/infrastructure/scheduler/scheduler.module.js.map +1 -1
  174. package/server/infrastructure/websocket/adapters/cluster.adapter.js +1 -3
  175. package/server/infrastructure/websocket/adapters/cluster.adapter.js.map +1 -1
  176. package/static/3rdpartylicenses.txt +137 -137
  177. package/static/chunk-2KLC4T2Z.js +1 -0
  178. package/static/chunk-373XVRXW.js +1 -0
  179. package/static/chunk-3GMLWAFZ.js +1 -0
  180. package/static/chunk-3XVM35O2.js +1 -0
  181. package/static/chunk-3YVRP3VM.js +2 -0
  182. package/static/chunk-5NMSIIQB.js +1 -0
  183. package/static/chunk-AF24EYXU.js +1 -0
  184. package/static/chunk-AKQVEHO6.js +2 -0
  185. package/static/{chunk-LUWQFIWR.js → chunk-AY2SZ3G6.js} +1 -1
  186. package/static/chunk-BCVX464U.js +2 -0
  187. package/static/{chunk-IPAC4VAF.js → chunk-BIKLW4YS.js} +1 -1
  188. package/static/chunk-C36MW4ME.js +562 -0
  189. package/static/chunk-CHJ64RJM.js +1 -0
  190. package/static/chunk-DKSEQTMX.js +1 -0
  191. package/static/chunk-DM4NXKEP.js +1 -0
  192. package/static/chunk-DPUVSXRB.js +1 -0
  193. package/static/chunk-DSWEWLXJ.js +1 -0
  194. package/static/chunk-FJE6BOFL.js +1 -0
  195. package/static/chunk-FZ3JPGYZ.js +1 -0
  196. package/static/chunk-GUGNR5TF.js +3 -0
  197. package/static/chunk-H6NE33VX.js +1 -0
  198. package/static/{chunk-S75P2FFI.js → chunk-HAS5ZOTR.js} +1 -1
  199. package/static/chunk-HNQRZALS.js +1 -0
  200. package/static/chunk-JPT5WEAT.js +1 -0
  201. package/static/{chunk-ZQQPUYLU.js → chunk-JSWCNGXJ.js} +1 -1
  202. package/static/chunk-KFJIQIGR.js +1 -0
  203. package/static/chunk-LNTUR3GU.js +1 -0
  204. package/static/chunk-LVM4QB22.js +1 -0
  205. package/static/chunk-M3XVNQZQ.js +1 -0
  206. package/static/{chunk-AWQ2YTVC.js → chunk-MFLIJH6T.js} +1 -1
  207. package/static/{chunk-IQOALFYU.js → chunk-MSUHTBB2.js} +1 -1
  208. package/static/chunk-N3U6637P.js +1 -0
  209. package/static/chunk-NNV4OXSB.js +1 -0
  210. package/static/chunk-NO2LTNW3.js +1 -0
  211. package/static/chunk-OOGP4WSH.js +2 -0
  212. package/static/chunk-PB4AIT7O.js +1 -0
  213. package/static/chunk-PCWDQPOM.js +2 -0
  214. package/static/chunk-PGZZP5W3.js +1 -0
  215. package/static/chunk-PVDHBQRM.js +1 -0
  216. package/static/chunk-Q5KM7LTX.js +1 -0
  217. package/static/chunk-QHC6ZPQ4.js +1 -0
  218. package/static/chunk-QO6BTONN.js +1 -0
  219. package/static/chunk-QZU2S5CV.js +1 -0
  220. package/static/chunk-SBZ572Q4.js +2 -0
  221. package/static/chunk-SHIVUDP3.js +1 -0
  222. package/static/chunk-SLHTEGRU.js +1 -0
  223. package/static/{chunk-SH5EVL4E.js → chunk-SSFF27P2.js} +1 -1
  224. package/static/chunk-TPYBFZS5.js +1 -0
  225. package/static/chunk-UEQCWMXD.js +1 -0
  226. package/static/chunk-UG5DMXYO.js +1 -0
  227. package/static/chunk-UJPPR4MX.js +1 -0
  228. package/static/chunk-UNCPXHHT.js +1 -0
  229. package/static/chunk-URHTCJ7G.js +1 -0
  230. package/static/chunk-V3AT2BKP.js +1 -0
  231. package/static/chunk-VKK5BSLX.js +1 -0
  232. package/static/{chunk-7DN7ZAPU.js → chunk-VM4YX6Q7.js} +1 -1
  233. package/static/chunk-WJW7CT6G.js +27 -0
  234. package/static/{chunk-7ITZXYYJ.js → chunk-WLMNXRBS.js} +1 -1
  235. package/static/chunk-X5XGK6T7.js +4 -0
  236. package/static/chunk-YEKR5OPO.js +1 -0
  237. package/static/chunk-YW57T2PF.js +1 -0
  238. package/static/chunk-Z5J5F5SX.js +1 -0
  239. package/static/chunk-ZIJQRARU.js +1 -0
  240. package/static/chunk-ZPF2DSQV.js +1 -0
  241. package/static/chunk-ZTCRGJ6Y.js +7 -0
  242. package/static/index.html +2 -2
  243. package/static/main-VOL6OMJ5.js +9 -0
  244. package/static/scripts-WRDOQIU5.js +24 -0
  245. package/static/{styles-A5VYX3CE.css → styles-2C2UNCNB.css} +1 -1
  246. package/server/applications/spaces/interfaces/space-quota.interface.js +0 -10
  247. package/server/applications/spaces/interfaces/space-quota.interface.js.map +0 -1
  248. package/static/chunk-22EANI6R.js +0 -1
  249. package/static/chunk-27YQB3TE.js +0 -1
  250. package/static/chunk-2I4CUFUA.js +0 -1
  251. package/static/chunk-2MTM6SWN.js +0 -4
  252. package/static/chunk-34MKICK5.js +0 -27
  253. package/static/chunk-5O3DIUU3.js +0 -1
  254. package/static/chunk-6NMVZIIT.js +0 -1
  255. package/static/chunk-7FUM3JGM.js +0 -1
  256. package/static/chunk-7P27WBGC.js +0 -4
  257. package/static/chunk-ATP3BFHV.js +0 -562
  258. package/static/chunk-DSOE3FEP.js +0 -1
  259. package/static/chunk-EFKMBLRE.js +0 -1
  260. package/static/chunk-FUFKVHPU.js +0 -1
  261. package/static/chunk-HCDLWTMW.js +0 -7
  262. package/static/chunk-JASU3CIH.js +0 -1
  263. package/static/chunk-JQ5FTO2M.js +0 -1
  264. package/static/chunk-JUNZFADM.js +0 -1
  265. package/static/chunk-JXZCNFW7.js +0 -1
  266. package/static/chunk-LJUKI4SQ.js +0 -1
  267. package/static/chunk-ORMRCEGT.js +0 -1
  268. package/static/chunk-Q7D6RN4N.js +0 -1
  269. package/static/chunk-QJX6ITLW.js +0 -1
  270. package/static/chunk-QQ6UQQBR.js +0 -1
  271. package/static/chunk-RTRJ3KFH.js +0 -1
  272. package/static/chunk-S2HDY3OL.js +0 -1
  273. package/static/chunk-T3EYFSVZ.js +0 -1
  274. package/static/chunk-U34OZUZ7.js +0 -1
  275. package/static/chunk-Y7EH7G5K.js +0 -1
  276. package/static/main-7SQDDVMD.js +0 -9
  277. package/static/scripts-VZVAP2P4.js +0 -30
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/users/schemas/users.schema.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { SQL, sql } from 'drizzle-orm'\nimport { bigint, boolean, char, datetime, index, mysqlTable, tinyint, uniqueIndex, varchar } from 'drizzle-orm/mysql-core'\nimport { jsonColumn } from '../../../infrastructure/database/columns'\nimport { UserSecrets } from '../interfaces/user-secrets.interface'\n\n/*\n role:\n 0: administrator\n 1: user\n 2: guest\n 3: link\n notification:\n 0: application\n 1: application + mail\n onlineStatus:\n 0: available\n 1: busy\n 2: absent\n 3: offline\n storageQuota:\n 0 : no storage\n null : unlimited\n other: limited to value\n*/\n\nexport const users = mysqlTable(\n 'users',\n {\n id: bigint('id', { mode: 'number', unsigned: true }).autoincrement().primaryKey(),\n email: varchar('email', { length: 255 }).notNull(),\n login: varchar('login', { length: 255 }).notNull(),\n firstName: varchar('firstName', { length: 255 }),\n lastName: varchar('lastName', { length: 255 }),\n password: varchar('password', { length: 255 }).notNull(),\n passwordAttempts: tinyint('passwordAttempts', { unsigned: true }).default(0).notNull(),\n role: tinyint('role', { unsigned: true }).default(1).notNull(),\n isActive: boolean('isActive').default(true).notNull(),\n secrets: jsonColumn<UserSecrets>()('secrets'),\n language: char('language', { length: 2 }),\n permissions: varchar('permissions', { length: 255 }).default('').notNull(),\n storageUsage: bigint('storageUsage', { mode: 'number', unsigned: true }).default(0),\n storageQuota: bigint('storageQuota', { mode: 'number', unsigned: true }),\n notification: tinyint('notification', { unsigned: true }).default(1).notNull(),\n onlineStatus: tinyint('onlineStatus', { unsigned: true }).default(0).notNull(),\n currentIp: varchar('currentIp', { length: 45 }),\n lastIp: varchar('lastIp', { length: 45 }),\n currentAccess: datetime('currentAccess', { mode: 'date' }),\n lastAccess: datetime('lastAccess', { mode: 'date' }),\n createdAt: datetime('createdAt', { mode: 'date' })\n .default(sql`CURRENT_TIMESTAMP`)\n .notNull()\n },\n (table) => [uniqueIndex('email_idx').on(table.email), uniqueIndex('login_idx').on(table.login), index('role_idx').on(table.role)]\n)\n\nexport const userFullNameSQL = (user: any): SQL<string> => sql`TRIM(CONCAT(${user.firstName}, ' ', ${user.lastName}))`\n"],"names":["userFullNameSQL","users","mysqlTable","id","bigint","mode","unsigned","autoincrement","primaryKey","email","varchar","length","notNull","login","firstName","lastName","password","passwordAttempts","tinyint","default","role","isActive","boolean","secrets","jsonColumn","language","char","permissions","storageUsage","storageQuota","notification","onlineStatus","currentIp","lastIp","currentAccess","datetime","lastAccess","createdAt","sql","table","uniqueIndex","on","index","user"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QAyDYA;eAAAA;;QA9BAC;eAAAA;;;4BAzBY;2BACyE;yBACvE;AAuBpB,MAAMA,QAAQC,IAAAA,qBAAU,EAC7B,SACA;IACEC,IAAIC,IAAAA,iBAAM,EAAC,MAAM;QAAEC,MAAM;QAAUC,UAAU;IAAK,GAAGC,aAAa,GAAGC,UAAU;IAC/EC,OAAOC,IAAAA,kBAAO,EAAC,SAAS;QAAEC,QAAQ;IAAI,GAAGC,OAAO;IAChDC,OAAOH,IAAAA,kBAAO,EAAC,SAAS;QAAEC,QAAQ;IAAI,GAAGC,OAAO;IAChDE,WAAWJ,IAAAA,kBAAO,EAAC,aAAa;QAAEC,QAAQ;IAAI;IAC9CI,UAAUL,IAAAA,kBAAO,EAAC,YAAY;QAAEC,QAAQ;IAAI;IAC5CK,UAAUN,IAAAA,kBAAO,EAAC,YAAY;QAAEC,QAAQ;IAAI,GAAGC,OAAO;IACtDK,kBAAkBC,IAAAA,kBAAO,EAAC,oBAAoB;QAAEZ,UAAU;IAAK,GAAGa,OAAO,CAAC,GAAGP,OAAO;IACpFQ,MAAMF,IAAAA,kBAAO,EAAC,QAAQ;QAAEZ,UAAU;IAAK,GAAGa,OAAO,CAAC,GAAGP,OAAO;IAC5DS,UAAUC,IAAAA,kBAAO,EAAC,YAAYH,OAAO,CAAC,MAAMP,OAAO;IACnDW,SAASC,IAAAA,mBAAU,IAAgB;IACnCC,UAAUC,IAAAA,eAAI,EAAC,YAAY;QAAEf,QAAQ;IAAE;IACvCgB,aAAajB,IAAAA,kBAAO,EAAC,eAAe;QAAEC,QAAQ;IAAI,GAAGQ,OAAO,CAAC,IAAIP,OAAO;IACxEgB,cAAcxB,IAAAA,iBAAM,EAAC,gBAAgB;QAAEC,MAAM;QAAUC,UAAU;IAAK,GAAGa,OAAO,CAAC;IACjFU,cAAczB,IAAAA,iBAAM,EAAC,gBAAgB;QAAEC,MAAM;QAAUC,UAAU;IAAK;IACtEwB,cAAcZ,IAAAA,kBAAO,EAAC,gBAAgB;QAAEZ,UAAU;IAAK,GAAGa,OAAO,CAAC,GAAGP,OAAO;IAC5EmB,cAAcb,IAAAA,kBAAO,EAAC,gBAAgB;QAAEZ,UAAU;IAAK,GAAGa,OAAO,CAAC,GAAGP,OAAO;IAC5EoB,WAAWtB,IAAAA,kBAAO,EAAC,aAAa;QAAEC,QAAQ;IAAG;IAC7CsB,QAAQvB,IAAAA,kBAAO,EAAC,UAAU;QAAEC,QAAQ;IAAG;IACvCuB,eAAeC,IAAAA,mBAAQ,EAAC,iBAAiB;QAAE9B,MAAM;IAAO;IACxD+B,YAAYD,IAAAA,mBAAQ,EAAC,cAAc;QAAE9B,MAAM;IAAO;IAClDgC,WAAWF,IAAAA,mBAAQ,EAAC,aAAa;QAAE9B,MAAM;IAAO,GAC7Cc,OAAO,CAACmB,IAAAA,eAAG,CAAA,CAAC,iBAAiB,CAAC,EAC9B1B,OAAO;AACZ,GACA,CAAC2B,QAAU;QAACC,IAAAA,sBAAW,EAAC,aAAaC,EAAE,CAACF,MAAM9B,KAAK;QAAG+B,IAAAA,sBAAW,EAAC,aAAaC,EAAE,CAACF,MAAM1B,KAAK;QAAG6B,IAAAA,gBAAK,EAAC,YAAYD,EAAE,CAACF,MAAMnB,IAAI;KAAE;AAG5H,MAAMpB,kBAAkB,CAAC2C,OAA2BL,IAAAA,eAAG,CAAA,CAAC,YAAY,EAAEK,KAAK7B,SAAS,CAAC,OAAO,EAAE6B,KAAK5B,QAAQ,CAAC,EAAE,CAAC"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/users/schemas/users.schema.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { SQL, sql } from 'drizzle-orm'\nimport { bigint, boolean, datetime, index, mysqlTable, tinyint, uniqueIndex, varchar } from 'drizzle-orm/mysql-core'\nimport { jsonColumn } from '../../../infrastructure/database/columns'\nimport { UserSecrets } from '../interfaces/user-secrets.interface'\n\n/*\n role:\n 0: administrator\n 1: user\n 2: guest\n 3: link\n notification:\n 0: application\n 1: application + mail\n onlineStatus:\n 0: available\n 1: busy\n 2: absent\n 3: offline\n storageQuota:\n 0 : no storage\n null : unlimited\n other: limited to value\n*/\n\nexport const users = mysqlTable(\n 'users',\n {\n id: bigint('id', { mode: 'number', unsigned: true }).autoincrement().primaryKey(),\n email: varchar('email', { length: 255 }).notNull(),\n login: varchar('login', { length: 255 }).notNull(),\n firstName: varchar('firstName', { length: 255 }),\n lastName: varchar('lastName', { length: 255 }),\n password: varchar('password', { length: 255 }).notNull(),\n passwordAttempts: tinyint('passwordAttempts', { unsigned: true }).default(0).notNull(),\n role: tinyint('role', { unsigned: true }).default(1).notNull(),\n isActive: boolean('isActive').default(true).notNull(),\n secrets: jsonColumn<UserSecrets>()('secrets'),\n language: varchar('language', { length: 10 }),\n permissions: varchar('permissions', { length: 255 }).default('').notNull(),\n storageUsage: bigint('storageUsage', { mode: 'number', unsigned: true }).default(0),\n storageQuota: bigint('storageQuota', { mode: 'number', unsigned: true }),\n storageIndexing: boolean('storageIndexing').default(true).notNull(),\n notification: tinyint('notification', { unsigned: true }).default(1).notNull(),\n onlineStatus: tinyint('onlineStatus', { unsigned: true }).default(0).notNull(),\n currentIp: varchar('currentIp', { length: 45 }),\n lastIp: varchar('lastIp', { length: 45 }),\n currentAccess: datetime('currentAccess', { mode: 'date' }),\n lastAccess: datetime('lastAccess', { mode: 'date' }),\n createdAt: datetime('createdAt', { mode: 'date' })\n .default(sql`CURRENT_TIMESTAMP`)\n .notNull()\n },\n (table) => [uniqueIndex('email_idx').on(table.email), uniqueIndex('login_idx').on(table.login), index('role_idx').on(table.role)]\n)\n\nexport const userFullNameSQL = (user: any): SQL<string> => sql`TRIM(CONCAT(${user.firstName}, ' ', ${user.lastName}))`\n"],"names":["userFullNameSQL","users","mysqlTable","id","bigint","mode","unsigned","autoincrement","primaryKey","email","varchar","length","notNull","login","firstName","lastName","password","passwordAttempts","tinyint","default","role","isActive","boolean","secrets","jsonColumn","language","permissions","storageUsage","storageQuota","storageIndexing","notification","onlineStatus","currentIp","lastIp","currentAccess","datetime","lastAccess","createdAt","sql","table","uniqueIndex","on","index","user"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QA0DYA;eAAAA;;QA/BAC;eAAAA;;;4BAzBY;2BACmE;yBACjE;AAuBpB,MAAMA,QAAQC,IAAAA,qBAAU,EAC7B,SACA;IACEC,IAAIC,IAAAA,iBAAM,EAAC,MAAM;QAAEC,MAAM;QAAUC,UAAU;IAAK,GAAGC,aAAa,GAAGC,UAAU;IAC/EC,OAAOC,IAAAA,kBAAO,EAAC,SAAS;QAAEC,QAAQ;IAAI,GAAGC,OAAO;IAChDC,OAAOH,IAAAA,kBAAO,EAAC,SAAS;QAAEC,QAAQ;IAAI,GAAGC,OAAO;IAChDE,WAAWJ,IAAAA,kBAAO,EAAC,aAAa;QAAEC,QAAQ;IAAI;IAC9CI,UAAUL,IAAAA,kBAAO,EAAC,YAAY;QAAEC,QAAQ;IAAI;IAC5CK,UAAUN,IAAAA,kBAAO,EAAC,YAAY;QAAEC,QAAQ;IAAI,GAAGC,OAAO;IACtDK,kBAAkBC,IAAAA,kBAAO,EAAC,oBAAoB;QAAEZ,UAAU;IAAK,GAAGa,OAAO,CAAC,GAAGP,OAAO;IACpFQ,MAAMF,IAAAA,kBAAO,EAAC,QAAQ;QAAEZ,UAAU;IAAK,GAAGa,OAAO,CAAC,GAAGP,OAAO;IAC5DS,UAAUC,IAAAA,kBAAO,EAAC,YAAYH,OAAO,CAAC,MAAMP,OAAO;IACnDW,SAASC,IAAAA,mBAAU,IAAgB;IACnCC,UAAUf,IAAAA,kBAAO,EAAC,YAAY;QAAEC,QAAQ;IAAG;IAC3Ce,aAAahB,IAAAA,kBAAO,EAAC,eAAe;QAAEC,QAAQ;IAAI,GAAGQ,OAAO,CAAC,IAAIP,OAAO;IACxEe,cAAcvB,IAAAA,iBAAM,EAAC,gBAAgB;QAAEC,MAAM;QAAUC,UAAU;IAAK,GAAGa,OAAO,CAAC;IACjFS,cAAcxB,IAAAA,iBAAM,EAAC,gBAAgB;QAAEC,MAAM;QAAUC,UAAU;IAAK;IACtEuB,iBAAiBP,IAAAA,kBAAO,EAAC,mBAAmBH,OAAO,CAAC,MAAMP,OAAO;IACjEkB,cAAcZ,IAAAA,kBAAO,EAAC,gBAAgB;QAAEZ,UAAU;IAAK,GAAGa,OAAO,CAAC,GAAGP,OAAO;IAC5EmB,cAAcb,IAAAA,kBAAO,EAAC,gBAAgB;QAAEZ,UAAU;IAAK,GAAGa,OAAO,CAAC,GAAGP,OAAO;IAC5EoB,WAAWtB,IAAAA,kBAAO,EAAC,aAAa;QAAEC,QAAQ;IAAG;IAC7CsB,QAAQvB,IAAAA,kBAAO,EAAC,UAAU;QAAEC,QAAQ;IAAG;IACvCuB,eAAeC,IAAAA,mBAAQ,EAAC,iBAAiB;QAAE9B,MAAM;IAAO;IACxD+B,YAAYD,IAAAA,mBAAQ,EAAC,cAAc;QAAE9B,MAAM;IAAO;IAClDgC,WAAWF,IAAAA,mBAAQ,EAAC,aAAa;QAAE9B,MAAM;IAAO,GAC7Cc,OAAO,CAACmB,IAAAA,eAAG,CAAA,CAAC,iBAAiB,CAAC,EAC9B1B,OAAO;AACZ,GACA,CAAC2B,QAAU;QAACC,IAAAA,sBAAW,EAAC,aAAaC,EAAE,CAACF,MAAM9B,KAAK;QAAG+B,IAAAA,sBAAW,EAAC,aAAaC,EAAE,CAACF,MAAM1B,KAAK;QAAG6B,IAAAA,gBAAK,EAAC,YAAYD,EAAE,CAACF,MAAMnB,IAAI;KAAE;AAG5H,MAAMpB,kBAAkB,CAAC2C,OAA2BL,IAAAA,eAAG,CAAA,CAAC,YAAY,EAAEK,KAAK7B,SAAS,CAAC,OAAO,EAAE6B,KAAK5B,QAAQ,CAAC,EAAE,CAAC"}
@@ -54,6 +54,7 @@ let AdminUsersManager = class AdminUsersManager {
54
54
  role: userRole
55
55
  });
56
56
  this.logger.log(`${this.createUserOrGuest.name} - ${_user.USER_ROLE[userRole]} (${userId}) was created : ${JSON.stringify((0, _functions.anonymizePassword)(createUserDto))}`);
57
+ this.adminQueries.usersQueries.clearWhiteListCaches('*');
57
58
  await user.makePaths();
58
59
  if (userRole <= _user.USER_ROLE.USER) {
59
60
  return asAdmin ? this.getUser(user.id) : user;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/users/services/admin-users-manager.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'\nimport { FastifyReply } from 'fastify'\nimport { LoginResponseDto } from '../../../authentication/dto/login-response.dto'\nimport { AuthManager } from '../../../authentication/services/auth-manager.service'\nimport { anonymizePassword, hashPassword } from '../../../common/functions'\nimport { isPathExists, moveFiles, removeFiles } from '../../files/utils/files'\nimport { GROUP_TYPE } from '../constants/group'\nimport { USER_ROLE } from '../constants/user'\nimport type { CreateOrUpdateGroupDto } from '../dto/create-or-update-group.dto'\nimport type { CreateUserDto, UpdateUserDto, UpdateUserFromGroupDto } from '../dto/create-or-update-user.dto'\nimport type { DeleteUserDto } from '../dto/delete-user.dto'\nimport type { SearchMembersDto } from '../dto/search-members.dto'\nimport type { AdminGroup } from '../interfaces/admin-group.interface'\nimport type { AdminUser } from '../interfaces/admin-user.interface'\nimport type { GroupBrowse } from '../interfaces/group-browse.interface'\nimport type { GuestUser } from '../interfaces/guest-user.interface'\nimport type { Member } from '../interfaces/member.interface'\nimport { UserModel } from '../models/user.model'\nimport type { Group } from '../schemas/group.interface'\nimport type { User } from '../schemas/user.interface'\nimport { AdminUsersQueries } from './admin-users-queries.service'\n\n@Injectable()\nexport class AdminUsersManager {\n private readonly logger = new Logger(AdminUsersManager.name)\n\n constructor(\n private readonly authManager: AuthManager,\n private readonly adminQueries: AdminUsersQueries\n ) {}\n\n listUsers(): Promise<AdminUser[]> {\n return this.adminQueries.listUsers()\n }\n\n async getUser(userId: number): Promise<AdminUser> {\n const user: AdminUser = await this.adminQueries.listUsers(userId)\n this.checkUser(user, true)\n return user\n }\n\n async getGuest(guestId: number): Promise<GuestUser> {\n const user: GuestUser = await this.adminQueries.usersQueries.listGuests(guestId, 0, true)\n this.checkUser(user, true)\n return user\n }\n\n async createUserOrGuest(createUserDto: CreateUserDto, userRole: USER_ROLE.GUEST, asAdmin: boolean): Promise<GuestUser>\n async createUserOrGuest(createUserDto: CreateUserDto, userRole: USER_ROLE, asAdmin: true): Promise<AdminUser | GuestUser>\n async createUserOrGuest(createUserDto: CreateUserDto, userRole: USER_ROLE, asAdmin?: false): Promise<UserModel>\n async createUserOrGuest(\n createUserDto: CreateUserDto,\n userRole: USER_ROLE = USER_ROLE.USER,\n asAdmin = false\n ): Promise<UserModel | AdminUser | GuestUser> {\n await this.loginOrEmailAlreadyUsed(createUserDto.login, createUserDto.email)\n try {\n createUserDto.password = await hashPassword(createUserDto.password)\n const userId: number = await this.adminQueries.usersQueries.createUserOrGuest(createUserDto, userRole)\n const user = new UserModel({ ...createUserDto, id: userId, role: userRole })\n this.logger.log(\n `${this.createUserOrGuest.name} - ${USER_ROLE[userRole]} (${userId}) was created : ${JSON.stringify(anonymizePassword(createUserDto))}`\n )\n await user.makePaths()\n if (userRole <= USER_ROLE.USER) {\n return asAdmin ? this.getUser(user.id) : user\n } else {\n return asAdmin ? this.getGuest(user.id) : user\n }\n } catch (e) {\n this.logger.error(`${this.createUserOrGuest.name} - unable to create user *${createUserDto.login}* : ${e}`)\n throw new HttpException('Unable to create user', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n\n async updateUserOrGuest(userId: number, updateUserDto: UpdateUserDto): Promise<AdminUser>\n async updateUserOrGuest(userId: number, updateUserDto: UpdateUserDto, userRole: USER_ROLE.GUEST): Promise<GuestUser>\n async updateUserOrGuest(\n userId: number,\n updateUserDto: UpdateUserDto,\n userRole: USER_ROLE.USER | USER_ROLE.GUEST = USER_ROLE.USER\n ): Promise<AdminUser | GuestUser> {\n const user: AdminUser & GuestUser = userRole === USER_ROLE.USER ? await this.getUser(userId) : await this.getGuest(userId)\n const updateUser: Partial<User> = {}\n const updateUserGroups: { add: number[]; delete: number[] } = { add: [], delete: [] }\n const updateGuestManagers: { add: number[]; delete: number[] } = { add: [], delete: [] }\n for (const [k, v] of Object.entries(updateUserDto)) {\n switch (k as keyof UpdateUserDto) {\n case 'login':\n if (user.login === v) {\n break\n }\n if (await this.adminQueries.usersQueries.checkUserExists(v)) {\n throw new HttpException('Login already used', HttpStatus.FORBIDDEN)\n }\n if (!(await this.renameUserSpace(user.login, v))) {\n throw new HttpException('Unable to rename user space', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n updateUser.login = v\n break\n case 'email':\n if (user.email === v) {\n break\n }\n if (await this.adminQueries.usersQueries.checkUserExists(null, v)) {\n throw new HttpException('Email already used', HttpStatus.FORBIDDEN)\n }\n updateUser.email = v\n break\n case 'isActive':\n updateUser.isActive = v\n if (v) {\n updateUser.passwordAttempts = 0\n }\n break\n case 'password':\n updateUser.password = await hashPassword(updateUserDto.password)\n break\n case 'groups':\n if (userRole === USER_ROLE.USER) {\n const currentGroups: number[] = user.groups?.length ? user.groups.map((g) => g.id) : []\n updateUserGroups.add = v.filter((id: number) => currentGroups.indexOf(id) === -1)\n updateUserGroups.delete = currentGroups.filter((id: number) => v.indexOf(id) === -1)\n }\n break\n case 'managers':\n if (userRole === USER_ROLE.GUEST) {\n const currentManagers: number[] = user.managers?.length ? user.managers.map((m) => m.id) : []\n updateGuestManagers.add = v.filter((id: number) => currentManagers.indexOf(id) === -1)\n updateGuestManagers.delete = currentManagers.filter((id: number) => v.indexOf(id) === -1)\n }\n break\n default:\n updateUser[k] = v\n }\n }\n if (Object.keys(updateUser).length) {\n // force the type for security reason\n const forceRole = userRole === USER_ROLE.GUEST ? USER_ROLE.GUEST : undefined\n if (!(await this.adminQueries.usersQueries.updateUserOrGuest(user.id, updateUser, forceRole))) {\n throw new HttpException('Unable to update user', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n if (userRole === USER_ROLE.USER) {\n if (updateUserGroups.add.length || updateUserGroups.delete.length) {\n try {\n await this.adminQueries.updateUserGroups(user.id, updateUserGroups)\n } catch {\n throw new HttpException('Unable to update user groups', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n return this.getUser(userId)\n } else {\n if (updateGuestManagers.add.length || updateGuestManagers.delete.length) {\n try {\n await this.adminQueries.updateGuestManagers(user.id, updateGuestManagers)\n } catch {\n throw new HttpException('Unable to update guest managers', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n return this.getGuest(userId)\n }\n }\n\n async deleteUserOrGuest(userId: number, userLogin: string, deleteUserDto: DeleteUserDto): Promise<void> {\n try {\n if (await this.adminQueries.deleteUser(userId, userLogin)) {\n this.logger.log(`${this.deleteUserOrGuest.name} - *${userLogin}* (${userId}) was deleted`)\n } else {\n this.logger.error(`${this.deleteUserOrGuest.name} - *${userLogin}* (${userId}) was not deleted : not found`)\n }\n if (deleteUserDto.deleteSpace) {\n await this.deleteUserSpace(userLogin, deleteUserDto.isGuest)\n }\n } catch (e) {\n this.logger.error(`${this.deleteUserOrGuest.name} - unable to delete *${userLogin}* (${userId}) : ${e}`)\n throw new HttpException('Unable to delete user', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n\n async deleteUserOrGuestFromAdmin(userId: number, deleteUserDto: DeleteUserDto): Promise<void> {\n const userToDelete: UserModel = this.checkUser(await this.adminQueries.usersQueries.from(userId))\n if (userToDelete.isGuest !== deleteUserDto.isGuest) {\n throw new HttpException('User mismatch', HttpStatus.BAD_REQUEST)\n }\n await this.deleteUserOrGuest(userToDelete.id, userToDelete.login, {\n deleteSpace: deleteUserDto.isGuest ? true : deleteUserDto.deleteSpace,\n isGuest: deleteUserDto.isGuest\n } satisfies DeleteUserDto)\n }\n\n listGuests(): Promise<AdminUser[]> {\n return this.adminQueries.usersQueries.listGuests(null, null, true)\n }\n\n createGuest(user: UserModel, createGuestDto: CreateUserDto): Promise<GuestUser> {\n if (!createGuestDto.managers.length) {\n createGuestDto.managers.push(user.id)\n }\n return this.createUserOrGuest(createGuestDto, USER_ROLE.GUEST, true)\n }\n\n updateGuest(guestId: number, updateGuestDto: UpdateUserDto): Promise<GuestUser> {\n if (!Object.keys(updateGuestDto).length) {\n throw new HttpException('No changes to update', HttpStatus.BAD_REQUEST)\n }\n if (updateGuestDto.managers && !updateGuestDto.managers.length) {\n throw new HttpException('Guest must have at least one manager', HttpStatus.BAD_REQUEST)\n }\n return this.updateUserOrGuest(guestId, updateGuestDto, USER_ROLE.GUEST)\n }\n\n async browseGroups(name?: string, type: GROUP_TYPE = GROUP_TYPE.USER): Promise<GroupBrowse> {\n if (name) {\n const group: Pick<Group, 'id' | 'name' | 'type'> = await this.adminQueries.groupFromName(name)\n if (!group) {\n throw new HttpException('Group not found', HttpStatus.NOT_FOUND)\n }\n return { parentGroup: group, members: await this.adminQueries.browseGroupMembers(group.id, type) }\n }\n return { parentGroup: undefined, members: await this.adminQueries.browseRootGroupMembers(type) }\n }\n\n async getGroup(groupId: number): Promise<AdminGroup> {\n const group = await this.adminQueries.groupFromId(groupId)\n if (!group) {\n throw new HttpException('Group not found', HttpStatus.NOT_FOUND)\n }\n return group\n }\n\n async createGroup(createGroupDto: CreateOrUpdateGroupDto): Promise<AdminGroup> {\n if (!createGroupDto.name) {\n this.logger.error(`${this.createGroup.name} - missing group name : ${JSON.stringify(createGroupDto)}`)\n throw new HttpException('Group name is missing', HttpStatus.BAD_REQUEST)\n }\n await this.checkGroupNameExists(createGroupDto.name)\n try {\n const groupId: number = await this.adminQueries.createGroup(createGroupDto)\n this.logger.log(`${this.createGroup.name} - group (${groupId}) was created : ${JSON.stringify(createGroupDto)}`)\n return this.adminQueries.groupFromId(groupId)\n } catch (e) {\n this.logger.error(`${this.createGroup.name} - group was not created : ${JSON.stringify(createGroupDto)} : ${e}`)\n throw new HttpException('Unable to create group', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n\n async updateGroup(groupId: number, updateGroupDto: CreateOrUpdateGroupDto): Promise<AdminGroup> {\n if (updateGroupDto.name) {\n await this.checkGroupNameExists(updateGroupDto.name)\n }\n if (!(await this.adminQueries.updateGroup(groupId, updateGroupDto))) {\n throw new HttpException('Unable to update group', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n return this.adminQueries.groupFromId(groupId)\n }\n\n async deleteGroup(groupId: number): Promise<void> {\n if (await this.adminQueries.deleteGroup(groupId)) {\n this.logger.log(`${this.deleteGroup.name} - group (${groupId}) was deleted`)\n } else {\n this.logger.warn(`${this.deleteGroup.name} - group (${groupId}) does not exist`)\n throw new HttpException('Unable to delete group', HttpStatus.BAD_REQUEST)\n }\n }\n\n async addUsersToGroup(groupId: number, userIds: number[]): Promise<void> {\n const group: AdminGroup = await this.adminQueries.groupFromId(groupId)\n if (!group) {\n throw new HttpException('Group not found', HttpStatus.NOT_FOUND)\n }\n try {\n await this.adminQueries.addUsersToGroup(groupId, userIds, group.type === GROUP_TYPE.USER ? USER_ROLE.USER : undefined)\n } catch (e) {\n throw new HttpException(e.message, HttpStatus.BAD_REQUEST)\n }\n }\n\n async updateUserFromGroup(groupId: number, userId: number, updateUserFromGroupDto: UpdateUserFromGroupDto): Promise<void> {\n try {\n await this.adminQueries.updateUserFromGroup(groupId, userId, updateUserFromGroupDto.role)\n } catch (e) {\n throw new HttpException(e.message, HttpStatus.BAD_REQUEST)\n }\n }\n\n async removeUserFromGroup(groupId: number, userId: number): Promise<void> {\n try {\n await this.adminQueries.removeUserFromGroup(groupId, userId)\n } catch (e) {\n throw new HttpException(e.message, HttpStatus.BAD_REQUEST)\n }\n }\n\n searchMembers(searchMembersDto: SearchMembersDto): Promise<Member[]> {\n return this.adminQueries.usersQueries.searchUsersOrGroups(searchMembersDto)\n }\n\n async impersonateUser(admin: UserModel, userId: number, res: FastifyReply): Promise<LoginResponseDto> {\n if (admin.id === userId) {\n throw new HttpException('You are already logged in', HttpStatus.BAD_REQUEST)\n }\n const user: UserModel = this.checkUser(await this.adminQueries.usersQueries.from(userId))\n user.impersonatedFromId = admin.id\n user.impersonatedClientId = admin.clientId\n return this.authManager.setCookies(user, res)\n }\n\n async logoutImpersonateUser(user: UserModel, res: FastifyReply): Promise<LoginResponseDto> {\n if (!user.impersonatedFromId) {\n throw new HttpException('You are not allowed to do this action', HttpStatus.FORBIDDEN)\n }\n const admin: UserModel = this.checkUser(await this.adminQueries.usersQueries.from(user.impersonatedFromId))\n if (!admin.isAdmin) {\n throw new HttpException('You are not allowed to do this action', HttpStatus.FORBIDDEN)\n }\n admin.clientId = user.impersonatedClientId\n return this.authManager.setCookies(admin, res)\n }\n\n async deleteUserSpace(userLogin: string, isGuest = false): Promise<void> {\n const userSpace: string = UserModel.getHomePath(userLogin, isGuest)\n try {\n if (await isPathExists(userSpace)) {\n await removeFiles(userSpace)\n this.logger.log(`${this.deleteUserSpace.name} - user space *${userLogin}* was deleted`)\n } else {\n this.logger.warn(`${this.deleteUserSpace.name} - user space *${userLogin}* does not exist : ${userSpace}`)\n }\n } catch (e) {\n this.logger.warn(`${this.deleteUserSpace.name} - user space *${userLogin}* (${userSpace}) was not deleted : ${e}`)\n throw new HttpException('Unable to delete user space', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n\n checkUser(user: User | AdminUser | GuestUser, checkOnly: true): void\n checkUser(user: User | AdminUser | GuestUser, checkOnly?: false): UserModel\n checkUser(user: User | AdminUser | GuestUser, checkOnly = false): UserModel | void {\n if (!user) {\n throw new HttpException('User not found', HttpStatus.NOT_FOUND)\n }\n if (!checkOnly) {\n return new UserModel(user, true)\n }\n }\n\n private async renameUserSpace(oldLogin: string, newLogin: string): Promise<boolean> {\n const currentUserSpace: string = UserModel.getHomePath(oldLogin)\n if (!(await isPathExists(currentUserSpace))) {\n this.logger.warn(`${this.renameUserSpace.name} - user space *${oldLogin}* does not exist : ${currentUserSpace}`)\n return false\n }\n const newUserSpace: string = UserModel.getHomePath(newLogin)\n if (await isPathExists(newUserSpace)) {\n this.logger.warn(`${this.renameUserSpace.name} - user space *${newLogin}* already exists : ${newUserSpace}`)\n return false\n }\n try {\n await moveFiles(currentUserSpace, newUserSpace)\n return true\n } catch (e) {\n // try to restore\n await moveFiles(newUserSpace, currentUserSpace, true)\n this.logger.error(`${this.renameUserSpace.name} - unable to rename user space from *${currentUserSpace}* to *${newUserSpace}* : ${e}`)\n return false\n }\n }\n\n private async checkGroupNameExists(groupName: string): Promise<void> {\n if (await this.adminQueries.usersQueries.checkGroupNameExists(groupName)) {\n throw new HttpException('Name already used', HttpStatus.BAD_REQUEST)\n }\n }\n\n private async loginOrEmailAlreadyUsed(login: string, email: string) {\n const exists = await this.adminQueries.usersQueries.checkUserExists(login, email)\n if (exists) {\n throw new HttpException(`${exists.login === login ? 'Login' : 'Email'} already used`, HttpStatus.BAD_REQUEST)\n }\n }\n}\n"],"names":["AdminUsersManager","listUsers","adminQueries","getUser","userId","user","checkUser","getGuest","guestId","usersQueries","listGuests","createUserOrGuest","createUserDto","userRole","USER_ROLE","USER","asAdmin","loginOrEmailAlreadyUsed","login","email","password","hashPassword","UserModel","id","role","logger","log","name","JSON","stringify","anonymizePassword","makePaths","e","error","HttpException","HttpStatus","INTERNAL_SERVER_ERROR","updateUserOrGuest","updateUserDto","updateUser","updateUserGroups","add","delete","updateGuestManagers","k","v","Object","entries","checkUserExists","FORBIDDEN","renameUserSpace","isActive","passwordAttempts","currentGroups","groups","length","map","g","filter","indexOf","GUEST","currentManagers","managers","m","keys","forceRole","undefined","deleteUserOrGuest","userLogin","deleteUserDto","deleteUser","deleteSpace","deleteUserSpace","isGuest","deleteUserOrGuestFromAdmin","userToDelete","from","BAD_REQUEST","createGuest","createGuestDto","push","updateGuest","updateGuestDto","browseGroups","type","GROUP_TYPE","group","groupFromName","NOT_FOUND","parentGroup","members","browseGroupMembers","browseRootGroupMembers","getGroup","groupId","groupFromId","createGroup","createGroupDto","checkGroupNameExists","updateGroup","updateGroupDto","deleteGroup","warn","addUsersToGroup","userIds","message","updateUserFromGroup","updateUserFromGroupDto","removeUserFromGroup","searchMembers","searchMembersDto","searchUsersOrGroups","impersonateUser","admin","res","impersonatedFromId","impersonatedClientId","clientId","authManager","setCookies","logoutImpersonateUser","isAdmin","userSpace","getHomePath","isPathExists","removeFiles","checkOnly","oldLogin","newLogin","currentUserSpace","newUserSpace","moveFiles","groupName","exists","Logger"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/users/services/admin-users-manager.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'\nimport { FastifyReply } from 'fastify'\nimport { LoginResponseDto } from '../../../authentication/dto/login-response.dto'\nimport { AuthManager } from '../../../authentication/services/auth-manager.service'\nimport { anonymizePassword, hashPassword } from '../../../common/functions'\nimport { isPathExists, moveFiles, removeFiles } from '../../files/utils/files'\nimport { GROUP_TYPE } from '../constants/group'\nimport { USER_ROLE } from '../constants/user'\nimport type { CreateOrUpdateGroupDto } from '../dto/create-or-update-group.dto'\nimport type { CreateUserDto, UpdateUserDto, UpdateUserFromGroupDto } from '../dto/create-or-update-user.dto'\nimport type { DeleteUserDto } from '../dto/delete-user.dto'\nimport type { SearchMembersDto } from '../dto/search-members.dto'\nimport type { AdminGroup } from '../interfaces/admin-group.interface'\nimport type { AdminUser } from '../interfaces/admin-user.interface'\nimport type { GroupBrowse } from '../interfaces/group-browse.interface'\nimport type { GuestUser } from '../interfaces/guest-user.interface'\nimport type { Member } from '../interfaces/member.interface'\nimport { UserModel } from '../models/user.model'\nimport type { Group } from '../schemas/group.interface'\nimport type { User } from '../schemas/user.interface'\nimport { AdminUsersQueries } from './admin-users-queries.service'\n\n@Injectable()\nexport class AdminUsersManager {\n private readonly logger = new Logger(AdminUsersManager.name)\n\n constructor(\n private readonly authManager: AuthManager,\n private readonly adminQueries: AdminUsersQueries\n ) {}\n\n listUsers(): Promise<AdminUser[]> {\n return this.adminQueries.listUsers()\n }\n\n async getUser(userId: number): Promise<AdminUser> {\n const user: AdminUser = await this.adminQueries.listUsers(userId)\n this.checkUser(user, true)\n return user\n }\n\n async getGuest(guestId: number): Promise<GuestUser> {\n const user: GuestUser = await this.adminQueries.usersQueries.listGuests(guestId, 0, true)\n this.checkUser(user, true)\n return user\n }\n\n async createUserOrGuest(createUserDto: CreateUserDto, userRole: USER_ROLE.GUEST, asAdmin: boolean): Promise<GuestUser>\n async createUserOrGuest(createUserDto: CreateUserDto, userRole: USER_ROLE, asAdmin: true): Promise<AdminUser | GuestUser>\n async createUserOrGuest(createUserDto: CreateUserDto, userRole: USER_ROLE, asAdmin?: false): Promise<UserModel>\n async createUserOrGuest(\n createUserDto: CreateUserDto,\n userRole: USER_ROLE = USER_ROLE.USER,\n asAdmin = false\n ): Promise<UserModel | AdminUser | GuestUser> {\n await this.loginOrEmailAlreadyUsed(createUserDto.login, createUserDto.email)\n try {\n createUserDto.password = await hashPassword(createUserDto.password)\n const userId: number = await this.adminQueries.usersQueries.createUserOrGuest(createUserDto, userRole)\n const user = new UserModel({ ...createUserDto, id: userId, role: userRole })\n this.logger.log(\n `${this.createUserOrGuest.name} - ${USER_ROLE[userRole]} (${userId}) was created : ${JSON.stringify(anonymizePassword(createUserDto))}`\n )\n this.adminQueries.usersQueries.clearWhiteListCaches('*')\n await user.makePaths()\n if (userRole <= USER_ROLE.USER) {\n return asAdmin ? this.getUser(user.id) : user\n } else {\n return asAdmin ? this.getGuest(user.id) : user\n }\n } catch (e) {\n this.logger.error(`${this.createUserOrGuest.name} - unable to create user *${createUserDto.login}* : ${e}`)\n throw new HttpException('Unable to create user', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n\n async updateUserOrGuest(userId: number, updateUserDto: UpdateUserDto): Promise<AdminUser>\n async updateUserOrGuest(userId: number, updateUserDto: UpdateUserDto, userRole: USER_ROLE.GUEST): Promise<GuestUser>\n async updateUserOrGuest(\n userId: number,\n updateUserDto: UpdateUserDto,\n userRole: USER_ROLE.USER | USER_ROLE.GUEST = USER_ROLE.USER\n ): Promise<AdminUser | GuestUser> {\n const user: AdminUser & GuestUser = userRole === USER_ROLE.USER ? await this.getUser(userId) : await this.getGuest(userId)\n const updateUser: Partial<User> = {}\n const updateUserGroups: { add: number[]; delete: number[] } = { add: [], delete: [] }\n const updateGuestManagers: { add: number[]; delete: number[] } = { add: [], delete: [] }\n for (const [k, v] of Object.entries(updateUserDto)) {\n switch (k as keyof UpdateUserDto) {\n case 'login':\n if (user.login === v) {\n break\n }\n if (await this.adminQueries.usersQueries.checkUserExists(v)) {\n throw new HttpException('Login already used', HttpStatus.FORBIDDEN)\n }\n if (!(await this.renameUserSpace(user.login, v))) {\n throw new HttpException('Unable to rename user space', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n updateUser.login = v\n break\n case 'email':\n if (user.email === v) {\n break\n }\n if (await this.adminQueries.usersQueries.checkUserExists(null, v)) {\n throw new HttpException('Email already used', HttpStatus.FORBIDDEN)\n }\n updateUser.email = v\n break\n case 'isActive':\n updateUser.isActive = v\n if (v) {\n updateUser.passwordAttempts = 0\n }\n break\n case 'password':\n updateUser.password = await hashPassword(updateUserDto.password)\n break\n case 'groups':\n if (userRole === USER_ROLE.USER) {\n const currentGroups: number[] = user.groups?.length ? user.groups.map((g) => g.id) : []\n updateUserGroups.add = v.filter((id: number) => currentGroups.indexOf(id) === -1)\n updateUserGroups.delete = currentGroups.filter((id: number) => v.indexOf(id) === -1)\n }\n break\n case 'managers':\n if (userRole === USER_ROLE.GUEST) {\n const currentManagers: number[] = user.managers?.length ? user.managers.map((m) => m.id) : []\n updateGuestManagers.add = v.filter((id: number) => currentManagers.indexOf(id) === -1)\n updateGuestManagers.delete = currentManagers.filter((id: number) => v.indexOf(id) === -1)\n }\n break\n default:\n updateUser[k] = v\n }\n }\n if (Object.keys(updateUser).length) {\n // force the type for security reason\n const forceRole = userRole === USER_ROLE.GUEST ? USER_ROLE.GUEST : undefined\n if (!(await this.adminQueries.usersQueries.updateUserOrGuest(user.id, updateUser, forceRole))) {\n throw new HttpException('Unable to update user', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n if (userRole === USER_ROLE.USER) {\n if (updateUserGroups.add.length || updateUserGroups.delete.length) {\n try {\n await this.adminQueries.updateUserGroups(user.id, updateUserGroups)\n } catch {\n throw new HttpException('Unable to update user groups', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n return this.getUser(userId)\n } else {\n if (updateGuestManagers.add.length || updateGuestManagers.delete.length) {\n try {\n await this.adminQueries.updateGuestManagers(user.id, updateGuestManagers)\n } catch {\n throw new HttpException('Unable to update guest managers', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n return this.getGuest(userId)\n }\n }\n\n async deleteUserOrGuest(userId: number, userLogin: string, deleteUserDto: DeleteUserDto): Promise<void> {\n try {\n if (await this.adminQueries.deleteUser(userId, userLogin)) {\n this.logger.log(`${this.deleteUserOrGuest.name} - *${userLogin}* (${userId}) was deleted`)\n } else {\n this.logger.error(`${this.deleteUserOrGuest.name} - *${userLogin}* (${userId}) was not deleted : not found`)\n }\n if (deleteUserDto.deleteSpace) {\n await this.deleteUserSpace(userLogin, deleteUserDto.isGuest)\n }\n } catch (e) {\n this.logger.error(`${this.deleteUserOrGuest.name} - unable to delete *${userLogin}* (${userId}) : ${e}`)\n throw new HttpException('Unable to delete user', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n\n async deleteUserOrGuestFromAdmin(userId: number, deleteUserDto: DeleteUserDto): Promise<void> {\n const userToDelete: UserModel = this.checkUser(await this.adminQueries.usersQueries.from(userId))\n if (userToDelete.isGuest !== deleteUserDto.isGuest) {\n throw new HttpException('User mismatch', HttpStatus.BAD_REQUEST)\n }\n await this.deleteUserOrGuest(userToDelete.id, userToDelete.login, {\n deleteSpace: deleteUserDto.isGuest ? true : deleteUserDto.deleteSpace,\n isGuest: deleteUserDto.isGuest\n } satisfies DeleteUserDto)\n }\n\n listGuests(): Promise<AdminUser[]> {\n return this.adminQueries.usersQueries.listGuests(null, null, true)\n }\n\n createGuest(user: UserModel, createGuestDto: CreateUserDto): Promise<GuestUser> {\n if (!createGuestDto.managers.length) {\n createGuestDto.managers.push(user.id)\n }\n return this.createUserOrGuest(createGuestDto, USER_ROLE.GUEST, true)\n }\n\n updateGuest(guestId: number, updateGuestDto: UpdateUserDto): Promise<GuestUser> {\n if (!Object.keys(updateGuestDto).length) {\n throw new HttpException('No changes to update', HttpStatus.BAD_REQUEST)\n }\n if (updateGuestDto.managers && !updateGuestDto.managers.length) {\n throw new HttpException('Guest must have at least one manager', HttpStatus.BAD_REQUEST)\n }\n return this.updateUserOrGuest(guestId, updateGuestDto, USER_ROLE.GUEST)\n }\n\n async browseGroups(name?: string, type: GROUP_TYPE = GROUP_TYPE.USER): Promise<GroupBrowse> {\n if (name) {\n const group: Pick<Group, 'id' | 'name' | 'type'> = await this.adminQueries.groupFromName(name)\n if (!group) {\n throw new HttpException('Group not found', HttpStatus.NOT_FOUND)\n }\n return { parentGroup: group, members: await this.adminQueries.browseGroupMembers(group.id, type) }\n }\n return { parentGroup: undefined, members: await this.adminQueries.browseRootGroupMembers(type) }\n }\n\n async getGroup(groupId: number): Promise<AdminGroup> {\n const group = await this.adminQueries.groupFromId(groupId)\n if (!group) {\n throw new HttpException('Group not found', HttpStatus.NOT_FOUND)\n }\n return group\n }\n\n async createGroup(createGroupDto: CreateOrUpdateGroupDto): Promise<AdminGroup> {\n if (!createGroupDto.name) {\n this.logger.error(`${this.createGroup.name} - missing group name : ${JSON.stringify(createGroupDto)}`)\n throw new HttpException('Group name is missing', HttpStatus.BAD_REQUEST)\n }\n await this.checkGroupNameExists(createGroupDto.name)\n try {\n const groupId: number = await this.adminQueries.createGroup(createGroupDto)\n this.logger.log(`${this.createGroup.name} - group (${groupId}) was created : ${JSON.stringify(createGroupDto)}`)\n return this.adminQueries.groupFromId(groupId)\n } catch (e) {\n this.logger.error(`${this.createGroup.name} - group was not created : ${JSON.stringify(createGroupDto)} : ${e}`)\n throw new HttpException('Unable to create group', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n\n async updateGroup(groupId: number, updateGroupDto: CreateOrUpdateGroupDto): Promise<AdminGroup> {\n if (updateGroupDto.name) {\n await this.checkGroupNameExists(updateGroupDto.name)\n }\n if (!(await this.adminQueries.updateGroup(groupId, updateGroupDto))) {\n throw new HttpException('Unable to update group', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n return this.adminQueries.groupFromId(groupId)\n }\n\n async deleteGroup(groupId: number): Promise<void> {\n if (await this.adminQueries.deleteGroup(groupId)) {\n this.logger.log(`${this.deleteGroup.name} - group (${groupId}) was deleted`)\n } else {\n this.logger.warn(`${this.deleteGroup.name} - group (${groupId}) does not exist`)\n throw new HttpException('Unable to delete group', HttpStatus.BAD_REQUEST)\n }\n }\n\n async addUsersToGroup(groupId: number, userIds: number[]): Promise<void> {\n const group: AdminGroup = await this.adminQueries.groupFromId(groupId)\n if (!group) {\n throw new HttpException('Group not found', HttpStatus.NOT_FOUND)\n }\n try {\n await this.adminQueries.addUsersToGroup(groupId, userIds, group.type === GROUP_TYPE.USER ? USER_ROLE.USER : undefined)\n } catch (e) {\n throw new HttpException(e.message, HttpStatus.BAD_REQUEST)\n }\n }\n\n async updateUserFromGroup(groupId: number, userId: number, updateUserFromGroupDto: UpdateUserFromGroupDto): Promise<void> {\n try {\n await this.adminQueries.updateUserFromGroup(groupId, userId, updateUserFromGroupDto.role)\n } catch (e) {\n throw new HttpException(e.message, HttpStatus.BAD_REQUEST)\n }\n }\n\n async removeUserFromGroup(groupId: number, userId: number): Promise<void> {\n try {\n await this.adminQueries.removeUserFromGroup(groupId, userId)\n } catch (e) {\n throw new HttpException(e.message, HttpStatus.BAD_REQUEST)\n }\n }\n\n searchMembers(searchMembersDto: SearchMembersDto): Promise<Member[]> {\n return this.adminQueries.usersQueries.searchUsersOrGroups(searchMembersDto)\n }\n\n async impersonateUser(admin: UserModel, userId: number, res: FastifyReply): Promise<LoginResponseDto> {\n if (admin.id === userId) {\n throw new HttpException('You are already logged in', HttpStatus.BAD_REQUEST)\n }\n const user: UserModel = this.checkUser(await this.adminQueries.usersQueries.from(userId))\n user.impersonatedFromId = admin.id\n user.impersonatedClientId = admin.clientId\n return this.authManager.setCookies(user, res)\n }\n\n async logoutImpersonateUser(user: UserModel, res: FastifyReply): Promise<LoginResponseDto> {\n if (!user.impersonatedFromId) {\n throw new HttpException('You are not allowed to do this action', HttpStatus.FORBIDDEN)\n }\n const admin: UserModel = this.checkUser(await this.adminQueries.usersQueries.from(user.impersonatedFromId))\n if (!admin.isAdmin) {\n throw new HttpException('You are not allowed to do this action', HttpStatus.FORBIDDEN)\n }\n admin.clientId = user.impersonatedClientId\n return this.authManager.setCookies(admin, res)\n }\n\n async deleteUserSpace(userLogin: string, isGuest = false): Promise<void> {\n const userSpace: string = UserModel.getHomePath(userLogin, isGuest)\n try {\n if (await isPathExists(userSpace)) {\n await removeFiles(userSpace)\n this.logger.log(`${this.deleteUserSpace.name} - user space *${userLogin}* was deleted`)\n } else {\n this.logger.warn(`${this.deleteUserSpace.name} - user space *${userLogin}* does not exist : ${userSpace}`)\n }\n } catch (e) {\n this.logger.warn(`${this.deleteUserSpace.name} - user space *${userLogin}* (${userSpace}) was not deleted : ${e}`)\n throw new HttpException('Unable to delete user space', HttpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n\n checkUser(user: User | AdminUser | GuestUser, checkOnly: true): void\n checkUser(user: User | AdminUser | GuestUser, checkOnly?: false): UserModel\n checkUser(user: User | AdminUser | GuestUser, checkOnly = false): UserModel | void {\n if (!user) {\n throw new HttpException('User not found', HttpStatus.NOT_FOUND)\n }\n if (!checkOnly) {\n return new UserModel(user, true)\n }\n }\n\n private async renameUserSpace(oldLogin: string, newLogin: string): Promise<boolean> {\n const currentUserSpace: string = UserModel.getHomePath(oldLogin)\n if (!(await isPathExists(currentUserSpace))) {\n this.logger.warn(`${this.renameUserSpace.name} - user space *${oldLogin}* does not exist : ${currentUserSpace}`)\n return false\n }\n const newUserSpace: string = UserModel.getHomePath(newLogin)\n if (await isPathExists(newUserSpace)) {\n this.logger.warn(`${this.renameUserSpace.name} - user space *${newLogin}* already exists : ${newUserSpace}`)\n return false\n }\n try {\n await moveFiles(currentUserSpace, newUserSpace)\n return true\n } catch (e) {\n // try to restore\n await moveFiles(newUserSpace, currentUserSpace, true)\n this.logger.error(`${this.renameUserSpace.name} - unable to rename user space from *${currentUserSpace}* to *${newUserSpace}* : ${e}`)\n return false\n }\n }\n\n private async checkGroupNameExists(groupName: string): Promise<void> {\n if (await this.adminQueries.usersQueries.checkGroupNameExists(groupName)) {\n throw new HttpException('Name already used', HttpStatus.BAD_REQUEST)\n }\n }\n\n private async loginOrEmailAlreadyUsed(login: string, email: string) {\n const exists = await this.adminQueries.usersQueries.checkUserExists(login, email)\n if (exists) {\n throw new HttpException(`${exists.login === login ? 'Login' : 'Email'} already used`, HttpStatus.BAD_REQUEST)\n }\n }\n}\n"],"names":["AdminUsersManager","listUsers","adminQueries","getUser","userId","user","checkUser","getGuest","guestId","usersQueries","listGuests","createUserOrGuest","createUserDto","userRole","USER_ROLE","USER","asAdmin","loginOrEmailAlreadyUsed","login","email","password","hashPassword","UserModel","id","role","logger","log","name","JSON","stringify","anonymizePassword","clearWhiteListCaches","makePaths","e","error","HttpException","HttpStatus","INTERNAL_SERVER_ERROR","updateUserOrGuest","updateUserDto","updateUser","updateUserGroups","add","delete","updateGuestManagers","k","v","Object","entries","checkUserExists","FORBIDDEN","renameUserSpace","isActive","passwordAttempts","currentGroups","groups","length","map","g","filter","indexOf","GUEST","currentManagers","managers","m","keys","forceRole","undefined","deleteUserOrGuest","userLogin","deleteUserDto","deleteUser","deleteSpace","deleteUserSpace","isGuest","deleteUserOrGuestFromAdmin","userToDelete","from","BAD_REQUEST","createGuest","createGuestDto","push","updateGuest","updateGuestDto","browseGroups","type","GROUP_TYPE","group","groupFromName","NOT_FOUND","parentGroup","members","browseGroupMembers","browseRootGroupMembers","getGroup","groupId","groupFromId","createGroup","createGroupDto","checkGroupNameExists","updateGroup","updateGroupDto","deleteGroup","warn","addUsersToGroup","userIds","message","updateUserFromGroup","updateUserFromGroupDto","removeUserFromGroup","searchMembers","searchMembersDto","searchUsersOrGroups","impersonateUser","admin","res","impersonatedFromId","impersonatedClientId","clientId","authManager","setCookies","logoutImpersonateUser","isAdmin","userSpace","getHomePath","isPathExists","removeFiles","checkOnly","oldLogin","newLogin","currentUserSpace","newUserSpace","moveFiles","groupName","exists","Logger"],"mappings":"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"}
@@ -74,7 +74,8 @@ describe(_adminusersmanagerservice.AdminUsersManager.name, ()=>{
74
74
  compareUserPassword: jest.fn(),
75
75
  checkGroupNameExists: jest.fn(),
76
76
  checkUserExists: jest.fn(),
77
- searchUsersOrGroups: jest.fn()
77
+ searchUsersOrGroups: jest.fn(),
78
+ clearWhiteListCaches: jest.fn()
78
79
  },
79
80
  updateUserGroups: jest.fn(),
80
81
  updateGuestManagers: jest.fn(),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/users/services/admin-users-manager.service.spec.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpException } from '@nestjs/common'\nimport { Test, TestingModule } from '@nestjs/testing'\nimport { AuthManager } from '../../../authentication/services/auth-manager.service'\nimport { GROUP_TYPE } from '../constants/group'\nimport { USER_GROUP_ROLE, USER_ROLE } from '../constants/user'\nimport type { CreateOrUpdateGroupDto } from '../dto/create-or-update-group.dto'\nimport type { CreateUserDto, UpdateUserDto, UpdateUserFromGroupDto } from '../dto/create-or-update-user.dto'\nimport type { DeleteUserDto } from '../dto/delete-user.dto'\nimport type { SearchMembersDto } from '../dto/search-members.dto'\nimport { UserModel } from '../models/user.model'\nimport { AdminUsersManager } from './admin-users-manager.service'\nimport { AdminUsersQueries } from './admin-users-queries.service'\n\n// mock file utils used by the service (delete/rename user space)\njest.mock('../../files/utils/files', () => ({\n isPathExists: jest.fn(),\n moveFiles: jest.fn(),\n removeFiles: jest.fn()\n}))\n\n// mock hash/anonymize utilities (preserve other module exports)\njest.mock('../../../common/functions', () => {\n const actual = jest.requireActual('../../../common/functions')\n return {\n ...actual,\n hashPassword: jest.fn(async (pwd: string) => `hashed:${pwd}`),\n anonymizePassword: jest.fn((dto: any) => ({ ...dto, password: '***' }))\n }\n})\n\n// Alias FS mocks (avoid repetitions)\nconst fs = jest.requireMock('../../files/utils/files') as { isPathExists: jest.Mock; moveFiles: jest.Mock; removeFiles: jest.Mock }\n\n// Helper utilities\nconst expectHttp = async (p: Promise<any>) => expect(p).rejects.toBeInstanceOf(HttpException)\nconst spyMakePaths = () => jest.spyOn(UserModel.prototype, 'makePaths').mockResolvedValueOnce(undefined)\n\ndescribe(AdminUsersManager.name, () => {\n let service: AdminUsersManager\n\n // deep mocks\n let authManagerMock: { setCookies: jest.Mock }\n let adminQueriesMock: {\n listUsers: jest.Mock\n usersQueries: {\n listGuests: jest.Mock\n from: jest.Mock\n createUserOrGuest: jest.Mock\n updateUserOrGuest: jest.Mock\n deleteUser: jest.Mock\n compareUserPassword: jest.Mock\n checkGroupNameExists: jest.Mock\n checkUserExists: jest.Mock\n searchUsersOrGroups: jest.Mock\n }\n updateUserGroups: jest.Mock\n updateGuestManagers: jest.Mock\n deleteUser: jest.Mock\n groupFromName: jest.Mock\n browseGroupMembers: jest.Mock\n browseRootGroupMembers: jest.Mock\n groupFromId: jest.Mock\n createGroup: jest.Mock\n updateGroup: jest.Mock\n deleteGroup: jest.Mock\n addUsersToGroup: jest.Mock\n updateUserFromGroup: jest.Mock\n removeUserFromGroup: jest.Mock\n }\n\n const setUser = (u: any) => adminQueriesMock.listUsers.mockResolvedValueOnce(u)\n const setGuest = (g: any) => adminQueriesMock.usersQueries.listGuests.mockResolvedValueOnce(g)\n\n const baseUser = {\n id: 10,\n login: 'john',\n email: 'john@example.com',\n isActive: true,\n role: USER_ROLE.USER,\n groups: [{ id: 1 }, { id: 3 }]\n } as any\n\n beforeAll(async () => {\n authManagerMock = { setCookies: jest.fn() }\n\n adminQueriesMock = {\n listUsers: jest.fn(),\n usersQueries: {\n listGuests: jest.fn(),\n from: jest.fn(),\n createUserOrGuest: jest.fn(),\n updateUserOrGuest: jest.fn(),\n deleteUser: jest.fn(),\n compareUserPassword: jest.fn(),\n checkGroupNameExists: jest.fn(),\n checkUserExists: jest.fn(),\n searchUsersOrGroups: jest.fn()\n },\n updateUserGroups: jest.fn(),\n updateGuestManagers: jest.fn(),\n deleteUser: jest.fn(),\n groupFromName: jest.fn(),\n browseGroupMembers: jest.fn(),\n browseRootGroupMembers: jest.fn(),\n groupFromId: jest.fn(),\n createGroup: jest.fn(),\n updateGroup: jest.fn(),\n deleteGroup: jest.fn(),\n addUsersToGroup: jest.fn(),\n updateUserFromGroup: jest.fn(),\n removeUserFromGroup: jest.fn()\n }\n\n const module: TestingModule = await Test.createTestingModule({\n providers: [AdminUsersManager, { provide: AuthManager, useValue: authManagerMock }, { provide: AdminUsersQueries, useValue: adminQueriesMock }]\n }).compile()\n\n module.useLogger(['fatal'])\n service = module.get<AdminUsersManager>(AdminUsersManager)\n })\n\n beforeEach(() => {\n jest.clearAllMocks()\n })\n\n it('should be defined', () => {\n expect(service).toBeDefined()\n })\n\n describe('getUser / getGuest', () => {\n it('user ok + not found + guest ok', async () => {\n setUser(baseUser)\n expect(await service.getUser(10)).toEqual(baseUser)\n expect(adminQueriesMock.listUsers).toHaveBeenCalledWith(10)\n\n setUser(null)\n await expectHttp(service.getUser(999))\n\n const guest = { id: 22, login: 'guest', email: 'g@x', managers: [], role: USER_ROLE.GUEST }\n setGuest(guest as any)\n expect(await service.getGuest(22)).toEqual(guest)\n expect(adminQueriesMock.usersQueries.listGuests).toHaveBeenCalledWith(22, 0, true)\n })\n })\n\n describe('createUserOrGuest', () => {\n it.each([\n { role: USER_ROLE.USER, asAdmin: false, id: 101, exp: 'UserModel' },\n { role: USER_ROLE.GUEST, asAdmin: true, id: 202, exp: 'AdminGuest' },\n { role: USER_ROLE.USER, asAdmin: true, id: 707, exp: 'AdminUser' },\n { role: USER_ROLE.GUEST, asAdmin: false, id: 808, exp: 'UserModel' }\n ])('creation matrix ($role / asAdmin=$asAdmin)', async ({ role, asAdmin, id, exp }) => {\n const dto: CreateUserDto = { login: 'alice', email: 'a@x', password: 'pwd', managers: role === USER_ROLE.GUEST ? [1] : [] } as any\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n adminQueriesMock.usersQueries.createUserOrGuest.mockResolvedValueOnce(id)\n spyMakePaths()\n\n if (exp === 'AdminUser') setUser({ id, login: 'alice', role })\n if (exp === 'AdminGuest') setGuest({ id, login: 'alice', role } as any)\n\n const res = await (service as any).createUserOrGuest(dto, role, asAdmin)\n\n if (exp === 'UserModel') {\n expect(res).toBeInstanceOf(UserModel)\n expect((res as any).id).toBe(id)\n } else if (exp === 'AdminUser') {\n expect(adminQueriesMock.listUsers).toHaveBeenCalledWith(id)\n } else {\n expect(adminQueriesMock.usersQueries.listGuests).toHaveBeenCalledWith(id, 0, true)\n }\n expect(adminQueriesMock.usersQueries.createUserOrGuest).toHaveBeenCalledWith(\n expect.objectContaining({ login: 'alice', email: 'a@x', password: 'hashed:pwd' }),\n role\n )\n })\n\n it('creation errors: duplication and DB error', async () => {\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce({ login: 'dup', email: 'dup@x' })\n await expectHttp(service.createUserOrGuest({ login: 'dup', email: 'dup@x', password: 'p', managers: [] } as any, USER_ROLE.USER, false))\n\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n adminQueriesMock.usersQueries.createUserOrGuest.mockRejectedValueOnce(new Error('db fail'))\n await expectHttp(service.createUserOrGuest({ login: 'bob', email: 'b@x', password: 'p', managers: [] } as any, USER_ROLE.USER, false))\n })\n })\n\n describe('updateUserOrGuest - USER branch', () => {\n it('full update + FS rename + groups diff', async () => {\n const current = { ...baseUser, groups: [{ id: 1 }, { id: 3 }] }\n setUser(current)\n const updated = { ...current, login: 'johnny', email: 'j@new' }\n setUser(updated)\n\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n fs.isPathExists.mockResolvedValueOnce(true)\n fs.isPathExists.mockResolvedValueOnce(false)\n fs.moveFiles.mockResolvedValueOnce(undefined)\n adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true)\n adminQueriesMock.updateUserGroups.mockResolvedValueOnce(undefined)\n\n const dto: UpdateUserDto = { login: 'johnny', email: 'j@new', isActive: true, password: 'newpwd', groups: [3, 5] }\n const res = await service.updateUserOrGuest(current.id, dto)\n\n expect(adminQueriesMock.usersQueries.updateUserOrGuest).toHaveBeenCalledWith(\n current.id,\n expect.objectContaining({ login: 'johnny', email: 'j@new', isActive: true, passwordAttempts: 0, password: 'hashed:newpwd' }),\n undefined\n )\n expect(adminQueriesMock.updateUserGroups).toHaveBeenCalledWith(current.id, { add: [5], delete: [1] })\n expect(res).toEqual(updated)\n })\n\n it('login/email conflict', async () => {\n const current = { ...baseUser }\n setUser(current)\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(true)\n await expectHttp(service.updateUserOrGuest(current.id, { login: 'taken' } as any))\n\n setUser(current)\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(true)\n await expectHttp(service.updateUserOrGuest(current.id, { email: 'dup@x' } as any))\n expect(adminQueriesMock.usersQueries.updateUserOrGuest).not.toHaveBeenCalled()\n })\n\n it('renameUserSpace impossible (new space exists)', async () => {\n const current = { ...baseUser }\n setUser(current)\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n fs.isPathExists.mockResolvedValueOnce(true) // current\n fs.isPathExists.mockResolvedValueOnce(true) // new already exists\n fs.moveFiles.mockResolvedValue(undefined)\n await expectHttp(service.updateUserOrGuest(current.id, { login: 'new' } as any))\n })\n\n it('DB update false => INTERNAL_SERVER_ERROR', async () => {\n const current = { ...baseUser }\n setUser(current)\n adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(false)\n await expectHttp(service.updateUserOrGuest(current.id, { email: 'e@x' } as any))\n })\n\n it('updateUserGroups fails', async () => {\n const current = { ...baseUser, groups: [{ id: 1 }] }\n setUser(current)\n adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true)\n adminQueriesMock.updateUserGroups.mockRejectedValueOnce(new Error('group error'))\n await expectHttp(service.updateUserOrGuest(current.id, { groups: [2] } as any))\n })\n\n it('no change when login or email unchanged', async () => {\n const current = { ...baseUser }\n setUser(current)\n setUser(current)\n expect(await service.updateUserOrGuest(current.id, { login: current.login } as any)).toEqual(current)\n expect(adminQueriesMock.usersQueries.checkUserExists).not.toHaveBeenCalled()\n\n setUser(current)\n setUser(current)\n expect(await service.updateUserOrGuest(current.id, { email: current.email } as any)).toEqual(current)\n expect(adminQueriesMock.usersQueries.updateUserOrGuest).not.toHaveBeenCalled()\n })\n\n it('default branch (unknown field)', async () => {\n const current = { ...baseUser }\n setUser(current)\n adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true)\n const updated = { ...current, language: 'fr' } as any\n setUser(updated)\n\n const res = await service.updateUserOrGuest(current.id, { language: 'fr' } as any)\n expect(adminQueriesMock.usersQueries.updateUserOrGuest).toHaveBeenCalledWith(current.id, expect.objectContaining({ language: 'fr' }), undefined)\n expect(res).toEqual(updated)\n })\n })\n\n describe('updateUserOrGuest - GUEST branch', () => {\n it('update guest + managers diff', async () => {\n const guest = { id: 33, login: 'g', email: 'g@x', managers: [{ id: 2 }, { id: 7 }], role: USER_ROLE.GUEST }\n setGuest(guest as any)\n const updatedGuest = { ...guest, email: 'new@x' }\n setGuest(updatedGuest as any)\n\n adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true)\n adminQueriesMock.updateGuestManagers.mockResolvedValueOnce(undefined)\n\n const res = await service.updateUserOrGuest(guest.id, { email: 'new@x', managers: [7, 9] } as UpdateUserDto, USER_ROLE.GUEST)\n expect(adminQueriesMock.usersQueries.updateUserOrGuest).toHaveBeenCalledWith(guest.id, { email: 'new@x' }, USER_ROLE.GUEST)\n expect(adminQueriesMock.updateGuestManagers).toHaveBeenCalledWith(guest.id, { add: [9], delete: [2] })\n expect(res).toEqual(updatedGuest)\n })\n\n it('validations updateGuest', async () => {\n expect(() => service.updateGuest(1, {} as any)).toThrow(/no changes to update/i)\n expect(() => service.updateGuest(1, { managers: [] } as any)).toThrow(/guest must have at least one manager/i)\n })\n\n it('updateGuestManagers échoue', async () => {\n const guest = { id: 33, login: 'g', email: 'g@x', managers: [{ id: 2 }], role: USER_ROLE.GUEST }\n setGuest(guest as any)\n adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true)\n adminQueriesMock.updateGuestManagers.mockRejectedValueOnce(new Error('mgr error'))\n await expectHttp(service.updateUserOrGuest(guest.id, { managers: [3] } as any, USER_ROLE.GUEST))\n })\n })\n\n describe('deleteUserOrGuest / deleteGuest', () => {\n it('delete user + optional space and errors', async () => {\n adminQueriesMock.deleteUser.mockResolvedValueOnce(true)\n fs.isPathExists.mockResolvedValueOnce(true)\n fs.removeFiles.mockResolvedValueOnce(undefined)\n await expect(service.deleteUserOrGuest(10, 'john', { deleteSpace: true, isGuest: false })).resolves.toBeUndefined()\n expect(adminQueriesMock.deleteUser).toHaveBeenCalledWith(10, 'john')\n expect(fs.isPathExists).toHaveBeenCalled()\n expect(fs.removeFiles).toHaveBeenCalled()\n\n adminQueriesMock.deleteUser.mockRejectedValueOnce(new Error('db crash'))\n await expectHttp(service.deleteUserOrGuest(10, 'john', { deleteSpace: false } as any))\n })\n })\n\n describe('deleteUserFromAdmin', () => {\n it('admin password incorrect / deletion ok', async () => {\n adminQueriesMock.usersQueries.compareUserPassword.mockResolvedValueOnce(false)\n await expectHttp(service.deleteUserOrGuestFromAdmin(10, { isGuest: false } as DeleteUserDto))\n\n adminQueriesMock.usersQueries.compareUserPassword.mockResolvedValueOnce(true)\n adminQueriesMock.usersQueries.from.mockResolvedValueOnce({ id: 10, login: 'to-del' } as any)\n adminQueriesMock.deleteUser.mockResolvedValueOnce(true)\n await service.deleteUserOrGuestFromAdmin(10, { isGuest: false, deleteSpace: true } as DeleteUserDto)\n expect(adminQueriesMock.deleteUser).toHaveBeenCalledWith(10, 'to-del')\n })\n })\n\n describe('groups', () => {\n it('browseGroups with/without name + NOT_FOUND', async () => {\n adminQueriesMock.groupFromName.mockResolvedValueOnce({ id: 5, name: 'dev', type: GROUP_TYPE.USER })\n adminQueriesMock.browseGroupMembers.mockResolvedValueOnce([{ id: 1 }, { id: 2 }])\n const withName = await service.browseGroups('dev', GROUP_TYPE.USER)\n expect(withName.parentGroup).toEqual({ id: 5, name: 'dev', type: GROUP_TYPE.USER })\n expect(withName.members).toHaveLength(2)\n\n adminQueriesMock.browseRootGroupMembers.mockResolvedValueOnce([{ id: 3 }])\n const root = await service.browseGroups(undefined, GROUP_TYPE.USER)\n expect(root.parentGroup).toBeUndefined()\n expect(root.members).toEqual([{ id: 3 }])\n\n adminQueriesMock.groupFromName.mockResolvedValueOnce(null)\n await expectHttp(service.browseGroups('unknown'))\n })\n\n it('getGroup OK / NOT_FOUND', async () => {\n adminQueriesMock.groupFromId.mockResolvedValueOnce({ id: 9 })\n expect(await service.getGroup(9)).toEqual({ id: 9 })\n adminQueriesMock.groupFromId.mockResolvedValueOnce(null)\n await expectHttp(service.getGroup(999))\n })\n\n it('createGroup OK + validations + creation error', async () => {\n const dto: CreateOrUpdateGroupDto = { name: 'team', type: GROUP_TYPE.USER } as any\n adminQueriesMock.usersQueries.checkGroupNameExists.mockResolvedValueOnce(false)\n adminQueriesMock.createGroup.mockResolvedValueOnce(123)\n adminQueriesMock.groupFromId.mockResolvedValueOnce({ id: 123, name: 'team' })\n expect(await service.createGroup(dto)).toEqual({ id: 123, name: 'team' })\n\n await expectHttp(service.createGroup({} as any))\n\n adminQueriesMock.usersQueries.checkGroupNameExists.mockResolvedValueOnce(true)\n await expectHttp(service.createGroup(dto))\n expect(adminQueriesMock.createGroup).toHaveBeenCalledTimes(1) // only the first one OK\n\n adminQueriesMock.usersQueries.checkGroupNameExists.mockResolvedValueOnce(false)\n adminQueriesMock.createGroup.mockRejectedValueOnce(new Error('db err'))\n await expectHttp(service.createGroup(dto))\n })\n\n it('updateGroup success / failure', async () => {\n adminQueriesMock.usersQueries.checkGroupNameExists.mockResolvedValueOnce(false)\n adminQueriesMock.updateGroup.mockResolvedValueOnce(true)\n adminQueriesMock.groupFromId.mockResolvedValueOnce({ id: 5, name: 'new' })\n expect(await service.updateGroup(5, { name: 'new' } as any)).toEqual({ id: 5, name: 'new' })\n\n adminQueriesMock.updateGroup.mockResolvedValueOnce(false)\n await expectHttp(service.updateGroup(5, {} as any))\n })\n\n it('deleteGroup success / fail', async () => {\n adminQueriesMock.deleteGroup.mockResolvedValueOnce(true)\n await expect(service.deleteGroup(5)).resolves.toBeUndefined()\n adminQueriesMock.deleteGroup.mockResolvedValueOnce(false)\n await expectHttp(service.deleteGroup(6))\n })\n\n it('addUsersToGroup: NOT_FOUND + error', async () => {\n adminQueriesMock.groupFromId.mockResolvedValueOnce(null)\n await expectHttp(service.addUsersToGroup(1, [2, 3]))\n\n adminQueriesMock.groupFromId.mockResolvedValueOnce({ id: 1, type: GROUP_TYPE.USER })\n adminQueriesMock.addUsersToGroup.mockRejectedValueOnce(new Error('bad users'))\n await expectHttp(service.addUsersToGroup(1, [2]))\n })\n\n it('updateUserFromGroup / removeUserFromGroup BAD_REQUEST errors', async () => {\n adminQueriesMock.updateUserFromGroup.mockRejectedValueOnce(new Error('bad role'))\n await expectHttp(service.updateUserFromGroup(1, 2, { role: USER_GROUP_ROLE.MEMBER } as UpdateUserFromGroupDto))\n\n adminQueriesMock.removeUserFromGroup.mockRejectedValueOnce(new Error('not member'))\n await expectHttp(service.removeUserFromGroup(1, 2))\n })\n })\n\n describe('searchMembers', () => {\n it('forwards to usersQueries.searchUsersOrGroups', async () => {\n const dto = { search: 'jo' } as SearchMembersDto\n adminQueriesMock.usersQueries.searchUsersOrGroups.mockResolvedValueOnce([{ id: 1 }])\n expect(await service.searchMembers(dto)).toEqual([{ id: 1 }])\n expect(adminQueriesMock.usersQueries.searchUsersOrGroups).toHaveBeenCalledWith(dto)\n })\n })\n\n describe('impersonation', () => {\n const res: any = {}\n it('self / bad password / ok + logout (guard + non-admin + admin)', async () => {\n const admin = new UserModel({ id: 5 } as any, true)\n await expectHttp(service.impersonateUser(admin, 5, res))\n\n adminQueriesMock.usersQueries.compareUserPassword.mockResolvedValueOnce(false)\n await expectHttp(service.impersonateUser(admin, 6, res))\n\n const admin2 = new UserModel({ id: 5, clientId: 'c1' } as any, true)\n adminQueriesMock.usersQueries.compareUserPassword.mockResolvedValueOnce(true)\n adminQueriesMock.usersQueries.from.mockResolvedValueOnce({ id: 6, login: 'user' } as any)\n authManagerMock.setCookies.mockResolvedValueOnce({ accessToken: 't' })\n expect(await service.impersonateUser(admin2, 6, res)).toEqual({ accessToken: 't' })\n\n const notImpersonated = new UserModel({ id: 1 } as any, true)\n await expectHttp(service.logoutImpersonateUser(notImpersonated, res))\n\n const impersonated = new UserModel({ id: 2, impersonatedFromId: 9, impersonatedClientId: 'X' } as any, true)\n adminQueriesMock.usersQueries.from.mockResolvedValueOnce({ id: 9, role: USER_ROLE.USER } as any)\n await expectHttp(service.logoutImpersonateUser(impersonated, res))\n\n adminQueriesMock.usersQueries.from.mockResolvedValueOnce({ id: 9, role: USER_ROLE.ADMINISTRATOR } as any)\n authManagerMock.setCookies.mockResolvedValueOnce({ accessToken: 'admin' })\n expect(await service.logoutImpersonateUser(impersonated, res)).toEqual({ accessToken: 'admin' })\n })\n })\n\n describe('listing', () => {\n it('forwards listUsers and listGuests', async () => {\n const users = [{ id: 1 }]\n adminQueriesMock.listUsers.mockResolvedValueOnce(users as any)\n expect(await service.listUsers()).toEqual(users)\n expect(adminQueriesMock.listUsers).toHaveBeenCalledWith()\n\n const guests = [{ id: 2 }]\n adminQueriesMock.usersQueries.listGuests.mockResolvedValueOnce(guests as any)\n expect(await service.listGuests()).toEqual(guests)\n expect(adminQueriesMock.usersQueries.listGuests).toHaveBeenCalledWith(null, null, true)\n })\n })\n\n describe('createGuest', () => {\n it('adds the creator as default manager and returns admin guest', async () => {\n const creator = new UserModel({ id: 88 } as any, true)\n const dto: CreateUserDto = { login: 'gg', email: 'g@x', password: 'pwd', managers: [] } as any\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n adminQueriesMock.usersQueries.createUserOrGuest.mockResolvedValueOnce(505)\n spyMakePaths()\n const expectedGuest = { id: 505, login: 'gg', role: USER_ROLE.GUEST }\n setGuest(expectedGuest as any)\n\n expect(await service.createGuest(creator, dto)).toEqual(expectedGuest)\n expect(adminQueriesMock.usersQueries.createUserOrGuest).toHaveBeenCalledWith(\n expect.objectContaining({ login: 'gg', email: 'g@x', managers: [88] }),\n USER_ROLE.GUEST\n )\n })\n })\n\n describe('updateGuest wrapper', () => {\n it('updateGuest() -> success', async () => {\n const guest = { id: 33, login: 'g', email: 'g@x', managers: [{ id: 2 }], role: USER_ROLE.GUEST }\n const updatedGuest = { ...guest, email: 'new@x' }\n setGuest(guest as any)\n adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true)\n setGuest(updatedGuest as any)\n expect(await service.updateGuest(guest.id, { email: 'new@x' } as any)).toEqual(updatedGuest)\n })\n })\n\n describe('deleteUserSpace', () => {\n it('space not existing / removeFiles failure', async () => {\n fs.isPathExists.mockResolvedValueOnce(false)\n await expect(service.deleteUserSpace('nobody')).resolves.toBeUndefined()\n\n fs.isPathExists.mockResolvedValueOnce(true)\n fs.removeFiles.mockRejectedValueOnce(new Error('fs error'))\n await expectHttp(service.deleteUserSpace('bob'))\n })\n })\n\n describe('renameUserSpace error handling', () => {\n it('moveFiles throws then restore', async () => {\n const current = { ...baseUser }\n setUser(current)\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n fs.isPathExists.mockResolvedValueOnce(true)\n fs.isPathExists.mockResolvedValueOnce(false)\n fs.moveFiles.mockRejectedValueOnce(new Error('io error'))\n fs.moveFiles.mockResolvedValueOnce(undefined)\n await expectHttp(service.updateUserOrGuest(current.id, { login: 'new-login' } as any))\n expect(fs.moveFiles).toHaveBeenCalledTimes(2)\n })\n\n it('current space missing -> early return', async () => {\n const current = { ...baseUser }\n setUser(current)\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n fs.isPathExists.mockResolvedValueOnce(false)\n await expectHttp(service.updateUserOrGuest(current.id, { login: 'new-login' } as any))\n expect(fs.moveFiles).not.toHaveBeenCalled()\n })\n })\n})\n"],"names":["jest","mock","isPathExists","fn","moveFiles","removeFiles","actual","requireActual","hashPassword","pwd","anonymizePassword","dto","password","fs","requireMock","expectHttp","p","expect","rejects","toBeInstanceOf","HttpException","spyMakePaths","spyOn","UserModel","prototype","mockResolvedValueOnce","undefined","describe","AdminUsersManager","name","service","authManagerMock","adminQueriesMock","setUser","u","listUsers","setGuest","g","usersQueries","listGuests","baseUser","id","login","email","isActive","role","USER_ROLE","USER","groups","beforeAll","setCookies","from","createUserOrGuest","updateUserOrGuest","deleteUser","compareUserPassword","checkGroupNameExists","checkUserExists","searchUsersOrGroups","updateUserGroups","updateGuestManagers","groupFromName","browseGroupMembers","browseRootGroupMembers","groupFromId","createGroup","updateGroup","deleteGroup","addUsersToGroup","updateUserFromGroup","removeUserFromGroup","module","Test","createTestingModule","providers","provide","AuthManager","useValue","AdminUsersQueries","compile","useLogger","get","beforeEach","clearAllMocks","it","toBeDefined","getUser","toEqual","toHaveBeenCalledWith","guest","managers","GUEST","getGuest","each","asAdmin","exp","res","toBe","objectContaining","mockRejectedValueOnce","Error","current","updated","passwordAttempts","add","delete","not","toHaveBeenCalled","mockResolvedValue","language","updatedGuest","updateGuest","toThrow","deleteUserOrGuest","deleteSpace","isGuest","resolves","toBeUndefined","deleteUserOrGuestFromAdmin","type","GROUP_TYPE","withName","browseGroups","parentGroup","members","toHaveLength","root","getGroup","toHaveBeenCalledTimes","USER_GROUP_ROLE","MEMBER","search","searchMembers","admin","impersonateUser","admin2","clientId","accessToken","notImpersonated","logoutImpersonateUser","impersonated","impersonatedFromId","impersonatedClientId","ADMINISTRATOR","users","guests","creator","expectedGuest","createGuest","deleteUserSpace"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/users/services/admin-users-manager.service.spec.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpException } from '@nestjs/common'\nimport { Test, TestingModule } from '@nestjs/testing'\nimport { AuthManager } from '../../../authentication/services/auth-manager.service'\nimport { GROUP_TYPE } from '../constants/group'\nimport { USER_GROUP_ROLE, USER_ROLE } from '../constants/user'\nimport type { CreateOrUpdateGroupDto } from '../dto/create-or-update-group.dto'\nimport type { CreateUserDto, UpdateUserDto, UpdateUserFromGroupDto } from '../dto/create-or-update-user.dto'\nimport type { DeleteUserDto } from '../dto/delete-user.dto'\nimport type { SearchMembersDto } from '../dto/search-members.dto'\nimport { UserModel } from '../models/user.model'\nimport { AdminUsersManager } from './admin-users-manager.service'\nimport { AdminUsersQueries } from './admin-users-queries.service'\n\n// mock file utils used by the service (delete/rename user space)\njest.mock('../../files/utils/files', () => ({\n isPathExists: jest.fn(),\n moveFiles: jest.fn(),\n removeFiles: jest.fn()\n}))\n\n// mock hash/anonymize utilities (preserve other module exports)\njest.mock('../../../common/functions', () => {\n const actual = jest.requireActual('../../../common/functions')\n return {\n ...actual,\n hashPassword: jest.fn(async (pwd: string) => `hashed:${pwd}`),\n anonymizePassword: jest.fn((dto: any) => ({ ...dto, password: '***' }))\n }\n})\n\n// Alias FS mocks (avoid repetitions)\nconst fs = jest.requireMock('../../files/utils/files') as { isPathExists: jest.Mock; moveFiles: jest.Mock; removeFiles: jest.Mock }\n\n// Helper utilities\nconst expectHttp = async (p: Promise<any>) => expect(p).rejects.toBeInstanceOf(HttpException)\nconst spyMakePaths = () => jest.spyOn(UserModel.prototype, 'makePaths').mockResolvedValueOnce(undefined)\n\ndescribe(AdminUsersManager.name, () => {\n let service: AdminUsersManager\n\n // deep mocks\n let authManagerMock: { setCookies: jest.Mock }\n let adminQueriesMock: {\n listUsers: jest.Mock\n usersQueries: {\n listGuests: jest.Mock\n from: jest.Mock\n createUserOrGuest: jest.Mock\n updateUserOrGuest: jest.Mock\n deleteUser: jest.Mock\n compareUserPassword: jest.Mock\n checkGroupNameExists: jest.Mock\n checkUserExists: jest.Mock\n searchUsersOrGroups: jest.Mock\n clearWhiteListCaches: jest.Mock\n }\n updateUserGroups: jest.Mock\n updateGuestManagers: jest.Mock\n deleteUser: jest.Mock\n groupFromName: jest.Mock\n browseGroupMembers: jest.Mock\n browseRootGroupMembers: jest.Mock\n groupFromId: jest.Mock\n createGroup: jest.Mock\n updateGroup: jest.Mock\n deleteGroup: jest.Mock\n addUsersToGroup: jest.Mock\n updateUserFromGroup: jest.Mock\n removeUserFromGroup: jest.Mock\n }\n\n const setUser = (u: any) => adminQueriesMock.listUsers.mockResolvedValueOnce(u)\n const setGuest = (g: any) => adminQueriesMock.usersQueries.listGuests.mockResolvedValueOnce(g)\n\n const baseUser = {\n id: 10,\n login: 'john',\n email: 'john@example.com',\n isActive: true,\n role: USER_ROLE.USER,\n groups: [{ id: 1 }, { id: 3 }]\n } as any\n\n beforeAll(async () => {\n authManagerMock = { setCookies: jest.fn() }\n\n adminQueriesMock = {\n listUsers: jest.fn(),\n usersQueries: {\n listGuests: jest.fn(),\n from: jest.fn(),\n createUserOrGuest: jest.fn(),\n updateUserOrGuest: jest.fn(),\n deleteUser: jest.fn(),\n compareUserPassword: jest.fn(),\n checkGroupNameExists: jest.fn(),\n checkUserExists: jest.fn(),\n searchUsersOrGroups: jest.fn(),\n clearWhiteListCaches: jest.fn()\n },\n updateUserGroups: jest.fn(),\n updateGuestManagers: jest.fn(),\n deleteUser: jest.fn(),\n groupFromName: jest.fn(),\n browseGroupMembers: jest.fn(),\n browseRootGroupMembers: jest.fn(),\n groupFromId: jest.fn(),\n createGroup: jest.fn(),\n updateGroup: jest.fn(),\n deleteGroup: jest.fn(),\n addUsersToGroup: jest.fn(),\n updateUserFromGroup: jest.fn(),\n removeUserFromGroup: jest.fn()\n }\n\n const module: TestingModule = await Test.createTestingModule({\n providers: [AdminUsersManager, { provide: AuthManager, useValue: authManagerMock }, { provide: AdminUsersQueries, useValue: adminQueriesMock }]\n }).compile()\n\n module.useLogger(['fatal'])\n service = module.get<AdminUsersManager>(AdminUsersManager)\n })\n\n beforeEach(() => {\n jest.clearAllMocks()\n })\n\n it('should be defined', () => {\n expect(service).toBeDefined()\n })\n\n describe('getUser / getGuest', () => {\n it('user ok + not found + guest ok', async () => {\n setUser(baseUser)\n expect(await service.getUser(10)).toEqual(baseUser)\n expect(adminQueriesMock.listUsers).toHaveBeenCalledWith(10)\n\n setUser(null)\n await expectHttp(service.getUser(999))\n\n const guest = { id: 22, login: 'guest', email: 'g@x', managers: [], role: USER_ROLE.GUEST }\n setGuest(guest as any)\n expect(await service.getGuest(22)).toEqual(guest)\n expect(adminQueriesMock.usersQueries.listGuests).toHaveBeenCalledWith(22, 0, true)\n })\n })\n\n describe('createUserOrGuest', () => {\n it.each([\n { role: USER_ROLE.USER, asAdmin: false, id: 101, exp: 'UserModel' },\n { role: USER_ROLE.GUEST, asAdmin: true, id: 202, exp: 'AdminGuest' },\n { role: USER_ROLE.USER, asAdmin: true, id: 707, exp: 'AdminUser' },\n { role: USER_ROLE.GUEST, asAdmin: false, id: 808, exp: 'UserModel' }\n ])('creation matrix ($role / asAdmin=$asAdmin)', async ({ role, asAdmin, id, exp }) => {\n const dto: CreateUserDto = { login: 'alice', email: 'a@x', password: 'pwd', managers: role === USER_ROLE.GUEST ? [1] : [] } as any\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n adminQueriesMock.usersQueries.createUserOrGuest.mockResolvedValueOnce(id)\n spyMakePaths()\n\n if (exp === 'AdminUser') setUser({ id, login: 'alice', role })\n if (exp === 'AdminGuest') setGuest({ id, login: 'alice', role } as any)\n\n const res = await (service as any).createUserOrGuest(dto, role, asAdmin)\n\n if (exp === 'UserModel') {\n expect(res).toBeInstanceOf(UserModel)\n expect((res as any).id).toBe(id)\n } else if (exp === 'AdminUser') {\n expect(adminQueriesMock.listUsers).toHaveBeenCalledWith(id)\n } else {\n expect(adminQueriesMock.usersQueries.listGuests).toHaveBeenCalledWith(id, 0, true)\n }\n expect(adminQueriesMock.usersQueries.createUserOrGuest).toHaveBeenCalledWith(\n expect.objectContaining({ login: 'alice', email: 'a@x', password: 'hashed:pwd' }),\n role\n )\n })\n\n it('creation errors: duplication and DB error', async () => {\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce({ login: 'dup', email: 'dup@x' })\n await expectHttp(service.createUserOrGuest({ login: 'dup', email: 'dup@x', password: 'p', managers: [] } as any, USER_ROLE.USER, false))\n\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n adminQueriesMock.usersQueries.createUserOrGuest.mockRejectedValueOnce(new Error('db fail'))\n await expectHttp(service.createUserOrGuest({ login: 'bob', email: 'b@x', password: 'p', managers: [] } as any, USER_ROLE.USER, false))\n })\n })\n\n describe('updateUserOrGuest - USER branch', () => {\n it('full update + FS rename + groups diff', async () => {\n const current = { ...baseUser, groups: [{ id: 1 }, { id: 3 }] }\n setUser(current)\n const updated = { ...current, login: 'johnny', email: 'j@new' }\n setUser(updated)\n\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n fs.isPathExists.mockResolvedValueOnce(true)\n fs.isPathExists.mockResolvedValueOnce(false)\n fs.moveFiles.mockResolvedValueOnce(undefined)\n adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true)\n adminQueriesMock.updateUserGroups.mockResolvedValueOnce(undefined)\n\n const dto: UpdateUserDto = { login: 'johnny', email: 'j@new', isActive: true, password: 'newpwd', groups: [3, 5] }\n const res = await service.updateUserOrGuest(current.id, dto)\n\n expect(adminQueriesMock.usersQueries.updateUserOrGuest).toHaveBeenCalledWith(\n current.id,\n expect.objectContaining({ login: 'johnny', email: 'j@new', isActive: true, passwordAttempts: 0, password: 'hashed:newpwd' }),\n undefined\n )\n expect(adminQueriesMock.updateUserGroups).toHaveBeenCalledWith(current.id, { add: [5], delete: [1] })\n expect(res).toEqual(updated)\n })\n\n it('login/email conflict', async () => {\n const current = { ...baseUser }\n setUser(current)\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(true)\n await expectHttp(service.updateUserOrGuest(current.id, { login: 'taken' } as any))\n\n setUser(current)\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(true)\n await expectHttp(service.updateUserOrGuest(current.id, { email: 'dup@x' } as any))\n expect(adminQueriesMock.usersQueries.updateUserOrGuest).not.toHaveBeenCalled()\n })\n\n it('renameUserSpace impossible (new space exists)', async () => {\n const current = { ...baseUser }\n setUser(current)\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n fs.isPathExists.mockResolvedValueOnce(true) // current\n fs.isPathExists.mockResolvedValueOnce(true) // new already exists\n fs.moveFiles.mockResolvedValue(undefined)\n await expectHttp(service.updateUserOrGuest(current.id, { login: 'new' } as any))\n })\n\n it('DB update false => INTERNAL_SERVER_ERROR', async () => {\n const current = { ...baseUser }\n setUser(current)\n adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(false)\n await expectHttp(service.updateUserOrGuest(current.id, { email: 'e@x' } as any))\n })\n\n it('updateUserGroups fails', async () => {\n const current = { ...baseUser, groups: [{ id: 1 }] }\n setUser(current)\n adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true)\n adminQueriesMock.updateUserGroups.mockRejectedValueOnce(new Error('group error'))\n await expectHttp(service.updateUserOrGuest(current.id, { groups: [2] } as any))\n })\n\n it('no change when login or email unchanged', async () => {\n const current = { ...baseUser }\n setUser(current)\n setUser(current)\n expect(await service.updateUserOrGuest(current.id, { login: current.login } as any)).toEqual(current)\n expect(adminQueriesMock.usersQueries.checkUserExists).not.toHaveBeenCalled()\n\n setUser(current)\n setUser(current)\n expect(await service.updateUserOrGuest(current.id, { email: current.email } as any)).toEqual(current)\n expect(adminQueriesMock.usersQueries.updateUserOrGuest).not.toHaveBeenCalled()\n })\n\n it('default branch (unknown field)', async () => {\n const current = { ...baseUser }\n setUser(current)\n adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true)\n const updated = { ...current, language: 'fr' } as any\n setUser(updated)\n\n const res = await service.updateUserOrGuest(current.id, { language: 'fr' } as any)\n expect(adminQueriesMock.usersQueries.updateUserOrGuest).toHaveBeenCalledWith(current.id, expect.objectContaining({ language: 'fr' }), undefined)\n expect(res).toEqual(updated)\n })\n })\n\n describe('updateUserOrGuest - GUEST branch', () => {\n it('update guest + managers diff', async () => {\n const guest = { id: 33, login: 'g', email: 'g@x', managers: [{ id: 2 }, { id: 7 }], role: USER_ROLE.GUEST }\n setGuest(guest as any)\n const updatedGuest = { ...guest, email: 'new@x' }\n setGuest(updatedGuest as any)\n\n adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true)\n adminQueriesMock.updateGuestManagers.mockResolvedValueOnce(undefined)\n\n const res = await service.updateUserOrGuest(guest.id, { email: 'new@x', managers: [7, 9] } as UpdateUserDto, USER_ROLE.GUEST)\n expect(adminQueriesMock.usersQueries.updateUserOrGuest).toHaveBeenCalledWith(guest.id, { email: 'new@x' }, USER_ROLE.GUEST)\n expect(adminQueriesMock.updateGuestManagers).toHaveBeenCalledWith(guest.id, { add: [9], delete: [2] })\n expect(res).toEqual(updatedGuest)\n })\n\n it('validations updateGuest', async () => {\n expect(() => service.updateGuest(1, {} as any)).toThrow(/no changes to update/i)\n expect(() => service.updateGuest(1, { managers: [] } as any)).toThrow(/guest must have at least one manager/i)\n })\n\n it('updateGuestManagers échoue', async () => {\n const guest = { id: 33, login: 'g', email: 'g@x', managers: [{ id: 2 }], role: USER_ROLE.GUEST }\n setGuest(guest as any)\n adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true)\n adminQueriesMock.updateGuestManagers.mockRejectedValueOnce(new Error('mgr error'))\n await expectHttp(service.updateUserOrGuest(guest.id, { managers: [3] } as any, USER_ROLE.GUEST))\n })\n })\n\n describe('deleteUserOrGuest / deleteGuest', () => {\n it('delete user + optional space and errors', async () => {\n adminQueriesMock.deleteUser.mockResolvedValueOnce(true)\n fs.isPathExists.mockResolvedValueOnce(true)\n fs.removeFiles.mockResolvedValueOnce(undefined)\n await expect(service.deleteUserOrGuest(10, 'john', { deleteSpace: true, isGuest: false })).resolves.toBeUndefined()\n expect(adminQueriesMock.deleteUser).toHaveBeenCalledWith(10, 'john')\n expect(fs.isPathExists).toHaveBeenCalled()\n expect(fs.removeFiles).toHaveBeenCalled()\n\n adminQueriesMock.deleteUser.mockRejectedValueOnce(new Error('db crash'))\n await expectHttp(service.deleteUserOrGuest(10, 'john', { deleteSpace: false } as any))\n })\n })\n\n describe('deleteUserFromAdmin', () => {\n it('admin password incorrect / deletion ok', async () => {\n adminQueriesMock.usersQueries.compareUserPassword.mockResolvedValueOnce(false)\n await expectHttp(service.deleteUserOrGuestFromAdmin(10, { isGuest: false } as DeleteUserDto))\n\n adminQueriesMock.usersQueries.compareUserPassword.mockResolvedValueOnce(true)\n adminQueriesMock.usersQueries.from.mockResolvedValueOnce({ id: 10, login: 'to-del' } as any)\n adminQueriesMock.deleteUser.mockResolvedValueOnce(true)\n await service.deleteUserOrGuestFromAdmin(10, { isGuest: false, deleteSpace: true } as DeleteUserDto)\n expect(adminQueriesMock.deleteUser).toHaveBeenCalledWith(10, 'to-del')\n })\n })\n\n describe('groups', () => {\n it('browseGroups with/without name + NOT_FOUND', async () => {\n adminQueriesMock.groupFromName.mockResolvedValueOnce({ id: 5, name: 'dev', type: GROUP_TYPE.USER })\n adminQueriesMock.browseGroupMembers.mockResolvedValueOnce([{ id: 1 }, { id: 2 }])\n const withName = await service.browseGroups('dev', GROUP_TYPE.USER)\n expect(withName.parentGroup).toEqual({ id: 5, name: 'dev', type: GROUP_TYPE.USER })\n expect(withName.members).toHaveLength(2)\n\n adminQueriesMock.browseRootGroupMembers.mockResolvedValueOnce([{ id: 3 }])\n const root = await service.browseGroups(undefined, GROUP_TYPE.USER)\n expect(root.parentGroup).toBeUndefined()\n expect(root.members).toEqual([{ id: 3 }])\n\n adminQueriesMock.groupFromName.mockResolvedValueOnce(null)\n await expectHttp(service.browseGroups('unknown'))\n })\n\n it('getGroup OK / NOT_FOUND', async () => {\n adminQueriesMock.groupFromId.mockResolvedValueOnce({ id: 9 })\n expect(await service.getGroup(9)).toEqual({ id: 9 })\n adminQueriesMock.groupFromId.mockResolvedValueOnce(null)\n await expectHttp(service.getGroup(999))\n })\n\n it('createGroup OK + validations + creation error', async () => {\n const dto: CreateOrUpdateGroupDto = { name: 'team', type: GROUP_TYPE.USER } as any\n adminQueriesMock.usersQueries.checkGroupNameExists.mockResolvedValueOnce(false)\n adminQueriesMock.createGroup.mockResolvedValueOnce(123)\n adminQueriesMock.groupFromId.mockResolvedValueOnce({ id: 123, name: 'team' })\n expect(await service.createGroup(dto)).toEqual({ id: 123, name: 'team' })\n\n await expectHttp(service.createGroup({} as any))\n\n adminQueriesMock.usersQueries.checkGroupNameExists.mockResolvedValueOnce(true)\n await expectHttp(service.createGroup(dto))\n expect(adminQueriesMock.createGroup).toHaveBeenCalledTimes(1) // only the first one OK\n\n adminQueriesMock.usersQueries.checkGroupNameExists.mockResolvedValueOnce(false)\n adminQueriesMock.createGroup.mockRejectedValueOnce(new Error('db err'))\n await expectHttp(service.createGroup(dto))\n })\n\n it('updateGroup success / failure', async () => {\n adminQueriesMock.usersQueries.checkGroupNameExists.mockResolvedValueOnce(false)\n adminQueriesMock.updateGroup.mockResolvedValueOnce(true)\n adminQueriesMock.groupFromId.mockResolvedValueOnce({ id: 5, name: 'new' })\n expect(await service.updateGroup(5, { name: 'new' } as any)).toEqual({ id: 5, name: 'new' })\n\n adminQueriesMock.updateGroup.mockResolvedValueOnce(false)\n await expectHttp(service.updateGroup(5, {} as any))\n })\n\n it('deleteGroup success / fail', async () => {\n adminQueriesMock.deleteGroup.mockResolvedValueOnce(true)\n await expect(service.deleteGroup(5)).resolves.toBeUndefined()\n adminQueriesMock.deleteGroup.mockResolvedValueOnce(false)\n await expectHttp(service.deleteGroup(6))\n })\n\n it('addUsersToGroup: NOT_FOUND + error', async () => {\n adminQueriesMock.groupFromId.mockResolvedValueOnce(null)\n await expectHttp(service.addUsersToGroup(1, [2, 3]))\n\n adminQueriesMock.groupFromId.mockResolvedValueOnce({ id: 1, type: GROUP_TYPE.USER })\n adminQueriesMock.addUsersToGroup.mockRejectedValueOnce(new Error('bad users'))\n await expectHttp(service.addUsersToGroup(1, [2]))\n })\n\n it('updateUserFromGroup / removeUserFromGroup BAD_REQUEST errors', async () => {\n adminQueriesMock.updateUserFromGroup.mockRejectedValueOnce(new Error('bad role'))\n await expectHttp(service.updateUserFromGroup(1, 2, { role: USER_GROUP_ROLE.MEMBER } as UpdateUserFromGroupDto))\n\n adminQueriesMock.removeUserFromGroup.mockRejectedValueOnce(new Error('not member'))\n await expectHttp(service.removeUserFromGroup(1, 2))\n })\n })\n\n describe('searchMembers', () => {\n it('forwards to usersQueries.searchUsersOrGroups', async () => {\n const dto = { search: 'jo' } as SearchMembersDto\n adminQueriesMock.usersQueries.searchUsersOrGroups.mockResolvedValueOnce([{ id: 1 }])\n expect(await service.searchMembers(dto)).toEqual([{ id: 1 }])\n expect(adminQueriesMock.usersQueries.searchUsersOrGroups).toHaveBeenCalledWith(dto)\n })\n })\n\n describe('impersonation', () => {\n const res: any = {}\n it('self / bad password / ok + logout (guard + non-admin + admin)', async () => {\n const admin = new UserModel({ id: 5 } as any, true)\n await expectHttp(service.impersonateUser(admin, 5, res))\n\n adminQueriesMock.usersQueries.compareUserPassword.mockResolvedValueOnce(false)\n await expectHttp(service.impersonateUser(admin, 6, res))\n\n const admin2 = new UserModel({ id: 5, clientId: 'c1' } as any, true)\n adminQueriesMock.usersQueries.compareUserPassword.mockResolvedValueOnce(true)\n adminQueriesMock.usersQueries.from.mockResolvedValueOnce({ id: 6, login: 'user' } as any)\n authManagerMock.setCookies.mockResolvedValueOnce({ accessToken: 't' })\n expect(await service.impersonateUser(admin2, 6, res)).toEqual({ accessToken: 't' })\n\n const notImpersonated = new UserModel({ id: 1 } as any, true)\n await expectHttp(service.logoutImpersonateUser(notImpersonated, res))\n\n const impersonated = new UserModel({ id: 2, impersonatedFromId: 9, impersonatedClientId: 'X' } as any, true)\n adminQueriesMock.usersQueries.from.mockResolvedValueOnce({ id: 9, role: USER_ROLE.USER } as any)\n await expectHttp(service.logoutImpersonateUser(impersonated, res))\n\n adminQueriesMock.usersQueries.from.mockResolvedValueOnce({ id: 9, role: USER_ROLE.ADMINISTRATOR } as any)\n authManagerMock.setCookies.mockResolvedValueOnce({ accessToken: 'admin' })\n expect(await service.logoutImpersonateUser(impersonated, res)).toEqual({ accessToken: 'admin' })\n })\n })\n\n describe('listing', () => {\n it('forwards listUsers and listGuests', async () => {\n const users = [{ id: 1 }]\n adminQueriesMock.listUsers.mockResolvedValueOnce(users as any)\n expect(await service.listUsers()).toEqual(users)\n expect(adminQueriesMock.listUsers).toHaveBeenCalledWith()\n\n const guests = [{ id: 2 }]\n adminQueriesMock.usersQueries.listGuests.mockResolvedValueOnce(guests as any)\n expect(await service.listGuests()).toEqual(guests)\n expect(adminQueriesMock.usersQueries.listGuests).toHaveBeenCalledWith(null, null, true)\n })\n })\n\n describe('createGuest', () => {\n it('adds the creator as default manager and returns admin guest', async () => {\n const creator = new UserModel({ id: 88 } as any, true)\n const dto: CreateUserDto = { login: 'gg', email: 'g@x', password: 'pwd', managers: [] } as any\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n adminQueriesMock.usersQueries.createUserOrGuest.mockResolvedValueOnce(505)\n spyMakePaths()\n const expectedGuest = { id: 505, login: 'gg', role: USER_ROLE.GUEST }\n setGuest(expectedGuest as any)\n\n expect(await service.createGuest(creator, dto)).toEqual(expectedGuest)\n expect(adminQueriesMock.usersQueries.createUserOrGuest).toHaveBeenCalledWith(\n expect.objectContaining({ login: 'gg', email: 'g@x', managers: [88] }),\n USER_ROLE.GUEST\n )\n })\n })\n\n describe('updateGuest wrapper', () => {\n it('updateGuest() -> success', async () => {\n const guest = { id: 33, login: 'g', email: 'g@x', managers: [{ id: 2 }], role: USER_ROLE.GUEST }\n const updatedGuest = { ...guest, email: 'new@x' }\n setGuest(guest as any)\n adminQueriesMock.usersQueries.updateUserOrGuest.mockResolvedValueOnce(true)\n setGuest(updatedGuest as any)\n expect(await service.updateGuest(guest.id, { email: 'new@x' } as any)).toEqual(updatedGuest)\n })\n })\n\n describe('deleteUserSpace', () => {\n it('space not existing / removeFiles failure', async () => {\n fs.isPathExists.mockResolvedValueOnce(false)\n await expect(service.deleteUserSpace('nobody')).resolves.toBeUndefined()\n\n fs.isPathExists.mockResolvedValueOnce(true)\n fs.removeFiles.mockRejectedValueOnce(new Error('fs error'))\n await expectHttp(service.deleteUserSpace('bob'))\n })\n })\n\n describe('renameUserSpace error handling', () => {\n it('moveFiles throws then restore', async () => {\n const current = { ...baseUser }\n setUser(current)\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n fs.isPathExists.mockResolvedValueOnce(true)\n fs.isPathExists.mockResolvedValueOnce(false)\n fs.moveFiles.mockRejectedValueOnce(new Error('io error'))\n fs.moveFiles.mockResolvedValueOnce(undefined)\n await expectHttp(service.updateUserOrGuest(current.id, { login: 'new-login' } as any))\n expect(fs.moveFiles).toHaveBeenCalledTimes(2)\n })\n\n it('current space missing -> early return', async () => {\n const current = { ...baseUser }\n setUser(current)\n adminQueriesMock.usersQueries.checkUserExists.mockResolvedValueOnce(false)\n fs.isPathExists.mockResolvedValueOnce(false)\n await expectHttp(service.updateUserOrGuest(current.id, { login: 'new-login' } as any))\n expect(fs.moveFiles).not.toHaveBeenCalled()\n })\n })\n})\n"],"names":["jest","mock","isPathExists","fn","moveFiles","removeFiles","actual","requireActual","hashPassword","pwd","anonymizePassword","dto","password","fs","requireMock","expectHttp","p","expect","rejects","toBeInstanceOf","HttpException","spyMakePaths","spyOn","UserModel","prototype","mockResolvedValueOnce","undefined","describe","AdminUsersManager","name","service","authManagerMock","adminQueriesMock","setUser","u","listUsers","setGuest","g","usersQueries","listGuests","baseUser","id","login","email","isActive","role","USER_ROLE","USER","groups","beforeAll","setCookies","from","createUserOrGuest","updateUserOrGuest","deleteUser","compareUserPassword","checkGroupNameExists","checkUserExists","searchUsersOrGroups","clearWhiteListCaches","updateUserGroups","updateGuestManagers","groupFromName","browseGroupMembers","browseRootGroupMembers","groupFromId","createGroup","updateGroup","deleteGroup","addUsersToGroup","updateUserFromGroup","removeUserFromGroup","module","Test","createTestingModule","providers","provide","AuthManager","useValue","AdminUsersQueries","compile","useLogger","get","beforeEach","clearAllMocks","it","toBeDefined","getUser","toEqual","toHaveBeenCalledWith","guest","managers","GUEST","getGuest","each","asAdmin","exp","res","toBe","objectContaining","mockRejectedValueOnce","Error","current","updated","passwordAttempts","add","delete","not","toHaveBeenCalled","mockResolvedValue","language","updatedGuest","updateGuest","toThrow","deleteUserOrGuest","deleteSpace","isGuest","resolves","toBeUndefined","deleteUserOrGuestFromAdmin","type","GROUP_TYPE","withName","browseGroups","parentGroup","members","toHaveLength","root","getGroup","toHaveBeenCalledTimes","USER_GROUP_ROLE","MEMBER","search","searchMembers","admin","impersonateUser","admin2","clientId","accessToken","notImpersonated","logoutImpersonateUser","impersonated","impersonatedFromId","impersonatedClientId","ADMINISTRATOR","users","guests","creator","expectedGuest","createGuest","deleteUserSpace"],"mappings":"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"}
@@ -16,6 +16,7 @@ const _common = require("@nestjs/common");
16
16
  const _bcryptjs = /*#__PURE__*/ _interop_require_default(require("bcryptjs"));
17
17
  const _nodefs = require("node:fs");
18
18
  const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
19
+ const _nodestream = require("node:stream");
19
20
  const _promises = require("node:stream/promises");
20
21
  const _constants = require("../../../common/constants");
21
22
  const _functions = require("../../../common/functions");
@@ -121,7 +122,12 @@ let UsersManager = class UsersManager {
121
122
  }
122
123
  async updateNotification(user, userNotificationDto) {
123
124
  if (!await this.usersQueries.updateUserOrGuest(user.id, userNotificationDto)) {
124
- throw new _common.HttpException('Unable to update notification', _common.HttpStatus.INTERNAL_SERVER_ERROR);
125
+ throw new _common.HttpException('Unable to update notification preference', _common.HttpStatus.INTERNAL_SERVER_ERROR);
126
+ }
127
+ }
128
+ async updateStorageIndexing(user, userStorageIndexingDto) {
129
+ if (!await this.usersQueries.updateUserOrGuest(user.id, userStorageIndexingDto)) {
130
+ throw new _common.HttpException('Unable to update full-text search preference', _common.HttpStatus.INTERNAL_SERVER_ERROR);
125
131
  }
126
132
  }
127
133
  async updateAvatar(req) {
@@ -200,7 +206,7 @@ let UsersManager = class UsersManager {
200
206
  throw new _common.HttpException(`avatar not found`, _common.HttpStatus.NOT_FOUND);
201
207
  }
202
208
  const avatarFile = (0, _nodefs.createWriteStream)(avatarPath);
203
- const avatarStream = (0, _image.generateAvatar)(user.getInitials());
209
+ const avatarStream = _nodestream.Readable.from(await (0, _image.generateAvatar)(user.getInitials()));
204
210
  try {
205
211
  await (0, _promises.pipeline)(avatarStream, avatarFile);
206
212
  } catch (e) {