@ozdao/martyrs 0.2.585 → 0.2.586
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/dist/auth.server.js +161 -96
- package/dist/{authJwt-J1csaMWA.js → authJwt-DKbMMjw0.js} +33 -0
- package/dist/chats.server.js +2 -2
- package/dist/community.server.js +1 -1
- package/dist/core.server.js +191 -2
- package/dist/{core.websocket-C2FxNmZ1.js → core.websocket-Cl76z2wT.js} +41 -5
- package/dist/{crud-q1ye5IhV.js → crud-DpOXTZep.js} +1 -1
- package/dist/events.server.js +2 -2
- package/dist/files.server.js +1 -1
- package/dist/gallery.server.js +1 -1
- package/dist/index-kvBwwb0w.js +427 -0
- package/dist/inventory.server.js +2 -2
- package/dist/{mailing-DuEFRsa3.js → mailing-DT7nbNjZ.js} +16 -3
- package/dist/{main-xL-jtBkT.js → main-BIf-WirR.js} +863 -865
- package/dist/marketplace.server.js +1 -1
- package/dist/martyrs/dist/{main-xL-jtBkT.js → main-BIf-WirR.js} +192 -38
- package/dist/martyrs/dist/main-BIf-WirR.js.map +1 -0
- package/dist/martyrs/dist/{web-BA6h6Z8P.js → web-O7lXcjg0.js} +2 -2
- package/dist/martyrs/dist/{web-BA6h6Z8P.js.map → web-O7lXcjg0.js.map} +1 -1
- package/dist/martyrs/src/components/Button/{Button.vue2.js → Button.vue.js} +8 -7
- package/dist/martyrs/src/components/Button/Button.vue.js.map +1 -0
- package/dist/martyrs/src/components/Feed/Feed.vue.js +1 -1
- package/dist/martyrs/src/components/FieldBig/FieldBig.vue.js +1 -1
- package/dist/martyrs/src/components/Loader/Loader.vue.js +1 -1
- package/dist/martyrs/src/components/Loader/Loader.vue.js.map +1 -1
- package/dist/martyrs/src/components/Spoiler/{Spoiler.vue2.js → Spoiler.vue.js} +2 -2
- package/dist/martyrs/src/components/Spoiler/Spoiler.vue.js.map +1 -0
- package/dist/martyrs/src/components/Tooltip/Tooltip.vue2.js +17 -22
- package/dist/martyrs/src/components/Tooltip/Tooltip.vue2.js.map +1 -1
- package/dist/martyrs/src/modules/auth/auth.client.js +18 -24
- package/dist/martyrs/src/modules/auth/auth.client.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/components/blocks/OtpDialog.vue.js +178 -0
- package/dist/martyrs/src/modules/auth/views/components/blocks/OtpDialog.vue.js.map +1 -0
- package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +53 -45
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditAccount.vue.js +198 -14
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditAccount.vue.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditProfile.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +70 -29
- package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +86 -30
- package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/plugins/otp.plugin.js +100 -0
- package/dist/martyrs/src/modules/auth/views/plugins/otp.plugin.js.map +1 -0
- package/dist/martyrs/src/modules/auth/views/router/auth.router.js +2 -31
- package/dist/martyrs/src/modules/auth/views/router/auth.router.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/router/users.router.js +0 -14
- package/dist/martyrs/src/modules/auth/views/router/users.router.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/store/auth.js +1 -56
- package/dist/martyrs/src/modules/auth/views/store/auth.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/store/users.js +5 -1
- package/dist/martyrs/src/modules/auth/views/store/users.js.map +1 -1
- package/dist/martyrs/src/modules/community/components/pages/BlogPost.vue.js +1 -1
- package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/blocks/CardHeader.vue.js +0 -1
- package/dist/martyrs/src/modules/core/views/components/blocks/CardHeader.vue.js.map +1 -1
- package/dist/martyrs/src/modules/core/views/components/blocks/PopupAuth.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/blocks/PopupDateSelector.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/elements/OnlineIndicator.vue.js +74 -0
- package/dist/martyrs/src/modules/core/views/components/elements/OnlineIndicator.vue.js.map +1 -0
- package/dist/martyrs/src/modules/core/views/components/layouts/App.vue.js.map +1 -1
- package/dist/martyrs/src/modules/core/views/components/layouts/Client.vue.js +63 -47
- package/dist/martyrs/src/modules/core/views/components/layouts/Client.vue.js.map +1 -1
- package/dist/martyrs/src/modules/core/views/components/partials/Header.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/partials/Navigation.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/partials/NavigationBar.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/sections/{Filters.vue2.js → Filters.vue.js} +2 -2
- package/dist/martyrs/src/modules/core/views/components/sections/Filters.vue.js.map +1 -0
- package/dist/martyrs/src/modules/events/components/elements/ButtonCheck.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/elements/ButtonJoin.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EditEventTickets.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/Event.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/sections/EditTickets.vue.js +1 -1
- package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.js +1 -1
- package/dist/martyrs/src/modules/inventory/components/forms/AdjustmentForm.vue.js +1 -1
- package/dist/martyrs/src/modules/inventory/components/forms/ColumnSettingsMenu.vue.js +1 -1
- package/dist/martyrs/src/modules/inventory/components/forms/HistoryView.vue.js +1 -1
- package/dist/martyrs/src/modules/inventory/components/forms/StockAlertsForm.vue.js +1 -1
- package/dist/martyrs/src/modules/inventory/components/pages/InventoryEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/landing/components/sections/SectionGuide.vue.js +1 -1
- package/dist/martyrs/src/modules/marketplace/views/components/pages/Marketplace.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/blocks/ActionButtons.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/cards/AlbumCard.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/cards/ArtistCardSmall.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/cards/PlaylistCard.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/forms/AlbumForm.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/forms/ArtistForm.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/forms/PlaylistForm.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Album.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Artist.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Track.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/TrackCreate.vue.js +0 -1
- package/dist/martyrs/src/modules/music/components/pages/TrackCreate.vue.js.map +1 -1
- package/dist/martyrs/src/modules/music/components/player/FullscreenPlayer.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/player/PlayerControls.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/player/VolumeControl.vue.js +1 -1
- package/dist/martyrs/src/modules/notifications/components/sections/NotificationPreferences.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/forms/FormApplicationDetails.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/forms/FormCustomerDetails.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/forms/FormSelectCustomer.vue.js +1 -2
- package/dist/martyrs/src/modules/orders/components/forms/FormSelectCustomer.vue.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/ApplicationDetails.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/CustomerDetails.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/blocks/CardDepartment.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/elements/ButtonToggleMembership.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/forms/AddExistingMembersForm.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/forms/DepartmentForm.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/forms/InviteForm.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Department.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.js +1 -2
- package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.js.map +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/MembersAdd.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +0 -1
- package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js.map +1 -1
- package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.js +0 -1
- package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.js.map +1 -1
- package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/pages/views/components/partials/SidebarPages.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js +0 -1
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +0 -1
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +3 -3
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/sections/EditAttributes.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/EditDiscounts.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/EditVariants.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/FilterProducts.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/ProductConfigurator.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/ProductsRecommended.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.js +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/RentsEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/reports/components/sections/FormReport.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/Map.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/Spot.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/sections/WorktimeEdit.vue.js +1 -1
- package/dist/martyrs.css +1 -1
- package/dist/martyrs.es.js +1 -1
- package/dist/music.server.js +1 -1
- package/dist/notifications.server.js +1 -1
- package/dist/orders.server.js +7 -6
- package/dist/organizations.server.js +2 -2
- package/dist/products.server.js +2 -2
- package/dist/profile.schema-C31Lynn3.js +21 -0
- package/dist/rents.server.js +1 -1
- package/dist/sessions.service-COcwjd0f.js +86 -0
- package/dist/style.css +178 -108
- package/dist/{tickets.controller-B7r0mK-5.js → tickets.controller-DdF85W-i.js} +1 -1
- package/dist/visitors.service-B1dhhuSo.js +83 -0
- package/dist/wallet.server.js +2 -2
- package/dist/{web-BA6h6Z8P.js → web-O7lXcjg0.js} +1 -1
- package/package.json +5 -1
- package/src/cli/commands/create.js +106 -0
- package/src/cli/index.js +25 -0
- package/src/cli/templates/app/.env.development.mustache +14 -0
- package/src/cli/templates/app/.env.production.mustache +14 -0
- package/src/cli/templates/app/Dockerfile +36 -0
- package/src/cli/templates/app/babel.config.js +14 -0
- package/src/cli/templates/app/env.js +3 -0
- package/src/cli/templates/app/index.js +46 -0
- package/src/cli/templates/app/mongodb.config.js +18 -0
- package/src/cli/templates/app/package.json.mustache +65 -0
- package/src/cli/templates/app/src/client.js +22 -0
- package/src/cli/templates/app/src/components/pages/Index.vue +11 -0
- package/src/cli/templates/app/src/configs/global.config.js.mustache +40 -0
- package/src/cli/templates/app/src/localization/extensions.js +2 -0
- package/src/cli/templates/app/src/localization/index.js +44 -0
- package/src/cli/templates/app/src/localization/overrides.js +2 -0
- package/src/cli/templates/app/src/localization/translations.js +10 -0
- package/src/cli/templates/app/src/models/index.js +9 -0
- package/src/cli/templates/app/src/router/index.js +48 -0
- package/src/cli/templates/app/src/scss/theme.scss +18 -0
- package/src/cli/templates/app/src/server.js +68 -0
- package/src/cli/templates/app/src/store/index.js +9 -0
- package/src/cli/templates/docker-compose.yaml.mustache +47 -0
- package/src/cli/templates/nginx/Dockerfile +5 -0
- package/src/cli/templates/nginx/default.conf.mustache +55 -0
- package/src/cli/templates/public/favicon/.gitkeep +0 -0
- package/src/cli/templates/start-dev.sh.mustache +131 -0
- package/src/cli/templates/start-prod.sh.mustache +12 -0
- package/src/components/Button/Button.vue +61 -15
- package/src/components/Loader/Loader.vue +1 -1
- package/src/components/Tooltip/Tooltip.vue +31 -23
- package/src/modules/TASKS.MD +30 -1
- package/src/modules/auth/CLAUDE.md +381 -0
- package/src/modules/auth/FIXES.md +0 -38
- package/src/modules/auth/auth.client.js +4 -6
- package/src/modules/auth/auth.server.js +4 -15
- package/src/modules/auth/controllers/middlewares/authJwt.js +59 -17
- package/src/modules/auth/controllers/middlewares/index.js +4 -1
- package/src/modules/auth/controllers/middlewares/otp.middleware.js +166 -0
- package/src/modules/auth/controllers/middlewares/verifySignUp.js +0 -1
- package/src/modules/auth/controllers/middlewares/verifyUser.js +58 -11
- package/src/modules/auth/controllers/routes/auth.routes.js +48 -6
- package/src/modules/auth/controllers/routes/users.routes.js +29 -8
- package/src/modules/auth/controllers/services/auth.service.js +62 -12
- package/src/modules/auth/controllers/services/otp.service.js +109 -0
- package/src/modules/auth/controllers/services/users.service.js +46 -6
- package/src/modules/auth/models/otp.model.js +20 -0
- package/src/modules/auth/views/components/blocks/OtpDialog.vue +168 -0
- package/src/modules/auth/views/components/pages/Profile.vue +18 -13
- package/src/modules/auth/views/components/pages/ProfileEditAccount.vue +199 -45
- package/src/modules/auth/views/components/pages/ResetPassword.vue +170 -132
- package/src/modules/auth/views/components/pages/SignIn.vue +2 -1
- package/src/modules/auth/views/components/pages/SignUp.vue +203 -147
- package/src/modules/auth/views/plugins/otp.plugin.js +104 -0
- package/src/modules/auth/views/router/auth.router.js +1 -24
- package/src/modules/auth/views/router/users.router.js +1 -12
- package/src/modules/auth/views/store/auth.js +0 -68
- package/src/modules/auth/views/store/users.js +6 -2
- package/src/modules/core/controllers/classes/core.websocket.js +57 -6
- package/src/modules/core/controllers/middlewares/visitor.logger.js +49 -0
- package/src/modules/core/controllers/services/requests.service.js +53 -0
- package/src/modules/core/controllers/services/sessions.service.js +98 -0
- package/src/modules/core/controllers/services/visitors.service.js +102 -0
- package/src/modules/core/controllers/utils/mailing.js +16 -3
- package/src/modules/core/core.server.js +45 -3
- package/src/modules/core/models/request.model.js +30 -0
- package/src/modules/core/models/session.model.js +43 -0
- package/src/modules/core/models/visitor.model.js +28 -0
- package/src/modules/core/views/components/elements/OnlineIndicator.vue +115 -0
- package/src/modules/core/views/components/layouts/App.vue +2 -2
- package/src/modules/core/views/components/layouts/Client.vue +443 -477
- package/src/modules/orders/controllers/orders.controller.js +3 -3
- package/src/modules/products/components/pages/Products.vue +1 -1
- package/dist/_virtual/alignment-pattern.js +0 -5
- package/dist/_virtual/alignment-pattern.js.map +0 -1
- package/dist/_virtual/browser.js +0 -8
- package/dist/_virtual/browser.js.map +0 -1
- package/dist/_virtual/browser2.js +0 -5
- package/dist/_virtual/browser2.js.map +0 -1
- package/dist/_virtual/canvas.js +0 -5
- package/dist/_virtual/canvas.js.map +0 -1
- package/dist/_virtual/dijkstra.js +0 -5
- package/dist/_virtual/dijkstra.js.map +0 -1
- package/dist/_virtual/error-correction-code.js +0 -5
- package/dist/_virtual/error-correction-code.js.map +0 -1
- package/dist/_virtual/error-correction-level.js +0 -5
- package/dist/_virtual/error-correction-level.js.map +0 -1
- package/dist/_virtual/finder-pattern.js +0 -5
- package/dist/_virtual/finder-pattern.js.map +0 -1
- package/dist/_virtual/format-info.js +0 -5
- package/dist/_virtual/format-info.js.map +0 -1
- package/dist/_virtual/galois-field.js +0 -5
- package/dist/_virtual/galois-field.js.map +0 -1
- package/dist/_virtual/mask-pattern.js +0 -5
- package/dist/_virtual/mask-pattern.js.map +0 -1
- package/dist/_virtual/mode.js +0 -5
- package/dist/_virtual/mode.js.map +0 -1
- package/dist/_virtual/polynomial.js +0 -5
- package/dist/_virtual/polynomial.js.map +0 -1
- package/dist/_virtual/qrcode.js +0 -5
- package/dist/_virtual/qrcode.js.map +0 -1
- package/dist/_virtual/regex.js +0 -5
- package/dist/_virtual/regex.js.map +0 -1
- package/dist/_virtual/segments.js +0 -5
- package/dist/_virtual/segments.js.map +0 -1
- package/dist/_virtual/svg-tag.js +0 -5
- package/dist/_virtual/svg-tag.js.map +0 -1
- package/dist/_virtual/utils.js +0 -5
- package/dist/_virtual/utils.js.map +0 -1
- package/dist/_virtual/utils2.js +0 -5
- package/dist/_virtual/utils2.js.map +0 -1
- package/dist/_virtual/version-check.js +0 -5
- package/dist/_virtual/version-check.js.map +0 -1
- package/dist/_virtual/version.js +0 -5
- package/dist/_virtual/version.js.map +0 -1
- package/dist/index-_Edcmck_.js +0 -170
- package/dist/martyrs/dist/main-xL-jtBkT.js.map +0 -1
- package/dist/martyrs/node_modules/.pnpm/bignumber.js@9.1.2/node_modules/bignumber.js/bignumber.js +0 -1336
- package/dist/martyrs/node_modules/.pnpm/bignumber.js@9.1.2/node_modules/bignumber.js/bignumber.js.map +0 -1
- package/dist/martyrs/src/components/Button/Button.vue2.js.map +0 -1
- package/dist/martyrs/src/components/Spoiler/Spoiler.vue2.js.map +0 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/EnterCode.vue.js +0 -166
- package/dist/martyrs/src/modules/auth/views/components/pages/EnterCode.vue.js.map +0 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +0 -118
- package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js.map +0 -1
- package/dist/martyrs/src/modules/auth/views/components/sections/ProfileEditCredentials.vue.js +0 -360
- package/dist/martyrs/src/modules/auth/views/components/sections/ProfileEditCredentials.vue.js.map +0 -1
- package/dist/martyrs/src/modules/auth/views/store/twofa.js +0 -40
- package/dist/martyrs/src/modules/auth/views/store/twofa.js.map +0 -1
- package/dist/martyrs/src/modules/core/views/components/sections/Filters.vue2.js.map +0 -1
- package/dist/martyrs/src/modules/wallet/views/components/blocks/CardBalanceReplenished.vue.js +0 -43
- package/dist/martyrs/src/modules/wallet/views/components/blocks/CardBalanceReplenished.vue.js.map +0 -1
- package/dist/martyrs/src/modules/wallet/views/components/blocks/CardDeposit.vue.js +0 -47
- package/dist/martyrs/src/modules/wallet/views/components/blocks/CardDeposit.vue.js.map +0 -1
- package/dist/martyrs/src/modules/wallet/views/components/blocks/CashDeposit.vue.js +0 -29
- package/dist/martyrs/src/modules/wallet/views/components/blocks/CashDeposit.vue.js.map +0 -1
- package/dist/martyrs/src/modules/wallet/views/components/blocks/CryptoDeposit.vue.js +0 -89
- package/dist/martyrs/src/modules/wallet/views/components/blocks/CryptoDeposit.vue.js.map +0 -1
- package/dist/martyrs/src/modules/wallet/views/components/blocks/CryptoDepositProcessing.vue.js +0 -136
- package/dist/martyrs/src/modules/wallet/views/components/blocks/CryptoDepositProcessing.vue.js.map +0 -1
- package/dist/martyrs/src/modules/wallet/views/components/pages/Wallet.vue.js +0 -238
- package/dist/martyrs/src/modules/wallet/views/components/pages/Wallet.vue.js.map +0 -1
- package/dist/martyrs/src/modules/wallet/views/localization/wallet.json.js +0 -9
- package/dist/martyrs/src/modules/wallet/views/localization/wallet.json.js.map +0 -1
- package/dist/martyrs/src/modules/wallet/views/store/wallet.store.js +0 -134
- package/dist/martyrs/src/modules/wallet/views/store/wallet.store.js.map +0 -1
- package/dist/node_modules/.pnpm/dijkstrajs@1.0.3/node_modules/dijkstrajs/dijkstra.js +0 -106
- package/dist/node_modules/.pnpm/dijkstrajs@1.0.3/node_modules/dijkstrajs/dijkstra.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/browser.js +0 -79
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/browser.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/can-promise.js +0 -14
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/can-promise.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/alignment-pattern.js +0 -43
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/alignment-pattern.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/alphanumeric-data.js +0 -85
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/alphanumeric-data.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/bit-buffer.js +0 -40
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/bit-buffer.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/bit-matrix.js +0 -34
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/bit-matrix.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/byte-data.js +0 -36
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/byte-data.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/error-correction-code.js +0 -367
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/error-correction-code.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/error-correction-level.js +0 -52
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/error-correction-level.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/finder-pattern.js +0 -25
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/finder-pattern.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/format-info.js +0 -24
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/format-info.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/galois-field.js +0 -38
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/galois-field.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/kanji-data.js +0 -46
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/kanji-data.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/mask-pattern.js +0 -149
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/mask-pattern.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/mode.js +0 -90
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/mode.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/numeric-data.js +0 -41
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/numeric-data.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/polynomial.js +0 -44
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/polynomial.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/qrcode.js +0 -279
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/qrcode.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/reed-solomon-encoder.js +0 -38
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/reed-solomon-encoder.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/regex.js +0 -33
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/regex.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/segments.js +0 -201
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/segments.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/utils.js +0 -84
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/utils.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/version-check.js +0 -14
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/version-check.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/version.js +0 -107
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/version.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/canvas.js +0 -61
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/canvas.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/svg-tag.js +0 -64
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/svg-tag.js.map +0 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/utils.js +0 -87
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/utils.js.map +0 -1
- package/dist/profile.schema-CjLOfG7b.js +0 -92
- package/src/modules/auth/controllers/middlewares/visitor.logger.js +0 -75
- package/src/modules/auth/controllers/routes/twofa.routes.js +0 -8
- package/src/modules/auth/controllers/services/twofa.service.js +0 -30
- package/src/modules/auth/models/request.model.js +0 -14
- package/src/modules/auth/models/visitor.model.js +0 -11
- package/src/modules/auth/views/components/pages/EnterCode.vue +0 -204
- package/src/modules/auth/views/components/pages/EnterPassword.vue +0 -123
- package/src/modules/auth/views/components/sections/ProfileEditCredentials.vue +0 -329
- package/src/modules/auth/views/store/twofa.js +0 -70
- package/src/modules/auth//320/220/320/240/320/245/320/230/320/242/320/225/320/232/320/242/320/243/320/240/320/220.md +0 -445
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as cookie from 'cookie';
|
|
2
2
|
import jwt from 'jsonwebtoken';
|
|
3
3
|
import uWS from 'uWebSockets.js';
|
|
4
|
+
import { getSessionsService } from '../services/sessions.service.js';
|
|
4
5
|
class WebSocketManager {
|
|
5
6
|
constructor(options = {}) {
|
|
6
7
|
// Создаем uWebSockets.js приложение внутри класса
|
|
@@ -25,10 +26,17 @@ class WebSocketManager {
|
|
|
25
26
|
idleTimeout: 120,
|
|
26
27
|
compression: uWS.SHARED_COMPRESSOR,
|
|
27
28
|
maxBackpressure: 1024 * 1024,
|
|
28
|
-
// Обработчик аутентификации и апгрейда соединения
|
|
29
|
+
// Обработчик аутентификации и апгрейда соединения (синхронный - uWS требует)
|
|
29
30
|
upgrade: (res, req, context) => {
|
|
30
31
|
let userId = null;
|
|
31
|
-
|
|
32
|
+
let sessionId = null;
|
|
33
|
+
let aborted = false;
|
|
34
|
+
|
|
35
|
+
res.onAborted(() => {
|
|
36
|
+
aborted = true;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Получаем cookies и все необходимые заголовки из HTTP-запроса (синхронно)
|
|
32
40
|
const headers = {};
|
|
33
41
|
req.forEach((key, value) => {
|
|
34
42
|
headers[key.toLowerCase()] = value;
|
|
@@ -37,6 +45,8 @@ class WebSocketManager {
|
|
|
37
45
|
const secWebSocketKey = headers['sec-websocket-key'] || '';
|
|
38
46
|
const secWebSocketProtocol = headers['sec-websocket-protocol'] || '';
|
|
39
47
|
const secWebSocketExtensions = headers['sec-websocket-extensions'] || '';
|
|
48
|
+
|
|
49
|
+
// Синхронный парсинг JWT (без await к Mongo)
|
|
40
50
|
try {
|
|
41
51
|
if (headers.cookie) {
|
|
42
52
|
const cookies = cookie.parse(headers.cookie);
|
|
@@ -44,24 +54,59 @@ class WebSocketManager {
|
|
|
44
54
|
const token = JSON.parse(decodeURIComponent(cookies.user));
|
|
45
55
|
const decoded = jwt.verify(token.accessToken, process.env.SECRET_KEY);
|
|
46
56
|
userId = decoded._id;
|
|
57
|
+
sessionId = decoded.session_id;
|
|
47
58
|
}
|
|
48
59
|
}
|
|
49
60
|
} catch (err) {
|
|
50
61
|
console.error('Invalid token:', err);
|
|
51
62
|
}
|
|
63
|
+
|
|
64
|
+
if (aborted) return;
|
|
65
|
+
|
|
52
66
|
// Если авторизация требуется, но userId не найден - отклоняем соединение
|
|
53
67
|
if (process.env.REQUIRE_AUTH === 'true' && !userId) {
|
|
54
68
|
res.writeStatus('401 Unauthorized').end('Authentication required');
|
|
55
69
|
return;
|
|
56
70
|
}
|
|
57
|
-
|
|
71
|
+
|
|
72
|
+
// Передаём данные для валидации сессии в open (async безопасен там)
|
|
73
|
+
const userData = { userId, sessionId, needsSessionValidation: !!sessionId };
|
|
58
74
|
res.upgrade(userData, secWebSocketKey, secWebSocketProtocol, secWebSocketExtensions, context);
|
|
59
75
|
},
|
|
60
|
-
// Обработчик открытия соединения
|
|
61
|
-
open: ws => {
|
|
76
|
+
// Обработчик открытия соединения (async безопасен здесь)
|
|
77
|
+
open: async ws => {
|
|
62
78
|
// Инициализация свойств клиента
|
|
63
|
-
|
|
79
|
+
const userData = ws.getUserData();
|
|
80
|
+
ws.userId = userData.userId;
|
|
81
|
+
ws.sessionId = userData.sessionId;
|
|
64
82
|
ws.subscriptions = new Set();
|
|
83
|
+
ws.lastSeenAt = Date.now();
|
|
84
|
+
|
|
85
|
+
// Валидация сессии (async, перенесено из upgrade)
|
|
86
|
+
if (userData.needsSessionValidation) {
|
|
87
|
+
try {
|
|
88
|
+
const sessionsService = getSessionsService();
|
|
89
|
+
const session = await sessionsService.validateSession({
|
|
90
|
+
sessionId: userData.sessionId,
|
|
91
|
+
userId: userData.userId,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
if (!session) {
|
|
95
|
+
ws.end(4001, 'Session expired or revoked');
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Touch session
|
|
100
|
+
sessionsService.touchSession(userData.sessionId).catch(err => {
|
|
101
|
+
console.error('Error updating session lastSeenAt:', err);
|
|
102
|
+
});
|
|
103
|
+
} catch (err) {
|
|
104
|
+
console.error('Session validation error:', err);
|
|
105
|
+
ws.end(4002, 'Session validation failed');
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
65
110
|
// Отслеживаем соединение
|
|
66
111
|
if (ws.userId) {
|
|
67
112
|
this._trackUserConnection(ws.userId, ws);
|
|
@@ -92,6 +137,12 @@ class WebSocketManager {
|
|
|
92
137
|
await this._handleRpcCall(ws, msg);
|
|
93
138
|
return;
|
|
94
139
|
}
|
|
140
|
+
// Обработка ping/pong
|
|
141
|
+
if (msg.type === 'ping') {
|
|
142
|
+
ws.lastSeenAt = Date.now();
|
|
143
|
+
ws.send(JSON.stringify({ type: 'pong' }), false);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
95
146
|
// Маршрутизация сообщения к соответствующему обработчику модуля
|
|
96
147
|
const moduleName = msg.module;
|
|
97
148
|
console.log(`[WebSocket Server] Message from ${ws.userId || 'anonymous'}, module: ${moduleName}, type: ${msg.type}, subscriptions:`, Array.from(ws.subscriptions));
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { getVisitorsService } from '../services/visitors.service.js';
|
|
2
|
+
import { getRequestsService } from '../services/requests.service.js';
|
|
3
|
+
|
|
4
|
+
const VISITOR_COOKIE_NAME = 'visitorId';
|
|
5
|
+
const VISITOR_COOKIE_MAX_AGE = 365 * 24 * 60 * 60 * 1000; // 1 year
|
|
6
|
+
|
|
7
|
+
const createVisitorLogger = () => {
|
|
8
|
+
const visitorLogger = async (req, res, next) => {
|
|
9
|
+
try {
|
|
10
|
+
const visitorsService = getVisitorsService();
|
|
11
|
+
const requestsService = getRequestsService();
|
|
12
|
+
|
|
13
|
+
const visitor = await visitorsService.findOrCreateVisitor(req);
|
|
14
|
+
|
|
15
|
+
// Set/update visitorId cookie if missing or different (handles "stale" cookie)
|
|
16
|
+
const cookieVisitorId = req.cookies?.visitorId;
|
|
17
|
+
if (!cookieVisitorId || cookieVisitorId !== visitor._id.toString()) {
|
|
18
|
+
res.cookie(VISITOR_COOKIE_NAME, visitor._id.toString(), {
|
|
19
|
+
maxAge: VISITOR_COOKIE_MAX_AGE,
|
|
20
|
+
httpOnly: true,
|
|
21
|
+
sameSite: 'lax',
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Attach visitor to request for downstream use
|
|
26
|
+
req.visitor = visitor;
|
|
27
|
+
req.visitorId = visitor._id;
|
|
28
|
+
|
|
29
|
+
// Log request AFTER response (userId/sessionId will be set by auth middleware by then)
|
|
30
|
+
res.on('finish', () => {
|
|
31
|
+
requestsService.logRequest({
|
|
32
|
+
visitorId: visitor._id,
|
|
33
|
+
req,
|
|
34
|
+
userId: req.userId || null,
|
|
35
|
+
sessionId: req.sessionId || null,
|
|
36
|
+
}).catch(err => console.error('Error logging request:', err));
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
next();
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error('Error processing visitor:', error);
|
|
42
|
+
next();
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return { visitorLogger };
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default createVisitorLogger;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
let instance = null;
|
|
2
|
+
|
|
3
|
+
export function initRequestsService(db) {
|
|
4
|
+
const Request = db.request;
|
|
5
|
+
|
|
6
|
+
async function logRequest({ visitorId, req, userId = null, sessionId = null }) {
|
|
7
|
+
const request = await Request.create({
|
|
8
|
+
visitor: visitorId ? new db.mongoose.Types.ObjectId(visitorId) : null,
|
|
9
|
+
target: userId ? new db.mongoose.Types.ObjectId(userId) : null,
|
|
10
|
+
session: sessionId ? new db.mongoose.Types.ObjectId(sessionId) : null,
|
|
11
|
+
path: req.path,
|
|
12
|
+
method: req.method,
|
|
13
|
+
referer: req.headers['referer'] || null,
|
|
14
|
+
query: req.query ? JSON.stringify(req.query) : null,
|
|
15
|
+
});
|
|
16
|
+
return request;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function getJourney(visitorId, { limit = 50, skip = 0 } = {}) {
|
|
20
|
+
const requests = await Request.find({ visitor: new db.mongoose.Types.ObjectId(visitorId) })
|
|
21
|
+
.sort({ timestamp: -1 })
|
|
22
|
+
.skip(skip)
|
|
23
|
+
.limit(limit)
|
|
24
|
+
.lean();
|
|
25
|
+
return requests;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function getUserJourney(userId, { limit = 50, skip = 0 } = {}) {
|
|
29
|
+
const requests = await Request.find({ target: new db.mongoose.Types.ObjectId(userId) })
|
|
30
|
+
.sort({ timestamp: -1 })
|
|
31
|
+
.skip(skip)
|
|
32
|
+
.limit(limit)
|
|
33
|
+
.lean();
|
|
34
|
+
return requests;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
instance = {
|
|
38
|
+
logRequest,
|
|
39
|
+
getJourney,
|
|
40
|
+
getUserJourney,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return instance;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function getRequestsService() {
|
|
47
|
+
if (!instance) {
|
|
48
|
+
throw new Error('Requests service not initialized. Call initRequestsService(db) first.');
|
|
49
|
+
}
|
|
50
|
+
return instance;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export default { initRequestsService, getRequestsService };
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const DEFAULT_SESSION_TTL = 864000; // 10 days in seconds
|
|
2
|
+
|
|
3
|
+
let instance = null;
|
|
4
|
+
|
|
5
|
+
export function initSessionsService(db) {
|
|
6
|
+
const Session = db.session;
|
|
7
|
+
|
|
8
|
+
async function createSession({ userId, visitorId = null, req, expiresIn = DEFAULT_SESSION_TTL }) {
|
|
9
|
+
const session = await Session.create({
|
|
10
|
+
target: new db.mongoose.Types.ObjectId(userId),
|
|
11
|
+
visitor: visitorId ? new db.mongoose.Types.ObjectId(visitorId) : null,
|
|
12
|
+
ip: req.ip,
|
|
13
|
+
userAgent: req.headers['user-agent'],
|
|
14
|
+
expiresAt: new Date(Date.now() + expiresIn * 1000),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
return session;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function validateSession({ sessionId, userId = null }) {
|
|
21
|
+
const query = {
|
|
22
|
+
_id: new db.mongoose.Types.ObjectId(sessionId),
|
|
23
|
+
isActive: true,
|
|
24
|
+
expiresAt: { $gt: new Date() },
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
if (userId) {
|
|
28
|
+
query.target = new db.mongoose.Types.ObjectId(userId);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const session = await Session.findOne(query).lean();
|
|
32
|
+
return session;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function deactivateSession(sessionId) {
|
|
36
|
+
const session = await Session.findByIdAndUpdate(
|
|
37
|
+
sessionId,
|
|
38
|
+
{
|
|
39
|
+
isActive: false,
|
|
40
|
+
revokedAt: new Date(),
|
|
41
|
+
},
|
|
42
|
+
{ new: true }
|
|
43
|
+
);
|
|
44
|
+
return session;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function deactivateAllUserSessions(userId, reason = null) {
|
|
48
|
+
const result = await Session.updateMany(
|
|
49
|
+
{
|
|
50
|
+
target: new db.mongoose.Types.ObjectId(userId),
|
|
51
|
+
isActive: true,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
isActive: false,
|
|
55
|
+
revokedAt: new Date(),
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function touchSession(sessionId) {
|
|
62
|
+
const session = await Session.findByIdAndUpdate(
|
|
63
|
+
sessionId,
|
|
64
|
+
{ lastSeenAt: new Date() },
|
|
65
|
+
{ new: true }
|
|
66
|
+
);
|
|
67
|
+
return session;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function getActiveSessions(userId) {
|
|
71
|
+
const sessions = await Session.find({
|
|
72
|
+
target: new db.mongoose.Types.ObjectId(userId),
|
|
73
|
+
isActive: true,
|
|
74
|
+
expiresAt: { $gt: new Date() },
|
|
75
|
+
}).lean();
|
|
76
|
+
return sessions;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
instance = {
|
|
80
|
+
createSession,
|
|
81
|
+
validateSession,
|
|
82
|
+
deactivateSession,
|
|
83
|
+
deactivateAllUserSessions,
|
|
84
|
+
touchSession,
|
|
85
|
+
getActiveSessions,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return instance;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function getSessionsService() {
|
|
92
|
+
if (!instance) {
|
|
93
|
+
throw new Error('Sessions service not initialized. Call initSessionsService(db) first.');
|
|
94
|
+
}
|
|
95
|
+
return instance;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export default { initSessionsService, getSessionsService };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
|
|
3
|
+
const fingerprintCache = new Map();
|
|
4
|
+
|
|
5
|
+
const generateFingerprint = req => {
|
|
6
|
+
const { ip, headers } = req;
|
|
7
|
+
const userAgent = headers['user-agent'] || '';
|
|
8
|
+
const acceptLanguage = headers['accept-language'] || '';
|
|
9
|
+
const key = `${ip}-${userAgent}-${acceptLanguage}`;
|
|
10
|
+
|
|
11
|
+
if (fingerprintCache.has(key)) {
|
|
12
|
+
return fingerprintCache.get(key);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const hash = crypto.createHash('sha256');
|
|
16
|
+
hash.update(key);
|
|
17
|
+
const digest = hash.digest('hex');
|
|
18
|
+
fingerprintCache.set(key, digest);
|
|
19
|
+
return digest;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const generateVisitorId = () => crypto.randomBytes(16).toString('hex');
|
|
23
|
+
|
|
24
|
+
let instance = null;
|
|
25
|
+
|
|
26
|
+
export function initVisitorsService(db) {
|
|
27
|
+
const Visitor = db.visitor;
|
|
28
|
+
|
|
29
|
+
async function findOrCreateVisitor(req) {
|
|
30
|
+
// Prefer cookie visitorId, fallback to fingerprint
|
|
31
|
+
let visitorId = req.cookies?.visitorId;
|
|
32
|
+
let visitor = null;
|
|
33
|
+
|
|
34
|
+
// Safe lookup by cookie ID (handle invalid ObjectId)
|
|
35
|
+
if (visitorId && db.mongoose.Types.ObjectId.isValid(visitorId)) {
|
|
36
|
+
try {
|
|
37
|
+
visitor = await Visitor.findById(visitorId);
|
|
38
|
+
} catch (err) {
|
|
39
|
+
// Invalid ObjectId format or DB error, ignore
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!visitor) {
|
|
44
|
+
const fingerprint = generateFingerprint(req);
|
|
45
|
+
// Atomic upsert to avoid race condition E11000
|
|
46
|
+
visitor = await Visitor.findOneAndUpdate(
|
|
47
|
+
{ fingerprint },
|
|
48
|
+
{
|
|
49
|
+
$setOnInsert: {
|
|
50
|
+
ip: req.ip,
|
|
51
|
+
userAgent: req.headers['user-agent'],
|
|
52
|
+
acceptLanguage: req.headers['accept-language'],
|
|
53
|
+
fingerprint,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{ upsert: true, new: true }
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return visitor;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function linkVisitorToUser({ visitorId, userId, sessionId = null }) {
|
|
64
|
+
const visitor = await Visitor.findByIdAndUpdate(
|
|
65
|
+
visitorId,
|
|
66
|
+
{
|
|
67
|
+
target: new db.mongoose.Types.ObjectId(userId),
|
|
68
|
+
linkedAt: new Date(),
|
|
69
|
+
},
|
|
70
|
+
{ new: true }
|
|
71
|
+
);
|
|
72
|
+
return visitor;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function getVisitorByFingerprint(fingerprint) {
|
|
76
|
+
return Visitor.findOne({ fingerprint });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function getVisitorById(visitorId) {
|
|
80
|
+
return Visitor.findById(visitorId);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
instance = {
|
|
84
|
+
findOrCreateVisitor,
|
|
85
|
+
linkVisitorToUser,
|
|
86
|
+
getVisitorByFingerprint,
|
|
87
|
+
getVisitorById,
|
|
88
|
+
generateFingerprint,
|
|
89
|
+
generateVisitorId,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
return instance;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function getVisitorsService() {
|
|
96
|
+
if (!instance) {
|
|
97
|
+
throw new Error('Visitors service not initialized. Call initVisitorsService(db) first.');
|
|
98
|
+
}
|
|
99
|
+
return instance;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export default { initVisitorsService, getVisitorsService };
|
|
@@ -38,12 +38,25 @@ async function sendEmail(to, subject, text, files = []) {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
async function sendSms(phone, message) {
|
|
41
|
-
const sessionUrl = `https://api.sms.to/sms/send?api_key=${process.env.SMS_API_KEY}&to=${phone}&message=${encodeURIComponent(message)}&sender_id=${encodeURIComponent(process.env.APP_NAME)}`;
|
|
42
41
|
try {
|
|
43
|
-
const response = await axios.
|
|
42
|
+
const response = await axios.post(
|
|
43
|
+
'https://api.brevo.com/v3/transactionalSMS/send',
|
|
44
|
+
{
|
|
45
|
+
recipient: phone,
|
|
46
|
+
sender: process.env.APP_NAME?.slice(0, 11) || 'App',
|
|
47
|
+
content: message,
|
|
48
|
+
type: 'transactional'
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
headers: {
|
|
52
|
+
'api-key': process.env.BREVO_API_KEY,
|
|
53
|
+
'Content-Type': 'application/json'
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
);
|
|
44
57
|
return true;
|
|
45
58
|
} catch (error) {
|
|
46
|
-
console.
|
|
59
|
+
console.error('SMS send failed');
|
|
47
60
|
return false;
|
|
48
61
|
}
|
|
49
62
|
}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import coreabac from './controllers/classes/abac/abac.js';
|
|
2
|
-
|
|
3
2
|
import initCorePolicies from './controllers/policies/core.policies.js';
|
|
4
3
|
|
|
4
|
+
import SessionModel from './models/session.model.js';
|
|
5
|
+
import VisitorModel from './models/visitor.model.js';
|
|
6
|
+
import RequestModel from './models/request.model.js';
|
|
7
|
+
|
|
8
|
+
import { initSessionsService } from './controllers/services/sessions.service.js';
|
|
9
|
+
import { initVisitorsService } from './controllers/services/visitors.service.js';
|
|
10
|
+
import { initRequestsService } from './controllers/services/requests.service.js';
|
|
11
|
+
|
|
12
|
+
import createVisitorLogger from './controllers/middlewares/visitor.logger.js';
|
|
13
|
+
|
|
5
14
|
const { getInstance } = coreabac;
|
|
6
15
|
|
|
7
16
|
// Ленивая загрузка WebSocketManager через асинхронную фабрику
|
|
@@ -19,8 +28,8 @@ async function createWebSocketManager(...args) {
|
|
|
19
28
|
// Для обратной совместимости экспортируем как WebSocketManager
|
|
20
29
|
const WebSocketManager = createWebSocketManager;
|
|
21
30
|
|
|
22
|
-
function initializeCore(app, db, origins, publicPath) {
|
|
23
|
-
//
|
|
31
|
+
function initializeCore(app, db, origins, publicPath, wss = null) {
|
|
32
|
+
// Log model
|
|
24
33
|
db.log =
|
|
25
34
|
db.mongoose.models.Log ||
|
|
26
35
|
db.mongoose.model(
|
|
@@ -34,8 +43,41 @@ function initializeCore(app, db, origins, publicPath) {
|
|
|
34
43
|
{ versionKey: false }
|
|
35
44
|
)
|
|
36
45
|
);
|
|
46
|
+
|
|
47
|
+
// Session, Visitor, Request models
|
|
48
|
+
db.session = SessionModel(db);
|
|
49
|
+
db.visitor = VisitorModel(db);
|
|
50
|
+
db.request = RequestModel(db);
|
|
51
|
+
|
|
52
|
+
// Initialize services
|
|
53
|
+
initSessionsService(db);
|
|
54
|
+
initVisitorsService(db);
|
|
55
|
+
initRequestsService(db);
|
|
56
|
+
|
|
57
|
+
// ABAC
|
|
37
58
|
const abac = getInstance(db);
|
|
38
59
|
const corePolicies = initCorePolicies(abac);
|
|
60
|
+
|
|
61
|
+
// Visitor logger middleware
|
|
62
|
+
if (app) {
|
|
63
|
+
const { visitorLogger } = createVisitorLogger();
|
|
64
|
+
app.use(visitorLogger);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// WebSocket RPC methods
|
|
68
|
+
if (wss) {
|
|
69
|
+
wss.registerRpcMethod('core', 'getOnlineStatus', async ({ userId }) => {
|
|
70
|
+
if (!userId) return { isOnline: false, lastSeenAt: null };
|
|
71
|
+
const isOnline = wss.userConnections.has(userId.toString());
|
|
72
|
+
if (isOnline) return { isOnline: true, lastSeenAt: new Date() };
|
|
73
|
+
const session = await db.session.findOne(
|
|
74
|
+
{ target: new db.mongoose.Types.ObjectId(userId), isActive: true },
|
|
75
|
+
{ lastSeenAt: 1 },
|
|
76
|
+
{ sort: { lastSeenAt: -1 } }
|
|
77
|
+
).lean();
|
|
78
|
+
return { isOnline: false, lastSeenAt: session?.lastSeenAt || null };
|
|
79
|
+
}, { requireAuth: false });
|
|
80
|
+
}
|
|
39
81
|
}
|
|
40
82
|
export { WebSocketManager, initializeCore as initialize };
|
|
41
83
|
export default {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export default db => {
|
|
2
|
+
const RequestSchema = new db.mongoose.Schema({
|
|
3
|
+
visitor: {
|
|
4
|
+
type: db.mongoose.Schema.Types.ObjectId,
|
|
5
|
+
ref: 'Visitor',
|
|
6
|
+
},
|
|
7
|
+
target: {
|
|
8
|
+
type: db.mongoose.Schema.Types.ObjectId,
|
|
9
|
+
ref: 'User',
|
|
10
|
+
default: null,
|
|
11
|
+
},
|
|
12
|
+
session: {
|
|
13
|
+
type: db.mongoose.Schema.Types.ObjectId,
|
|
14
|
+
ref: 'Session',
|
|
15
|
+
default: null,
|
|
16
|
+
},
|
|
17
|
+
path: String,
|
|
18
|
+
method: String,
|
|
19
|
+
referer: String,
|
|
20
|
+
query: String,
|
|
21
|
+
timestamp: { type: Date, default: Date.now },
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
RequestSchema.index({ visitor: 1 });
|
|
25
|
+
RequestSchema.index({ target: 1 }, { sparse: true });
|
|
26
|
+
RequestSchema.index({ timestamp: -1 });
|
|
27
|
+
|
|
28
|
+
const Request = db.mongoose.models.Request || db.mongoose.model('Request', RequestSchema);
|
|
29
|
+
return Request;
|
|
30
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export default db => {
|
|
2
|
+
const SessionSchema = new db.mongoose.Schema(
|
|
3
|
+
{
|
|
4
|
+
target: {
|
|
5
|
+
type: db.mongoose.Schema.Types.ObjectId,
|
|
6
|
+
ref: 'User',
|
|
7
|
+
required: true,
|
|
8
|
+
},
|
|
9
|
+
visitor: {
|
|
10
|
+
type: db.mongoose.Schema.Types.ObjectId,
|
|
11
|
+
ref: 'Visitor',
|
|
12
|
+
default: null,
|
|
13
|
+
},
|
|
14
|
+
isActive: {
|
|
15
|
+
type: Boolean,
|
|
16
|
+
default: true,
|
|
17
|
+
},
|
|
18
|
+
ip: String,
|
|
19
|
+
userAgent: String,
|
|
20
|
+
lastSeenAt: {
|
|
21
|
+
type: Date,
|
|
22
|
+
default: Date.now,
|
|
23
|
+
},
|
|
24
|
+
revokedAt: {
|
|
25
|
+
type: Date,
|
|
26
|
+
default: null,
|
|
27
|
+
},
|
|
28
|
+
expiresAt: {
|
|
29
|
+
type: Date,
|
|
30
|
+
required: true,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
timestamps: true,
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
SessionSchema.index({ target: 1, isActive: 1 });
|
|
39
|
+
SessionSchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
40
|
+
|
|
41
|
+
const Session = db.mongoose.models.Session || db.mongoose.model('Session', SessionSchema);
|
|
42
|
+
return Session;
|
|
43
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export default db => {
|
|
2
|
+
const VisitorSchema = new db.mongoose.Schema(
|
|
3
|
+
{
|
|
4
|
+
ip: String,
|
|
5
|
+
userAgent: String,
|
|
6
|
+
acceptLanguage: String,
|
|
7
|
+
fingerprint: { type: String, unique: true },
|
|
8
|
+
target: {
|
|
9
|
+
type: db.mongoose.Schema.Types.ObjectId,
|
|
10
|
+
ref: 'User',
|
|
11
|
+
default: null,
|
|
12
|
+
},
|
|
13
|
+
linkedAt: {
|
|
14
|
+
type: Date,
|
|
15
|
+
default: null,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
timestamps: true,
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
// fingerprint index created by unique: true
|
|
24
|
+
VisitorSchema.index({ target: 1 }, { sparse: true });
|
|
25
|
+
|
|
26
|
+
const Visitor = db.mongoose.models.Visitor || db.mongoose.model('Visitor', VisitorSchema);
|
|
27
|
+
return Visitor;
|
|
28
|
+
};
|