@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/webdav/filters/webdav.filter.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 */\nimport { ArgumentsHost, HttpException } from '@nestjs/common'\nimport { Test } from '@nestjs/testing'\nimport { SERVER_NAME } from '../../../app.constants'\nimport { XML_CONTENT_TYPE } from '../constants/webdav'\nimport { WebDAVExceptionsFilter } from './webdav.filter'\n\ndescribe('WebDAVExceptionsFilter', () => {\n let filter: WebDAVExceptionsFilter\n\n const createMockResponse = () => {\n const res: any = {}\n res.header = jest.fn().mockReturnValue(res)\n res.type = jest.fn().mockReturnValue(res)\n res.status = jest.fn().mockReturnValue(res)\n res.send = jest.fn().mockReturnValue(res)\n return res\n }\n\n const createMockHost = (res: any): ArgumentsHost =>\n ({\n switchToHttp: () => ({\n getResponse: () => res\n })\n // Other methods not used by the filter\n }) as unknown as ArgumentsHost\n\n beforeEach(async () => {\n const moduleRef = await Test.createTestingModule({\n providers: [WebDAVExceptionsFilter]\n }).compile()\n\n filter = moduleRef.get(WebDAVExceptionsFilter)\n })\n\n afterEach(() => {\n jest.clearAllMocks()\n })\n\n it('should set WWW-Authenticate header and send empty body for 401', () => {\n const res = createMockResponse()\n const host = createMockHost(res)\n const exception = new HttpException('Unauthorized', 401)\n\n filter.catch(exception, host)\n\n expect(res.header).toHaveBeenCalledWith('WWW-Authenticate', `Basic realm=\"${SERVER_NAME}\"`)\n expect(res.status).toHaveBeenCalledWith(401)\n expect(res.type).not.toHaveBeenCalled()\n expect(res.send).toHaveBeenCalled()\n // Ensure no body is sent\n expect(res.send.mock.calls[0][0]).toBeUndefined()\n })\n\n it('should set XML content type and forward string response for non-401', () => {\n const res = createMockResponse()\n const host = createMockHost(res)\n const exception = new HttpException('Internal error', 500)\n\n filter.catch(exception, host)\n\n expect(res.type).toHaveBeenCalledWith(XML_CONTENT_TYPE)\n expect(res.status).toHaveBeenCalledWith(500)\n expect(res.send).toHaveBeenCalledWith('Internal error')\n expect(res.header).not.toHaveBeenCalled()\n })\n\n it('should extract \"message\" from object response and send it as XML for non-401', () => {\n const res = createMockResponse()\n const host = createMockHost(res)\n const payload = { message: '<error>Bad Request</error>' }\n const exception = new HttpException(payload, 400)\n\n filter.catch(exception, host)\n\n expect(res.type).toHaveBeenCalledWith(XML_CONTENT_TYPE)\n expect(res.status).toHaveBeenCalledWith(400)\n expect(res.send).toHaveBeenCalledWith(payload.message)\n expect(res.header).not.toHaveBeenCalled()\n })\n})\n"],"names":["describe","filter","createMockResponse","res","header","jest","fn","mockReturnValue","type","status","send","createMockHost","switchToHttp","getResponse","beforeEach","moduleRef","Test","createTestingModule","providers","WebDAVExceptionsFilter","compile","get","afterEach","clearAllMocks","it","host","exception","HttpException","catch","expect","toHaveBeenCalledWith","SERVER_NAME","not","toHaveBeenCalled","mock","calls","toBeUndefined","XML_CONTENT_TYPE","payload","message"],"mappings":"AAAA;;;;CAIC;;;;wBAC4C;yBACxB;8BACO;wBACK;8BACM;AAEvCA,SAAS,0BAA0B;IACjC,IAAIC;IAEJ,MAAMC,qBAAqB;QACzB,MAAMC,MAAW,CAAC;QAClBA,IAAIC,MAAM,GAAGC,KAAKC,EAAE,GAAGC,eAAe,CAACJ;QACvCA,IAAIK,IAAI,GAAGH,KAAKC,EAAE,GAAGC,eAAe,CAACJ;QACrCA,IAAIM,MAAM,GAAGJ,KAAKC,EAAE,GAAGC,eAAe,CAACJ;QACvCA,IAAIO,IAAI,GAAGL,KAAKC,EAAE,GAAGC,eAAe,CAACJ;QACrC,OAAOA;IACT;IAEA,MAAMQ,iBAAiB,CAACR,MACrB,CAAA;YACCS,cAAc,IAAO,CAAA;oBACnBC,aAAa,IAAMV;gBACrB,CAAA;QAEF,CAAA;IAEFW,WAAW;QACT,MAAMC,YAAY,MAAMC,aAAI,CAACC,mBAAmB,CAAC;YAC/CC,WAAW;gBAACC,oCAAsB;aAAC;QACrC,GAAGC,OAAO;QAEVnB,SAASc,UAAUM,GAAG,CAACF,oCAAsB;IAC/C;IAEAG,UAAU;QACRjB,KAAKkB,aAAa;IACpB;IAEAC,GAAG,kEAAkE;QACnE,MAAMrB,MAAMD;QACZ,MAAMuB,OAAOd,eAAeR;QAC5B,MAAMuB,YAAY,IAAIC,qBAAa,CAAC,gBAAgB;QAEpD1B,OAAO2B,KAAK,CAACF,WAAWD;QAExBI,OAAO1B,IAAIC,MAAM,EAAE0B,oBAAoB,CAAC,oBAAoB,CAAC,aAAa,EAAEC,yBAAW,CAAC,CAAC,CAAC;QAC1FF,OAAO1B,IAAIM,MAAM,EAAEqB,oBAAoB,CAAC;QACxCD,OAAO1B,IAAIK,IAAI,EAAEwB,GAAG,CAACC,gBAAgB;QACrCJ,OAAO1B,IAAIO,IAAI,EAAEuB,gBAAgB;QACjC,yBAAyB;QACzBJ,OAAO1B,IAAIO,IAAI,CAACwB,IAAI,CAACC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAEC,aAAa;IACjD;IAEAZ,GAAG,uEAAuE;QACxE,MAAMrB,MAAMD;QACZ,MAAMuB,OAAOd,eAAeR;QAC5B,MAAMuB,YAAY,IAAIC,qBAAa,CAAC,kBAAkB;QAEtD1B,OAAO2B,KAAK,CAACF,WAAWD;QAExBI,OAAO1B,IAAIK,IAAI,EAAEsB,oBAAoB,CAACO,wBAAgB;QACtDR,OAAO1B,IAAIM,MAAM,EAAEqB,oBAAoB,CAAC;QACxCD,OAAO1B,IAAIO,IAAI,EAAEoB,oBAAoB,CAAC;QACtCD,OAAO1B,IAAIC,MAAM,EAAE4B,GAAG,CAACC,gBAAgB;IACzC;IAEAT,GAAG,gFAAgF;QACjF,MAAMrB,MAAMD;QACZ,MAAMuB,OAAOd,eAAeR;QAC5B,MAAMmC,UAAU;YAAEC,SAAS;QAA6B;QACxD,MAAMb,YAAY,IAAIC,qBAAa,CAACW,SAAS;QAE7CrC,OAAO2B,KAAK,CAACF,WAAWD;QAExBI,OAAO1B,IAAIK,IAAI,EAAEsB,oBAAoB,CAACO,wBAAgB;QACtDR,OAAO1B,IAAIM,MAAM,EAAEqB,oBAAoB,CAAC;QACxCD,OAAO1B,IAAIO,IAAI,EAAEoB,oBAAoB,CAACQ,QAAQC,OAAO;QACrDV,OAAO1B,IAAIC,MAAM,EAAE4B,GAAG,CAACC,gBAAgB;IACzC;AACF"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/webdav/filters/webdav.filter.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 */\nimport { ArgumentsHost, HttpException } from '@nestjs/common'\nimport { Test } from '@nestjs/testing'\nimport { SERVER_NAME } from '../../../common/shared'\nimport { XML_CONTENT_TYPE } from '../constants/webdav'\nimport { WebDAVExceptionsFilter } from './webdav.filter'\n\ndescribe('WebDAVExceptionsFilter', () => {\n let filter: WebDAVExceptionsFilter\n\n const createMockResponse = () => {\n const res: any = {}\n res.header = jest.fn().mockReturnValue(res)\n res.type = jest.fn().mockReturnValue(res)\n res.status = jest.fn().mockReturnValue(res)\n res.send = jest.fn().mockReturnValue(res)\n return res\n }\n\n const createMockHost = (res: any): ArgumentsHost =>\n ({\n switchToHttp: () => ({\n getResponse: () => res\n })\n // Other methods not used by the filter\n }) as unknown as ArgumentsHost\n\n beforeEach(async () => {\n const moduleRef = await Test.createTestingModule({\n providers: [WebDAVExceptionsFilter]\n }).compile()\n\n filter = moduleRef.get(WebDAVExceptionsFilter)\n })\n\n afterEach(() => {\n jest.clearAllMocks()\n })\n\n it('should set WWW-Authenticate header and send empty body for 401', () => {\n const res = createMockResponse()\n const host = createMockHost(res)\n const exception = new HttpException('Unauthorized', 401)\n\n filter.catch(exception, host)\n\n expect(res.header).toHaveBeenCalledWith('WWW-Authenticate', `Basic realm=\"${SERVER_NAME}\"`)\n expect(res.status).toHaveBeenCalledWith(401)\n expect(res.type).not.toHaveBeenCalled()\n expect(res.send).toHaveBeenCalled()\n // Ensure no body is sent\n expect(res.send.mock.calls[0][0]).toBeUndefined()\n })\n\n it('should set XML content type and forward string response for non-401', () => {\n const res = createMockResponse()\n const host = createMockHost(res)\n const exception = new HttpException('Internal error', 500)\n\n filter.catch(exception, host)\n\n expect(res.type).toHaveBeenCalledWith(XML_CONTENT_TYPE)\n expect(res.status).toHaveBeenCalledWith(500)\n expect(res.send).toHaveBeenCalledWith('Internal error')\n expect(res.header).not.toHaveBeenCalled()\n })\n\n it('should extract \"message\" from object response and send it as XML for non-401', () => {\n const res = createMockResponse()\n const host = createMockHost(res)\n const payload = { message: '<error>Bad Request</error>' }\n const exception = new HttpException(payload, 400)\n\n filter.catch(exception, host)\n\n expect(res.type).toHaveBeenCalledWith(XML_CONTENT_TYPE)\n expect(res.status).toHaveBeenCalledWith(400)\n expect(res.send).toHaveBeenCalledWith(payload.message)\n expect(res.header).not.toHaveBeenCalled()\n })\n})\n"],"names":["describe","filter","createMockResponse","res","header","jest","fn","mockReturnValue","type","status","send","createMockHost","switchToHttp","getResponse","beforeEach","moduleRef","Test","createTestingModule","providers","WebDAVExceptionsFilter","compile","get","afterEach","clearAllMocks","it","host","exception","HttpException","catch","expect","toHaveBeenCalledWith","SERVER_NAME","not","toHaveBeenCalled","mock","calls","toBeUndefined","XML_CONTENT_TYPE","payload","message"],"mappings":"AAAA;;;;CAIC;;;;wBAC4C;yBACxB;wBACO;wBACK;8BACM;AAEvCA,SAAS,0BAA0B;IACjC,IAAIC;IAEJ,MAAMC,qBAAqB;QACzB,MAAMC,MAAW,CAAC;QAClBA,IAAIC,MAAM,GAAGC,KAAKC,EAAE,GAAGC,eAAe,CAACJ;QACvCA,IAAIK,IAAI,GAAGH,KAAKC,EAAE,GAAGC,eAAe,CAACJ;QACrCA,IAAIM,MAAM,GAAGJ,KAAKC,EAAE,GAAGC,eAAe,CAACJ;QACvCA,IAAIO,IAAI,GAAGL,KAAKC,EAAE,GAAGC,eAAe,CAACJ;QACrC,OAAOA;IACT;IAEA,MAAMQ,iBAAiB,CAACR,MACrB,CAAA;YACCS,cAAc,IAAO,CAAA;oBACnBC,aAAa,IAAMV;gBACrB,CAAA;QAEF,CAAA;IAEFW,WAAW;QACT,MAAMC,YAAY,MAAMC,aAAI,CAACC,mBAAmB,CAAC;YAC/CC,WAAW;gBAACC,oCAAsB;aAAC;QACrC,GAAGC,OAAO;QAEVnB,SAASc,UAAUM,GAAG,CAACF,oCAAsB;IAC/C;IAEAG,UAAU;QACRjB,KAAKkB,aAAa;IACpB;IAEAC,GAAG,kEAAkE;QACnE,MAAMrB,MAAMD;QACZ,MAAMuB,OAAOd,eAAeR;QAC5B,MAAMuB,YAAY,IAAIC,qBAAa,CAAC,gBAAgB;QAEpD1B,OAAO2B,KAAK,CAACF,WAAWD;QAExBI,OAAO1B,IAAIC,MAAM,EAAE0B,oBAAoB,CAAC,oBAAoB,CAAC,aAAa,EAAEC,mBAAW,CAAC,CAAC,CAAC;QAC1FF,OAAO1B,IAAIM,MAAM,EAAEqB,oBAAoB,CAAC;QACxCD,OAAO1B,IAAIK,IAAI,EAAEwB,GAAG,CAACC,gBAAgB;QACrCJ,OAAO1B,IAAIO,IAAI,EAAEuB,gBAAgB;QACjC,yBAAyB;QACzBJ,OAAO1B,IAAIO,IAAI,CAACwB,IAAI,CAACC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAEC,aAAa;IACjD;IAEAZ,GAAG,uEAAuE;QACxE,MAAMrB,MAAMD;QACZ,MAAMuB,OAAOd,eAAeR;QAC5B,MAAMuB,YAAY,IAAIC,qBAAa,CAAC,kBAAkB;QAEtD1B,OAAO2B,KAAK,CAACF,WAAWD;QAExBI,OAAO1B,IAAIK,IAAI,EAAEsB,oBAAoB,CAACO,wBAAgB;QACtDR,OAAO1B,IAAIM,MAAM,EAAEqB,oBAAoB,CAAC;QACxCD,OAAO1B,IAAIO,IAAI,EAAEoB,oBAAoB,CAAC;QACtCD,OAAO1B,IAAIC,MAAM,EAAE4B,GAAG,CAACC,gBAAgB;IACzC;IAEAT,GAAG,gFAAgF;QACjF,MAAMrB,MAAMD;QACZ,MAAMuB,OAAOd,eAAeR;QAC5B,MAAMmC,UAAU;YAAEC,SAAS;QAA6B;QACxD,MAAMb,YAAY,IAAIC,qBAAa,CAACW,SAAS;QAE7CrC,OAAO2B,KAAK,CAACF,WAAWD;QAExBI,OAAO1B,IAAIK,IAAI,EAAEsB,oBAAoB,CAACO,wBAAgB;QACtDR,OAAO1B,IAAIM,MAAM,EAAEqB,oBAAoB,CAAC;QACxCD,OAAO1B,IAAIO,IAAI,EAAEoB,oBAAoB,CAACQ,QAAQC,OAAO;QACrDV,OAAO1B,IAAIC,MAAM,EAAE4B,GAAG,CAACC,gBAAgB;IACzC;AACF"}
@@ -420,12 +420,13 @@ let WebDAVMethods = class WebDAVMethods {
420
420
  }
421
421
  handleError(req, res, e, toUrl) {
422
422
  this.logger.error(`Unable to ${req.method} ${req.dav.url}${toUrl ? ` -> ${toUrl}` : ''} : ${e.message}`);
423
+ const errorMsg = e.message.split(',')[0];
423
424
  if (e instanceof _filelockerror.LockConflict) {
424
425
  return (0, _webdav1.DAV_ERROR_RES)(_common.HttpStatus.LOCKED, _webdav.PRECONDITION.LOCK_CONFLICT, res, e.lock.davLock?.lockroot || e.lock.dbFilePath);
425
426
  } else if (e instanceof _fileerror.FileError) {
426
- return res.status(e.httpCode).send(e.message);
427
+ return res.status(e.httpCode).send(errorMsg);
427
428
  }
428
- throw new _common.HttpException(e.message, _common.HttpStatus.INTERNAL_SERVER_ERROR);
429
+ throw new _common.HttpException(errorMsg, _common.HttpStatus.INTERNAL_SERVER_ERROR);
429
430
  }
430
431
  constructor(webDAVHandler, filesManager, filesLockManager){
431
432
  this.webDAVHandler = webDAVHandler;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/webdav/services/webdav-methods.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, StreamableFile } from '@nestjs/common'\nimport { FastifyReply } from 'fastify'\nimport { currentTimeStamp, encodeUrl } from '../../../common/shared'\nimport { FileLock } from '../../files/interfaces/file-lock.interface'\nimport { FileError } from '../../files/models/file-error'\nimport { LockConflict } from '../../files/models/file-lock-error'\nimport { FilesLockManager } from '../../files/services/files-lock-manager.service'\nimport { FilesManager } from '../../files/services/files-manager.service'\nimport { dirName, genEtag, isPathExists } from '../../files/utils/files'\nimport { SPACE_OPERATION, SPACE_REPOSITORY } from '../../spaces/constants/spaces'\nimport { SpaceEnv } from '../../spaces/models/space-env.model'\nimport { dbFileFromSpace } from '../../spaces/utils/paths'\nimport { haveSpaceEnvPermissions } from '../../spaces/utils/permissions'\nimport {\n DEPTH,\n LOCK_DISCOVERY_PROP,\n NS_PREFIX,\n PRECONDITION,\n PROPPATCH_METHOD,\n PROPPATCH_MODIFIED_PROPS,\n PROPPATCH_PROP_UPDATE,\n PROPPATCH_SUPPORTED_PROPS,\n PROPSTAT,\n STANDARD_PROPS,\n XML_CONTENT_TYPE\n} from '../constants/webdav'\nimport { IfHeaderDecorator } from '../decorators/if-header.decorator'\nimport { FastifyDAVRequest, WebDAVLock } from '../interfaces/webdav.interface'\nimport { extractAllTokens, extractOneToken } from '../utils/if-header'\nimport { DAV_ERROR_RES, LOCK_DISCOVERY, LOCK_PROP, MULTI_STATUS, PROP, PROP_STAT } from '../utils/webdav'\nimport { xmlBuild } from '../utils/xml'\nimport { WebDAVSpaces } from './webdav-spaces.service'\n\n@Injectable()\nexport class WebDAVMethods {\n private readonly logger = new Logger(WebDAVMethods.name)\n\n constructor(\n private readonly webDAVHandler: WebDAVSpaces,\n private readonly filesManager: FilesManager,\n private readonly filesLockManager: FilesLockManager\n ) {}\n\n async headOrGet(req: FastifyDAVRequest, res: FastifyReply, repository: string): Promise<StreamableFile> {\n if (repository === SPACE_REPOSITORY.FILES && !req.space.inSharesList) {\n const sendFile = this.filesManager.sendFileFromSpace(req.space)\n try {\n await sendFile.checks()\n return await sendFile.stream(req, res)\n } catch (e) {\n return this.handleError(req, res, e)\n }\n }\n this.logger.warn(`Not allowed on this resource : ${repository}`)\n return res.status(HttpStatus.FORBIDDEN).send('Not allowed on this resource')\n }\n\n @IfHeaderDecorator()\n async lock(req: FastifyDAVRequest, res: FastifyReply) {\n const isLockRefresh = !req.dav.body\n const rExists = await isPathExists(req.space.realPath)\n\n if (isLockRefresh) {\n // if the body has no content, the request must refresh the lock\n if (!rExists) {\n this.logger.warn('Lock refresh must specify an existing resource')\n return res.status(HttpStatus.BAD_REQUEST).send('Lock refresh must specify an existing resource')\n }\n return this.lockRefresh(req, res, req.space.dbFile.path)\n }\n if (!rExists) {\n if (!haveSpaceEnvPermissions(req.space, SPACE_OPERATION.ADD)) {\n this.logger.warn(`is not allowed to create on this space : *${req.space.alias}* (${req.space.id}) : ${req.space.url}`)\n return res.status(HttpStatus.FORBIDDEN).send('You are not allowed to do this action')\n }\n if (!(await isPathExists(dirName(req.space.realPath)))) {\n return res.status(HttpStatus.CONFLICT).send('Parent must exists')\n }\n }\n\n const davLock: WebDAVLock = {\n lockroot: req.dav.url,\n locktoken: null, // created later\n lockscope: req.dav.lock.lockscope,\n owner: req.dav.lock.owner\n }\n\n const [ok, fileLock] = await this.filesLockManager.create(req.user, req.space.dbFile, req.dav.depth, req.dav.lock.timeout, davLock)\n if (ok) {\n // Locking unmapped URLs: must create an empty resource (that is not a collection)\n if (!rExists) {\n // checkLocks set to false because the conflicts are already checked in `filesLockManager.create` method\n await this.filesManager.mkFile(req.user, req.space, false, false, false)\n }\n const lockProp = LOCK_PROP([fileLock])\n return res\n .header('lock-token', `<${davLock.locktoken}>`)\n .type(XML_CONTENT_TYPE)\n .status(rExists ? HttpStatus.OK : HttpStatus.CREATED)\n .send(xmlBuild(lockProp))\n } else {\n return DAV_ERROR_RES(HttpStatus.LOCKED, PRECONDITION.LOCK_CONFLICT, res, fileLock.davLock?.lockroot || fileLock.dbFilePath)\n }\n }\n\n @IfHeaderDecorator()\n async unlock(req: FastifyDAVRequest, res: FastifyReply) {\n if (!(await isPathExists(req.space.realPath))) {\n this.logger.warn(`Unable to unlock ${req.dav.url} : resource does not exist`)\n return res.status(HttpStatus.NOT_FOUND).send(req.dav.url)\n }\n\n const lock = await this.filesLockManager.isLockedWithToken(req.dav.lock.token, req.space.dbFile.path)\n if (!lock) {\n this.logger.warn(`Lock token does not exist or not match URL : ${req.dav.lock.token}`)\n return DAV_ERROR_RES(HttpStatus.CONFLICT, PRECONDITION.LOCK_TOKEN_MISMATCH, res)\n }\n if (req.user.id !== lock.owner.id) {\n return res.status(HttpStatus.FORBIDDEN).send('Token was created by another user')\n }\n\n await this.filesLockManager.removeLock(lock.key)\n return res.status(HttpStatus.NO_CONTENT).send()\n }\n\n @IfHeaderDecorator()\n async propfind(req: FastifyDAVRequest, res: FastifyReply, repository: string): Promise<string> {\n if (repository === SPACE_REPOSITORY.FILES && !req.space.inSharesList) {\n if (!(await isPathExists(req.space.realPath))) {\n return res.status(HttpStatus.NOT_FOUND).send(req.dav.url)\n }\n }\n\n const responses: any[] = []\n let requestedProps: string[]\n let locks: Record<string, FileLock> = {}\n\n if (req.dav.propfindMode === PROPSTAT.PROP) {\n // ignores all unknown properties (non-RFC compliant but avoids generating too much content, faster)\n requestedProps = Object.keys(req.dav.body.propfind.prop).filter((prop: string) => STANDARD_PROPS.indexOf(prop) > -1)\n } else {\n requestedProps = STANDARD_PROPS\n }\n\n // Searches all child locks (only for real files) & ignores /webdav/shares endpoint (special case)\n if (req.dav.propfindMode !== PROPSTAT.PROPNAME && repository === SPACE_REPOSITORY.FILES && !req.space.inSharesList) {\n if (req.dav.depth === DEPTH.RESOURCE) {\n // match depth '0'\n locks = await this.filesLockManager.browseLocks(req.space.dbFile)\n } else {\n // match depth '1' or 'infinity'\n locks = await this.filesLockManager.browseParentChildLocks(req.space.dbFile)\n }\n }\n\n for await (const f of this.webDAVHandler.propfind(req, repository)) {\n let prop: any\n if (req.dav.propfindMode === PROPSTAT.PROPNAME) {\n prop = { ...Object.fromEntries(requestedProps.map((x) => [`${NS_PREFIX}:${x}`, ''])) }\n } else {\n prop = {}\n for (const p of requestedProps) {\n let fP: any\n if (p === LOCK_DISCOVERY_PROP) {\n fP = repository === SPACE_REPOSITORY.FILES && f.name in locks ? LOCK_DISCOVERY([locks[f.name]]) : null\n } else {\n fP = f[p]\n }\n if (fP !== undefined) prop[`${NS_PREFIX}:${p}`] = fP\n }\n }\n responses.push(PROP_STAT(f.href, PROP(prop, req.dav.httpVersion, HttpStatus.OK)))\n }\n const propfind = xmlBuild(MULTI_STATUS(responses))\n return res.type(XML_CONTENT_TYPE).status(HttpStatus.MULTI_STATUS).send(propfind)\n }\n\n @IfHeaderDecorator()\n async put(req: FastifyDAVRequest, res: FastifyReply): Promise<FastifyReply> {\n let rExists: boolean\n try {\n rExists = await this.filesManager.saveStream(req.user, req.space, req, {\n dav: {\n depth: req.dav.depth,\n lockTokens: extractAllTokens(req.dav.ifHeaders)\n }\n })\n } catch (e) {\n return this.handleError(req, res, e)\n }\n return res\n .header('etag', genEtag(null, req.space.realPath))\n .status(rExists ? HttpStatus.NO_CONTENT : HttpStatus.CREATED)\n .send()\n }\n\n @IfHeaderDecorator()\n async delete(req: FastifyDAVRequest, res: FastifyReply) {\n try {\n await this.filesManager.delete(req.user, req.space, { lockTokens: extractAllTokens(req.dav.ifHeaders) })\n } catch (e) {\n return this.handleError(req, res, e)\n }\n return res.status(HttpStatus.NO_CONTENT).send()\n }\n\n @IfHeaderDecorator()\n async proppatch(req: FastifyDAVRequest, res: FastifyReply) {\n /* only support 'time modifications' */\n if (!(await isPathExists(req.space.realPath))) {\n return res.status(HttpStatus.NOT_FOUND).send(req.dav.url)\n }\n\n // check locks\n try {\n await this.filesLockManager.checkConflicts(req.space.dbFile, req.dav.depth, {\n userId: req.user.id,\n lockTokens: extractAllTokens(req.dav.ifHeaders)\n })\n } catch (e) {\n return this.handleError(req, res, e)\n }\n\n // evaluate props and return multistatus if errors\n req.dav.proppatch = { props: {}, errors: [] }\n for (const action of Object.keys(req.dav.body[PROPPATCH_PROP_UPDATE])) {\n if (Object.values(PROPPATCH_METHOD).indexOf(action) === -1) {\n const msg = `Unknown tag : expected ${PROPPATCH_METHOD.SET} or ${PROPPATCH_METHOD.REMOVE}`\n this.logger.debug(msg)\n return res.status(HttpStatus.BAD_REQUEST).send(msg)\n }\n\n if (Array.isArray(req.dav.body[PROPPATCH_PROP_UPDATE][action])) {\n if (Object.keys(req.dav.body[PROPPATCH_PROP_UPDATE][action][0])[0] === PROPSTAT.PROP) {\n req.dav.body[PROPPATCH_PROP_UPDATE][action] = {\n [PROPSTAT.PROP]: req.dav.body[PROPPATCH_PROP_UPDATE][action].map((e: any) => e[PROPSTAT.PROP])\n }\n }\n }\n\n if (Object.keys(req.dav.body[PROPPATCH_PROP_UPDATE][action])[0] !== PROPSTAT.PROP) {\n const msg = `Unknown tag : expected ${PROPSTAT.PROP}`\n this.logger.debug(msg)\n return res.status(HttpStatus.BAD_REQUEST).send(msg)\n }\n\n if (!Array.isArray(req.dav.body[PROPPATCH_PROP_UPDATE][action][PROPSTAT.PROP])) {\n req.dav.body[PROPPATCH_PROP_UPDATE][action][PROPSTAT.PROP] = [req.dav.body[PROPPATCH_PROP_UPDATE][action][PROPSTAT.PROP]]\n }\n\n for (const prop of req.dav.body[PROPPATCH_PROP_UPDATE][action][PROPSTAT.PROP] as Record<string, string>[]) {\n for (let [name, value] of Object.entries(prop)) {\n if (action === PROPPATCH_METHOD.REMOVE) {\n value = null\n this.logger.debug(`Proppatch remove method not handled : ${name} -> ${value}`)\n }\n if (PROPPATCH_SUPPORTED_PROPS.indexOf(name) === -1) {\n req.dav.proppatch.errors.push(\n PROP(\n { [`${NS_PREFIX}:${name}`]: null },\n req.dav.httpVersion,\n HttpStatus.FORBIDDEN,\n STANDARD_PROPS.indexOf(name) > -1 ? PRECONDITION.PROTECTED_PROPERTY : undefined\n )\n )\n continue\n }\n req.dav.proppatch.props[name] = value\n }\n }\n }\n\n if (req.dav.proppatch.errors.length) {\n // convert all passed props to failed dependency\n for (const name of Object.keys(req.dav.proppatch.props)) {\n req.dav.proppatch.errors.push(PROP({ [`${NS_PREFIX}:${name}`]: null }, req.dav.httpVersion, HttpStatus.FAILED_DEPENDENCY))\n }\n const proppatch = xmlBuild(MULTI_STATUS(PROP_STAT(encodeUrl(req.dav.url), req.dav.proppatch.errors)))\n return res.status(HttpStatus.MULTI_STATUS).type(XML_CONTENT_TYPE).send(proppatch)\n }\n\n // apply modifications\n let atLeastOneError = false\n const states: Record<string, boolean> = {}\n for (const [name, value] of Object.entries(req.dav.proppatch.props)) {\n if (PROPPATCH_MODIFIED_PROPS.indexOf(name) > -1) {\n try {\n await this.filesManager.touch(req.user, req.space, currentTimeStamp(new Date(value)), false)\n } catch (e) {\n this.logger.error(`${this.proppatch.name} - unable to modify mtime on ${req.dav.url} : ${e}`)\n states[name] = false\n atLeastOneError = true\n }\n }\n // hook: we let the known Win32* properties pass to return a consistent result\n states[name] = true\n }\n\n const props = []\n for (const [name, state] of Object.entries(states)) {\n props.push(\n PROP(\n { [`${NS_PREFIX}:${name}`]: null },\n req.dav.httpVersion,\n state ? (atLeastOneError ? HttpStatus.FAILED_DEPENDENCY : HttpStatus.OK) : HttpStatus.BAD_REQUEST\n )\n )\n }\n const proppatch = xmlBuild(MULTI_STATUS(PROP_STAT(encodeUrl(req.dav.url), props)))\n return res.type(XML_CONTENT_TYPE).status(HttpStatus.MULTI_STATUS).send(proppatch)\n }\n\n @IfHeaderDecorator()\n async mkcol(req: FastifyDAVRequest, res: FastifyReply) {\n try {\n await this.filesManager.mkDir(req.user, req.space, false, { depth: req.dav.depth, lockTokens: extractAllTokens(req.dav.ifHeaders) })\n } catch (e) {\n return this.handleError(req, res, e)\n }\n return res.status(HttpStatus.CREATED).send()\n }\n\n @IfHeaderDecorator()\n async copyMove(req: FastifyDAVRequest, res: FastifyReply) {\n const dstSpace: SpaceEnv = await this.webDAVHandler.spaceEnv(req.user, req.dav.copyMove.destination)\n if (!dstSpace) {\n this.logger.warn(`Space not found for destination : ${req.dav.copyMove.destination}`)\n return res.status(HttpStatus.NOT_FOUND).send(req.dav.copyMove.destination)\n }\n const dstExisted = await isPathExists(dstSpace.realPath)\n // We must evaluate the if-headers on the destination\n const fakeDstReq = {\n dav: { ...req.dav, url: req.dav.copyMove.destination },\n user: req.user,\n space: dstSpace\n } as FastifyDAVRequest\n if (!(await this.evaluateIfHeaders(fakeDstReq, res))) {\n // if there is an error the response is generated inside the `evaluateIfHeaders` function\n return\n }\n try {\n await this.filesManager.copyMove(req.user, req.space, dstSpace, req.dav.copyMove.isMove, req.dav.copyMove.overwrite, false, {\n depth: req.dav.depth,\n lockTokens: extractAllTokens(req.dav.ifHeaders)\n })\n } catch (e) {\n return this.handleError(req, res, e, dstSpace.url)\n }\n return res.status(dstExisted ? HttpStatus.NO_CONTENT : HttpStatus.CREATED).send()\n }\n\n protected async evaluateIfHeaders(req: FastifyDAVRequest, res: FastifyReply): Promise<boolean> {\n if (!req.dav.ifHeaders) return true\n const errors: string[] = []\n let lastPath = null\n let lastSpaceEnv: SpaceEnv\n let lastRPath = undefined\n let lastEtag = undefined // for now, we only generate one etag type (weak)\n let atLeastOneOk = false\n\n for (const condition of req.dav.ifHeaders) {\n if (condition.path) {\n if (condition.path !== lastPath) {\n lastPath = condition.path\n lastSpaceEnv = await this.webDAVHandler.spaceEnv(req.user, lastPath)\n }\n // the path will be the same across conditions\n if (!lastSpaceEnv) {\n this.logger.warn(`If Header : path mismatch (${condition.path})`)\n return false\n }\n } else {\n lastPath = req.dav.url\n lastSpaceEnv = req.space\n }\n\n if (condition.haveLock) {\n try {\n const dbFile = dbFileFromSpace(req.user.id, lastSpaceEnv)\n const match = !!(await this.filesLockManager.getLocksByPath(dbFile)).length\n if (condition.haveLock.mustMatch !== match) {\n errors.push(`have lock condition mismatch (${condition.haveLock.mustMatch} != ${match})`)\n continue\n }\n } catch (e) {\n errors.push(`have lock condition mismatch : ${e.message}`)\n continue\n }\n }\n\n if (condition.token) {\n const token = await this.filesLockManager.getLockByToken(condition.token.value)\n const match = token && lastPath.startsWith(token.davLock?.lockroot)\n if (condition.token.mustMatch !== match) {\n if (!token) {\n errors.push(`lock token not found`)\n } else {\n errors.push(`lock token url mismatch (${lastPath} is not a child of ${token.davLock?.lockroot})`)\n }\n continue\n }\n }\n\n if (condition.etag) {\n if (lastEtag === undefined) {\n if (lastRPath === undefined) {\n lastRPath = (await isPathExists(req.space.realPath)) ? req.space.realPath : null\n }\n lastEtag = lastRPath ? genEtag(null, lastRPath) : null\n }\n const match = lastEtag === condition.etag.value\n if (condition.etag.mustMatch !== match) {\n errors.push(`etag mismatch (${condition.etag.value} != ${lastEtag})`)\n continue\n }\n }\n\n atLeastOneOk = true\n break\n }\n\n if (!atLeastOneOk) {\n this.logger.warn(`If header condition failed : ${errors.join(', ')}`)\n res.status(HttpStatus.PRECONDITION_FAILED).send('If header condition failed')\n }\n return atLeastOneOk\n }\n\n private async lockRefresh(req: FastifyDAVRequest, res: FastifyReply, dbFilePath: string) {\n if (req.dav?.ifHeaders?.length !== 1) {\n this.logger.warn('Expected a lock token (only one lock may be refreshed at a time)')\n return res.status(HttpStatus.BAD_REQUEST).send('Expected a lock token (only one lock may be refreshed at a time)')\n }\n\n let token: string\n try {\n token = extractOneToken(req.dav.ifHeaders)\n } catch (e) {\n this.logger.warn(`${this.lockRefresh.name} - unable to extract token : ${JSON.stringify(req.dav.ifHeaders)} (${e})`)\n return res.status(HttpStatus.BAD_REQUEST).send('Unable to extract token')\n }\n\n const lock = await this.filesLockManager.isLockedWithToken(token, dbFilePath)\n if (!lock) {\n this.logger.warn(`Lock token does not exist or not match URL : ${token}`)\n return DAV_ERROR_RES(HttpStatus.PRECONDITION_FAILED, PRECONDITION.LOCK_TOKEN_MISMATCH, res)\n }\n if (lock.owner.id !== req.user.id) {\n this.logger.warn(`Lock token does not match owner : ${lock.owner.login} != ${req.user.login}`)\n return res.status(HttpStatus.FORBIDDEN).send('Lock token does not match owner')\n }\n\n await this.filesLockManager.refreshLockTimeout(lock, req.dav.lock.timeout)\n const lockProp = LOCK_PROP([lock])\n return res.type(XML_CONTENT_TYPE).status(HttpStatus.OK).send(xmlBuild(lockProp))\n }\n\n private handleError(req: FastifyDAVRequest, res: FastifyReply, e: any, toUrl?: string) {\n this.logger.error(`Unable to ${req.method} ${req.dav.url}${toUrl ? ` -> ${toUrl}` : ''} : ${e.message}`)\n if (e instanceof LockConflict) {\n return DAV_ERROR_RES(HttpStatus.LOCKED, PRECONDITION.LOCK_CONFLICT, res, e.lock.davLock?.lockroot || e.lock.dbFilePath)\n } else if (e instanceof FileError) {\n return res.status(e.httpCode).send(e.message)\n }\n throw new HttpException(e.message, HttpStatus.INTERNAL_SERVER_ERROR)\n }\n}\n"],"names":["WebDAVMethods","headOrGet","req","res","repository","SPACE_REPOSITORY","FILES","space","inSharesList","sendFile","filesManager","sendFileFromSpace","checks","stream","e","handleError","logger","warn","status","HttpStatus","FORBIDDEN","send","lock","isLockRefresh","dav","body","rExists","isPathExists","realPath","BAD_REQUEST","lockRefresh","dbFile","path","haveSpaceEnvPermissions","SPACE_OPERATION","ADD","alias","id","url","dirName","CONFLICT","davLock","lockroot","locktoken","lockscope","owner","ok","fileLock","filesLockManager","create","user","depth","timeout","mkFile","lockProp","LOCK_PROP","header","type","XML_CONTENT_TYPE","OK","CREATED","xmlBuild","DAV_ERROR_RES","LOCKED","PRECONDITION","LOCK_CONFLICT","dbFilePath","unlock","NOT_FOUND","isLockedWithToken","token","LOCK_TOKEN_MISMATCH","removeLock","key","NO_CONTENT","propfind","responses","requestedProps","locks","propfindMode","PROPSTAT","PROP","Object","keys","prop","filter","STANDARD_PROPS","indexOf","PROPNAME","DEPTH","RESOURCE","browseLocks","browseParentChildLocks","f","webDAVHandler","fromEntries","map","x","NS_PREFIX","p","fP","LOCK_DISCOVERY_PROP","name","LOCK_DISCOVERY","undefined","push","PROP_STAT","href","httpVersion","MULTI_STATUS","put","saveStream","lockTokens","extractAllTokens","ifHeaders","genEtag","delete","proppatch","checkConflicts","userId","props","errors","action","PROPPATCH_PROP_UPDATE","values","PROPPATCH_METHOD","msg","SET","REMOVE","debug","Array","isArray","value","entries","PROPPATCH_SUPPORTED_PROPS","PROTECTED_PROPERTY","length","FAILED_DEPENDENCY","encodeUrl","atLeastOneError","states","PROPPATCH_MODIFIED_PROPS","touch","currentTimeStamp","Date","error","state","mkcol","mkDir","copyMove","dstSpace","spaceEnv","destination","dstExisted","fakeDstReq","evaluateIfHeaders","isMove","overwrite","lastPath","lastSpaceEnv","lastRPath","lastEtag","atLeastOneOk","condition","haveLock","dbFileFromSpace","match","getLocksByPath","mustMatch","message","getLockByToken","startsWith","etag","join","PRECONDITION_FAILED","extractOneToken","JSON","stringify","login","refreshLockTimeout","toUrl","method","LockConflict","FileError","httpCode","HttpException","INTERNAL_SERVER_ERROR","Logger"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/webdav/services/webdav-methods.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, StreamableFile } from '@nestjs/common'\nimport { FastifyReply } from 'fastify'\nimport { currentTimeStamp, encodeUrl } from '../../../common/shared'\nimport { FileLock } from '../../files/interfaces/file-lock.interface'\nimport { FileError } from '../../files/models/file-error'\nimport { LockConflict } from '../../files/models/file-lock-error'\nimport { FilesLockManager } from '../../files/services/files-lock-manager.service'\nimport { FilesManager } from '../../files/services/files-manager.service'\nimport { dirName, genEtag, isPathExists } from '../../files/utils/files'\nimport { SPACE_OPERATION, SPACE_REPOSITORY } from '../../spaces/constants/spaces'\nimport { SpaceEnv } from '../../spaces/models/space-env.model'\nimport { dbFileFromSpace } from '../../spaces/utils/paths'\nimport { haveSpaceEnvPermissions } from '../../spaces/utils/permissions'\nimport {\n DEPTH,\n LOCK_DISCOVERY_PROP,\n NS_PREFIX,\n PRECONDITION,\n PROPPATCH_METHOD,\n PROPPATCH_MODIFIED_PROPS,\n PROPPATCH_PROP_UPDATE,\n PROPPATCH_SUPPORTED_PROPS,\n PROPSTAT,\n STANDARD_PROPS,\n XML_CONTENT_TYPE\n} from '../constants/webdav'\nimport { IfHeaderDecorator } from '../decorators/if-header.decorator'\nimport { FastifyDAVRequest, WebDAVLock } from '../interfaces/webdav.interface'\nimport { extractAllTokens, extractOneToken } from '../utils/if-header'\nimport { DAV_ERROR_RES, LOCK_DISCOVERY, LOCK_PROP, MULTI_STATUS, PROP, PROP_STAT } from '../utils/webdav'\nimport { xmlBuild } from '../utils/xml'\nimport { WebDAVSpaces } from './webdav-spaces.service'\n\n@Injectable()\nexport class WebDAVMethods {\n private readonly logger = new Logger(WebDAVMethods.name)\n\n constructor(\n private readonly webDAVHandler: WebDAVSpaces,\n private readonly filesManager: FilesManager,\n private readonly filesLockManager: FilesLockManager\n ) {}\n\n async headOrGet(req: FastifyDAVRequest, res: FastifyReply, repository: string): Promise<StreamableFile> {\n if (repository === SPACE_REPOSITORY.FILES && !req.space.inSharesList) {\n const sendFile = this.filesManager.sendFileFromSpace(req.space)\n try {\n await sendFile.checks()\n return await sendFile.stream(req, res)\n } catch (e) {\n return this.handleError(req, res, e)\n }\n }\n this.logger.warn(`Not allowed on this resource : ${repository}`)\n return res.status(HttpStatus.FORBIDDEN).send('Not allowed on this resource')\n }\n\n @IfHeaderDecorator()\n async lock(req: FastifyDAVRequest, res: FastifyReply) {\n const isLockRefresh = !req.dav.body\n const rExists = await isPathExists(req.space.realPath)\n\n if (isLockRefresh) {\n // if the body has no content, the request must refresh the lock\n if (!rExists) {\n this.logger.warn('Lock refresh must specify an existing resource')\n return res.status(HttpStatus.BAD_REQUEST).send('Lock refresh must specify an existing resource')\n }\n return this.lockRefresh(req, res, req.space.dbFile.path)\n }\n if (!rExists) {\n if (!haveSpaceEnvPermissions(req.space, SPACE_OPERATION.ADD)) {\n this.logger.warn(`is not allowed to create on this space : *${req.space.alias}* (${req.space.id}) : ${req.space.url}`)\n return res.status(HttpStatus.FORBIDDEN).send('You are not allowed to do this action')\n }\n if (!(await isPathExists(dirName(req.space.realPath)))) {\n return res.status(HttpStatus.CONFLICT).send('Parent must exists')\n }\n }\n\n const davLock: WebDAVLock = {\n lockroot: req.dav.url,\n locktoken: null, // created later\n lockscope: req.dav.lock.lockscope,\n owner: req.dav.lock.owner\n }\n\n const [ok, fileLock] = await this.filesLockManager.create(req.user, req.space.dbFile, req.dav.depth, req.dav.lock.timeout, davLock)\n if (ok) {\n // Locking unmapped URLs: must create an empty resource (that is not a collection)\n if (!rExists) {\n // checkLocks set to false because the conflicts are already checked in `filesLockManager.create` method\n await this.filesManager.mkFile(req.user, req.space, false, false, false)\n }\n const lockProp = LOCK_PROP([fileLock])\n return res\n .header('lock-token', `<${davLock.locktoken}>`)\n .type(XML_CONTENT_TYPE)\n .status(rExists ? HttpStatus.OK : HttpStatus.CREATED)\n .send(xmlBuild(lockProp))\n } else {\n return DAV_ERROR_RES(HttpStatus.LOCKED, PRECONDITION.LOCK_CONFLICT, res, fileLock.davLock?.lockroot || fileLock.dbFilePath)\n }\n }\n\n @IfHeaderDecorator()\n async unlock(req: FastifyDAVRequest, res: FastifyReply) {\n if (!(await isPathExists(req.space.realPath))) {\n this.logger.warn(`Unable to unlock ${req.dav.url} : resource does not exist`)\n return res.status(HttpStatus.NOT_FOUND).send(req.dav.url)\n }\n\n const lock = await this.filesLockManager.isLockedWithToken(req.dav.lock.token, req.space.dbFile.path)\n if (!lock) {\n this.logger.warn(`Lock token does not exist or not match URL : ${req.dav.lock.token}`)\n return DAV_ERROR_RES(HttpStatus.CONFLICT, PRECONDITION.LOCK_TOKEN_MISMATCH, res)\n }\n if (req.user.id !== lock.owner.id) {\n return res.status(HttpStatus.FORBIDDEN).send('Token was created by another user')\n }\n\n await this.filesLockManager.removeLock(lock.key)\n return res.status(HttpStatus.NO_CONTENT).send()\n }\n\n @IfHeaderDecorator()\n async propfind(req: FastifyDAVRequest, res: FastifyReply, repository: string): Promise<string> {\n if (repository === SPACE_REPOSITORY.FILES && !req.space.inSharesList) {\n if (!(await isPathExists(req.space.realPath))) {\n return res.status(HttpStatus.NOT_FOUND).send(req.dav.url)\n }\n }\n\n const responses: any[] = []\n let requestedProps: string[]\n let locks: Record<string, FileLock> = {}\n\n if (req.dav.propfindMode === PROPSTAT.PROP) {\n // ignores all unknown properties (non-RFC compliant but avoids generating too much content, faster)\n requestedProps = Object.keys(req.dav.body.propfind.prop).filter((prop: string) => STANDARD_PROPS.indexOf(prop) > -1)\n } else {\n requestedProps = STANDARD_PROPS\n }\n\n // Searches all child locks (only for real files) & ignores /webdav/shares endpoint (special case)\n if (req.dav.propfindMode !== PROPSTAT.PROPNAME && repository === SPACE_REPOSITORY.FILES && !req.space.inSharesList) {\n if (req.dav.depth === DEPTH.RESOURCE) {\n // match depth '0'\n locks = await this.filesLockManager.browseLocks(req.space.dbFile)\n } else {\n // match depth '1' or 'infinity'\n locks = await this.filesLockManager.browseParentChildLocks(req.space.dbFile)\n }\n }\n\n for await (const f of this.webDAVHandler.propfind(req, repository)) {\n let prop: any\n if (req.dav.propfindMode === PROPSTAT.PROPNAME) {\n prop = { ...Object.fromEntries(requestedProps.map((x) => [`${NS_PREFIX}:${x}`, ''])) }\n } else {\n prop = {}\n for (const p of requestedProps) {\n let fP: any\n if (p === LOCK_DISCOVERY_PROP) {\n fP = repository === SPACE_REPOSITORY.FILES && f.name in locks ? LOCK_DISCOVERY([locks[f.name]]) : null\n } else {\n fP = f[p]\n }\n if (fP !== undefined) prop[`${NS_PREFIX}:${p}`] = fP\n }\n }\n responses.push(PROP_STAT(f.href, PROP(prop, req.dav.httpVersion, HttpStatus.OK)))\n }\n const propfind = xmlBuild(MULTI_STATUS(responses))\n return res.type(XML_CONTENT_TYPE).status(HttpStatus.MULTI_STATUS).send(propfind)\n }\n\n @IfHeaderDecorator()\n async put(req: FastifyDAVRequest, res: FastifyReply): Promise<FastifyReply> {\n let rExists: boolean\n try {\n rExists = await this.filesManager.saveStream(req.user, req.space, req, {\n dav: {\n depth: req.dav.depth,\n lockTokens: extractAllTokens(req.dav.ifHeaders)\n }\n })\n } catch (e) {\n return this.handleError(req, res, e)\n }\n return res\n .header('etag', genEtag(null, req.space.realPath))\n .status(rExists ? HttpStatus.NO_CONTENT : HttpStatus.CREATED)\n .send()\n }\n\n @IfHeaderDecorator()\n async delete(req: FastifyDAVRequest, res: FastifyReply) {\n try {\n await this.filesManager.delete(req.user, req.space, { lockTokens: extractAllTokens(req.dav.ifHeaders) })\n } catch (e) {\n return this.handleError(req, res, e)\n }\n return res.status(HttpStatus.NO_CONTENT).send()\n }\n\n @IfHeaderDecorator()\n async proppatch(req: FastifyDAVRequest, res: FastifyReply) {\n /* only support 'time modifications' */\n if (!(await isPathExists(req.space.realPath))) {\n return res.status(HttpStatus.NOT_FOUND).send(req.dav.url)\n }\n\n // check locks\n try {\n await this.filesLockManager.checkConflicts(req.space.dbFile, req.dav.depth, {\n userId: req.user.id,\n lockTokens: extractAllTokens(req.dav.ifHeaders)\n })\n } catch (e) {\n return this.handleError(req, res, e)\n }\n\n // evaluate props and return multistatus if errors\n req.dav.proppatch = { props: {}, errors: [] }\n for (const action of Object.keys(req.dav.body[PROPPATCH_PROP_UPDATE])) {\n if (Object.values(PROPPATCH_METHOD).indexOf(action) === -1) {\n const msg = `Unknown tag : expected ${PROPPATCH_METHOD.SET} or ${PROPPATCH_METHOD.REMOVE}`\n this.logger.debug(msg)\n return res.status(HttpStatus.BAD_REQUEST).send(msg)\n }\n\n if (Array.isArray(req.dav.body[PROPPATCH_PROP_UPDATE][action])) {\n if (Object.keys(req.dav.body[PROPPATCH_PROP_UPDATE][action][0])[0] === PROPSTAT.PROP) {\n req.dav.body[PROPPATCH_PROP_UPDATE][action] = {\n [PROPSTAT.PROP]: req.dav.body[PROPPATCH_PROP_UPDATE][action].map((e: any) => e[PROPSTAT.PROP])\n }\n }\n }\n\n if (Object.keys(req.dav.body[PROPPATCH_PROP_UPDATE][action])[0] !== PROPSTAT.PROP) {\n const msg = `Unknown tag : expected ${PROPSTAT.PROP}`\n this.logger.debug(msg)\n return res.status(HttpStatus.BAD_REQUEST).send(msg)\n }\n\n if (!Array.isArray(req.dav.body[PROPPATCH_PROP_UPDATE][action][PROPSTAT.PROP])) {\n req.dav.body[PROPPATCH_PROP_UPDATE][action][PROPSTAT.PROP] = [req.dav.body[PROPPATCH_PROP_UPDATE][action][PROPSTAT.PROP]]\n }\n\n for (const prop of req.dav.body[PROPPATCH_PROP_UPDATE][action][PROPSTAT.PROP] as Record<string, string>[]) {\n for (let [name, value] of Object.entries(prop)) {\n if (action === PROPPATCH_METHOD.REMOVE) {\n value = null\n this.logger.debug(`Proppatch remove method not handled : ${name} -> ${value}`)\n }\n if (PROPPATCH_SUPPORTED_PROPS.indexOf(name) === -1) {\n req.dav.proppatch.errors.push(\n PROP(\n { [`${NS_PREFIX}:${name}`]: null },\n req.dav.httpVersion,\n HttpStatus.FORBIDDEN,\n STANDARD_PROPS.indexOf(name) > -1 ? PRECONDITION.PROTECTED_PROPERTY : undefined\n )\n )\n continue\n }\n req.dav.proppatch.props[name] = value\n }\n }\n }\n\n if (req.dav.proppatch.errors.length) {\n // convert all passed props to failed dependency\n for (const name of Object.keys(req.dav.proppatch.props)) {\n req.dav.proppatch.errors.push(PROP({ [`${NS_PREFIX}:${name}`]: null }, req.dav.httpVersion, HttpStatus.FAILED_DEPENDENCY))\n }\n const proppatch = xmlBuild(MULTI_STATUS(PROP_STAT(encodeUrl(req.dav.url), req.dav.proppatch.errors)))\n return res.status(HttpStatus.MULTI_STATUS).type(XML_CONTENT_TYPE).send(proppatch)\n }\n\n // apply modifications\n let atLeastOneError = false\n const states: Record<string, boolean> = {}\n for (const [name, value] of Object.entries(req.dav.proppatch.props)) {\n if (PROPPATCH_MODIFIED_PROPS.indexOf(name) > -1) {\n try {\n await this.filesManager.touch(req.user, req.space, currentTimeStamp(new Date(value)), false)\n } catch (e) {\n this.logger.error(`${this.proppatch.name} - unable to modify mtime on ${req.dav.url} : ${e}`)\n states[name] = false\n atLeastOneError = true\n }\n }\n // hook: we let the known Win32* properties pass to return a consistent result\n states[name] = true\n }\n\n const props = []\n for (const [name, state] of Object.entries(states)) {\n props.push(\n PROP(\n { [`${NS_PREFIX}:${name}`]: null },\n req.dav.httpVersion,\n state ? (atLeastOneError ? HttpStatus.FAILED_DEPENDENCY : HttpStatus.OK) : HttpStatus.BAD_REQUEST\n )\n )\n }\n const proppatch = xmlBuild(MULTI_STATUS(PROP_STAT(encodeUrl(req.dav.url), props)))\n return res.type(XML_CONTENT_TYPE).status(HttpStatus.MULTI_STATUS).send(proppatch)\n }\n\n @IfHeaderDecorator()\n async mkcol(req: FastifyDAVRequest, res: FastifyReply) {\n try {\n await this.filesManager.mkDir(req.user, req.space, false, { depth: req.dav.depth, lockTokens: extractAllTokens(req.dav.ifHeaders) })\n } catch (e) {\n return this.handleError(req, res, e)\n }\n return res.status(HttpStatus.CREATED).send()\n }\n\n @IfHeaderDecorator()\n async copyMove(req: FastifyDAVRequest, res: FastifyReply) {\n const dstSpace: SpaceEnv = await this.webDAVHandler.spaceEnv(req.user, req.dav.copyMove.destination)\n if (!dstSpace) {\n this.logger.warn(`Space not found for destination : ${req.dav.copyMove.destination}`)\n return res.status(HttpStatus.NOT_FOUND).send(req.dav.copyMove.destination)\n }\n const dstExisted = await isPathExists(dstSpace.realPath)\n // We must evaluate the if-headers on the destination\n const fakeDstReq = {\n dav: { ...req.dav, url: req.dav.copyMove.destination },\n user: req.user,\n space: dstSpace\n } as FastifyDAVRequest\n if (!(await this.evaluateIfHeaders(fakeDstReq, res))) {\n // if there is an error the response is generated inside the `evaluateIfHeaders` function\n return\n }\n try {\n await this.filesManager.copyMove(req.user, req.space, dstSpace, req.dav.copyMove.isMove, req.dav.copyMove.overwrite, false, {\n depth: req.dav.depth,\n lockTokens: extractAllTokens(req.dav.ifHeaders)\n })\n } catch (e) {\n return this.handleError(req, res, e, dstSpace.url)\n }\n return res.status(dstExisted ? HttpStatus.NO_CONTENT : HttpStatus.CREATED).send()\n }\n\n protected async evaluateIfHeaders(req: FastifyDAVRequest, res: FastifyReply): Promise<boolean> {\n if (!req.dav.ifHeaders) return true\n const errors: string[] = []\n let lastPath = null\n let lastSpaceEnv: SpaceEnv\n let lastRPath = undefined\n let lastEtag = undefined // for now, we only generate one etag type (weak)\n let atLeastOneOk = false\n\n for (const condition of req.dav.ifHeaders) {\n if (condition.path) {\n if (condition.path !== lastPath) {\n lastPath = condition.path\n lastSpaceEnv = await this.webDAVHandler.spaceEnv(req.user, lastPath)\n }\n // the path will be the same across conditions\n if (!lastSpaceEnv) {\n this.logger.warn(`If Header : path mismatch (${condition.path})`)\n return false\n }\n } else {\n lastPath = req.dav.url\n lastSpaceEnv = req.space\n }\n\n if (condition.haveLock) {\n try {\n const dbFile = dbFileFromSpace(req.user.id, lastSpaceEnv)\n const match = !!(await this.filesLockManager.getLocksByPath(dbFile)).length\n if (condition.haveLock.mustMatch !== match) {\n errors.push(`have lock condition mismatch (${condition.haveLock.mustMatch} != ${match})`)\n continue\n }\n } catch (e) {\n errors.push(`have lock condition mismatch : ${e.message}`)\n continue\n }\n }\n\n if (condition.token) {\n const token = await this.filesLockManager.getLockByToken(condition.token.value)\n const match = token && lastPath.startsWith(token.davLock?.lockroot)\n if (condition.token.mustMatch !== match) {\n if (!token) {\n errors.push(`lock token not found`)\n } else {\n errors.push(`lock token url mismatch (${lastPath} is not a child of ${token.davLock?.lockroot})`)\n }\n continue\n }\n }\n\n if (condition.etag) {\n if (lastEtag === undefined) {\n if (lastRPath === undefined) {\n lastRPath = (await isPathExists(req.space.realPath)) ? req.space.realPath : null\n }\n lastEtag = lastRPath ? genEtag(null, lastRPath) : null\n }\n const match = lastEtag === condition.etag.value\n if (condition.etag.mustMatch !== match) {\n errors.push(`etag mismatch (${condition.etag.value} != ${lastEtag})`)\n continue\n }\n }\n\n atLeastOneOk = true\n break\n }\n\n if (!atLeastOneOk) {\n this.logger.warn(`If header condition failed : ${errors.join(', ')}`)\n res.status(HttpStatus.PRECONDITION_FAILED).send('If header condition failed')\n }\n return atLeastOneOk\n }\n\n private async lockRefresh(req: FastifyDAVRequest, res: FastifyReply, dbFilePath: string) {\n if (req.dav?.ifHeaders?.length !== 1) {\n this.logger.warn('Expected a lock token (only one lock may be refreshed at a time)')\n return res.status(HttpStatus.BAD_REQUEST).send('Expected a lock token (only one lock may be refreshed at a time)')\n }\n\n let token: string\n try {\n token = extractOneToken(req.dav.ifHeaders)\n } catch (e) {\n this.logger.warn(`${this.lockRefresh.name} - unable to extract token : ${JSON.stringify(req.dav.ifHeaders)} (${e})`)\n return res.status(HttpStatus.BAD_REQUEST).send('Unable to extract token')\n }\n\n const lock = await this.filesLockManager.isLockedWithToken(token, dbFilePath)\n if (!lock) {\n this.logger.warn(`Lock token does not exist or not match URL : ${token}`)\n return DAV_ERROR_RES(HttpStatus.PRECONDITION_FAILED, PRECONDITION.LOCK_TOKEN_MISMATCH, res)\n }\n if (lock.owner.id !== req.user.id) {\n this.logger.warn(`Lock token does not match owner : ${lock.owner.login} != ${req.user.login}`)\n return res.status(HttpStatus.FORBIDDEN).send('Lock token does not match owner')\n }\n\n await this.filesLockManager.refreshLockTimeout(lock, req.dav.lock.timeout)\n const lockProp = LOCK_PROP([lock])\n return res.type(XML_CONTENT_TYPE).status(HttpStatus.OK).send(xmlBuild(lockProp))\n }\n\n private handleError(req: FastifyDAVRequest, res: FastifyReply, e: any, toUrl?: string) {\n this.logger.error(`Unable to ${req.method} ${req.dav.url}${toUrl ? ` -> ${toUrl}` : ''} : ${e.message}`)\n const errorMsg = e.message.split(',')[0]\n if (e instanceof LockConflict) {\n return DAV_ERROR_RES(HttpStatus.LOCKED, PRECONDITION.LOCK_CONFLICT, res, e.lock.davLock?.lockroot || e.lock.dbFilePath)\n } else if (e instanceof FileError) {\n return res.status(e.httpCode).send(errorMsg)\n }\n throw new HttpException(errorMsg, HttpStatus.INTERNAL_SERVER_ERROR)\n }\n}\n"],"names":["WebDAVMethods","headOrGet","req","res","repository","SPACE_REPOSITORY","FILES","space","inSharesList","sendFile","filesManager","sendFileFromSpace","checks","stream","e","handleError","logger","warn","status","HttpStatus","FORBIDDEN","send","lock","isLockRefresh","dav","body","rExists","isPathExists","realPath","BAD_REQUEST","lockRefresh","dbFile","path","haveSpaceEnvPermissions","SPACE_OPERATION","ADD","alias","id","url","dirName","CONFLICT","davLock","lockroot","locktoken","lockscope","owner","ok","fileLock","filesLockManager","create","user","depth","timeout","mkFile","lockProp","LOCK_PROP","header","type","XML_CONTENT_TYPE","OK","CREATED","xmlBuild","DAV_ERROR_RES","LOCKED","PRECONDITION","LOCK_CONFLICT","dbFilePath","unlock","NOT_FOUND","isLockedWithToken","token","LOCK_TOKEN_MISMATCH","removeLock","key","NO_CONTENT","propfind","responses","requestedProps","locks","propfindMode","PROPSTAT","PROP","Object","keys","prop","filter","STANDARD_PROPS","indexOf","PROPNAME","DEPTH","RESOURCE","browseLocks","browseParentChildLocks","f","webDAVHandler","fromEntries","map","x","NS_PREFIX","p","fP","LOCK_DISCOVERY_PROP","name","LOCK_DISCOVERY","undefined","push","PROP_STAT","href","httpVersion","MULTI_STATUS","put","saveStream","lockTokens","extractAllTokens","ifHeaders","genEtag","delete","proppatch","checkConflicts","userId","props","errors","action","PROPPATCH_PROP_UPDATE","values","PROPPATCH_METHOD","msg","SET","REMOVE","debug","Array","isArray","value","entries","PROPPATCH_SUPPORTED_PROPS","PROTECTED_PROPERTY","length","FAILED_DEPENDENCY","encodeUrl","atLeastOneError","states","PROPPATCH_MODIFIED_PROPS","touch","currentTimeStamp","Date","error","state","mkcol","mkDir","copyMove","dstSpace","spaceEnv","destination","dstExisted","fakeDstReq","evaluateIfHeaders","isMove","overwrite","lastPath","lastSpaceEnv","lastRPath","lastEtag","atLeastOneOk","condition","haveLock","dbFileFromSpace","match","getLocksByPath","mustMatch","message","getLockByToken","startsWith","etag","join","PRECONDITION_FAILED","extractOneToken","JSON","stringify","login","refreshLockTimeout","toUrl","method","errorMsg","split","LockConflict","FileError","httpCode","HttpException","INTERNAL_SERVER_ERROR","Logger"],"mappings":"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"}
@@ -48,7 +48,6 @@ _export(exports, {
48
48
  }
49
49
  });
50
50
  const _nodehttp = /*#__PURE__*/ _interop_require_default(require("node:http"));
51
- const _appconstants = require("../../../app.constants");
52
51
  const _shared = require("../../../common/shared");
53
52
  const _webdav = require("../constants/webdav");
54
53
  const _xml = require("./xml");
@@ -127,7 +126,7 @@ function LOCK_DISCOVERY(locks) {
127
126
  [`${_webdav.NS_PREFIX}:${lock.davLock?.lockscope || _webdav.LOCK_SCOPE.EXCLUSIVE}`]: null
128
127
  },
129
128
  [`${_webdav.NS_PREFIX}:locktoken`]: {
130
- [`${_webdav.NS_PREFIX}:href`]: lock.davLock?.locktoken || _appconstants.SERVER_NAME
129
+ [`${_webdav.NS_PREFIX}:href`]: lock.davLock?.locktoken || _shared.SERVER_NAME
131
130
  },
132
131
  [`${_webdav.NS_PREFIX}:lockroot`]: {
133
132
  [`${_webdav.NS_PREFIX}:href`]: (0, _shared.encodeUrl)(lock.davLock?.lockroot || lock.dbFilePath)
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../backend/src/applications/webdav/utils/webdav.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 { FastifyReply } from 'fastify'\nimport http from 'node:http'\nimport { SERVER_NAME } from '../../../app.constants'\nimport { currentTimeStamp, encodeUrl } from '../../../common/shared'\nimport { FileLock } from '../../files/interfaces/file-lock.interface'\nimport { LOCK_SCOPE, NS_DAV, NS_PREFIX, PROPSTAT, XML_CONTENT_TYPE } from '../constants/webdav'\nimport { XML_NS, xmlBuild } from './xml'\n\nexport const XML_DAV_NS = { [`${XML_NS}:${NS_PREFIX}`]: `${NS_DAV}` }\nexport const PROPFIND_COLLECTION = { [`${NS_PREFIX}:collection`]: null }\nexport const PROPFIND_ALL_PROP = {\n [`${NS_PREFIX}:propfind`]: {\n [`${NS_PREFIX}:${PROPSTAT.ALLPROP}`]: null,\n ...XML_DAV_NS\n }\n}\n\nexport const SUPPORTED_LOCKS = {\n [`${NS_PREFIX}:lockentry`]: [\n {\n [`${NS_PREFIX}:lockscope`]: {\n [`${NS_PREFIX}:exclusive`]: null\n },\n [`${NS_PREFIX}:locktype`]: {\n [`${NS_PREFIX}:write`]: null\n }\n },\n {\n [`${NS_PREFIX}:lockscope`]: {\n [`${NS_PREFIX}:shared`]: null\n },\n [`${NS_PREFIX}:locktype`]: {\n [`${NS_PREFIX}:write`]: null\n }\n }\n ]\n}\n\nexport function PROP(prop: any, httpVersion: string, httpStatus: number, description?: string) {\n return {\n [`${NS_PREFIX}:prop`]: prop,\n [`${NS_PREFIX}:status`]: `${httpVersion} ${httpStatus} ${http.STATUS_CODES[httpStatus]}`,\n [`${NS_PREFIX}:responsedescription`]: description ? { [`${NS_PREFIX}:error`]: { [`${NS_PREFIX}:${description}`]: null } } : undefined\n }\n}\n\nexport function PROP_STAT(href: string, props: any) {\n return {\n [`${NS_PREFIX}:href`]: href,\n [`${NS_PREFIX}:propstat`]: props\n }\n}\n\nexport function MULTI_STATUS(content: any) {\n return {\n [`${NS_PREFIX}:multistatus`]: { [`${NS_PREFIX}:response`]: content, ...XML_DAV_NS }\n }\n}\n\nexport function LOCK_DISCOVERY(locks: FileLock[]) {\n // only locktype write is currently implemented in RFC\n const activeLocks = []\n for (const lock of locks) {\n activeLocks.push({\n [`${NS_PREFIX}:activelock`]: {\n [`${NS_PREFIX}:locktype`]: { [`${NS_PREFIX}:write`]: null },\n [`${NS_PREFIX}:lockscope`]: { [`${NS_PREFIX}:${lock.davLock?.lockscope || LOCK_SCOPE.EXCLUSIVE}`]: null },\n [`${NS_PREFIX}:locktoken`]: { [`${NS_PREFIX}:href`]: lock.davLock?.locktoken || SERVER_NAME },\n [`${NS_PREFIX}:lockroot`]: { [`${NS_PREFIX}:href`]: encodeUrl(lock.davLock?.lockroot || lock.dbFilePath) },\n [`${NS_PREFIX}:owner`]: lock.davLock?.owner || 'WebDAV',\n [`${NS_PREFIX}:timeout`]: `Second-${Math.floor(lock.expiration - currentTimeStamp())}`,\n [`${NS_PREFIX}:depth`]: lock.depth\n }\n })\n }\n return activeLocks\n}\n\nexport function LOCK_PROP(locks: FileLock[]) {\n return { [`${NS_PREFIX}:prop`]: { [`${NS_PREFIX}:lockdiscovery`]: LOCK_DISCOVERY(locks), ...XML_DAV_NS } }\n}\n\nexport function DAV_ERROR(error: string, href?: string): string {\n return xmlBuild({\n 'ns0:error': { [`ns0:${error}`]: href ? [{ 'ns0:href': encodeUrl(href) }] : '', [`${XML_NS}:ns0`]: `${NS_DAV}` }\n })\n}\n\nexport function DAV_ERROR_RES(code: number, error: string, res: FastifyReply, href?: string): FastifyReply {\n return res.status(code).type(XML_CONTENT_TYPE).send(DAV_ERROR(error, href))\n}\n"],"names":["DAV_ERROR","DAV_ERROR_RES","LOCK_DISCOVERY","LOCK_PROP","MULTI_STATUS","PROP","PROPFIND_ALL_PROP","PROPFIND_COLLECTION","PROP_STAT","SUPPORTED_LOCKS","XML_DAV_NS","XML_NS","NS_PREFIX","NS_DAV","PROPSTAT","ALLPROP","prop","httpVersion","httpStatus","description","http","STATUS_CODES","undefined","href","props","content","locks","activeLocks","lock","push","davLock","lockscope","LOCK_SCOPE","EXCLUSIVE","locktoken","SERVER_NAME","encodeUrl","lockroot","dbFilePath","owner","Math","floor","expiration","currentTimeStamp","depth","error","xmlBuild","code","res","status","type","XML_CONTENT_TYPE","send"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../backend/src/applications/webdav/utils/webdav.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 { FastifyReply } from 'fastify'\nimport http from 'node:http'\nimport { currentTimeStamp, encodeUrl, SERVER_NAME } from '../../../common/shared'\nimport { FileLock } from '../../files/interfaces/file-lock.interface'\nimport { LOCK_SCOPE, NS_DAV, NS_PREFIX, PROPSTAT, XML_CONTENT_TYPE } from '../constants/webdav'\nimport { XML_NS, xmlBuild } from './xml'\n\nexport const XML_DAV_NS = { [`${XML_NS}:${NS_PREFIX}`]: `${NS_DAV}` }\nexport const PROPFIND_COLLECTION = { [`${NS_PREFIX}:collection`]: null }\nexport const PROPFIND_ALL_PROP = {\n [`${NS_PREFIX}:propfind`]: {\n [`${NS_PREFIX}:${PROPSTAT.ALLPROP}`]: null,\n ...XML_DAV_NS\n }\n}\n\nexport const SUPPORTED_LOCKS = {\n [`${NS_PREFIX}:lockentry`]: [\n {\n [`${NS_PREFIX}:lockscope`]: {\n [`${NS_PREFIX}:exclusive`]: null\n },\n [`${NS_PREFIX}:locktype`]: {\n [`${NS_PREFIX}:write`]: null\n }\n },\n {\n [`${NS_PREFIX}:lockscope`]: {\n [`${NS_PREFIX}:shared`]: null\n },\n [`${NS_PREFIX}:locktype`]: {\n [`${NS_PREFIX}:write`]: null\n }\n }\n ]\n}\n\nexport function PROP(prop: any, httpVersion: string, httpStatus: number, description?: string) {\n return {\n [`${NS_PREFIX}:prop`]: prop,\n [`${NS_PREFIX}:status`]: `${httpVersion} ${httpStatus} ${http.STATUS_CODES[httpStatus]}`,\n [`${NS_PREFIX}:responsedescription`]: description ? { [`${NS_PREFIX}:error`]: { [`${NS_PREFIX}:${description}`]: null } } : undefined\n }\n}\n\nexport function PROP_STAT(href: string, props: any) {\n return {\n [`${NS_PREFIX}:href`]: href,\n [`${NS_PREFIX}:propstat`]: props\n }\n}\n\nexport function MULTI_STATUS(content: any) {\n return {\n [`${NS_PREFIX}:multistatus`]: { [`${NS_PREFIX}:response`]: content, ...XML_DAV_NS }\n }\n}\n\nexport function LOCK_DISCOVERY(locks: FileLock[]) {\n // only locktype write is currently implemented in RFC\n const activeLocks = []\n for (const lock of locks) {\n activeLocks.push({\n [`${NS_PREFIX}:activelock`]: {\n [`${NS_PREFIX}:locktype`]: { [`${NS_PREFIX}:write`]: null },\n [`${NS_PREFIX}:lockscope`]: { [`${NS_PREFIX}:${lock.davLock?.lockscope || LOCK_SCOPE.EXCLUSIVE}`]: null },\n [`${NS_PREFIX}:locktoken`]: { [`${NS_PREFIX}:href`]: lock.davLock?.locktoken || SERVER_NAME },\n [`${NS_PREFIX}:lockroot`]: { [`${NS_PREFIX}:href`]: encodeUrl(lock.davLock?.lockroot || lock.dbFilePath) },\n [`${NS_PREFIX}:owner`]: lock.davLock?.owner || 'WebDAV',\n [`${NS_PREFIX}:timeout`]: `Second-${Math.floor(lock.expiration - currentTimeStamp())}`,\n [`${NS_PREFIX}:depth`]: lock.depth\n }\n })\n }\n return activeLocks\n}\n\nexport function LOCK_PROP(locks: FileLock[]) {\n return { [`${NS_PREFIX}:prop`]: { [`${NS_PREFIX}:lockdiscovery`]: LOCK_DISCOVERY(locks), ...XML_DAV_NS } }\n}\n\nexport function DAV_ERROR(error: string, href?: string): string {\n return xmlBuild({\n 'ns0:error': { [`ns0:${error}`]: href ? [{ 'ns0:href': encodeUrl(href) }] : '', [`${XML_NS}:ns0`]: `${NS_DAV}` }\n })\n}\n\nexport function DAV_ERROR_RES(code: number, error: string, res: FastifyReply, href?: string): FastifyReply {\n return res.status(code).type(XML_CONTENT_TYPE).send(DAV_ERROR(error, href))\n}\n"],"names":["DAV_ERROR","DAV_ERROR_RES","LOCK_DISCOVERY","LOCK_PROP","MULTI_STATUS","PROP","PROPFIND_ALL_PROP","PROPFIND_COLLECTION","PROP_STAT","SUPPORTED_LOCKS","XML_DAV_NS","XML_NS","NS_PREFIX","NS_DAV","PROPSTAT","ALLPROP","prop","httpVersion","httpStatus","description","http","STATUS_CODES","undefined","href","props","content","locks","activeLocks","lock","push","davLock","lockscope","LOCK_SCOPE","EXCLUSIVE","locktoken","SERVER_NAME","encodeUrl","lockroot","dbFilePath","owner","Math","floor","expiration","currentTimeStamp","depth","error","xmlBuild","code","res","status","type","XML_CONTENT_TYPE","send"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QAmFeA;eAAAA;;QAMAC;eAAAA;;QA7BAC;eAAAA;;QAmBAC;eAAAA;;QAzBAC;eAAAA;;QAfAC;eAAAA;;QA5BHC;eAAAA;;QADAC;eAAAA;;QAqCGC;eAAAA;;QA7BHC;eAAAA;;QATAC;eAAAA;;;iEANI;wBACwC;wBAEiB;qBACzC;;;;;;AAE1B,MAAMA,aAAa;IAAE,CAAC,GAAGC,WAAM,CAAC,CAAC,EAAEC,iBAAS,EAAE,CAAC,EAAE,GAAGC,cAAM,EAAE;AAAC;AAC7D,MAAMN,sBAAsB;IAAE,CAAC,GAAGK,iBAAS,CAAC,WAAW,CAAC,CAAC,EAAE;AAAK;AAChE,MAAMN,oBAAoB;IAC/B,CAAC,GAAGM,iBAAS,CAAC,SAAS,CAAC,CAAC,EAAE;QACzB,CAAC,GAAGA,iBAAS,CAAC,CAAC,EAAEE,gBAAQ,CAACC,OAAO,EAAE,CAAC,EAAE;QACtC,GAAGL,UAAU;IACf;AACF;AAEO,MAAMD,kBAAkB;IAC7B,CAAC,GAAGG,iBAAS,CAAC,UAAU,CAAC,CAAC,EAAE;QAC1B;YACE,CAAC,GAAGA,iBAAS,CAAC,UAAU,CAAC,CAAC,EAAE;gBAC1B,CAAC,GAAGA,iBAAS,CAAC,UAAU,CAAC,CAAC,EAAE;YAC9B;YACA,CAAC,GAAGA,iBAAS,CAAC,SAAS,CAAC,CAAC,EAAE;gBACzB,CAAC,GAAGA,iBAAS,CAAC,MAAM,CAAC,CAAC,EAAE;YAC1B;QACF;QACA;YACE,CAAC,GAAGA,iBAAS,CAAC,UAAU,CAAC,CAAC,EAAE;gBAC1B,CAAC,GAAGA,iBAAS,CAAC,OAAO,CAAC,CAAC,EAAE;YAC3B;YACA,CAAC,GAAGA,iBAAS,CAAC,SAAS,CAAC,CAAC,EAAE;gBACzB,CAAC,GAAGA,iBAAS,CAAC,MAAM,CAAC,CAAC,EAAE;YAC1B;QACF;KACD;AACH;AAEO,SAASP,KAAKW,IAAS,EAAEC,WAAmB,EAAEC,UAAkB,EAAEC,WAAoB;IAC3F,OAAO;QACL,CAAC,GAAGP,iBAAS,CAAC,KAAK,CAAC,CAAC,EAAEI;QACvB,CAAC,GAAGJ,iBAAS,CAAC,OAAO,CAAC,CAAC,EAAE,GAAGK,YAAY,CAAC,EAAEC,WAAW,CAAC,EAAEE,iBAAI,CAACC,YAAY,CAACH,WAAW,EAAE;QACxF,CAAC,GAAGN,iBAAS,CAAC,oBAAoB,CAAC,CAAC,EAAEO,cAAc;YAAE,CAAC,GAAGP,iBAAS,CAAC,MAAM,CAAC,CAAC,EAAE;gBAAE,CAAC,GAAGA,iBAAS,CAAC,CAAC,EAAEO,aAAa,CAAC,EAAE;YAAK;QAAE,IAAIG;IAC9H;AACF;AAEO,SAASd,UAAUe,IAAY,EAAEC,KAAU;IAChD,OAAO;QACL,CAAC,GAAGZ,iBAAS,CAAC,KAAK,CAAC,CAAC,EAAEW;QACvB,CAAC,GAAGX,iBAAS,CAAC,SAAS,CAAC,CAAC,EAAEY;IAC7B;AACF;AAEO,SAASpB,aAAaqB,OAAY;IACvC,OAAO;QACL,CAAC,GAAGb,iBAAS,CAAC,YAAY,CAAC,CAAC,EAAE;YAAE,CAAC,GAAGA,iBAAS,CAAC,SAAS,CAAC,CAAC,EAAEa;YAAS,GAAGf,UAAU;QAAC;IACpF;AACF;AAEO,SAASR,eAAewB,KAAiB;IAC9C,sDAAsD;IACtD,MAAMC,cAAc,EAAE;IACtB,KAAK,MAAMC,QAAQF,MAAO;QACxBC,YAAYE,IAAI,CAAC;YACf,CAAC,GAAGjB,iBAAS,CAAC,WAAW,CAAC,CAAC,EAAE;gBAC3B,CAAC,GAAGA,iBAAS,CAAC,SAAS,CAAC,CAAC,EAAE;oBAAE,CAAC,GAAGA,iBAAS,CAAC,MAAM,CAAC,CAAC,EAAE;gBAAK;gBAC1D,CAAC,GAAGA,iBAAS,CAAC,UAAU,CAAC,CAAC,EAAE;oBAAE,CAAC,GAAGA,iBAAS,CAAC,CAAC,EAAEgB,KAAKE,OAAO,EAAEC,aAAaC,kBAAU,CAACC,SAAS,EAAE,CAAC,EAAE;gBAAK;gBACxG,CAAC,GAAGrB,iBAAS,CAAC,UAAU,CAAC,CAAC,EAAE;oBAAE,CAAC,GAAGA,iBAAS,CAAC,KAAK,CAAC,CAAC,EAAEgB,KAAKE,OAAO,EAAEI,aAAaC,mBAAW;gBAAC;gBAC5F,CAAC,GAAGvB,iBAAS,CAAC,SAAS,CAAC,CAAC,EAAE;oBAAE,CAAC,GAAGA,iBAAS,CAAC,KAAK,CAAC,CAAC,EAAEwB,IAAAA,iBAAS,EAACR,KAAKE,OAAO,EAAEO,YAAYT,KAAKU,UAAU;gBAAE;gBACzG,CAAC,GAAG1B,iBAAS,CAAC,MAAM,CAAC,CAAC,EAAEgB,KAAKE,OAAO,EAAES,SAAS;gBAC/C,CAAC,GAAG3B,iBAAS,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE4B,KAAKC,KAAK,CAACb,KAAKc,UAAU,GAAGC,IAAAA,wBAAgB,MAAK;gBACtF,CAAC,GAAG/B,iBAAS,CAAC,MAAM,CAAC,CAAC,EAAEgB,KAAKgB,KAAK;YACpC;QACF;IACF;IACA,OAAOjB;AACT;AAEO,SAASxB,UAAUuB,KAAiB;IACzC,OAAO;QAAE,CAAC,GAAGd,iBAAS,CAAC,KAAK,CAAC,CAAC,EAAE;YAAE,CAAC,GAAGA,iBAAS,CAAC,cAAc,CAAC,CAAC,EAAEV,eAAewB;YAAQ,GAAGhB,UAAU;QAAC;IAAE;AAC3G;AAEO,SAASV,UAAU6C,KAAa,EAAEtB,IAAa;IACpD,OAAOuB,IAAAA,aAAQ,EAAC;QACd,aAAa;YAAE,CAAC,CAAC,IAAI,EAAED,OAAO,CAAC,EAAEtB,OAAO;gBAAC;oBAAE,YAAYa,IAAAA,iBAAS,EAACb;gBAAM;aAAE,GAAG;YAAI,CAAC,GAAGZ,WAAM,CAAC,IAAI,CAAC,CAAC,EAAE,GAAGE,cAAM,EAAE;QAAC;IACjH;AACF;AAEO,SAASZ,cAAc8C,IAAY,EAAEF,KAAa,EAAEG,GAAiB,EAAEzB,IAAa;IACzF,OAAOyB,IAAIC,MAAM,CAACF,MAAMG,IAAI,CAACC,wBAAgB,EAAEC,IAAI,CAACpD,UAAU6C,OAAOtB;AACvE"}
@@ -46,7 +46,7 @@ _export(exports, {
46
46
  });
47
47
  const _classtransformer = require("class-transformer");
48
48
  const _classvalidator = require("class-validator");
49
- const _appconstants = require("../app.constants");
49
+ const _shared = require("../common/shared");
50
50
  const _auth = require("./constants/auth");
51
51
  const _authldap = require("./constants/auth-ldap");
52
52
  function _ts_decorate(decorators, target, key, desc) {
@@ -61,7 +61,7 @@ function _ts_metadata(k, v) {
61
61
  let AuthMfaTotpConfig = class AuthMfaTotpConfig {
62
62
  constructor(){
63
63
  this.enabled = true;
64
- this.issuer = _appconstants.SERVER_NAME;
64
+ this.issuer = _shared.SERVER_NAME;
65
65
  }
66
66
  };
67
67
  _ts_decorate([
@@ -230,6 +230,21 @@ _ts_decorate([
230
230
  (0, _classtransformer.Type)(()=>AuthMethodLdapAttributesConfig),
231
231
  _ts_metadata("design:type", typeof AuthMethodLdapAttributesConfig === "undefined" ? Object : AuthMethodLdapAttributesConfig)
232
232
  ], AuthMethodLdapConfig.prototype, "attributes", void 0);
233
+ _ts_decorate([
234
+ (0, _classvalidator.IsOptional)(),
235
+ (0, _classvalidator.IsString)(),
236
+ _ts_metadata("design:type", String)
237
+ ], AuthMethodLdapConfig.prototype, "adminGroup", void 0);
238
+ _ts_decorate([
239
+ (0, _classvalidator.IsOptional)(),
240
+ (0, _classvalidator.IsString)(),
241
+ _ts_metadata("design:type", String)
242
+ ], AuthMethodLdapConfig.prototype, "upnSuffix", void 0);
243
+ _ts_decorate([
244
+ (0, _classvalidator.IsOptional)(),
245
+ (0, _classvalidator.IsString)(),
246
+ _ts_metadata("design:type", String)
247
+ ], AuthMethodLdapConfig.prototype, "netbiosName", void 0);
233
248
  let AuthConfig = class AuthConfig {
234
249
  constructor(){
235
250
  this.method = 'mysql';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../backend/src/authentication/auth.config.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, Transform, Type } from 'class-transformer'\nimport {\n ArrayNotEmpty,\n IsArray,\n IsBoolean,\n IsDefined,\n IsEnum,\n IsIn,\n IsNotEmpty,\n IsNotEmptyObject,\n IsObject,\n IsOptional,\n IsString,\n ValidateIf,\n ValidateNested\n} from 'class-validator'\nimport { SERVER_NAME } from '../app.constants'\nimport { ACCESS_KEY, CSRF_KEY, REFRESH_KEY, WS_KEY } from './constants/auth'\nimport { LDAP_COMMON_ATTR, LDAP_LOGIN_ATTR } from './constants/auth-ldap'\n\nexport class AuthMfaTotpConfig {\n @IsBoolean()\n enabled = true\n\n @IsString()\n issuer = SERVER_NAME\n}\n\nexport class AuthMfaConfig {\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthMfaTotpConfig)\n totp: AuthMfaTotpConfig = new AuthMfaTotpConfig()\n}\n\nexport class AuthTokenAccessConfig {\n @Exclude({ toClassOnly: true })\n // force default name\n name = ACCESS_KEY\n\n @IsString()\n @IsNotEmpty()\n secret: string\n\n @IsString()\n @IsNotEmpty()\n expiration = '30m'\n}\n\nexport class AuthTokenRefreshConfig {\n @Exclude({ toClassOnly: true })\n // force default name\n name = REFRESH_KEY\n\n @IsString()\n @IsNotEmpty()\n secret: string\n\n @IsString()\n @IsNotEmpty()\n expiration = '4h'\n}\n\nexport class AuthTokenCsrfConfig extends AuthTokenRefreshConfig {\n @IsString()\n @IsNotEmpty()\n override name: string = CSRF_KEY\n}\n\nexport class AuthTokenWSConfig extends AuthTokenRefreshConfig {\n @IsString()\n @IsNotEmpty()\n override name: string = WS_KEY\n}\n\nexport class AuthTokenConfig {\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthTokenAccessConfig)\n access: AuthTokenAccessConfig\n\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthTokenRefreshConfig)\n refresh: AuthTokenRefreshConfig\n\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthTokenCsrfConfig)\n csrf: AuthTokenCsrfConfig\n\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthTokenWSConfig)\n ws: AuthTokenWSConfig\n}\n\nexport class AuthMethodLdapAttributesConfig {\n @IsOptional()\n @IsString()\n @Transform(({ value }) => value || LDAP_LOGIN_ATTR.UID)\n @IsEnum(LDAP_LOGIN_ATTR)\n login: LDAP_LOGIN_ATTR = LDAP_LOGIN_ATTR.UID\n\n @IsOptional()\n @IsString()\n @Transform(({ value }) => value || LDAP_COMMON_ATTR.MAIL)\n email: string = LDAP_COMMON_ATTR.MAIL\n}\n\nexport class AuthMethodLdapConfig {\n @Transform(({ value }) => (Array.isArray(value) ? value.filter((v: string) => Boolean(v)) : value))\n @ArrayNotEmpty()\n @IsArray()\n @IsString({ each: true })\n servers: string[]\n\n @IsString()\n @IsNotEmpty()\n baseDN: string\n\n @IsOptional()\n @IsString()\n filter?: string\n\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthMethodLdapAttributesConfig)\n attributes: AuthMethodLdapAttributesConfig = new AuthMethodLdapAttributesConfig()\n}\n\nexport class AuthConfig {\n @IsString()\n @IsIn(['mysql', 'ldap'])\n method: 'mysql' | 'ldap' = 'mysql'\n\n @IsOptional()\n @IsString()\n encryptionKey: string\n\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthMfaConfig)\n mfa: AuthMfaConfig = new AuthMfaConfig()\n\n @IsString()\n @IsIn(['lax', 'strict'])\n cookieSameSite: 'lax' | 'strict' = 'strict'\n\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthTokenConfig)\n token: AuthTokenConfig\n\n @ValidateIf((o: AuthConfig) => o.method === 'ldap')\n @IsDefined()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthMethodLdapConfig)\n ldap: AuthMethodLdapConfig\n}\n"],"names":["AuthConfig","AuthMethodLdapAttributesConfig","AuthMethodLdapConfig","AuthMfaConfig","AuthMfaTotpConfig","AuthTokenAccessConfig","AuthTokenConfig","AuthTokenCsrfConfig","AuthTokenRefreshConfig","AuthTokenWSConfig","enabled","issuer","SERVER_NAME","totp","name","ACCESS_KEY","expiration","toClassOnly","REFRESH_KEY","CSRF_KEY","WS_KEY","login","LDAP_LOGIN_ATTR","UID","email","LDAP_COMMON_ATTR","MAIL","value","attributes","Array","isArray","filter","v","Boolean","each","method","mfa","cookieSameSite","o"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QAiJYA;eAAAA;;QApCAC;eAAAA;;QAaAC;eAAAA;;QA5FAC;eAAAA;;QARAC;eAAAA;;QAiBAC;eAAAA;;QAwCAC;eAAAA;;QAZAC;eAAAA;;QAdAC;eAAAA;;QAoBAC;eAAAA;;;kCAvE4B;gCAelC;8BACqB;sBAC8B;0BACR;;;;;;;;;;AAE3C,IAAA,AAAML,oBAAN,MAAMA;;aAEXM,UAAU;aAGVC,SAASC,yBAAW;;AACtB;;;;;;;AAEO,IAAA,AAAMT,gBAAN,MAAMA;;aAMXU,OAA0B,IAAIT;;AAChC;;;;;;oCAFcA;;;AAIP,IAAA,AAAMC,wBAAN,MAAMA;;aAEX,qBAAqB;QACrBS,OAAOC,gBAAU;aAQjBC,aAAa;;AACf;;;QAXaC,aAAa;;;;;;;;;;;;AAanB,IAAA,AAAMT,yBAAN,MAAMA;;aAEX,qBAAqB;QACrBM,OAAOI,iBAAW;aAQlBF,aAAa;;AACf;;;QAXaC,aAAa;;;;;;;;;;;;AAanB,IAAA,AAAMV,sBAAN,MAAMA,4BAA4BC;;QAAlC,qBAGIM,OAAeK,cAAQ;;AAClC;;;;;;AAEO,IAAA,AAAMV,oBAAN,MAAMA,0BAA0BD;;QAAhC,qBAGIM,OAAeM,YAAM;;AAChC;;;;;;AAEO,IAAA,AAAMd,kBAAN,MAAMA;AA4Bb;;;;;;oCAvBcD;;;;;;;;oCAOAG;;;;;;;;oCAOAD;;;;;;;;oCAOAE;;;AAIP,IAAA,AAAMR,iCAAN,MAAMA;;aAKXoB,QAAyBC,yBAAe,CAACC,GAAG;aAK5CC,QAAgBC,0BAAgB,CAACC,IAAI;;AACvC;;;;sCARc,EAAEC,KAAK,EAAE,GAAKA,SAASL,yBAAe,CAACC,GAAG;;;;;;;sCAM1C,EAAEI,KAAK,EAAE,GAAKA,SAASF,0BAAgB,CAACC,IAAI;;;AAInD,IAAA,AAAMxB,uBAAN,MAAMA;;aAoBX0B,aAA6C,IAAI3B;;AACnD;;sCApBc,EAAE0B,KAAK,EAAE,GAAME,MAAMC,OAAO,CAACH,SAASA,MAAMI,MAAM,CAAC,CAACC,IAAcC,QAAQD,MAAML;;;;QAGhFO,MAAM;;;;;;;;;;;;;;;;;;;oCAeNjC;;;AAIP,IAAA,AAAMD,aAAN,MAAMA;;aAGXmC,SAA2B;aAW3BC,MAAqB,IAAIjC;aAIzBkC,iBAAmC;;AAerC;;;;QA/BS;QAAS;;;;;;;;;;;;;;oCAWJlC;;;;;;QAIL;QAAO;;;;;;;;;oCAOFG;;;;qCAGCgC,IAAkBA,EAAEH,MAAM,KAAK;;;;oCAIhCjC"}
1
+ {"version":3,"sources":["../../../backend/src/authentication/auth.config.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, Transform, Type } from 'class-transformer'\nimport {\n ArrayNotEmpty,\n IsArray,\n IsBoolean,\n IsDefined,\n IsEnum,\n IsIn,\n IsNotEmpty,\n IsNotEmptyObject,\n IsObject,\n IsOptional,\n IsString,\n ValidateIf,\n ValidateNested\n} from 'class-validator'\nimport { SERVER_NAME } from '../common/shared'\nimport { ACCESS_KEY, CSRF_KEY, REFRESH_KEY, WS_KEY } from './constants/auth'\nimport { LDAP_COMMON_ATTR, LDAP_LOGIN_ATTR } from './constants/auth-ldap'\n\nexport class AuthMfaTotpConfig {\n @IsBoolean()\n enabled = true\n\n @IsString()\n issuer = SERVER_NAME\n}\n\nexport class AuthMfaConfig {\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthMfaTotpConfig)\n totp: AuthMfaTotpConfig = new AuthMfaTotpConfig()\n}\n\nexport class AuthTokenAccessConfig {\n @Exclude({ toClassOnly: true })\n // force default name\n name = ACCESS_KEY\n\n @IsString()\n @IsNotEmpty()\n secret: string\n\n @IsString()\n @IsNotEmpty()\n expiration = '30m'\n}\n\nexport class AuthTokenRefreshConfig {\n @Exclude({ toClassOnly: true })\n // force default name\n name = REFRESH_KEY\n\n @IsString()\n @IsNotEmpty()\n secret: string\n\n @IsString()\n @IsNotEmpty()\n expiration = '4h'\n}\n\nexport class AuthTokenCsrfConfig extends AuthTokenRefreshConfig {\n @IsString()\n @IsNotEmpty()\n override name: string = CSRF_KEY\n}\n\nexport class AuthTokenWSConfig extends AuthTokenRefreshConfig {\n @IsString()\n @IsNotEmpty()\n override name: string = WS_KEY\n}\n\nexport class AuthTokenConfig {\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthTokenAccessConfig)\n access: AuthTokenAccessConfig\n\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthTokenRefreshConfig)\n refresh: AuthTokenRefreshConfig\n\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthTokenCsrfConfig)\n csrf: AuthTokenCsrfConfig\n\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthTokenWSConfig)\n ws: AuthTokenWSConfig\n}\n\nexport class AuthMethodLdapAttributesConfig {\n @IsOptional()\n @IsString()\n @Transform(({ value }) => value || LDAP_LOGIN_ATTR.UID)\n @IsEnum(LDAP_LOGIN_ATTR)\n login: LDAP_LOGIN_ATTR = LDAP_LOGIN_ATTR.UID\n\n @IsOptional()\n @IsString()\n @Transform(({ value }) => value || LDAP_COMMON_ATTR.MAIL)\n email: string = LDAP_COMMON_ATTR.MAIL\n}\n\nexport class AuthMethodLdapConfig {\n @Transform(({ value }) => (Array.isArray(value) ? value.filter((v: string) => Boolean(v)) : value))\n @ArrayNotEmpty()\n @IsArray()\n @IsString({ each: true })\n servers: string[]\n\n @IsString()\n @IsNotEmpty()\n baseDN: string\n\n @IsOptional()\n @IsString()\n filter?: string\n\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthMethodLdapAttributesConfig)\n attributes: AuthMethodLdapAttributesConfig = new AuthMethodLdapAttributesConfig()\n\n @IsOptional()\n @IsString()\n adminGroup?: string\n\n @IsOptional()\n @IsString()\n upnSuffix?: string\n\n @IsOptional()\n @IsString()\n netbiosName?: string\n}\n\nexport class AuthConfig {\n @IsString()\n @IsIn(['mysql', 'ldap'])\n method: 'mysql' | 'ldap' = 'mysql'\n\n @IsOptional()\n @IsString()\n encryptionKey: string\n\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthMfaConfig)\n mfa: AuthMfaConfig = new AuthMfaConfig()\n\n @IsString()\n @IsIn(['lax', 'strict'])\n cookieSameSite: 'lax' | 'strict' = 'strict'\n\n @IsDefined()\n @IsNotEmptyObject()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthTokenConfig)\n token: AuthTokenConfig\n\n @ValidateIf((o: AuthConfig) => o.method === 'ldap')\n @IsDefined()\n @IsObject()\n @ValidateNested()\n @Type(() => AuthMethodLdapConfig)\n ldap: AuthMethodLdapConfig\n}\n"],"names":["AuthConfig","AuthMethodLdapAttributesConfig","AuthMethodLdapConfig","AuthMfaConfig","AuthMfaTotpConfig","AuthTokenAccessConfig","AuthTokenConfig","AuthTokenCsrfConfig","AuthTokenRefreshConfig","AuthTokenWSConfig","enabled","issuer","SERVER_NAME","totp","name","ACCESS_KEY","expiration","toClassOnly","REFRESH_KEY","CSRF_KEY","WS_KEY","login","LDAP_LOGIN_ATTR","UID","email","LDAP_COMMON_ATTR","MAIL","value","attributes","Array","isArray","filter","v","Boolean","each","method","mfa","cookieSameSite","o"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QA6JYA;eAAAA;;QAhDAC;eAAAA;;QAaAC;eAAAA;;QA5FAC;eAAAA;;QARAC;eAAAA;;QAiBAC;eAAAA;;QAwCAC;eAAAA;;QAZAC;eAAAA;;QAdAC;eAAAA;;QAoBAC;eAAAA;;;kCAvE4B;gCAelC;wBACqB;sBAC8B;0BACR;;;;;;;;;;AAE3C,IAAA,AAAML,oBAAN,MAAMA;;aAEXM,UAAU;aAGVC,SAASC,mBAAW;;AACtB;;;;;;;AAEO,IAAA,AAAMT,gBAAN,MAAMA;;aAMXU,OAA0B,IAAIT;;AAChC;;;;;;oCAFcA;;;AAIP,IAAA,AAAMC,wBAAN,MAAMA;;aAEX,qBAAqB;QACrBS,OAAOC,gBAAU;aAQjBC,aAAa;;AACf;;;QAXaC,aAAa;;;;;;;;;;;;AAanB,IAAA,AAAMT,yBAAN,MAAMA;;aAEX,qBAAqB;QACrBM,OAAOI,iBAAW;aAQlBF,aAAa;;AACf;;;QAXaC,aAAa;;;;;;;;;;;;AAanB,IAAA,AAAMV,sBAAN,MAAMA,4BAA4BC;;QAAlC,qBAGIM,OAAeK,cAAQ;;AAClC;;;;;;AAEO,IAAA,AAAMV,oBAAN,MAAMA,0BAA0BD;;QAAhC,qBAGIM,OAAeM,YAAM;;AAChC;;;;;;AAEO,IAAA,AAAMd,kBAAN,MAAMA;AA4Bb;;;;;;oCAvBcD;;;;;;;;oCAOAG;;;;;;;;oCAOAD;;;;;;;;oCAOAE;;;AAIP,IAAA,AAAMR,iCAAN,MAAMA;;aAKXoB,QAAyBC,yBAAe,CAACC,GAAG;aAK5CC,QAAgBC,0BAAgB,CAACC,IAAI;;AACvC;;;;sCARc,EAAEC,KAAK,EAAE,GAAKA,SAASL,yBAAe,CAACC,GAAG;;;;;;;sCAM1C,EAAEI,KAAK,EAAE,GAAKA,SAASF,0BAAgB,CAACC,IAAI;;;AAInD,IAAA,AAAMxB,uBAAN,MAAMA;;aAoBX0B,aAA6C,IAAI3B;;AAanD;;sCAhCc,EAAE0B,KAAK,EAAE,GAAME,MAAMC,OAAO,CAACH,SAASA,MAAMI,MAAM,CAAC,CAACC,IAAcC,QAAQD,MAAML;;;;QAGhFO,MAAM;;;;;;;;;;;;;;;;;;;oCAeNjC;;;;;;;;;;;;;;;;;;AAgBP,IAAA,AAAMD,aAAN,MAAMA;;aAGXmC,SAA2B;aAW3BC,MAAqB,IAAIjC;aAIzBkC,iBAAmC;;AAerC;;;;QA/BS;QAAS;;;;;;;;;;;;;;oCAWJlC;;;;;;QAIL;QAAO;;;;;;;;;oCAOFG;;;;qCAGCgC,IAAkBA,EAAEH,MAAM,KAAK;;;;oCAIhCjC"}
@@ -34,7 +34,8 @@ const LDAP_COMMON_ATTR = {
34
34
  GIVEN_NAME: 'givenName',
35
35
  SN: 'sn',
36
36
  CN: 'cn',
37
- DISPLAY_NAME: 'displayName'
37
+ DISPLAY_NAME: 'displayName',
38
+ MEMBER_OF: 'memberOf'
38
39
  };
39
40
  const ALL_LDAP_ATTRIBUTES = [
40
41
  ...Object.values(LDAP_LOGIN_ATTR),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../backend/src/authentication/constants/auth-ldap.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\nexport enum LDAP_LOGIN_ATTR {\n UID = 'uid',\n SAM = 'sAMAccountName',\n UPN = 'userPrincipalName'\n}\n\nexport const LDAP_COMMON_ATTR = {\n MAIL: 'mail',\n GIVEN_NAME: 'givenName',\n SN: 'sn',\n CN: 'cn',\n DISPLAY_NAME: 'displayName'\n} as const\n\nexport const ALL_LDAP_ATTRIBUTES = [...Object.values(LDAP_LOGIN_ATTR), ...Object.values(LDAP_COMMON_ATTR)]\n"],"names":["ALL_LDAP_ATTRIBUTES","LDAP_COMMON_ATTR","LDAP_LOGIN_ATTR","MAIL","GIVEN_NAME","SN","CN","DISPLAY_NAME","Object","values"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QAgBYA;eAAAA;;QARAC;eAAAA;;QANDC;eAAAA;;;AAAL,IAAA,AAAKA,yCAAAA;;;;WAAAA;;AAML,MAAMD,mBAAmB;IAC9BE,MAAM;IACNC,YAAY;IACZC,IAAI;IACJC,IAAI;IACJC,cAAc;AAChB;AAEO,MAAMP,sBAAsB;OAAIQ,OAAOC,MAAM,CAACP;OAAqBM,OAAOC,MAAM,CAACR;CAAkB"}
1
+ {"version":3,"sources":["../../../../backend/src/authentication/constants/auth-ldap.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\nexport enum LDAP_LOGIN_ATTR {\n UID = 'uid',\n SAM = 'sAMAccountName',\n UPN = 'userPrincipalName'\n}\n\nexport const LDAP_COMMON_ATTR = {\n MAIL: 'mail',\n GIVEN_NAME: 'givenName',\n SN: 'sn',\n CN: 'cn',\n DISPLAY_NAME: 'displayName',\n MEMBER_OF: 'memberOf'\n} as const\n\nexport const ALL_LDAP_ATTRIBUTES = [...Object.values(LDAP_LOGIN_ATTR), ...Object.values(LDAP_COMMON_ATTR)]\n"],"names":["ALL_LDAP_ATTRIBUTES","LDAP_COMMON_ATTR","LDAP_LOGIN_ATTR","MAIL","GIVEN_NAME","SN","CN","DISPLAY_NAME","MEMBER_OF","Object","values"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QAiBYA;eAAAA;;QATAC;eAAAA;;QANDC;eAAAA;;;AAAL,IAAA,AAAKA,yCAAAA;;;;WAAAA;;AAML,MAAMD,mBAAmB;IAC9BE,MAAM;IACNC,YAAY;IACZC,IAAI;IACJC,IAAI;IACJC,cAAc;IACdC,WAAW;AACb;AAEO,MAAMR,sBAAsB;OAAIS,OAAOC,MAAM,CAACR;OAAqBO,OAAOC,MAAM,CAACT;CAAkB"}
@@ -17,8 +17,8 @@ const _passport = require("@nestjs/passport");
17
17
  const _classtransformer = require("class-transformer");
18
18
  const _nestjspino = require("nestjs-pino");
19
19
  const _passporthttp = require("passport-http");
20
- const _appconstants = require("../../app.constants");
21
20
  const _usermodel = require("../../applications/users/models/user.model");
21
+ const _shared = require("../../common/shared");
22
22
  const _cacheservice = require("../../infrastructure/cache/services/cache.service");
23
23
  const _scope = require("../constants/scope");
24
24
  const _authmethod = require("../models/auth-method");
@@ -33,6 +33,8 @@ function _ts_metadata(k, v) {
33
33
  }
34
34
  let AuthBasicStrategy = class AuthBasicStrategy extends (0, _passport.PassportStrategy)(_passporthttp.BasicStrategy, 'basic') {
35
35
  async validate(req, loginOrEmail, password) {
36
+ loginOrEmail = loginOrEmail.trim();
37
+ password = password.trim();
36
38
  this.logger.assign({
37
39
  user: loginOrEmail
38
40
  });
@@ -62,7 +64,7 @@ let AuthBasicStrategy = class AuthBasicStrategy extends (0, _passport.PassportSt
62
64
  constructor(authMethod, cache, logger){
63
65
  super({
64
66
  passReqToCallback: true,
65
- realm: _appconstants.SERVER_NAME
67
+ realm: _shared.SERVER_NAME
66
68
  }), this.authMethod = authMethod, this.cache = cache, this.logger = logger, this.CACHE_TTL = 900, this.CACHE_KEY_PREFIX = 'auth-webdav';
67
69
  }
68
70
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../backend/src/authentication/guards/auth-basic.strategy.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 { Injectable } from '@nestjs/common'\nimport { AbstractStrategy, PassportStrategy } from '@nestjs/passport'\nimport { instanceToPlain, plainToInstance } from 'class-transformer'\nimport { FastifyRequest } from 'fastify'\nimport { PinoLogger } from 'nestjs-pino'\nimport { BasicStrategy } from 'passport-http'\nimport { SERVER_NAME } from '../../app.constants'\nimport { UserModel } from '../../applications/users/models/user.model'\nimport { Cache } from '../../infrastructure/cache/services/cache.service'\nimport { AUTH_SCOPE } from '../constants/scope'\nimport { AuthMethod } from '../models/auth-method'\n\n@Injectable()\nexport class AuthBasicStrategy extends PassportStrategy(BasicStrategy, 'basic') implements AbstractStrategy {\n private readonly CACHE_TTL = 900\n private readonly CACHE_KEY_PREFIX = 'auth-webdav'\n\n constructor(\n private readonly authMethod: AuthMethod,\n private readonly cache: Cache,\n private readonly logger: PinoLogger\n ) {\n super({ passReqToCallback: true, realm: SERVER_NAME })\n }\n\n async validate(req: FastifyRequest, loginOrEmail: string, password: string): Promise<Omit<UserModel, 'password'> | null> {\n this.logger.assign({ user: loginOrEmail })\n const authBasicUser = `${this.CACHE_KEY_PREFIX}-${req.headers['authorization'].split(' ').at(-1).toLowerCase()}`\n const userFromCache: any = await this.cache.get(authBasicUser)\n if (userFromCache === null) {\n // not authorized\n return null\n }\n if (userFromCache !== undefined) {\n // cached\n // warning: plainToInstance do not use constructor to instantiate class\n return plainToInstance(UserModel, userFromCache)\n }\n const userFromDB: UserModel = await this.authMethod.validateUser(loginOrEmail, password, req.ip, AUTH_SCOPE.WEBDAV)\n if (userFromDB !== null) {\n userFromDB.removePassword()\n }\n const userToCache: Record<string, any> | null = userFromDB ? instanceToPlain(userFromDB, { excludePrefixes: ['_'] }) : null\n this.cache.set(authBasicUser, userToCache, this.CACHE_TTL).catch((e: Error) => this.logger.error(`${this.validate.name} - ${e}`))\n return userFromDB\n }\n}\n"],"names":["AuthBasicStrategy","PassportStrategy","BasicStrategy","validate","req","loginOrEmail","password","logger","assign","user","authBasicUser","CACHE_KEY_PREFIX","headers","split","at","toLowerCase","userFromCache","cache","get","undefined","plainToInstance","UserModel","userFromDB","authMethod","validateUser","ip","AUTH_SCOPE","WEBDAV","removePassword","userToCache","instanceToPlain","excludePrefixes","set","CACHE_TTL","catch","e","error","name","passReqToCallback","realm","SERVER_NAME"],"mappings":"AAAA;;;;CAIC;;;;+BAeYA;;;eAAAA;;;wBAbc;0BACwB;kCACF;4BAEtB;8BACG;8BACF;2BACF;8BACJ;uBACK;4BACA;;;;;;;;;;AAGpB,IAAA,AAAMA,oBAAN,MAAMA,0BAA0BC,IAAAA,0BAAgB,EAACC,2BAAa,EAAE;IAYrE,MAAMC,SAASC,GAAmB,EAAEC,YAAoB,EAAEC,QAAgB,EAA+C;QACvH,IAAI,CAACC,MAAM,CAACC,MAAM,CAAC;YAAEC,MAAMJ;QAAa;QACxC,MAAMK,gBAAgB,GAAG,IAAI,CAACC,gBAAgB,CAAC,CAAC,EAAEP,IAAIQ,OAAO,CAAC,gBAAgB,CAACC,KAAK,CAAC,KAAKC,EAAE,CAAC,CAAC,GAAGC,WAAW,IAAI;QAChH,MAAMC,gBAAqB,MAAM,IAAI,CAACC,KAAK,CAACC,GAAG,CAACR;QAChD,IAAIM,kBAAkB,MAAM;YAC1B,iBAAiB;YACjB,OAAO;QACT;QACA,IAAIA,kBAAkBG,WAAW;YAC/B,SAAS;YACT,uEAAuE;YACvE,OAAOC,IAAAA,iCAAe,EAACC,oBAAS,EAAEL;QACpC;QACA,MAAMM,aAAwB,MAAM,IAAI,CAACC,UAAU,CAACC,YAAY,CAACnB,cAAcC,UAAUF,IAAIqB,EAAE,EAAEC,iBAAU,CAACC,MAAM;QAClH,IAAIL,eAAe,MAAM;YACvBA,WAAWM,cAAc;QAC3B;QACA,MAAMC,cAA0CP,aAAaQ,IAAAA,iCAAe,EAACR,YAAY;YAAES,iBAAiB;gBAAC;aAAI;QAAC,KAAK;QACvH,IAAI,CAACd,KAAK,CAACe,GAAG,CAACtB,eAAemB,aAAa,IAAI,CAACI,SAAS,EAAEC,KAAK,CAAC,CAACC,IAAa,IAAI,CAAC5B,MAAM,CAAC6B,KAAK,CAAC,GAAG,IAAI,CAACjC,QAAQ,CAACkC,IAAI,CAAC,GAAG,EAAEF,GAAG;QAC/H,OAAOb;IACT;IA5BA,YACE,AAAiBC,UAAsB,EACvC,AAAiBN,KAAY,EAC7B,AAAiBV,MAAkB,CACnC;QACA,KAAK,CAAC;YAAE+B,mBAAmB;YAAMC,OAAOC,yBAAW;QAAC,SAJnCjB,aAAAA,iBACAN,QAAAA,YACAV,SAAAA,aANF0B,YAAY,UACZtB,mBAAmB;IAQpC;AAuBF"}
1
+ {"version":3,"sources":["../../../../backend/src/authentication/guards/auth-basic.strategy.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 { Injectable } from '@nestjs/common'\nimport { AbstractStrategy, PassportStrategy } from '@nestjs/passport'\nimport { instanceToPlain, plainToInstance } from 'class-transformer'\nimport { FastifyRequest } from 'fastify'\nimport { PinoLogger } from 'nestjs-pino'\nimport { BasicStrategy } from 'passport-http'\nimport { UserModel } from '../../applications/users/models/user.model'\nimport { SERVER_NAME } from '../../common/shared'\nimport { Cache } from '../../infrastructure/cache/services/cache.service'\nimport { AUTH_SCOPE } from '../constants/scope'\nimport { AuthMethod } from '../models/auth-method'\n\n@Injectable()\nexport class AuthBasicStrategy extends PassportStrategy(BasicStrategy, 'basic') implements AbstractStrategy {\n private readonly CACHE_TTL = 900\n private readonly CACHE_KEY_PREFIX = 'auth-webdav'\n\n constructor(\n private readonly authMethod: AuthMethod,\n private readonly cache: Cache,\n private readonly logger: PinoLogger\n ) {\n super({ passReqToCallback: true, realm: SERVER_NAME })\n }\n\n async validate(req: FastifyRequest, loginOrEmail: string, password: string): Promise<Omit<UserModel, 'password'> | null> {\n loginOrEmail = loginOrEmail.trim()\n password = password.trim()\n this.logger.assign({ user: loginOrEmail })\n const authBasicUser = `${this.CACHE_KEY_PREFIX}-${req.headers['authorization'].split(' ').at(-1).toLowerCase()}`\n const userFromCache: any = await this.cache.get(authBasicUser)\n if (userFromCache === null) {\n // not authorized\n return null\n }\n if (userFromCache !== undefined) {\n // cached\n // warning: plainToInstance do not use constructor to instantiate class\n return plainToInstance(UserModel, userFromCache)\n }\n const userFromDB: UserModel = await this.authMethod.validateUser(loginOrEmail, password, req.ip, AUTH_SCOPE.WEBDAV)\n if (userFromDB !== null) {\n userFromDB.removePassword()\n }\n const userToCache: Record<string, any> | null = userFromDB ? instanceToPlain(userFromDB, { excludePrefixes: ['_'] }) : null\n this.cache.set(authBasicUser, userToCache, this.CACHE_TTL).catch((e: Error) => this.logger.error(`${this.validate.name} - ${e}`))\n return userFromDB\n }\n}\n"],"names":["AuthBasicStrategy","PassportStrategy","BasicStrategy","validate","req","loginOrEmail","password","trim","logger","assign","user","authBasicUser","CACHE_KEY_PREFIX","headers","split","at","toLowerCase","userFromCache","cache","get","undefined","plainToInstance","UserModel","userFromDB","authMethod","validateUser","ip","AUTH_SCOPE","WEBDAV","removePassword","userToCache","instanceToPlain","excludePrefixes","set","CACHE_TTL","catch","e","error","name","passReqToCallback","realm","SERVER_NAME"],"mappings":"AAAA;;;;CAIC;;;;+BAeYA;;;eAAAA;;;wBAbc;0BACwB;kCACF;4BAEtB;8BACG;2BACJ;wBACE;8BACN;uBACK;4BACA;;;;;;;;;;AAGpB,IAAA,AAAMA,oBAAN,MAAMA,0BAA0BC,IAAAA,0BAAgB,EAACC,2BAAa,EAAE;IAYrE,MAAMC,SAASC,GAAmB,EAAEC,YAAoB,EAAEC,QAAgB,EAA+C;QACvHD,eAAeA,aAAaE,IAAI;QAChCD,WAAWA,SAASC,IAAI;QACxB,IAAI,CAACC,MAAM,CAACC,MAAM,CAAC;YAAEC,MAAML;QAAa;QACxC,MAAMM,gBAAgB,GAAG,IAAI,CAACC,gBAAgB,CAAC,CAAC,EAAER,IAAIS,OAAO,CAAC,gBAAgB,CAACC,KAAK,CAAC,KAAKC,EAAE,CAAC,CAAC,GAAGC,WAAW,IAAI;QAChH,MAAMC,gBAAqB,MAAM,IAAI,CAACC,KAAK,CAACC,GAAG,CAACR;QAChD,IAAIM,kBAAkB,MAAM;YAC1B,iBAAiB;YACjB,OAAO;QACT;QACA,IAAIA,kBAAkBG,WAAW;YAC/B,SAAS;YACT,uEAAuE;YACvE,OAAOC,IAAAA,iCAAe,EAACC,oBAAS,EAAEL;QACpC;QACA,MAAMM,aAAwB,MAAM,IAAI,CAACC,UAAU,CAACC,YAAY,CAACpB,cAAcC,UAAUF,IAAIsB,EAAE,EAAEC,iBAAU,CAACC,MAAM;QAClH,IAAIL,eAAe,MAAM;YACvBA,WAAWM,cAAc;QAC3B;QACA,MAAMC,cAA0CP,aAAaQ,IAAAA,iCAAe,EAACR,YAAY;YAAES,iBAAiB;gBAAC;aAAI;QAAC,KAAK;QACvH,IAAI,CAACd,KAAK,CAACe,GAAG,CAACtB,eAAemB,aAAa,IAAI,CAACI,SAAS,EAAEC,KAAK,CAAC,CAACC,IAAa,IAAI,CAAC5B,MAAM,CAAC6B,KAAK,CAAC,GAAG,IAAI,CAAClC,QAAQ,CAACmC,IAAI,CAAC,GAAG,EAAEF,GAAG;QAC/H,OAAOb;IACT;IA9BA,YACE,AAAiBC,UAAsB,EACvC,AAAiBN,KAAY,EAC7B,AAAiBV,MAAkB,CACnC;QACA,KAAK,CAAC;YAAE+B,mBAAmB;YAAMC,OAAOC,mBAAW;QAAC,SAJnCjB,aAAAA,iBACAN,QAAAA,YACAV,SAAAA,aANF0B,YAAY,UACZtB,mBAAmB;IAQpC;AAyBF"}
@@ -28,6 +28,8 @@ function _ts_metadata(k, v) {
28
28
  }
29
29
  let AuthLocalStrategy = class AuthLocalStrategy extends (0, _passport.PassportStrategy)(_passportlocal.Strategy, 'local') {
30
30
  async validate(req, loginOrEmail, password) {
31
+ loginOrEmail = loginOrEmail.trim();
32
+ password = password.trim();
31
33
  this.logger.assign({
32
34
  user: loginOrEmail
33
35
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../backend/src/authentication/guards/auth-local.strategy.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 { Injectable, UnauthorizedException } from '@nestjs/common'\nimport { PassportStrategy, AbstractStrategy } from '@nestjs/passport'\nimport type { FastifyRequest } from 'fastify'\nimport { PinoLogger } from 'nestjs-pino'\nimport { Strategy } from 'passport-local'\nimport type { UserModel } from '../../applications/users/models/user.model'\nimport { AuthMethod } from '../models/auth-method'\n\n@Injectable()\nexport class AuthLocalStrategy extends PassportStrategy(Strategy, 'local') implements AbstractStrategy {\n constructor(\n private readonly authMethod: AuthMethod,\n private readonly logger: PinoLogger\n ) {\n super({ usernameField: 'login', passwordField: 'password', passReqToCallback: true })\n }\n\n async validate(req: FastifyRequest, loginOrEmail: string, password: string): Promise<UserModel> {\n this.logger.assign({ user: loginOrEmail })\n const user: UserModel = await this.authMethod.validateUser(loginOrEmail, password, req.ip)\n if (user) {\n user.removePassword()\n return user\n }\n throw new UnauthorizedException('Wrong login or password')\n }\n}\n"],"names":["AuthLocalStrategy","PassportStrategy","Strategy","validate","req","loginOrEmail","password","logger","assign","user","authMethod","validateUser","ip","removePassword","UnauthorizedException","usernameField","passwordField","passReqToCallback"],"mappings":"AAAA;;;;CAIC;;;;+BAWYA;;;eAAAA;;;wBATqC;0BACC;4BAExB;+BACF;4BAEE;;;;;;;;;;AAGpB,IAAA,AAAMA,oBAAN,MAAMA,0BAA0BC,IAAAA,0BAAgB,EAACC,uBAAQ,EAAE;IAQhE,MAAMC,SAASC,GAAmB,EAAEC,YAAoB,EAAEC,QAAgB,EAAsB;QAC9F,IAAI,CAACC,MAAM,CAACC,MAAM,CAAC;YAAEC,MAAMJ;QAAa;QACxC,MAAMI,OAAkB,MAAM,IAAI,CAACC,UAAU,CAACC,YAAY,CAACN,cAAcC,UAAUF,IAAIQ,EAAE;QACzF,IAAIH,MAAM;YACRA,KAAKI,cAAc;YACnB,OAAOJ;QACT;QACA,MAAM,IAAIK,6BAAqB,CAAC;IAClC;IAfA,YACE,AAAiBJ,UAAsB,EACvC,AAAiBH,MAAkB,CACnC;QACA,KAAK,CAAC;YAAEQ,eAAe;YAASC,eAAe;YAAYC,mBAAmB;QAAK,SAHlEP,aAAAA,iBACAH,SAAAA;IAGnB;AAWF"}
1
+ {"version":3,"sources":["../../../../backend/src/authentication/guards/auth-local.strategy.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 { Injectable, UnauthorizedException } from '@nestjs/common'\nimport { AbstractStrategy, PassportStrategy } from '@nestjs/passport'\nimport type { FastifyRequest } from 'fastify'\nimport { PinoLogger } from 'nestjs-pino'\nimport { Strategy } from 'passport-local'\nimport type { UserModel } from '../../applications/users/models/user.model'\nimport { AuthMethod } from '../models/auth-method'\n\n@Injectable()\nexport class AuthLocalStrategy extends PassportStrategy(Strategy, 'local') implements AbstractStrategy {\n constructor(\n private readonly authMethod: AuthMethod,\n private readonly logger: PinoLogger\n ) {\n super({ usernameField: 'login', passwordField: 'password', passReqToCallback: true })\n }\n\n async validate(req: FastifyRequest, loginOrEmail: string, password: string): Promise<UserModel> {\n loginOrEmail = loginOrEmail.trim()\n password = password.trim()\n this.logger.assign({ user: loginOrEmail })\n const user: UserModel = await this.authMethod.validateUser(loginOrEmail, password, req.ip)\n if (user) {\n user.removePassword()\n return user\n }\n throw new UnauthorizedException('Wrong login or password')\n }\n}\n"],"names":["AuthLocalStrategy","PassportStrategy","Strategy","validate","req","loginOrEmail","password","trim","logger","assign","user","authMethod","validateUser","ip","removePassword","UnauthorizedException","usernameField","passwordField","passReqToCallback"],"mappings":"AAAA;;;;CAIC;;;;+BAWYA;;;eAAAA;;;wBATqC;0BACC;4BAExB;+BACF;4BAEE;;;;;;;;;;AAGpB,IAAA,AAAMA,oBAAN,MAAMA,0BAA0BC,IAAAA,0BAAgB,EAACC,uBAAQ,EAAE;IAQhE,MAAMC,SAASC,GAAmB,EAAEC,YAAoB,EAAEC,QAAgB,EAAsB;QAC9FD,eAAeA,aAAaE,IAAI;QAChCD,WAAWA,SAASC,IAAI;QACxB,IAAI,CAACC,MAAM,CAACC,MAAM,CAAC;YAAEC,MAAML;QAAa;QACxC,MAAMK,OAAkB,MAAM,IAAI,CAACC,UAAU,CAACC,YAAY,CAACP,cAAcC,UAAUF,IAAIS,EAAE;QACzF,IAAIH,MAAM;YACRA,KAAKI,cAAc;YACnB,OAAOJ;QACT;QACA,MAAM,IAAIK,6BAAqB,CAAC;IAClC;IAjBA,YACE,AAAiBJ,UAAsB,EACvC,AAAiBH,MAAkB,CACnC;QACA,KAAK,CAAC;YAAEQ,eAAe;YAASC,eAAe;YAAYC,mBAAmB;QAAK,SAHlEP,aAAAA,iBACAH,SAAAA;IAGnB;AAaF"}