@sync-in/server 1.5.2 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +2 -1
- package/environment/environment.dist.min.yaml +1 -0
- package/environment/environment.dist.yaml +88 -30
- package/migrations/0002_sleepy_korath.sql +1 -0
- package/migrations/meta/0002_snapshot.json +2424 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +14 -12
- package/server/app.bootstrap.js +1 -1
- package/server/app.bootstrap.js.map +1 -1
- package/server/applications/files/services/files-manager.service.js +1 -2
- package/server/applications/files/services/files-manager.service.js.map +1 -1
- package/server/applications/files/services/files-only-office-manager.service.js +5 -6
- package/server/applications/files/services/files-only-office-manager.service.js.map +1 -1
- package/server/applications/files/utils/files.js +6 -4
- package/server/applications/files/utils/files.js.map +1 -1
- package/server/applications/links/links.controller.js +2 -2
- package/server/applications/links/links.controller.js.map +1 -1
- package/server/applications/links/services/links-manager.service.js +2 -1
- package/server/applications/links/services/links-manager.service.js.map +1 -1
- package/server/applications/links/services/links-manager.service.spec.js +6 -3
- package/server/applications/links/services/links-manager.service.spec.js.map +1 -1
- package/server/applications/notifications/constants/notifications.js +9 -0
- package/server/applications/notifications/constants/notifications.js.map +1 -1
- package/server/applications/notifications/i18n/fr.js +10 -1
- package/server/applications/notifications/i18n/fr.js.map +1 -1
- package/server/applications/notifications/interfaces/notification-properties.interface.js.map +1 -1
- package/server/applications/notifications/mails/models.js +41 -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/schemas/notifications.schema.js +2 -1
- package/server/applications/notifications/schemas/notifications.schema.js.map +1 -1
- package/server/applications/notifications/services/notifications-manager.service.js +16 -13
- package/server/applications/notifications/services/notifications-manager.service.js.map +1 -1
- package/server/applications/notifications/services/notifications-manager.service.spec.js +9 -8
- package/server/applications/notifications/services/notifications-manager.service.spec.js.map +1 -1
- package/server/applications/notifications/services/notifications-queries.service.js +1 -1
- package/server/applications/notifications/services/notifications-queries.service.js.map +1 -1
- package/server/applications/shares/services/shares-manager.service.js +3 -2
- package/server/applications/shares/services/shares-manager.service.js.map +1 -1
- package/server/applications/sync/constants/auth.js +2 -2
- package/server/applications/sync/constants/auth.js.map +1 -1
- package/server/applications/sync/dtos/sync-client-registration.dto.js +5 -0
- package/server/applications/sync/dtos/sync-client-registration.dto.js.map +1 -1
- package/server/applications/sync/dtos/sync-operations.dto.js +1 -2
- package/server/applications/sync/dtos/sync-operations.dto.js.map +1 -1
- package/server/applications/sync/schemas/sync-clients.schema.js +2 -1
- package/server/applications/sync/schemas/sync-clients.schema.js.map +1 -1
- package/server/applications/sync/schemas/sync-paths.schema.js +2 -1
- package/server/applications/sync/schemas/sync-paths.schema.js.map +1 -1
- package/server/applications/sync/services/sync-clients-manager.service.js +28 -20
- package/server/applications/sync/services/sync-clients-manager.service.js.map +1 -1
- package/server/applications/sync/services/sync-clients-manager.service.spec.js +24 -18
- package/server/applications/sync/services/sync-clients-manager.service.spec.js.map +1 -1
- package/server/applications/sync/services/sync-queries.service.js +5 -5
- package/server/applications/sync/services/sync-queries.service.js.map +1 -1
- package/server/applications/users/admin-users.controller.js +48 -37
- package/server/applications/users/admin-users.controller.js.map +1 -1
- package/server/applications/users/admin-users.controller.spec.js +15 -0
- package/server/applications/users/admin-users.controller.spec.js.map +1 -1
- package/server/applications/users/constants/routes.js +5 -0
- package/server/applications/users/constants/routes.js.map +1 -1
- package/server/applications/users/constants/user.js +8 -0
- package/server/applications/users/constants/user.js.map +1 -1
- package/server/applications/users/dto/delete-user.dto.js +5 -23
- package/server/applications/users/dto/delete-user.dto.js.map +1 -1
- package/server/applications/users/dto/user-properties.dto.js +38 -3
- package/server/applications/users/dto/user-properties.dto.js.map +1 -1
- package/server/applications/users/interfaces/admin-user.interface.js.map +1 -1
- package/server/applications/users/interfaces/user-secrets.interface.js +10 -0
- package/server/applications/users/interfaces/user-secrets.interface.js.map +1 -0
- package/server/applications/users/models/user.model.js +84 -50
- package/server/applications/users/models/user.model.js.map +1 -1
- package/server/applications/users/schemas/user.interface.js.map +1 -1
- package/server/applications/users/schemas/users.schema.js +2 -0
- package/server/applications/users/schemas/users.schema.js.map +1 -1
- package/server/applications/users/services/admin-users-manager.service.js +7 -19
- package/server/applications/users/services/admin-users-manager.service.js.map +1 -1
- package/server/applications/users/services/admin-users-manager.service.spec.js +7 -26
- package/server/applications/users/services/admin-users-manager.service.spec.js.map +1 -1
- package/server/applications/users/services/admin-users-queries.service.js +1 -0
- package/server/applications/users/services/admin-users-queries.service.js.map +1 -1
- package/server/applications/users/services/users-manager.service.js +138 -28
- package/server/applications/users/services/users-manager.service.js.map +1 -1
- package/server/applications/users/services/users-manager.service.spec.js +11 -9
- package/server/applications/users/services/users-manager.service.spec.js.map +1 -1
- package/server/applications/users/services/users-queries.service.js +63 -57
- package/server/applications/users/services/users-queries.service.js.map +1 -1
- package/server/applications/users/users.controller.js +48 -1
- package/server/applications/users/users.controller.js.map +1 -1
- package/server/applications/users/users.controller.spec.js +8 -1
- package/server/applications/users/users.controller.spec.js.map +1 -1
- package/server/applications/users/users.e2e-spec.js +2 -1
- package/server/applications/users/users.e2e-spec.js.map +1 -1
- package/server/applications/users/utils/avatar.js +48 -0
- package/server/applications/users/utils/avatar.js.map +1 -0
- package/server/authentication/auth.config.js +89 -26
- package/server/authentication/auth.config.js.map +1 -1
- package/server/authentication/auth.controller.js +117 -9
- package/server/authentication/auth.controller.js.map +1 -1
- package/server/authentication/auth.controller.spec.js +16 -1
- package/server/authentication/auth.controller.spec.js.map +1 -1
- package/server/authentication/auth.e2e-spec.js +4 -3
- package/server/authentication/auth.e2e-spec.js.map +1 -1
- package/server/authentication/auth.module.js +4 -1
- package/server/authentication/auth.module.js.map +1 -1
- package/server/authentication/constants/auth-ldap.js +44 -0
- package/server/authentication/constants/auth-ldap.js.map +1 -0
- package/server/authentication/constants/auth.js +37 -4
- package/server/authentication/constants/auth.js.map +1 -1
- package/server/authentication/constants/routes.js +21 -0
- package/server/authentication/constants/routes.js.map +1 -1
- package/server/authentication/constants/scope.js +20 -0
- package/server/authentication/constants/scope.js.map +1 -0
- package/server/authentication/dto/login-response.dto.js +27 -4
- package/server/authentication/dto/login-response.dto.js.map +1 -1
- package/server/authentication/dto/token-response.dto.js +5 -0
- package/server/authentication/dto/token-response.dto.js.map +1 -1
- package/server/{applications/users/dto/user-password.dto.js → authentication/dto/two-fa-verify.dto.js} +27 -9
- package/server/authentication/dto/two-fa-verify.dto.js.map +1 -0
- package/server/authentication/guards/auth-basic.strategy.js +6 -5
- package/server/authentication/guards/auth-basic.strategy.js.map +1 -1
- package/server/authentication/guards/auth-token-access.strategy.js +3 -2
- package/server/authentication/guards/auth-token-access.strategy.js.map +1 -1
- package/server/authentication/guards/auth-token-refresh.strategy.js +3 -2
- package/server/authentication/guards/auth-token-refresh.strategy.js.map +1 -1
- package/server/authentication/guards/auth-two-fa-guard.js +81 -0
- package/server/authentication/guards/auth-two-fa-guard.js.map +1 -0
- package/server/authentication/interfaces/jwt-payload.interface.js +5 -0
- package/server/authentication/interfaces/jwt-payload.interface.js.map +1 -1
- package/server/authentication/interfaces/token.interface.js +2 -0
- package/server/authentication/interfaces/token.interface.js.map +1 -1
- package/server/authentication/interfaces/two-fa-setup.interface.js +10 -0
- package/server/authentication/interfaces/two-fa-setup.interface.js.map +1 -0
- package/server/authentication/models/auth-method.js.map +1 -1
- package/server/authentication/services/auth-manager.service.js +72 -49
- package/server/authentication/services/auth-manager.service.js.map +1 -1
- package/server/authentication/services/auth-methods/auth-method-database.service.js +3 -3
- package/server/authentication/services/auth-methods/auth-method-database.service.js.map +1 -1
- package/server/authentication/services/auth-methods/auth-method-database.service.spec.js +5 -0
- package/server/authentication/services/auth-methods/auth-method-database.service.spec.js.map +1 -1
- package/server/authentication/services/auth-methods/auth-method-ldap.service.js +151 -66
- package/server/authentication/services/auth-methods/auth-method-ldap.service.js.map +1 -1
- package/server/authentication/services/auth-methods/auth-method-ldap.service.spec.js +52 -50
- package/server/authentication/services/auth-methods/auth-method-ldap.service.spec.js.map +1 -1
- package/server/authentication/services/auth-methods/auth-method-two-fa.service.js +251 -0
- package/server/authentication/services/auth-methods/auth-method-two-fa.service.js.map +1 -0
- package/server/authentication/services/auth-methods/auth-method-two-fa.service.spec.js +41 -0
- package/server/authentication/services/auth-methods/auth-method-two-fa.service.spec.js.map +1 -0
- package/server/authentication/utils/crypt-secret.js +68 -0
- package/server/authentication/utils/crypt-secret.js.map +1 -0
- package/server/common/functions.js +18 -2
- package/server/common/functions.js.map +1 -1
- package/server/common/qrcode.js +34 -0
- package/server/common/qrcode.js.map +1 -0
- package/server/common/shared.js +18 -0
- package/server/common/shared.js.map +1 -1
- package/server/configuration/config.environment.js +23 -6
- package/server/configuration/config.environment.js.map +1 -1
- package/server/configuration/config.interfaces.js +10 -0
- package/server/configuration/config.interfaces.js.map +1 -0
- package/server/configuration/config.loader.js.map +1 -1
- package/server/configuration/config.validation.js +13 -13
- package/server/configuration/config.validation.js.map +1 -1
- package/server/infrastructure/cache/adapters/mysql-cache.adapter.js +6 -6
- package/server/infrastructure/cache/adapters/mysql-cache.adapter.js.map +1 -1
- package/server/infrastructure/cache/schemas/mysql-cache.schema.js +2 -1
- package/server/infrastructure/cache/schemas/mysql-cache.schema.js.map +1 -1
- package/server/infrastructure/cache/services/cache.service.js.map +1 -1
- package/server/infrastructure/database/columns.js +39 -0
- package/server/infrastructure/database/columns.js.map +1 -0
- package/server/infrastructure/database/database.config.js +0 -1
- package/server/infrastructure/database/database.config.js.map +1 -1
- package/server/infrastructure/mailer/interfaces/mail.interface.js.map +1 -1
- package/server/infrastructure/mailer/mailer.config.js +12 -0
- package/server/infrastructure/mailer/mailer.config.js.map +1 -1
- package/server/infrastructure/mailer/mailer.service.js +2 -1
- package/server/infrastructure/mailer/mailer.service.js.map +1 -1
- package/static/assets/mimes/text-x-c.svg +1 -0
- package/static/assets/pdfjs/build/pdf.mjs +2522 -914
- package/static/assets/pdfjs/build/pdf.mjs.map +1 -1
- package/static/assets/pdfjs/build/pdf.sandbox.mjs +2 -2
- package/static/assets/pdfjs/build/pdf.worker.mjs +1024 -566
- package/static/assets/pdfjs/build/pdf.worker.mjs.map +1 -1
- package/static/assets/pdfjs/version +1 -1
- package/static/assets/pdfjs/web/debugger.mjs +116 -37
- package/static/assets/pdfjs/web/images/comment-popup-editButton.svg +5 -0
- package/static/assets/pdfjs/web/locale/ach/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/af/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/an/viewer.ftl +0 -16
- package/static/assets/pdfjs/web/locale/ar/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/ast/viewer.ftl +0 -19
- package/static/assets/pdfjs/web/locale/az/viewer.ftl +0 -16
- package/static/assets/pdfjs/web/locale/be/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/bg/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/bn/viewer.ftl +0 -16
- package/static/assets/pdfjs/web/locale/bo/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/br/viewer.ftl +0 -22
- package/static/assets/pdfjs/web/locale/brx/viewer.ftl +0 -16
- package/static/assets/pdfjs/web/locale/bs/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/ca/viewer.ftl +12 -23
- package/static/assets/pdfjs/web/locale/cak/viewer.ftl +0 -23
- package/static/assets/pdfjs/web/locale/ckb/viewer.ftl +0 -16
- package/static/assets/pdfjs/web/locale/cs/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/cy/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/da/viewer.ftl +3 -35
- package/static/assets/pdfjs/web/locale/de/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/dsb/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/el/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/en-CA/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/en-GB/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/en-US/viewer.ftl +25 -13
- package/static/assets/pdfjs/web/locale/eo/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/es-AR/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/es-CL/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/es-ES/viewer.ftl +5 -32
- package/static/assets/pdfjs/web/locale/es-MX/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/et/viewer.ftl +0 -16
- package/static/assets/pdfjs/web/locale/eu/viewer.ftl +38 -32
- package/static/assets/pdfjs/web/locale/fa/viewer.ftl +0 -19
- package/static/assets/pdfjs/web/locale/ff/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/fi/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/fr/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/fur/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/fy-NL/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/ga-IE/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/gd/viewer.ftl +0 -23
- package/static/assets/pdfjs/web/locale/gl/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/gn/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/gu-IN/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/he/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/hi-IN/viewer.ftl +0 -16
- package/static/assets/pdfjs/web/locale/hr/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/hsb/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/hu/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/hy-AM/viewer.ftl +372 -16
- package/static/assets/pdfjs/web/locale/hye/viewer.ftl +0 -16
- package/static/assets/pdfjs/web/locale/ia/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/id/viewer.ftl +38 -32
- package/static/assets/pdfjs/web/locale/is/viewer.ftl +27 -32
- package/static/assets/pdfjs/web/locale/it/viewer.ftl +0 -33
- package/static/assets/pdfjs/web/locale/ja/viewer.ftl +31 -33
- package/static/assets/pdfjs/web/locale/ka/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/kab/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/kk/viewer.ftl +31 -32
- package/static/assets/pdfjs/web/locale/km/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/kn/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/ko/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/lij/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/lo/viewer.ftl +0 -23
- package/static/assets/pdfjs/web/locale/lt/viewer.ftl +0 -16
- package/static/assets/pdfjs/web/locale/ltg/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/lv/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/meh/viewer.ftl +0 -14
- package/static/assets/pdfjs/web/locale/mk/viewer.ftl +0 -19
- package/static/assets/pdfjs/web/locale/ml/viewer.ftl +0 -31
- package/static/assets/pdfjs/web/locale/mr/viewer.ftl +0 -16
- package/static/assets/pdfjs/web/locale/ms/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/my/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/nb-NO/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/ne-NP/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/nl/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/nn-NO/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/oc/viewer.ftl +0 -24
- package/static/assets/pdfjs/web/locale/pa-IN/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/pl/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/pt-BR/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/pt-PT/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/rm/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/ro/viewer.ftl +5 -37
- package/static/assets/pdfjs/web/locale/ru/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/sat/viewer.ftl +0 -23
- package/static/assets/pdfjs/web/locale/sc/viewer.ftl +8 -27
- package/static/assets/pdfjs/web/locale/sco/viewer.ftl +0 -16
- package/static/assets/pdfjs/web/locale/si/viewer.ftl +0 -22
- package/static/assets/pdfjs/web/locale/sk/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/skr/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/sl/viewer.ftl +30 -32
- package/static/assets/pdfjs/web/locale/son/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/sq/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/sr/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/sv-SE/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/szl/viewer.ftl +0 -16
- package/static/assets/pdfjs/web/locale/ta/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/te/viewer.ftl +0 -16
- package/static/assets/pdfjs/web/locale/tg/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/th/viewer.ftl +38 -32
- package/static/assets/pdfjs/web/locale/tl/viewer.ftl +0 -16
- package/static/assets/pdfjs/web/locale/tr/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/trs/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/uk/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/ur/viewer.ftl +0 -16
- package/static/assets/pdfjs/web/locale/uz/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/vi/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/xh/viewer.ftl +0 -12
- package/static/assets/pdfjs/web/locale/zh-CN/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/locale/zh-TW/viewer.ftl +0 -32
- package/static/assets/pdfjs/web/viewer.css +586 -437
- package/static/assets/pdfjs/web/viewer.html +12 -23
- package/static/assets/pdfjs/web/viewer.mjs +955 -514
- package/static/assets/pdfjs/web/viewer.mjs.map +1 -1
- package/static/assets/pdfjs/web/wasm/openjpeg.wasm +0 -0
- package/static/assets/pdfjs/web/wasm/openjpeg_nowasm_fallback.js +10 -22
- package/static/{chunk-SPTF6FSM.js → chunk-27YQB3TE.js} +1 -1
- package/static/chunk-2I4CUFUA.js +1 -0
- package/static/chunk-2MTM6SWN.js +4 -0
- package/static/{chunk-7VRUZRJG.js → chunk-34MKICK5.js} +2 -2
- package/static/chunk-5O3DIUU3.js +1 -0
- package/static/{chunk-VJRTMDEJ.js → chunk-6NMVZIIT.js} +1 -1
- package/static/{chunk-L6MU6S2V.js → chunk-7DN7ZAPU.js} +1 -1
- package/static/{chunk-MVO4WZLK.js → chunk-7FUM3JGM.js} +1 -1
- package/static/{chunk-RSS6GYNE.js → chunk-7ITZXYYJ.js} +1 -1
- package/static/chunk-7P27WBGC.js +4 -0
- package/static/chunk-ATP3BFHV.js +562 -0
- package/static/chunk-AWQ2YTVC.js +1 -0
- package/static/chunk-DSOE3FEP.js +1 -0
- package/static/{chunk-2R6HHGUR.js → chunk-EFKMBLRE.js} +1 -1
- package/static/chunk-FUFKVHPU.js +1 -0
- package/static/{chunk-MRSWNAVB.js → chunk-HCDLWTMW.js} +1 -1
- package/static/chunk-IPAC4VAF.js +1 -0
- package/static/{chunk-ZC5NIT55.js → chunk-IQOALFYU.js} +1 -1
- package/static/chunk-JASU3CIH.js +1 -0
- package/static/{chunk-6OJZWYRZ.js → chunk-JQ5FTO2M.js} +1 -1
- package/static/chunk-JUNZFADM.js +1 -0
- package/static/{chunk-LLWSLOSX.js → chunk-LJUKI4SQ.js} +1 -1
- package/static/{chunk-WI7FOANP.js → chunk-LUWQFIWR.js} +1 -1
- package/static/{chunk-BIUNUYZ5.js → chunk-ORMRCEGT.js} +1 -1
- package/static/{chunk-IZL7JPTS.js → chunk-Q7D6RN4N.js} +1 -1
- package/static/{chunk-JYXLQRHG.js → chunk-QJX6ITLW.js} +1 -1
- package/static/{chunk-YJMN3B4N.js → chunk-QQ6UQQBR.js} +1 -1
- package/static/chunk-S2HDY3OL.js +1 -0
- package/static/{chunk-NE4NDO45.js → chunk-S75P2FFI.js} +1 -1
- package/static/{chunk-CRQNEHTX.js → chunk-T3EYFSVZ.js} +1 -1
- package/static/{chunk-MCLQFZ3S.js → chunk-U34OZUZ7.js} +1 -1
- package/static/chunk-Y7EH7G5K.js +1 -0
- package/static/{chunk-MGGT6MIJ.js → chunk-ZQQPUYLU.js} +1 -1
- package/static/index.html +2 -2
- package/static/main-7SQDDVMD.js +9 -0
- package/static/{styles-FYUSO6OJ.css → styles-A5VYX3CE.css} +1 -1
- package/server/applications/users/dto/user-password.dto.js.map +0 -1
- package/static/chunk-4U5A2DEP.js +0 -4
- package/static/chunk-54EAZ2UD.js +0 -1
- package/static/chunk-7ZRXJONB.js +0 -1
- package/static/chunk-F2J2IIJE.js +0 -1
- package/static/chunk-FNFGUIQH.js +0 -4
- package/static/chunk-GGLK52CG.js +0 -1
- package/static/chunk-HW2H3ISM.js +0 -559
- package/static/chunk-HX6BBYVD.js +0 -1
- package/static/chunk-JF7S3UYQ.js +0 -1
- package/static/chunk-KSHPKI4G.js +0 -1
- package/static/chunk-VPJ2V27B.js +0 -1
- package/static/chunk-VUI3KV7V.js +0 -1
- package/static/chunk-ZXS4V7J2.js +0 -1
- package/static/main-FFIWFD2F.js +0 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/notifications/mails/models.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 { SERVER_NAME } from '../../../app.constants'\nimport { ACTION } from '../../../common/constants'\nimport { capitalizeString } from '../../../common/shared'\nimport { fileName } from '../../files/utils/files'\nimport { UserModel } from '../../users/models/user.model'\nimport { translateObject } from '../i18n'\nimport { NotificationContent } from '../interfaces/notification-properties.interface'\nimport { defaultFooter, mailAuthor, mailEventOnElement, mailItalicContent, mailTemplate } from './templates'\nimport { urlFromLink, urlFromSpace, urlFromSpaceFile, urlFromSync } from './urls'\n\nexport function commentMail(\n language: string,\n notification: NotificationContent,\n options: {\n content: string\n currentUrl: string\n author: UserModel\n }\n): [string, string] {\n const tr = translateObject(language, {\n title: 'Comment',\n defaultFooter: defaultFooter,\n footer: 'You receive this notification if you are the owner of the file or if you have also commented on this file',\n urlText: 'Access it from',\n event: notification.event\n })\n\n const content = `${mailAuthor(options.author)}${mailEventOnElement(tr.event, notification.element)}${mailItalicContent(options.content)}`\n\n const footer = `<br>${tr.urlText} <a href=\"${urlFromSpaceFile(options.currentUrl, notification)}\">${SERVER_NAME}</a><br>${tr.footer}<br>${tr.defaultFooter}`\n\n return [`${tr.title}: ${capitalizeString(notification.element)}`, mailTemplate(content, footer)]\n}\n\nexport function spaceMail(\n language: string,\n notification: NotificationContent,\n options: {\n currentUrl: string\n action: ACTION\n }\n): [string, string] {\n const tr = translateObject(language, {\n title: 'Space',\n defaultFooter: defaultFooter,\n urlText: options.action === ACTION.ADD ? 'Access it from' : 'Access your spaces from',\n event: notification.event\n })\n\n const spaceUrl = urlFromSpace(options.currentUrl, options.action === ACTION.ADD ? notification.element : undefined)\n\n const content = `${mailEventOnElement(tr.event, notification.element)}`\n\n const footer = `<br>${tr.urlText} <a href=\"${spaceUrl}\">${SERVER_NAME}</a><br>${tr.defaultFooter}`\n\n return [`${tr.title}: ${capitalizeString(notification.element)}`, mailTemplate(content, footer)]\n}\n\nexport function spaceRootMail(\n language: string,\n notification: NotificationContent,\n options: {\n currentUrl: string\n author: UserModel\n action: ACTION\n }\n): [string, string] {\n const tr = translateObject(language, {\n title: 'Space',\n defaultFooter: defaultFooter,\n urlText: options.action === ACTION.ADD ? 'Access it from' : 'Access this space from',\n event: notification.event,\n originEvent: options.action === ACTION.ADD ? 'to the space' : 'from the space'\n })\n\n const spaceName = fileName(notification.url)\n const spaceRootUrl =\n options.action === ACTION.ADD ? urlFromSpaceFile(options.currentUrl, notification) : urlFromSpace(options.currentUrl, spaceName)\n\n const content = `${mailAuthor(options.author)}${mailEventOnElement(tr.event, notification.element)} ${tr.originEvent} <b>${spaceName}</b>`\n\n const footer = `<br>${tr.urlText} <a href=\"${spaceRootUrl}\">${SERVER_NAME}</a><br>${tr.defaultFooter}`\n\n return [`${tr.title}: ${capitalizeString(spaceName)}`, mailTemplate(content, footer)]\n}\n\nexport function shareMail(\n language: string,\n notification: NotificationContent,\n options: {\n currentUrl: string\n author: UserModel\n action: ACTION\n }\n): [string, string] {\n const tr = translateObject(language, {\n title: 'Share',\n defaultFooter: defaultFooter,\n urlText: options.action === ACTION.ADD ? 'Access it from' : 'Access your shares from',\n event: notification.event\n })\n\n const content = `${options.author ? mailAuthor(options.author) : ''}${mailEventOnElement(tr.event, notification.element)}`\n\n const footer = `<br>${tr.urlText} <a href=\"${urlFromSpaceFile(options.currentUrl, notification)}\">${SERVER_NAME}</a><br>${tr.defaultFooter}`\n\n return [`${tr.title}: ${capitalizeString(notification.element)}`, mailTemplate(content, footer)]\n}\n\nexport function linkMail(\n language: string,\n notification: NotificationContent,\n options: {\n currentUrl: string\n author: UserModel\n action: ACTION\n linkUUID: string\n }\n): [string, string] {\n const tr = translateObject(language, {\n title: options.action === ACTION.ADD ? 'Share' : 'Space',\n defaultFooter: defaultFooter,\n urlText: 'Access it from',\n event: notification.event\n })\n\n const content = `${options.author ? mailAuthor(options.author) : ''}${mailEventOnElement(tr.event, notification.element)}`\n\n const footer = `<br>${tr.urlText} <a href=\"${urlFromLink(options.currentUrl, options.linkUUID)}\">${SERVER_NAME}</a><br>${tr.defaultFooter}`\n\n return [`${tr.title}: ${capitalizeString(notification.element)}`, mailTemplate(content, footer)]\n}\n\nexport function syncMail(\n language: string,\n notification: NotificationContent,\n options: {\n currentUrl: string\n action: ACTION\n }\n): [string, string] {\n const tr = translateObject(language, {\n title: 'Sync',\n defaultFooter: defaultFooter,\n urlText: options.action === ACTION.ADD ? 'Access it from' : 'Access your syncs from',\n event: notification.event\n })\n\n const syncUrl = urlFromSync(options.currentUrl)\n\n const content = `${mailEventOnElement(tr.event, notification.element)}`\n\n const footer = `<br>${tr.urlText} <a href=\"${syncUrl}\">${SERVER_NAME}</a><br>${tr.defaultFooter}`\n\n return [`${tr.title}: ${capitalizeString(notification.element)}`, mailTemplate(content, footer)]\n}\n"],"names":["commentMail","linkMail","shareMail","spaceMail","spaceRootMail","syncMail","language","notification","options","tr","translateObject","title","defaultFooter","footer","urlText","event","content","mailAuthor","author","mailEventOnElement","element","mailItalicContent","urlFromSpaceFile","currentUrl","SERVER_NAME","capitalizeString","mailTemplate","action","ACTION","ADD","spaceUrl","urlFromSpace","undefined","originEvent","spaceName","fileName","url","spaceRootUrl","urlFromLink","linkUUID","syncUrl","urlFromSync"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/notifications/mails/models.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 { SERVER_NAME } from '../../../app.constants'\nimport { ACTION } from '../../../common/constants'\nimport { capitalizeString } from '../../../common/shared'\nimport { fileName } from '../../files/utils/files'\nimport { UserModel } from '../../users/models/user.model'\nimport { translateObject } from '../i18n'\nimport { NotificationContent } from '../interfaces/notification-properties.interface'\nimport { defaultFooter, mailAuthor, mailEventOnElement, mailItalicContent, mailTemplate } from './templates'\nimport { urlFromLink, urlFromSpace, urlFromSpaceFile, urlFromSync } from './urls'\n\nexport function commentMail(\n language: string,\n notification: NotificationContent,\n options: {\n content: string\n currentUrl: string\n author: UserModel\n }\n): [string, string] {\n const tr = translateObject(language, {\n title: 'Comment',\n defaultFooter: defaultFooter,\n footer: 'You receive this notification if you are the owner of the file or if you have also commented on this file',\n urlText: 'Access it from',\n event: notification.event\n })\n\n const content = `${mailAuthor(options.author)}${mailEventOnElement(tr.event, notification.element)}${mailItalicContent(options.content)}`\n\n const footer = `<br>${tr.urlText} <a href=\"${urlFromSpaceFile(options.currentUrl, notification)}\">${SERVER_NAME}</a><br>${tr.footer}<br>${tr.defaultFooter}`\n\n return [`${tr.title}: ${capitalizeString(notification.element)}`, mailTemplate(content, footer)]\n}\n\nexport function spaceMail(\n language: string,\n notification: NotificationContent,\n options: {\n currentUrl: string\n action: ACTION\n }\n): [string, string] {\n const tr = translateObject(language, {\n title: 'Space',\n defaultFooter: defaultFooter,\n urlText: options.action === ACTION.ADD ? 'Access it from' : 'Access your spaces from',\n event: notification.event\n })\n\n const spaceUrl = urlFromSpace(options.currentUrl, options.action === ACTION.ADD ? notification.element : undefined)\n\n const content = `${mailEventOnElement(tr.event, notification.element)}`\n\n const footer = `<br>${tr.urlText} <a href=\"${spaceUrl}\">${SERVER_NAME}</a><br>${tr.defaultFooter}`\n\n return [`${tr.title}: ${capitalizeString(notification.element)}`, mailTemplate(content, footer)]\n}\n\nexport function spaceRootMail(\n language: string,\n notification: NotificationContent,\n options: {\n currentUrl: string\n author: UserModel\n action: ACTION\n }\n): [string, string] {\n const tr = translateObject(language, {\n title: 'Space',\n defaultFooter: defaultFooter,\n urlText: options.action === ACTION.ADD ? 'Access it from' : 'Access this space from',\n event: notification.event,\n originEvent: options.action === ACTION.ADD ? 'to the space' : 'from the space'\n })\n\n const spaceName = fileName(notification.url)\n const spaceRootUrl =\n options.action === ACTION.ADD ? urlFromSpaceFile(options.currentUrl, notification) : urlFromSpace(options.currentUrl, spaceName)\n\n const content = `${mailAuthor(options.author)}${mailEventOnElement(tr.event, notification.element)} ${tr.originEvent} <b>${spaceName}</b>`\n\n const footer = `<br>${tr.urlText} <a href=\"${spaceRootUrl}\">${SERVER_NAME}</a><br>${tr.defaultFooter}`\n\n return [`${tr.title}: ${capitalizeString(spaceName)}`, mailTemplate(content, footer)]\n}\n\nexport function shareMail(\n language: string,\n notification: NotificationContent,\n options: {\n currentUrl: string\n author: UserModel\n action: ACTION\n }\n): [string, string] {\n const tr = translateObject(language, {\n title: 'Share',\n defaultFooter: defaultFooter,\n urlText: options.action === ACTION.ADD ? 'Access it from' : 'Access your shares from',\n event: notification.event\n })\n\n const content = `${options.author ? mailAuthor(options.author) : ''}${mailEventOnElement(tr.event, notification.element)}`\n\n const footer = `<br>${tr.urlText} <a href=\"${urlFromSpaceFile(options.currentUrl, notification)}\">${SERVER_NAME}</a><br>${tr.defaultFooter}`\n\n return [`${tr.title}: ${capitalizeString(notification.element)}`, mailTemplate(content, footer)]\n}\n\nexport function linkMail(\n language: string,\n notification: NotificationContent,\n options: {\n currentUrl: string\n author: UserModel\n action: ACTION\n linkUUID: string\n linkPassword: string\n }\n): [string, string] {\n const tr = translateObject(language, {\n title: options.action === ACTION.ADD ? 'Share' : 'Space',\n passwordText: 'Access password',\n urlText: 'Access it from',\n event: notification.event\n })\n\n let content = `${options.author ? mailAuthor(options.author) : ''}${mailEventOnElement(tr.event, notification.element)}`\n\n if (options.linkPassword) {\n content += `<br><br>${tr.passwordText}: <div style=\"border:1px solid #000; padding:8px; display:inline-block;\">${options.linkPassword}</div>`\n }\n\n const footer = `<br>${tr.urlText} <a href=\"${urlFromLink(options.currentUrl, options.linkUUID)}\">${SERVER_NAME}</a>`\n\n return [`${tr.title}: ${capitalizeString(notification.element)}`, mailTemplate(content, footer)]\n}\n\nexport function syncMail(\n language: string,\n notification: NotificationContent,\n options: {\n currentUrl: string\n action: ACTION\n }\n): [string, string] {\n const tr = translateObject(language, {\n title: 'Sync',\n defaultFooter: defaultFooter,\n urlText: options.action === ACTION.ADD ? 'Access it from' : 'Access your syncs from',\n event: notification.event\n })\n\n const syncUrl = urlFromSync(options.currentUrl)\n\n const content = `${mailEventOnElement(tr.event, notification.element)}`\n\n const footer = `<br>${tr.urlText} <a href=\"${syncUrl}\">${SERVER_NAME}</a><br>${tr.defaultFooter}`\n\n return [`${tr.title}: ${capitalizeString(notification.element)}`, mailTemplate(content, footer)]\n}\n\nexport function auth2FaMail(language: string, notification: NotificationContent): [string, string] {\n const tr = translateObject(language, {\n title: 'Security notification',\n footer:\n 'You received this notification because the security of your Sync-in account has changed. If you think this was a mistake, please review your security settings or contact your administrator.',\n event: notification.event,\n addressIp: 'Address IP',\n browser: 'Browser'\n })\n\n const content = `${tr.event}<br><br>${tr.addressIp}: ${notification.url}<br>${tr.browser}: ${notification.element}`\n\n const footer = `<br>${tr.footer}<br>`\n\n return [tr.title, mailTemplate(content, footer)]\n}\n\nexport function authLocked(language: string, notification: NotificationContent): [string, string] {\n const tr = translateObject(language, {\n title: 'Security notification',\n footer:\n 'This security notification concerns your Sync-in account. Please contact an administrator to perform the analysis and unlock your account.',\n event: notification.event,\n addressIp: 'Address IP'\n })\n\n const content = `${tr.event}<br><br>${tr.addressIp}: ${notification.url}<br>`\n\n const footer = `<br>${tr.footer}<br>`\n\n return [tr.title, mailTemplate(content, footer)]\n}\n"],"names":["auth2FaMail","authLocked","commentMail","linkMail","shareMail","spaceMail","spaceRootMail","syncMail","language","notification","options","tr","translateObject","title","defaultFooter","footer","urlText","event","content","mailAuthor","author","mailEventOnElement","element","mailItalicContent","urlFromSpaceFile","currentUrl","SERVER_NAME","capitalizeString","mailTemplate","action","ACTION","ADD","spaceUrl","urlFromSpace","undefined","originEvent","spaceName","fileName","url","spaceRootUrl","passwordText","linkPassword","urlFromLink","linkUUID","syncUrl","urlFromSync","addressIp","browser"],"mappings":"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"}
|
|
@@ -45,7 +45,7 @@ ${footer}
|
|
|
45
45
|
</body
|
|
46
46
|
</html>`;
|
|
47
47
|
const mailAuthor = (author)=>`<img style="border-radius: 50% !important; vertical-align: middle; object-fit: cover;" height="40" width="40" src="${author.avatarBase64}" alt="avatar"> <b>${author.fullName}</b> `;
|
|
48
|
-
const mailEventOnElement = (event, element)=>`${event}
|
|
48
|
+
const mailEventOnElement = (event, element)=>`${event}: <b>${(0, _shared.capitalizeString)(element)}</b>`;
|
|
49
49
|
const mailItalicContent = (content)=>`<p><i>${content}</i></p>`;
|
|
50
50
|
|
|
51
51
|
//# sourceMappingURL=templates.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/notifications/mails/templates.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 { capitalizeString } from '../../../common/shared'\nimport { UserModel } from '../../users/models/user.model'\n\nexport const defaultFooter = 'If you no longer wish to receive notifications, change your preferences directly from your user space'\n\nexport const mailTemplate = (content: string, footer: string) => `\n<html lang=\"en\">\n<meta charset=\"utf-8\"/>\n<body>\n<div>\n${content}\n</div>\n<small style=\"color:#666\">\n--\n${footer}\n</small>\n</body\n</html>`\n\nexport const mailAuthor = (author: UserModel) =>\n `<img style=\"border-radius: 50% !important; vertical-align: middle; object-fit: cover;\" height=\"40\" width=\"40\" src=\"${author.avatarBase64}\" alt=\"avatar\"> <b>${author.fullName}</b> `\n\nexport const mailEventOnElement = (event: string, element: string) => `${event}
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/notifications/mails/templates.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 { capitalizeString } from '../../../common/shared'\nimport { UserModel } from '../../users/models/user.model'\n\nexport const defaultFooter = 'If you no longer wish to receive notifications, change your preferences directly from your user space'\n\nexport const mailTemplate = (content: string, footer: string) => `\n<html lang=\"en\">\n<meta charset=\"utf-8\"/>\n<body>\n<div>\n${content}\n</div>\n<small style=\"color:#666\">\n--\n${footer}\n</small>\n</body\n</html>`\n\nexport const mailAuthor = (author: UserModel) =>\n `<img style=\"border-radius: 50% !important; vertical-align: middle; object-fit: cover;\" height=\"40\" width=\"40\" src=\"${author.avatarBase64}\" alt=\"avatar\"> <b>${author.fullName}</b> `\n\nexport const mailEventOnElement = (event: string, element: string) => `${event}: <b>${capitalizeString(element)}</b>`\n\nexport const mailItalicContent = (content: string) => `<p><i>${content}</i></p>`\n"],"names":["defaultFooter","mailAuthor","mailEventOnElement","mailItalicContent","mailTemplate","content","footer","author","avatarBase64","fullName","event","element","capitalizeString"],"mappings":"AAAA;;;;CAIC;;;;;;;;;;;QAKYA;eAAAA;;QAgBAC;eAAAA;;QAGAC;eAAAA;;QAEAC;eAAAA;;QAnBAC;eAAAA;;;wBALoB;AAG1B,MAAMJ,gBAAgB;AAEtB,MAAMI,eAAe,CAACC,SAAiBC,SAAmB,CAAC;;;;;AAKlE,EAAED,QAAQ;;;;AAIV,EAAEC,OAAO;;;OAGF,CAAC;AAED,MAAML,aAAa,CAACM,SACzB,CAAC,mHAAmH,EAAEA,OAAOC,YAAY,CAAC,wBAAwB,EAAED,OAAOE,QAAQ,CAAC,UAAU,CAAC;AAE1L,MAAMP,qBAAqB,CAACQ,OAAeC,UAAoB,GAAGD,MAAM,UAAU,EAAEE,IAAAA,wBAAgB,EAACD,SAAS,IAAI,CAAC;AAEnH,MAAMR,oBAAoB,CAACE,UAAoB,CAAC,MAAM,EAAEA,QAAQ,QAAQ,CAAC"}
|
|
@@ -14,6 +14,7 @@ Object.defineProperty(exports, "notifications", {
|
|
|
14
14
|
});
|
|
15
15
|
const _drizzleorm = require("drizzle-orm");
|
|
16
16
|
const _mysqlcore = require("drizzle-orm/mysql-core");
|
|
17
|
+
const _columns = require("../../../infrastructure/database/columns");
|
|
17
18
|
const _usersschema = require("../../users/schemas/users.schema");
|
|
18
19
|
const notifications = (0, _mysqlcore.mysqlTable)('notifications', {
|
|
19
20
|
id: (0, _mysqlcore.bigint)('id', {
|
|
@@ -32,7 +33,7 @@ const notifications = (0, _mysqlcore.mysqlTable)('notifications', {
|
|
|
32
33
|
}).references(()=>_usersschema.users.id, {
|
|
33
34
|
onDelete: 'cascade'
|
|
34
35
|
}).notNull(),
|
|
35
|
-
content: (0,
|
|
36
|
+
content: (0, _columns.jsonColumn)()('content'),
|
|
36
37
|
wasRead: (0, _mysqlcore.boolean)('wasRead').default(false).notNull(),
|
|
37
38
|
createdAt: (0, _mysqlcore.datetime)('createdAt', {
|
|
38
39
|
mode: 'date'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/notifications/schemas/notifications.schema.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { sql } from 'drizzle-orm'\nimport { bigint, boolean, datetime, index,
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/notifications/schemas/notifications.schema.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { sql } from 'drizzle-orm'\nimport { bigint, boolean, datetime, index, mysqlTable } from 'drizzle-orm/mysql-core'\nimport { jsonColumn } from '../../../infrastructure/database/columns'\nimport { users } from '../../users/schemas/users.schema'\nimport type { NotificationContent } from '../interfaces/notification-properties.interface'\n\nexport const notifications = mysqlTable(\n 'notifications',\n {\n id: bigint('id', { mode: 'number', unsigned: true }).autoincrement().primaryKey(),\n fromUserId: bigint('fromUserId', { mode: 'number', unsigned: true }).references(() => users.id, { onDelete: 'cascade' }),\n toUserId: bigint('toUserId', { mode: 'number', unsigned: true })\n .references(() => users.id, { onDelete: 'cascade' })\n .notNull(),\n content: jsonColumn<NotificationContent>()('content'),\n wasRead: boolean('wasRead').default(false).notNull(),\n createdAt: datetime('createdAt', { mode: 'date' })\n .default(sql`CURRENT_TIMESTAMP`)\n .notNull()\n },\n (table) => [index('from_user_idx').on(table.fromUserId), index('to_user_idx').on(table.toUserId)]\n)\n"],"names":["notifications","mysqlTable","id","bigint","mode","unsigned","autoincrement","primaryKey","fromUserId","references","users","onDelete","toUserId","notNull","content","jsonColumn","wasRead","boolean","default","createdAt","datetime","sql","table","index","on"],"mappings":"AAAA;;;;CAIC;;;;+BAQYA;;;eAAAA;;;4BANO;2BACyC;yBAClC;6BACL;AAGf,MAAMA,gBAAgBC,IAAAA,qBAAU,EACrC,iBACA;IACEC,IAAIC,IAAAA,iBAAM,EAAC,MAAM;QAAEC,MAAM;QAAUC,UAAU;IAAK,GAAGC,aAAa,GAAGC,UAAU;IAC/EC,YAAYL,IAAAA,iBAAM,EAAC,cAAc;QAAEC,MAAM;QAAUC,UAAU;IAAK,GAAGI,UAAU,CAAC,IAAMC,kBAAK,CAACR,EAAE,EAAE;QAAES,UAAU;IAAU;IACtHC,UAAUT,IAAAA,iBAAM,EAAC,YAAY;QAAEC,MAAM;QAAUC,UAAU;IAAK,GAC3DI,UAAU,CAAC,IAAMC,kBAAK,CAACR,EAAE,EAAE;QAAES,UAAU;IAAU,GACjDE,OAAO;IACVC,SAASC,IAAAA,mBAAU,IAAwB;IAC3CC,SAASC,IAAAA,kBAAO,EAAC,WAAWC,OAAO,CAAC,OAAOL,OAAO;IAClDM,WAAWC,IAAAA,mBAAQ,EAAC,aAAa;QAAEhB,MAAM;IAAO,GAC7Cc,OAAO,CAACG,IAAAA,eAAG,CAAA,CAAC,iBAAiB,CAAC,EAC9BR,OAAO;AACZ,GACA,CAACS,QAAU;QAACC,IAAAA,gBAAK,EAAC,iBAAiBC,EAAE,CAACF,MAAMd,UAAU;QAAGe,IAAAA,gBAAK,EAAC,eAAeC,EAAE,CAACF,MAAMV,QAAQ;KAAE"}
|
|
@@ -15,7 +15,7 @@ Object.defineProperty(exports, "NotificationsManager", {
|
|
|
15
15
|
const _common = require("@nestjs/common");
|
|
16
16
|
const _mailerservice = require("../../../infrastructure/mailer/mailer.service");
|
|
17
17
|
const _user = require("../../users/constants/user");
|
|
18
|
-
const
|
|
18
|
+
const _avatar = require("../../users/utils/avatar");
|
|
19
19
|
const _notifications = require("../constants/notifications");
|
|
20
20
|
const _websocket = require("../constants/websocket");
|
|
21
21
|
const _models = require("../mails/models");
|
|
@@ -56,20 +56,12 @@ let NotificationsManager = class NotificationsManager {
|
|
|
56
56
|
async delete(user, notificationId) {
|
|
57
57
|
return this.notificationsQueries.delete(user.id, notificationId);
|
|
58
58
|
}
|
|
59
|
-
async storeNotification(toUserIds, content, authorId) {
|
|
60
|
-
// store it in db
|
|
61
|
-
try {
|
|
62
|
-
await this.notificationsQueries.create(authorId || null, toUserIds, content);
|
|
63
|
-
} catch (e) {
|
|
64
|
-
this.logger.error(`${this.create.name} - ${e}`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
59
|
async sendEmailNotification(toUsers, content, options) {
|
|
68
60
|
if (!this.mailer.available) {
|
|
69
61
|
return;
|
|
70
62
|
}
|
|
71
63
|
if (options?.author) {
|
|
72
|
-
options.author.avatarBase64 = await
|
|
64
|
+
options.author.avatarBase64 = await (0, _avatar.getAvatarBase64)(options.author.login);
|
|
73
65
|
}
|
|
74
66
|
this.mailer.sendMails(await Promise.all(toUsers.map(async (m)=>{
|
|
75
67
|
const [title, html] = this.genMail(m.language, content, options);
|
|
@@ -80,6 +72,14 @@ let NotificationsManager = class NotificationsManager {
|
|
|
80
72
|
};
|
|
81
73
|
}))).catch((e)=>this.logger.error(`${this.sendEmailNotification.name} - ${e}`));
|
|
82
74
|
}
|
|
75
|
+
async storeNotification(toUserIds, content, authorId) {
|
|
76
|
+
// store it in db
|
|
77
|
+
try {
|
|
78
|
+
await this.notificationsQueries.create(authorId || null, toUserIds, content);
|
|
79
|
+
} catch (e) {
|
|
80
|
+
this.logger.error(`${this.create.name} - ${e}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
83
|
genMail(language, content, options) {
|
|
84
84
|
switch(content.app){
|
|
85
85
|
case _notifications.NOTIFICATION_APP.COMMENTS:
|
|
@@ -110,6 +110,7 @@ let NotificationsManager = class NotificationsManager {
|
|
|
110
110
|
currentUrl: options.currentUrl,
|
|
111
111
|
author: options.author,
|
|
112
112
|
linkUUID: options.linkUUID,
|
|
113
|
+
linkPassword: options.linkPassword,
|
|
113
114
|
action: options.action
|
|
114
115
|
});
|
|
115
116
|
case _notifications.NOTIFICATION_APP.SYNC:
|
|
@@ -117,12 +118,15 @@ let NotificationsManager = class NotificationsManager {
|
|
|
117
118
|
currentUrl: options.currentUrl,
|
|
118
119
|
action: options.action
|
|
119
120
|
});
|
|
121
|
+
case _notifications.NOTIFICATION_APP.AUTH_2FA:
|
|
122
|
+
return (0, _models.auth2FaMail)(language, content);
|
|
123
|
+
case _notifications.NOTIFICATION_APP.AUTH_LOCKED:
|
|
124
|
+
return (0, _models.authLocked)(language, content);
|
|
120
125
|
default:
|
|
121
126
|
this.logger.error(`${this.genMail.name} - case not handled : ${content.app}`);
|
|
122
127
|
}
|
|
123
128
|
}
|
|
124
|
-
constructor(
|
|
125
|
-
this.usersManager = usersManager;
|
|
129
|
+
constructor(mailer, notificationsQueries, webSocketNotifications){
|
|
126
130
|
this.mailer = mailer;
|
|
127
131
|
this.notificationsQueries = notificationsQueries;
|
|
128
132
|
this.webSocketNotifications = webSocketNotifications;
|
|
@@ -133,7 +137,6 @@ NotificationsManager = _ts_decorate([
|
|
|
133
137
|
(0, _common.Injectable)(),
|
|
134
138
|
_ts_metadata("design:type", Function),
|
|
135
139
|
_ts_metadata("design:paramtypes", [
|
|
136
|
-
typeof _usersmanagerservice.UsersManager === "undefined" ? Object : _usersmanagerservice.UsersManager,
|
|
137
140
|
typeof _mailerservice.Mailer === "undefined" ? Object : _mailerservice.Mailer,
|
|
138
141
|
typeof _notificationsqueriesservice.NotificationsQueries === "undefined" ? Object : _notificationsqueriesservice.NotificationsQueries,
|
|
139
142
|
typeof _notificationsgateway.WebSocketNotifications === "undefined" ? Object : _notificationsgateway.WebSocketNotifications
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/notifications/services/notifications-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 { Injectable, Logger } from '@nestjs/common'\nimport { MailProps } from '../../../infrastructure/mailer/interfaces/mail.interface'\nimport { Mailer } from '../../../infrastructure/mailer/mailer.service'\nimport { USER_NOTIFICATION } from '../../users/constants/user'\nimport { UserModel } from '../../users/models/user.model'\nimport { UsersManager } from '../../users/services/users-manager.service'\nimport { NOTIFICATION_APP } from '../constants/notifications'\nimport { NOTIFICATIONS_WS } from '../constants/websocket'\nimport type { NotificationContent, NotificationFromUser, NotificationOptions } from '../interfaces/notification-properties.interface'\nimport type { UserMailNotification } from '../interfaces/user-mail-notification'\nimport { commentMail, linkMail, shareMail, spaceMail, spaceRootMail, syncMail } from '../mails/models'\nimport { WebSocketNotifications } from '../notifications.gateway'\nimport { NotificationsQueries } from './notifications-queries.service'\n\n@Injectable()\nexport class NotificationsManager {\n private readonly logger = new Logger(NotificationsManager.name)\n\n constructor(\n private readonly usersManager: UsersManager,\n private readonly mailer: Mailer,\n private readonly notificationsQueries: NotificationsQueries,\n private readonly webSocketNotifications: WebSocketNotifications\n ) {}\n\n list(user: UserModel, onlyUnread: boolean = false): Promise<NotificationFromUser[]> {\n return this.notificationsQueries.list(user.id, onlyUnread)\n }\n\n async create(toUsers: UserMailNotification[] | number[], content: NotificationContent, options?: NotificationOptions): Promise<void> {\n // store it in db\n const isArrayOfUsers: boolean = typeof toUsers[0] === 'object'\n const toUserIds = isArrayOfUsers ? (toUsers as UserMailNotification[]).map((m) => m.id) : (toUsers as number[])\n this.storeNotification(toUserIds, content, options?.author?.id).catch((e: Error) => this.logger.error(`${this.create.name} - ${e}`))\n\n // send websocket notification\n this.webSocketNotifications.sendMessageToUsers(toUserIds, NOTIFICATIONS_WS.EVENTS.NOTIFICATION, 'check')\n\n // send emails\n if (this.mailer.available) {\n const usersNotifiedByEmail: UserMailNotification[] = isArrayOfUsers\n ? (toUsers as UserMailNotification[]).filter((u) => u.notification === USER_NOTIFICATION.APPLICATION_EMAIL)\n : await this.notificationsQueries.usersNotifiedByEmail(toUsers as number[])\n if (!usersNotifiedByEmail.length) {\n return\n }\n this.sendEmailNotification(usersNotifiedByEmail, content, options).catch((e: Error) => this.logger.error(`${this.create.name} - ${e}`))\n }\n }\n\n wasRead(user: UserModel, notificationId?: number): void {\n this.notificationsQueries.wasRead(user.id, notificationId).catch((e: Error) => this.logger.error(`${this.wasRead.name} - ${e}`))\n }\n\n async delete(user: UserModel, notificationId?: number): Promise<void> {\n return this.notificationsQueries.delete(user.id, notificationId)\n }\n\n private async storeNotification(toUserIds: number[], content: NotificationContent, authorId?: number): Promise<void> {\n // store it in db\n try {\n await this.notificationsQueries.create(authorId || null, toUserIds, content)\n } catch (e) {\n this.logger.error(`${this.create.name} - ${e}`)\n }\n }\n\n async sendEmailNotification(toUsers: UserMailNotification[], content: NotificationContent, options?: NotificationOptions): Promise<void> {\n if (!this.mailer.available) {\n return\n }\n if (options?.author) {\n options.author.avatarBase64 = await this.usersManager.getAvatarBase64(options.author.login)\n }\n this.mailer\n .sendMails(\n await Promise.all(\n toUsers.map(async (m) => {\n const [title, html] = this.genMail(m.language, content, options)\n return {\n to: m.email,\n subject: title,\n html: html\n } satisfies MailProps\n })\n )\n )\n .catch((e: Error) => this.logger.error(`${this.sendEmailNotification.name} - ${e}`))\n }\n\n private genMail(language: string, content: NotificationContent, options?: NotificationOptions): [string, string] {\n switch (content.app) {\n case NOTIFICATION_APP.COMMENTS:\n return commentMail(language, content, { content: options.content, currentUrl: options.currentUrl, author: options.author })\n case NOTIFICATION_APP.SPACES:\n return spaceMail(language, content, { currentUrl: options.currentUrl, action: options.action })\n case NOTIFICATION_APP.SPACE_ROOTS:\n return spaceRootMail(language, content, { currentUrl: options.currentUrl, author: options.author, action: options.action })\n case NOTIFICATION_APP.SHARES:\n return shareMail(language, content, { currentUrl: options.currentUrl, author: options.author, action: options.action })\n case NOTIFICATION_APP.LINKS:\n return linkMail(language, content, {\n currentUrl: options.currentUrl,\n author: options.author,\n linkUUID: options.linkUUID,\n action: options.action\n })\n case NOTIFICATION_APP.SYNC:\n return syncMail(language, content, { currentUrl: options.currentUrl, action: options.action })\n default:\n this.logger.error(`${this.genMail.name} - case not handled : ${content.app}`)\n }\n }\n}\n"],"names":["NotificationsManager","list","user","onlyUnread","notificationsQueries","id","create","toUsers","content","options","isArrayOfUsers","toUserIds","map","m","storeNotification","author","catch","e","logger","error","name","webSocketNotifications","sendMessageToUsers","NOTIFICATIONS_WS","EVENTS","NOTIFICATION","mailer","available","usersNotifiedByEmail","filter","u","notification","USER_NOTIFICATION","APPLICATION_EMAIL","length","sendEmailNotification","wasRead","notificationId","delete","authorId","avatarBase64","usersManager","getAvatarBase64","login","sendMails","Promise","all","title","html","genMail","language","to","email","subject","app","NOTIFICATION_APP","COMMENTS","commentMail","currentUrl","SPACES","spaceMail","action","SPACE_ROOTS","spaceRootMail","SHARES","shareMail","LINKS","linkMail","linkUUID","SYNC","syncMail","Logger"],"mappings":"AAAA;;;;CAIC;;;;+BAiBYA;;;eAAAA;;;wBAfsB;+BAEZ;sBACW;qCAEL;+BACI;2BACA;wBAGoD;sCAC9C;6CACF;;;;;;;;;;AAG9B,IAAA,AAAMA,uBAAN,MAAMA;IAUXC,KAAKC,IAAe,EAAEC,aAAsB,KAAK,EAAmC;QAClF,OAAO,IAAI,CAACC,oBAAoB,CAACH,IAAI,CAACC,KAAKG,EAAE,EAAEF;IACjD;IAEA,MAAMG,OAAOC,OAA0C,EAAEC,OAA4B,EAAEC,OAA6B,EAAiB;QACnI,iBAAiB;QACjB,MAAMC,iBAA0B,OAAOH,OAAO,CAAC,EAAE,KAAK;QACtD,MAAMI,YAAYD,iBAAiB,AAACH,QAAmCK,GAAG,CAAC,CAACC,IAAMA,EAAER,EAAE,IAAKE;QAC3F,IAAI,CAACO,iBAAiB,CAACH,WAAWH,SAASC,SAASM,QAAQV,IAAIW,KAAK,CAAC,CAACC,IAAa,IAAI,CAACC,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAACb,MAAM,CAACc,IAAI,CAAC,GAAG,EAAEH,GAAG;QAElI,8BAA8B;QAC9B,IAAI,CAACI,sBAAsB,CAACC,kBAAkB,CAACX,WAAWY,2BAAgB,CAACC,MAAM,CAACC,YAAY,EAAE;QAEhG,cAAc;QACd,IAAI,IAAI,CAACC,MAAM,CAACC,SAAS,EAAE;YACzB,MAAMC,uBAA+ClB,iBACjD,AAACH,QAAmCsB,MAAM,CAAC,CAACC,IAAMA,EAAEC,YAAY,KAAKC,uBAAiB,CAACC,iBAAiB,IACxG,MAAM,IAAI,CAAC7B,oBAAoB,CAACwB,oBAAoB,CAACrB;YACzD,IAAI,CAACqB,qBAAqBM,MAAM,EAAE;gBAChC;YACF;YACA,IAAI,CAACC,qBAAqB,CAACP,sBAAsBpB,SAASC,SAASO,KAAK,CAAC,CAACC,IAAa,IAAI,CAACC,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAACb,MAAM,CAACc,IAAI,CAAC,GAAG,EAAEH,GAAG;QACvI;IACF;IAEAmB,QAAQlC,IAAe,EAAEmC,cAAuB,EAAQ;QACtD,IAAI,CAACjC,oBAAoB,CAACgC,OAAO,CAAClC,KAAKG,EAAE,EAAEgC,gBAAgBrB,KAAK,CAAC,CAACC,IAAa,IAAI,CAACC,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAACiB,OAAO,CAAChB,IAAI,CAAC,GAAG,EAAEH,GAAG;IAChI;IAEA,MAAMqB,OAAOpC,IAAe,EAAEmC,cAAuB,EAAiB;QACpE,OAAO,IAAI,CAACjC,oBAAoB,CAACkC,MAAM,CAACpC,KAAKG,EAAE,EAAEgC;IACnD;IAEA,MAAcvB,kBAAkBH,SAAmB,EAAEH,OAA4B,EAAE+B,QAAiB,EAAiB;QACnH,iBAAiB;QACjB,IAAI;YACF,MAAM,IAAI,CAACnC,oBAAoB,CAACE,MAAM,CAACiC,YAAY,MAAM5B,WAAWH;QACtE,EAAE,OAAOS,GAAG;YACV,IAAI,CAACC,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAACb,MAAM,CAACc,IAAI,CAAC,GAAG,EAAEH,GAAG;QAChD;IACF;IAEA,MAAMkB,sBAAsB5B,OAA+B,EAAEC,OAA4B,EAAEC,OAA6B,EAAiB;QACvI,IAAI,CAAC,IAAI,CAACiB,MAAM,CAACC,SAAS,EAAE;YAC1B;QACF;QACA,IAAIlB,SAASM,QAAQ;YACnBN,QAAQM,MAAM,CAACyB,YAAY,GAAG,MAAM,IAAI,CAACC,YAAY,CAACC,eAAe,CAACjC,QAAQM,MAAM,CAAC4B,KAAK;QAC5F;QACA,IAAI,CAACjB,MAAM,CACRkB,SAAS,CACR,MAAMC,QAAQC,GAAG,CACfvC,QAAQK,GAAG,CAAC,OAAOC;YACjB,MAAM,CAACkC,OAAOC,KAAK,GAAG,IAAI,CAACC,OAAO,CAACpC,EAAEqC,QAAQ,EAAE1C,SAASC;YACxD,OAAO;gBACL0C,IAAItC,EAAEuC,KAAK;gBACXC,SAASN;gBACTC,MAAMA;YACR;QACF,KAGHhC,KAAK,CAAC,CAACC,IAAa,IAAI,CAACC,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAACgB,qBAAqB,CAACf,IAAI,CAAC,GAAG,EAAEH,GAAG;IACtF;IAEQgC,QAAQC,QAAgB,EAAE1C,OAA4B,EAAEC,OAA6B,EAAoB;QAC/G,OAAQD,QAAQ8C,GAAG;YACjB,KAAKC,+BAAgB,CAACC,QAAQ;gBAC5B,OAAOC,IAAAA,mBAAW,EAACP,UAAU1C,SAAS;oBAAEA,SAASC,QAAQD,OAAO;oBAAEkD,YAAYjD,QAAQiD,UAAU;oBAAE3C,QAAQN,QAAQM,MAAM;gBAAC;YAC3H,KAAKwC,+BAAgB,CAACI,MAAM;gBAC1B,OAAOC,IAAAA,iBAAS,EAACV,UAAU1C,SAAS;oBAAEkD,YAAYjD,QAAQiD,UAAU;oBAAEG,QAAQpD,QAAQoD,MAAM;gBAAC;YAC/F,KAAKN,+BAAgB,CAACO,WAAW;gBAC/B,OAAOC,IAAAA,qBAAa,EAACb,UAAU1C,SAAS;oBAAEkD,YAAYjD,QAAQiD,UAAU;oBAAE3C,QAAQN,QAAQM,MAAM;oBAAE8C,QAAQpD,QAAQoD,MAAM;gBAAC;YAC3H,KAAKN,+BAAgB,CAACS,MAAM;gBAC1B,OAAOC,IAAAA,iBAAS,EAACf,UAAU1C,SAAS;oBAAEkD,YAAYjD,QAAQiD,UAAU;oBAAE3C,QAAQN,QAAQM,MAAM;oBAAE8C,QAAQpD,QAAQoD,MAAM;gBAAC;YACvH,KAAKN,+BAAgB,CAACW,KAAK;gBACzB,OAAOC,IAAAA,gBAAQ,EAACjB,UAAU1C,SAAS;oBACjCkD,YAAYjD,QAAQiD,UAAU;oBAC9B3C,QAAQN,QAAQM,MAAM;oBACtBqD,UAAU3D,QAAQ2D,QAAQ;oBAC1BP,QAAQpD,QAAQoD,MAAM;gBACxB;YACF,KAAKN,+BAAgB,CAACc,IAAI;gBACxB,OAAOC,IAAAA,gBAAQ,EAACpB,UAAU1C,SAAS;oBAAEkD,YAAYjD,QAAQiD,UAAU;oBAAEG,QAAQpD,QAAQoD,MAAM;gBAAC;YAC9F;gBACE,IAAI,CAAC3C,MAAM,CAACC,KAAK,CAAC,GAAG,IAAI,CAAC8B,OAAO,CAAC7B,IAAI,CAAC,sBAAsB,EAAEZ,QAAQ8C,GAAG,EAAE;QAChF;IACF;IA9FA,YACE,AAAiBb,YAA0B,EAC3C,AAAiBf,MAAc,EAC/B,AAAiBtB,oBAA0C,EAC3D,AAAiBiB,sBAA8C,CAC/D;aAJiBoB,eAAAA;aACAf,SAAAA;aACAtB,uBAAAA;aACAiB,yBAAAA;aANFH,SAAS,IAAIqD,cAAM,CAACvE,qBAAqBoB,IAAI;IAO3D;AA0FL"}
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/notifications/services/notifications-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 { Injectable, Logger } from '@nestjs/common'\nimport { MailProps } from '../../../infrastructure/mailer/interfaces/mail.interface'\nimport { Mailer } from '../../../infrastructure/mailer/mailer.service'\nimport { USER_NOTIFICATION } from '../../users/constants/user'\nimport { UserModel } from '../../users/models/user.model'\nimport { getAvatarBase64 } from '../../users/utils/avatar'\nimport { NOTIFICATION_APP } from '../constants/notifications'\nimport { NOTIFICATIONS_WS } from '../constants/websocket'\nimport type { NotificationContent, NotificationFromUser, NotificationOptions } from '../interfaces/notification-properties.interface'\nimport type { UserMailNotification } from '../interfaces/user-mail-notification'\nimport { auth2FaMail, authLocked, commentMail, linkMail, shareMail, spaceMail, spaceRootMail, syncMail } from '../mails/models'\nimport { WebSocketNotifications } from '../notifications.gateway'\nimport { NotificationsQueries } from './notifications-queries.service'\n\n@Injectable()\nexport class NotificationsManager {\n private readonly logger = new Logger(NotificationsManager.name)\n\n constructor(\n private readonly mailer: Mailer,\n private readonly notificationsQueries: NotificationsQueries,\n private readonly webSocketNotifications: WebSocketNotifications\n ) {}\n\n list(user: UserModel, onlyUnread: boolean = false): Promise<NotificationFromUser[]> {\n return this.notificationsQueries.list(user.id, onlyUnread)\n }\n\n async create(toUsers: UserMailNotification[] | number[], content: NotificationContent, options?: NotificationOptions): Promise<void> {\n // store it in db\n const isArrayOfUsers: boolean = typeof toUsers[0] === 'object'\n const toUserIds = isArrayOfUsers ? (toUsers as UserMailNotification[]).map((m) => m.id) : (toUsers as number[])\n this.storeNotification(toUserIds, content, options?.author?.id).catch((e: Error) => this.logger.error(`${this.create.name} - ${e}`))\n\n // send websocket notification\n this.webSocketNotifications.sendMessageToUsers(toUserIds, NOTIFICATIONS_WS.EVENTS.NOTIFICATION, 'check')\n\n // send emails\n if (this.mailer.available) {\n const usersNotifiedByEmail: UserMailNotification[] = isArrayOfUsers\n ? (toUsers as UserMailNotification[]).filter((u) => u.notification === USER_NOTIFICATION.APPLICATION_EMAIL)\n : await this.notificationsQueries.usersNotifiedByEmail(toUsers as number[])\n if (!usersNotifiedByEmail.length) {\n return\n }\n this.sendEmailNotification(usersNotifiedByEmail, content, options).catch((e: Error) => this.logger.error(`${this.create.name} - ${e}`))\n }\n }\n\n wasRead(user: UserModel, notificationId?: number): void {\n this.notificationsQueries.wasRead(user.id, notificationId).catch((e: Error) => this.logger.error(`${this.wasRead.name} - ${e}`))\n }\n\n async delete(user: UserModel, notificationId?: number): Promise<void> {\n return this.notificationsQueries.delete(user.id, notificationId)\n }\n\n async sendEmailNotification(toUsers: UserMailNotification[], content: NotificationContent, options?: NotificationOptions): Promise<void> {\n if (!this.mailer.available) {\n return\n }\n if (options?.author) {\n options.author.avatarBase64 = await getAvatarBase64(options.author.login)\n }\n this.mailer\n .sendMails(\n await Promise.all(\n toUsers.map(async (m) => {\n const [title, html] = this.genMail(m.language, content, options)\n return {\n to: m.email,\n subject: title,\n html: html\n } satisfies MailProps\n })\n )\n )\n .catch((e: Error) => this.logger.error(`${this.sendEmailNotification.name} - ${e}`))\n }\n\n private async storeNotification(toUserIds: number[], content: NotificationContent, authorId?: number): Promise<void> {\n // store it in db\n try {\n await this.notificationsQueries.create(authorId || null, toUserIds, content)\n } catch (e) {\n this.logger.error(`${this.create.name} - ${e}`)\n }\n }\n\n private genMail(language: string, content: NotificationContent, options?: NotificationOptions): [string, string] {\n switch (content.app) {\n case NOTIFICATION_APP.COMMENTS:\n return commentMail(language, content, { content: options.content, currentUrl: options.currentUrl, author: options.author })\n case NOTIFICATION_APP.SPACES:\n return spaceMail(language, content, { currentUrl: options.currentUrl, action: options.action })\n case NOTIFICATION_APP.SPACE_ROOTS:\n return spaceRootMail(language, content, { currentUrl: options.currentUrl, author: options.author, action: options.action })\n case NOTIFICATION_APP.SHARES:\n return shareMail(language, content, { currentUrl: options.currentUrl, author: options.author, action: options.action })\n case NOTIFICATION_APP.LINKS:\n return linkMail(language, content, {\n currentUrl: options.currentUrl,\n author: options.author,\n linkUUID: options.linkUUID,\n linkPassword: options.linkPassword,\n action: options.action\n })\n case NOTIFICATION_APP.SYNC:\n return syncMail(language, content, { currentUrl: options.currentUrl, action: options.action })\n case NOTIFICATION_APP.AUTH_2FA:\n return auth2FaMail(language, content)\n case NOTIFICATION_APP.AUTH_LOCKED:\n return authLocked(language, content)\n default:\n this.logger.error(`${this.genMail.name} - case not handled : ${content.app}`)\n }\n }\n}\n"],"names":["NotificationsManager","list","user","onlyUnread","notificationsQueries","id","create","toUsers","content","options","isArrayOfUsers","toUserIds","map","m","storeNotification","author","catch","e","logger","error","name","webSocketNotifications","sendMessageToUsers","NOTIFICATIONS_WS","EVENTS","NOTIFICATION","mailer","available","usersNotifiedByEmail","filter","u","notification","USER_NOTIFICATION","APPLICATION_EMAIL","length","sendEmailNotification","wasRead","notificationId","delete","avatarBase64","getAvatarBase64","login","sendMails","Promise","all","title","html","genMail","language","to","email","subject","authorId","app","NOTIFICATION_APP","COMMENTS","commentMail","currentUrl","SPACES","spaceMail","action","SPACE_ROOTS","spaceRootMail","SHARES","shareMail","LINKS","linkMail","linkUUID","linkPassword","SYNC","syncMail","AUTH_2FA","auth2FaMail","AUTH_LOCKED","authLocked","Logger"],"mappings":"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"}
|
|
@@ -10,6 +10,7 @@ const _testing = require("@nestjs/testing");
|
|
|
10
10
|
const _mailerservice = require("../../../infrastructure/mailer/mailer.service");
|
|
11
11
|
const _user = require("../../users/constants/user");
|
|
12
12
|
const _usersmanagerservice = require("../../users/services/users-manager.service");
|
|
13
|
+
const _avatar = require("../../users/utils/avatar");
|
|
13
14
|
const _notifications = require("../constants/notifications");
|
|
14
15
|
const _websocket = require("../constants/websocket");
|
|
15
16
|
const _models = /*#__PURE__*/ _interop_require_wildcard(require("../mails/models"));
|
|
@@ -84,11 +85,11 @@ jest.mock('../mails/models', ()=>({
|
|
|
84
85
|
'sync html'
|
|
85
86
|
])
|
|
86
87
|
}));
|
|
88
|
+
jest.mock('../../users/utils/avatar', ()=>({
|
|
89
|
+
getAvatarBase64: jest.fn()
|
|
90
|
+
}));
|
|
87
91
|
describe(_notificationsmanagerservice.NotificationsManager.name, ()=>{
|
|
88
92
|
let service;
|
|
89
|
-
const usersManagerMock = {
|
|
90
|
-
getAvatarBase64: jest.fn()
|
|
91
|
-
};
|
|
92
93
|
const mailerMock = {
|
|
93
94
|
available: true,
|
|
94
95
|
sendMails: jest.fn()
|
|
@@ -114,13 +115,12 @@ describe(_notificationsmanagerservice.NotificationsManager.name, ()=>{
|
|
|
114
115
|
notificationsQueriesMock.delete.mockResolvedValue(undefined);
|
|
115
116
|
notificationsQueriesMock.list.mockResolvedValue([]);
|
|
116
117
|
notificationsQueriesMock.usersNotifiedByEmail.mockResolvedValue([]);
|
|
117
|
-
usersManagerMock.getAvatarBase64.mockResolvedValue('avatar-base64');
|
|
118
118
|
const module = await _testing.Test.createTestingModule({
|
|
119
119
|
providers: [
|
|
120
120
|
_notificationsmanagerservice.NotificationsManager,
|
|
121
121
|
{
|
|
122
122
|
provide: _usersmanagerservice.UsersManager,
|
|
123
|
-
useValue:
|
|
123
|
+
useValue: {}
|
|
124
124
|
},
|
|
125
125
|
{
|
|
126
126
|
provide: _mailerservice.Mailer,
|
|
@@ -342,11 +342,12 @@ describe(_notificationsmanagerservice.NotificationsManager.name, ()=>{
|
|
|
342
342
|
login: 'john'
|
|
343
343
|
}
|
|
344
344
|
});
|
|
345
|
-
expect(
|
|
345
|
+
expect(_avatar.getAvatarBase64).not.toHaveBeenCalled();
|
|
346
346
|
expect(mailerMock.sendMails).not.toHaveBeenCalled();
|
|
347
347
|
});
|
|
348
348
|
it('enriches author avatar and sends mapped mails', async ()=>{
|
|
349
|
-
|
|
349
|
+
;
|
|
350
|
+
_avatar.getAvatarBase64.mockResolvedValueOnce('base64-xxx');
|
|
350
351
|
const toUsers = [
|
|
351
352
|
{
|
|
352
353
|
id: 1,
|
|
@@ -371,7 +372,7 @@ describe(_notificationsmanagerservice.NotificationsManager.name, ()=>{
|
|
|
371
372
|
app: _notifications.NOTIFICATION_APP.COMMENTS
|
|
372
373
|
};
|
|
373
374
|
await service.sendEmailNotification(toUsers, content, options);
|
|
374
|
-
expect(
|
|
375
|
+
expect(_avatar.getAvatarBase64).toHaveBeenCalledWith('jdoe');
|
|
375
376
|
expect(options.author.avatarBase64).toBe('base64-xxx');
|
|
376
377
|
expect(mailerMock.sendMails).toHaveBeenCalledTimes(1);
|
|
377
378
|
expect(mailerMock.sendMails.mock.calls[0][0]).toEqual([
|
package/server/applications/notifications/services/notifications-manager.service.spec.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/notifications/services/notifications-manager.service.spec.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { Test, TestingModule } from '@nestjs/testing'\nimport { Mailer } from '../../../infrastructure/mailer/mailer.service'\nimport { USER_NOTIFICATION } from '../../users/constants/user'\nimport { UsersManager } from '../../users/services/users-manager.service'\nimport { NOTIFICATION_APP } from '../constants/notifications'\nimport { NOTIFICATIONS_WS } from '../constants/websocket'\nimport * as mailModels from '../mails/models'\nimport { WebSocketNotifications } from '../notifications.gateway'\nimport { NotificationsManager } from './notifications-manager.service'\nimport { NotificationsQueries } from './notifications-queries.service'\n\n// Compact mock for mail generators\njest.mock('../mails/models', () => ({\n commentMail: jest.fn(() => ['comment title', 'comment html']),\n spaceMail: jest.fn(() => ['space title', 'space html']),\n spaceRootMail: jest.fn(() => ['spaceRoot title', 'spaceRoot html']),\n shareMail: jest.fn(() => ['share title', 'share html']),\n linkMail: jest.fn(() => ['link title', 'link html']),\n syncMail: jest.fn(() => ['sync title', 'sync html'])\n}))\n\ndescribe(NotificationsManager.name, () => {\n let service: NotificationsManager\n\n const usersManagerMock = { getAvatarBase64: jest.fn() }\n const mailerMock = { available: true, sendMails: jest.fn() }\n const notificationsQueriesMock = {\n list: jest.fn(),\n usersNotifiedByEmail: jest.fn(),\n create: jest.fn(),\n wasRead: jest.fn(),\n delete: jest.fn()\n }\n const webSocketNotificationsMock = { sendMessageToUsers: jest.fn() }\n\n const flushPromises = () => new Promise<void>((r) => setImmediate(r))\n const spyLogger = () => jest.spyOn((service as any).logger, 'error').mockImplementation(() => undefined as any)\n\n beforeEach(async () => {\n jest.clearAllMocks()\n mailerMock.available = true\n mailerMock.sendMails.mockResolvedValue(undefined)\n notificationsQueriesMock.create.mockResolvedValue(undefined)\n notificationsQueriesMock.wasRead.mockResolvedValue(undefined)\n notificationsQueriesMock.delete.mockResolvedValue(undefined)\n notificationsQueriesMock.list.mockResolvedValue([])\n notificationsQueriesMock.usersNotifiedByEmail.mockResolvedValue([])\n usersManagerMock.getAvatarBase64.mockResolvedValue('avatar-base64')\n\n const module: TestingModule = await Test.createTestingModule({\n providers: [\n NotificationsManager,\n { provide: UsersManager, useValue: usersManagerMock },\n { provide: Mailer, useValue: mailerMock },\n { provide: WebSocketNotifications, useValue: webSocketNotificationsMock },\n { provide: NotificationsQueries, useValue: notificationsQueriesMock }\n ]\n }).compile()\n service = module.get<NotificationsManager>(NotificationsManager)\n })\n\n it('should be defined', () => {\n expect(service).toBeDefined()\n })\n\n describe('list', () => {\n it.each`\n userId | onlyUnread | expected\n ${42} | ${true} | ${true}\n ${1} | ${undefined} | ${false}\n `('should list notifications (userId=$userId, onlyUnread=$onlyUnread)', async ({ userId, onlyUnread, expected }) => {\n const expectedRes = [{ id: userId }] as any\n notificationsQueriesMock.list.mockResolvedValueOnce(expectedRes)\n const res = await service.list({ id: userId } as any, onlyUnread as any)\n expect(notificationsQueriesMock.list).toHaveBeenCalledWith(userId, expected)\n expect(res).toBe(expectedRes)\n })\n })\n\n describe('create', () => {\n it('stores, sends WS and no email when filtered list empty (object input)', async () => {\n const sendEmailSpy = jest.spyOn(service, 'sendEmailNotification').mockResolvedValue(undefined)\n const toUsers = [\n { id: 10, email: 'u1@test.tld', language: 'en', notification: USER_NOTIFICATION.APPLICATION },\n { id: 11, email: 'u2@test.tld', language: 'fr', notification: USER_NOTIFICATION.APPLICATION }\n ]\n await service.create(toUsers as any, { app: NOTIFICATION_APP.COMMENTS } as any, { author: { id: 99, login: 'john' } } as any)\n expect(notificationsQueriesMock.create).toHaveBeenCalledWith(99, [10, 11], { app: NOTIFICATION_APP.COMMENTS })\n expect(webSocketNotificationsMock.sendMessageToUsers).toHaveBeenCalledWith([10, 11], NOTIFICATIONS_WS.EVENTS.NOTIFICATION, 'check')\n expect(sendEmailSpy).not.toHaveBeenCalled()\n expect(notificationsQueriesMock.usersNotifiedByEmail).not.toHaveBeenCalled()\n })\n\n it('stores, sends WS and email for ids input', async () => {\n const sendEmailSpy = jest.spyOn(service, 'sendEmailNotification').mockResolvedValue(undefined)\n const toUserIds = [1, 2, 3]\n const content = { app: NOTIFICATION_APP.SHARES } as any\n const emailUsers = [\n { id: 1, email: 'a@test', language: 'en' },\n { id: 3, email: 'c@test', language: 'fr' }\n ]\n notificationsQueriesMock.usersNotifiedByEmail.mockResolvedValueOnce(emailUsers as any)\n await service.create(toUserIds, content)\n expect(notificationsQueriesMock.create).toHaveBeenCalledWith(null, toUserIds, content)\n expect(webSocketNotificationsMock.sendMessageToUsers).toHaveBeenCalledWith(toUserIds, NOTIFICATIONS_WS.EVENTS.NOTIFICATION, 'check')\n expect(notificationsQueriesMock.usersNotifiedByEmail).toHaveBeenCalledWith(toUserIds)\n expect(sendEmailSpy).toHaveBeenCalledWith(emailUsers as any, content, undefined)\n })\n\n it('does not try email when mailer is unavailable', async () => {\n mailerMock.available = false\n const sendEmailSpy = jest.spyOn(service, 'sendEmailNotification').mockResolvedValue(undefined)\n await service.create([7], { app: NOTIFICATION_APP.SYNC } as any, { author: { id: 12, login: 'jane' } } as any)\n expect(notificationsQueriesMock.create).toHaveBeenCalledWith(12, [7], { app: NOTIFICATION_APP.SYNC })\n expect(webSocketNotificationsMock.sendMessageToUsers).toHaveBeenCalledWith([7], NOTIFICATIONS_WS.EVENTS.NOTIFICATION, 'check')\n expect(notificationsQueriesMock.usersNotifiedByEmail).not.toHaveBeenCalled()\n expect(sendEmailSpy).not.toHaveBeenCalled()\n })\n\n it('logs error when storeNotification internal try/catch catches create error', async () => {\n const loggerSpy = spyLogger()\n notificationsQueriesMock.create.mockRejectedValueOnce(new Error('DB fail'))\n await service.create([1], { app: NOTIFICATION_APP.LINKS } as any)\n await flushPromises()\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls[0]?.[0] as string).toMatch(/create/i)\n })\n\n it('logs error when storeNotification promise rejects (create catch)', async () => {\n const loggerSpy = spyLogger()\n jest.spyOn<any, any>(service as any, 'storeNotification').mockRejectedValueOnce(new Error('store reject'))\n await service.create([1, 2], { app: NOTIFICATION_APP.SYNC } as any, { author: { id: 5, login: 'xx' } } as any)\n await flushPromises()\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls[0]?.[0] as string).toMatch(/create/i)\n })\n\n it('logs error when sendEmailNotification rejects (create catch)', async () => {\n const loggerSpy = spyLogger()\n notificationsQueriesMock.usersNotifiedByEmail.mockResolvedValueOnce([{ id: 1, email: 'a@test', language: 'en' }] as any)\n jest.spyOn(service, 'sendEmailNotification').mockRejectedValueOnce(new Error('email reject'))\n await service.create([1], { app: NOTIFICATION_APP.COMMENTS } as any)\n await flushPromises()\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls[0]?.[0] as string).toMatch(/create/i)\n })\n })\n\n describe('wasRead', () => {\n it('calls queries.wasRead and logs on error', async () => {\n service.wasRead({ id: 5 } as any, 123)\n expect(notificationsQueriesMock.wasRead).toHaveBeenCalledWith(5, 123)\n const loggerSpy = spyLogger()\n notificationsQueriesMock.wasRead.mockRejectedValueOnce(new Error('fail'))\n service.wasRead({ id: 8 } as any, undefined)\n await flushPromises()\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls[0]?.[0] as string).toMatch(/wasRead/i)\n })\n })\n\n describe('delete', () => {\n it('forwards to queries.delete', async () => {\n await service.delete({ id: 77 } as any, 456)\n expect(notificationsQueriesMock.delete).toHaveBeenCalledWith(77, 456)\n })\n })\n\n describe('sendEmailNotification', () => {\n it('returns early when mailer is not available', async () => {\n mailerMock.available = false\n await service.sendEmailNotification(\n [{ id: 1, email: 'a@test', language: 'en' }] as any,\n { app: NOTIFICATION_APP.COMMENTS } as any,\n {\n author: { id: 1, login: 'john' }\n } as any\n )\n expect(usersManagerMock.getAvatarBase64).not.toHaveBeenCalled()\n expect(mailerMock.sendMails).not.toHaveBeenCalled()\n })\n\n it('enriches author avatar and sends mapped mails', async () => {\n usersManagerMock.getAvatarBase64.mockResolvedValueOnce('base64-xxx')\n const toUsers = [\n { id: 1, email: 'a@test', language: 'en' },\n { id: 2, email: 'b@test', language: 'fr' }\n ]\n const options: any = { author: { id: 9, login: 'jdoe' }, content: 'hello', currentUrl: 'https://app.test/path' }\n const content = { app: NOTIFICATION_APP.COMMENTS } as any\n await service.sendEmailNotification(toUsers as any, content, options)\n expect(usersManagerMock.getAvatarBase64).toHaveBeenCalledWith('jdoe')\n expect(options.author.avatarBase64).toBe('base64-xxx')\n expect(mailerMock.sendMails).toHaveBeenCalledTimes(1)\n expect((mailerMock.sendMails as jest.Mock).mock.calls[0][0]).toEqual([\n { to: 'a@test', subject: 'comment title', html: 'comment html' },\n { to: 'b@test', subject: 'comment title', html: 'comment html' }\n ])\n })\n\n it('logs error when sendMails rejects', async () => {\n mailerMock.sendMails.mockRejectedValueOnce(new Error('smtp down'))\n const loggerSpy = spyLogger()\n await service.sendEmailNotification([{ id: 1, email: 'a@test', language: 'en' }] as any, { app: NOTIFICATION_APP.SYNC } as any, {} as any)\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls[0]?.[0] as string).toMatch(/sendEmailNotification/i)\n })\n })\n\n describe('genMail (private) - switch coverage', () => {\n const cases = [\n {\n name: 'COMMENTS',\n app: NOTIFICATION_APP.COMMENTS,\n fn: 'commentMail',\n options: { content: 'c', currentUrl: 'u', author: { id: 1, login: 'x' } }\n },\n { name: 'SPACES', app: NOTIFICATION_APP.SPACES, fn: 'spaceMail', options: { currentUrl: 'u', action: 'A' } },\n {\n name: 'SPACE_ROOTS',\n app: NOTIFICATION_APP.SPACE_ROOTS,\n fn: 'spaceRootMail',\n options: { currentUrl: 'u', author: { id: 2, login: 'y' }, action: 'B' }\n },\n { name: 'SHARES', app: NOTIFICATION_APP.SHARES, fn: 'shareMail', options: { currentUrl: 'u', author: { id: 3, login: 'z' }, action: 'C' } },\n {\n name: 'LINKS',\n app: NOTIFICATION_APP.LINKS,\n fn: 'linkMail',\n options: { currentUrl: 'u', author: { id: 4, login: 'w' }, linkUUID: 'uuid', action: 'D' }\n },\n { name: 'SYNC', app: NOTIFICATION_APP.SYNC, fn: 'syncMail', options: { currentUrl: 'u', action: 'E' } }\n ] as const\n\n it.each(cases)('uses $fn for $name', ({ app, fn, options }) => {\n const res = (service as any).genMail('en', { app } as any, options as any)\n expect(res).toEqual([\n `${fn.replace('Mail', '')} title`.replace('spaceRoot', 'spaceRoot'),\n `${fn.replace('Mail', '')} html`.replace('spaceRoot', 'spaceRoot')\n ])\n expect((mailModels as any)[fn]).toHaveBeenCalled()\n })\n\n it('logs error for unhandled app', () => {\n const loggerSpy = spyLogger()\n const result = (service as any).genMail('en', { app: 99999 } as any, {} as any)\n expect(result).toBeUndefined()\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls[0]?.[0] as string).toMatch(/case not handled/i)\n })\n })\n})\n"],"names":["jest","mock","commentMail","fn","spaceMail","spaceRootMail","shareMail","linkMail","syncMail","describe","NotificationsManager","name","service","usersManagerMock","getAvatarBase64","mailerMock","available","sendMails","notificationsQueriesMock","list","usersNotifiedByEmail","create","wasRead","delete","webSocketNotificationsMock","sendMessageToUsers","flushPromises","Promise","r","setImmediate","spyLogger","spyOn","logger","mockImplementation","undefined","beforeEach","clearAllMocks","mockResolvedValue","module","Test","createTestingModule","providers","provide","UsersManager","useValue","Mailer","WebSocketNotifications","NotificationsQueries","compile","get","it","expect","toBeDefined","each","userId","onlyUnread","expected","expectedRes","id","mockResolvedValueOnce","res","toHaveBeenCalledWith","toBe","sendEmailSpy","toUsers","email","language","notification","USER_NOTIFICATION","APPLICATION","app","NOTIFICATION_APP","COMMENTS","author","login","NOTIFICATIONS_WS","EVENTS","NOTIFICATION","not","toHaveBeenCalled","toUserIds","content","SHARES","emailUsers","SYNC","loggerSpy","mockRejectedValueOnce","Error","LINKS","calls","toMatch","sendEmailNotification","options","currentUrl","avatarBase64","toHaveBeenCalledTimes","toEqual","to","subject","html","cases","SPACES","action","SPACE_ROOTS","linkUUID","genMail","replace","mailModels","result","toBeUndefined"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/notifications/services/notifications-manager.service.spec.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { Test, TestingModule } from '@nestjs/testing'\nimport { Mailer } from '../../../infrastructure/mailer/mailer.service'\nimport { USER_NOTIFICATION } from '../../users/constants/user'\nimport { UsersManager } from '../../users/services/users-manager.service'\nimport { getAvatarBase64 } from '../../users/utils/avatar'\nimport { NOTIFICATION_APP } from '../constants/notifications'\nimport { NOTIFICATIONS_WS } from '../constants/websocket'\nimport * as mailModels from '../mails/models'\nimport { WebSocketNotifications } from '../notifications.gateway'\nimport { NotificationsManager } from './notifications-manager.service'\nimport { NotificationsQueries } from './notifications-queries.service'\n\n// Compact mock for mail generators\njest.mock('../mails/models', () => ({\n commentMail: jest.fn(() => ['comment title', 'comment html']),\n spaceMail: jest.fn(() => ['space title', 'space html']),\n spaceRootMail: jest.fn(() => ['spaceRoot title', 'spaceRoot html']),\n shareMail: jest.fn(() => ['share title', 'share html']),\n linkMail: jest.fn(() => ['link title', 'link html']),\n syncMail: jest.fn(() => ['sync title', 'sync html'])\n}))\n\njest.mock('../../users/utils/avatar', () => ({\n getAvatarBase64: jest.fn()\n}))\n\ndescribe(NotificationsManager.name, () => {\n let service: NotificationsManager\n\n const mailerMock = { available: true, sendMails: jest.fn() }\n const notificationsQueriesMock = {\n list: jest.fn(),\n usersNotifiedByEmail: jest.fn(),\n create: jest.fn(),\n wasRead: jest.fn(),\n delete: jest.fn()\n }\n const webSocketNotificationsMock = { sendMessageToUsers: jest.fn() }\n\n const flushPromises = () => new Promise<void>((r) => setImmediate(r))\n const spyLogger = () => jest.spyOn((service as any).logger, 'error').mockImplementation(() => undefined as any)\n\n beforeEach(async () => {\n jest.clearAllMocks()\n mailerMock.available = true\n mailerMock.sendMails.mockResolvedValue(undefined)\n notificationsQueriesMock.create.mockResolvedValue(undefined)\n notificationsQueriesMock.wasRead.mockResolvedValue(undefined)\n notificationsQueriesMock.delete.mockResolvedValue(undefined)\n notificationsQueriesMock.list.mockResolvedValue([])\n notificationsQueriesMock.usersNotifiedByEmail.mockResolvedValue([])\n\n const module: TestingModule = await Test.createTestingModule({\n providers: [\n NotificationsManager,\n { provide: UsersManager, useValue: {} },\n { provide: Mailer, useValue: mailerMock },\n { provide: WebSocketNotifications, useValue: webSocketNotificationsMock },\n { provide: NotificationsQueries, useValue: notificationsQueriesMock }\n ]\n }).compile()\n service = module.get<NotificationsManager>(NotificationsManager)\n })\n\n it('should be defined', () => {\n expect(service).toBeDefined()\n })\n\n describe('list', () => {\n it.each`\n userId | onlyUnread | expected\n ${42} | ${true} | ${true}\n ${1} | ${undefined} | ${false}\n `('should list notifications (userId=$userId, onlyUnread=$onlyUnread)', async ({ userId, onlyUnread, expected }) => {\n const expectedRes = [{ id: userId }] as any\n notificationsQueriesMock.list.mockResolvedValueOnce(expectedRes)\n const res = await service.list({ id: userId } as any, onlyUnread as any)\n expect(notificationsQueriesMock.list).toHaveBeenCalledWith(userId, expected)\n expect(res).toBe(expectedRes)\n })\n })\n\n describe('create', () => {\n it('stores, sends WS and no email when filtered list empty (object input)', async () => {\n const sendEmailSpy = jest.spyOn(service, 'sendEmailNotification').mockResolvedValue(undefined)\n const toUsers = [\n { id: 10, email: 'u1@test.tld', language: 'en', notification: USER_NOTIFICATION.APPLICATION },\n { id: 11, email: 'u2@test.tld', language: 'fr', notification: USER_NOTIFICATION.APPLICATION }\n ]\n await service.create(toUsers as any, { app: NOTIFICATION_APP.COMMENTS } as any, { author: { id: 99, login: 'john' } } as any)\n expect(notificationsQueriesMock.create).toHaveBeenCalledWith(99, [10, 11], { app: NOTIFICATION_APP.COMMENTS })\n expect(webSocketNotificationsMock.sendMessageToUsers).toHaveBeenCalledWith([10, 11], NOTIFICATIONS_WS.EVENTS.NOTIFICATION, 'check')\n expect(sendEmailSpy).not.toHaveBeenCalled()\n expect(notificationsQueriesMock.usersNotifiedByEmail).not.toHaveBeenCalled()\n })\n\n it('stores, sends WS and email for ids input', async () => {\n const sendEmailSpy = jest.spyOn(service, 'sendEmailNotification').mockResolvedValue(undefined)\n const toUserIds = [1, 2, 3]\n const content = { app: NOTIFICATION_APP.SHARES } as any\n const emailUsers = [\n { id: 1, email: 'a@test', language: 'en' },\n { id: 3, email: 'c@test', language: 'fr' }\n ]\n notificationsQueriesMock.usersNotifiedByEmail.mockResolvedValueOnce(emailUsers as any)\n await service.create(toUserIds, content)\n expect(notificationsQueriesMock.create).toHaveBeenCalledWith(null, toUserIds, content)\n expect(webSocketNotificationsMock.sendMessageToUsers).toHaveBeenCalledWith(toUserIds, NOTIFICATIONS_WS.EVENTS.NOTIFICATION, 'check')\n expect(notificationsQueriesMock.usersNotifiedByEmail).toHaveBeenCalledWith(toUserIds)\n expect(sendEmailSpy).toHaveBeenCalledWith(emailUsers as any, content, undefined)\n })\n\n it('does not try email when mailer is unavailable', async () => {\n mailerMock.available = false\n const sendEmailSpy = jest.spyOn(service, 'sendEmailNotification').mockResolvedValue(undefined)\n await service.create([7], { app: NOTIFICATION_APP.SYNC } as any, { author: { id: 12, login: 'jane' } } as any)\n expect(notificationsQueriesMock.create).toHaveBeenCalledWith(12, [7], { app: NOTIFICATION_APP.SYNC })\n expect(webSocketNotificationsMock.sendMessageToUsers).toHaveBeenCalledWith([7], NOTIFICATIONS_WS.EVENTS.NOTIFICATION, 'check')\n expect(notificationsQueriesMock.usersNotifiedByEmail).not.toHaveBeenCalled()\n expect(sendEmailSpy).not.toHaveBeenCalled()\n })\n\n it('logs error when storeNotification internal try/catch catches create error', async () => {\n const loggerSpy = spyLogger()\n notificationsQueriesMock.create.mockRejectedValueOnce(new Error('DB fail'))\n await service.create([1], { app: NOTIFICATION_APP.LINKS } as any)\n await flushPromises()\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls[0]?.[0] as string).toMatch(/create/i)\n })\n\n it('logs error when storeNotification promise rejects (create catch)', async () => {\n const loggerSpy = spyLogger()\n jest.spyOn<any, any>(service as any, 'storeNotification').mockRejectedValueOnce(new Error('store reject'))\n await service.create([1, 2], { app: NOTIFICATION_APP.SYNC } as any, { author: { id: 5, login: 'xx' } } as any)\n await flushPromises()\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls[0]?.[0] as string).toMatch(/create/i)\n })\n\n it('logs error when sendEmailNotification rejects (create catch)', async () => {\n const loggerSpy = spyLogger()\n notificationsQueriesMock.usersNotifiedByEmail.mockResolvedValueOnce([{ id: 1, email: 'a@test', language: 'en' }] as any)\n jest.spyOn(service, 'sendEmailNotification').mockRejectedValueOnce(new Error('email reject'))\n await service.create([1], { app: NOTIFICATION_APP.COMMENTS } as any)\n await flushPromises()\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls[0]?.[0] as string).toMatch(/create/i)\n })\n })\n\n describe('wasRead', () => {\n it('calls queries.wasRead and logs on error', async () => {\n service.wasRead({ id: 5 } as any, 123)\n expect(notificationsQueriesMock.wasRead).toHaveBeenCalledWith(5, 123)\n const loggerSpy = spyLogger()\n notificationsQueriesMock.wasRead.mockRejectedValueOnce(new Error('fail'))\n service.wasRead({ id: 8 } as any, undefined)\n await flushPromises()\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls[0]?.[0] as string).toMatch(/wasRead/i)\n })\n })\n\n describe('delete', () => {\n it('forwards to queries.delete', async () => {\n await service.delete({ id: 77 } as any, 456)\n expect(notificationsQueriesMock.delete).toHaveBeenCalledWith(77, 456)\n })\n })\n\n describe('sendEmailNotification', () => {\n it('returns early when mailer is not available', async () => {\n mailerMock.available = false\n await service.sendEmailNotification(\n [{ id: 1, email: 'a@test', language: 'en' }] as any,\n { app: NOTIFICATION_APP.COMMENTS } as any,\n {\n author: { id: 1, login: 'john' }\n } as any\n )\n expect(getAvatarBase64).not.toHaveBeenCalled()\n expect(mailerMock.sendMails).not.toHaveBeenCalled()\n })\n\n it('enriches author avatar and sends mapped mails', async () => {\n ;(getAvatarBase64 as jest.Mock).mockResolvedValueOnce('base64-xxx')\n const toUsers = [\n { id: 1, email: 'a@test', language: 'en' },\n { id: 2, email: 'b@test', language: 'fr' }\n ]\n const options: any = { author: { id: 9, login: 'jdoe' }, content: 'hello', currentUrl: 'https://app.test/path' }\n const content = { app: NOTIFICATION_APP.COMMENTS } as any\n await service.sendEmailNotification(toUsers as any, content, options)\n expect(getAvatarBase64).toHaveBeenCalledWith('jdoe')\n expect(options.author.avatarBase64).toBe('base64-xxx')\n expect(mailerMock.sendMails).toHaveBeenCalledTimes(1)\n expect((mailerMock.sendMails as jest.Mock).mock.calls[0][0]).toEqual([\n { to: 'a@test', subject: 'comment title', html: 'comment html' },\n { to: 'b@test', subject: 'comment title', html: 'comment html' }\n ])\n })\n\n it('logs error when sendMails rejects', async () => {\n mailerMock.sendMails.mockRejectedValueOnce(new Error('smtp down'))\n const loggerSpy = spyLogger()\n await service.sendEmailNotification([{ id: 1, email: 'a@test', language: 'en' }] as any, { app: NOTIFICATION_APP.SYNC } as any, {} as any)\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls[0]?.[0] as string).toMatch(/sendEmailNotification/i)\n })\n })\n\n describe('genMail (private) - switch coverage', () => {\n const cases = [\n {\n name: 'COMMENTS',\n app: NOTIFICATION_APP.COMMENTS,\n fn: 'commentMail',\n options: { content: 'c', currentUrl: 'u', author: { id: 1, login: 'x' } }\n },\n { name: 'SPACES', app: NOTIFICATION_APP.SPACES, fn: 'spaceMail', options: { currentUrl: 'u', action: 'A' } },\n {\n name: 'SPACE_ROOTS',\n app: NOTIFICATION_APP.SPACE_ROOTS,\n fn: 'spaceRootMail',\n options: { currentUrl: 'u', author: { id: 2, login: 'y' }, action: 'B' }\n },\n { name: 'SHARES', app: NOTIFICATION_APP.SHARES, fn: 'shareMail', options: { currentUrl: 'u', author: { id: 3, login: 'z' }, action: 'C' } },\n {\n name: 'LINKS',\n app: NOTIFICATION_APP.LINKS,\n fn: 'linkMail',\n options: { currentUrl: 'u', author: { id: 4, login: 'w' }, linkUUID: 'uuid', action: 'D' }\n },\n { name: 'SYNC', app: NOTIFICATION_APP.SYNC, fn: 'syncMail', options: { currentUrl: 'u', action: 'E' } }\n ] as const\n\n it.each(cases)('uses $fn for $name', ({ app, fn, options }) => {\n const res = (service as any).genMail('en', { app } as any, options as any)\n expect(res).toEqual([\n `${fn.replace('Mail', '')} title`.replace('spaceRoot', 'spaceRoot'),\n `${fn.replace('Mail', '')} html`.replace('spaceRoot', 'spaceRoot')\n ])\n expect((mailModels as any)[fn]).toHaveBeenCalled()\n })\n\n it('logs error for unhandled app', () => {\n const loggerSpy = spyLogger()\n const result = (service as any).genMail('en', { app: 99999 } as any, {} as any)\n expect(result).toBeUndefined()\n expect(loggerSpy).toHaveBeenCalled()\n expect(loggerSpy.mock.calls[0]?.[0] as string).toMatch(/case not handled/i)\n })\n })\n})\n"],"names":["jest","mock","commentMail","fn","spaceMail","spaceRootMail","shareMail","linkMail","syncMail","getAvatarBase64","describe","NotificationsManager","name","service","mailerMock","available","sendMails","notificationsQueriesMock","list","usersNotifiedByEmail","create","wasRead","delete","webSocketNotificationsMock","sendMessageToUsers","flushPromises","Promise","r","setImmediate","spyLogger","spyOn","logger","mockImplementation","undefined","beforeEach","clearAllMocks","mockResolvedValue","module","Test","createTestingModule","providers","provide","UsersManager","useValue","Mailer","WebSocketNotifications","NotificationsQueries","compile","get","it","expect","toBeDefined","each","userId","onlyUnread","expected","expectedRes","id","mockResolvedValueOnce","res","toHaveBeenCalledWith","toBe","sendEmailSpy","toUsers","email","language","notification","USER_NOTIFICATION","APPLICATION","app","NOTIFICATION_APP","COMMENTS","author","login","NOTIFICATIONS_WS","EVENTS","NOTIFICATION","not","toHaveBeenCalled","toUserIds","content","SHARES","emailUsers","SYNC","loggerSpy","mockRejectedValueOnce","Error","LINKS","calls","toMatch","sendEmailNotification","options","currentUrl","avatarBase64","toHaveBeenCalledTimes","toEqual","to","subject","html","cases","SPACES","action","SPACE_ROOTS","linkUUID","genMail","replace","mailModels","result","toBeUndefined"],"mappings":"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"}
|
|
@@ -50,7 +50,7 @@ let NotificationsQueries = class NotificationsQueries {
|
|
|
50
50
|
email: _usersschema.users.email,
|
|
51
51
|
fullName: (0, _usersschema.userFullNameSQL)(_usersschema.users)
|
|
52
52
|
},
|
|
53
|
-
content:
|
|
53
|
+
content: _notificationsschema.notifications.content,
|
|
54
54
|
wasRead: _notificationsschema.notifications.wasRead,
|
|
55
55
|
createdAt: _notificationsschema.notifications.createdAt
|
|
56
56
|
}).from(_notificationsschema.notifications).leftJoin(_usersschema.users, (0, _drizzleorm.eq)(_usersschema.users.id, _notificationsschema.notifications.fromUserId)).where((0, _drizzleorm.and)(...where)).orderBy((0, _drizzleorm.desc)(_notificationsschema.notifications.id));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/notifications/services/notifications-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 } from '@nestjs/common'\nimport { and, desc, eq, inArray, SelectedFields,
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/notifications/services/notifications-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 } from '@nestjs/common'\nimport { and, desc, eq, inArray, SelectedFields, SQL } from 'drizzle-orm'\nimport { DB_TOKEN_PROVIDER } from '../../../infrastructure/database/constants'\nimport { DBSchema } from '../../../infrastructure/database/interfaces/database.interface'\nimport { dbCheckAffectedRows } from '../../../infrastructure/database/utils'\nimport { USER_NOTIFICATION } from '../../users/constants/user'\nimport { userFullNameSQL, users } from '../../users/schemas/users.schema'\nimport type { NotificationContent, NotificationFromUser } from '../interfaces/notification-properties.interface'\nimport type { UserMailNotification } from '../interfaces/user-mail-notification'\nimport { Notification } from '../schemas/notification.interface'\nimport { notifications } from '../schemas/notifications.schema'\n\n@Injectable()\nexport class NotificationsQueries {\n constructor(@Inject(DB_TOKEN_PROVIDER) private readonly db: DBSchema) {}\n\n list(userId: number, onlyUnread: boolean = false): Promise<NotificationFromUser[]> {\n const where: SQL[] = [eq(notifications.toUserId, userId), ...(onlyUnread ? [eq(notifications.wasRead, false)] : [])]\n return this.db\n .select({\n id: notifications.id,\n fromUser: { id: users.id, login: users.login, email: users.email, fullName: userFullNameSQL(users) },\n content: notifications.content,\n wasRead: notifications.wasRead,\n createdAt: notifications.createdAt\n } satisfies NotificationFromUser | SelectedFields<any, any>)\n .from(notifications)\n .leftJoin(users, eq(users.id, notifications.fromUserId))\n .where(and(...where))\n .orderBy(desc(notifications.id))\n }\n\n async create(fromUserId: number, toUserIds: number[], content: NotificationContent): Promise<void> {\n dbCheckAffectedRows(\n await this.db.insert(notifications).values(\n toUserIds.map((toUserId: number) => ({\n fromUserId: fromUserId,\n toUserId: toUserId,\n content: content\n }))\n ),\n toUserIds.length\n )\n }\n\n async wasRead(userId: number, notificationId: number): Promise<void> {\n await this.db\n .update(notifications)\n .set({ wasRead: true } as Notification)\n .where(and(eq(notifications.toUserId, userId), eq(notifications.id, notificationId), eq(notifications.wasRead, false)))\n }\n\n async delete(userId: number, notificationId?: number): Promise<void> {\n const where: SQL[] = [eq(notifications.toUserId, userId), ...(notificationId ? [eq(notifications.id, notificationId)] : [])]\n await this.db.delete(notifications).where(and(...where))\n }\n\n usersNotifiedByEmail(userIds: number[]): Promise<UserMailNotification[]> {\n return this.db\n .select({\n id: users.id,\n email: users.email,\n language: users.language,\n notification: users.notification\n } satisfies UserMailNotification | SelectedFields<any, any>)\n .from(users)\n .where(and(inArray(users.id, userIds), eq(users.notification, USER_NOTIFICATION.APPLICATION_EMAIL)))\n }\n}\n"],"names":["NotificationsQueries","list","userId","onlyUnread","where","eq","notifications","toUserId","wasRead","db","select","id","fromUser","users","login","email","fullName","userFullNameSQL","content","createdAt","from","leftJoin","fromUserId","and","orderBy","desc","create","toUserIds","dbCheckAffectedRows","insert","values","map","length","notificationId","update","set","delete","usersNotifiedByEmail","userIds","language","notification","inArray","USER_NOTIFICATION","APPLICATION_EMAIL"],"mappings":"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"}
|
|
@@ -599,7 +599,7 @@ let SharesManager = class SharesManager {
|
|
|
599
599
|
}
|
|
600
600
|
}
|
|
601
601
|
async createGuestLink(permission, password, language, isActive = true) {
|
|
602
|
-
const random = (0, _functions.generateShortUUID)(
|
|
602
|
+
const random = (0, _functions.generateShortUUID)(64);
|
|
603
603
|
const guestLink = {
|
|
604
604
|
login: random,
|
|
605
605
|
email: `${random}@sync-in`,
|
|
@@ -607,7 +607,7 @@ let SharesManager = class SharesManager {
|
|
|
607
607
|
lastName: 'Link',
|
|
608
608
|
language: language || null,
|
|
609
609
|
permissions: permission,
|
|
610
|
-
password: await (0, _functions.hashPassword)(password || (0, _functions.generateShortUUID)(
|
|
610
|
+
password: await (0, _functions.hashPassword)(password || (0, _functions.generateShortUUID)(24)),
|
|
611
611
|
role: _user.USER_ROLE.LINK,
|
|
612
612
|
isActive: isActive
|
|
613
613
|
};
|
|
@@ -980,6 +980,7 @@ let SharesManager = class SharesManager {
|
|
|
980
980
|
}, {
|
|
981
981
|
author: user,
|
|
982
982
|
linkUUID: link.linkSettings.uuid,
|
|
983
|
+
linkPassword: link.linkSettings.password,
|
|
983
984
|
currentUrl: this.contextManager.get('headerOriginUrl'),
|
|
984
985
|
action: action
|
|
985
986
|
}).catch((e)=>this.logger.error(`${this.notifyGuestLink.name} - ${e}`));
|