@sync-in/server 1.5.2 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (355) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +2 -1
  3. package/environment/environment.dist.min.yaml +1 -0
  4. package/environment/environment.dist.yaml +88 -30
  5. package/migrations/0002_sleepy_korath.sql +1 -0
  6. package/migrations/meta/0002_snapshot.json +2424 -0
  7. package/migrations/meta/_journal.json +7 -0
  8. package/package.json +14 -12
  9. package/server/app.bootstrap.js +1 -1
  10. package/server/app.bootstrap.js.map +1 -1
  11. package/server/applications/files/services/files-manager.service.js +1 -2
  12. package/server/applications/files/services/files-manager.service.js.map +1 -1
  13. package/server/applications/files/services/files-only-office-manager.service.js +5 -6
  14. package/server/applications/files/services/files-only-office-manager.service.js.map +1 -1
  15. package/server/applications/files/utils/files.js +6 -4
  16. package/server/applications/files/utils/files.js.map +1 -1
  17. package/server/applications/links/links.controller.js +2 -2
  18. package/server/applications/links/links.controller.js.map +1 -1
  19. package/server/applications/links/services/links-manager.service.js +2 -1
  20. package/server/applications/links/services/links-manager.service.js.map +1 -1
  21. package/server/applications/links/services/links-manager.service.spec.js +6 -3
  22. package/server/applications/links/services/links-manager.service.spec.js.map +1 -1
  23. package/server/applications/notifications/constants/notifications.js +9 -0
  24. package/server/applications/notifications/constants/notifications.js.map +1 -1
  25. package/server/applications/notifications/i18n/fr.js +10 -1
  26. package/server/applications/notifications/i18n/fr.js.map +1 -1
  27. package/server/applications/notifications/interfaces/notification-properties.interface.js.map +1 -1
  28. package/server/applications/notifications/mails/models.js +41 -3
  29. package/server/applications/notifications/mails/models.js.map +1 -1
  30. package/server/applications/notifications/mails/templates.js +1 -1
  31. package/server/applications/notifications/mails/templates.js.map +1 -1
  32. package/server/applications/notifications/schemas/notifications.schema.js +2 -1
  33. package/server/applications/notifications/schemas/notifications.schema.js.map +1 -1
  34. package/server/applications/notifications/services/notifications-manager.service.js +16 -13
  35. package/server/applications/notifications/services/notifications-manager.service.js.map +1 -1
  36. package/server/applications/notifications/services/notifications-manager.service.spec.js +9 -8
  37. package/server/applications/notifications/services/notifications-manager.service.spec.js.map +1 -1
  38. package/server/applications/notifications/services/notifications-queries.service.js +1 -1
  39. package/server/applications/notifications/services/notifications-queries.service.js.map +1 -1
  40. package/server/applications/shares/services/shares-manager.service.js +3 -2
  41. package/server/applications/shares/services/shares-manager.service.js.map +1 -1
  42. package/server/applications/sync/constants/auth.js +2 -2
  43. package/server/applications/sync/constants/auth.js.map +1 -1
  44. package/server/applications/sync/dtos/sync-client-registration.dto.js +5 -0
  45. package/server/applications/sync/dtos/sync-client-registration.dto.js.map +1 -1
  46. package/server/applications/sync/dtos/sync-operations.dto.js +1 -2
  47. package/server/applications/sync/dtos/sync-operations.dto.js.map +1 -1
  48. package/server/applications/sync/schemas/sync-clients.schema.js +2 -1
  49. package/server/applications/sync/schemas/sync-clients.schema.js.map +1 -1
  50. package/server/applications/sync/schemas/sync-paths.schema.js +2 -1
  51. package/server/applications/sync/schemas/sync-paths.schema.js.map +1 -1
  52. package/server/applications/sync/services/sync-clients-manager.service.js +28 -20
  53. package/server/applications/sync/services/sync-clients-manager.service.js.map +1 -1
  54. package/server/applications/sync/services/sync-clients-manager.service.spec.js +24 -18
  55. package/server/applications/sync/services/sync-clients-manager.service.spec.js.map +1 -1
  56. package/server/applications/sync/services/sync-queries.service.js +5 -5
  57. package/server/applications/sync/services/sync-queries.service.js.map +1 -1
  58. package/server/applications/users/admin-users.controller.js +48 -37
  59. package/server/applications/users/admin-users.controller.js.map +1 -1
  60. package/server/applications/users/admin-users.controller.spec.js +15 -0
  61. package/server/applications/users/admin-users.controller.spec.js.map +1 -1
  62. package/server/applications/users/constants/routes.js +5 -0
  63. package/server/applications/users/constants/routes.js.map +1 -1
  64. package/server/applications/users/constants/user.js +8 -0
  65. package/server/applications/users/constants/user.js.map +1 -1
  66. package/server/applications/users/dto/delete-user.dto.js +5 -23
  67. package/server/applications/users/dto/delete-user.dto.js.map +1 -1
  68. package/server/applications/users/dto/user-properties.dto.js +38 -3
  69. package/server/applications/users/dto/user-properties.dto.js.map +1 -1
  70. package/server/applications/users/interfaces/admin-user.interface.js.map +1 -1
  71. package/server/applications/users/interfaces/user-secrets.interface.js +10 -0
  72. package/server/applications/users/interfaces/user-secrets.interface.js.map +1 -0
  73. package/server/applications/users/models/user.model.js +84 -50
  74. package/server/applications/users/models/user.model.js.map +1 -1
  75. package/server/applications/users/schemas/user.interface.js.map +1 -1
  76. package/server/applications/users/schemas/users.schema.js +2 -0
  77. package/server/applications/users/schemas/users.schema.js.map +1 -1
  78. package/server/applications/users/services/admin-users-manager.service.js +7 -19
  79. package/server/applications/users/services/admin-users-manager.service.js.map +1 -1
  80. package/server/applications/users/services/admin-users-manager.service.spec.js +7 -26
  81. package/server/applications/users/services/admin-users-manager.service.spec.js.map +1 -1
  82. package/server/applications/users/services/admin-users-queries.service.js +1 -0
  83. package/server/applications/users/services/admin-users-queries.service.js.map +1 -1
  84. package/server/applications/users/services/users-manager.service.js +138 -28
  85. package/server/applications/users/services/users-manager.service.js.map +1 -1
  86. package/server/applications/users/services/users-manager.service.spec.js +11 -9
  87. package/server/applications/users/services/users-manager.service.spec.js.map +1 -1
  88. package/server/applications/users/services/users-queries.service.js +63 -57
  89. package/server/applications/users/services/users-queries.service.js.map +1 -1
  90. package/server/applications/users/users.controller.js +48 -1
  91. package/server/applications/users/users.controller.js.map +1 -1
  92. package/server/applications/users/users.controller.spec.js +8 -1
  93. package/server/applications/users/users.controller.spec.js.map +1 -1
  94. package/server/applications/users/users.e2e-spec.js +2 -1
  95. package/server/applications/users/users.e2e-spec.js.map +1 -1
  96. package/server/applications/users/utils/avatar.js +48 -0
  97. package/server/applications/users/utils/avatar.js.map +1 -0
  98. package/server/authentication/auth.config.js +89 -26
  99. package/server/authentication/auth.config.js.map +1 -1
  100. package/server/authentication/auth.controller.js +117 -9
  101. package/server/authentication/auth.controller.js.map +1 -1
  102. package/server/authentication/auth.controller.spec.js +16 -1
  103. package/server/authentication/auth.controller.spec.js.map +1 -1
  104. package/server/authentication/auth.e2e-spec.js +4 -3
  105. package/server/authentication/auth.e2e-spec.js.map +1 -1
  106. package/server/authentication/auth.module.js +4 -1
  107. package/server/authentication/auth.module.js.map +1 -1
  108. package/server/authentication/constants/auth-ldap.js +44 -0
  109. package/server/authentication/constants/auth-ldap.js.map +1 -0
  110. package/server/authentication/constants/auth.js +37 -4
  111. package/server/authentication/constants/auth.js.map +1 -1
  112. package/server/authentication/constants/routes.js +21 -0
  113. package/server/authentication/constants/routes.js.map +1 -1
  114. package/server/authentication/constants/scope.js +20 -0
  115. package/server/authentication/constants/scope.js.map +1 -0
  116. package/server/authentication/dto/login-response.dto.js +27 -4
  117. package/server/authentication/dto/login-response.dto.js.map +1 -1
  118. package/server/authentication/dto/token-response.dto.js +5 -0
  119. package/server/authentication/dto/token-response.dto.js.map +1 -1
  120. package/server/{applications/users/dto/user-password.dto.js → authentication/dto/two-fa-verify.dto.js} +27 -9
  121. package/server/authentication/dto/two-fa-verify.dto.js.map +1 -0
  122. package/server/authentication/guards/auth-basic.strategy.js +6 -5
  123. package/server/authentication/guards/auth-basic.strategy.js.map +1 -1
  124. package/server/authentication/guards/auth-token-access.strategy.js +3 -2
  125. package/server/authentication/guards/auth-token-access.strategy.js.map +1 -1
  126. package/server/authentication/guards/auth-token-refresh.strategy.js +3 -2
  127. package/server/authentication/guards/auth-token-refresh.strategy.js.map +1 -1
  128. package/server/authentication/guards/auth-two-fa-guard.js +81 -0
  129. package/server/authentication/guards/auth-two-fa-guard.js.map +1 -0
  130. package/server/authentication/interfaces/jwt-payload.interface.js +5 -0
  131. package/server/authentication/interfaces/jwt-payload.interface.js.map +1 -1
  132. package/server/authentication/interfaces/token.interface.js +2 -0
  133. package/server/authentication/interfaces/token.interface.js.map +1 -1
  134. package/server/authentication/interfaces/two-fa-setup.interface.js +10 -0
  135. package/server/authentication/interfaces/two-fa-setup.interface.js.map +1 -0
  136. package/server/authentication/models/auth-method.js.map +1 -1
  137. package/server/authentication/services/auth-manager.service.js +72 -49
  138. package/server/authentication/services/auth-manager.service.js.map +1 -1
  139. package/server/authentication/services/auth-methods/auth-method-database.service.js +3 -3
  140. package/server/authentication/services/auth-methods/auth-method-database.service.js.map +1 -1
  141. package/server/authentication/services/auth-methods/auth-method-database.service.spec.js +5 -0
  142. package/server/authentication/services/auth-methods/auth-method-database.service.spec.js.map +1 -1
  143. package/server/authentication/services/auth-methods/auth-method-ldap.service.js +151 -66
  144. package/server/authentication/services/auth-methods/auth-method-ldap.service.js.map +1 -1
  145. package/server/authentication/services/auth-methods/auth-method-ldap.service.spec.js +52 -50
  146. package/server/authentication/services/auth-methods/auth-method-ldap.service.spec.js.map +1 -1
  147. package/server/authentication/services/auth-methods/auth-method-two-fa.service.js +251 -0
  148. package/server/authentication/services/auth-methods/auth-method-two-fa.service.js.map +1 -0
  149. package/server/authentication/services/auth-methods/auth-method-two-fa.service.spec.js +41 -0
  150. package/server/authentication/services/auth-methods/auth-method-two-fa.service.spec.js.map +1 -0
  151. package/server/authentication/utils/crypt-secret.js +68 -0
  152. package/server/authentication/utils/crypt-secret.js.map +1 -0
  153. package/server/common/functions.js +18 -2
  154. package/server/common/functions.js.map +1 -1
  155. package/server/common/qrcode.js +34 -0
  156. package/server/common/qrcode.js.map +1 -0
  157. package/server/common/shared.js +18 -0
  158. package/server/common/shared.js.map +1 -1
  159. package/server/configuration/config.environment.js +23 -6
  160. package/server/configuration/config.environment.js.map +1 -1
  161. package/server/configuration/config.interfaces.js +10 -0
  162. package/server/configuration/config.interfaces.js.map +1 -0
  163. package/server/configuration/config.loader.js.map +1 -1
  164. package/server/configuration/config.validation.js +13 -13
  165. package/server/configuration/config.validation.js.map +1 -1
  166. package/server/infrastructure/cache/adapters/mysql-cache.adapter.js +6 -6
  167. package/server/infrastructure/cache/adapters/mysql-cache.adapter.js.map +1 -1
  168. package/server/infrastructure/cache/schemas/mysql-cache.schema.js +2 -1
  169. package/server/infrastructure/cache/schemas/mysql-cache.schema.js.map +1 -1
  170. package/server/infrastructure/cache/services/cache.service.js.map +1 -1
  171. package/server/infrastructure/database/columns.js +39 -0
  172. package/server/infrastructure/database/columns.js.map +1 -0
  173. package/server/infrastructure/database/database.config.js +0 -1
  174. package/server/infrastructure/database/database.config.js.map +1 -1
  175. package/server/infrastructure/mailer/interfaces/mail.interface.js.map +1 -1
  176. package/server/infrastructure/mailer/mailer.config.js +12 -0
  177. package/server/infrastructure/mailer/mailer.config.js.map +1 -1
  178. package/server/infrastructure/mailer/mailer.service.js +2 -1
  179. package/server/infrastructure/mailer/mailer.service.js.map +1 -1
  180. package/static/assets/mimes/text-x-c.svg +1 -0
  181. package/static/assets/pdfjs/build/pdf.mjs +2522 -914
  182. package/static/assets/pdfjs/build/pdf.mjs.map +1 -1
  183. package/static/assets/pdfjs/build/pdf.sandbox.mjs +2 -2
  184. package/static/assets/pdfjs/build/pdf.worker.mjs +1024 -566
  185. package/static/assets/pdfjs/build/pdf.worker.mjs.map +1 -1
  186. package/static/assets/pdfjs/version +1 -1
  187. package/static/assets/pdfjs/web/debugger.mjs +116 -37
  188. package/static/assets/pdfjs/web/images/comment-popup-editButton.svg +5 -0
  189. package/static/assets/pdfjs/web/locale/ach/viewer.ftl +0 -12
  190. package/static/assets/pdfjs/web/locale/af/viewer.ftl +0 -12
  191. package/static/assets/pdfjs/web/locale/an/viewer.ftl +0 -16
  192. package/static/assets/pdfjs/web/locale/ar/viewer.ftl +0 -32
  193. package/static/assets/pdfjs/web/locale/ast/viewer.ftl +0 -19
  194. package/static/assets/pdfjs/web/locale/az/viewer.ftl +0 -16
  195. package/static/assets/pdfjs/web/locale/be/viewer.ftl +0 -32
  196. package/static/assets/pdfjs/web/locale/bg/viewer.ftl +0 -32
  197. package/static/assets/pdfjs/web/locale/bn/viewer.ftl +0 -16
  198. package/static/assets/pdfjs/web/locale/bo/viewer.ftl +0 -12
  199. package/static/assets/pdfjs/web/locale/br/viewer.ftl +0 -22
  200. package/static/assets/pdfjs/web/locale/brx/viewer.ftl +0 -16
  201. package/static/assets/pdfjs/web/locale/bs/viewer.ftl +0 -32
  202. package/static/assets/pdfjs/web/locale/ca/viewer.ftl +12 -23
  203. package/static/assets/pdfjs/web/locale/cak/viewer.ftl +0 -23
  204. package/static/assets/pdfjs/web/locale/ckb/viewer.ftl +0 -16
  205. package/static/assets/pdfjs/web/locale/cs/viewer.ftl +0 -32
  206. package/static/assets/pdfjs/web/locale/cy/viewer.ftl +0 -32
  207. package/static/assets/pdfjs/web/locale/da/viewer.ftl +3 -35
  208. package/static/assets/pdfjs/web/locale/de/viewer.ftl +0 -32
  209. package/static/assets/pdfjs/web/locale/dsb/viewer.ftl +0 -32
  210. package/static/assets/pdfjs/web/locale/el/viewer.ftl +0 -32
  211. package/static/assets/pdfjs/web/locale/en-CA/viewer.ftl +0 -32
  212. package/static/assets/pdfjs/web/locale/en-GB/viewer.ftl +0 -32
  213. package/static/assets/pdfjs/web/locale/en-US/viewer.ftl +25 -13
  214. package/static/assets/pdfjs/web/locale/eo/viewer.ftl +0 -32
  215. package/static/assets/pdfjs/web/locale/es-AR/viewer.ftl +0 -32
  216. package/static/assets/pdfjs/web/locale/es-CL/viewer.ftl +0 -32
  217. package/static/assets/pdfjs/web/locale/es-ES/viewer.ftl +5 -32
  218. package/static/assets/pdfjs/web/locale/es-MX/viewer.ftl +0 -32
  219. package/static/assets/pdfjs/web/locale/et/viewer.ftl +0 -16
  220. package/static/assets/pdfjs/web/locale/eu/viewer.ftl +38 -32
  221. package/static/assets/pdfjs/web/locale/fa/viewer.ftl +0 -19
  222. package/static/assets/pdfjs/web/locale/ff/viewer.ftl +0 -12
  223. package/static/assets/pdfjs/web/locale/fi/viewer.ftl +0 -32
  224. package/static/assets/pdfjs/web/locale/fr/viewer.ftl +0 -32
  225. package/static/assets/pdfjs/web/locale/fur/viewer.ftl +0 -32
  226. package/static/assets/pdfjs/web/locale/fy-NL/viewer.ftl +0 -32
  227. package/static/assets/pdfjs/web/locale/ga-IE/viewer.ftl +0 -12
  228. package/static/assets/pdfjs/web/locale/gd/viewer.ftl +0 -23
  229. package/static/assets/pdfjs/web/locale/gl/viewer.ftl +0 -32
  230. package/static/assets/pdfjs/web/locale/gn/viewer.ftl +0 -32
  231. package/static/assets/pdfjs/web/locale/gu-IN/viewer.ftl +0 -12
  232. package/static/assets/pdfjs/web/locale/he/viewer.ftl +0 -32
  233. package/static/assets/pdfjs/web/locale/hi-IN/viewer.ftl +0 -16
  234. package/static/assets/pdfjs/web/locale/hr/viewer.ftl +0 -32
  235. package/static/assets/pdfjs/web/locale/hsb/viewer.ftl +0 -32
  236. package/static/assets/pdfjs/web/locale/hu/viewer.ftl +0 -32
  237. package/static/assets/pdfjs/web/locale/hy-AM/viewer.ftl +372 -16
  238. package/static/assets/pdfjs/web/locale/hye/viewer.ftl +0 -16
  239. package/static/assets/pdfjs/web/locale/ia/viewer.ftl +0 -32
  240. package/static/assets/pdfjs/web/locale/id/viewer.ftl +38 -32
  241. package/static/assets/pdfjs/web/locale/is/viewer.ftl +27 -32
  242. package/static/assets/pdfjs/web/locale/it/viewer.ftl +0 -33
  243. package/static/assets/pdfjs/web/locale/ja/viewer.ftl +31 -33
  244. package/static/assets/pdfjs/web/locale/ka/viewer.ftl +0 -32
  245. package/static/assets/pdfjs/web/locale/kab/viewer.ftl +0 -32
  246. package/static/assets/pdfjs/web/locale/kk/viewer.ftl +31 -32
  247. package/static/assets/pdfjs/web/locale/km/viewer.ftl +0 -12
  248. package/static/assets/pdfjs/web/locale/kn/viewer.ftl +0 -12
  249. package/static/assets/pdfjs/web/locale/ko/viewer.ftl +0 -32
  250. package/static/assets/pdfjs/web/locale/lij/viewer.ftl +0 -12
  251. package/static/assets/pdfjs/web/locale/lo/viewer.ftl +0 -23
  252. package/static/assets/pdfjs/web/locale/lt/viewer.ftl +0 -16
  253. package/static/assets/pdfjs/web/locale/ltg/viewer.ftl +0 -12
  254. package/static/assets/pdfjs/web/locale/lv/viewer.ftl +0 -12
  255. package/static/assets/pdfjs/web/locale/meh/viewer.ftl +0 -14
  256. package/static/assets/pdfjs/web/locale/mk/viewer.ftl +0 -19
  257. package/static/assets/pdfjs/web/locale/ml/viewer.ftl +0 -31
  258. package/static/assets/pdfjs/web/locale/mr/viewer.ftl +0 -16
  259. package/static/assets/pdfjs/web/locale/ms/viewer.ftl +0 -12
  260. package/static/assets/pdfjs/web/locale/my/viewer.ftl +0 -12
  261. package/static/assets/pdfjs/web/locale/nb-NO/viewer.ftl +0 -32
  262. package/static/assets/pdfjs/web/locale/ne-NP/viewer.ftl +0 -12
  263. package/static/assets/pdfjs/web/locale/nl/viewer.ftl +0 -32
  264. package/static/assets/pdfjs/web/locale/nn-NO/viewer.ftl +0 -32
  265. package/static/assets/pdfjs/web/locale/oc/viewer.ftl +0 -24
  266. package/static/assets/pdfjs/web/locale/pa-IN/viewer.ftl +0 -32
  267. package/static/assets/pdfjs/web/locale/pl/viewer.ftl +0 -32
  268. package/static/assets/pdfjs/web/locale/pt-BR/viewer.ftl +0 -32
  269. package/static/assets/pdfjs/web/locale/pt-PT/viewer.ftl +0 -32
  270. package/static/assets/pdfjs/web/locale/rm/viewer.ftl +0 -32
  271. package/static/assets/pdfjs/web/locale/ro/viewer.ftl +5 -37
  272. package/static/assets/pdfjs/web/locale/ru/viewer.ftl +0 -32
  273. package/static/assets/pdfjs/web/locale/sat/viewer.ftl +0 -23
  274. package/static/assets/pdfjs/web/locale/sc/viewer.ftl +8 -27
  275. package/static/assets/pdfjs/web/locale/sco/viewer.ftl +0 -16
  276. package/static/assets/pdfjs/web/locale/si/viewer.ftl +0 -22
  277. package/static/assets/pdfjs/web/locale/sk/viewer.ftl +0 -32
  278. package/static/assets/pdfjs/web/locale/skr/viewer.ftl +0 -32
  279. package/static/assets/pdfjs/web/locale/sl/viewer.ftl +30 -32
  280. package/static/assets/pdfjs/web/locale/son/viewer.ftl +0 -12
  281. package/static/assets/pdfjs/web/locale/sq/viewer.ftl +0 -32
  282. package/static/assets/pdfjs/web/locale/sr/viewer.ftl +0 -32
  283. package/static/assets/pdfjs/web/locale/sv-SE/viewer.ftl +0 -32
  284. package/static/assets/pdfjs/web/locale/szl/viewer.ftl +0 -16
  285. package/static/assets/pdfjs/web/locale/ta/viewer.ftl +0 -12
  286. package/static/assets/pdfjs/web/locale/te/viewer.ftl +0 -16
  287. package/static/assets/pdfjs/web/locale/tg/viewer.ftl +0 -32
  288. package/static/assets/pdfjs/web/locale/th/viewer.ftl +38 -32
  289. package/static/assets/pdfjs/web/locale/tl/viewer.ftl +0 -16
  290. package/static/assets/pdfjs/web/locale/tr/viewer.ftl +0 -32
  291. package/static/assets/pdfjs/web/locale/trs/viewer.ftl +0 -12
  292. package/static/assets/pdfjs/web/locale/uk/viewer.ftl +0 -32
  293. package/static/assets/pdfjs/web/locale/ur/viewer.ftl +0 -16
  294. package/static/assets/pdfjs/web/locale/uz/viewer.ftl +0 -12
  295. package/static/assets/pdfjs/web/locale/vi/viewer.ftl +0 -32
  296. package/static/assets/pdfjs/web/locale/xh/viewer.ftl +0 -12
  297. package/static/assets/pdfjs/web/locale/zh-CN/viewer.ftl +0 -32
  298. package/static/assets/pdfjs/web/locale/zh-TW/viewer.ftl +0 -32
  299. package/static/assets/pdfjs/web/viewer.css +586 -437
  300. package/static/assets/pdfjs/web/viewer.html +12 -23
  301. package/static/assets/pdfjs/web/viewer.mjs +955 -514
  302. package/static/assets/pdfjs/web/viewer.mjs.map +1 -1
  303. package/static/assets/pdfjs/web/wasm/openjpeg.wasm +0 -0
  304. package/static/assets/pdfjs/web/wasm/openjpeg_nowasm_fallback.js +10 -22
  305. package/static/{chunk-SPTF6FSM.js → chunk-27YQB3TE.js} +1 -1
  306. package/static/chunk-2I4CUFUA.js +1 -0
  307. package/static/chunk-2MTM6SWN.js +4 -0
  308. package/static/{chunk-7VRUZRJG.js → chunk-34MKICK5.js} +2 -2
  309. package/static/chunk-5O3DIUU3.js +1 -0
  310. package/static/{chunk-VJRTMDEJ.js → chunk-6NMVZIIT.js} +1 -1
  311. package/static/{chunk-L6MU6S2V.js → chunk-7DN7ZAPU.js} +1 -1
  312. package/static/{chunk-MVO4WZLK.js → chunk-7FUM3JGM.js} +1 -1
  313. package/static/{chunk-RSS6GYNE.js → chunk-7ITZXYYJ.js} +1 -1
  314. package/static/chunk-7P27WBGC.js +4 -0
  315. package/static/chunk-ATP3BFHV.js +562 -0
  316. package/static/chunk-AWQ2YTVC.js +1 -0
  317. package/static/chunk-DSOE3FEP.js +1 -0
  318. package/static/{chunk-2R6HHGUR.js → chunk-EFKMBLRE.js} +1 -1
  319. package/static/chunk-FUFKVHPU.js +1 -0
  320. package/static/{chunk-MRSWNAVB.js → chunk-HCDLWTMW.js} +1 -1
  321. package/static/chunk-IPAC4VAF.js +1 -0
  322. package/static/{chunk-ZC5NIT55.js → chunk-IQOALFYU.js} +1 -1
  323. package/static/chunk-JASU3CIH.js +1 -0
  324. package/static/{chunk-6OJZWYRZ.js → chunk-JQ5FTO2M.js} +1 -1
  325. package/static/chunk-JUNZFADM.js +1 -0
  326. package/static/{chunk-LLWSLOSX.js → chunk-LJUKI4SQ.js} +1 -1
  327. package/static/{chunk-WI7FOANP.js → chunk-LUWQFIWR.js} +1 -1
  328. package/static/{chunk-BIUNUYZ5.js → chunk-ORMRCEGT.js} +1 -1
  329. package/static/{chunk-IZL7JPTS.js → chunk-Q7D6RN4N.js} +1 -1
  330. package/static/{chunk-JYXLQRHG.js → chunk-QJX6ITLW.js} +1 -1
  331. package/static/{chunk-YJMN3B4N.js → chunk-QQ6UQQBR.js} +1 -1
  332. package/static/chunk-S2HDY3OL.js +1 -0
  333. package/static/{chunk-NE4NDO45.js → chunk-S75P2FFI.js} +1 -1
  334. package/static/{chunk-CRQNEHTX.js → chunk-T3EYFSVZ.js} +1 -1
  335. package/static/{chunk-MCLQFZ3S.js → chunk-U34OZUZ7.js} +1 -1
  336. package/static/chunk-Y7EH7G5K.js +1 -0
  337. package/static/{chunk-MGGT6MIJ.js → chunk-ZQQPUYLU.js} +1 -1
  338. package/static/index.html +2 -2
  339. package/static/main-7SQDDVMD.js +9 -0
  340. package/static/{styles-FYUSO6OJ.css → styles-A5VYX3CE.css} +1 -1
  341. package/server/applications/users/dto/user-password.dto.js.map +0 -1
  342. package/static/chunk-4U5A2DEP.js +0 -4
  343. package/static/chunk-54EAZ2UD.js +0 -1
  344. package/static/chunk-7ZRXJONB.js +0 -1
  345. package/static/chunk-F2J2IIJE.js +0 -1
  346. package/static/chunk-FNFGUIQH.js +0 -4
  347. package/static/chunk-GGLK52CG.js +0 -1
  348. package/static/chunk-HW2H3ISM.js +0 -559
  349. package/static/chunk-HX6BBYVD.js +0 -1
  350. package/static/chunk-JF7S3UYQ.js +0 -1
  351. package/static/chunk-KSHPKI4G.js +0 -1
  352. package/static/chunk-VPJ2V27B.js +0 -1
  353. package/static/chunk-VUI3KV7V.js +0 -1
  354. package/static/chunk-ZXS4V7J2.js +0 -1
  355. package/static/main-FFIWFD2F.js +0 -7
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/users/dto/delete-user.dto.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 { IsBoolean, IsNotEmpty, IsOptional, IsString } from 'class-validator'\n\nexport class DeleteUserDto {\n @IsBoolean()\n deleteSpace: boolean\n\n @IsOptional()\n @IsBoolean()\n isGuest? = false\n}\n\nexport class AdminDeleteUserDto extends DeleteUserDto {\n @IsNotEmpty()\n @IsString()\n adminPassword: string\n}\n"],"names":["AdminDeleteUserDto","DeleteUserDto","isGuest"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QAaYA;eAAAA;;QATAC;eAAAA;;;gCAF+C;;;;;;;;;;AAErD,IAAA,AAAMA,gBAAN,MAAMA;;aAMXC,UAAW;;AACb;;;;;;;;;AAEO,IAAA,AAAMF,qBAAN,MAAMA,2BAA2BC;AAIxC"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/users/dto/delete-user.dto.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 { IsBoolean } from 'class-validator'\n\nexport class DeleteUserDto {\n @IsBoolean()\n deleteSpace: boolean\n\n @IsBoolean()\n isGuest: boolean\n}\n"],"names":["DeleteUserDto"],"mappings":"AAAA;;;;CAIC;;;;+BAIYA;;;eAAAA;;;gCAFa;;;;;;;;;;AAEnB,IAAA,AAAMA,gBAAN,MAAMA;AAMb"}
@@ -13,6 +13,9 @@ function _export(target, all) {
13
13
  });
14
14
  }
15
15
  _export(exports, {
16
+ get UserAppPasswordDto () {
17
+ return UserAppPasswordDto;
18
+ },
16
19
  get UserLanguageDto () {
17
20
  return UserLanguageDto;
18
21
  },
@@ -21,9 +24,15 @@ _export(exports, {
21
24
  },
22
25
  get UserPasswordDto () {
23
26
  return UserPasswordDto;
27
+ },
28
+ get UserUpdatePasswordDto () {
29
+ return UserUpdatePasswordDto;
24
30
  }
25
31
  });
32
+ const _classtransformer = require("class-transformer");
26
33
  const _classvalidator = require("class-validator");
34
+ const _scope = require("../../../authentication/constants/scope");
35
+ const _shared = require("../../../common/shared");
27
36
  const _user = require("../constants/user");
28
37
  function _ts_decorate(decorators, target, key, desc) {
29
38
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -47,18 +56,44 @@ _ts_decorate([
47
56
  (0, _classvalidator.IsInt)(),
48
57
  _ts_metadata("design:type", Number)
49
58
  ], UserNotificationDto.prototype, "notification", void 0);
50
- let UserPasswordDto = class UserPasswordDto {
59
+ let UserUpdatePasswordDto = class UserUpdatePasswordDto {
51
60
  };
52
61
  _ts_decorate([
53
62
  (0, _classvalidator.IsNotEmpty)(),
54
63
  (0, _classvalidator.IsString)(),
55
64
  _ts_metadata("design:type", String)
56
- ], UserPasswordDto.prototype, "oldPassword", void 0);
65
+ ], UserUpdatePasswordDto.prototype, "oldPassword", void 0);
57
66
  _ts_decorate([
58
67
  (0, _classvalidator.IsNotEmpty)(),
59
68
  (0, _classvalidator.IsString)(),
60
69
  (0, _classvalidator.MinLength)(_user.USER_PASSWORD_MIN_LENGTH),
61
70
  _ts_metadata("design:type", String)
62
- ], UserPasswordDto.prototype, "newPassword", void 0);
71
+ ], UserUpdatePasswordDto.prototype, "newPassword", void 0);
72
+ let UserPasswordDto = class UserPasswordDto {
73
+ };
74
+ _ts_decorate([
75
+ (0, _classvalidator.IsNotEmpty)(),
76
+ (0, _classvalidator.IsString)(),
77
+ (0, _classvalidator.MinLength)(_user.USER_PASSWORD_MIN_LENGTH),
78
+ _ts_metadata("design:type", String)
79
+ ], UserPasswordDto.prototype, "password", void 0);
80
+ let UserAppPasswordDto = class UserAppPasswordDto {
81
+ };
82
+ _ts_decorate([
83
+ (0, _classvalidator.IsNotEmpty)(),
84
+ (0, _classvalidator.IsString)(),
85
+ _ts_metadata("design:type", String)
86
+ ], UserAppPasswordDto.prototype, "name", void 0);
87
+ _ts_decorate([
88
+ (0, _classtransformer.Transform)(({ value })=>value.toLowerCase()),
89
+ (0, _classvalidator.IsEnum)(_scope.AUTH_SCOPE),
90
+ _ts_metadata("design:type", typeof _scope.AUTH_SCOPE === "undefined" ? Object : _scope.AUTH_SCOPE)
91
+ ], UserAppPasswordDto.prototype, "app", void 0);
92
+ _ts_decorate([
93
+ (0, _classvalidator.IsOptional)(),
94
+ (0, _classtransformer.Transform)(({ value })=>value ? (0, _shared.currentDate)(value) : null),
95
+ (0, _classvalidator.IsDate)(),
96
+ _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
97
+ ], UserAppPasswordDto.prototype, "expiration", void 0);
63
98
 
64
99
  //# sourceMappingURL=user-properties.dto.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/users/dto/user-properties.dto.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 { IsInt, IsNotEmpty, IsString, MinLength, ValidateIf } from 'class-validator'\nimport { USER_PASSWORD_MIN_LENGTH } from '../constants/user'\n\nexport class UserLanguageDto {\n @ValidateIf((_, language) => language === null || typeof language === 'string')\n language: string | null\n}\n\nexport class UserNotificationDto {\n @IsNotEmpty()\n @IsInt()\n notification: number\n}\n\nexport class UserPasswordDto {\n @IsNotEmpty()\n @IsString()\n oldPassword: string\n\n @IsNotEmpty()\n @IsString()\n @MinLength(USER_PASSWORD_MIN_LENGTH)\n newPassword: string\n}\n"],"names":["UserLanguageDto","UserNotificationDto","UserPasswordDto","_","language"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QAKYA;eAAAA;;QAKAC;eAAAA;;QAMAC;eAAAA;;;gCAdsD;sBAC1B;;;;;;;;;;AAElC,IAAA,AAAMF,kBAAN,MAAMA;AAGb;;qCAFeG,GAAGC,WAAaA,aAAa,QAAQ,OAAOA,aAAa;;;AAIjE,IAAA,AAAMH,sBAAN,MAAMA;AAIb;;;;;;AAEO,IAAA,AAAMC,kBAAN,MAAMA;AASb"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/users/dto/user-properties.dto.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 { Transform } from 'class-transformer'\nimport { IsDate, IsEnum, IsInt, IsNotEmpty, IsOptional, IsString, MinLength, ValidateIf } from 'class-validator'\nimport { AUTH_SCOPE } from '../../../authentication/constants/scope'\nimport { currentDate } from '../../../common/shared'\nimport { USER_PASSWORD_MIN_LENGTH } from '../constants/user'\n\nexport class UserLanguageDto {\n @ValidateIf((_, language) => language === null || typeof language === 'string')\n language: string | null\n}\n\nexport class UserNotificationDto {\n @IsNotEmpty()\n @IsInt()\n notification: number\n}\n\nexport class UserUpdatePasswordDto {\n @IsNotEmpty()\n @IsString()\n oldPassword: string\n\n @IsNotEmpty()\n @IsString()\n @MinLength(USER_PASSWORD_MIN_LENGTH)\n newPassword: string\n}\n\nexport class UserPasswordDto {\n @IsNotEmpty()\n @IsString()\n @MinLength(USER_PASSWORD_MIN_LENGTH)\n password: string\n}\n\nexport class UserAppPasswordDto {\n @IsNotEmpty()\n @IsString()\n name: string\n\n @Transform(({ value }) => value.toLowerCase())\n @IsEnum(AUTH_SCOPE)\n app: AUTH_SCOPE\n\n @IsOptional()\n @Transform(({ value }) => (value ? currentDate(value) : null))\n @IsDate()\n expiration?: Date\n}\n"],"names":["UserAppPasswordDto","UserLanguageDto","UserNotificationDto","UserPasswordDto","UserUpdatePasswordDto","_","language","value","toLowerCase","currentDate"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QAqCYA;eAAAA;;QA7BAC;eAAAA;;QAKAC;eAAAA;;QAiBAC;eAAAA;;QAXAC;eAAAA;;;kCAjBa;gCACqE;uBACpE;wBACC;sBACa;;;;;;;;;;AAElC,IAAA,AAAMH,kBAAN,MAAMA;AAGb;;qCAFeI,GAAGC,WAAaA,aAAa,QAAQ,OAAOA,aAAa;;;AAIjE,IAAA,AAAMJ,sBAAN,MAAMA;AAIb;;;;;;AAEO,IAAA,AAAME,wBAAN,MAAMA;AASb;;;;;;;;;;;;AAEO,IAAA,AAAMD,kBAAN,MAAMA;AAKb;;;;;;;AAEO,IAAA,AAAMH,qBAAN,MAAMA;AAab;;;;;;;sCARc,EAAEO,KAAK,EAAE,GAAKA,MAAMC,WAAW;;;;;;sCAK/B,EAAED,KAAK,EAAE,GAAMA,QAAQE,IAAAA,mBAAW,EAACF,SAAS"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/users/interfaces/admin-user.interface.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 type { User } from '../schemas/user.interface'\nimport type { Member } from './member.interface'\n\nexport type AdminUser = Partial<User> & { fullName: string; groups?: Member[] }\n"],"names":[],"mappings":"AAAA;;;;CAIC"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/users/interfaces/admin-user.interface.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 type { User } from '../schemas/user.interface'\nimport type { Member } from './member.interface'\n\nexport type AdminUser = Partial<User> & { fullName: string; groups?: Member[]; twoFaEnabled?: boolean }\n"],"names":[],"mappings":"AAAA;;;;CAIC"}
@@ -0,0 +1,10 @@
1
+ /*
2
+ * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>
3
+ * This file is part of Sync-in | The open source file sync and share solution
4
+ * See the LICENSE file for licensing details
5
+ */ "use strict";
6
+ Object.defineProperty(exports, "__esModule", {
7
+ value: true
8
+ });
9
+
10
+ //# sourceMappingURL=user-secrets.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../backend/src/applications/users/interfaces/user-secrets.interface.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 { AUTH_SCOPE } from '../../../authentication/constants/scope'\nimport { USER_SECRET } from '../constants/user'\n\nexport interface UserAppPassword {\n name: string\n app: AUTH_SCOPE\n password: string\n expiration: Date\n currentIp: string\n lastIp: string\n currentAccess: Date\n lastAccess: Date\n createdAt: Date\n}\n\nexport interface UserSecrets {\n [USER_SECRET.TWO_FA_SECRET]?: string\n [USER_SECRET.RECOVERY_CODES]?: string[]\n [USER_SECRET.APP_PASSWORDS]?: UserAppPassword[]\n}\n"],"names":[],"mappings":"AAAA;;;;CAIC"}
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "UserModel", {
15
15
  const _classtransformer = require("class-transformer");
16
16
  const _promises = /*#__PURE__*/ _interop_require_default(require("node:fs/promises"));
17
17
  const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
18
+ const _shared = require("../../../common/shared");
18
19
  const _configenvironment = require("../../../configuration/config.environment");
19
20
  const _spaces = require("../../spaces/constants/spaces");
20
21
  const _user = require("../constants/user");
@@ -33,16 +34,23 @@ function _ts_metadata(k, v) {
33
34
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
34
35
  }
35
36
  let UserModel = class UserModel {
36
- toString() {
37
- return `*User <${this.login}> (${this.id})*`;
37
+ get homePath() {
38
+ if (this.isLink || this.isGuest) {
39
+ return this._homePath ||= _nodepath.default.join(_configenvironment.configuration.applications.files.tmpPath, this.isGuest ? 'guests' : 'links', this.login);
40
+ }
41
+ return this._homePath ||= _nodepath.default.join(_configenvironment.configuration.applications.files.usersPath, this.login);
38
42
  }
39
- removePassword() {
40
- delete this.password;
43
+ get filesPath() {
44
+ return this._filesPath ||= _nodepath.default.join(this.homePath, _spaces.SPACE_REPOSITORY.FILES);
41
45
  }
42
- setFullName() {
43
- if (!this.fullName) {
44
- this.fullName = `${this.firstName || ''} ${this.lastName || ''}`.trim();
45
- }
46
+ get trashPath() {
47
+ return this._trashPath ||= _nodepath.default.join(this.homePath, _spaces.SPACE_REPOSITORY.TRASH);
48
+ }
49
+ get tmpPath() {
50
+ return this._tmpPath ||= _nodepath.default.join(this.homePath, _user.USER_PATH.TMP);
51
+ }
52
+ get tasksPath() {
53
+ return this._tasksPath ||= _nodepath.default.join(this.tmpPath, _user.USER_PATH.TASKS);
46
54
  }
47
55
  get isAdmin() {
48
56
  return this.role === _user.USER_ROLE.ADMINISTRATOR;
@@ -59,23 +67,41 @@ let UserModel = class UserModel {
59
67
  get quotaIsExceeded() {
60
68
  return this.storageQuota !== null && this.storageUsage >= this.storageQuota;
61
69
  }
62
- get homePath() {
63
- if (this.isLink || this.isGuest) {
64
- return this._homePath ||= _nodepath.default.join(_configenvironment.configuration.applications.files.tmpPath, this.isGuest ? 'guests' : 'links', this.login);
70
+ get twoFaEnabled() {
71
+ return !!this.secrets?.twoFaSecret;
72
+ }
73
+ get appPasswords() {
74
+ return this.secrets?.appPasswords?.length || 0;
75
+ }
76
+ static getHomePath(userLogin, isGuest = false, isLink = false) {
77
+ if (isGuest || isLink) {
78
+ return _nodepath.default.join(_configenvironment.configuration.applications.files.tmpPath, isGuest ? 'guests' : 'links', userLogin);
65
79
  }
66
- return this._homePath ||= _nodepath.default.join(_configenvironment.configuration.applications.files.usersPath, this.login);
80
+ return _nodepath.default.join(_configenvironment.configuration.applications.files.usersPath, userLogin);
67
81
  }
68
- get filesPath() {
69
- return this._filesPath ||= _nodepath.default.join(this.homePath, _spaces.SPACE_REPOSITORY.FILES);
82
+ static getFilesPath(userLogin) {
83
+ return _nodepath.default.join(UserModel.getHomePath(userLogin), _spaces.SPACE_REPOSITORY.FILES);
70
84
  }
71
- get trashPath() {
72
- return this._trashPath ||= _nodepath.default.join(this.homePath, _spaces.SPACE_REPOSITORY.TRASH);
85
+ static getTrashPath(userLogin) {
86
+ return _nodepath.default.join(UserModel.getHomePath(userLogin), _spaces.SPACE_REPOSITORY.TRASH);
73
87
  }
74
- get tmpPath() {
75
- return this._tmpPath ||= _nodepath.default.join(this.homePath, _user.USER_PATH.TMP);
88
+ static getTasksPath(userLogin, isGuest = false, isLink = false) {
89
+ return _nodepath.default.join(UserModel.getHomePath(userLogin, isGuest, isLink), _user.USER_PATH.TMP, _user.USER_PATH.TASKS);
76
90
  }
77
- get tasksPath() {
78
- return this._tasksPath ||= _nodepath.default.join(this.tmpPath, _user.USER_PATH.TASKS);
91
+ static getRepositoryPath(userLogin, inTrash = false) {
92
+ if (inTrash) return UserModel.getTrashPath(userLogin);
93
+ return UserModel.getFilesPath(userLogin);
94
+ }
95
+ toString() {
96
+ return `*User <${this.login}> (${this.id})*`;
97
+ }
98
+ removePassword() {
99
+ delete this.password;
100
+ }
101
+ setFullName(force = false) {
102
+ if (!this.fullName || force) {
103
+ this.fullName = `${this.firstName || ''} ${this.lastName || ''}`.trim();
104
+ }
79
105
  }
80
106
  async makePaths() {
81
107
  if (this.isGuest || this.isLink) {
@@ -123,21 +149,6 @@ let UserModel = class UserModel {
123
149
  }
124
150
  return `${initials.f.toUpperCase()}${initials.l.toLowerCase()}`;
125
151
  }
126
- setProfile() {
127
- if (this.isLink) {
128
- this.login = `Link (${this.id})`;
129
- this.email = 'guest-link@sync-in';
130
- }
131
- }
132
- setApplications() {
133
- if (this.isGuest) {
134
- // dynamically set the permissions
135
- this.applications = Object.values(_user.GUEST_PERMISSION);
136
- } else if (this.permissions) {
137
- this.applications = this.permissions.split(_user.USER_PERMS_SEP);
138
- }
139
- delete this.permissions;
140
- }
141
152
  havePermission(permission) {
142
153
  if (this.isAdmin) {
143
154
  return true;
@@ -150,28 +161,37 @@ let UserModel = class UserModel {
150
161
  haveRole(role) {
151
162
  return this.role <= role;
152
163
  }
153
- static getHomePath(userLogin, isGuest = false, isLink = false) {
154
- if (isGuest || isLink) {
155
- return _nodepath.default.join(_configenvironment.configuration.applications.files.tmpPath, isGuest ? 'guests' : 'links', userLogin);
164
+ initSecrets(props) {
165
+ // Remove the `twoFaEnabled` property to avoid conflicts with the current getter when using `plainToClass` with `class-validator`
166
+ // The `props` variable may be empty when the class is instantiated using `plainToClass`
167
+ if (props && 'twoFaEnabled' in props) {
168
+ // Only used when the User model is instantiated from a token payload
169
+ // Set a `twoFaSecret` property (boolean) on the `secrets` property so that the `twoFaEnabled` getter returns `true`
170
+ this.secrets = {
171
+ twoFaSecret: (0, _shared.popFromObject)('twoFaEnabled', props)
172
+ };
156
173
  }
157
- return _nodepath.default.join(_configenvironment.configuration.applications.files.usersPath, userLogin);
158
- }
159
- static getFilesPath(userLogin) {
160
- return _nodepath.default.join(UserModel.getHomePath(userLogin), _spaces.SPACE_REPOSITORY.FILES);
161
- }
162
- static getTrashPath(userLogin) {
163
- return _nodepath.default.join(UserModel.getHomePath(userLogin), _spaces.SPACE_REPOSITORY.TRASH);
164
174
  }
165
- static getTasksPath(userLogin, isGuest = false, isLink = false) {
166
- return _nodepath.default.join(UserModel.getHomePath(userLogin, isGuest, isLink), _user.USER_PATH.TMP, _user.USER_PATH.TASKS);
175
+ setProfile() {
176
+ if (this.isLink) {
177
+ this.login = `Link (${this.id})`;
178
+ this.email = 'guest-link@sync-in';
179
+ }
167
180
  }
168
- static getRepositoryPath(userLogin, inTrash = false) {
169
- if (inTrash) return UserModel.getTrashPath(userLogin);
170
- return UserModel.getFilesPath(userLogin);
181
+ setApplications() {
182
+ if (this.isGuest) {
183
+ // dynamically set the permissions
184
+ this.applications = Object.values(_user.GUEST_PERMISSION);
185
+ } else if (this.permissions) {
186
+ this.applications = this.permissions.split(_user.USER_PERMS_SEP);
187
+ }
188
+ delete this.permissions;
171
189
  }
172
190
  constructor(props, removePassword = true){
173
191
  // permissions as a list
174
192
  this.applications = [];
193
+ // User model can be instantiated with data from the database or from a token payload
194
+ this.initSecrets(props);
175
195
  Object.assign(this, props);
176
196
  if (removePassword) {
177
197
  // always remove the password field from model for obvious security reasons
@@ -187,6 +207,10 @@ _ts_decorate([
187
207
  (0, _classtransformer.Exclude)(),
188
208
  _ts_metadata("design:type", String)
189
209
  ], UserModel.prototype, "password", void 0);
210
+ _ts_decorate([
211
+ (0, _classtransformer.Exclude)(),
212
+ _ts_metadata("design:type", typeof UserSecrets === "undefined" ? Object : UserSecrets)
213
+ ], UserModel.prototype, "secrets", void 0);
190
214
  _ts_decorate([
191
215
  (0, _classtransformer.Exclude)(),
192
216
  _ts_metadata("design:type", Number)
@@ -222,5 +246,15 @@ _ts_decorate([
222
246
  _ts_metadata("design:type", Boolean),
223
247
  _ts_metadata("design:paramtypes", [])
224
248
  ], UserModel.prototype, "quotaIsExceeded", null);
249
+ _ts_decorate([
250
+ (0, _classtransformer.Expose)(),
251
+ _ts_metadata("design:type", Boolean),
252
+ _ts_metadata("design:paramtypes", [])
253
+ ], UserModel.prototype, "twoFaEnabled", null);
254
+ _ts_decorate([
255
+ (0, _classtransformer.Expose)(),
256
+ _ts_metadata("design:type", Number),
257
+ _ts_metadata("design:paramtypes", [])
258
+ ], UserModel.prototype, "appPasswords", null);
225
259
 
226
260
  //# sourceMappingURL=user.model.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/users/models/user.model.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 { Exclude, Expose } from 'class-transformer'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { configuration } from '../../../configuration/config.environment'\nimport { SPACE_REPOSITORY } from '../../spaces/constants/spaces'\nimport { GUEST_PERMISSION, USER_PATH, USER_PERMISSION, USER_PERMS_SEP, USER_ROLE } from '../constants/user'\nimport type { Owner } from '../interfaces/owner.interface'\nimport type { User } from '../schemas/user.interface'\n\nexport class UserModel implements User {\n id: number\n login: string\n email: string\n firstName: string\n lastName: string\n role: number\n language: string\n notification: number\n onlineStatus: number\n permissions: string\n storageUsage: number\n storageQuota: number\n isActive: boolean\n passwordAttempts: number\n currentIp: string\n lastIp: string\n currentAccess: Date\n lastAccess: Date\n createdAt: Date\n // exclusions\n @Exclude()\n password: string\n @Exclude()\n // only used on backend\n impersonatedFromId?: number\n impersonatedClientId?: string\n // used for desktop|cmd app\n clientId?: string\n\n // outside db schema\n fullName: string\n impersonated?: boolean\n avatarBase64?: string\n // permissions as a list\n applications: string[] = []\n private _homePath: string\n private _filesPath: string\n private _trashPath: string\n private _tmpPath: string\n private _tasksPath: string\n\n @Exclude({ toPlainOnly: true })\n exp?: number // refresh token expiration needed to refresh\n\n constructor(props: Partial<User> & { exp?: number }, removePassword = true) {\n Object.assign(this, props)\n if (removePassword) {\n // always remove the password field from model for obvious security reasons\n // do not remove it from `props` to not mutate the object\n this.removePassword()\n }\n this.setFullName()\n this.setApplications()\n this.setProfile()\n }\n\n toString(): string {\n return `*User <${this.login}> (${this.id})*`\n }\n\n removePassword() {\n delete this.password\n }\n\n setFullName() {\n if (!this.fullName) {\n this.fullName = `${this.firstName || ''} ${this.lastName || ''}`.trim()\n }\n }\n\n @Expose()\n get isAdmin(): boolean {\n return this.role === USER_ROLE.ADMINISTRATOR\n }\n\n @Expose()\n get isUser(): boolean {\n return this.role === USER_ROLE.USER || this.role === USER_ROLE.ADMINISTRATOR\n }\n\n @Expose()\n get isGuest(): boolean {\n return this.role === USER_ROLE.GUEST\n }\n\n @Expose()\n get isLink(): boolean {\n return this.role === USER_ROLE.LINK\n }\n\n @Expose()\n get quotaIsExceeded(): boolean {\n return this.storageQuota !== null && this.storageUsage >= this.storageQuota\n }\n\n get homePath(): string {\n if (this.isLink || this.isGuest) {\n return (this._homePath ||= path.join(configuration.applications.files.tmpPath, this.isGuest ? 'guests' : 'links', this.login))\n }\n return (this._homePath ||= path.join(configuration.applications.files.usersPath, this.login))\n }\n\n get filesPath(): string {\n return (this._filesPath ||= path.join(this.homePath, SPACE_REPOSITORY.FILES))\n }\n\n get trashPath(): string {\n return (this._trashPath ||= path.join(this.homePath, SPACE_REPOSITORY.TRASH))\n }\n\n get tmpPath(): string {\n return (this._tmpPath ||= path.join(this.homePath, USER_PATH.TMP))\n }\n\n get tasksPath(): string {\n return (this._tasksPath ||= path.join(this.tmpPath, USER_PATH.TASKS))\n }\n\n async makePaths(): Promise<void> {\n if (this.isGuest || this.isLink) {\n await fs.mkdir(this.tasksPath, { recursive: true })\n } else {\n for (const p of [this.filesPath, this.trashPath, this.tasksPath]) {\n await fs.mkdir(p, { recursive: true })\n }\n }\n }\n\n asOwner(): Owner {\n return { id: this.id, login: this.login, email: this.email, fullName: this.fullName }\n }\n\n getInitials(): string {\n let initials: { f: string; l: string }\n if (this.firstName) {\n if (this.lastName) {\n initials = { f: this.firstName.charAt(0), l: this.lastName.charAt(0) }\n }\n initials = { f: this.firstName.charAt(0), l: this.firstName.charAt(1) }\n } else {\n initials = { f: this.login.charAt(0), l: this.login.charAt(1) }\n }\n return `${initials.f.toUpperCase()}${initials.l.toLowerCase()}`\n }\n\n private setProfile() {\n if (this.isLink) {\n this.login = `Link (${this.id})`\n this.email = 'guest-link@sync-in'\n }\n }\n\n private setApplications() {\n if (this.isGuest) {\n // dynamically set the permissions\n this.applications = Object.values(GUEST_PERMISSION)\n } else if (this.permissions) {\n this.applications = this.permissions.split(USER_PERMS_SEP)\n }\n delete this.permissions\n }\n\n havePermission(permission: string): boolean {\n if (this.isAdmin) {\n return true\n }\n if (permission === USER_PERMISSION.PERSONAL_SPACE && this.isGuest) {\n return false\n }\n return this.applications.indexOf(permission) !== -1\n }\n\n haveRole(role: number): boolean {\n return this.role <= role\n }\n\n static getHomePath(userLogin: string, isGuest = false, isLink = false): string {\n if (isGuest || isLink) {\n return path.join(configuration.applications.files.tmpPath, isGuest ? 'guests' : 'links', userLogin)\n }\n return path.join(configuration.applications.files.usersPath, userLogin)\n }\n\n static getFilesPath(userLogin: string): string {\n return path.join(UserModel.getHomePath(userLogin), SPACE_REPOSITORY.FILES)\n }\n\n static getTrashPath(userLogin: string): string {\n return path.join(UserModel.getHomePath(userLogin), SPACE_REPOSITORY.TRASH)\n }\n\n static getTasksPath(userLogin: string, isGuest = false, isLink = false): string {\n return path.join(UserModel.getHomePath(userLogin, isGuest, isLink), USER_PATH.TMP, USER_PATH.TASKS)\n }\n\n static getRepositoryPath(userLogin: string, inTrash = false): string {\n if (inTrash) return UserModel.getTrashPath(userLogin)\n return UserModel.getFilesPath(userLogin)\n }\n}\n"],"names":["UserModel","toString","login","id","removePassword","password","setFullName","fullName","firstName","lastName","trim","isAdmin","role","USER_ROLE","ADMINISTRATOR","isUser","USER","isGuest","GUEST","isLink","LINK","quotaIsExceeded","storageQuota","storageUsage","homePath","_homePath","path","join","configuration","applications","files","tmpPath","usersPath","filesPath","_filesPath","SPACE_REPOSITORY","FILES","trashPath","_trashPath","TRASH","_tmpPath","USER_PATH","TMP","tasksPath","_tasksPath","TASKS","makePaths","fs","mkdir","recursive","p","asOwner","email","getInitials","initials","f","charAt","l","toUpperCase","toLowerCase","setProfile","setApplications","Object","values","GUEST_PERMISSION","permissions","split","USER_PERMS_SEP","havePermission","permission","USER_PERMISSION","PERSONAL_SPACE","indexOf","haveRole","getHomePath","userLogin","getFilesPath","getTrashPath","getTasksPath","getRepositoryPath","inTrash","props","assign","toPlainOnly"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/users/models/user.model.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 { Exclude, Expose } from 'class-transformer'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { popFromObject } from '../../../common/shared'\nimport { configuration } from '../../../configuration/config.environment'\nimport { SPACE_REPOSITORY } from '../../spaces/constants/spaces'\nimport { GUEST_PERMISSION, USER_PATH, USER_PERMISSION, USER_PERMS_SEP, USER_ROLE } from '../constants/user'\nimport type { Owner } from '../interfaces/owner.interface'\nimport type { UserSecrets } from '../interfaces/user-secrets.interface'\nimport type { User } from '../schemas/user.interface'\n\nexport class UserModel implements User {\n id: number\n login: string\n email: string\n firstName: string\n lastName: string\n role: number\n language: string\n isActive: boolean\n notification: number\n onlineStatus: number\n permissions: string\n storageUsage: number\n storageQuota: number\n passwordAttempts: number\n currentIp: string\n lastIp: string\n currentAccess: Date\n lastAccess: Date\n createdAt: Date\n // exclusions\n @Exclude()\n password: string\n @Exclude()\n secrets: UserSecrets\n @Exclude()\n // only used on backend\n impersonatedFromId?: number\n impersonatedClientId?: string\n // used for desktop|cmd app\n clientId?: string\n\n // outside db schema\n fullName: string\n impersonated?: boolean\n avatarBase64?: string\n // permissions as a list\n applications: string[] = []\n @Exclude({ toPlainOnly: true })\n exp?: number // refresh token expiration needed to refresh\n\n constructor(props: Partial<User> & { exp?: number; twoFaEnabled?: boolean }, removePassword = true) {\n // User model can be instantiated with data from the database or from a token payload\n this.initSecrets(props)\n Object.assign(this, props)\n if (removePassword) {\n // always remove the password field from model for obvious security reasons\n // do not remove it from `props` to not mutate the object\n this.removePassword()\n }\n this.setFullName()\n this.setApplications()\n this.setProfile()\n }\n\n private _homePath: string\n\n get homePath(): string {\n if (this.isLink || this.isGuest) {\n return (this._homePath ||= path.join(configuration.applications.files.tmpPath, this.isGuest ? 'guests' : 'links', this.login))\n }\n return (this._homePath ||= path.join(configuration.applications.files.usersPath, this.login))\n }\n\n private _filesPath: string\n\n get filesPath(): string {\n return (this._filesPath ||= path.join(this.homePath, SPACE_REPOSITORY.FILES))\n }\n\n private _trashPath: string\n\n get trashPath(): string {\n return (this._trashPath ||= path.join(this.homePath, SPACE_REPOSITORY.TRASH))\n }\n\n private _tmpPath: string\n\n get tmpPath(): string {\n return (this._tmpPath ||= path.join(this.homePath, USER_PATH.TMP))\n }\n\n private _tasksPath: string\n\n get tasksPath(): string {\n return (this._tasksPath ||= path.join(this.tmpPath, USER_PATH.TASKS))\n }\n\n @Expose()\n get isAdmin(): boolean {\n return this.role === USER_ROLE.ADMINISTRATOR\n }\n\n @Expose()\n get isUser(): boolean {\n return this.role === USER_ROLE.USER || this.role === USER_ROLE.ADMINISTRATOR\n }\n\n @Expose()\n get isGuest(): boolean {\n return this.role === USER_ROLE.GUEST\n }\n\n @Expose()\n get isLink(): boolean {\n return this.role === USER_ROLE.LINK\n }\n\n @Expose()\n get quotaIsExceeded(): boolean {\n return this.storageQuota !== null && this.storageUsage >= this.storageQuota\n }\n\n @Expose()\n get twoFaEnabled(): boolean {\n return !!this.secrets?.twoFaSecret\n }\n\n @Expose()\n get appPasswords(): number {\n return this.secrets?.appPasswords?.length || 0\n }\n\n static getHomePath(userLogin: string, isGuest = false, isLink = false): string {\n if (isGuest || isLink) {\n return path.join(configuration.applications.files.tmpPath, isGuest ? 'guests' : 'links', userLogin)\n }\n return path.join(configuration.applications.files.usersPath, userLogin)\n }\n\n static getFilesPath(userLogin: string): string {\n return path.join(UserModel.getHomePath(userLogin), SPACE_REPOSITORY.FILES)\n }\n\n static getTrashPath(userLogin: string): string {\n return path.join(UserModel.getHomePath(userLogin), SPACE_REPOSITORY.TRASH)\n }\n\n static getTasksPath(userLogin: string, isGuest = false, isLink = false): string {\n return path.join(UserModel.getHomePath(userLogin, isGuest, isLink), USER_PATH.TMP, USER_PATH.TASKS)\n }\n\n static getRepositoryPath(userLogin: string, inTrash = false): string {\n if (inTrash) return UserModel.getTrashPath(userLogin)\n return UserModel.getFilesPath(userLogin)\n }\n\n toString(): string {\n return `*User <${this.login}> (${this.id})*`\n }\n\n removePassword() {\n delete this.password\n }\n\n setFullName(force = false) {\n if (!this.fullName || force) {\n this.fullName = `${this.firstName || ''} ${this.lastName || ''}`.trim()\n }\n }\n\n async makePaths(): Promise<void> {\n if (this.isGuest || this.isLink) {\n await fs.mkdir(this.tasksPath, { recursive: true })\n } else {\n for (const p of [this.filesPath, this.trashPath, this.tasksPath]) {\n await fs.mkdir(p, { recursive: true })\n }\n }\n }\n\n asOwner(): Owner {\n return { id: this.id, login: this.login, email: this.email, fullName: this.fullName }\n }\n\n getInitials(): string {\n let initials: { f: string; l: string }\n if (this.firstName) {\n if (this.lastName) {\n initials = { f: this.firstName.charAt(0), l: this.lastName.charAt(0) }\n }\n initials = { f: this.firstName.charAt(0), l: this.firstName.charAt(1) }\n } else {\n initials = { f: this.login.charAt(0), l: this.login.charAt(1) }\n }\n return `${initials.f.toUpperCase()}${initials.l.toLowerCase()}`\n }\n\n havePermission(permission: string): boolean {\n if (this.isAdmin) {\n return true\n }\n if (permission === USER_PERMISSION.PERSONAL_SPACE && this.isGuest) {\n return false\n }\n return this.applications.indexOf(permission) !== -1\n }\n\n haveRole(role: number): boolean {\n return this.role <= role\n }\n\n private initSecrets(props: Partial<UserModel>) {\n // Remove the `twoFaEnabled` property to avoid conflicts with the current getter when using `plainToClass` with `class-validator`\n // The `props` variable may be empty when the class is instantiated using `plainToClass`\n if (props && 'twoFaEnabled' in props) {\n // Only used when the User model is instantiated from a token payload\n // Set a `twoFaSecret` property (boolean) on the `secrets` property so that the `twoFaEnabled` getter returns `true`\n this.secrets = { twoFaSecret: popFromObject('twoFaEnabled', props) }\n }\n }\n\n private setProfile() {\n if (this.isLink) {\n this.login = `Link (${this.id})`\n this.email = 'guest-link@sync-in'\n }\n }\n\n private setApplications() {\n if (this.isGuest) {\n // dynamically set the permissions\n this.applications = Object.values(GUEST_PERMISSION)\n } else if (this.permissions) {\n this.applications = this.permissions.split(USER_PERMS_SEP)\n }\n delete this.permissions\n }\n}\n"],"names":["UserModel","homePath","isLink","isGuest","_homePath","path","join","configuration","applications","files","tmpPath","login","usersPath","filesPath","_filesPath","SPACE_REPOSITORY","FILES","trashPath","_trashPath","TRASH","_tmpPath","USER_PATH","TMP","tasksPath","_tasksPath","TASKS","isAdmin","role","USER_ROLE","ADMINISTRATOR","isUser","USER","GUEST","LINK","quotaIsExceeded","storageQuota","storageUsage","twoFaEnabled","secrets","twoFaSecret","appPasswords","length","getHomePath","userLogin","getFilesPath","getTrashPath","getTasksPath","getRepositoryPath","inTrash","toString","id","removePassword","password","setFullName","force","fullName","firstName","lastName","trim","makePaths","fs","mkdir","recursive","p","asOwner","email","getInitials","initials","f","charAt","l","toUpperCase","toLowerCase","havePermission","permission","USER_PERMISSION","PERSONAL_SPACE","indexOf","haveRole","initSecrets","props","popFromObject","setProfile","setApplications","Object","values","GUEST_PERMISSION","permissions","split","USER_PERMS_SEP","assign","toPlainOnly"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/users/schemas/user.interface.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 type { users } from './users.schema'\n\ntype UserSchema = typeof users.$inferSelect\n\nexport class User implements UserSchema {\n id: number\n email: string\n login: string\n firstName: string\n lastName: string\n password: string\n role: number\n isActive: boolean\n language: string\n permissions: string\n storageUsage: number\n storageQuota: number\n notification: number\n onlineStatus: number\n passwordAttempts: number\n currentIp: string\n lastIp: string\n currentAccess: Date\n lastAccess: Date\n createdAt: Date\n}\n"],"names":["User"],"mappings":"AAAA;;;;CAIC;;;;+BAMYA;;;eAAAA;;;AAAN,IAAA,AAAMA,OAAN,MAAMA;AAqBb"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/users/schemas/user.interface.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 type { UserSecrets } from '../interfaces/user-secrets.interface'\nimport type { users } from './users.schema'\n\ntype UserSchema = typeof users.$inferSelect\n\nexport class User implements UserSchema {\n id: number\n email: string\n login: string\n firstName: string\n lastName: string\n password: string\n role: number\n isActive: boolean\n secrets: UserSecrets\n language: string\n permissions: string\n storageUsage: number\n storageQuota: number\n notification: number\n onlineStatus: number\n passwordAttempts: number\n currentIp: string\n lastIp: string\n currentAccess: Date\n lastAccess: Date\n createdAt: Date\n}\n"],"names":["User"],"mappings":"AAAA;;;;CAIC;;;;+BAOYA;;;eAAAA;;;AAAN,IAAA,AAAMA,OAAN,MAAMA;AAsBb"}
@@ -22,6 +22,7 @@ _export(exports, {
22
22
  });
23
23
  const _drizzleorm = require("drizzle-orm");
24
24
  const _mysqlcore = require("drizzle-orm/mysql-core");
25
+ const _columns = require("../../../infrastructure/database/columns");
25
26
  const users = (0, _mysqlcore.mysqlTable)('users', {
26
27
  id: (0, _mysqlcore.bigint)('id', {
27
28
  mode: 'number',
@@ -49,6 +50,7 @@ const users = (0, _mysqlcore.mysqlTable)('users', {
49
50
  unsigned: true
50
51
  }).default(1).notNull(),
51
52
  isActive: (0, _mysqlcore.boolean)('isActive').default(true).notNull(),
53
+ secrets: (0, _columns.jsonColumn)()('secrets'),
52
54
  language: (0, _mysqlcore.char)('language', {
53
55
  length: 2
54
56
  }),
@@ -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'\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 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","language","char","permissions","storageUsage","storageQuota","notification","onlineStatus","currentIp","lastIp","currentAccess","datetime","lastAccess","createdAt","sql","table","uniqueIndex","on","index","user"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QAsDYA;eAAAA;;QA7BAC;eAAAA;;;4BAvBY;2BACyE;AAsB3F,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,UAAUC,IAAAA,eAAI,EAAC,YAAY;QAAEb,QAAQ;IAAE;IACvCc,aAAaf,IAAAA,kBAAO,EAAC,eAAe;QAAEC,QAAQ;IAAI,GAAGQ,OAAO,CAAC,IAAIP,OAAO;IACxEc,cAActB,IAAAA,iBAAM,EAAC,gBAAgB;QAAEC,MAAM;QAAUC,UAAU;IAAK,GAAGa,OAAO,CAAC;IACjFQ,cAAcvB,IAAAA,iBAAM,EAAC,gBAAgB;QAAEC,MAAM;QAAUC,UAAU;IAAK;IACtEsB,cAAcV,IAAAA,kBAAO,EAAC,gBAAgB;QAAEZ,UAAU;IAAK,GAAGa,OAAO,CAAC,GAAGP,OAAO;IAC5EiB,cAAcX,IAAAA,kBAAO,EAAC,gBAAgB;QAAEZ,UAAU;IAAK,GAAGa,OAAO,CAAC,GAAGP,OAAO;IAC5EkB,WAAWpB,IAAAA,kBAAO,EAAC,aAAa;QAAEC,QAAQ;IAAG;IAC7CoB,QAAQrB,IAAAA,kBAAO,EAAC,UAAU;QAAEC,QAAQ;IAAG;IACvCqB,eAAeC,IAAAA,mBAAQ,EAAC,iBAAiB;QAAE5B,MAAM;IAAO;IACxD6B,YAAYD,IAAAA,mBAAQ,EAAC,cAAc;QAAE5B,MAAM;IAAO;IAClD8B,WAAWF,IAAAA,mBAAQ,EAAC,aAAa;QAAE5B,MAAM;IAAO,GAC7Cc,OAAO,CAACiB,IAAAA,eAAG,CAAA,CAAC,iBAAiB,CAAC,EAC9BxB,OAAO;AACZ,GACA,CAACyB,QAAU;QAACC,IAAAA,sBAAW,EAAC,aAAaC,EAAE,CAACF,MAAM5B,KAAK;QAAG6B,IAAAA,sBAAW,EAAC,aAAaC,EAAE,CAACF,MAAMxB,KAAK;QAAG2B,IAAAA,gBAAK,EAAC,YAAYD,EAAE,CAACF,MAAMjB,IAAI;KAAE;AAG5H,MAAMpB,kBAAkB,CAACyC,OAA2BL,IAAAA,eAAG,CAAA,CAAC,YAAY,EAAEK,KAAK3B,SAAS,CAAC,OAAO,EAAE2B,KAAK1B,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, 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"}
@@ -168,14 +168,14 @@ let AdminUsersManager = class AdminUsersManager {
168
168
  throw new _common.HttpException('Unable to delete user', _common.HttpStatus.INTERNAL_SERVER_ERROR);
169
169
  }
170
170
  }
171
- async deleteUserFromAdmin(admin, userId, adminDeleteUserDto) {
172
- // check admin password
173
- if (!await this.adminQueries.usersQueries.compareUserPassword(admin.id, adminDeleteUserDto.adminPassword)) {
174
- throw new _common.HttpException('Bad password', _common.HttpStatus.BAD_REQUEST);
175
- }
171
+ async deleteUserOrGuestFromAdmin(userId, deleteUserDto) {
176
172
  const userToDelete = this.checkUser(await this.adminQueries.usersQueries.from(userId));
173
+ if (userToDelete.isGuest !== deleteUserDto.isGuest) {
174
+ throw new _common.HttpException('User mismatch', _common.HttpStatus.BAD_REQUEST);
175
+ }
177
176
  await this.deleteUserOrGuest(userToDelete.id, userToDelete.login, {
178
- deleteSpace: adminDeleteUserDto.deleteSpace
177
+ deleteSpace: deleteUserDto.isGuest ? true : deleteUserDto.deleteSpace,
178
+ isGuest: deleteUserDto.isGuest
179
179
  });
180
180
  }
181
181
  listGuests() {
@@ -196,14 +196,6 @@ let AdminUsersManager = class AdminUsersManager {
196
196
  }
197
197
  return this.updateUserOrGuest(guestId, updateGuestDto, _user.USER_ROLE.GUEST);
198
198
  }
199
- async deleteGuest(guestId) {
200
- // guest has no space but a temporary directory
201
- const guest = await this.getGuest(guestId);
202
- return this.deleteUserOrGuest(guest.id, guest.login, {
203
- deleteSpace: true,
204
- isGuest: true
205
- });
206
- }
207
199
  async browseGroups(name, type = _group.GROUP_TYPE.USER) {
208
200
  if (name) {
209
201
  const group = await this.adminQueries.groupFromName(name);
@@ -287,14 +279,10 @@ let AdminUsersManager = class AdminUsersManager {
287
279
  searchMembers(searchMembersDto) {
288
280
  return this.adminQueries.usersQueries.searchUsersOrGroups(searchMembersDto);
289
281
  }
290
- async impersonateUser(admin, userId, adminPassword, res) {
291
- // check admin password
282
+ async impersonateUser(admin, userId, res) {
292
283
  if (admin.id === userId) {
293
284
  throw new _common.HttpException('You are already logged in', _common.HttpStatus.BAD_REQUEST);
294
285
  }
295
- if (!await this.adminQueries.usersQueries.compareUserPassword(admin.id, adminPassword.password)) {
296
- throw new _common.HttpException('Bad password', _common.HttpStatus.BAD_REQUEST);
297
- }
298
286
  const user = this.checkUser(await this.adminQueries.usersQueries.from(userId));
299
287
  user.impersonatedFromId = admin.id;
300
288
  user.impersonatedClientId = admin.clientId;