@sync-in/server 1.8.1 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -11
- package/environment/environment.dist.yaml +29 -26
- package/package.json +15 -15
- package/server/app.constants.js +9 -0
- package/server/app.constants.js.map +1 -1
- package/server/app.functions.js +42 -0
- package/server/app.functions.js.map +1 -0
- package/server/app.module.js +4 -0
- package/server/app.module.js.map +1 -1
- package/server/applications/admin/admin.module.js +6 -1
- package/server/applications/admin/admin.module.js.map +1 -1
- package/server/applications/{notifications/interfaces/user-mail-notification.js → admin/interfaces/check-update.interfaces.js} +1 -1
- package/server/applications/admin/interfaces/check-update.interfaces.js.map +1 -0
- package/server/applications/admin/services/admin-scheduler.service.js +53 -0
- package/server/applications/admin/services/admin-scheduler.service.js.map +1 -0
- package/server/applications/admin/services/admin.service.js +102 -0
- package/server/applications/admin/services/admin.service.js.map +1 -0
- package/server/applications/admin/services/admin.service.spec.js +46 -0
- package/server/applications/admin/services/admin.service.spec.js.map +1 -0
- package/server/applications/admin/utils/check-update.js +28 -0
- package/server/applications/admin/utils/check-update.js.map +1 -0
- package/server/applications/comments/services/comments-manager.service.js +1 -1
- package/server/applications/comments/services/comments-manager.service.js.map +1 -1
- package/server/applications/comments/services/comments-manager.service.spec.js +1 -1
- package/server/applications/comments/services/comments-manager.service.spec.js.map +1 -1
- package/server/applications/comments/services/comments-queries.service.js.map +1 -1
- package/server/applications/files/constants/cache.js +10 -1
- package/server/applications/files/constants/cache.js.map +1 -1
- package/server/applications/files/constants/only-office.js +0 -25
- package/server/applications/files/constants/only-office.js.map +1 -1
- package/server/applications/files/constants/operations.js +20 -3
- package/server/applications/files/constants/operations.js.map +1 -1
- package/server/applications/files/dto/file-operations.dto.js +7 -0
- package/server/applications/files/dto/file-operations.dto.js.map +1 -1
- package/server/applications/files/files-only-office.controller.js +3 -2
- package/server/applications/files/files-only-office.controller.js.map +1 -1
- package/server/applications/files/files-only-office.controller.spec.js +6 -5
- package/server/applications/files/files-only-office.controller.spec.js.map +1 -1
- package/server/applications/files/files.controller.js +88 -8
- package/server/applications/files/files.controller.js.map +1 -1
- package/server/applications/files/files.controller.spec.js +11 -4
- package/server/applications/files/files.controller.spec.js.map +1 -1
- package/server/applications/files/guards/files-only-office.guard.js +6 -0
- package/server/applications/files/guards/files-only-office.guard.js.map +1 -1
- package/server/applications/files/interfaces/file-db-props.interface.js.map +1 -1
- package/server/applications/files/interfaces/file-props.interface.js.map +1 -1
- package/server/applications/files/interfaces/only-office-config.interface.js.map +1 -1
- package/server/applications/files/services/files-content-manager.service.js +3 -3
- package/server/applications/files/services/files-content-manager.service.js.map +1 -1
- package/server/applications/files/services/files-lock-manager.service.js +61 -22
- package/server/applications/files/services/files-lock-manager.service.js.map +1 -1
- package/server/applications/files/services/files-manager.service.js +122 -24
- package/server/applications/files/services/files-manager.service.js.map +1 -1
- package/server/applications/files/services/files-manager.service.spec.js +15 -0
- package/server/applications/files/services/files-manager.service.spec.js.map +1 -1
- package/server/applications/files/services/files-methods.service.js +38 -8
- package/server/applications/files/services/files-methods.service.js.map +1 -1
- package/server/applications/files/services/files-only-office-manager.service.js +12 -12
- package/server/applications/files/services/files-only-office-manager.service.js.map +1 -1
- package/server/applications/files/services/files-parser.service.js +1 -1
- package/server/applications/files/services/files-parser.service.js.map +1 -1
- package/server/applications/files/services/files-queries.service.js +10 -0
- package/server/applications/files/services/files-queries.service.js.map +1 -1
- package/server/applications/files/utils/files.js +1 -1
- package/server/applications/files/utils/files.js.map +1 -1
- package/server/applications/files/utils/send-file.js +3 -2
- package/server/applications/files/utils/send-file.js.map +1 -1
- package/server/applications/links/services/links-queries.service.js +1 -1
- package/server/applications/links/services/links-queries.service.js.map +1 -1
- package/server/applications/notifications/constants/notifications.js +5 -1
- package/server/applications/notifications/constants/notifications.js.map +1 -1
- package/server/applications/notifications/i18n/de.js +8 -2
- package/server/applications/notifications/i18n/de.js.map +1 -1
- package/server/applications/notifications/i18n/es.js +8 -2
- package/server/applications/notifications/i18n/es.js.map +1 -1
- package/server/applications/notifications/i18n/fr.js +8 -2
- package/server/applications/notifications/i18n/fr.js.map +1 -1
- package/server/applications/notifications/i18n/hi.js +8 -2
- package/server/applications/notifications/i18n/hi.js.map +1 -1
- package/server/applications/notifications/i18n/it.js +8 -2
- package/server/applications/notifications/i18n/it.js.map +1 -1
- package/server/applications/notifications/i18n/ja.js +8 -2
- package/server/applications/notifications/i18n/ja.js.map +1 -1
- package/server/applications/notifications/i18n/ko.js +8 -2
- package/server/applications/notifications/i18n/ko.js.map +1 -1
- package/server/applications/notifications/i18n/pl.js +8 -2
- package/server/applications/notifications/i18n/pl.js.map +1 -1
- package/server/applications/notifications/i18n/pt.js +8 -2
- package/server/applications/notifications/i18n/pt.js.map +1 -1
- package/server/applications/notifications/i18n/pt_br.js +8 -2
- package/server/applications/notifications/i18n/pt_br.js.map +1 -1
- package/server/applications/notifications/i18n/ru.js +8 -2
- package/server/applications/notifications/i18n/ru.js.map +1 -1
- package/server/applications/notifications/i18n/tr.js +8 -2
- package/server/applications/notifications/i18n/tr.js.map +1 -1
- package/server/applications/notifications/i18n/zh.js +8 -2
- package/server/applications/notifications/i18n/zh.js.map +1 -1
- package/server/applications/notifications/interfaces/notification-properties.interface.js.map +1 -1
- package/server/applications/notifications/interfaces/user-mail-notification.interface.js +10 -0
- package/server/applications/notifications/interfaces/user-mail-notification.interface.js.map +1 -0
- package/server/applications/notifications/mails/models.js +38 -3
- package/server/applications/notifications/mails/models.js.map +1 -1
- package/server/applications/notifications/mails/templates.js +1 -1
- package/server/applications/notifications/mails/templates.js.map +1 -1
- package/server/applications/notifications/services/notifications-manager.service.js +8 -1
- package/server/applications/notifications/services/notifications-manager.service.js.map +1 -1
- package/server/applications/notifications/services/notifications-queries.service.js.map +1 -1
- package/server/applications/shares/services/shares-manager.service.js +17 -10
- package/server/applications/shares/services/shares-manager.service.js.map +1 -1
- package/server/applications/shares/services/shares-manager.service.spec.js +10 -3
- package/server/applications/shares/services/shares-manager.service.spec.js.map +1 -1
- package/server/applications/shares/services/shares-queries.service.js +11 -1
- package/server/applications/shares/services/shares-queries.service.js.map +1 -1
- package/server/applications/spaces/guards/space.guard.spec.js +2 -2
- package/server/applications/spaces/guards/space.guard.spec.js.map +1 -1
- package/server/applications/spaces/services/spaces-browser.service.js +31 -11
- package/server/applications/spaces/services/spaces-browser.service.js.map +1 -1
- package/server/applications/spaces/services/spaces-manager.service.js +2 -2
- package/server/applications/spaces/services/spaces-manager.service.js.map +1 -1
- package/server/applications/spaces/services/spaces-queries.service.js +6 -2
- package/server/applications/spaces/services/spaces-queries.service.js.map +1 -1
- package/server/applications/spaces/utils/permissions.js +2 -2
- package/server/applications/spaces/utils/permissions.js.map +1 -1
- package/server/applications/sync/services/sync-manager.service.js +1 -0
- package/server/applications/sync/services/sync-manager.service.js.map +1 -1
- package/server/applications/sync/services/sync-paths-manager.service.js +1 -1
- package/server/applications/sync/services/sync-paths-manager.service.js.map +1 -1
- package/server/applications/sync/services/sync-paths-manager.service.spec.js +1 -1
- package/server/applications/sync/services/sync-paths-manager.service.spec.js.map +1 -1
- package/server/applications/users/constants/user.js +1 -1
- package/server/applications/users/constants/user.js.map +1 -1
- package/server/applications/users/services/admin-users-queries.service.js +8 -0
- package/server/applications/users/services/admin-users-queries.service.js.map +1 -1
- package/server/applications/users/services/users-queries.service.js +67 -68
- package/server/applications/users/services/users-queries.service.js.map +1 -1
- package/server/applications/users/users.module.js +2 -1
- package/server/applications/users/users.module.js.map +1 -1
- package/server/applications/webdav/guards/webdav-protocol.guard.js +4 -4
- package/server/applications/webdav/guards/webdav-protocol.guard.js.map +1 -1
- package/server/applications/webdav/guards/webdav-protocol.guard.spec.js +6 -6
- package/server/applications/webdav/guards/webdav-protocol.guard.spec.js.map +1 -1
- package/server/applications/webdav/services/webdav-methods.service.js +3 -2
- package/server/applications/webdav/services/webdav-methods.service.js.map +1 -1
- package/server/applications/webdav/services/webdav-methods.service.spec.js +2 -2
- package/server/applications/webdav/services/webdav-methods.service.spec.js.map +1 -1
- package/server/authentication/constants/auth-ldap.js +2 -0
- package/server/authentication/constants/auth-ldap.js.map +1 -1
- package/server/authentication/services/auth-methods/auth-method-ldap.service.js +34 -21
- package/server/authentication/services/auth-methods/auth-method-ldap.service.js.map +1 -1
- package/server/common/functions.js +0 -8
- package/server/common/functions.js.map +1 -1
- package/server/common/image.js +1 -0
- package/server/common/image.js.map +1 -1
- package/server/common/shared.js +18 -1
- package/server/common/shared.js.map +1 -1
- package/server/infrastructure/context/services/context-manager.service.js +3 -0
- package/server/infrastructure/context/services/context-manager.service.js.map +1 -1
- package/server/infrastructure/websocket/adapters/cluster.adapter.js +4 -4
- package/server/infrastructure/websocket/adapters/cluster.adapter.js.map +1 -1
- package/static/3rdpartylicenses.txt +1393 -44
- package/static/assets/favicon.svg +2 -25
- package/static/assets/logo-dark.svg +2 -32
- package/static/assets/logo.svg +2 -32
- package/static/assets/mimes/application-sql.svg +29 -1
- package/static/assets/mimes/application-x-sql.svg +29 -0
- package/static/assets/mimes/image-bmp.svg +12 -0
- package/static/assets/pdfjs/build/pdf.mjs +4869 -4454
- package/static/assets/pdfjs/build/pdf.mjs.map +1 -1
- package/static/assets/pdfjs/build/pdf.sandbox.mjs +3 -3
- package/static/assets/pdfjs/build/pdf.sandbox.mjs.map +1 -1
- package/static/assets/pdfjs/build/pdf.worker.mjs +885 -596
- package/static/assets/pdfjs/build/pdf.worker.mjs.map +1 -1
- package/static/assets/pdfjs/version +1 -1
- package/static/assets/pdfjs/web/locale/be/viewer.ftl +40 -0
- package/static/assets/pdfjs/web/locale/bg/viewer.ftl +2 -0
- package/static/assets/pdfjs/web/locale/cs/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/cy/viewer.ftl +43 -0
- package/static/assets/pdfjs/web/locale/da/viewer.ftl +39 -0
- package/static/assets/pdfjs/web/locale/de/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/dsb/viewer.ftl +43 -0
- package/static/assets/pdfjs/web/locale/el/viewer.ftl +39 -0
- package/static/assets/pdfjs/web/locale/en-CA/viewer.ftl +35 -0
- package/static/assets/pdfjs/web/locale/en-GB/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/en-US/viewer.ftl +2 -2
- package/static/assets/pdfjs/web/locale/eo/viewer.ftl +39 -0
- package/static/assets/pdfjs/web/locale/es-AR/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/es-CL/viewer.ftl +39 -0
- package/static/assets/pdfjs/web/locale/es-ES/viewer.ftl +72 -0
- package/static/assets/pdfjs/web/locale/es-MX/viewer.ftl +120 -0
- package/static/assets/pdfjs/web/locale/eu/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/fi/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/fr/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/fur/viewer.ftl +77 -0
- package/static/assets/pdfjs/web/locale/fy-NL/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/gn/viewer.ftl +39 -0
- package/static/assets/pdfjs/web/locale/he/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/hsb/viewer.ftl +43 -0
- package/static/assets/pdfjs/web/locale/hu/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/hy-AM/viewer.ftl +1 -1
- package/static/assets/pdfjs/web/locale/ia/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/it/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/ja/viewer.ftl +32 -0
- package/static/assets/pdfjs/web/locale/ka/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/kab/viewer.ftl +73 -0
- package/static/assets/pdfjs/web/locale/kk/viewer.ftl +21 -0
- package/static/assets/pdfjs/web/locale/ko/viewer.ftl +38 -1
- package/static/assets/pdfjs/web/locale/nb-NO/viewer.ftl +39 -0
- package/static/assets/pdfjs/web/locale/nl/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/nn-NO/viewer.ftl +37 -0
- package/static/assets/pdfjs/web/locale/pa-IN/viewer.ftl +37 -0
- package/static/assets/pdfjs/web/locale/pl/viewer.ftl +39 -0
- package/static/assets/pdfjs/web/locale/pt-BR/viewer.ftl +39 -0
- package/static/assets/pdfjs/web/locale/rm/viewer.ftl +73 -0
- package/static/assets/pdfjs/web/locale/ro/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/ru/viewer.ftl +42 -0
- package/static/assets/pdfjs/web/locale/sc/viewer.ftl +6 -0
- package/static/assets/pdfjs/web/locale/sk/viewer.ftl +43 -0
- package/static/assets/pdfjs/web/locale/sl/viewer.ftl +42 -1
- package/static/assets/pdfjs/web/locale/sq/viewer.ftl +77 -0
- package/static/assets/pdfjs/web/locale/sv-SE/viewer.ftl +41 -0
- package/static/assets/pdfjs/web/locale/tg/viewer.ftl +39 -0
- package/static/assets/pdfjs/web/locale/th/viewer.ftl +35 -0
- package/static/assets/pdfjs/web/locale/tr/viewer.ftl +39 -0
- package/static/assets/pdfjs/web/locale/vi/viewer.ftl +42 -5
- package/static/assets/pdfjs/web/locale/zh-CN/viewer.ftl +35 -0
- package/static/assets/pdfjs/web/locale/zh-TW/viewer.ftl +37 -0
- package/static/assets/pdfjs/web/viewer.css +141 -110
- package/static/assets/pdfjs/web/viewer.html +7 -7
- package/static/assets/pdfjs/web/viewer.mjs +97 -14
- package/static/assets/pdfjs/web/viewer.mjs.map +1 -1
- package/static/chunk-22DWHRCL.js +1 -0
- package/static/chunk-23UUFZSR.js +1 -0
- package/static/chunk-25QTY2GI.js +1 -0
- package/static/chunk-2E7IJZLL.js +1 -0
- package/static/chunk-2FC5EKS5.js +1 -0
- package/static/chunk-2TB2INBF.js +1 -0
- package/static/chunk-32L7RG2G.js +1 -0
- package/static/chunk-3OHSTP3R.js +1 -0
- package/static/chunk-3WLBVJ2S.js +1 -0
- package/static/{chunk-MTVSJTIW.js → chunk-3YDYZLF7.js} +1 -1
- package/static/chunk-42L6C5MT.js +1 -0
- package/static/chunk-4AGQL5GV.js +1 -0
- package/static/chunk-4BPSQMI2.js +1 -0
- package/static/chunk-4FDRWZWT.js +1 -0
- package/static/chunk-4GCCF6PF.js +1 -0
- package/static/chunk-4ORP3SBY.js +1 -0
- package/static/chunk-4PZPHJ7L.js +1 -0
- package/static/chunk-4QBOHIC3.js +1 -0
- package/static/chunk-4YT6K5KY.js +1 -0
- package/static/chunk-556I6YIW.js +1 -0
- package/static/chunk-5DPIGJU4.js +1 -0
- package/static/chunk-5E3TYOL3.js +1 -0
- package/static/chunk-5IL7C45D.js +1 -0
- package/static/chunk-5KJXGMKR.js +1 -0
- package/static/chunk-5S6KPQRA.js +1 -0
- package/static/chunk-5SPGSHKL.js +1 -0
- package/static/chunk-5WCQBTXW.js +1 -0
- package/static/chunk-5XUIPWOH.js +1 -0
- package/static/chunk-62WT7PI3.js +1 -0
- package/static/chunk-6B3GGAV3.js +4 -0
- package/static/chunk-6F6OMQ5H.js +1 -0
- package/static/chunk-6I5BGQHT.js +1 -0
- package/static/chunk-6NEBGCAZ.js +1 -0
- package/static/chunk-6NOS45DG.js +1 -0
- package/static/chunk-6OKLPRCD.js +1 -0
- package/static/chunk-6VEJCG43.js +1 -0
- package/static/chunk-77SS36Z2.js +1 -0
- package/static/chunk-7AXEPO3G.js +1 -0
- package/static/chunk-7CKHC72R.js +1 -0
- package/static/chunk-7DUTYOJG.js +1 -0
- package/static/chunk-7HKFYRPF.js +1 -0
- package/static/chunk-7NZJZATZ.js +1 -0
- package/static/chunk-AADK5D2H.js +1 -0
- package/static/chunk-ACUF7IKP.js +1 -0
- package/static/chunk-AGREZPV4.js +1 -0
- package/static/chunk-ATBJWFA3.js +1 -0
- package/static/chunk-ATXLZN2B.js +1 -0
- package/static/chunk-AZ5TF5Y3.js +1 -0
- package/static/chunk-BBHYIURC.js +1 -0
- package/static/chunk-BHZEPHRI.js +13 -0
- package/static/chunk-BODMMLVB.js +7 -0
- package/static/chunk-BSB4VROD.js +2 -0
- package/static/chunk-BU4ZICZR.js +1 -0
- package/static/chunk-C3AAEQKW.js +1 -0
- package/static/chunk-CFTKW432.js +1 -0
- package/static/chunk-CNOVT6KU.js +1 -0
- package/static/chunk-D56H3XE2.js +1 -0
- package/static/chunk-DFOOSIIA.js +1 -0
- package/static/chunk-DHFQIFOF.js +1 -0
- package/static/{chunk-3GMLWAFZ.js → chunk-DIC2MVRI.js} +1 -1
- package/static/chunk-DJDRX53V.js +2 -0
- package/static/chunk-DKGXUMLT.js +1 -0
- package/static/chunk-DQ3GEMPM.js +1 -0
- package/static/chunk-DRHPEERW.js +2 -0
- package/static/chunk-DWYP6ZGG.js +1 -0
- package/static/chunk-EDJAISWO.js +13 -0
- package/static/chunk-EIYRBM4J.js +1 -0
- package/static/chunk-EL6QL4TP.js +1 -0
- package/static/chunk-ERDZ7IVF.js +1 -0
- package/static/chunk-EVQKKVUZ.js +1 -0
- package/static/chunk-F2XG7EWI.js +1 -0
- package/static/chunk-F672FY5I.js +1 -0
- package/static/chunk-F6V37MKG.js +1 -0
- package/static/chunk-FCGTI42I.js +1 -0
- package/static/chunk-FNOTGWRW.js +1 -0
- package/static/chunk-FQHOSSCO.js +1 -0
- package/static/chunk-GAGHHYLF.js +1 -0
- package/static/chunk-GNZPP2VO.js +1 -0
- package/static/{chunk-JPT5WEAT.js → chunk-GOJYWL2M.js} +1 -1
- package/static/chunk-GRLHFXGB.js +1 -0
- package/static/chunk-H6WOTGQ5.js +1 -0
- package/static/{chunk-CHJ64RJM.js → chunk-H6ZXFINQ.js} +1 -1
- package/static/chunk-HC7F57NA.js +1 -0
- package/static/chunk-HCSWO7BO.js +7 -0
- package/static/chunk-HHWXIK2M.js +7 -0
- package/static/chunk-HKRGIRKB.js +3 -0
- package/static/chunk-HMOB6XC5.js +1 -0
- package/static/chunk-HNMGPG72.js +1 -0
- package/static/chunk-HS4S6BV3.js +1 -0
- package/static/chunk-I2S3XPC5.js +3 -0
- package/static/chunk-IJ7K7ATQ.js +1 -0
- package/static/chunk-IOIBQGHN.js +562 -0
- package/static/chunk-ITVA26X2.js +2 -0
- package/static/chunk-J6YSFHLZ.js +1 -0
- package/static/chunk-JAEJ6IMV.js +1 -0
- package/static/chunk-JB5R6V33.js +1 -0
- package/static/chunk-JF6WIV6M.js +1 -0
- package/static/chunk-JGB4LLUT.js +1 -0
- package/static/chunk-JGXVTKLG.js +1 -0
- package/static/chunk-JMYAD7E2.js +1 -0
- package/static/chunk-JSE63Q5X.js +1 -0
- package/static/chunk-JVV3ZL6L.js +1 -0
- package/static/chunk-JWPXQOS3.js +5 -0
- package/static/chunk-JXZCNFW7.js +1 -0
- package/static/chunk-JY2I3HGL.js +1 -0
- package/static/chunk-K657XPXA.js +1 -0
- package/static/chunk-KAVP6UXH.js +1 -0
- package/static/{chunk-3R74L4UU.js → chunk-KDEEERWZ.js} +1 -1
- package/static/chunk-KLOUBIO4.js +1 -0
- package/static/chunk-KMF3ZRAO.js +1 -0
- package/static/chunk-KT3TWCST.js +1 -0
- package/static/chunk-L6SYG23T.js +1 -0
- package/static/{chunk-LNTUR3GU.js → chunk-LRDKG274.js} +1 -1
- package/static/chunk-LRQSPCYZ.js +1 -0
- package/static/chunk-LUSVISM6.js +1 -0
- package/static/{chunk-LVSNIS5P.js → chunk-LYZGJZNP.js} +1 -1
- package/static/chunk-LZKI5P5T.js +1 -0
- package/static/chunk-M4XL3JN5.js +6 -0
- package/static/{chunk-UNCPXHHT.js → chunk-MGWG7OD7.js} +1 -1
- package/static/chunk-MIA5YBOI.js +1 -0
- package/static/chunk-MKUUWY6Y.js +1 -0
- package/static/chunk-MR3U7TKQ.js +1 -0
- package/static/chunk-MYM43ENO.js +1 -0
- package/static/chunk-NAH4V2R6.js +2 -0
- package/static/chunk-NBBDVVUF.js +1 -0
- package/static/chunk-NKGKBQBX.js +1 -0
- package/static/chunk-NMF2ZFBE.js +1 -0
- package/static/chunk-NN4ONTOT.js +1 -0
- package/static/chunk-NOPACN4F.js +1 -0
- package/static/chunk-NYJPOP4L.js +1 -0
- package/static/chunk-OQRWXCLY.js +1 -0
- package/static/chunk-PCFH5HCI.js +2 -0
- package/static/chunk-PJF5XUTO.js +1 -0
- package/static/{chunk-FJE6BOFL.js → chunk-PSUAQBYM.js} +1 -1
- package/static/chunk-PTLYIUFW.js +1 -0
- package/static/chunk-PXRT4L57.js +1 -0
- package/static/chunk-PZGLDZZM.js +1 -0
- package/static/chunk-Q4VNZGFI.js +1 -0
- package/static/chunk-Q556XB3S.js +1 -0
- package/static/{chunk-PB4AIT7O.js → chunk-Q7IXRPOO.js} +1 -1
- package/static/chunk-Q7U2VPIS.js +1 -0
- package/static/chunk-QM6CQMEX.js +1 -0
- package/static/chunk-QMHUIHSR.js +1 -0
- package/static/chunk-QVFPHTOH.js +1 -0
- package/static/chunk-R4MI25E2.js +1 -0
- package/static/chunk-R7JRAR3P.js +1 -0
- package/static/chunk-R7PNKQU2.js +1 -0
- package/static/chunk-RCAORRB7.js +1 -0
- package/static/chunk-RDNTK4YH.js +1 -0
- package/static/{chunk-VJTXJ43D.js → chunk-RK2ONYTL.js} +1 -1
- package/static/chunk-RK7XRDNB.js +1 -0
- package/static/chunk-RO7SAOLK.js +1 -0
- package/static/chunk-RQUUINHV.js +1 -0
- package/static/chunk-RUN556VW.js +1 -0
- package/static/chunk-S2VBGI6Q.js +1 -0
- package/static/chunk-S7S5M3AZ.js +1 -0
- package/static/chunk-SBLNYV74.js +1 -0
- package/static/chunk-SIZCHHUA.js +1 -0
- package/static/chunk-SRBOO7AO.js +1 -0
- package/static/{chunk-PVDHBQRM.js → chunk-STA7NTYL.js} +1 -1
- package/static/chunk-T3YI3BSS.js +1 -0
- package/static/chunk-TAL3RTTQ.js +1 -0
- package/static/chunk-TGLJFALR.js +1 -0
- package/static/chunk-TJZKTNNS.js +1 -0
- package/static/chunk-U4RW6XG5.js +1 -0
- package/static/chunk-UJTFWZEC.js +1 -0
- package/static/chunk-UPGVU5LG.js +1 -0
- package/static/chunk-UQ6O3I6W.js +1 -0
- package/static/{chunk-5NMSIIQB.js → chunk-V43RGNXA.js} +1 -1
- package/static/chunk-V6FA5QY4.js +1 -0
- package/static/chunk-VK7XMFVE.js +1 -0
- package/static/chunk-VQJYCYWI.js +1 -0
- package/static/chunk-VWIRXLNE.js +1 -0
- package/static/chunk-VZMVGIVW.js +1 -0
- package/static/chunk-VZPCXSRG.js +2 -0
- package/static/chunk-WR3MA3L3.js +1 -0
- package/static/chunk-XCLK7NJL.js +1 -0
- package/static/{chunk-DSWEWLXJ.js → chunk-XCPDPB5G.js} +1 -1
- package/static/chunk-XEGHEUP5.js +1 -0
- package/static/chunk-XKEBQNQJ.js +1 -0
- package/static/chunk-XOF4UW3S.js +1 -0
- package/static/chunk-XQGPSNQB.js +1 -0
- package/static/{chunk-QO6BTONN.js → chunk-Y4MAPE2C.js} +1 -1
- package/static/chunk-Y5RLD72B.js +1 -0
- package/static/{chunk-DPUVSXRB.js → chunk-Y5XTRCFK.js} +1 -1
- package/static/chunk-Y63UUJGJ.js +1 -0
- package/static/chunk-YBNAC7QM.js +1 -0
- package/static/chunk-YCTCESL4.js +1 -0
- package/static/chunk-YMAN4LIU.js +1 -0
- package/static/chunk-YTDE6SXT.js +1 -0
- package/static/chunk-YZPIUJB3.js +1 -0
- package/static/chunk-ZCOWBVOT.js +1 -0
- package/static/chunk-ZHRYYMYE.js +1 -0
- package/static/chunk-ZNXTOQFG.js +1 -0
- package/static/{chunk-URHTCJ7G.js → chunk-ZQLBPLXI.js} +1 -1
- package/static/chunk-ZXXHFBGL.js +1 -0
- package/static/favicon.ico +0 -0
- package/static/index.html +2 -2
- package/static/main-56PZQ6TJ.js +11 -0
- package/static/styles-Q4OZOSSK.css +1 -0
- package/server/applications/notifications/interfaces/user-mail-notification.js.map +0 -1
- package/static/assets/codemirror/mode/apl/apl.js +0 -174
- package/static/assets/codemirror/mode/asciiarmor/asciiarmor.js +0 -74
- package/static/assets/codemirror/mode/asn.1/asn.1.js +0 -204
- package/static/assets/codemirror/mode/asterisk/asterisk.js +0 -220
- package/static/assets/codemirror/mode/brainfuck/brainfuck.js +0 -85
- package/static/assets/codemirror/mode/clike/clike.js +0 -942
- package/static/assets/codemirror/mode/clojure/clojure.js +0 -293
- package/static/assets/codemirror/mode/cmake/cmake.js +0 -97
- package/static/assets/codemirror/mode/cobol/cobol.js +0 -255
- package/static/assets/codemirror/mode/coffeescript/coffeescript.js +0 -359
- package/static/assets/codemirror/mode/commonlisp/commonlisp.js +0 -125
- package/static/assets/codemirror/mode/crystal/crystal.js +0 -433
- package/static/assets/codemirror/mode/css/css.js +0 -862
- package/static/assets/codemirror/mode/cypher/cypher.js +0 -152
- package/static/assets/codemirror/mode/d/d.js +0 -223
- package/static/assets/codemirror/mode/dart/dart.js +0 -168
- package/static/assets/codemirror/mode/diff/diff.js +0 -47
- package/static/assets/codemirror/mode/django/django.js +0 -356
- package/static/assets/codemirror/mode/dockerfile/dockerfile.js +0 -211
- package/static/assets/codemirror/mode/dtd/dtd.js +0 -142
- package/static/assets/codemirror/mode/dylan/dylan.js +0 -352
- package/static/assets/codemirror/mode/ebnf/ebnf.js +0 -195
- package/static/assets/codemirror/mode/ecl/ecl.js +0 -206
- package/static/assets/codemirror/mode/eiffel/eiffel.js +0 -160
- package/static/assets/codemirror/mode/elm/elm.js +0 -245
- package/static/assets/codemirror/mode/erlang/erlang.js +0 -619
- package/static/assets/codemirror/mode/factor/factor.js +0 -85
- package/static/assets/codemirror/mode/fcl/fcl.js +0 -173
- package/static/assets/codemirror/mode/forth/forth.js +0 -180
- package/static/assets/codemirror/mode/fortran/fortran.js +0 -188
- package/static/assets/codemirror/mode/gas/gas.js +0 -355
- package/static/assets/codemirror/mode/gfm/gfm.js +0 -129
- package/static/assets/codemirror/mode/gherkin/gherkin.js +0 -194
- package/static/assets/codemirror/mode/go/go.js +0 -187
- package/static/assets/codemirror/mode/groovy/groovy.js +0 -245
- package/static/assets/codemirror/mode/haml/haml.js +0 -161
- package/static/assets/codemirror/mode/handlebars/handlebars.js +0 -70
- package/static/assets/codemirror/mode/haskell/haskell.js +0 -268
- package/static/assets/codemirror/mode/haskell-literate/haskell-literate.js +0 -43
- package/static/assets/codemirror/mode/haxe/haxe.js +0 -515
- package/static/assets/codemirror/mode/htmlembedded/htmlembedded.js +0 -37
- package/static/assets/codemirror/mode/htmlmixed/htmlmixed.js +0 -153
- package/static/assets/codemirror/mode/http/http.js +0 -113
- package/static/assets/codemirror/mode/idl/idl.js +0 -290
- package/static/assets/codemirror/mode/javascript/javascript.js +0 -960
- package/static/assets/codemirror/mode/jinja2/jinja2.js +0 -193
- package/static/assets/codemirror/mode/jsx/jsx.js +0 -149
- package/static/assets/codemirror/mode/julia/julia.js +0 -390
- package/static/assets/codemirror/mode/livescript/livescript.js +0 -280
- package/static/assets/codemirror/mode/lua/lua.js +0 -160
- package/static/assets/codemirror/mode/markdown/markdown.js +0 -886
- package/static/assets/codemirror/mode/mathematica/mathematica.js +0 -176
- package/static/assets/codemirror/mode/mbox/mbox.js +0 -129
- package/static/assets/codemirror/mode/meta.js +0 -221
- package/static/assets/codemirror/mode/mirc/mirc.js +0 -193
- package/static/assets/codemirror/mode/mllike/mllike.js +0 -359
- package/static/assets/codemirror/mode/modelica/modelica.js +0 -245
- package/static/assets/codemirror/mode/mscgen/mscgen.js +0 -175
- package/static/assets/codemirror/mode/mumps/mumps.js +0 -148
- package/static/assets/codemirror/mode/nginx/nginx.js +0 -178
- package/static/assets/codemirror/mode/nsis/nsis.js +0 -95
- package/static/assets/codemirror/mode/ntriples/ntriples.js +0 -195
- package/static/assets/codemirror/mode/octave/octave.js +0 -139
- package/static/assets/codemirror/mode/oz/oz.js +0 -252
- package/static/assets/codemirror/mode/pascal/pascal.js +0 -136
- package/static/assets/codemirror/mode/pegjs/pegjs.js +0 -111
- package/static/assets/codemirror/mode/perl/perl.js +0 -836
- package/static/assets/codemirror/mode/php/php.js +0 -234
- package/static/assets/codemirror/mode/pig/pig.js +0 -178
- package/static/assets/codemirror/mode/powershell/powershell.js +0 -398
- package/static/assets/codemirror/mode/properties/properties.js +0 -78
- package/static/assets/codemirror/mode/protobuf/protobuf.js +0 -72
- package/static/assets/codemirror/mode/pug/pug.js +0 -591
- package/static/assets/codemirror/mode/puppet/puppet.js +0 -220
- package/static/assets/codemirror/mode/python/python.js +0 -402
- package/static/assets/codemirror/mode/q/q.js +0 -139
- package/static/assets/codemirror/mode/r/r.js +0 -190
- package/static/assets/codemirror/mode/rpm/changes/index.html +0 -66
- package/static/assets/codemirror/mode/rpm/rpm.js +0 -109
- package/static/assets/codemirror/mode/rst/rst.js +0 -557
- package/static/assets/codemirror/mode/ruby/ruby.js +0 -303
- package/static/assets/codemirror/mode/rust/rust.js +0 -72
- package/static/assets/codemirror/mode/sas/sas.js +0 -303
- package/static/assets/codemirror/mode/sass/sass.js +0 -459
- package/static/assets/codemirror/mode/scheme/scheme.js +0 -284
- package/static/assets/codemirror/mode/shell/shell.js +0 -168
- package/static/assets/codemirror/mode/sieve/sieve.js +0 -193
- package/static/assets/codemirror/mode/slim/slim.js +0 -575
- package/static/assets/codemirror/mode/smalltalk/smalltalk.js +0 -168
- package/static/assets/codemirror/mode/smarty/smarty.js +0 -225
- package/static/assets/codemirror/mode/solr/solr.js +0 -104
- package/static/assets/codemirror/mode/soy/soy.js +0 -665
- package/static/assets/codemirror/mode/sparql/sparql.js +0 -184
- package/static/assets/codemirror/mode/spreadsheet/spreadsheet.js +0 -112
- package/static/assets/codemirror/mode/sql/sql.js +0 -529
- package/static/assets/codemirror/mode/stex/stex.js +0 -264
- package/static/assets/codemirror/mode/stylus/stylus.js +0 -775
- package/static/assets/codemirror/mode/swift/swift.js +0 -221
- package/static/assets/codemirror/mode/tcl/tcl.js +0 -140
- package/static/assets/codemirror/mode/textile/textile.js +0 -469
- package/static/assets/codemirror/mode/tiddlywiki/tiddlywiki.css +0 -14
- package/static/assets/codemirror/mode/tiddlywiki/tiddlywiki.js +0 -308
- package/static/assets/codemirror/mode/tiki/tiki.css +0 -26
- package/static/assets/codemirror/mode/tiki/tiki.js +0 -312
- package/static/assets/codemirror/mode/toml/toml.js +0 -88
- package/static/assets/codemirror/mode/tornado/tornado.js +0 -68
- package/static/assets/codemirror/mode/troff/troff.js +0 -84
- package/static/assets/codemirror/mode/ttcn/ttcn.js +0 -283
- package/static/assets/codemirror/mode/ttcn-cfg/ttcn-cfg.js +0 -214
- package/static/assets/codemirror/mode/turtle/turtle.js +0 -162
- package/static/assets/codemirror/mode/twig/twig.js +0 -141
- package/static/assets/codemirror/mode/vb/vb.js +0 -275
- package/static/assets/codemirror/mode/vbscript/vbscript.js +0 -350
- package/static/assets/codemirror/mode/velocity/velocity.js +0 -202
- package/static/assets/codemirror/mode/verilog/verilog.js +0 -781
- package/static/assets/codemirror/mode/vhdl/vhdl.js +0 -189
- package/static/assets/codemirror/mode/vue/vue.js +0 -77
- package/static/assets/codemirror/mode/wast/wast.js +0 -132
- package/static/assets/codemirror/mode/webidl/webidl.js +0 -195
- package/static/assets/codemirror/mode/xml/xml.js +0 -417
- package/static/assets/codemirror/mode/xquery/xquery.js +0 -448
- package/static/assets/codemirror/mode/yacas/yacas.js +0 -204
- package/static/assets/codemirror/mode/yaml/yaml.js +0 -120
- package/static/assets/codemirror/mode/yaml-frontmatter/yaml-frontmatter.js +0 -72
- package/static/assets/codemirror/mode/z80/z80.js +0 -116
- package/static/chunk-2KLC4T2Z.js +0 -1
- package/static/chunk-2VMSXRCB.js +0 -12
- package/static/chunk-3OHSRRKH.js +0 -4
- package/static/chunk-3R4WKOHQ.js +0 -1
- package/static/chunk-3XVM35O2.js +0 -1
- package/static/chunk-3YVRP3VM.js +0 -2
- package/static/chunk-5UKZLU5H.js +0 -1
- package/static/chunk-AF24EYXU.js +0 -1
- package/static/chunk-AKQVEHO6.js +0 -2
- package/static/chunk-BCVX464U.js +0 -2
- package/static/chunk-BQV4FRM6.js +0 -1
- package/static/chunk-CETH7UYS.js +0 -1
- package/static/chunk-DIT6W7VM.js +0 -562
- package/static/chunk-DKSEQTMX.js +0 -1
- package/static/chunk-FZ3JPGYZ.js +0 -1
- package/static/chunk-IQSKQXC3.js +0 -1
- package/static/chunk-ITUFI2BJ.js +0 -1
- package/static/chunk-LCTZJ537.js +0 -1
- package/static/chunk-LK2UCQJ6.js +0 -1
- package/static/chunk-LP5TBXEN.js +0 -7
- package/static/chunk-N3U6637P.js +0 -1
- package/static/chunk-NNV4OXSB.js +0 -1
- package/static/chunk-O6FYXVHI.js +0 -1
- package/static/chunk-OOGP4WSH.js +0 -2
- package/static/chunk-PCWDQPOM.js +0 -2
- package/static/chunk-PNR6M34W.js +0 -1
- package/static/chunk-Q5KM7LTX.js +0 -1
- package/static/chunk-QHC6ZPQ4.js +0 -1
- package/static/chunk-QMRBZHE4.js +0 -1
- package/static/chunk-QSJRY3TF.js +0 -1
- package/static/chunk-QUUIRSYT.js +0 -1
- package/static/chunk-RFH46UW3.js +0 -1
- package/static/chunk-RSXHRKM5.js +0 -1
- package/static/chunk-RV3VZJPZ.js +0 -1
- package/static/chunk-S7HNXVRB.js +0 -1
- package/static/chunk-SBZ572Q4.js +0 -2
- package/static/chunk-SJR5R3Y4.js +0 -1
- package/static/chunk-SLHTEGRU.js +0 -1
- package/static/chunk-SSFF27P2.js +0 -24
- package/static/chunk-V3LHHZYN.js +0 -1
- package/static/chunk-VQQKMY2C.js +0 -1
- package/static/chunk-WSSU2HXE.js +0 -1
- package/static/chunk-XDZGW64M.js +0 -3
- package/static/chunk-XTRDKGKG.js +0 -1
- package/static/chunk-YLWTEC3X.js +0 -1
- package/static/chunk-Z5J5F5SX.js +0 -1
- package/static/main-4H5BJY3J.js +0 -9
- package/static/scripts-WRDOQIU5.js +0 -24
- package/static/styles-2C2UNCNB.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/files/services/files-only-office-manager.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpService } from '@nestjs/axios'\nimport { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'\nimport { JwtService } from '@nestjs/jwt'\nimport { AxiosResponse } from 'axios'\nimport https from 'https'\nimport crypto from 'node:crypto'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { JwtIdentityPayload } from '../../../authentication/interfaces/jwt-payload.interface'\nimport { convertHumanTimeToSeconds, generateShortUUID } from '../../../common/functions'\nimport { SERVER_NAME } from '../../../common/shared'\nimport { configuration } from '../../../configuration/config.environment'\nimport { Cache } from '../../../infrastructure/cache/services/cache.service'\nimport { ContextManager } from '../../../infrastructure/context/services/context-manager.service'\nimport { HTTP_METHOD } from '../../applications.constants'\nimport { SPACE_OPERATION } from '../../spaces/constants/spaces'\nimport { FastifySpaceRequest } from '../../spaces/interfaces/space-request.interface'\nimport type { SpaceEnv } from '../../spaces/models/space-env.model'\nimport { haveSpaceEnvPermissions } from '../../spaces/utils/permissions'\nimport type { UserModel } from '../../users/models/user.model'\nimport { getAvatarBase64 } from '../../users/utils/avatar'\nimport { DEPTH, LOCK_SCOPE } from '../../webdav/constants/webdav'\nimport { CACHE_ONLY_OFFICE } from '../constants/cache'\nimport {\n ONLY_OFFICE_CONVERT_ERROR,\n ONLY_OFFICE_CONVERT_EXTENSIONS,\n ONLY_OFFICE_EXTENSIONS,\n ONLY_OFFICE_INTERNAL_URI,\n ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME\n} from '../constants/only-office'\nimport { API_FILES_ONLY_OFFICE_CALLBACK, API_FILES_ONLY_OFFICE_DOCUMENT } from '../constants/routes'\nimport type { FileProps } from '../interfaces/file-props.interface'\nimport { OnlyOfficeCallBack, OnlyOfficeConfig, OnlyOfficeConvertForm, OnlyOfficeReqConfig } from '../interfaces/only-office-config.interface'\nimport { copyFileContent, fileSize, getProps, isPathExists, isPathIsDir, removeFiles, uniqueFilePathFromDir, writeFromStream } from '../utils/files'\nimport { FilesLockManager } from './files-lock-manager.service'\nimport { FilesQueries } from './files-queries.service'\n\n@Injectable()\nexport class FilesOnlyOfficeManager {\n private logger = new Logger(FilesOnlyOfficeManager.name)\n private readonly externalOnlyOfficeServer = configuration.applications.files.onlyoffice.externalServer || null\n private readonly rejectUnauthorized: boolean = !configuration.applications.files.onlyoffice?.verifySSL\n private readonly convertUrl = this.externalOnlyOfficeServer ? `${this.externalOnlyOfficeServer}/ConvertService.ashx` : null\n private readonly expiration = convertHumanTimeToSeconds(configuration.auth.token.refresh.expiration)\n private readonly mobileRegex: RegExp = /android|webos|iphone|ipad|ipod|blackberry|windows phone|opera mini|iemobile|mobile/i\n\n constructor(\n private readonly http: HttpService,\n private readonly contextManager: ContextManager,\n private readonly cache: Cache,\n private readonly jwt: JwtService,\n private readonly filesLockManager: FilesLockManager,\n private readonly filesQueries: FilesQueries\n ) {}\n\n getStatus(): { enabled: boolean } {\n return { enabled: configuration.applications.files.onlyoffice.enabled }\n }\n\n async getSettings(user: UserModel, space: SpaceEnv, mode: 'edit' | 'view', req: FastifySpaceRequest): Promise<OnlyOfficeReqConfig> {\n if (!(await isPathExists(space.realPath))) {\n throw new HttpException('Document not found', HttpStatus.NOT_FOUND)\n }\n if (await isPathIsDir(space.realPath)) {\n throw new HttpException('Document must be a file', HttpStatus.BAD_REQUEST)\n }\n const fileExtension = path.extname(space.realPath).slice(1)\n if (!ONLY_OFFICE_EXTENSIONS.VIEWABLE.has(fileExtension) && !ONLY_OFFICE_EXTENSIONS.EDITABLE.has(fileExtension)) {\n throw new HttpException('Document not supported', HttpStatus.BAD_REQUEST)\n }\n if (mode === 'edit' && (!ONLY_OFFICE_EXTENSIONS.EDITABLE.has(fileExtension) || !haveSpaceEnvPermissions(space, SPACE_OPERATION.MODIFY))) {\n mode = 'view'\n }\n if (mode === 'edit') {\n // check lock conflicts\n try {\n await this.filesLockManager.checkConflicts(space.dbFile, DEPTH.RESOURCE, { userId: user.id, lockScope: LOCK_SCOPE.SHARED })\n } catch {\n throw new HttpException('The file is locked', HttpStatus.LOCKED)\n }\n }\n const isMobile: boolean = this.mobileRegex.test(req.headers['user-agent'])\n const fileProps: FileProps = await getProps(space.realPath, space.dbFile.path)\n const fileId: string = ((await this.filesQueries.getSpaceFileId(fileProps, space.dbFile)) || fileProps.id).toString()\n const userToken: string = await this.genUserToken(user)\n const fileUrl = this.getDocumentUrl(space, userToken)\n const callBackUrl = this.getCallBackUrl(space, userToken, fileId)\n const config: OnlyOfficeReqConfig = await this.genConfiguration(user, space, mode, fileId, fileUrl, fileExtension, callBackUrl, isMobile)\n config.config.token = await this.genPayloadToken(config.config)\n return config\n }\n\n async callBack(user: UserModel, space: SpaceEnv, token: string, fileId: string) {\n const callBackData: OnlyOfficeCallBack = await this.jwt.verifyAsync(token, { secret: configuration.applications.files.onlyoffice.secret })\n try {\n switch (callBackData.status) {\n case 1:\n await this.checkFileLock(user, space, callBackData)\n this.logger.debug(`document is being edited : ${space.url}`)\n break\n case 2:\n await this.checkFileLock(user, space, callBackData)\n if (callBackData.notmodified) {\n this.logger.debug(`document was edited but closed with no changes : ${space.url}`)\n } else {\n this.logger.debug(`document was edited but not saved (let's do it) : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n }\n await this.removeDocumentKey(fileId, space)\n break\n case 3:\n this.logger.error(`document cannot be saved, an error has occurred (try to save it) : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n break\n case 4:\n await this.removeFileLock(user.id, space)\n await this.removeDocumentKey(fileId, space)\n this.logger.debug(`document was closed with no changes : ${space.url}`)\n break\n case 6:\n this.logger.debug(`document is edited but save was requested : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n break\n case 7:\n this.logger.error(`document cannot be force saved, an error has occurred (try to save it) : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n break\n default:\n this.logger.error('unhandled case')\n }\n } catch (e) {\n this.logger.error(`${this.callBack.name} - ${e.message} : ${space.url}`)\n return { error: e.message }\n }\n return { error: 0 }\n }\n\n private async genConfiguration(\n user: UserModel,\n space: SpaceEnv,\n mode: 'edit' | 'view',\n fileId: string,\n fileUrl: string,\n fileExtension: string,\n callBackUrl: string,\n isMobile: boolean\n ): Promise<OnlyOfficeReqConfig> {\n const documentType = ONLY_OFFICE_EXTENSIONS.EDITABLE.get(fileExtension) || ONLY_OFFICE_EXTENSIONS.VIEWABLE.get(fileExtension)\n return {\n documentServerUrl: this.externalOnlyOfficeServer || `${this.contextManager.get('headerOriginUrl')}${ONLY_OFFICE_INTERNAL_URI}`,\n config: {\n type: isMobile ? 'mobile' : 'desktop',\n height: '100%',\n width: '100%',\n documentType: documentType,\n document: {\n title: path.basename(space.relativeUrl),\n fileType: fileExtension,\n key: await this.getDocumentKey(fileId),\n permissions: {\n download: true,\n edit: mode === 'edit',\n changeHistory: false,\n comment: true,\n fillForms: true,\n print: true,\n review: mode === 'edit'\n },\n url: fileUrl\n },\n editorConfig: {\n mode: mode,\n lang: 'en',\n region: 'en',\n callbackUrl: callBackUrl,\n user: { id: user.id.toString(), name: `${user.fullName} (${user.email})`, image: await getAvatarBase64(user.login) },\n coEditing: {\n mode: 'fast',\n change: true\n },\n embedded: {\n embedUrl: fileUrl,\n saveUrl: fileUrl,\n shareUrl: fileUrl,\n toolbarDocked: 'top'\n },\n customization: {\n about: false,\n autosave: false,\n forcesave: true,\n zoom: documentType === 'slide' ? 60 : 90,\n help: false,\n features: { featuresTips: false },\n plugins: false\n }\n }\n }\n }\n }\n\n private getDocumentUrl(space: SpaceEnv, token: string): string {\n // user refresh token is used here for long session\n return `${this.contextManager.get('headerOriginUrl')}${API_FILES_ONLY_OFFICE_DOCUMENT}/${space.url}?${ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME}=${token}`\n }\n\n private getCallBackUrl(space: SpaceEnv, token: string, fileId: string): string {\n // user refresh token is used here for long session\n return `${this.contextManager.get('headerOriginUrl')}${API_FILES_ONLY_OFFICE_CALLBACK}/${space.url}?fid=${fileId}&${ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME}=${token}`\n }\n\n private genPayloadToken(payload: OnlyOfficeConfig | OnlyOfficeConvertForm): Promise<string> {\n return this.jwt.signAsync(payload, { secret: configuration.applications.files.onlyoffice.secret, expiresIn: 60 })\n }\n\n private genUserToken(user: UserModel): Promise<string> {\n // use refresh expiration to allow long session\n return this.jwt.signAsync(\n {\n identity: {\n id: user.id,\n login: user.login,\n email: user.email,\n fullName: user.fullName,\n language: user.language,\n role: user.role,\n applications: user.applications\n } satisfies JwtIdentityPayload\n },\n {\n secret: configuration.auth.token.access.secret,\n expiresIn: this.expiration\n }\n )\n }\n\n private async checkFileLock(user: UserModel, space: SpaceEnv, callBackData: OnlyOfficeCallBack) {\n for (const action of callBackData.actions) {\n if (action.type === 0) {\n // disconnect\n await this.removeFileLock(parseInt(action.userid), space)\n } else if (action.type === 1) {\n // connect\n await this.genFileLock(user, space)\n }\n }\n }\n\n private async genFileLock(user: UserModel, space: SpaceEnv): Promise<void> {\n const [ok, _fileLock] = await this.filesLockManager.create(user, space.dbFile, DEPTH.RESOURCE, this.expiration, {\n lockroot: null,\n locktoken: null,\n lockscope: LOCK_SCOPE.SHARED,\n owner: `${SERVER_NAME} - ${user.fullName} (${user.email})`\n })\n if (!ok) {\n throw new Error('document is locked')\n }\n }\n\n private async removeFileLock(userId: number, space: SpaceEnv): Promise<void> {\n for (const lock of await this.filesLockManager.getLocksByPath(space.dbFile)) {\n if (lock.owner.id === userId) {\n await this.filesLockManager.removeLock(lock.key)\n }\n }\n }\n\n private async removeDocumentKey(fileId: string, space: SpaceEnv): Promise<void> {\n if (!(await this.filesLockManager.isPathLocked(space.dbFile))) {\n const cacheKey = this.getCacheKey(fileId)\n const r = await this.cache.del(cacheKey)\n this.logger.debug(`${this.removeDocumentKey.name} - ${cacheKey} ${r ? '' : 'not'} removed`)\n }\n }\n\n private async getDocumentKey(fileId: string): Promise<string> {\n const cacheKey = this.getCacheKey(fileId)\n const existingDocKey: string = await this.cache.get(cacheKey)\n if (existingDocKey) {\n return existingDocKey\n }\n const docKey = generateShortUUID(64)\n await this.cache.set(cacheKey, docKey, this.expiration)\n this.logger.debug(`${this.getDocumentKey.name} - ${cacheKey} (${docKey}) created`)\n return docKey\n }\n\n private async saveDocument(space: SpaceEnv, url: string): Promise<void> {\n /* url format:\n https://onlyoffice-server.com/cache/files/data/-33120641_7158/output.pptx/output.pptx\n ?md5=duFHKC-5d47s-RRcYn3hAw&expires=1739400549&shardkey=-33120641&filename=output.pptx\n */\n const urlParams = new URLSearchParams(url.split('?').at(-1))\n // it is not the md5 of the file but a md5 generated by the combination of the elements of the url\n const md5: string = urlParams.get('md5')\n const tmpFilePath = await uniqueFilePathFromDir(path.join(os.tmpdir(), `${md5}-${urlParams.get('filename')}`))\n\n // convert remote file to the local file with the current extension if these extensions aren't equal\n const localExtension = path.extname(space.realPath).slice(1)\n const remoteExtension = path.extname(urlParams.get('filename')).slice(1)\n\n let downloadUrl: string\n if (localExtension !== remoteExtension && !ONLY_OFFICE_CONVERT_EXTENSIONS.ALLOW_AUTO.has(localExtension)) {\n if (ONLY_OFFICE_CONVERT_EXTENSIONS.FROM.has(remoteExtension) && ONLY_OFFICE_CONVERT_EXTENSIONS.TO.has(localExtension)) {\n downloadUrl = await this.convertDocument(urlParams.get('shardkey'), url, remoteExtension, localExtension, space.url)\n } else {\n throw new Error(`document cannot be converted from ${remoteExtension} -> ${localExtension} : ${space.url}`)\n }\n } else {\n downloadUrl = url\n }\n\n // download file\n let res: AxiosResponse\n try {\n res = await this.http.axiosRef({\n method: HTTP_METHOD.GET,\n url: downloadUrl,\n responseType: 'stream',\n httpsAgent: new https.Agent({ rejectUnauthorized: this.rejectUnauthorized })\n })\n await writeFromStream(tmpFilePath, res.data)\n } catch (e) {\n throw new Error(`unable to get document : ${e.message}`)\n }\n\n // try to verify the downloaded size\n const contentLength = parseInt(res.headers['content-length'], 10)\n if (!isNaN(contentLength)) {\n if (contentLength === 0) {\n this.logger.debug(`${this.saveDocument.name} - content length is 0 : ${space.url}`)\n return\n }\n const tmpFileSize = await fileSize(tmpFilePath)\n if (tmpFileSize !== contentLength) {\n throw new Error(`document size differs (${tmpFileSize} != ${contentLength})`)\n }\n }\n // copy contents to avoid inode changes (fileId in some cases)\n try {\n await copyFileContent(tmpFilePath, space.realPath)\n await removeFiles(tmpFilePath)\n } catch (e) {\n throw new Error(`unable to save document : ${e.message}`)\n }\n }\n\n private async convertDocument(id: string, url: string, fileType: string, outputType: string, spaceUrl: string): Promise<string> {\n const key: string = `${id}-${crypto.randomBytes(20).toString('hex')}`.slice(0, 20).replace('-', '_')\n const payload: OnlyOfficeConvertForm = {\n key: key,\n url: url,\n filetype: fileType,\n outputtype: outputType,\n async: false\n }\n payload.token = await this.genPayloadToken(payload)\n let result: { fileUrl?: string; fileType?: string; endConvert?: boolean; error?: number }\n try {\n const res: AxiosResponse = await this.http.axiosRef({\n method: HTTP_METHOD.POST,\n url: this.convertUrl,\n data: payload,\n httpsAgent: new https.Agent({ rejectUnauthorized: this.rejectUnauthorized })\n })\n result = res.data\n } catch (e) {\n throw new Error(`convert failed with status : ${e.response.status}`)\n }\n if (result.error) {\n throw new Error(`convert failed with reason : ${ONLY_OFFICE_CONVERT_ERROR.get(result.error)}`)\n }\n if (result.endConvert) {\n this.logger.log(`${this.convertDocument.name} - ${fileType} -> ${outputType} : ${spaceUrl}`)\n return result.fileUrl\n }\n }\n\n private getCacheKey(fileId: string): string {\n return `${CACHE_ONLY_OFFICE}|${fileId}`\n }\n}\n"],"names":["FilesOnlyOfficeManager","getStatus","enabled","configuration","applications","files","onlyoffice","getSettings","user","space","mode","req","isPathExists","realPath","HttpException","HttpStatus","NOT_FOUND","isPathIsDir","BAD_REQUEST","fileExtension","path","extname","slice","ONLY_OFFICE_EXTENSIONS","VIEWABLE","has","EDITABLE","haveSpaceEnvPermissions","SPACE_OPERATION","MODIFY","filesLockManager","checkConflicts","dbFile","DEPTH","RESOURCE","userId","id","lockScope","LOCK_SCOPE","SHARED","LOCKED","isMobile","mobileRegex","test","headers","fileProps","getProps","fileId","filesQueries","getSpaceFileId","toString","userToken","genUserToken","fileUrl","getDocumentUrl","callBackUrl","getCallBackUrl","config","genConfiguration","token","genPayloadToken","callBack","callBackData","jwt","verifyAsync","secret","status","checkFileLock","logger","debug","url","notmodified","saveDocument","removeDocumentKey","error","removeFileLock","e","name","message","documentType","get","documentServerUrl","externalOnlyOfficeServer","contextManager","ONLY_OFFICE_INTERNAL_URI","type","height","width","document","title","basename","relativeUrl","fileType","key","getDocumentKey","permissions","download","edit","changeHistory","comment","fillForms","print","review","editorConfig","lang","region","callbackUrl","fullName","email","image","getAvatarBase64","login","coEditing","change","embedded","embedUrl","saveUrl","shareUrl","toolbarDocked","customization","about","autosave","forcesave","zoom","help","features","featuresTips","plugins","API_FILES_ONLY_OFFICE_DOCUMENT","ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME","API_FILES_ONLY_OFFICE_CALLBACK","payload","signAsync","expiresIn","identity","language","role","auth","access","expiration","action","actions","parseInt","userid","genFileLock","ok","_fileLock","create","lockroot","locktoken","lockscope","owner","SERVER_NAME","Error","lock","getLocksByPath","removeLock","isPathLocked","cacheKey","getCacheKey","r","cache","del","existingDocKey","docKey","generateShortUUID","set","urlParams","URLSearchParams","split","at","md5","tmpFilePath","uniqueFilePathFromDir","join","os","tmpdir","localExtension","remoteExtension","downloadUrl","ONLY_OFFICE_CONVERT_EXTENSIONS","ALLOW_AUTO","FROM","TO","convertDocument","res","http","axiosRef","method","HTTP_METHOD","GET","responseType","httpsAgent","https","Agent","rejectUnauthorized","writeFromStream","data","contentLength","isNaN","tmpFileSize","fileSize","copyFileContent","removeFiles","outputType","spaceUrl","crypto","randomBytes","replace","filetype","outputtype","async","result","POST","convertUrl","response","ONLY_OFFICE_CONVERT_ERROR","endConvert","log","CACHE_ONLY_OFFICE","Logger","externalServer","verifySSL","convertHumanTimeToSeconds","refresh"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/files/services/files-only-office-manager.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpService } from '@nestjs/axios'\nimport { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'\nimport { JwtService } from '@nestjs/jwt'\nimport { AxiosResponse } from 'axios'\nimport https from 'https'\nimport crypto from 'node:crypto'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { JwtIdentityPayload } from '../../../authentication/interfaces/jwt-payload.interface'\nimport { convertHumanTimeToSeconds, generateShortUUID } from '../../../common/functions'\nimport { configuration } from '../../../configuration/config.environment'\nimport { Cache } from '../../../infrastructure/cache/services/cache.service'\nimport { ContextManager } from '../../../infrastructure/context/services/context-manager.service'\nimport { HTTP_METHOD } from '../../applications.constants'\nimport { SPACE_OPERATION } from '../../spaces/constants/spaces'\nimport { FastifySpaceRequest } from '../../spaces/interfaces/space-request.interface'\nimport type { SpaceEnv } from '../../spaces/models/space-env.model'\nimport { haveSpaceEnvPermissions } from '../../spaces/utils/permissions'\nimport type { UserModel } from '../../users/models/user.model'\nimport { getAvatarBase64 } from '../../users/utils/avatar'\nimport { DEPTH, LOCK_SCOPE } from '../../webdav/constants/webdav'\nimport { WebDAVLock } from '../../webdav/interfaces/webdav.interface'\nimport { CACHE_ONLY_OFFICE } from '../constants/cache'\nimport {\n ONLY_OFFICE_CONVERT_ERROR,\n ONLY_OFFICE_CONVERT_EXTENSIONS,\n ONLY_OFFICE_EXTENSIONS,\n ONLY_OFFICE_INTERNAL_URI,\n ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME\n} from '../constants/only-office'\nimport { FILE_MODE } from '../constants/operations'\nimport { API_FILES_ONLY_OFFICE_CALLBACK, API_FILES_ONLY_OFFICE_DOCUMENT } from '../constants/routes'\nimport type { FileProps } from '../interfaces/file-props.interface'\nimport { OnlyOfficeCallBack, OnlyOfficeConfig, OnlyOfficeConvertForm, OnlyOfficeReqConfig } from '../interfaces/only-office-config.interface'\nimport { copyFileContent, fileSize, getProps, isPathExists, isPathIsDir, removeFiles, uniqueFilePathFromDir, writeFromStream } from '../utils/files'\nimport { FilesLockManager } from './files-lock-manager.service'\nimport { FilesQueries } from './files-queries.service'\n\n@Injectable()\nexport class FilesOnlyOfficeManager {\n private logger = new Logger(FilesOnlyOfficeManager.name)\n private readonly externalOnlyOfficeServer = configuration.applications.files.onlyoffice.externalServer || null\n private readonly rejectUnauthorized: boolean = !configuration.applications.files.onlyoffice?.verifySSL\n private readonly convertUrl = this.externalOnlyOfficeServer ? `${this.externalOnlyOfficeServer}/ConvertService.ashx` : null\n private readonly expiration = convertHumanTimeToSeconds(configuration.auth.token.refresh.expiration)\n private readonly mobileRegex: RegExp = /android|webos|iphone|ipad|ipod|blackberry|windows phone|opera mini|iemobile|mobile/i\n\n constructor(\n private readonly http: HttpService,\n private readonly contextManager: ContextManager,\n private readonly cache: Cache,\n private readonly jwt: JwtService,\n private readonly filesLockManager: FilesLockManager,\n private readonly filesQueries: FilesQueries\n ) {}\n\n getStatus(): { enabled: boolean } {\n return { enabled: configuration.applications.files.onlyoffice.enabled }\n }\n\n async getSettings(user: UserModel, space: SpaceEnv, mode: FILE_MODE, req: FastifySpaceRequest): Promise<OnlyOfficeReqConfig> {\n if (!(await isPathExists(space.realPath))) {\n throw new HttpException('Document not found', HttpStatus.NOT_FOUND)\n }\n if (await isPathIsDir(space.realPath)) {\n throw new HttpException('Document must be a file', HttpStatus.BAD_REQUEST)\n }\n const fileExtension = path.extname(space.realPath).slice(1)\n if (!ONLY_OFFICE_EXTENSIONS.VIEWABLE.has(fileExtension) && !ONLY_OFFICE_EXTENSIONS.EDITABLE.has(fileExtension)) {\n throw new HttpException('Document not supported', HttpStatus.BAD_REQUEST)\n }\n if (mode === FILE_MODE.EDIT && (!ONLY_OFFICE_EXTENSIONS.EDITABLE.has(fileExtension) || !haveSpaceEnvPermissions(space, SPACE_OPERATION.MODIFY))) {\n mode = FILE_MODE.VIEW\n }\n if (mode === FILE_MODE.EDIT) {\n // check lock conflicts\n try {\n await this.filesLockManager.checkConflicts(space.dbFile, DEPTH.RESOURCE, { userId: user.id, lockScope: LOCK_SCOPE.SHARED })\n } catch {\n throw new HttpException('The file is locked', HttpStatus.LOCKED)\n }\n }\n const isMobile: boolean = this.mobileRegex.test(req.headers['user-agent'])\n const fileProps: FileProps = await getProps(space.realPath, space.dbFile.path)\n const fileId: string = ((await this.filesQueries.getSpaceFileId(fileProps, space.dbFile)) || fileProps.id).toString()\n const userToken: string = await this.genUserToken(user)\n const fileUrl = this.getDocumentUrl(space, userToken)\n const callBackUrl = this.getCallBackUrl(space, userToken, fileId)\n const config: OnlyOfficeReqConfig = await this.genConfiguration(user, space, mode, fileId, fileUrl, fileExtension, callBackUrl, isMobile)\n config.config.token = await this.genPayloadToken(config.config)\n return config\n }\n\n async callBack(user: UserModel, space: SpaceEnv, token: string, fileId: string) {\n const callBackData: OnlyOfficeCallBack = await this.jwt.verifyAsync(token, { secret: configuration.applications.files.onlyoffice.secret })\n try {\n switch (callBackData.status) {\n case 1:\n await this.checkFileLock(user, space, callBackData)\n this.logger.debug(`document is being edited : ${space.url}`)\n break\n case 2:\n await this.checkFileLock(user, space, callBackData)\n if (callBackData.notmodified) {\n this.logger.debug(`document was edited but closed with no changes : ${space.url}`)\n } else {\n this.logger.debug(`document was edited but not saved (let's do it) : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n }\n await this.removeDocumentKey(fileId, space)\n break\n case 3:\n this.logger.error(`document cannot be saved, an error has occurred (try to save it) : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n break\n case 4:\n await this.removeFileLock(user.id, space)\n await this.removeDocumentKey(fileId, space)\n this.logger.debug(`document was closed with no changes : ${space.url}`)\n break\n case 6:\n this.logger.debug(`document is edited but save was requested : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n break\n case 7:\n this.logger.error(`document cannot be force saved, an error has occurred (try to save it) : ${space.url}`)\n await this.saveDocument(space, callBackData.url)\n break\n default:\n this.logger.error('unhandled case')\n }\n } catch (e) {\n this.logger.error(`${this.callBack.name} - ${e.message} : ${space.url}`)\n return { error: e.message }\n }\n return { error: 0 }\n }\n\n private async genConfiguration(\n user: UserModel,\n space: SpaceEnv,\n mode: FILE_MODE,\n fileId: string,\n fileUrl: string,\n fileExtension: string,\n callBackUrl: string,\n isMobile: boolean\n ): Promise<OnlyOfficeReqConfig> {\n const documentType = ONLY_OFFICE_EXTENSIONS.EDITABLE.get(fileExtension) || ONLY_OFFICE_EXTENSIONS.VIEWABLE.get(fileExtension)\n return {\n documentServerUrl: this.externalOnlyOfficeServer || `${this.contextManager.headerOriginUrl()}${ONLY_OFFICE_INTERNAL_URI}`,\n config: {\n type: isMobile ? 'mobile' : 'desktop',\n height: '100%',\n width: '100%',\n documentType: documentType,\n document: {\n title: path.basename(space.relativeUrl),\n fileType: fileExtension,\n key: await this.getDocumentKey(fileId),\n permissions: {\n download: true,\n edit: mode === FILE_MODE.EDIT,\n changeHistory: false,\n comment: true,\n fillForms: true,\n print: true,\n review: mode === FILE_MODE.EDIT\n },\n url: fileUrl\n },\n editorConfig: {\n mode: mode,\n lang: 'en',\n region: 'en',\n callbackUrl: callBackUrl,\n user: { id: user.id.toString(), name: `${user.fullName} (${user.email})`, image: await getAvatarBase64(user.login) },\n coEditing: {\n mode: 'fast',\n change: true\n },\n embedded: {\n embedUrl: fileUrl,\n saveUrl: fileUrl,\n shareUrl: fileUrl,\n toolbarDocked: 'top'\n },\n customization: {\n about: false,\n autosave: false,\n forcesave: true,\n zoom: documentType === 'slide' ? 60 : 90,\n help: false,\n features: { featuresTips: false },\n plugins: false\n }\n }\n }\n }\n }\n\n private getDocumentUrl(space: SpaceEnv, token: string): string {\n // user refresh token is used here for long session\n return `${this.contextManager.headerOriginUrl()}${API_FILES_ONLY_OFFICE_DOCUMENT}/${space.url}?${ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME}=${token}`\n }\n\n private getCallBackUrl(space: SpaceEnv, token: string, fileId: string): string {\n // user refresh token is used here for long session\n return `${this.contextManager.headerOriginUrl()}${API_FILES_ONLY_OFFICE_CALLBACK}/${space.url}?fid=${fileId}&${ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME}=${token}`\n }\n\n private genPayloadToken(payload: OnlyOfficeConfig | OnlyOfficeConvertForm): Promise<string> {\n return this.jwt.signAsync(payload, { secret: configuration.applications.files.onlyoffice.secret, expiresIn: 60 })\n }\n\n private genUserToken(user: UserModel): Promise<string> {\n // use refresh expiration to allow long session\n return this.jwt.signAsync(\n {\n identity: {\n id: user.id,\n login: user.login,\n email: user.email,\n fullName: user.fullName,\n language: user.language,\n role: user.role,\n applications: user.applications\n } satisfies JwtIdentityPayload\n },\n {\n secret: configuration.auth.token.access.secret,\n expiresIn: this.expiration\n }\n )\n }\n\n private async checkFileLock(user: UserModel, space: SpaceEnv, callBackData: OnlyOfficeCallBack) {\n for (const action of callBackData.actions) {\n if (action.type === 0) {\n // disconnect\n await this.removeFileLock(parseInt(action.userid), space)\n } else if (action.type === 1) {\n // connect\n await this.genFileLock(user, space)\n }\n }\n }\n\n private async genFileLock(user: UserModel, space: SpaceEnv): Promise<void> {\n const [ok, _fileLock] = await this.filesLockManager.create(\n user,\n space.dbFile,\n DEPTH.RESOURCE,\n {\n lockroot: null,\n locktoken: null,\n lockscope: LOCK_SCOPE.SHARED,\n owner: `OnlyOffice - ${user.fullName} (${user.email})`\n } satisfies WebDAVLock,\n this.expiration\n )\n if (!ok) {\n throw new Error('document is locked')\n }\n }\n\n private async removeFileLock(userId: number, space: SpaceEnv): Promise<void> {\n for (const lock of await this.filesLockManager.getLocksByPath(space.dbFile)) {\n if (lock.owner.id === userId) {\n await this.filesLockManager.removeLock(lock.key)\n }\n }\n }\n\n private async removeDocumentKey(fileId: string, space: SpaceEnv): Promise<void> {\n if (!(await this.filesLockManager.isPathLocked(space.dbFile))) {\n const cacheKey = this.getCacheKey(fileId)\n const r = await this.cache.del(cacheKey)\n this.logger.debug(`${this.removeDocumentKey.name} - ${cacheKey} ${r ? '' : 'not'} removed`)\n }\n }\n\n private async getDocumentKey(fileId: string): Promise<string> {\n const cacheKey = this.getCacheKey(fileId)\n const existingDocKey: string = await this.cache.get(cacheKey)\n if (existingDocKey) {\n return existingDocKey\n }\n const docKey = generateShortUUID(64)\n await this.cache.set(cacheKey, docKey, this.expiration)\n this.logger.debug(`${this.getDocumentKey.name} - ${cacheKey} (${docKey}) created`)\n return docKey\n }\n\n private async saveDocument(space: SpaceEnv, url: string): Promise<void> {\n /* url format:\n https://onlyoffice-server.com/cache/files/data/-33120641_7158/output.pptx/output.pptx\n ?md5=duFHKC-5d47s-RRcYn3hAw&expires=1739400549&shardkey=-33120641&filename=output.pptx\n */\n const urlParams = new URLSearchParams(url.split('?').at(-1))\n // it is not the md5 of the file but a md5 generated by the combination of the elements of the url\n const md5: string = urlParams.get('md5')\n const tmpFilePath = await uniqueFilePathFromDir(path.join(os.tmpdir(), `${md5}-${urlParams.get('filename')}`))\n\n // convert remote file to the local file with the current extension if these extensions aren't equal\n const localExtension = path.extname(space.realPath).slice(1)\n const remoteExtension = path.extname(urlParams.get('filename')).slice(1)\n\n let downloadUrl: string\n if (localExtension !== remoteExtension && !ONLY_OFFICE_CONVERT_EXTENSIONS.ALLOW_AUTO.has(localExtension)) {\n if (ONLY_OFFICE_CONVERT_EXTENSIONS.FROM.has(remoteExtension) && ONLY_OFFICE_CONVERT_EXTENSIONS.TO.has(localExtension)) {\n downloadUrl = await this.convertDocument(urlParams.get('shardkey'), url, remoteExtension, localExtension, space.url)\n } else {\n throw new Error(`document cannot be converted from ${remoteExtension} -> ${localExtension} : ${space.url}`)\n }\n } else {\n downloadUrl = url\n }\n\n // download file\n let res: AxiosResponse\n try {\n res = await this.http.axiosRef({\n method: HTTP_METHOD.GET,\n url: downloadUrl,\n responseType: 'stream',\n httpsAgent: new https.Agent({ rejectUnauthorized: this.rejectUnauthorized })\n })\n await writeFromStream(tmpFilePath, res.data)\n } catch (e) {\n throw new Error(`unable to get document : ${e.message}`)\n }\n\n // try to verify the downloaded size\n const contentLength = parseInt(res.headers['content-length'], 10)\n if (!isNaN(contentLength)) {\n if (contentLength === 0) {\n this.logger.debug(`${this.saveDocument.name} - content length is 0 : ${space.url}`)\n return\n }\n const tmpFileSize = await fileSize(tmpFilePath)\n if (tmpFileSize !== contentLength) {\n throw new Error(`document size differs (${tmpFileSize} != ${contentLength})`)\n }\n }\n // copy contents to avoid inode changes (fileId in some cases)\n try {\n await copyFileContent(tmpFilePath, space.realPath)\n await removeFiles(tmpFilePath)\n } catch (e) {\n throw new Error(`unable to save document : ${e.message}`)\n }\n }\n\n private async convertDocument(id: string, url: string, fileType: string, outputType: string, spaceUrl: string): Promise<string> {\n const key: string = `${id}-${crypto.randomBytes(20).toString('hex')}`.slice(0, 20).replace('-', '_')\n const payload: OnlyOfficeConvertForm = {\n key: key,\n url: url,\n filetype: fileType,\n outputtype: outputType,\n async: false\n }\n payload.token = await this.genPayloadToken(payload)\n let result: { fileUrl?: string; fileType?: string; endConvert?: boolean; error?: number }\n try {\n const res: AxiosResponse = await this.http.axiosRef({\n method: HTTP_METHOD.POST,\n url: this.convertUrl,\n data: payload,\n httpsAgent: new https.Agent({ rejectUnauthorized: this.rejectUnauthorized })\n })\n result = res.data\n } catch (e) {\n throw new Error(`convert failed with status : ${e.response.status}`)\n }\n if (result.error) {\n throw new Error(`convert failed with reason : ${ONLY_OFFICE_CONVERT_ERROR.get(result.error)}`)\n }\n if (result.endConvert) {\n this.logger.log(`${this.convertDocument.name} - ${fileType} -> ${outputType} : ${spaceUrl}`)\n return result.fileUrl\n }\n }\n\n private getCacheKey(fileId: string): string {\n return `${CACHE_ONLY_OFFICE}|${fileId}`\n }\n}\n"],"names":["FilesOnlyOfficeManager","getStatus","enabled","configuration","applications","files","onlyoffice","getSettings","user","space","mode","req","isPathExists","realPath","HttpException","HttpStatus","NOT_FOUND","isPathIsDir","BAD_REQUEST","fileExtension","path","extname","slice","ONLY_OFFICE_EXTENSIONS","VIEWABLE","has","EDITABLE","FILE_MODE","EDIT","haveSpaceEnvPermissions","SPACE_OPERATION","MODIFY","VIEW","filesLockManager","checkConflicts","dbFile","DEPTH","RESOURCE","userId","id","lockScope","LOCK_SCOPE","SHARED","LOCKED","isMobile","mobileRegex","test","headers","fileProps","getProps","fileId","filesQueries","getSpaceFileId","toString","userToken","genUserToken","fileUrl","getDocumentUrl","callBackUrl","getCallBackUrl","config","genConfiguration","token","genPayloadToken","callBack","callBackData","jwt","verifyAsync","secret","status","checkFileLock","logger","debug","url","notmodified","saveDocument","removeDocumentKey","error","removeFileLock","e","name","message","documentType","get","documentServerUrl","externalOnlyOfficeServer","contextManager","headerOriginUrl","ONLY_OFFICE_INTERNAL_URI","type","height","width","document","title","basename","relativeUrl","fileType","key","getDocumentKey","permissions","download","edit","changeHistory","comment","fillForms","print","review","editorConfig","lang","region","callbackUrl","fullName","email","image","getAvatarBase64","login","coEditing","change","embedded","embedUrl","saveUrl","shareUrl","toolbarDocked","customization","about","autosave","forcesave","zoom","help","features","featuresTips","plugins","API_FILES_ONLY_OFFICE_DOCUMENT","ONLY_OFFICE_TOKEN_QUERY_PARAM_NAME","API_FILES_ONLY_OFFICE_CALLBACK","payload","signAsync","expiresIn","identity","language","role","auth","access","expiration","action","actions","parseInt","userid","genFileLock","ok","_fileLock","create","lockroot","locktoken","lockscope","owner","Error","lock","getLocksByPath","removeLock","isPathLocked","cacheKey","getCacheKey","r","cache","del","existingDocKey","docKey","generateShortUUID","set","urlParams","URLSearchParams","split","at","md5","tmpFilePath","uniqueFilePathFromDir","join","os","tmpdir","localExtension","remoteExtension","downloadUrl","ONLY_OFFICE_CONVERT_EXTENSIONS","ALLOW_AUTO","FROM","TO","convertDocument","res","http","axiosRef","method","HTTP_METHOD","GET","responseType","httpsAgent","https","Agent","rejectUnauthorized","writeFromStream","data","contentLength","isNaN","tmpFileSize","fileSize","copyFileContent","removeFiles","outputType","spaceUrl","crypto","randomBytes","replace","filetype","outputtype","async","result","POST","convertUrl","response","ONLY_OFFICE_CONVERT_ERROR","endConvert","log","CACHE_ONLY_OFFICE","Logger","externalServer","verifySSL","convertHumanTimeToSeconds","refresh"],"mappings":"AAAA;;;;CAIC;;;;+BAyCYA;;;eAAAA;;;uBAvCe;wBACkC;qBACnC;8DAET;mEACC;+DACJ;iEACE;2BAE4C;mCAC/B;8BACR;uCACS;uCACH;wBACI;6BAGQ;wBAER;wBACE;uBAEA;4BAO3B;4BACmB;wBACqD;uBAGqD;yCACnG;qCACJ;;;;;;;;;;;;;;;AAGtB,IAAA,AAAMA,yBAAN,MAAMA;IAiBXC,YAAkC;QAChC,OAAO;YAAEC,SAASC,gCAAa,CAACC,YAAY,CAACC,KAAK,CAACC,UAAU,CAACJ,OAAO;QAAC;IACxE;IAEA,MAAMK,YAAYC,IAAe,EAAEC,KAAe,EAAEC,IAAe,EAAEC,GAAwB,EAAgC;QAC3H,IAAI,CAAE,MAAMC,IAAAA,mBAAY,EAACH,MAAMI,QAAQ,GAAI;YACzC,MAAM,IAAIC,qBAAa,CAAC,sBAAsBC,kBAAU,CAACC,SAAS;QACpE;QACA,IAAI,MAAMC,IAAAA,kBAAW,EAACR,MAAMI,QAAQ,GAAG;YACrC,MAAM,IAAIC,qBAAa,CAAC,2BAA2BC,kBAAU,CAACG,WAAW;QAC3E;QACA,MAAMC,gBAAgBC,iBAAI,CAACC,OAAO,CAACZ,MAAMI,QAAQ,EAAES,KAAK,CAAC;QACzD,IAAI,CAACC,kCAAsB,CAACC,QAAQ,CAACC,GAAG,CAACN,kBAAkB,CAACI,kCAAsB,CAACG,QAAQ,CAACD,GAAG,CAACN,gBAAgB;YAC9G,MAAM,IAAIL,qBAAa,CAAC,0BAA0BC,kBAAU,CAACG,WAAW;QAC1E;QACA,IAAIR,SAASiB,qBAAS,CAACC,IAAI,IAAK,CAAA,CAACL,kCAAsB,CAACG,QAAQ,CAACD,GAAG,CAACN,kBAAkB,CAACU,IAAAA,oCAAuB,EAACpB,OAAOqB,uBAAe,CAACC,MAAM,CAAA,GAAI;YAC/IrB,OAAOiB,qBAAS,CAACK,IAAI;QACvB;QACA,IAAItB,SAASiB,qBAAS,CAACC,IAAI,EAAE;YAC3B,uBAAuB;YACvB,IAAI;gBACF,MAAM,IAAI,CAACK,gBAAgB,CAACC,cAAc,CAACzB,MAAM0B,MAAM,EAAEC,aAAK,CAACC,QAAQ,EAAE;oBAAEC,QAAQ9B,KAAK+B,EAAE;oBAAEC,WAAWC,kBAAU,CAACC,MAAM;gBAAC;YAC3H,EAAE,OAAM;gBACN,MAAM,IAAI5B,qBAAa,CAAC,sBAAsBC,kBAAU,CAAC4B,MAAM;YACjE;QACF;QACA,MAAMC,WAAoB,IAAI,CAACC,WAAW,CAACC,IAAI,CAACnC,IAAIoC,OAAO,CAAC,aAAa;QACzE,MAAMC,YAAuB,MAAMC,IAAAA,eAAQ,EAACxC,MAAMI,QAAQ,EAAEJ,MAAM0B,MAAM,CAACf,IAAI;QAC7E,MAAM8B,SAAiB,AAAC,CAAA,AAAC,MAAM,IAAI,CAACC,YAAY,CAACC,cAAc,CAACJ,WAAWvC,MAAM0B,MAAM,KAAMa,UAAUT,EAAE,AAAD,EAAGc,QAAQ;QACnH,MAAMC,YAAoB,MAAM,IAAI,CAACC,YAAY,CAAC/C;QAClD,MAAMgD,UAAU,IAAI,CAACC,cAAc,CAAChD,OAAO6C;QAC3C,MAAMI,cAAc,IAAI,CAACC,cAAc,CAAClD,OAAO6C,WAAWJ;QAC1D,MAAMU,SAA8B,MAAM,IAAI,CAACC,gBAAgB,CAACrD,MAAMC,OAAOC,MAAMwC,QAAQM,SAASrC,eAAeuC,aAAad;QAChIgB,OAAOA,MAAM,CAACE,KAAK,GAAG,MAAM,IAAI,CAACC,eAAe,CAACH,OAAOA,MAAM;QAC9D,OAAOA;IACT;IAEA,MAAMI,SAASxD,IAAe,EAAEC,KAAe,EAAEqD,KAAa,EAAEZ,MAAc,EAAE;QAC9E,MAAMe,eAAmC,MAAM,IAAI,CAACC,GAAG,CAACC,WAAW,CAACL,OAAO;YAAEM,QAAQjE,gCAAa,CAACC,YAAY,CAACC,KAAK,CAACC,UAAU,CAAC8D,MAAM;QAAC;QACxI,IAAI;YACF,OAAQH,aAAaI,MAAM;gBACzB,KAAK;oBACH,MAAM,IAAI,CAACC,aAAa,CAAC9D,MAAMC,OAAOwD;oBACtC,IAAI,CAACM,MAAM,CAACC,KAAK,CAAC,CAAC,2BAA2B,EAAE/D,MAAMgE,GAAG,EAAE;oBAC3D;gBACF,KAAK;oBACH,MAAM,IAAI,CAACH,aAAa,CAAC9D,MAAMC,OAAOwD;oBACtC,IAAIA,aAAaS,WAAW,EAAE;wBAC5B,IAAI,CAACH,MAAM,CAACC,KAAK,CAAC,CAAC,iDAAiD,EAAE/D,MAAMgE,GAAG,EAAE;oBACnF,OAAO;wBACL,IAAI,CAACF,MAAM,CAACC,KAAK,CAAC,CAAC,kDAAkD,EAAE/D,MAAMgE,GAAG,EAAE;wBAClF,MAAM,IAAI,CAACE,YAAY,CAAClE,OAAOwD,aAAaQ,GAAG;oBACjD;oBACA,MAAM,IAAI,CAACG,iBAAiB,CAAC1B,QAAQzC;oBACrC;gBACF,KAAK;oBACH,IAAI,CAAC8D,MAAM,CAACM,KAAK,CAAC,CAAC,mEAAmE,EAAEpE,MAAMgE,GAAG,EAAE;oBACnG,MAAM,IAAI,CAACE,YAAY,CAAClE,OAAOwD,aAAaQ,GAAG;oBAC/C;gBACF,KAAK;oBACH,MAAM,IAAI,CAACK,cAAc,CAACtE,KAAK+B,EAAE,EAAE9B;oBACnC,MAAM,IAAI,CAACmE,iBAAiB,CAAC1B,QAAQzC;oBACrC,IAAI,CAAC8D,MAAM,CAACC,KAAK,CAAC,CAAC,sCAAsC,EAAE/D,MAAMgE,GAAG,EAAE;oBACtE;gBACF,KAAK;oBACH,IAAI,CAACF,MAAM,CAACC,KAAK,CAAC,CAAC,4CAA4C,EAAE/D,MAAMgE,GAAG,EAAE;oBAC5E,MAAM,IAAI,CAACE,YAAY,CAAClE,OAAOwD,aAAaQ,GAAG;oBAC/C;gBACF,KAAK;oBACH,IAAI,CAACF,MAAM,CAACM,KAAK,CAAC,CAAC,yEAAyE,EAAEpE,MAAMgE,GAAG,EAAE;oBACzG,MAAM,IAAI,CAACE,YAAY,CAAClE,OAAOwD,aAAaQ,GAAG;oBAC/C;gBACF;oBACE,IAAI,CAACF,MAAM,CAACM,KAAK,CAAC;YACtB;QACF,EAAE,OAAOE,GAAG;YACV,IAAI,CAACR,MAAM,CAACM,KAAK,CAAC,GAAG,IAAI,CAACb,QAAQ,CAACgB,IAAI,CAAC,GAAG,EAAED,EAAEE,OAAO,CAAC,GAAG,EAAExE,MAAMgE,GAAG,EAAE;YACvE,OAAO;gBAAEI,OAAOE,EAAEE,OAAO;YAAC;QAC5B;QACA,OAAO;YAAEJ,OAAO;QAAE;IACpB;IAEA,MAAchB,iBACZrD,IAAe,EACfC,KAAe,EACfC,IAAe,EACfwC,MAAc,EACdM,OAAe,EACfrC,aAAqB,EACrBuC,WAAmB,EACnBd,QAAiB,EACa;QAC9B,MAAMsC,eAAe3D,kCAAsB,CAACG,QAAQ,CAACyD,GAAG,CAAChE,kBAAkBI,kCAAsB,CAACC,QAAQ,CAAC2D,GAAG,CAAChE;QAC/G,OAAO;YACLiE,mBAAmB,IAAI,CAACC,wBAAwB,IAAI,GAAG,IAAI,CAACC,cAAc,CAACC,eAAe,KAAKC,oCAAwB,EAAE;YACzH5B,QAAQ;gBACN6B,MAAM7C,WAAW,WAAW;gBAC5B8C,QAAQ;gBACRC,OAAO;gBACPT,cAAcA;gBACdU,UAAU;oBACRC,OAAOzE,iBAAI,CAAC0E,QAAQ,CAACrF,MAAMsF,WAAW;oBACtCC,UAAU7E;oBACV8E,KAAK,MAAM,IAAI,CAACC,cAAc,CAAChD;oBAC/BiD,aAAa;wBACXC,UAAU;wBACVC,MAAM3F,SAASiB,qBAAS,CAACC,IAAI;wBAC7B0E,eAAe;wBACfC,SAAS;wBACTC,WAAW;wBACXC,OAAO;wBACPC,QAAQhG,SAASiB,qBAAS,CAACC,IAAI;oBACjC;oBACA6C,KAAKjB;gBACP;gBACAmD,cAAc;oBACZjG,MAAMA;oBACNkG,MAAM;oBACNC,QAAQ;oBACRC,aAAapD;oBACblD,MAAM;wBAAE+B,IAAI/B,KAAK+B,EAAE,CAACc,QAAQ;wBAAI2B,MAAM,GAAGxE,KAAKuG,QAAQ,CAAC,EAAE,EAAEvG,KAAKwG,KAAK,CAAC,CAAC,CAAC;wBAAEC,OAAO,MAAMC,IAAAA,uBAAe,EAAC1G,KAAK2G,KAAK;oBAAE;oBACnHC,WAAW;wBACT1G,MAAM;wBACN2G,QAAQ;oBACV;oBACAC,UAAU;wBACRC,UAAU/D;wBACVgE,SAAShE;wBACTiE,UAAUjE;wBACVkE,eAAe;oBACjB;oBACAC,eAAe;wBACbC,OAAO;wBACPC,UAAU;wBACVC,WAAW;wBACXC,MAAM7C,iBAAiB,UAAU,KAAK;wBACtC8C,MAAM;wBACNC,UAAU;4BAAEC,cAAc;wBAAM;wBAChCC,SAAS;oBACX;gBACF;YACF;QACF;IACF;IAEQ1E,eAAehD,KAAe,EAAEqD,KAAa,EAAU;QAC7D,mDAAmD;QACnD,OAAO,GAAG,IAAI,CAACwB,cAAc,CAACC,eAAe,KAAK6C,sCAA8B,CAAC,CAAC,EAAE3H,MAAMgE,GAAG,CAAC,CAAC,EAAE4D,8CAAkC,CAAC,CAAC,EAAEvE,OAAO;IAChJ;IAEQH,eAAelD,KAAe,EAAEqD,KAAa,EAAEZ,MAAc,EAAU;QAC7E,mDAAmD;QACnD,OAAO,GAAG,IAAI,CAACoC,cAAc,CAACC,eAAe,KAAK+C,sCAA8B,CAAC,CAAC,EAAE7H,MAAMgE,GAAG,CAAC,KAAK,EAAEvB,OAAO,CAAC,EAAEmF,8CAAkC,CAAC,CAAC,EAAEvE,OAAO;IAC9J;IAEQC,gBAAgBwE,OAAiD,EAAmB;QAC1F,OAAO,IAAI,CAACrE,GAAG,CAACsE,SAAS,CAACD,SAAS;YAAEnE,QAAQjE,gCAAa,CAACC,YAAY,CAACC,KAAK,CAACC,UAAU,CAAC8D,MAAM;YAAEqE,WAAW;QAAG;IACjH;IAEQlF,aAAa/C,IAAe,EAAmB;QACrD,+CAA+C;QAC/C,OAAO,IAAI,CAAC0D,GAAG,CAACsE,SAAS,CACvB;YACEE,UAAU;gBACRnG,IAAI/B,KAAK+B,EAAE;gBACX4E,OAAO3G,KAAK2G,KAAK;gBACjBH,OAAOxG,KAAKwG,KAAK;gBACjBD,UAAUvG,KAAKuG,QAAQ;gBACvB4B,UAAUnI,KAAKmI,QAAQ;gBACvBC,MAAMpI,KAAKoI,IAAI;gBACfxI,cAAcI,KAAKJ,YAAY;YACjC;QACF,GACA;YACEgE,QAAQjE,gCAAa,CAAC0I,IAAI,CAAC/E,KAAK,CAACgF,MAAM,CAAC1E,MAAM;YAC9CqE,WAAW,IAAI,CAACM,UAAU;QAC5B;IAEJ;IAEA,MAAczE,cAAc9D,IAAe,EAAEC,KAAe,EAAEwD,YAAgC,EAAE;QAC9F,KAAK,MAAM+E,UAAU/E,aAAagF,OAAO,CAAE;YACzC,IAAID,OAAOvD,IAAI,KAAK,GAAG;gBACrB,aAAa;gBACb,MAAM,IAAI,CAACX,cAAc,CAACoE,SAASF,OAAOG,MAAM,GAAG1I;YACrD,OAAO,IAAIuI,OAAOvD,IAAI,KAAK,GAAG;gBAC5B,UAAU;gBACV,MAAM,IAAI,CAAC2D,WAAW,CAAC5I,MAAMC;YAC/B;QACF;IACF;IAEA,MAAc2I,YAAY5I,IAAe,EAAEC,KAAe,EAAiB;QACzE,MAAM,CAAC4I,IAAIC,UAAU,GAAG,MAAM,IAAI,CAACrH,gBAAgB,CAACsH,MAAM,CACxD/I,MACAC,MAAM0B,MAAM,EACZC,aAAK,CAACC,QAAQ,EACd;YACEmH,UAAU;YACVC,WAAW;YACXC,WAAWjH,kBAAU,CAACC,MAAM;YAC5BiH,OAAO,CAAC,aAAa,EAAEnJ,KAAKuG,QAAQ,CAAC,EAAE,EAAEvG,KAAKwG,KAAK,CAAC,CAAC,CAAC;QACxD,GACA,IAAI,CAAC+B,UAAU;QAEjB,IAAI,CAACM,IAAI;YACP,MAAM,IAAIO,MAAM;QAClB;IACF;IAEA,MAAc9E,eAAexC,MAAc,EAAE7B,KAAe,EAAiB;QAC3E,KAAK,MAAMoJ,QAAQ,CAAA,MAAM,IAAI,CAAC5H,gBAAgB,CAAC6H,cAAc,CAACrJ,MAAM0B,MAAM,CAAA,EAAG;YAC3E,IAAI0H,KAAKF,KAAK,CAACpH,EAAE,KAAKD,QAAQ;gBAC5B,MAAM,IAAI,CAACL,gBAAgB,CAAC8H,UAAU,CAACF,KAAK5D,GAAG;YACjD;QACF;IACF;IAEA,MAAcrB,kBAAkB1B,MAAc,EAAEzC,KAAe,EAAiB;QAC9E,IAAI,CAAE,MAAM,IAAI,CAACwB,gBAAgB,CAAC+H,YAAY,CAACvJ,MAAM0B,MAAM,GAAI;YAC7D,MAAM8H,WAAW,IAAI,CAACC,WAAW,CAAChH;YAClC,MAAMiH,IAAI,MAAM,IAAI,CAACC,KAAK,CAACC,GAAG,CAACJ;YAC/B,IAAI,CAAC1F,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAACI,iBAAiB,CAACI,IAAI,CAAC,GAAG,EAAEiF,SAAS,CAAC,EAAEE,IAAI,KAAK,MAAM,QAAQ,CAAC;QAC5F;IACF;IAEA,MAAcjE,eAAehD,MAAc,EAAmB;QAC5D,MAAM+G,WAAW,IAAI,CAACC,WAAW,CAAChH;QAClC,MAAMoH,iBAAyB,MAAM,IAAI,CAACF,KAAK,CAACjF,GAAG,CAAC8E;QACpD,IAAIK,gBAAgB;YAClB,OAAOA;QACT;QACA,MAAMC,SAASC,IAAAA,4BAAiB,EAAC;QACjC,MAAM,IAAI,CAACJ,KAAK,CAACK,GAAG,CAACR,UAAUM,QAAQ,IAAI,CAACxB,UAAU;QACtD,IAAI,CAACxE,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAAC0B,cAAc,CAAClB,IAAI,CAAC,GAAG,EAAEiF,SAAS,EAAE,EAAEM,OAAO,SAAS,CAAC;QACjF,OAAOA;IACT;IAEA,MAAc5F,aAAalE,KAAe,EAAEgE,GAAW,EAAiB;QACtE;;;KAGC,GACD,MAAMiG,YAAY,IAAIC,gBAAgBlG,IAAImG,KAAK,CAAC,KAAKC,EAAE,CAAC,CAAC;QACzD,kGAAkG;QAClG,MAAMC,MAAcJ,UAAUvF,GAAG,CAAC;QAClC,MAAM4F,cAAc,MAAMC,IAAAA,4BAAqB,EAAC5J,iBAAI,CAAC6J,IAAI,CAACC,eAAE,CAACC,MAAM,IAAI,GAAGL,IAAI,CAAC,EAAEJ,UAAUvF,GAAG,CAAC,aAAa;QAE5G,oGAAoG;QACpG,MAAMiG,iBAAiBhK,iBAAI,CAACC,OAAO,CAACZ,MAAMI,QAAQ,EAAES,KAAK,CAAC;QAC1D,MAAM+J,kBAAkBjK,iBAAI,CAACC,OAAO,CAACqJ,UAAUvF,GAAG,CAAC,aAAa7D,KAAK,CAAC;QAEtE,IAAIgK;QACJ,IAAIF,mBAAmBC,mBAAmB,CAACE,0CAA8B,CAACC,UAAU,CAAC/J,GAAG,CAAC2J,iBAAiB;YACxG,IAAIG,0CAA8B,CAACE,IAAI,CAAChK,GAAG,CAAC4J,oBAAoBE,0CAA8B,CAACG,EAAE,CAACjK,GAAG,CAAC2J,iBAAiB;gBACrHE,cAAc,MAAM,IAAI,CAACK,eAAe,CAACjB,UAAUvF,GAAG,CAAC,aAAaV,KAAK4G,iBAAiBD,gBAAgB3K,MAAMgE,GAAG;YACrH,OAAO;gBACL,MAAM,IAAImF,MAAM,CAAC,kCAAkC,EAAEyB,gBAAgB,IAAI,EAAED,eAAe,GAAG,EAAE3K,MAAMgE,GAAG,EAAE;YAC5G;QACF,OAAO;YACL6G,cAAc7G;QAChB;QAEA,gBAAgB;QAChB,IAAImH;QACJ,IAAI;YACFA,MAAM,MAAM,IAAI,CAACC,IAAI,CAACC,QAAQ,CAAC;gBAC7BC,QAAQC,kCAAW,CAACC,GAAG;gBACvBxH,KAAK6G;gBACLY,cAAc;gBACdC,YAAY,IAAIC,cAAK,CAACC,KAAK,CAAC;oBAAEC,oBAAoB,IAAI,CAACA,kBAAkB;gBAAC;YAC5E;YACA,MAAMC,IAAAA,sBAAe,EAACxB,aAAaa,IAAIY,IAAI;QAC7C,EAAE,OAAOzH,GAAG;YACV,MAAM,IAAI6E,MAAM,CAAC,yBAAyB,EAAE7E,EAAEE,OAAO,EAAE;QACzD;QAEA,oCAAoC;QACpC,MAAMwH,gBAAgBvD,SAAS0C,IAAI7I,OAAO,CAAC,iBAAiB,EAAE;QAC9D,IAAI,CAAC2J,MAAMD,gBAAgB;YACzB,IAAIA,kBAAkB,GAAG;gBACvB,IAAI,CAAClI,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAACG,YAAY,CAACK,IAAI,CAAC,yBAAyB,EAAEvE,MAAMgE,GAAG,EAAE;gBAClF;YACF;YACA,MAAMkI,cAAc,MAAMC,IAAAA,eAAQ,EAAC7B;YACnC,IAAI4B,gBAAgBF,eAAe;gBACjC,MAAM,IAAI7C,MAAM,CAAC,uBAAuB,EAAE+C,YAAY,IAAI,EAAEF,cAAc,CAAC,CAAC;YAC9E;QACF;QACA,8DAA8D;QAC9D,IAAI;YACF,MAAMI,IAAAA,sBAAe,EAAC9B,aAAatK,MAAMI,QAAQ;YACjD,MAAMiM,IAAAA,kBAAW,EAAC/B;QACpB,EAAE,OAAOhG,GAAG;YACV,MAAM,IAAI6E,MAAM,CAAC,0BAA0B,EAAE7E,EAAEE,OAAO,EAAE;QAC1D;IACF;IAEA,MAAc0G,gBAAgBpJ,EAAU,EAAEkC,GAAW,EAAEuB,QAAgB,EAAE+G,UAAkB,EAAEC,QAAgB,EAAmB;QAC9H,MAAM/G,MAAc,GAAG1D,GAAG,CAAC,EAAE0K,mBAAM,CAACC,WAAW,CAAC,IAAI7J,QAAQ,CAAC,QAAQ,CAAC/B,KAAK,CAAC,GAAG,IAAI6L,OAAO,CAAC,KAAK;QAChG,MAAM5E,UAAiC;YACrCtC,KAAKA;YACLxB,KAAKA;YACL2I,UAAUpH;YACVqH,YAAYN;YACZO,OAAO;QACT;QACA/E,QAAQzE,KAAK,GAAG,MAAM,IAAI,CAACC,eAAe,CAACwE;QAC3C,IAAIgF;QACJ,IAAI;YACF,MAAM3B,MAAqB,MAAM,IAAI,CAACC,IAAI,CAACC,QAAQ,CAAC;gBAClDC,QAAQC,kCAAW,CAACwB,IAAI;gBACxB/I,KAAK,IAAI,CAACgJ,UAAU;gBACpBjB,MAAMjE;gBACN4D,YAAY,IAAIC,cAAK,CAACC,KAAK,CAAC;oBAAEC,oBAAoB,IAAI,CAACA,kBAAkB;gBAAC;YAC5E;YACAiB,SAAS3B,IAAIY,IAAI;QACnB,EAAE,OAAOzH,GAAG;YACV,MAAM,IAAI6E,MAAM,CAAC,6BAA6B,EAAE7E,EAAE2I,QAAQ,CAACrJ,MAAM,EAAE;QACrE;QACA,IAAIkJ,OAAO1I,KAAK,EAAE;YAChB,MAAM,IAAI+E,MAAM,CAAC,6BAA6B,EAAE+D,qCAAyB,CAACxI,GAAG,CAACoI,OAAO1I,KAAK,GAAG;QAC/F;QACA,IAAI0I,OAAOK,UAAU,EAAE;YACrB,IAAI,CAACrJ,MAAM,CAACsJ,GAAG,CAAC,GAAG,IAAI,CAAClC,eAAe,CAAC3G,IAAI,CAAC,GAAG,EAAEgB,SAAS,IAAI,EAAE+G,WAAW,GAAG,EAAEC,UAAU;YAC3F,OAAOO,OAAO/J,OAAO;QACvB;IACF;IAEQ0G,YAAYhH,MAAc,EAAU;QAC1C,OAAO,GAAG4K,wBAAiB,CAAC,CAAC,EAAE5K,QAAQ;IACzC;IApVA,YACE,AAAiB2I,IAAiB,EAClC,AAAiBvG,cAA8B,EAC/C,AAAiB8E,KAAY,EAC7B,AAAiBlG,GAAe,EAChC,AAAiBjC,gBAAkC,EACnD,AAAiBkB,YAA0B,CAC3C;aANiB0I,OAAAA;aACAvG,iBAAAA;aACA8E,QAAAA;aACAlG,MAAAA;aACAjC,mBAAAA;aACAkB,eAAAA;aAbXoB,SAAS,IAAIwJ,cAAM,CAAC/N,uBAAuBgF,IAAI;aACtCK,2BAA2BlF,gCAAa,CAACC,YAAY,CAACC,KAAK,CAACC,UAAU,CAAC0N,cAAc,IAAI;aACzF1B,qBAA8B,CAACnM,gCAAa,CAACC,YAAY,CAACC,KAAK,CAACC,UAAU,EAAE2N;aAC5ER,aAAa,IAAI,CAACpI,wBAAwB,GAAG,GAAG,IAAI,CAACA,wBAAwB,CAAC,oBAAoB,CAAC,GAAG;aACtG0D,aAAamF,IAAAA,oCAAyB,EAAC/N,gCAAa,CAAC0I,IAAI,CAAC/E,KAAK,CAACqK,OAAO,CAACpF,UAAU;aAClFlG,cAAsB;IASpC;AA8UL"}
|
|
@@ -135,7 +135,7 @@ let FilesParser = class FilesParser {
|
|
|
135
135
|
id: _sharesschema.shares.id,
|
|
136
136
|
alias: _sharesschema.shares.alias,
|
|
137
137
|
externalPath: (0, _drizzleorm.sql)`IF (${_sharesschema.shares.externalPath} IS NOT NULL, ${_sharesschema.shares.externalPath}, ${_spacesrootsschema.spacesRoots.externalPath})`,
|
|
138
|
-
isDir: (0, _drizzleorm.sql)`IF (${_sharesschema.shares.externalPath} IS NOT NULL, 1, ${_filesschema.files.isDir})`,
|
|
138
|
+
isDir: (0, _drizzleorm.sql)`IF (${_sharesschema.shares.externalPath} IS NOT NULL AND ${_sharesschema.shares.fileId} IS NULL, 1, ${_filesschema.files.isDir})`,
|
|
139
139
|
file: {
|
|
140
140
|
path: (0, _drizzleorm.sql)`IF (${_filesschema.files.id} IS NOT NULL, ${(0, _filesschema.filePathSQL)(_filesschema.files)}, '.')`,
|
|
141
141
|
fromOwner: _usersschema.users.login,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/files/services/files-parser.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 { Inject, Injectable, Logger } from '@nestjs/common'\nimport { and, eq, inArray, isNotNull, isNull, lte, or, sql } from 'drizzle-orm'\nimport path from 'node:path'\nimport { DB_TOKEN_PROVIDER } from '../../../infrastructure/database/constants'\nimport { DBSchema } from '../../../infrastructure/database/interfaces/database.interface'\nimport { concatDistinctObjectsInArray } from '../../../infrastructure/database/utils'\nimport { SHARE_TYPE } from '../../shares/constants/shares'\nimport { shares } from '../../shares/schemas/shares.schema'\nimport { SPACE_ALIAS, SPACE_REPOSITORY } from '../../spaces/constants/spaces'\nimport { SpaceModel } from '../../spaces/models/space.model'\nimport { spacesRoots } from '../../spaces/schemas/spaces-roots.schema'\nimport { spaces } from '../../spaces/schemas/spaces.schema'\nimport { USER_ROLE } from '../../users/constants/user'\nimport { UserModel } from '../../users/models/user.model'\nimport { users } from '../../users/schemas/users.schema'\nimport { FileParseContext, FileParseType } from '../interfaces/file-parse-index'\nimport { filePathSQL, files } from '../schemas/files.schema'\nimport { isPathExists } from '../utils/files'\n\n@Injectable()\nexport class FilesParser {\n private readonly logger = new Logger(FilesParser.name)\n\n constructor(@Inject(DB_TOKEN_PROVIDER) private readonly db: DBSchema) {}\n\n async *allPaths(userId?: number, spaceIds?: number[], shareIds?: number[]): AsyncGenerator<[number, FileParseType, FileParseContext[]]> {\n yield* this.userPaths(userId)\n yield* this.spacePaths(spaceIds)\n yield* this.sharePaths(shareIds)\n }\n\n async *userPaths(userId?: number): AsyncGenerator<[number, FileParseType, FileParseContext[]]> {\n for (const user of await this.db\n .select({\n id: users.id,\n login: users.login\n })\n .from(users)\n .where(and(...[eq(users.storageIndexing, true), lte(users.role, USER_ROLE.USER), ...(userId ? [eq(users.id, userId)] : [])]))) {\n const userFilesPath = UserModel.getFilesPath(user.login)\n if (!(await isPathExists(userFilesPath))) {\n this.logger.warn(`${this.userPaths.name} - user path does not exist : ${userFilesPath}`)\n continue\n }\n yield [user.id, 'user', [{ realPath: userFilesPath, pathPrefix: `${SPACE_REPOSITORY.FILES}/${SPACE_ALIAS.PERSONAL}`, isDir: true }]]\n }\n }\n\n async *spacePaths(spaceIds?: number[]): AsyncGenerator<[number, FileParseType, FileParseContext[]]> {\n for (const space of await this.db\n .select({\n id: spaces.id,\n alias: spaces.alias,\n roots: concatDistinctObjectsInArray(spacesRoots.alias, {\n alias: spacesRoots.alias,\n externalPath: spacesRoots.externalPath,\n isDir: sql<boolean>`IF (${spacesRoots.externalPath} IS NOT NULL, 1, ${files.isDir})`,\n file: {\n path: filePathSQL(files),\n fromOwner: users.login\n }\n })\n })\n .from(spaces)\n .leftJoin(spacesRoots, eq(spacesRoots.spaceId, spaces.id))\n .leftJoin(files, eq(files.id, spacesRoots.fileId))\n .leftJoin(users, eq(users.id, files.ownerId))\n .where(and(eq(spaces.storageIndexing, true), ...(spaceIds ? [inArray(spaces.id, spaceIds)] : [])))\n .groupBy(spaces.id)) {\n const spaceFilesPath = SpaceModel.getFilesPath(space.alias)\n if (!(await isPathExists(spaceFilesPath))) {\n this.logger.warn(`${this.spacePaths.name} - space path does not exist : ${spaceFilesPath}`)\n continue\n }\n const spacePath = [{ realPath: spaceFilesPath, pathPrefix: `${SPACE_REPOSITORY.FILES}/${space.alias}`, isDir: true }]\n const rootPaths = space.roots.map(\n (r: any): FileParseContext =>\n r.externalPath\n ? {\n realPath: r.externalPath,\n pathPrefix: `${SPACE_REPOSITORY.FILES}/${space.alias}/${r.alias}`,\n isDir: r.isDir\n }\n : {\n realPath: path.join(UserModel.getFilesPath(r.file.fromOwner), r.file.path),\n pathPrefix: `${SPACE_REPOSITORY.FILES}/${space.alias}/${r.alias}`,\n isDir: r.isDir\n }\n )\n yield [space.id, 'space', [...spacePath, ...rootPaths]]\n }\n }\n\n async *sharePaths(shareIds?: number[]): AsyncGenerator<[number, FileParseType, FileParseContext[]]> {\n for (const share of await this.db\n .select({\n id: shares.id,\n alias: shares.alias,\n externalPath: sql<string>`IF (${shares.externalPath} IS NOT NULL, ${shares.externalPath}, ${spacesRoots.externalPath})`,\n isDir: sql<boolean>`IF (${shares.externalPath} IS NOT NULL, 1, ${files.isDir})`,\n file: { path: sql<string>`IF (${files.id} IS NOT NULL, ${filePathSQL(files)}, '.')`, fromOwner: users.login, fromSpace: spaces.alias }\n })\n .from(shares)\n .leftJoin(spacesRoots, eq(spacesRoots.id, shares.spaceRootId))\n .leftJoin(\n files,\n or(\n // If the child share is from a share with an external path, the child share should have an external path and a fileId\n and(isNotNull(shares.fileId), eq(files.id, shares.fileId)),\n and(isNull(shares.externalPath), isNull(shares.fileId), isNotNull(spacesRoots.fileId), eq(files.id, spacesRoots.fileId))\n )\n )\n .leftJoin(spaces, and(isNull(shares.externalPath), isNotNull(files.spaceId), eq(spaces.id, files.spaceId), eq(spaces.storageIndexing, true)))\n .leftJoin(users, and(eq(users.id, files.ownerId), eq(users.storageIndexing, true)))\n .where(and(eq(shares.storageIndexing, true), ...[eq(shares.type, SHARE_TYPE.COMMON), ...(shareIds ? [inArray(shares.id, shareIds)] : [])]))\n .groupBy(shares.id)) {\n let shareFilesPath: string\n if (share.externalPath) {\n shareFilesPath = path.join(share.externalPath, share.file.path)\n } else if (share.file.fromOwner) {\n shareFilesPath = path.join(UserModel.getFilesPath(share.file.fromOwner), share.file.path)\n } else if (share.file.fromSpace) {\n shareFilesPath = path.join(SpaceModel.getFilesPath(share.file.fromSpace), share.file.path)\n } else {\n // Exclude shares that don’t match these cases (join conditions)\n continue\n }\n if (!(await isPathExists(shareFilesPath))) {\n this.logger.warn(`${this.sharePaths.name} - share path does not exist : ${shareFilesPath}`)\n continue\n }\n yield [share.id, 'share', [{ realPath: shareFilesPath, pathPrefix: `${SPACE_REPOSITORY.SHARES}/${share.alias}`, isDir: share.isDir }]]\n }\n }\n}\n"],"names":["FilesParser","allPaths","userId","spaceIds","shareIds","userPaths","spacePaths","sharePaths","user","db","select","id","users","login","from","where","and","eq","storageIndexing","lte","role","USER_ROLE","USER","userFilesPath","UserModel","getFilesPath","isPathExists","logger","warn","name","realPath","pathPrefix","SPACE_REPOSITORY","FILES","SPACE_ALIAS","PERSONAL","isDir","space","spaces","alias","roots","concatDistinctObjectsInArray","spacesRoots","externalPath","sql","files","file","path","filePathSQL","fromOwner","leftJoin","spaceId","fileId","ownerId","inArray","groupBy","spaceFilesPath","SpaceModel","spacePath","rootPaths","map","r","join","share","shares","fromSpace","spaceRootId","or","isNotNull","isNull","type","SHARE_TYPE","COMMON","shareFilesPath","SHARES","Logger"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/files/services/files-parser.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 { Inject, Injectable, Logger } from '@nestjs/common'\nimport { and, eq, inArray, isNotNull, isNull, lte, or, sql } from 'drizzle-orm'\nimport path from 'node:path'\nimport { DB_TOKEN_PROVIDER } from '../../../infrastructure/database/constants'\nimport { DBSchema } from '../../../infrastructure/database/interfaces/database.interface'\nimport { concatDistinctObjectsInArray } from '../../../infrastructure/database/utils'\nimport { SHARE_TYPE } from '../../shares/constants/shares'\nimport { shares } from '../../shares/schemas/shares.schema'\nimport { SPACE_ALIAS, SPACE_REPOSITORY } from '../../spaces/constants/spaces'\nimport { SpaceModel } from '../../spaces/models/space.model'\nimport { spacesRoots } from '../../spaces/schemas/spaces-roots.schema'\nimport { spaces } from '../../spaces/schemas/spaces.schema'\nimport { USER_ROLE } from '../../users/constants/user'\nimport { UserModel } from '../../users/models/user.model'\nimport { users } from '../../users/schemas/users.schema'\nimport { FileParseContext, FileParseType } from '../interfaces/file-parse-index'\nimport { filePathSQL, files } from '../schemas/files.schema'\nimport { isPathExists } from '../utils/files'\n\n@Injectable()\nexport class FilesParser {\n private readonly logger = new Logger(FilesParser.name)\n\n constructor(@Inject(DB_TOKEN_PROVIDER) private readonly db: DBSchema) {}\n\n async *allPaths(userId?: number, spaceIds?: number[], shareIds?: number[]): AsyncGenerator<[number, FileParseType, FileParseContext[]]> {\n yield* this.userPaths(userId)\n yield* this.spacePaths(spaceIds)\n yield* this.sharePaths(shareIds)\n }\n\n async *userPaths(userId?: number): AsyncGenerator<[number, FileParseType, FileParseContext[]]> {\n for (const user of await this.db\n .select({\n id: users.id,\n login: users.login\n })\n .from(users)\n .where(and(...[eq(users.storageIndexing, true), lte(users.role, USER_ROLE.USER), ...(userId ? [eq(users.id, userId)] : [])]))) {\n const userFilesPath = UserModel.getFilesPath(user.login)\n if (!(await isPathExists(userFilesPath))) {\n this.logger.warn(`${this.userPaths.name} - user path does not exist : ${userFilesPath}`)\n continue\n }\n yield [user.id, 'user', [{ realPath: userFilesPath, pathPrefix: `${SPACE_REPOSITORY.FILES}/${SPACE_ALIAS.PERSONAL}`, isDir: true }]]\n }\n }\n\n async *spacePaths(spaceIds?: number[]): AsyncGenerator<[number, FileParseType, FileParseContext[]]> {\n for (const space of await this.db\n .select({\n id: spaces.id,\n alias: spaces.alias,\n roots: concatDistinctObjectsInArray(spacesRoots.alias, {\n alias: spacesRoots.alias,\n externalPath: spacesRoots.externalPath,\n isDir: sql<boolean>`IF (${spacesRoots.externalPath} IS NOT NULL, 1, ${files.isDir})`,\n file: {\n path: filePathSQL(files),\n fromOwner: users.login\n }\n })\n })\n .from(spaces)\n .leftJoin(spacesRoots, eq(spacesRoots.spaceId, spaces.id))\n .leftJoin(files, eq(files.id, spacesRoots.fileId))\n .leftJoin(users, eq(users.id, files.ownerId))\n .where(and(eq(spaces.storageIndexing, true), ...(spaceIds ? [inArray(spaces.id, spaceIds)] : [])))\n .groupBy(spaces.id)) {\n const spaceFilesPath = SpaceModel.getFilesPath(space.alias)\n if (!(await isPathExists(spaceFilesPath))) {\n this.logger.warn(`${this.spacePaths.name} - space path does not exist : ${spaceFilesPath}`)\n continue\n }\n const spacePath = [{ realPath: spaceFilesPath, pathPrefix: `${SPACE_REPOSITORY.FILES}/${space.alias}`, isDir: true }]\n const rootPaths = space.roots.map(\n (r: any): FileParseContext =>\n r.externalPath\n ? {\n realPath: r.externalPath,\n pathPrefix: `${SPACE_REPOSITORY.FILES}/${space.alias}/${r.alias}`,\n isDir: r.isDir\n }\n : {\n realPath: path.join(UserModel.getFilesPath(r.file.fromOwner), r.file.path),\n pathPrefix: `${SPACE_REPOSITORY.FILES}/${space.alias}/${r.alias}`,\n isDir: r.isDir\n }\n )\n yield [space.id, 'space', [...spacePath, ...rootPaths]]\n }\n }\n\n async *sharePaths(shareIds?: number[]): AsyncGenerator<[number, FileParseType, FileParseContext[]]> {\n for (const share of await this.db\n .select({\n id: shares.id,\n alias: shares.alias,\n externalPath: sql<string>`IF (${shares.externalPath} IS NOT NULL, ${shares.externalPath}, ${spacesRoots.externalPath})`,\n isDir: sql<boolean>`IF (${shares.externalPath} IS NOT NULL AND ${shares.fileId} IS NULL, 1, ${files.isDir})`,\n file: { path: sql<string>`IF (${files.id} IS NOT NULL, ${filePathSQL(files)}, '.')`, fromOwner: users.login, fromSpace: spaces.alias }\n })\n .from(shares)\n .leftJoin(spacesRoots, eq(spacesRoots.id, shares.spaceRootId))\n .leftJoin(\n files,\n or(\n // If the child share is from a share with an external path, the child share should have an external path and a fileId\n and(isNotNull(shares.fileId), eq(files.id, shares.fileId)),\n and(isNull(shares.externalPath), isNull(shares.fileId), isNotNull(spacesRoots.fileId), eq(files.id, spacesRoots.fileId))\n )\n )\n .leftJoin(spaces, and(isNull(shares.externalPath), isNotNull(files.spaceId), eq(spaces.id, files.spaceId), eq(spaces.storageIndexing, true)))\n .leftJoin(users, and(eq(users.id, files.ownerId), eq(users.storageIndexing, true)))\n .where(and(eq(shares.storageIndexing, true), ...[eq(shares.type, SHARE_TYPE.COMMON), ...(shareIds ? [inArray(shares.id, shareIds)] : [])]))\n .groupBy(shares.id)) {\n let shareFilesPath: string\n if (share.externalPath) {\n shareFilesPath = path.join(share.externalPath, share.file.path)\n } else if (share.file.fromOwner) {\n shareFilesPath = path.join(UserModel.getFilesPath(share.file.fromOwner), share.file.path)\n } else if (share.file.fromSpace) {\n shareFilesPath = path.join(SpaceModel.getFilesPath(share.file.fromSpace), share.file.path)\n } else {\n // Exclude shares that don’t match these cases (join conditions)\n continue\n }\n if (!(await isPathExists(shareFilesPath))) {\n this.logger.warn(`${this.sharePaths.name} - share path does not exist : ${shareFilesPath}`)\n continue\n }\n yield [share.id, 'share', [{ realPath: shareFilesPath, pathPrefix: `${SPACE_REPOSITORY.SHARES}/${share.alias}`, isDir: share.isDir }]]\n }\n }\n}\n"],"names":["FilesParser","allPaths","userId","spaceIds","shareIds","userPaths","spacePaths","sharePaths","user","db","select","id","users","login","from","where","and","eq","storageIndexing","lte","role","USER_ROLE","USER","userFilesPath","UserModel","getFilesPath","isPathExists","logger","warn","name","realPath","pathPrefix","SPACE_REPOSITORY","FILES","SPACE_ALIAS","PERSONAL","isDir","space","spaces","alias","roots","concatDistinctObjectsInArray","spacesRoots","externalPath","sql","files","file","path","filePathSQL","fromOwner","leftJoin","spaceId","fileId","ownerId","inArray","groupBy","spaceFilesPath","SpaceModel","spacePath","rootPaths","map","r","join","share","shares","fromSpace","spaceRootId","or","isNotNull","isNull","type","SHARE_TYPE","COMMON","shareFilesPath","SHARES","Logger"],"mappings":"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"}
|
|
@@ -97,6 +97,16 @@ let FilesQueries = class FilesQueries {
|
|
|
97
97
|
}
|
|
98
98
|
return q;
|
|
99
99
|
}
|
|
100
|
+
async getUserFile(userId, fileId) {
|
|
101
|
+
if (fileId > 0) {
|
|
102
|
+
const [fileInDB] = await this.db.select({
|
|
103
|
+
id: _filesschema.files.id,
|
|
104
|
+
path: (0, _filesschema.filePathSQL)(_filesschema.files)
|
|
105
|
+
}).from(_filesschema.files).where((0, _drizzleorm.and)((0, _drizzleorm.eq)(_filesschema.files.ownerId, userId), (0, _drizzleorm.eq)(_filesschema.files.id, fileId))).limit(1);
|
|
106
|
+
return fileInDB;
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
100
110
|
async getOrCreateUserFile(userId, file) {
|
|
101
111
|
if (file.id && file.id > 0) {
|
|
102
112
|
const [searchFileInDB] = await this.db.select({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/files/services/files-queries.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 { Inject, Injectable, Logger } from '@nestjs/common'\nimport { and, desc, eq, getTableColumns, inArray, isNull, or, SelectedFields, sql, SQL } from 'drizzle-orm'\nimport { popFromObject } from '../../../common/shared'\nimport { DB_TOKEN_PROVIDER } from '../../../infrastructure/database/constants'\nimport { DBSchema } from '../../../infrastructure/database/interfaces/database.interface'\nimport { concatDistinctObjectsInArray, convertToWhere, dbCheckAffectedRows, dbGetInsertedId } from '../../../infrastructure/database/utils'\nimport { fileHasCommentsSubquerySQL } from '../../comments/schemas/comments.schema'\nimport { shares } from '../../shares/schemas/shares.schema'\nimport { spacesRoots } from '../../spaces/schemas/spaces-roots.schema'\nimport { spaces } from '../../spaces/schemas/spaces.schema'\nimport { syncClients } from '../../sync/schemas/sync-clients.schema'\nimport { syncPaths } from '../../sync/schemas/sync-paths.schema'\nimport { FileDBProps } from '../interfaces/file-db-props.interface'\nimport { FileProps } from '../interfaces/file-props.interface'\nimport { FileRecentLocation } from '../interfaces/file-recent-location.interface'\nimport { FileRecent } from '../schemas/file-recent.interface'\nimport { File } from '../schemas/file.interface'\nimport { filesRecents } from '../schemas/files-recents.schema'\nimport { childFilesFindRegexp, childFilesReplaceRegexp, files } from '../schemas/files.schema'\nimport { dirName, fileName } from '../utils/files'\n\n@Injectable()\nexport class FilesQueries {\n private readonly logger = new Logger(FilesQueries.name)\n\n constructor(@Inject(DB_TOKEN_PROVIDER) private readonly db: DBSchema) {}\n\n browseFiles(\n userId: number,\n dbFile: FileDBProps,\n options: {\n withSpaces?: boolean\n withShares?: boolean\n withSyncs?: boolean\n withHasComments?: boolean\n ignoreChildShares?: boolean\n }\n ): Promise<FileProps[]> {\n const q = this.db\n .select({\n id: files.id,\n path: files.path,\n name: files.name,\n isDir: files.isDir,\n mime: files.mime,\n size: files.size,\n mtime: files.mtime,\n ctime: files.ctime,\n ...(options.withSpaces && { spaces: concatDistinctObjectsInArray(spaces.id, { id: spaces.id, alias: spaces.alias, name: spaces.name }) }),\n ...(options.withShares && {\n shares: concatDistinctObjectsInArray(shares.id, {\n id: shares.id,\n alias: shares.alias,\n name: shares.name,\n type: shares.type\n })\n }),\n ...(options.withSyncs && {\n syncs: concatDistinctObjectsInArray(syncPaths.id, {\n id: syncPaths.id,\n clientId: syncClients.id,\n clientName: sql`JSON_VALUE(${syncClients.info}, '$.node')`\n })\n }),\n ...(options.withHasComments && { hasComments: sql`${fileHasCommentsSubquerySQL(files.id)}`.mapWith(Boolean) })\n })\n .from(files)\n .where(and(...convertToWhere(files, dbFile)))\n .groupBy(files.id)\n if (options.withSpaces) {\n // show spaces for files in personal space\n q.leftJoin(spacesRoots, eq(spacesRoots.fileId, files.id))\n q.leftJoin(spaces, eq(spaces.id, spacesRoots.spaceId))\n }\n if (options.withShares) {\n q.leftJoin(\n shares,\n and(...[eq(shares.ownerId, userId), eq(shares.fileId, files.id)], ...(options.ignoreChildShares ? [isNull(shares.parentId)] : []))\n )\n }\n if (options.withSyncs) {\n q.leftJoin(syncClients, eq(syncClients.ownerId, userId))\n q.leftJoin(syncPaths, and(eq(syncPaths.clientId, syncClients.id), eq(syncPaths.fileId, files.id)))\n }\n return q\n }\n\n async getOrCreateUserFile(userId: number, file: FileProps): Promise<number> {\n if (file.id && file.id > 0) {\n const [searchFileInDB] = await this.db\n .select({ id: files.id })\n .from(files)\n .where(and(eq(files.ownerId, userId), eq(files.id, file.id)))\n .limit(1)\n if (searchFileInDB?.id === file.id) {\n return file.id\n } else {\n this.logger.warn(`${this.getOrCreateUserFile.name} - file mismatch : ${JSON.stringify(searchFileInDB)} !== ${JSON.stringify(file)}`)\n }\n }\n return dbGetInsertedId(await this.db.insert(files).values({ ...file, id: undefined, ownerId: userId } as File))\n }\n\n async getOrCreateSpaceFile(fileId: number, file: FileProps, dbFile: FileDBProps): Promise<number> {\n if (fileId && fileId > 0) {\n const fileInDB = {\n ...dbFile,\n name: file.name,\n path: file.path,\n isDir: file.isDir\n }\n const [searchFileInDB] = await this.db\n .select({ id: files.id })\n .from(files)\n .where(and(...convertToWhere(files, fileInDB), eq(files.id, fileId)))\n .limit(1)\n if (searchFileInDB?.id === fileId) {\n return fileId\n } else {\n this.logger.warn(`${this.getOrCreateSpaceFile.name} - file mismatch : ${JSON.stringify(dbFile)} -> ${fileId} !== ${searchFileInDB?.id}`)\n }\n }\n // order is important, path is replaced by the FileProps.path\n return dbGetInsertedId(await this.db.insert(files).values({ ...dbFile, ...file }))\n }\n\n async getSpaceFileId(file: FileProps, dbFile: FileDBProps): Promise<number> {\n const fileInDB = {\n ...dbFile,\n name: file.name,\n path: file.path,\n isDir: file.isDir\n }\n const [searchFileInDB] = await this.db\n .select({ id: files.id })\n .from(files)\n .where(and(...convertToWhere(files, fileInDB)))\n .limit(1)\n return searchFileInDB?.id\n }\n\n async updateFile(id: number, file: Partial<FileProps>): Promise<void> {\n try {\n dbCheckAffectedRows(await this.db.update(files).set(file).where(eq(files.id, id)), 1)\n } catch (e) {\n this.logger.error(`${this.updateFile.name} - file (${id}) properties was not updated : ${e}`)\n }\n }\n\n async deleteFiles(props: FileDBProps, isDir: boolean, force = false): Promise<void> {\n const commonProps: Omit<FileDBProps, 'path'> = {\n ownerId: props.ownerId || null,\n spaceId: props.spaceId || null,\n spaceExternalRootId: props.spaceExternalRootId || null,\n shareExternalId: props.shareExternalId || null,\n inTrash: props.inTrash\n }\n\n // prepare file update/delete\n const fileProps: FileDBProps & { name: string; isDir: boolean } = {\n ...commonProps,\n path: dirName(props.path),\n name: fileName(props.path),\n isDir: isDir\n }\n\n // prepare (or not) the child files update/delete\n const childFiles = isDir ? childFilesFindRegexp(props.path) : null\n if (fileProps.inTrash || force) {\n // delete file\n await this.db.delete(files).where(and(...convertToWhere(files, fileProps)))\n if (childFiles) {\n // delete child files\n await this.db.delete(files).where(and(...[...convertToWhere(files, commonProps), childFiles]))\n }\n } else {\n // move file to trash\n await this.db\n .update(files)\n .set({ inTrash: true } as File)\n .where(and(...convertToWhere(files, fileProps)))\n if (childFiles) {\n // move child files to trash\n await this.db\n .update(files)\n .set({ inTrash: true } as File)\n .where(and(...convertToWhere(files, commonProps), childFiles))\n }\n }\n }\n\n async moveFiles(srcProps: FileDBProps, dstProps: FileDBProps, isDir: boolean): Promise<void> {\n const srcCommonProps: Omit<FileDBProps, 'path'> = {\n ownerId: srcProps.ownerId || null,\n spaceId: srcProps.spaceId || null,\n spaceExternalRootId: srcProps.spaceExternalRootId || null,\n shareExternalId: srcProps.shareExternalId || null,\n inTrash: srcProps.inTrash\n }\n const dstCommonProps: Omit<FileDBProps, 'path'> = {\n ownerId: dstProps.ownerId || null,\n spaceId: dstProps.spaceId || null,\n spaceExternalRootId: dstProps.spaceExternalRootId || null,\n shareExternalId: dstProps.shareExternalId || null,\n inTrash: dstProps.inTrash\n }\n\n // prepare file props update\n const srcFileDB: FileDBProps & { name: string; isDir: boolean } = {\n ...srcCommonProps,\n path: dirName(srcProps.path),\n name: fileName(srcProps.path),\n isDir: isDir\n }\n const dstFileDB: FileDBProps & { name: string; isDir: boolean } = {\n ...dstCommonProps,\n path: dirName(dstProps.path),\n name: fileName(dstProps.path),\n isDir: isDir\n }\n\n // update file props\n await this.db\n .update(files)\n .set(dstFileDB)\n .where(and(...convertToWhere(files, srcFileDB)))\n if (isDir) {\n // prepare child file props update\n const childFiles: SQL<string> = childFilesFindRegexp(srcProps.path)\n const childProps: Omit<FileDBProps, 'path'> & { path: SQL<string> } = {\n ...dstCommonProps,\n path: childFilesReplaceRegexp(srcProps.path, dstProps.path)\n }\n // update child file props\n await this.db\n .update(files)\n .set(childProps)\n .where(and(...convertToWhere(files, srcCommonProps), childFiles))\n }\n }\n\n async compareAndUpdateFileProps(dbFile: FileProps, fsFile: FileProps): Promise<void> {\n if (\n dbFile.isDir !== fsFile.isDir ||\n dbFile.size !== fsFile.size ||\n dbFile.ctime !== fsFile.ctime ||\n dbFile.mtime !== fsFile.mtime ||\n dbFile.mime !== fsFile.mime\n ) {\n this.logger.verbose(`${this.compareAndUpdateFileProps.name} - ${dbFile.path} (${dbFile.id})`)\n await this.updateFile(dbFile.id, {\n isDir: fsFile.isDir,\n size: fsFile.size,\n ctime: fsFile.ctime,\n mtime: fsFile.mtime,\n mime: fsFile.mime\n })\n }\n }\n\n getRecentsFromUser(userId: number, spaceIds: number[], shareIds: number[], limit = 10): Promise<FileRecent[]> {\n return this.db\n .select({\n id: filesRecents.id,\n ownerId: sql<number>`IF(${filesRecents.ownerId} IS NULL, 0, 1)`.as('ownerId'),\n spaceId: sql<number>`IF(${filesRecents.spaceId} IS NULL, 0, 1)`.as('spaceId'),\n shareId: sql<number>`IF(${filesRecents.shareId} IS NULL, 0, 1)`.as('shareId'),\n path: filesRecents.path,\n name: filesRecents.name,\n mime: filesRecents.mime,\n mtime: filesRecents.mtime\n } satisfies FileRecent | SelectedFields<any, any>)\n .from(filesRecents)\n .where(or(eq(filesRecents.ownerId, userId), inArray(filesRecents.spaceId, spaceIds), inArray(filesRecents.shareId, shareIds)))\n .groupBy(filesRecents.id)\n .orderBy(desc(filesRecents.mtime))\n .limit(limit)\n }\n\n getRecentsFromLocation(location: Partial<Record<keyof FileRecent, any>>): Promise<FileRecent[]> {\n const where: SQL[] = convertToWhere(filesRecents, location)\n return this.db\n .select(getTableColumns(filesRecents))\n .from(filesRecents)\n .where(and(...where))\n }\n\n async updateRecents(\n location: FileRecentLocation,\n add: Partial<FileRecent>[] | FileRecent[],\n update: Record<string | 'object', Partial<FileProps> | FileProps>[],\n remove: FileRecent['id'][]\n ): Promise<void> {\n const where: SQL[] = convertToWhere(filesRecents, location)\n // add\n if (add.length) {\n try {\n await this.db.insert(filesRecents).values(add as FileRecent[])\n } catch (e) {\n this.logger.error(`${this.updateRecents.name} - ${e}`)\n }\n }\n // update\n if (update.length) {\n for (const props of update) {\n const f: FileProps = popFromObject('object', props)\n try {\n await this.db\n .update(filesRecents)\n .set({ ...props })\n .where(and(...where, eq(filesRecents.id, f.id)))\n .limit(1)\n } catch (e) {\n this.logger.error(`${this.updateRecents.name} - ${e}`)\n }\n }\n }\n // remove\n if (remove.length) {\n try {\n await this.db.delete(filesRecents).where(and(...where, inArray(filesRecents.id, remove)))\n } catch (e) {\n this.logger.error(`${this.updateRecents.name} - ${e}`)\n }\n }\n }\n}\n"],"names":["FilesQueries","browseFiles","userId","dbFile","options","q","db","select","id","files","path","name","isDir","mime","size","mtime","ctime","withSpaces","spaces","concatDistinctObjectsInArray","alias","withShares","shares","type","withSyncs","syncs","syncPaths","clientId","syncClients","clientName","sql","info","withHasComments","hasComments","fileHasCommentsSubquerySQL","mapWith","Boolean","from","where","and","convertToWhere","groupBy","leftJoin","spacesRoots","eq","fileId","spaceId","ownerId","ignoreChildShares","isNull","parentId","getOrCreateUserFile","file","searchFileInDB","limit","logger","warn","JSON","stringify","dbGetInsertedId","insert","values","undefined","getOrCreateSpaceFile","fileInDB","getSpaceFileId","updateFile","dbCheckAffectedRows","update","set","e","error","deleteFiles","props","force","commonProps","spaceExternalRootId","shareExternalId","inTrash","fileProps","dirName","fileName","childFiles","childFilesFindRegexp","delete","moveFiles","srcProps","dstProps","srcCommonProps","dstCommonProps","srcFileDB","dstFileDB","childProps","childFilesReplaceRegexp","compareAndUpdateFileProps","fsFile","verbose","getRecentsFromUser","spaceIds","shareIds","filesRecents","as","shareId","or","inArray","orderBy","desc","getRecentsFromLocation","location","getTableColumns","updateRecents","add","remove","length","f","popFromObject","Logger"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/files/services/files-queries.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 { Inject, Injectable, Logger } from '@nestjs/common'\nimport { and, desc, eq, getTableColumns, inArray, isNull, or, SelectedFields, sql, SQL } from 'drizzle-orm'\nimport { popFromObject } from '../../../common/shared'\nimport { DB_TOKEN_PROVIDER } from '../../../infrastructure/database/constants'\nimport { DBSchema } from '../../../infrastructure/database/interfaces/database.interface'\nimport { concatDistinctObjectsInArray, convertToWhere, dbCheckAffectedRows, dbGetInsertedId } from '../../../infrastructure/database/utils'\nimport { fileHasCommentsSubquerySQL } from '../../comments/schemas/comments.schema'\nimport { shares } from '../../shares/schemas/shares.schema'\nimport { spacesRoots } from '../../spaces/schemas/spaces-roots.schema'\nimport { spaces } from '../../spaces/schemas/spaces.schema'\nimport { syncClients } from '../../sync/schemas/sync-clients.schema'\nimport { syncPaths } from '../../sync/schemas/sync-paths.schema'\nimport { FileDBProps } from '../interfaces/file-db-props.interface'\nimport { FileProps } from '../interfaces/file-props.interface'\nimport { FileRecentLocation } from '../interfaces/file-recent-location.interface'\nimport { FileRecent } from '../schemas/file-recent.interface'\nimport { File } from '../schemas/file.interface'\nimport { filesRecents } from '../schemas/files-recents.schema'\nimport { childFilesFindRegexp, childFilesReplaceRegexp, filePathSQL, files } from '../schemas/files.schema'\nimport { dirName, fileName } from '../utils/files'\n\n@Injectable()\nexport class FilesQueries {\n private readonly logger = new Logger(FilesQueries.name)\n\n constructor(@Inject(DB_TOKEN_PROVIDER) private readonly db: DBSchema) {}\n\n browseFiles(\n userId: number,\n dbFile: FileDBProps,\n options: {\n withSpaces?: boolean\n withShares?: boolean\n withSyncs?: boolean\n withHasComments?: boolean\n ignoreChildShares?: boolean\n }\n ): Promise<FileProps[]> {\n const q = this.db\n .select({\n id: files.id,\n path: files.path,\n name: files.name,\n isDir: files.isDir,\n mime: files.mime,\n size: files.size,\n mtime: files.mtime,\n ctime: files.ctime,\n ...(options.withSpaces && { spaces: concatDistinctObjectsInArray(spaces.id, { id: spaces.id, alias: spaces.alias, name: spaces.name }) }),\n ...(options.withShares && {\n shares: concatDistinctObjectsInArray(shares.id, {\n id: shares.id,\n alias: shares.alias,\n name: shares.name,\n type: shares.type\n })\n }),\n ...(options.withSyncs && {\n syncs: concatDistinctObjectsInArray(syncPaths.id, {\n id: syncPaths.id,\n clientId: syncClients.id,\n clientName: sql`JSON_VALUE(${syncClients.info}, '$.node')`\n })\n }),\n ...(options.withHasComments && { hasComments: sql`${fileHasCommentsSubquerySQL(files.id)}`.mapWith(Boolean) })\n })\n .from(files)\n .where(and(...convertToWhere(files, dbFile)))\n .groupBy(files.id)\n if (options.withSpaces) {\n // show spaces for files in personal space\n q.leftJoin(spacesRoots, eq(spacesRoots.fileId, files.id))\n q.leftJoin(spaces, eq(spaces.id, spacesRoots.spaceId))\n }\n if (options.withShares) {\n q.leftJoin(\n shares,\n and(...[eq(shares.ownerId, userId), eq(shares.fileId, files.id)], ...(options.ignoreChildShares ? [isNull(shares.parentId)] : []))\n )\n }\n if (options.withSyncs) {\n q.leftJoin(syncClients, eq(syncClients.ownerId, userId))\n q.leftJoin(syncPaths, and(eq(syncPaths.clientId, syncClients.id), eq(syncPaths.fileId, files.id)))\n }\n return q\n }\n\n async getUserFile(userId: number, fileId: number): Promise<Pick<File, 'id' | 'path'>> {\n if (fileId > 0) {\n const [fileInDB] = await this.db\n .select({ id: files.id, path: filePathSQL(files) })\n .from(files)\n .where(and(eq(files.ownerId, userId), eq(files.id, fileId)))\n .limit(1)\n return fileInDB\n }\n return null\n }\n\n async getOrCreateUserFile(userId: number, file: FileProps): Promise<number> {\n if (file.id && file.id > 0) {\n const [searchFileInDB] = await this.db\n .select({ id: files.id })\n .from(files)\n .where(and(eq(files.ownerId, userId), eq(files.id, file.id)))\n .limit(1)\n if (searchFileInDB?.id === file.id) {\n return file.id\n } else {\n this.logger.warn(`${this.getOrCreateUserFile.name} - file mismatch : ${JSON.stringify(searchFileInDB)} !== ${JSON.stringify(file)}`)\n }\n }\n return dbGetInsertedId(await this.db.insert(files).values({ ...file, id: undefined, ownerId: userId } as File))\n }\n\n async getOrCreateSpaceFile(fileId: number, file: FileProps, dbFile: FileDBProps): Promise<number> {\n if (fileId && fileId > 0) {\n const fileInDB = {\n ...dbFile,\n name: file.name,\n path: file.path,\n isDir: file.isDir\n }\n const [searchFileInDB] = await this.db\n .select({ id: files.id })\n .from(files)\n .where(and(...convertToWhere(files, fileInDB), eq(files.id, fileId)))\n .limit(1)\n if (searchFileInDB?.id === fileId) {\n return fileId\n } else {\n this.logger.warn(`${this.getOrCreateSpaceFile.name} - file mismatch : ${JSON.stringify(dbFile)} -> ${fileId} !== ${searchFileInDB?.id}`)\n }\n }\n // order is important, path is replaced by the FileProps.path\n return dbGetInsertedId(await this.db.insert(files).values({ ...dbFile, ...file }))\n }\n\n async getSpaceFileId(file: FileProps, dbFile: FileDBProps): Promise<number> {\n const fileInDB = {\n ...dbFile,\n name: file.name,\n path: file.path,\n isDir: file.isDir\n }\n const [searchFileInDB] = await this.db\n .select({ id: files.id })\n .from(files)\n .where(and(...convertToWhere(files, fileInDB)))\n .limit(1)\n return searchFileInDB?.id\n }\n\n async updateFile(id: number, file: Partial<FileProps>): Promise<void> {\n try {\n dbCheckAffectedRows(await this.db.update(files).set(file).where(eq(files.id, id)), 1)\n } catch (e) {\n this.logger.error(`${this.updateFile.name} - file (${id}) properties was not updated : ${e}`)\n }\n }\n\n async deleteFiles(props: FileDBProps, isDir: boolean, force = false): Promise<void> {\n const commonProps: Omit<FileDBProps, 'path'> = {\n ownerId: props.ownerId || null,\n spaceId: props.spaceId || null,\n spaceExternalRootId: props.spaceExternalRootId || null,\n shareExternalId: props.shareExternalId || null,\n inTrash: props.inTrash\n }\n\n // prepare file update/delete\n const fileProps: FileDBProps & { name: string; isDir: boolean } = {\n ...commonProps,\n path: dirName(props.path),\n name: fileName(props.path),\n isDir: isDir\n }\n\n // prepare (or not) the child files update/delete\n const childFiles = isDir ? childFilesFindRegexp(props.path) : null\n if (fileProps.inTrash || force) {\n // delete file\n await this.db.delete(files).where(and(...convertToWhere(files, fileProps)))\n if (childFiles) {\n // delete child files\n await this.db.delete(files).where(and(...[...convertToWhere(files, commonProps), childFiles]))\n }\n } else {\n // move file to trash\n await this.db\n .update(files)\n .set({ inTrash: true } as File)\n .where(and(...convertToWhere(files, fileProps)))\n if (childFiles) {\n // move child files to trash\n await this.db\n .update(files)\n .set({ inTrash: true } as File)\n .where(and(...convertToWhere(files, commonProps), childFiles))\n }\n }\n }\n\n async moveFiles(srcProps: FileDBProps, dstProps: FileDBProps, isDir: boolean): Promise<void> {\n const srcCommonProps: Omit<FileDBProps, 'path'> = {\n ownerId: srcProps.ownerId || null,\n spaceId: srcProps.spaceId || null,\n spaceExternalRootId: srcProps.spaceExternalRootId || null,\n shareExternalId: srcProps.shareExternalId || null,\n inTrash: srcProps.inTrash\n }\n const dstCommonProps: Omit<FileDBProps, 'path'> = {\n ownerId: dstProps.ownerId || null,\n spaceId: dstProps.spaceId || null,\n spaceExternalRootId: dstProps.spaceExternalRootId || null,\n shareExternalId: dstProps.shareExternalId || null,\n inTrash: dstProps.inTrash\n }\n\n // prepare file props update\n const srcFileDB: FileDBProps & { name: string; isDir: boolean } = {\n ...srcCommonProps,\n path: dirName(srcProps.path),\n name: fileName(srcProps.path),\n isDir: isDir\n }\n const dstFileDB: FileDBProps & { name: string; isDir: boolean } = {\n ...dstCommonProps,\n path: dirName(dstProps.path),\n name: fileName(dstProps.path),\n isDir: isDir\n }\n\n // update file props\n await this.db\n .update(files)\n .set(dstFileDB)\n .where(and(...convertToWhere(files, srcFileDB)))\n if (isDir) {\n // prepare child file props update\n const childFiles: SQL<string> = childFilesFindRegexp(srcProps.path)\n const childProps: Omit<FileDBProps, 'path'> & { path: SQL<string> } = {\n ...dstCommonProps,\n path: childFilesReplaceRegexp(srcProps.path, dstProps.path)\n }\n // update child file props\n await this.db\n .update(files)\n .set(childProps)\n .where(and(...convertToWhere(files, srcCommonProps), childFiles))\n }\n }\n\n async compareAndUpdateFileProps(dbFile: FileProps, fsFile: FileProps): Promise<void> {\n if (\n dbFile.isDir !== fsFile.isDir ||\n dbFile.size !== fsFile.size ||\n dbFile.ctime !== fsFile.ctime ||\n dbFile.mtime !== fsFile.mtime ||\n dbFile.mime !== fsFile.mime\n ) {\n this.logger.verbose(`${this.compareAndUpdateFileProps.name} - ${dbFile.path} (${dbFile.id})`)\n await this.updateFile(dbFile.id, {\n isDir: fsFile.isDir,\n size: fsFile.size,\n ctime: fsFile.ctime,\n mtime: fsFile.mtime,\n mime: fsFile.mime\n })\n }\n }\n\n getRecentsFromUser(userId: number, spaceIds: number[], shareIds: number[], limit = 10): Promise<FileRecent[]> {\n return this.db\n .select({\n id: filesRecents.id,\n ownerId: sql<number>`IF(${filesRecents.ownerId} IS NULL, 0, 1)`.as('ownerId'),\n spaceId: sql<number>`IF(${filesRecents.spaceId} IS NULL, 0, 1)`.as('spaceId'),\n shareId: sql<number>`IF(${filesRecents.shareId} IS NULL, 0, 1)`.as('shareId'),\n path: filesRecents.path,\n name: filesRecents.name,\n mime: filesRecents.mime,\n mtime: filesRecents.mtime\n } satisfies FileRecent | SelectedFields<any, any>)\n .from(filesRecents)\n .where(or(eq(filesRecents.ownerId, userId), inArray(filesRecents.spaceId, spaceIds), inArray(filesRecents.shareId, shareIds)))\n .groupBy(filesRecents.id)\n .orderBy(desc(filesRecents.mtime))\n .limit(limit)\n }\n\n getRecentsFromLocation(location: Partial<Record<keyof FileRecent, any>>): Promise<FileRecent[]> {\n const where: SQL[] = convertToWhere(filesRecents, location)\n return this.db\n .select(getTableColumns(filesRecents))\n .from(filesRecents)\n .where(and(...where))\n }\n\n async updateRecents(\n location: FileRecentLocation,\n add: Partial<FileRecent>[] | FileRecent[],\n update: Record<string | 'object', Partial<FileProps> | FileProps>[],\n remove: FileRecent['id'][]\n ): Promise<void> {\n const where: SQL[] = convertToWhere(filesRecents, location)\n // add\n if (add.length) {\n try {\n await this.db.insert(filesRecents).values(add as FileRecent[])\n } catch (e) {\n this.logger.error(`${this.updateRecents.name} - ${e}`)\n }\n }\n // update\n if (update.length) {\n for (const props of update) {\n const f: FileProps = popFromObject('object', props)\n try {\n await this.db\n .update(filesRecents)\n .set({ ...props })\n .where(and(...where, eq(filesRecents.id, f.id)))\n .limit(1)\n } catch (e) {\n this.logger.error(`${this.updateRecents.name} - ${e}`)\n }\n }\n }\n // remove\n if (remove.length) {\n try {\n await this.db.delete(filesRecents).where(and(...where, inArray(filesRecents.id, remove)))\n } catch (e) {\n this.logger.error(`${this.updateRecents.name} - ${e}`)\n }\n }\n }\n}\n"],"names":["FilesQueries","browseFiles","userId","dbFile","options","q","db","select","id","files","path","name","isDir","mime","size","mtime","ctime","withSpaces","spaces","concatDistinctObjectsInArray","alias","withShares","shares","type","withSyncs","syncs","syncPaths","clientId","syncClients","clientName","sql","info","withHasComments","hasComments","fileHasCommentsSubquerySQL","mapWith","Boolean","from","where","and","convertToWhere","groupBy","leftJoin","spacesRoots","eq","fileId","spaceId","ownerId","ignoreChildShares","isNull","parentId","getUserFile","fileInDB","filePathSQL","limit","getOrCreateUserFile","file","searchFileInDB","logger","warn","JSON","stringify","dbGetInsertedId","insert","values","undefined","getOrCreateSpaceFile","getSpaceFileId","updateFile","dbCheckAffectedRows","update","set","e","error","deleteFiles","props","force","commonProps","spaceExternalRootId","shareExternalId","inTrash","fileProps","dirName","fileName","childFiles","childFilesFindRegexp","delete","moveFiles","srcProps","dstProps","srcCommonProps","dstCommonProps","srcFileDB","dstFileDB","childProps","childFilesReplaceRegexp","compareAndUpdateFileProps","fsFile","verbose","getRecentsFromUser","spaceIds","shareIds","filesRecents","as","shareId","or","inArray","orderBy","desc","getRecentsFromLocation","location","getTableColumns","updateRecents","add","remove","length","f","popFromObject","Logger"],"mappings":"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"}
|
|
@@ -368,7 +368,7 @@ async function uniqueDatedFilePath(rPath) {
|
|
|
368
368
|
const extension = _nodepath.default.extname(rPath);
|
|
369
369
|
const nameWithoutExtension = _nodepath.default.basename(rPath, extension);
|
|
370
370
|
return {
|
|
371
|
-
isDir:
|
|
371
|
+
isDir: false,
|
|
372
372
|
path: _nodepath.default.join(_nodepath.default.dirname(rPath), `${nameWithoutExtension}-${date}${extension}`)
|
|
373
373
|
};
|
|
374
374
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/files/utils/files.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 { HttpStatus } from '@nestjs/common'\nimport { WriteStream } from 'fs'\nimport fse from 'fs-extra'\nimport mime from 'mime-types'\nimport crypto from 'node:crypto'\nimport { createReadStream, createWriteStream, Dirent, statSync } from 'node:fs'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { Readable } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport { formatDateISOString } from '../../../common/functions'\nimport { currentTimeStamp, isValidFileName, regExpPreventPathTraversal } from '../../../common/shared'\nimport { DEFAULT_HIGH_WATER_MARK, EXTRA_MIMES_TYPE } from '../constants/files'\nimport type { FileProps } from '../interfaces/file-props.interface'\nimport { FileError } from '../models/file-error'\n\nexport function sanitizePath(fPath: string): string {\n return path.normalize(fPath).replace(regExpPreventPathTraversal, '')\n}\n\nexport function sanitizeName(name: string): string {\n return name\n .replace(/^\\s+|[. ]+$/g, '') // trimStart + trimEnd + strip trailing dots\n .replace(/[/\\\\]/g, '') // remove slashes\n .replace(/\\.\\./g, '') // remove '..'\n}\n\nexport function checkFileName(fPath: string): string {\n const fName = fileName(fPath)\n try {\n isValidFileName(fName)\n return fName\n } catch {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Forbidden characters')\n }\n}\n\nexport function isPathExists(rPath: string): Promise<boolean> {\n return fse.pathExists(rPath)\n}\n\nexport async function isPathIsReadable(rPath: string): Promise<boolean> {\n try {\n await fs.access(rPath, fs.constants.R_OK)\n } catch {\n return false\n }\n return true\n}\n\nexport async function isPathIsWriteable(rPath: string): Promise<boolean> {\n try {\n await fs.access(rPath, fs.constants.W_OK)\n } catch {\n return false\n }\n return true\n}\n\nexport async function isPathIsDir(rPath: string): Promise<boolean> {\n return (await fs.stat(rPath)).isDirectory()\n}\n\nexport function fileName(fPath: string): string {\n return path.posix.basename(fPath)\n}\n\nexport function dirName(fPath: string): string {\n return path.dirname(fPath)\n}\n\nexport async function fileSize(rPath: string): Promise<number> {\n return (await fs.stat(rPath)).size\n}\n\nexport function createEmptyFile(rPath: string): Promise<void> {\n return fs.writeFile(rPath, '')\n}\n\nexport function makeDir(rPath: string, recursive?: boolean): Promise<string> {\n return fs.mkdir(rPath, { recursive: recursive })\n}\n\nexport function getMimeType(fPath: string, isDir: boolean): string {\n if (isDir) {\n return 'directory'\n }\n const extName: string = path.extname(fPath)\n if (EXTRA_MIMES_TYPE.has(extName)) {\n return EXTRA_MIMES_TYPE.get(extName)\n }\n const m = mime.lookup(extName)\n if (m) {\n return m.replace('/', '-')\n }\n return 'file'\n}\n\nexport function genEtag(file?: Pick<FileProps, 'size' | 'mtime'>, rPath?: string): string {\n if (!file) {\n if (!rPath) throw new Error('File or path are missing')\n const stats = statSync(rPath)\n file = { size: stats.size, mtime: stats.mtime.getTime() }\n }\n return `W/\"${file.size.toString(16)}-${file.mtime.toString(16)}\"`\n}\n\nexport function removeFiles(rPath: string): Promise<void> {\n // if the file does not exist, no error is thrown\n return fse.remove(rPath)\n}\n\nexport async function getProps(rPath: string, fPath?: string, isDir?: boolean): Promise<FileProps> {\n const stats = await fs.stat(rPath)\n const isDirectory = isDir === undefined ? stats.isDirectory() : isDir\n return {\n id: -stats.ino, // use negative number to avoid conflicts with existing database ids\n path: dirName(fPath !== undefined ? fPath : rPath),\n name: fileName(fPath !== undefined ? fPath : rPath),\n isDir: isDirectory,\n size: isDirectory ? 0 : stats.size,\n ctime: stats.birthtime.getTime(),\n mtime: stats.mtime.getTime(),\n mime: getMimeType(rPath, isDirectory)\n }\n}\n\nexport function touchFile(rPath: string, mtime?: number): Promise<void> {\n if (!mtime) mtime = currentTimeStamp()\n return fs.utimes(rPath, mtime, mtime)\n}\n\nexport async function copyFiles(srcPath: string, dstPath: string, overwrite = false, recursive = true, preserveTimestamps = true): Promise<void> {\n /*\n If src is a directory it will copy everything inside of this directory, not the entire directory itself\n If src is a file, dest cannot be a directory\n */\n if (!recursive && (await isPathIsDir(srcPath))) {\n await fs.mkdir(dstPath)\n if (preserveTimestamps) {\n const stat = await fs.stat(srcPath)\n await fs.utimes(dstPath, stat.atime, stat.mtime)\n }\n } else {\n await fse.copy(srcPath, dstPath, { overwrite, preserveTimestamps: preserveTimestamps })\n }\n}\n\nexport function moveFiles(srcPath: string, dstPath: string, overwrite = false): Promise<void> {\n /*\n If src is a file, dest must be a file and when src is a directory, dest must be a directory\n */\n return fse.move(srcPath, dstPath, { overwrite })\n}\n\nexport async function checksumFile(filePath: string, alg: string): Promise<string> {\n const hash = crypto.createHash(alg)\n const stream = createReadStream(filePath, { highWaterMark: DEFAULT_HIGH_WATER_MARK })\n await pipeline(stream, hash)\n return hash.digest('hex')\n}\n\nexport function writeFromStream(rPath: string, stream: Readable, start: number = 0): Promise<void> {\n const dst: WriteStream = createWriteStream(rPath, { flags: start ? 'a' : 'w', start: start, highWaterMark: DEFAULT_HIGH_WATER_MARK })\n return pipeline(stream, dst)\n}\n\nexport async function writeFromStreamAndChecksum(rPath: string, stream: Readable, hasRange: number, alg: string): Promise<string> {\n const hash = crypto.createHash(alg)\n if (hasRange) {\n const src = createReadStream(rPath, { highWaterMark: DEFAULT_HIGH_WATER_MARK })\n await pipeline(src, hash, { end: false })\n }\n const dst = createWriteStream(rPath, { flags: hasRange ? 'a' : 'w', highWaterMark: DEFAULT_HIGH_WATER_MARK })\n await pipeline(\n stream,\n async function* (source) {\n for await (const chunk of source) {\n hash.update(chunk)\n yield chunk\n }\n },\n dst\n )\n hash.end()\n return hash.digest('hex')\n}\n\nexport function copyFileContent(srcPath: string, dstPath: string): Promise<void> {\n const srcStream = createReadStream(srcPath, { highWaterMark: DEFAULT_HIGH_WATER_MARK })\n return writeFromStream(dstPath, srcStream)\n}\n\nexport async function dirSize(rPath: string): Promise<[number, any]> {\n let size = 0\n const errors: Record<string, string> = {}\n for (const f of await fs.readdir(rPath, { withFileTypes: true, recursive: true })) {\n if (f.isFile()) {\n const p = path.join(f.parentPath, f.name)\n try {\n size += (await fs.stat(p)).size\n } catch (e: any) {\n errors[p] = e.message\n }\n }\n }\n return [size, errors]\n}\n\nexport async function dirListFileNames(rPath: string): Promise<string[]> {\n return (await fs.readdir(rPath)).map((path: string) => fileName(path))\n}\n\nexport async function countDirEntries(rPath: string): Promise<{ files: number; directories: number }> {\n return (await fs.readdir(rPath, { withFileTypes: true, recursive: true })).reduce(\n (acc, f: Dirent) => {\n if (f.isDirectory()) {\n acc.directories++\n } else {\n acc.files++\n }\n return acc\n },\n { files: 0, directories: 0 }\n )\n}\n\nexport async function dirHasChildren(rPath: string, mustContainsDirs = true): Promise<boolean> {\n for await (const file of await fs.opendir(rPath)) {\n if (mustContainsDirs) {\n if (file.isDirectory()) return true\n } else {\n return true\n }\n }\n return false\n}\n\nexport async function uniqueFilePathFromDir(rPath: string): Promise<string> {\n if (await isPathExists(rPath)) {\n const parentDir = path.dirname(rPath)\n const extension = path.extname(rPath)\n const nameWithoutExtension = path.basename(rPath, extension)\n let count = 1\n while (await isPathExists(path.join(parentDir, `${nameWithoutExtension} (${count})${extension}`))) {\n count++\n }\n return path.join(parentDir, `${nameWithoutExtension} (${count})${extension}`)\n }\n return rPath\n}\n\nexport async function uniqueDatedFilePath(rPath: string): Promise<{ isDir: boolean; path: string }> {\n const date = formatDateISOString(new Date())\n if (await isPathIsDir(rPath)) {\n return { isDir: true, path: `${rPath}-${date}` }\n } else {\n const extension = path.extname(rPath)\n const nameWithoutExtension = path.basename(rPath, extension)\n return { isDir: true, path: path.join(path.dirname(rPath), `${nameWithoutExtension}-${date}${extension}`) }\n }\n}\n\nexport async function checkExternalPath(rPath: string) {\n if (!(await isPathExists(rPath))) {\n throw new FileError(HttpStatus.NOT_FOUND, 'The location does not exist')\n }\n if (!(await isPathIsReadable(rPath))) {\n throw new FileError(HttpStatus.NOT_ACCEPTABLE, 'The location is not readable')\n }\n if (!(await isPathIsWriteable(rPath))) {\n throw new FileError(HttpStatus.NOT_ACCEPTABLE, 'The location is not writeable')\n }\n}\n"],"names":["checkExternalPath","checkFileName","checksumFile","copyFileContent","copyFiles","countDirEntries","createEmptyFile","dirHasChildren","dirListFileNames","dirName","dirSize","fileName","fileSize","genEtag","getMimeType","getProps","isPathExists","isPathIsDir","isPathIsReadable","isPathIsWriteable","makeDir","moveFiles","removeFiles","sanitizeName","sanitizePath","touchFile","uniqueDatedFilePath","uniqueFilePathFromDir","writeFromStream","writeFromStreamAndChecksum","fPath","path","normalize","replace","regExpPreventPathTraversal","name","fName","isValidFileName","FileError","HttpStatus","BAD_REQUEST","rPath","fse","pathExists","fs","access","constants","R_OK","W_OK","stat","isDirectory","posix","basename","dirname","size","writeFile","recursive","mkdir","isDir","extName","extname","EXTRA_MIMES_TYPE","has","get","m","mime","lookup","file","Error","stats","statSync","mtime","getTime","toString","remove","undefined","id","ino","ctime","birthtime","currentTimeStamp","utimes","srcPath","dstPath","overwrite","preserveTimestamps","atime","copy","move","filePath","alg","hash","crypto","createHash","stream","createReadStream","highWaterMark","DEFAULT_HIGH_WATER_MARK","pipeline","digest","start","dst","createWriteStream","flags","hasRange","src","end","source","chunk","update","srcStream","errors","f","readdir","withFileTypes","isFile","p","join","parentPath","e","message","map","reduce","acc","directories","files","mustContainsDirs","opendir","parentDir","extension","nameWithoutExtension","count","date","formatDateISOString","Date","NOT_FOUND","NOT_ACCEPTABLE"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/files/utils/files.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 { HttpStatus } from '@nestjs/common'\nimport { WriteStream } from 'fs'\nimport fse from 'fs-extra'\nimport mime from 'mime-types'\nimport crypto from 'node:crypto'\nimport { createReadStream, createWriteStream, Dirent, statSync } from 'node:fs'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { Readable } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport { formatDateISOString } from '../../../common/functions'\nimport { currentTimeStamp, isValidFileName, regExpPreventPathTraversal } from '../../../common/shared'\nimport { DEFAULT_HIGH_WATER_MARK, EXTRA_MIMES_TYPE } from '../constants/files'\nimport type { FileProps } from '../interfaces/file-props.interface'\nimport { FileError } from '../models/file-error'\n\nexport function sanitizePath(fPath: string): string {\n return path.normalize(fPath).replace(regExpPreventPathTraversal, '')\n}\n\nexport function sanitizeName(name: string): string {\n return name\n .replace(/^\\s+|[. ]+$/g, '') // trimStart + trimEnd + strip trailing dots\n .replace(/[/\\\\]/g, '') // remove slashes\n .replace(/\\.\\./g, '') // remove '..'\n}\n\nexport function checkFileName(fPath: string): string {\n const fName = fileName(fPath)\n try {\n isValidFileName(fName)\n return fName\n } catch {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Forbidden characters')\n }\n}\n\nexport function isPathExists(rPath: string): Promise<boolean> {\n return fse.pathExists(rPath)\n}\n\nexport async function isPathIsReadable(rPath: string): Promise<boolean> {\n try {\n await fs.access(rPath, fs.constants.R_OK)\n } catch {\n return false\n }\n return true\n}\n\nexport async function isPathIsWriteable(rPath: string): Promise<boolean> {\n try {\n await fs.access(rPath, fs.constants.W_OK)\n } catch {\n return false\n }\n return true\n}\n\nexport async function isPathIsDir(rPath: string): Promise<boolean> {\n return (await fs.stat(rPath)).isDirectory()\n}\n\nexport function fileName(fPath: string): string {\n return path.posix.basename(fPath)\n}\n\nexport function dirName(fPath: string): string {\n return path.dirname(fPath)\n}\n\nexport async function fileSize(rPath: string): Promise<number> {\n return (await fs.stat(rPath)).size\n}\n\nexport function createEmptyFile(rPath: string): Promise<void> {\n return fs.writeFile(rPath, '')\n}\n\nexport function makeDir(rPath: string, recursive?: boolean): Promise<string> {\n return fs.mkdir(rPath, { recursive: recursive })\n}\n\nexport function getMimeType(fPath: string, isDir: boolean): string {\n if (isDir) {\n return 'directory'\n }\n const extName: string = path.extname(fPath)\n if (EXTRA_MIMES_TYPE.has(extName)) {\n return EXTRA_MIMES_TYPE.get(extName)\n }\n const m = mime.lookup(extName)\n if (m) {\n return m.replace('/', '-')\n }\n return 'file'\n}\n\nexport function genEtag(file?: Pick<FileProps, 'size' | 'mtime'>, rPath?: string): string {\n if (!file) {\n if (!rPath) throw new Error('File or path are missing')\n const stats = statSync(rPath)\n file = { size: stats.size, mtime: stats.mtime.getTime() }\n }\n return `W/\"${file.size.toString(16)}-${file.mtime.toString(16)}\"`\n}\n\nexport function removeFiles(rPath: string): Promise<void> {\n // if the file does not exist, no error is thrown\n return fse.remove(rPath)\n}\n\nexport async function getProps(rPath: string, fPath?: string, isDir?: boolean): Promise<FileProps> {\n const stats = await fs.stat(rPath)\n const isDirectory = isDir === undefined ? stats.isDirectory() : isDir\n return {\n id: -stats.ino, // use negative number to avoid conflicts with existing database ids\n path: dirName(fPath !== undefined ? fPath : rPath),\n name: fileName(fPath !== undefined ? fPath : rPath),\n isDir: isDirectory,\n size: isDirectory ? 0 : stats.size,\n ctime: stats.birthtime.getTime(),\n mtime: stats.mtime.getTime(),\n mime: getMimeType(rPath, isDirectory)\n }\n}\n\nexport function touchFile(rPath: string, mtime?: number): Promise<void> {\n if (!mtime) mtime = currentTimeStamp()\n return fs.utimes(rPath, mtime, mtime)\n}\n\nexport async function copyFiles(srcPath: string, dstPath: string, overwrite = false, recursive = true, preserveTimestamps = true): Promise<void> {\n /*\n If src is a directory it will copy everything inside of this directory, not the entire directory itself\n If src is a file, dest cannot be a directory\n */\n if (!recursive && (await isPathIsDir(srcPath))) {\n await fs.mkdir(dstPath)\n if (preserveTimestamps) {\n const stat = await fs.stat(srcPath)\n await fs.utimes(dstPath, stat.atime, stat.mtime)\n }\n } else {\n await fse.copy(srcPath, dstPath, { overwrite, preserveTimestamps: preserveTimestamps })\n }\n}\n\nexport function moveFiles(srcPath: string, dstPath: string, overwrite = false): Promise<void> {\n /*\n If src is a file, dest must be a file and when src is a directory, dest must be a directory\n */\n return fse.move(srcPath, dstPath, { overwrite })\n}\n\nexport async function checksumFile(filePath: string, alg: string): Promise<string> {\n const hash = crypto.createHash(alg)\n const stream = createReadStream(filePath, { highWaterMark: DEFAULT_HIGH_WATER_MARK })\n await pipeline(stream, hash)\n return hash.digest('hex')\n}\n\nexport function writeFromStream(rPath: string, stream: Readable, start: number = 0): Promise<void> {\n const dst: WriteStream = createWriteStream(rPath, { flags: start ? 'a' : 'w', start: start, highWaterMark: DEFAULT_HIGH_WATER_MARK })\n return pipeline(stream, dst)\n}\n\nexport async function writeFromStreamAndChecksum(rPath: string, stream: Readable, hasRange: number, alg: string): Promise<string> {\n const hash = crypto.createHash(alg)\n if (hasRange) {\n const src = createReadStream(rPath, { highWaterMark: DEFAULT_HIGH_WATER_MARK })\n await pipeline(src, hash, { end: false })\n }\n const dst = createWriteStream(rPath, { flags: hasRange ? 'a' : 'w', highWaterMark: DEFAULT_HIGH_WATER_MARK })\n await pipeline(\n stream,\n async function* (source) {\n for await (const chunk of source) {\n hash.update(chunk)\n yield chunk\n }\n },\n dst\n )\n hash.end()\n return hash.digest('hex')\n}\n\nexport function copyFileContent(srcPath: string, dstPath: string): Promise<void> {\n const srcStream = createReadStream(srcPath, { highWaterMark: DEFAULT_HIGH_WATER_MARK })\n return writeFromStream(dstPath, srcStream)\n}\n\nexport async function dirSize(rPath: string): Promise<[number, any]> {\n let size = 0\n const errors: Record<string, string> = {}\n for (const f of await fs.readdir(rPath, { withFileTypes: true, recursive: true })) {\n if (f.isFile()) {\n const p = path.join(f.parentPath, f.name)\n try {\n size += (await fs.stat(p)).size\n } catch (e: any) {\n errors[p] = e.message\n }\n }\n }\n return [size, errors]\n}\n\nexport async function dirListFileNames(rPath: string): Promise<string[]> {\n return (await fs.readdir(rPath)).map((path: string) => fileName(path))\n}\n\nexport async function countDirEntries(rPath: string): Promise<{ files: number; directories: number }> {\n return (await fs.readdir(rPath, { withFileTypes: true, recursive: true })).reduce(\n (acc, f: Dirent) => {\n if (f.isDirectory()) {\n acc.directories++\n } else {\n acc.files++\n }\n return acc\n },\n { files: 0, directories: 0 }\n )\n}\n\nexport async function dirHasChildren(rPath: string, mustContainsDirs = true): Promise<boolean> {\n for await (const file of await fs.opendir(rPath)) {\n if (mustContainsDirs) {\n if (file.isDirectory()) return true\n } else {\n return true\n }\n }\n return false\n}\n\nexport async function uniqueFilePathFromDir(rPath: string): Promise<string> {\n if (await isPathExists(rPath)) {\n const parentDir = path.dirname(rPath)\n const extension = path.extname(rPath)\n const nameWithoutExtension = path.basename(rPath, extension)\n let count = 1\n while (await isPathExists(path.join(parentDir, `${nameWithoutExtension} (${count})${extension}`))) {\n count++\n }\n return path.join(parentDir, `${nameWithoutExtension} (${count})${extension}`)\n }\n return rPath\n}\n\nexport async function uniqueDatedFilePath(rPath: string): Promise<{ isDir: boolean; path: string }> {\n const date = formatDateISOString(new Date())\n if (await isPathIsDir(rPath)) {\n return { isDir: true, path: `${rPath}-${date}` }\n } else {\n const extension = path.extname(rPath)\n const nameWithoutExtension = path.basename(rPath, extension)\n return { isDir: false, path: path.join(path.dirname(rPath), `${nameWithoutExtension}-${date}${extension}`) }\n }\n}\n\nexport async function checkExternalPath(rPath: string) {\n if (!(await isPathExists(rPath))) {\n throw new FileError(HttpStatus.NOT_FOUND, 'The location does not exist')\n }\n if (!(await isPathIsReadable(rPath))) {\n throw new FileError(HttpStatus.NOT_ACCEPTABLE, 'The location is not readable')\n }\n if (!(await isPathIsWriteable(rPath))) {\n throw new FileError(HttpStatus.NOT_ACCEPTABLE, 'The location is not writeable')\n }\n}\n"],"names":["checkExternalPath","checkFileName","checksumFile","copyFileContent","copyFiles","countDirEntries","createEmptyFile","dirHasChildren","dirListFileNames","dirName","dirSize","fileName","fileSize","genEtag","getMimeType","getProps","isPathExists","isPathIsDir","isPathIsReadable","isPathIsWriteable","makeDir","moveFiles","removeFiles","sanitizeName","sanitizePath","touchFile","uniqueDatedFilePath","uniqueFilePathFromDir","writeFromStream","writeFromStreamAndChecksum","fPath","path","normalize","replace","regExpPreventPathTraversal","name","fName","isValidFileName","FileError","HttpStatus","BAD_REQUEST","rPath","fse","pathExists","fs","access","constants","R_OK","W_OK","stat","isDirectory","posix","basename","dirname","size","writeFile","recursive","mkdir","isDir","extName","extname","EXTRA_MIMES_TYPE","has","get","m","mime","lookup","file","Error","stats","statSync","mtime","getTime","toString","remove","undefined","id","ino","ctime","birthtime","currentTimeStamp","utimes","srcPath","dstPath","overwrite","preserveTimestamps","atime","copy","move","filePath","alg","hash","crypto","createHash","stream","createReadStream","highWaterMark","DEFAULT_HIGH_WATER_MARK","pipeline","digest","start","dst","createWriteStream","flags","hasRange","src","end","source","chunk","update","srcStream","errors","f","readdir","withFileTypes","isFile","p","join","parentPath","e","message","map","reduce","acc","directories","files","mustContainsDirs","opendir","parentDir","extension","nameWithoutExtension","count","date","formatDateISOString","Date","NOT_FOUND","NOT_ACCEPTABLE"],"mappings":"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"}
|
|
@@ -32,7 +32,7 @@ let SendFile = class SendFile {
|
|
|
32
32
|
async stream(req, res) {
|
|
33
33
|
// SendStream manages HEAD (no including body in response) & GET request (with body)
|
|
34
34
|
// Ranges, LastModified, Etag are also handled
|
|
35
|
-
// Send function uses decodeURIComponent, but filePath is already decoded
|
|
35
|
+
// Send function uses decodeURIComponent, but filePath is already decoded: we need to encode it again before passing it.
|
|
36
36
|
const encodedFilePath = encodeURIComponent(this.filePath);
|
|
37
37
|
this.fileName = encodeURIComponent(this.downloadName ? this.downloadName : (0, _files1.fileName)(this.filePath));
|
|
38
38
|
const sendResult = await (0, _send.send)(req.raw, encodedFilePath, this.sendOptions);
|
|
@@ -56,7 +56,8 @@ let SendFile = class SendFile {
|
|
|
56
56
|
etag: true,
|
|
57
57
|
dotfiles: 'allow',
|
|
58
58
|
lastModified: true,
|
|
59
|
-
cacheControl:
|
|
59
|
+
cacheControl: true,
|
|
60
|
+
maxAge: 0,
|
|
60
61
|
index: false,
|
|
61
62
|
highWaterMark: _files.DEFAULT_HIGH_WATER_MARK
|
|
62
63
|
}){
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/files/utils/send-file.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 { send, SendOptions, SendResult } from '@fastify/send'\nimport { HttpStatus, StreamableFile } from '@nestjs/common'\nimport { FastifyReply, FastifyRequest } from 'fastify'\nimport { DEFAULT_HIGH_WATER_MARK } from '../constants/files'\nimport { FileError } from '../models/file-error'\nimport { fileName, isPathExists, isPathIsDir, isPathIsReadable } from './files'\n\nexport class SendFile {\n private fileName: string\n\n constructor(\n private readonly filePath: string,\n private readonly asAttachment = true,\n private readonly downloadName = '',\n private readonly sendOptions: SendOptions = {\n acceptRanges: true,\n etag: true,\n dotfiles: 'allow',\n lastModified: true,\n cacheControl:
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/files/utils/send-file.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 { send, SendOptions, SendResult } from '@fastify/send'\nimport { HttpStatus, StreamableFile } from '@nestjs/common'\nimport { FastifyReply, FastifyRequest } from 'fastify'\nimport { DEFAULT_HIGH_WATER_MARK } from '../constants/files'\nimport { FileError } from '../models/file-error'\nimport { fileName, isPathExists, isPathIsDir, isPathIsReadable } from './files'\n\nexport class SendFile {\n private fileName: string\n\n constructor(\n private readonly filePath: string,\n private readonly asAttachment = true,\n private readonly downloadName = '',\n private readonly sendOptions: SendOptions = {\n acceptRanges: true,\n etag: true,\n dotfiles: 'allow',\n lastModified: true,\n cacheControl: true,\n maxAge: 0,\n index: false,\n highWaterMark: DEFAULT_HIGH_WATER_MARK\n }\n ) {}\n\n async checks() {\n if (!(await isPathExists(this.filePath))) {\n throw new FileError(HttpStatus.NOT_FOUND, 'Location not found')\n }\n if (await isPathIsDir(this.filePath)) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'The location is a directory')\n }\n if (!(await isPathIsReadable(this.filePath))) {\n throw new FileError(HttpStatus.METHOD_NOT_ALLOWED, 'The location is not readable')\n }\n }\n\n async stream(req: FastifyRequest, res: FastifyReply): Promise<StreamableFile> {\n // SendStream manages HEAD (no including body in response) & GET request (with body)\n // Ranges, LastModified, Etag are also handled\n // Send function uses decodeURIComponent, but filePath is already decoded: we need to encode it again before passing it.\n const encodedFilePath = encodeURIComponent(this.filePath)\n this.fileName = encodeURIComponent(this.downloadName ? this.downloadName : fileName(this.filePath))\n const sendResult: SendResult = await send(req.raw, encodedFilePath, this.sendOptions)\n // Check if the path was correctly validated\n if (sendResult.metadata['path'] === undefined) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Location not found')\n }\n if (this.asAttachment) {\n const downloadName = this.fileName.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '')\n sendResult.headers['content-disposition'] = `attachment; filename=\"${downloadName}\";filename*=UTF-8''${this.fileName}`\n }\n res.headers(sendResult.headers)\n res.status(sendResult.statusCode)\n // sendStream.once('stream', () => console.log(`Sending: ${this.fileName}`))\n // sendStream.once('end', () => console.log(`Received: ${this.fileName}`))\n // sendStream.once('error', (e: Error) => console.error(`Transfer error : ${this.fileName} - ${e}`))\n return new StreamableFile(sendResult.stream)\n }\n}\n"],"names":["SendFile","checks","isPathExists","filePath","FileError","HttpStatus","NOT_FOUND","isPathIsDir","BAD_REQUEST","isPathIsReadable","METHOD_NOT_ALLOWED","stream","req","res","encodedFilePath","encodeURIComponent","fileName","downloadName","sendResult","send","raw","sendOptions","metadata","undefined","asAttachment","normalize","replace","headers","status","statusCode","StreamableFile","acceptRanges","etag","dotfiles","lastModified","cacheControl","maxAge","index","highWaterMark","DEFAULT_HIGH_WATER_MARK"],"mappings":"AAAA;;;;CAIC;;;;+BASYA;;;eAAAA;;;sBAPiC;wBACH;uBAEH;2BACd;wBAC4C;AAE/D,IAAA,AAAMA,WAAN,MAAMA;IAmBX,MAAMC,SAAS;QACb,IAAI,CAAE,MAAMC,IAAAA,oBAAY,EAAC,IAAI,CAACC,QAAQ,GAAI;YACxC,MAAM,IAAIC,oBAAS,CAACC,kBAAU,CAACC,SAAS,EAAE;QAC5C;QACA,IAAI,MAAMC,IAAAA,mBAAW,EAAC,IAAI,CAACJ,QAAQ,GAAG;YACpC,MAAM,IAAIC,oBAAS,CAACC,kBAAU,CAACG,WAAW,EAAE;QAC9C;QACA,IAAI,CAAE,MAAMC,IAAAA,wBAAgB,EAAC,IAAI,CAACN,QAAQ,GAAI;YAC5C,MAAM,IAAIC,oBAAS,CAACC,kBAAU,CAACK,kBAAkB,EAAE;QACrD;IACF;IAEA,MAAMC,OAAOC,GAAmB,EAAEC,GAAiB,EAA2B;QAC5E,oFAAoF;QACpF,8CAA8C;QAC9C,wHAAwH;QACxH,MAAMC,kBAAkBC,mBAAmB,IAAI,CAACZ,QAAQ;QACxD,IAAI,CAACa,QAAQ,GAAGD,mBAAmB,IAAI,CAACE,YAAY,GAAG,IAAI,CAACA,YAAY,GAAGD,IAAAA,gBAAQ,EAAC,IAAI,CAACb,QAAQ;QACjG,MAAMe,aAAyB,MAAMC,IAAAA,UAAI,EAACP,IAAIQ,GAAG,EAAEN,iBAAiB,IAAI,CAACO,WAAW;QACpF,4CAA4C;QAC5C,IAAIH,WAAWI,QAAQ,CAAC,OAAO,KAAKC,WAAW;YAC7C,MAAM,IAAInB,oBAAS,CAACC,kBAAU,CAACG,WAAW,EAAE;QAC9C;QACA,IAAI,IAAI,CAACgB,YAAY,EAAE;YACrB,MAAMP,eAAe,IAAI,CAACD,QAAQ,CAACS,SAAS,CAAC,OAAOC,OAAO,CAAC,oBAAoB;YAChFR,WAAWS,OAAO,CAAC,sBAAsB,GAAG,CAAC,sBAAsB,EAAEV,aAAa,mBAAmB,EAAE,IAAI,CAACD,QAAQ,EAAE;QACxH;QACAH,IAAIc,OAAO,CAACT,WAAWS,OAAO;QAC9Bd,IAAIe,MAAM,CAACV,WAAWW,UAAU;QAChC,4EAA4E;QAC5E,0EAA0E;QAC1E,oGAAoG;QACpG,OAAO,IAAIC,sBAAc,CAACZ,WAAWP,MAAM;IAC7C;IAjDA,YACE,AAAiBR,QAAgB,EACjC,AAAiBqB,eAAe,IAAI,EACpC,AAAiBP,eAAe,EAAE,EAClC,AAAiBI,cAA2B;QAC1CU,cAAc;QACdC,MAAM;QACNC,UAAU;QACVC,cAAc;QACdC,cAAc;QACdC,QAAQ;QACRC,OAAO;QACPC,eAAeC,8BAAuB;IACxC,CAAC,CACD;aAbiBpC,WAAAA;aACAqB,eAAAA;aACAP,eAAAA;aACAI,cAAAA;IAUhB;AAoCL"}
|
|
@@ -123,7 +123,7 @@ let LinksQueries = class LinksQueries {
|
|
|
123
123
|
name: _sharesschema.shares.name,
|
|
124
124
|
alias: _sharesschema.shares.alias,
|
|
125
125
|
hasParent: (0, _drizzleorm.isNotNull)(_sharesschema.shares.parentId).mapWith(Boolean),
|
|
126
|
-
isDir: (0, _drizzleorm.sql)`IF (${(0, _drizzleorm.isNotNull)(_sharesschema.shares.externalPath)}, 1 ,${_filesschema.files.isDir})`.mapWith(Boolean),
|
|
126
|
+
isDir: (0, _drizzleorm.sql)`IF (${(0, _drizzleorm.isNotNull)(_sharesschema.shares.externalPath)} OR ${(0, _drizzleorm.isNotNull)(shareSpaceRoot.externalPath)}, 1 ,${_filesschema.files.isDir})`.mapWith(Boolean),
|
|
127
127
|
mime: _filesschema.files.mime
|
|
128
128
|
},
|
|
129
129
|
space: {
|