@ozdao/martyrs 0.2.564 → 0.2.566

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (366) hide show
  1. package/dist/abac-BPl9Bmf9.js +1527 -0
  2. package/dist/builder.js +51 -39
  3. package/dist/{common.schema-GFSlNJo7.js → common.schema-DswiUXKB.js} +1 -1
  4. package/dist/community.server.js +48 -9
  5. package/dist/core.server.js +6 -4
  6. package/dist/{crud-C7FSTUes.js → crud-q1ye5IhV.js} +7 -7
  7. package/dist/events.server.js +3 -3
  8. package/dist/gallery.server.js +2 -2
  9. package/dist/inventory.server.js +4 -6
  10. package/dist/{main-CmjWiDVF.js → main-B9o1iBAZ.js} +1279 -1287
  11. package/dist/marketplace.server.js +1 -1
  12. package/dist/martyrs/dist/main-B9o1iBAZ.js +943 -0
  13. package/dist/martyrs/dist/main-B9o1iBAZ.js.map +1 -0
  14. package/dist/martyrs/dist/web-BF3ijvEr.js +55 -0
  15. package/dist/martyrs/dist/web-BF3ijvEr.js.map +1 -0
  16. package/dist/martyrs/src/components/BottomSheet/BottomSheet.vue.js +96 -0
  17. package/dist/martyrs/src/components/BottomSheet/BottomSheet.vue.js.map +1 -0
  18. package/dist/martyrs/src/components/Button/{Button.vue.js → Button.vue2.js} +36 -45
  19. package/dist/martyrs/src/components/Button/Button.vue2.js.map +1 -0
  20. package/dist/martyrs/src/components/Feed/Carousel.vue.js +1 -1
  21. package/dist/martyrs/src/components/Feed/Feed.vue.js +1 -1
  22. package/dist/martyrs/src/components/Field/{Field.vue2.js → Field.vue.js} +2 -2
  23. package/dist/martyrs/src/components/Field/Field.vue.js.map +1 -0
  24. package/dist/martyrs/src/components/FieldBig/FieldBig.vue.js +2 -2
  25. package/dist/martyrs/src/components/FieldPhone/FieldPhone.vue.js +1 -1
  26. package/dist/martyrs/src/components/FieldPhone/FieldPhone.vue.js.map +1 -1
  27. package/dist/martyrs/src/components/Loader/{Loader.vue2.js → Loader.vue.js} +3 -4
  28. package/dist/martyrs/src/components/Loader/Loader.vue.js.map +1 -0
  29. package/dist/martyrs/src/components/LocationMarker/LocationMarker.vue.js +1 -1
  30. package/dist/martyrs/src/components/Media/Media.vue.js +1 -1
  31. package/dist/martyrs/src/components/Menu/{Menu.vue.js → Menu.vue2.js} +2 -2
  32. package/dist/martyrs/src/components/Menu/Menu.vue2.js.map +1 -0
  33. package/dist/martyrs/src/components/Select/{Select.vue2.js → Select.vue.js} +2 -2
  34. package/dist/martyrs/src/components/Select/Select.vue.js.map +1 -0
  35. package/dist/martyrs/src/components/SelectMulti/{SelectMulti.vue.js → SelectMulti.vue2.js} +2 -2
  36. package/dist/martyrs/src/components/SelectMulti/SelectMulti.vue2.js.map +1 -0
  37. package/dist/martyrs/src/components/Tree/Tree.vue.js +6 -3
  38. package/dist/martyrs/src/components/Tree/Tree.vue.js.map +1 -1
  39. package/dist/martyrs/src/components/UploadImage/UploadImage.vue.js +1 -1
  40. package/dist/martyrs/src/components/UploadImageMultiple/UploadImageMultiple.vue.js +1 -1
  41. package/dist/martyrs/src/modules/auth/auth.client.js +10 -7
  42. package/dist/martyrs/src/modules/auth/auth.client.js.map +1 -1
  43. package/dist/martyrs/src/modules/auth/views/components/pages/EnterCode.vue.js +1 -1
  44. package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +2 -2
  45. package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +2 -2
  46. package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +3 -3
  47. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEdit.vue.js +1 -1
  48. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditAccount.vue.js +1 -1
  49. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditProfile.vue.js +2 -2
  50. package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +2 -2
  51. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +13 -13
  52. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js.map +1 -1
  53. package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +2 -2
  54. package/dist/martyrs/src/modules/auth/views/components/sections/ProfileEditCredentials.vue.js +2 -2
  55. package/dist/martyrs/src/modules/auth/views/router/auth.router.js +116 -0
  56. package/dist/martyrs/src/modules/auth/views/router/auth.router.js.map +1 -0
  57. package/dist/martyrs/src/modules/auth/views/router/users.router.js +180 -0
  58. package/dist/martyrs/src/modules/auth/views/router/users.router.js.map +1 -0
  59. package/dist/martyrs/src/modules/backoffice/components/partials/Sidebar.vue.js +4 -4
  60. package/dist/martyrs/src/modules/backoffice/components/partials/Sidebar.vue.js.map +1 -1
  61. package/dist/martyrs/src/modules/community/components/layouts/Community.vue.js +1 -1
  62. package/dist/martyrs/src/modules/community/components/pages/BlogPost.vue.js +2 -2
  63. package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.js +2 -2
  64. package/dist/martyrs/src/modules/constructor/components/elements/Card.vue.js +1 -1
  65. package/dist/martyrs/src/modules/constructor/components/elements/Embed.vue.js +1 -1
  66. package/dist/martyrs/src/modules/core/locales/en.js +45 -0
  67. package/dist/martyrs/src/modules/core/locales/en.js.map +1 -1
  68. package/dist/martyrs/src/modules/core/locales/ru.js +45 -0
  69. package/dist/martyrs/src/modules/core/locales/ru.js.map +1 -1
  70. package/dist/martyrs/src/modules/core/views/classes/i18n.manager.js +9 -0
  71. package/dist/martyrs/src/modules/core/views/classes/i18n.manager.js.map +1 -1
  72. package/dist/martyrs/src/modules/core/views/components/blocks/BlockSearch.vue.js +1 -1
  73. package/dist/martyrs/src/modules/core/views/components/blocks/CardHeader.vue.js +1 -1
  74. package/dist/martyrs/src/modules/core/views/components/blocks/PopupAuth.vue.js +1 -1
  75. package/dist/martyrs/src/modules/core/views/components/blocks/PopupDateSelector.vue.js +2 -2
  76. package/dist/martyrs/src/modules/core/views/components/layouts/App.vue.js +1 -1
  77. package/dist/martyrs/src/modules/core/views/components/layouts/Client.vue.js +3 -2
  78. package/dist/martyrs/src/modules/core/views/components/layouts/Client.vue.js.map +1 -1
  79. package/dist/martyrs/src/modules/core/views/components/partials/Header.vue.js +2 -2
  80. package/dist/martyrs/src/modules/core/views/components/partials/NavigationBar.vue.js +1 -1
  81. package/dist/martyrs/src/modules/core/views/components/sections/Walkthrough.vue.js +1 -1
  82. package/dist/martyrs/src/modules/core/views/components/sections/filters/FilterRange.vue.js +1 -1
  83. package/dist/martyrs/src/modules/core/views/mixins/mixins.js +1 -2
  84. package/dist/martyrs/src/modules/core/views/mixins/mixins.js.map +1 -1
  85. package/dist/martyrs/src/modules/core/views/router/addRoutes.js +6 -1
  86. package/dist/martyrs/src/modules/core/views/router/addRoutes.js.map +1 -1
  87. package/dist/martyrs/src/modules/events/components/elements/ButtonCheck.vue.js +2 -2
  88. package/dist/martyrs/src/modules/events/components/elements/ButtonJoin.vue.js +1 -1
  89. package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +4 -4
  90. package/dist/martyrs/src/modules/events/components/pages/EditEventTickets.vue.js +2 -2
  91. package/dist/martyrs/src/modules/events/components/pages/Event.vue.js +2 -2
  92. package/dist/martyrs/src/modules/events/components/sections/EditTickets.vue.js +2 -2
  93. package/dist/martyrs/src/modules/events/components/sections/Feed.vue.js +1 -1
  94. package/dist/martyrs/src/modules/events/components/sections/List.vue.js +1 -1
  95. package/dist/martyrs/src/modules/events/events.client.js +15 -12
  96. package/dist/martyrs/src/modules/events/events.client.js.map +1 -1
  97. package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.js +4 -4
  98. package/dist/martyrs/src/modules/inventory/components/forms/AdjustmentForm.vue.js +3 -3
  99. package/dist/martyrs/src/modules/inventory/components/forms/ColumnSettingsMenu.vue.js +1 -1
  100. package/dist/martyrs/src/modules/inventory/components/forms/HistoryView.vue.js +1 -1
  101. package/dist/martyrs/src/modules/inventory/components/forms/StockAlertsForm.vue.js +3 -3
  102. package/dist/martyrs/src/modules/inventory/components/pages/InventoryEdit.vue.js +5 -5
  103. package/dist/martyrs/src/modules/inventory/components/pages/InventoryEdit.vue.js.map +1 -1
  104. package/dist/martyrs/src/modules/marketplace/views/components/pages/Marketplace.vue.js +1 -1
  105. package/dist/martyrs/src/modules/marketplace/views/components/sections/SectionMenu.vue.js +1 -1
  106. package/dist/martyrs/src/modules/music/components/blocks/ActionButtons.vue.js +95 -0
  107. package/dist/martyrs/src/modules/music/components/blocks/ActionButtons.vue.js.map +1 -0
  108. package/dist/martyrs/src/modules/music/components/cards/AlbumCard.vue.js +6 -3
  109. package/dist/martyrs/src/modules/music/components/cards/AlbumCard.vue.js.map +1 -1
  110. package/dist/martyrs/src/modules/music/components/cards/ArtistCardSmall.vue.js +25 -25
  111. package/dist/martyrs/src/modules/music/components/cards/ArtistCardSmall.vue.js.map +1 -1
  112. package/dist/martyrs/src/modules/music/components/cards/PlaylistCard.vue.js +1 -1
  113. package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.js +1 -1
  114. package/dist/martyrs/src/modules/music/components/forms/AlbumForm.vue.js +3 -3
  115. package/dist/martyrs/src/modules/music/components/forms/ArtistForm.vue.js +4 -4
  116. package/dist/martyrs/src/modules/music/components/forms/PlaylistForm.vue.js +2 -2
  117. package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.js +1 -1
  118. package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.js +3 -3
  119. package/dist/martyrs/src/modules/music/components/layouts/MusicBottomPlayer.vue.js +31 -6
  120. package/dist/martyrs/src/modules/music/components/layouts/MusicBottomPlayer.vue.js.map +1 -1
  121. package/dist/martyrs/src/modules/music/components/pages/Album.vue.js +121 -206
  122. package/dist/martyrs/src/modules/music/components/pages/Album.vue.js.map +1 -1
  123. package/dist/martyrs/src/modules/music/components/pages/Artist.vue.js +2 -2
  124. package/dist/martyrs/src/modules/music/components/pages/MusicHome.vue.js +9 -13
  125. package/dist/martyrs/src/modules/music/components/pages/MusicHome.vue.js.map +1 -1
  126. package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.js +1 -1
  127. package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.js +167 -246
  128. package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.js.map +1 -1
  129. package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.js +2 -2
  130. package/dist/martyrs/src/modules/music/components/pages/Track.vue.js +136 -221
  131. package/dist/martyrs/src/modules/music/components/pages/Track.vue.js.map +1 -1
  132. package/dist/martyrs/src/modules/music/components/pages/TrackCreate.vue.js +1 -1
  133. package/dist/martyrs/src/modules/music/components/player/FullscreenPlayer.vue.js +171 -0
  134. package/dist/martyrs/src/modules/music/components/player/FullscreenPlayer.vue.js.map +1 -0
  135. package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.js +32 -154
  136. package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.js.map +1 -1
  137. package/dist/martyrs/src/modules/music/components/player/PlayerControls.vue.js +96 -0
  138. package/dist/martyrs/src/modules/music/components/player/PlayerControls.vue.js.map +1 -0
  139. package/dist/martyrs/src/modules/music/components/player/VolumeControl.vue.js +55 -27
  140. package/dist/martyrs/src/modules/music/components/player/VolumeControl.vue.js.map +1 -1
  141. package/dist/martyrs/src/modules/music/components/player/tonar.png.js +5 -0
  142. package/dist/martyrs/src/modules/music/components/player/tonar.png.js.map +1 -0
  143. package/dist/martyrs/src/modules/music/store/albums.js +8 -2
  144. package/dist/martyrs/src/modules/music/store/albums.js.map +1 -1
  145. package/dist/martyrs/src/modules/music/store/player.js +83 -65
  146. package/dist/martyrs/src/modules/music/store/player.js.map +1 -1
  147. package/dist/martyrs/src/modules/music/store/tracks.js +4 -13
  148. package/dist/martyrs/src/modules/music/store/tracks.js.map +1 -1
  149. package/dist/martyrs/src/modules/notifications/components/elements/NotificationBadge.vue.js +4 -4
  150. package/dist/martyrs/src/modules/notifications/components/elements/NotificationBadge.vue.js.map +1 -1
  151. package/dist/martyrs/src/modules/notifications/notifications.client.js +2 -2
  152. package/dist/martyrs/src/modules/orders/components/elements/FieldSubscribeNewsletter.vue.js +3 -0
  153. package/dist/martyrs/src/modules/orders/components/elements/FieldSubscribeNewsletter.vue.js.map +1 -1
  154. package/dist/martyrs/src/modules/orders/components/forms/FormApplicationDetails.vue.js +3 -3
  155. package/dist/martyrs/src/modules/orders/components/forms/FormCustomerDetails.vue.js +3 -3
  156. package/dist/martyrs/src/modules/orders/components/forms/FormSelectCustomer.vue.js +2 -2
  157. package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.js +2 -2
  158. package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.js +1 -1
  159. package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +2 -2
  160. package/dist/martyrs/src/modules/orders/components/sections/ApplicationDetails.vue.js +1 -1
  161. package/dist/martyrs/src/modules/orders/components/sections/CustomerDetails.vue.js +1 -1
  162. package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js +2 -2
  163. package/dist/martyrs/src/modules/orders/components/sections/FormPayment.vue.js +1 -1
  164. package/dist/martyrs/src/modules/organizations/components/blocks/CardOrganization.vue.js +1 -1
  165. package/dist/martyrs/src/modules/organizations/components/blocks/CardOrganization.vue.js.map +1 -1
  166. package/dist/martyrs/src/modules/organizations/components/elements/ButtonToggleMembership.vue.js +1 -1
  167. package/dist/martyrs/src/modules/organizations/components/forms/AddExistingMembersForm.vue.js +1 -1
  168. package/dist/martyrs/src/modules/organizations/components/forms/DepartmentForm.vue.js +2 -2
  169. package/dist/martyrs/src/modules/organizations/components/forms/InviteForm.vue.js +2 -2
  170. package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js +1 -1
  171. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.js +2 -2
  172. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +5 -5
  173. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js.map +1 -1
  174. package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.js +3 -3
  175. package/dist/martyrs/src/modules/organizations/components/sections/MembersAdd.vue.js +3 -3
  176. package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +3 -3
  177. package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.js +2 -2
  178. package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.js +2 -2
  179. package/dist/martyrs/src/modules/pages/views/components/partials/SidebarPages.vue.js +1 -1
  180. package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.js +1 -1
  181. package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.js.map +1 -1
  182. package/dist/martyrs/src/modules/products/components/blocks/CardProduct.vue.js +15 -2
  183. package/dist/martyrs/src/modules/products/components/blocks/CardProduct.vue.js.map +1 -1
  184. package/dist/martyrs/src/modules/products/components/elements/Image360.vue.js +1 -1
  185. package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js +10 -7
  186. package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js.map +1 -1
  187. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +7 -6
  188. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js.map +1 -1
  189. package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +11 -2
  190. package/dist/martyrs/src/modules/products/components/pages/Product.vue.js.map +1 -1
  191. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +4 -4
  192. package/dist/martyrs/src/modules/products/components/pages/ProductRecommmendation.vue.js +1 -1
  193. package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +1 -1
  194. package/dist/martyrs/src/modules/products/components/sections/EditAttributes.vue.js +2 -2
  195. package/dist/martyrs/src/modules/products/components/sections/EditDiscounts.vue.js +3 -3
  196. package/dist/martyrs/src/modules/products/components/sections/EditVariants.vue.js +3 -3
  197. package/dist/martyrs/src/modules/products/components/sections/ProductConfigurator.vue.js +1 -1
  198. package/dist/martyrs/src/modules/products/components/sections/ProductsRecommended.vue.js +1 -1
  199. package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js +11 -8
  200. package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js.map +1 -1
  201. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.js +1 -1
  202. package/dist/martyrs/src/modules/rents/views/components/pages/RentsEdit.vue.js +211 -61
  203. package/dist/martyrs/src/modules/rents/views/components/pages/RentsEdit.vue.js.map +1 -1
  204. package/dist/martyrs/src/modules/reports/components/sections/FormReport.vue.js +2 -2
  205. package/dist/martyrs/src/modules/spots/components/blocks/SpotMemberModify.vue.js +2 -2
  206. package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.js +1 -1
  207. package/dist/martyrs/src/modules/spots/components/pages/Map.vue.js +4 -4
  208. package/dist/martyrs/src/modules/spots/components/pages/Map.vue.js.map +1 -1
  209. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +3 -3
  210. package/dist/martyrs/src/modules/spots/components/sections/WorktimeEdit.vue.js +3 -3
  211. package/dist/martyrs/src/modules/wallet/views/components/blocks/CardDeposit.vue.js +1 -1
  212. package/dist/martyrs/src/modules/wallet/views/components/blocks/CryptoDeposit.vue.js +2 -2
  213. package/dist/martyrs/src/modules/wallet/views/components/pages/Wallet.vue.js +2 -2
  214. package/dist/martyrs.css +1 -1
  215. package/dist/martyrs.es.js +1 -1
  216. package/dist/music.server.js +44 -18
  217. package/dist/node_modules/.pnpm/{@capacitor-mlkit_barcode-scanning@7.1.0_@capacitor_core@7.0.1 → @capacitor-mlkit_barcode-scanning@7.3.0_@capacitor_core@7.4.4}/node_modules/@capacitor-mlkit/barcode-scanning/dist/esm/definitions.js +1 -0
  218. package/dist/node_modules/.pnpm/@capacitor-mlkit_barcode-scanning@7.3.0_@capacitor_core@7.4.4/node_modules/@capacitor-mlkit/barcode-scanning/dist/esm/definitions.js.map +1 -0
  219. package/dist/node_modules/.pnpm/{@capacitor-mlkit_barcode-scanning@7.1.0_@capacitor_core@7.0.1 → @capacitor-mlkit_barcode-scanning@7.3.0_@capacitor_core@7.4.4}/node_modules/@capacitor-mlkit/barcode-scanning/dist/esm/index.js +1 -1
  220. package/dist/node_modules/.pnpm/{@capacitor-mlkit_barcode-scanning@7.1.0_@capacitor_core@7.0.1 → @capacitor-mlkit_barcode-scanning@7.3.0_@capacitor_core@7.4.4}/node_modules/@capacitor-mlkit/barcode-scanning/dist/esm/index.js.map +1 -1
  221. package/dist/node_modules/.pnpm/{@capacitor-mlkit_barcode-scanning@7.1.0_@capacitor_core@7.0.1 → @capacitor-mlkit_barcode-scanning@7.3.0_@capacitor_core@7.4.4}/node_modules/@capacitor-mlkit/barcode-scanning/dist/esm/web.js +16 -1
  222. package/dist/node_modules/.pnpm/@capacitor-mlkit_barcode-scanning@7.3.0_@capacitor_core@7.4.4/node_modules/@capacitor-mlkit/barcode-scanning/dist/esm/web.js.map +1 -0
  223. package/dist/node_modules/.pnpm/{@capacitor_core@7.0.1 → @capacitor_core@7.4.4}/node_modules/@capacitor/core/dist/index.js +2 -1
  224. package/dist/node_modules/.pnpm/@capacitor_core@7.4.4/node_modules/@capacitor/core/dist/index.js.map +1 -0
  225. package/dist/node_modules/.pnpm/{@capacitor_device@7.0.0_@capacitor_core@7.0.1 → @capacitor_device@7.0.1_@capacitor_core@7.4.4}/node_modules/@capacitor/device/dist/esm/index.js +1 -1
  226. package/dist/node_modules/.pnpm/{@capacitor_device@7.0.0_@capacitor_core@7.0.1 → @capacitor_device@7.0.1_@capacitor_core@7.4.4}/node_modules/@capacitor/device/dist/esm/index.js.map +1 -1
  227. package/dist/node_modules/.pnpm/{@capacitor_device@7.0.0_@capacitor_core@7.0.1 → @capacitor_device@7.0.1_@capacitor_core@7.4.4}/node_modules/@capacitor/device/dist/esm/web.js +1 -1
  228. package/dist/node_modules/.pnpm/{@capacitor_device@7.0.0_@capacitor_core@7.0.1 → @capacitor_device@7.0.1_@capacitor_core@7.4.4}/node_modules/@capacitor/device/dist/esm/web.js.map +1 -1
  229. package/dist/node_modules/.pnpm/{@capacitor_keyboard@7.0.0_@capacitor_core@7.0.1 → @capacitor_keyboard@7.0.1_@capacitor_core@7.4.4}/node_modules/@capacitor/keyboard/dist/esm/definitions.js.map +1 -1
  230. package/dist/node_modules/.pnpm/{@capacitor_keyboard@7.0.0_@capacitor_core@7.0.1 → @capacitor_keyboard@7.0.1_@capacitor_core@7.4.4}/node_modules/@capacitor/keyboard/dist/esm/index.js +1 -1
  231. package/dist/node_modules/.pnpm/{@capacitor_keyboard@7.0.0_@capacitor_core@7.0.1 → @capacitor_keyboard@7.0.1_@capacitor_core@7.4.4}/node_modules/@capacitor/keyboard/dist/esm/index.js.map +1 -1
  232. package/dist/node_modules/.pnpm/{@capacitor_push-notifications@7.0.0_@capacitor_core@7.0.1 → @capacitor_push-notifications@7.0.3_@capacitor_core@7.4.4}/node_modules/@capacitor/push-notifications/dist/esm/index.js +1 -1
  233. package/dist/node_modules/.pnpm/{@capacitor_push-notifications@7.0.0_@capacitor_core@7.0.1 → @capacitor_push-notifications@7.0.3_@capacitor_core@7.4.4}/node_modules/@capacitor/push-notifications/dist/esm/index.js.map +1 -1
  234. package/dist/node_modules/.pnpm/{capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.0.1 → capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.4.4}/node_modules/capacitor-plugin-app-tracking-transparency/dist/esm/index.js +1 -1
  235. package/dist/node_modules/.pnpm/{capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.0.1 → capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.4.4}/node_modules/capacitor-plugin-app-tracking-transparency/dist/esm/index.js.map +1 -1
  236. package/dist/node_modules/.pnpm/{capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.0.1 → capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.4.4}/node_modules/capacitor-plugin-app-tracking-transparency/dist/esm/web.js +1 -1
  237. package/dist/node_modules/.pnpm/{capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.0.1 → capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.4.4}/node_modules/capacitor-plugin-app-tracking-transparency/dist/esm/web.js.map +1 -1
  238. package/dist/notifications.server.js +0 -3
  239. package/dist/orders.server.js +5 -6
  240. package/dist/organizations.server.js +9 -10
  241. package/dist/products.server.js +27 -26
  242. package/dist/{queryProcessor-CBQgZycY.js → queryProcessor-C_5Iipam.js} +4 -1
  243. package/dist/rents.server.js +2 -3
  244. package/dist/spots.server.js +1 -1
  245. package/dist/style.css +252 -161
  246. package/dist/{web-cNKIl_cL.js → web-BF3ijvEr.js} +1 -1
  247. package/package.json +1 -1
  248. package/src/builder/modes/ssr.rspack.dev.js +4 -3
  249. package/src/builder/rspack/rspack.config.api.js +15 -4
  250. package/src/builder/rspack/rspack.config.base.js +3 -3
  251. package/src/builder/rspack/rspack.config.ssr.client.js +28 -28
  252. package/src/builder/templates/page.js +2 -2
  253. package/src/components/BottomSheet/BottomSheet.vue +4 -4
  254. package/src/components/Button/Button.vue +50 -37
  255. package/src/components/FieldPhone/FieldPhone.vue +1 -1
  256. package/src/components/Loader/Loader.vue +1 -1
  257. package/src/components/Tree/Tree.vue +6 -3
  258. package/src/modules/LAYOUT.MD +767 -0
  259. package/src/modules/PROCESS.md +0 -0
  260. package/src/modules/TASKS.MD +17 -0
  261. package/src/modules/auth/auth.client.js +11 -7
  262. package/src/modules/auth/views/components/pages/SignIn.vue +1 -1
  263. package/src/modules/auth/views/router/auth.router.js +94 -0
  264. package/src/modules/auth/views/router/users.router.js +153 -0
  265. package/src/modules/backoffice/components/partials/Sidebar.vue +7 -7
  266. package/src/modules/community/community.server.js +8 -0
  267. package/src/modules/community/policies/blog.policies.js +55 -0
  268. package/src/modules/community/routes/blog.routes.js +1 -1
  269. package/src/modules/community/routes/comments.routes.js +1 -1
  270. package/src/modules/community/routes/reactions.routes.js +1 -4
  271. package/src/modules/core/controllers/classes/abac/abac.adapter.express.js +206 -124
  272. package/src/modules/core/controllers/classes/abac/abac.adapter.ws.js +203 -50
  273. package/src/modules/core/controllers/classes/abac/abac.core.js +127 -36
  274. package/src/modules/core/controllers/classes/abac/abac.fields.js +144 -179
  275. package/src/modules/core/controllers/classes/abac/abac.js +201 -10
  276. package/src/modules/core/controllers/classes/abac/abac.policies.js +147 -57
  277. package/src/modules/core/controllers/classes/crud/crud.policies.js +5 -5
  278. package/src/modules/core/controllers/policies/core.policies.js +5 -2
  279. package/src/modules/core/controllers/utils/queryProcessor.js +4 -1
  280. package/src/modules/core/core.server.js +1 -0
  281. package/src/modules/core/locales/en.js +45 -0
  282. package/src/modules/core/locales/ru.js +45 -0
  283. package/src/modules/core/models/schemas/common.schema.js +1 -1
  284. package/src/modules/core/views/classes/i18n.manager.js +13 -0
  285. package/src/modules/core/views/components/layouts/Client.vue +1 -1
  286. package/src/modules/core/views/components/sections/filters/FilterPrice.vue +81 -0
  287. package/src/modules/core/views/mixins/mixins.js +1 -2
  288. package/src/modules/core/views/router/addRoutes.js +6 -1
  289. package/src/modules/events/events.client.js +3 -0
  290. package/src/modules/events/routes/events.routes.js +1 -1
  291. package/src/modules/inventory/components/pages/InventoryEdit.vue +3 -3
  292. package/src/modules/inventory/policies/inventory.policies.js +1 -1
  293. package/src/modules/inventory/routes/inventory.routes.js +1 -1
  294. package/src/modules/marketplace/marketplace.router.js +66 -0
  295. package/src/modules/marketplace/views/components/layouts/Marketplace.vue +363 -0
  296. package/src/modules/marketplace/views/components/pages/Catalog.vue +73 -0
  297. package/src/modules/music/components/blocks/ActionButtons.vue +74 -0
  298. package/src/modules/music/components/cards/AlbumCard.vue +1 -1
  299. package/src/modules/music/components/cards/ArtistCardSmall.vue +8 -6
  300. package/src/modules/music/components/layouts/MusicBottomPlayer.vue +94 -4
  301. package/src/modules/music/components/pages/Album.vue +55 -67
  302. package/src/modules/music/components/pages/MusicHome.vue +4 -6
  303. package/src/modules/music/components/pages/Playlist.vue +61 -70
  304. package/src/modules/music/components/pages/Track.vue +54 -71
  305. package/src/modules/music/components/player/FullscreenPlayer.vue +248 -0
  306. package/src/modules/music/components/player/MusicPlayer.vue +21 -216
  307. package/src/modules/music/components/player/PlayerControls.vue +112 -0
  308. package/src/modules/music/components/player/Visualizer.vue +151 -0
  309. package/src/modules/music/components/player/VolumeControl.vue +75 -23
  310. package/src/modules/music/components/player/tonar.png +0 -0
  311. package/src/modules/music/controllers/stream.controller.js +1 -1
  312. package/src/modules/music/music.server.js +1 -1
  313. package/src/modules/music/policies/music.policies.js +3 -2
  314. package/src/modules/music/router/library.router.js +26 -0
  315. package/src/modules/music/router/music.router.js +176 -0
  316. package/src/modules/music/routes/albums.routes.js +13 -12
  317. package/src/modules/music/routes/tracks.routes.js +39 -0
  318. package/src/modules/music/store/albums.js +10 -2
  319. package/src/modules/music/store/player.js +101 -89
  320. package/src/modules/music/store/tracks.js +5 -21
  321. package/src/modules/notifications/components/elements/NotificationBadge.vue +5 -6
  322. package/src/modules/notifications/notifications.server.js +1 -3
  323. package/src/modules/orders/components/elements/FieldSubscribeNewsletter.vue +5 -0
  324. package/src/modules/orders/orders.server.js +0 -1
  325. package/src/modules/organizations/components/blocks/CardOrganization.vue +2 -2
  326. package/src/modules/organizations/components/pages/DepartmentEdit.vue +2 -2
  327. package/src/modules/organizations/components/pages/OrganizationEdit.vue +2 -2
  328. package/src/modules/organizations/policies/organizations.policies.js +12 -6
  329. package/src/modules/organizations/routes/organizations.routes.js +1 -3
  330. package/src/modules/products/components/blocks/CardCategory.vue +1 -1
  331. package/src/modules/products/components/blocks/CardProduct.vue +16 -2
  332. package/src/modules/products/components/pages/Categories.vue +9 -6
  333. package/src/modules/products/components/pages/CategoryEdit.vue +8 -4
  334. package/src/modules/products/components/pages/Product.vue +11 -5
  335. package/src/modules/products/components/sections/SectionProduct.vue +11 -7
  336. package/src/modules/products/controllers/categories.controller.js +32 -27
  337. package/src/modules/products/routes/categories.routes.js +1 -1
  338. package/src/modules/rents/controllers/routes/rents.routes.js +1 -1
  339. package/src/modules/rents/views/components/pages/RentsEdit.vue +208 -49
  340. package/src/modules/spots/components/pages/Map.vue +2 -2
  341. package/src/styles/config.scss +6 -6
  342. package/dist/abac-DYoheWuc.js +0 -1031
  343. package/dist/core.abac-DUPBnlk6.js +0 -298
  344. package/dist/core.logger-C3q8A9dl.js +0 -51
  345. package/dist/martyrs/src/components/Button/Button.vue.js.map +0 -1
  346. package/dist/martyrs/src/components/Field/Field.vue2.js.map +0 -1
  347. package/dist/martyrs/src/components/Loader/Loader.vue2.js.map +0 -1
  348. package/dist/martyrs/src/components/Menu/Menu.vue.js.map +0 -1
  349. package/dist/martyrs/src/components/Select/Select.vue2.js.map +0 -1
  350. package/dist/martyrs/src/components/SelectMulti/SelectMulti.vue.js.map +0 -1
  351. package/dist/martyrs/src/modules/auth/auth.router.js +0 -342
  352. package/dist/martyrs/src/modules/auth/auth.router.js.map +0 -1
  353. package/dist/node_modules/.pnpm/@capacitor-mlkit_barcode-scanning@7.1.0_@capacitor_core@7.0.1/node_modules/@capacitor-mlkit/barcode-scanning/dist/esm/definitions.js.map +0 -1
  354. package/dist/node_modules/.pnpm/@capacitor-mlkit_barcode-scanning@7.1.0_@capacitor_core@7.0.1/node_modules/@capacitor-mlkit/barcode-scanning/dist/esm/web.js.map +0 -1
  355. package/dist/node_modules/.pnpm/@capacitor_core@7.0.1/node_modules/@capacitor/core/dist/index.js.map +0 -1
  356. package/src/modules/auth/auth.router.js +0 -262
  357. package/src/modules/core/controllers/classes/abac/v2/abac-core-fixed.js +0 -313
  358. package/src/modules/core/controllers/classes/abac/v2/abac-express-fixed.js +0 -276
  359. package/src/modules/core/controllers/classes/abac/v2/abac-fields-fixed.js +0 -425
  360. package/src/modules/core/controllers/classes/abac/v2/abac-main-fixed.js +0 -295
  361. package/src/modules/core/controllers/classes/abac/v2/abac-policies-fixed.js +0 -316
  362. package/src/modules/core/controllers/classes/abac/v2/abac-ws-fixed.js +0 -237
  363. package/src/modules/core/controllers/classes/core.abac.js +0 -310
  364. package/src/modules/core/controllers/classes/core.crud.js +0 -89
  365. package/src/modules/governance/reactcode/eslint.config.js +0 -28
  366. /package/dist/node_modules/.pnpm/{@capacitor_keyboard@7.0.0_@capacitor_core@7.0.1 → @capacitor_keyboard@7.0.1_@capacitor_core@7.4.4}/node_modules/@capacitor/keyboard/dist/esm/definitions.js +0 -0
@@ -0,0 +1,1527 @@
1
+ import { C as CacheNamespaced } from "./core.cache-DALYFDdy.js";
2
+ import set from "lodash/set.js";
3
+ import get from "lodash/get.js";
4
+ import unset from "lodash/unset.js";
5
+ import cloneDeep from "lodash/cloneDeep.js";
6
+ class Logger {
7
+ constructor(db) {
8
+ this.LogModel = db.log;
9
+ }
10
+ async log(level, message) {
11
+ const logEntry = new this.LogModel({
12
+ level,
13
+ message
14
+ });
15
+ try {
16
+ await logEntry.save();
17
+ console.info(`Logged: ${level} - ${message}`);
18
+ } catch (err) {
19
+ console.error("Logging error:", err);
20
+ }
21
+ }
22
+ async info(message) {
23
+ await this.log("info", message);
24
+ }
25
+ async error(message) {
26
+ await this.log("error", message);
27
+ }
28
+ }
29
+ const instances = /* @__PURE__ */ new Map();
30
+ class LoggerNamespaced {
31
+ constructor(namespaceOrDb, db) {
32
+ if (!db && namespaceOrDb && typeof namespaceOrDb === "object") {
33
+ const namespace2 = "global";
34
+ if (instances.has(namespace2)) {
35
+ return instances.get(namespace2);
36
+ }
37
+ const instance3 = new Logger(namespaceOrDb);
38
+ instances.set(namespace2, instance3);
39
+ return instance3;
40
+ }
41
+ const namespace = namespaceOrDb;
42
+ if (instances.has(namespace)) {
43
+ return instances.get(namespace);
44
+ }
45
+ const instance2 = new Logger(db);
46
+ instances.set(namespace, instance2);
47
+ return instance2;
48
+ }
49
+ // Статический метод для получения всех namespace'ов
50
+ static getNamespaces() {
51
+ return Array.from(instances.keys());
52
+ }
53
+ }
54
+ class ABACCore {
55
+ constructor(abac) {
56
+ this.abac = abac;
57
+ this.runningPolicies = /* @__PURE__ */ new Map();
58
+ }
59
+ /**
60
+ * Нормализация контекста
61
+ */
62
+ normalizeContext(input) {
63
+ const context = {
64
+ user: null,
65
+ action: null,
66
+ resource: null,
67
+ currentResource: null,
68
+ resourceId: null,
69
+ // Добавляем ID ресурса для кэша
70
+ data: {},
71
+ req: null,
72
+ socket: null,
73
+ params: {},
74
+ _cache: /* @__PURE__ */ new Map(),
75
+ _abac: this.abac,
76
+ skipFieldPolicies: input.skipFieldPolicies || false
77
+ };
78
+ if (input.req) {
79
+ context.user = input.user || input.req.userId;
80
+ context.data = {
81
+ body: input.req.body || {},
82
+ query: input.req.query || {},
83
+ params: input.req.params || {}
84
+ };
85
+ context.params = input.req.params;
86
+ context.req = input.req;
87
+ context.resourceId = input.req.params?._id || input.req.params?.id || input.req.body?._id || input.req.body?.id;
88
+ } else if (input.socket) {
89
+ context.user = input.user || input.socket.userId;
90
+ context.socket = input.socket;
91
+ context.data = input.data || {};
92
+ context.resourceId = input.data?._id || input.data?.id;
93
+ }
94
+ return Object.assign(context, {
95
+ ...input,
96
+ data: context.data
97
+ // Сохраняем структурированную data
98
+ });
99
+ }
100
+ /**
101
+ * Выполнение политики с кэшированием
102
+ */
103
+ async executePolicyWithCache(policyName, policyFn, context) {
104
+ const contextCacheKey = `${policyName}_${context.action}`;
105
+ if (context._cache.has(contextCacheKey)) {
106
+ return context._cache.get(contextCacheKey);
107
+ }
108
+ const globalCacheKey = this._buildCacheKey(policyName, context);
109
+ if (this.abac.options.cacheEnabled) {
110
+ const cached = await this.abac.cache.get(globalCacheKey);
111
+ if (cached !== void 0) {
112
+ context._cache.set(contextCacheKey, cached);
113
+ return cached;
114
+ }
115
+ }
116
+ const result = await policyFn(context);
117
+ context._cache.set(contextCacheKey, result);
118
+ if (this.abac.options.cacheEnabled) {
119
+ const tags = [
120
+ `user_${context.user}`,
121
+ `resource_${context.resource}`,
122
+ `policy_${policyName}`
123
+ ];
124
+ if (context.resourceId) {
125
+ tags.push(`resourceId_${context.resourceId}`);
126
+ }
127
+ await this.abac.cache.setWithTags(globalCacheKey, result, tags);
128
+ }
129
+ return result;
130
+ }
131
+ /**
132
+ * Построение ключа кэша с учетом ID ресурса
133
+ * @private
134
+ */
135
+ _buildCacheKey(policyName, context) {
136
+ const parts = [
137
+ "policy",
138
+ policyName,
139
+ context.user,
140
+ context.resource,
141
+ context.action
142
+ ];
143
+ if (context.resourceId) {
144
+ parts.push(context.resourceId);
145
+ }
146
+ return parts.join("_");
147
+ }
148
+ /**
149
+ * Выполнение политик с ограничением параллельности
150
+ */
151
+ async executePoliciesLimited(policies, context, stopOnDeny = false) {
152
+ const results = [];
153
+ const limit = this.abac.options.concurrencyLimit;
154
+ const batches = [];
155
+ for (let i = 0; i < policies.length; i += limit) {
156
+ batches.push(policies.slice(i, i + limit));
157
+ }
158
+ for (const batch of batches) {
159
+ const batchPromises = batch.map(async ([name, policy]) => {
160
+ try {
161
+ const policyFn = typeof policy === "function" ? policy : policy.fn;
162
+ const result = await this.executePolicyWithCache(name, policyFn, context);
163
+ return { name, result: this.normalizeResult(result, name) };
164
+ } catch (error) {
165
+ this.abac.logger?.error("Policy execution error", {
166
+ policy: name,
167
+ error: error.message,
168
+ stack: error.stack
169
+ });
170
+ return {
171
+ name,
172
+ result: {
173
+ allow: !this.abac.options.strictMode,
174
+ reason: `POLICY_ERROR_${name.toUpperCase()}`
175
+ },
176
+ error
177
+ };
178
+ }
179
+ });
180
+ const batchResults = await Promise.all(batchPromises);
181
+ results.push(...batchResults);
182
+ if (stopOnDeny) {
183
+ const shouldStop = batchResults.some((r) => !r.result.allow || r.result.force);
184
+ if (shouldStop) break;
185
+ }
186
+ }
187
+ return results;
188
+ }
189
+ /**
190
+ * Нормализация результата политики
191
+ */
192
+ normalizeResult(result, policyName) {
193
+ if (this.abac.options.strictMode && result === void 0) {
194
+ return {
195
+ allow: false,
196
+ force: false,
197
+ reason: `UNDEFINED_IN_STRICT_MODE_${policyName.toUpperCase()}`
198
+ };
199
+ }
200
+ if (result && typeof result === "object" && ("allow" in result || "force" in result)) {
201
+ return {
202
+ allow: result.allow !== void 0 ? !!result.allow : true,
203
+ force: !!result.force,
204
+ reason: result.reason || `POLICY_${policyName.toUpperCase()}`
205
+ };
206
+ }
207
+ if (result === true) {
208
+ return {
209
+ allow: true,
210
+ force: false,
211
+ reason: `ALLOWED_BY_${policyName.toUpperCase()}`
212
+ };
213
+ }
214
+ if (result === false) {
215
+ return {
216
+ allow: false,
217
+ force: false,
218
+ reason: `DENIED_BY_${policyName.toUpperCase()}`
219
+ };
220
+ }
221
+ return {
222
+ allow: !this.abac.options.strictMode,
223
+ force: false,
224
+ reason: `NEUTRAL_${policyName.toUpperCase()}`
225
+ };
226
+ }
227
+ /**
228
+ * Основной метод проверки доступа
229
+ */
230
+ async checkAccess(rawContext, customPolicies = {}) {
231
+ const startTime = Date.now();
232
+ const context = this.normalizeContext(rawContext);
233
+ if (context.isServiceRequest) {
234
+ return { allow: true, reason: "SERVICE_REQUEST_ALLOWED" };
235
+ }
236
+ if (!context.user && !context.options?.allowUnauthenticated) {
237
+ return { allow: false, reason: "UNAUTHENTICATED_ACCESS_DENIED" };
238
+ }
239
+ if (!context.currentResource) {
240
+ await this.loadResource(context);
241
+ }
242
+ const result = await this.abac.policies.evaluate(context, customPolicies);
243
+ if (this.abac.options.enableAudit) {
244
+ await this.audit(context, result, Date.now() - startTime);
245
+ }
246
+ return result;
247
+ }
248
+ /**
249
+ * Загрузка ресурса
250
+ */
251
+ async loadResource(context) {
252
+ const resourceModel = this.abac.getResourceModel(context.resource);
253
+ if (!resourceModel) return;
254
+ try {
255
+ let currentResource;
256
+ const id = context.resourceId || context.data?.body?._id || context.data?.params?._id;
257
+ if (id) {
258
+ currentResource = await resourceModel.findById(id);
259
+ } else if (context.data?.body?.url || context.data?.params?.url) {
260
+ const url = context.data.body?.url || context.data.params?.url;
261
+ currentResource = await resourceModel.findOne({ url });
262
+ }
263
+ if (currentResource) {
264
+ context.currentResource = currentResource;
265
+ context.resourceModel = resourceModel;
266
+ context.resourceId = currentResource._id?.toString();
267
+ }
268
+ } catch (error) {
269
+ this.abac.logger?.error("Resource loading error", {
270
+ resource: context.resource,
271
+ error: error.message
272
+ });
273
+ }
274
+ }
275
+ /**
276
+ * Структурированный аудит
277
+ */
278
+ async audit(context, result, duration) {
279
+ try {
280
+ const auditEntry = {
281
+ type: "ACCESS_CHECK",
282
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
283
+ user: context.user,
284
+ resource: context.resource,
285
+ resourceId: context.resourceId,
286
+ action: context.action,
287
+ result: result.allow,
288
+ reason: result.reason,
289
+ duration,
290
+ ip: context.req?.ip,
291
+ userAgent: context.req?.get?.("user-agent"),
292
+ metadata: context.auditMetadata || {}
293
+ };
294
+ await this.abac.logger.info("Access check", auditEntry);
295
+ if (["delete", "admin", "export"].includes(context.action)) {
296
+ await this.abac.logger.warn("Critical action attempt", auditEntry);
297
+ }
298
+ } catch (error) {
299
+ this.abac.logger?.error("Audit logging error", {
300
+ error: error.message
301
+ });
302
+ }
303
+ }
304
+ }
305
+ class ABACPolicies {
306
+ constructor(abac) {
307
+ this.abac = abac;
308
+ this.global = /* @__PURE__ */ new Map();
309
+ this.resources = /* @__PURE__ */ new Map();
310
+ this.extensions = /* @__PURE__ */ new Map();
311
+ this.priorities = {
312
+ static: [],
313
+ dynamic: [],
314
+ extensions: []
315
+ };
316
+ }
317
+ /**
318
+ * Регистрация глобальной политики
319
+ */
320
+ registerGlobalPolicy(name, policyFn, metadata = {}) {
321
+ if (typeof policyFn !== "function") {
322
+ throw new Error(`Global policy "${name}" must be a function`);
323
+ }
324
+ const policy = {
325
+ fn: policyFn,
326
+ type: metadata.type || "dynamic",
327
+ priority: metadata.priority || 0,
328
+ ...metadata
329
+ };
330
+ this.global.set(name, policy);
331
+ this.updatePriorities();
332
+ return this.abac;
333
+ }
334
+ /**
335
+ * Регистрация политики ресурса
336
+ */
337
+ registerResourcePolicy(resourceName, policyFn, options = {}) {
338
+ if (typeof policyFn !== "function") {
339
+ throw new Error(`Resource policy for "${resourceName}" must be a function`);
340
+ }
341
+ this.resources.set(resourceName, {
342
+ fn: policyFn,
343
+ modelName: options.modelName || options.model || resourceName,
344
+ ...options
345
+ });
346
+ return this.abac;
347
+ }
348
+ /**
349
+ * Регистрация расширения
350
+ */
351
+ registerExtension(moduleName, extensionFn) {
352
+ if (typeof extensionFn !== "function") {
353
+ throw new Error(`Extension "${moduleName}" must be a function`);
354
+ }
355
+ this.extensions.set(moduleName, extensionFn);
356
+ this.updatePriorities();
357
+ return this.abac;
358
+ }
359
+ /**
360
+ * Обновление приоритетов с сортировкой
361
+ */
362
+ updatePriorities() {
363
+ this.priorities = {
364
+ static: [],
365
+ dynamic: [],
366
+ extensions: []
367
+ };
368
+ for (const [name, policy] of this.global) {
369
+ const type = policy.type || "dynamic";
370
+ this.priorities[type].push([name, policy]);
371
+ }
372
+ this.priorities.static.sort((a, b) => (b[1].priority || 0) - (a[1].priority || 0));
373
+ this.priorities.dynamic.sort((a, b) => (b[1].priority || 0) - (a[1].priority || 0));
374
+ this.priorities.extensions = Array.from(this.extensions.entries());
375
+ }
376
+ /**
377
+ * Основная логика оценки политик
378
+ */
379
+ async evaluate(context, customPolicies = {}) {
380
+ const core = this.abac.core;
381
+ const evaluation = {
382
+ hasForceAllow: false,
383
+ hasForceDisallow: false,
384
+ hasDeny: false,
385
+ denyReason: "",
386
+ allowReason: "",
387
+ appliedPolicies: []
388
+ };
389
+ const processResult = (name, result) => {
390
+ evaluation.appliedPolicies.push({ name, result });
391
+ if (result.force) {
392
+ if (result.allow) {
393
+ evaluation.hasForceAllow = true;
394
+ evaluation.allowReason = result.reason;
395
+ } else {
396
+ evaluation.hasForceDisallow = true;
397
+ evaluation.denyReason = result.reason;
398
+ }
399
+ } else if (!result.allow) {
400
+ evaluation.hasDeny = true;
401
+ if (!evaluation.denyReason) {
402
+ evaluation.denyReason = result.reason;
403
+ }
404
+ }
405
+ };
406
+ const checkForceFlags = () => {
407
+ if (evaluation.hasForceDisallow) {
408
+ return {
409
+ allow: false,
410
+ reason: evaluation.denyReason || "FORCE_DENIED_BY_POLICY",
411
+ policies: evaluation.appliedPolicies
412
+ };
413
+ }
414
+ if (evaluation.hasForceAllow) {
415
+ return {
416
+ allow: true,
417
+ reason: evaluation.allowReason || "FORCE_ALLOWED_BY_POLICY",
418
+ policies: evaluation.appliedPolicies
419
+ };
420
+ }
421
+ return null;
422
+ };
423
+ const staticResults = await core.executePoliciesLimited(
424
+ this.priorities.static,
425
+ context,
426
+ true
427
+ // останавливаемся на deny
428
+ );
429
+ for (const { name, result, error } of staticResults) {
430
+ if (!error) {
431
+ processResult(name, result);
432
+ }
433
+ }
434
+ let forceResult = checkForceFlags();
435
+ if (forceResult) return forceResult;
436
+ const dynamicPolicies = [...this.priorities.dynamic];
437
+ for (const [name, fn] of Object.entries(customPolicies)) {
438
+ dynamicPolicies.push([name, { fn, type: "dynamic" }]);
439
+ }
440
+ const dynamicResults = await core.executePoliciesLimited(
441
+ dynamicPolicies,
442
+ context,
443
+ false
444
+ );
445
+ for (const { name, result, error } of dynamicResults) {
446
+ if (!error) {
447
+ processResult(name, result);
448
+ }
449
+ }
450
+ forceResult = checkForceFlags();
451
+ if (forceResult) return forceResult;
452
+ const resourcePolicy = this.resources.get(context.resource);
453
+ if (resourcePolicy) {
454
+ const results = await core.executePoliciesLimited(
455
+ [[`RESOURCE_${context.resource}`, resourcePolicy]],
456
+ context
457
+ );
458
+ if (!results[0].error) {
459
+ processResult(`RESOURCE_${context.resource}`, results[0].result);
460
+ }
461
+ forceResult = checkForceFlags();
462
+ if (forceResult) return forceResult;
463
+ }
464
+ if (evaluation.hasDeny) {
465
+ return {
466
+ allow: false,
467
+ reason: evaluation.denyReason || "DENIED_BY_POLICY",
468
+ policies: evaluation.appliedPolicies
469
+ };
470
+ }
471
+ const extensionResults = await core.executePoliciesLimited(
472
+ this.priorities.extensions,
473
+ context
474
+ );
475
+ for (const { name, result } of extensionResults) {
476
+ processResult(name, result);
477
+ if (result.allow) {
478
+ return {
479
+ allow: true,
480
+ reason: result.reason,
481
+ policies: evaluation.appliedPolicies
482
+ };
483
+ }
484
+ }
485
+ const defaultAllow = !this.abac.options.defaultDeny;
486
+ return {
487
+ allow: defaultAllow,
488
+ reason: defaultAllow ? "DEFAULT_ALLOW" : "DEFAULT_DENY",
489
+ policies: evaluation.appliedPolicies
490
+ };
491
+ }
492
+ /**
493
+ * Проверка конкретных политик
494
+ */
495
+ async checkPolicies(rawContext, policyNames = [], customPolicies = {}) {
496
+ const context = this.abac.core.normalizeContext(rawContext);
497
+ const policies = this.getPoliciesByNames(policyNames, customPolicies);
498
+ const results = await this.abac.core.executePoliciesLimited(
499
+ Object.entries(policies),
500
+ context,
501
+ this.abac.options.strictMode
502
+ );
503
+ const evaluation = {
504
+ passed: [],
505
+ failed: [],
506
+ errors: []
507
+ };
508
+ for (const { name, result, error } of results) {
509
+ if (error) {
510
+ evaluation.errors.push({ name, error: error.message });
511
+ continue;
512
+ }
513
+ if (result.force) {
514
+ return {
515
+ allow: result.allow,
516
+ reason: result.reason,
517
+ evaluation
518
+ };
519
+ }
520
+ if (result.allow) {
521
+ evaluation.passed.push(name);
522
+ } else {
523
+ evaluation.failed.push({ name, reason: result.reason });
524
+ if (this.abac.options.strictMode) {
525
+ return {
526
+ allow: false,
527
+ reason: result.reason,
528
+ evaluation
529
+ };
530
+ }
531
+ }
532
+ }
533
+ const allPassed = evaluation.failed.length === 0 && evaluation.errors.length === 0;
534
+ return {
535
+ allow: allPassed,
536
+ reason: allPassed ? "POLICIES_PASSED" : `FAILED: ${evaluation.failed[0]?.name}`,
537
+ evaluation
538
+ };
539
+ }
540
+ /**
541
+ * Получение политик по именам
542
+ */
543
+ getPoliciesByNames(names, customPolicies = {}) {
544
+ const policies = {};
545
+ for (const name of names) {
546
+ if (this.global.has(name)) {
547
+ policies[name] = this.global.get(name);
548
+ } else if (this.extensions.has(name)) {
549
+ policies[name] = { fn: this.extensions.get(name), type: "extension" };
550
+ } else if (this.resources.has(name)) {
551
+ policies[name] = this.resources.get(name);
552
+ } else {
553
+ this.abac.logger?.warn("Policy not found", { name });
554
+ }
555
+ }
556
+ Object.assign(policies, customPolicies);
557
+ return policies;
558
+ }
559
+ }
560
+ class ABACFields {
561
+ constructor(abac) {
562
+ this.abac = abac;
563
+ this.configs = /* @__PURE__ */ new Map();
564
+ this.compiledPatterns = /* @__PURE__ */ new Map();
565
+ }
566
+ /**
567
+ * Регистрация field policies
568
+ */
569
+ registerFieldsPolicy(resourceName, config) {
570
+ const normalized = {};
571
+ for (const [pattern, conf] of Object.entries(config)) {
572
+ const { actions, ...baseSettings } = conf;
573
+ const base = {
574
+ actions: baseSettings.actions || "*",
575
+ access: baseSettings.access || "allow",
576
+ validator: baseSettings.validator || null,
577
+ transform: baseSettings.transform || null,
578
+ rule: baseSettings.rule || "remove",
579
+ force: baseSettings.force || false,
580
+ pattern
581
+ };
582
+ if (actions && typeof actions === "object") {
583
+ normalized[pattern] = {
584
+ base,
585
+ actions: Object.entries(actions).reduce((acc, [action, override]) => {
586
+ acc[action] = { ...base, ...override };
587
+ return acc;
588
+ }, {})
589
+ };
590
+ } else {
591
+ normalized[pattern] = { base };
592
+ }
593
+ }
594
+ this.configs.set(resourceName, normalized);
595
+ this.compiledPatterns.delete(resourceName);
596
+ return this;
597
+ }
598
+ /**
599
+ * Проверка доступа к полям
600
+ */
601
+ async checkFields(context, data, action = null) {
602
+ const normalizedContext = this.abac.core.normalizeContext(context);
603
+ if (normalizedContext.skipFieldPolicies) {
604
+ return {
605
+ allowed: data,
606
+ denied: [],
607
+ errors: [],
608
+ transformed: data
609
+ };
610
+ }
611
+ const { resource } = normalizedContext;
612
+ const fieldAction = action || normalizedContext.action;
613
+ const config = normalizedContext.options?.fieldsConfig || this.configs.get(resource);
614
+ if (!config) {
615
+ return { allowed: data, denied: [], errors: [], transformed: data };
616
+ }
617
+ await this._applyExtensions(normalizedContext);
618
+ const result = {
619
+ allowed: this._deepClone(data),
620
+ denied: [],
621
+ errors: [],
622
+ transformed: null
623
+ };
624
+ const rules = this._collectRulesOptimized(data, config, fieldAction, resource);
625
+ const forced = rules.filter((r) => r.rule.force);
626
+ const regular = rules.filter((r) => !r.rule.force);
627
+ const processed = /* @__PURE__ */ new Set();
628
+ for (const { path, value, rule } of [...forced, ...regular]) {
629
+ if (processed.has(path)) continue;
630
+ processed.add(path);
631
+ const hasAccess = await this._checkFieldAccess(
632
+ rule.access,
633
+ normalizedContext,
634
+ path,
635
+ value
636
+ );
637
+ if (!hasAccess) {
638
+ await this._handleDenied(result, path, rule.rule);
639
+ continue;
640
+ }
641
+ if (rule.validator && rule.access !== "optional") {
642
+ const validation = await this._validateField(
643
+ rule.validator,
644
+ value,
645
+ normalizedContext,
646
+ path
647
+ );
648
+ if (!validation.isValid) {
649
+ result.errors.push({ path, errors: validation.errors });
650
+ if (rule.rule === "error") {
651
+ throw new Error(`Validation failed: ${path}`);
652
+ }
653
+ await this._handleDenied(result, path, rule.rule);
654
+ }
655
+ }
656
+ }
657
+ result.transformed = this._deepClone(result.allowed);
658
+ for (const { path, value, rule } of [...forced, ...regular]) {
659
+ if (!rule.transform) continue;
660
+ const isDenied = result.denied.some((d) => d.path === path);
661
+ if (isDenied) continue;
662
+ const transformed = await this._transformField(
663
+ rule.transform,
664
+ value,
665
+ normalizedContext,
666
+ path,
667
+ result.transformed
668
+ );
669
+ set(result.transformed, path, transformed);
670
+ }
671
+ return result;
672
+ }
673
+ /**
674
+ * Применение расширений
675
+ * @private
676
+ */
677
+ async _applyExtensions(context) {
678
+ if (!this.abac.policies || !this.abac.policies.priorities.extensions.length) {
679
+ return;
680
+ }
681
+ for (const [name, extensionFn] of this.abac.policies.priorities.extensions) {
682
+ try {
683
+ await extensionFn(context);
684
+ } catch (error) {
685
+ this.abac.logger?.error("Extension error", { name, error });
686
+ }
687
+ }
688
+ }
689
+ /**
690
+ * Безопасное клонирование
691
+ * @private
692
+ */
693
+ _deepClone(obj) {
694
+ if (typeof structuredClone === "function") {
695
+ try {
696
+ return structuredClone(obj);
697
+ } catch (e) {
698
+ }
699
+ }
700
+ return cloneDeep(obj);
701
+ }
702
+ /**
703
+ * Оптимизированный сбор правил
704
+ * @private
705
+ */
706
+ _collectRulesOptimized(data, config, action, resource) {
707
+ const rules = [];
708
+ const compiledPatterns = this._getCompiledPatterns(resource, config);
709
+ const hasWildcard = compiledPatterns.has("*");
710
+ const dataPaths = this._extractPathsOptimized(data);
711
+ if (hasWildcard) {
712
+ const wildcardConfig = config["*"];
713
+ const rule = this._getRuleForAction(wildcardConfig, action);
714
+ if (this._matchesAction(rule.actions, action)) {
715
+ for (const path of dataPaths) {
716
+ rules.push({
717
+ path,
718
+ value: get(data, path),
719
+ rule
720
+ });
721
+ }
722
+ return rules;
723
+ }
724
+ }
725
+ for (const path of dataPaths) {
726
+ for (const [pattern, matcher] of compiledPatterns) {
727
+ if (pattern === "*") continue;
728
+ if (matcher(path)) {
729
+ const fieldConfig = config[pattern];
730
+ const rule = this._getRuleForAction(fieldConfig, action);
731
+ if (this._matchesAction(rule.actions, action)) {
732
+ rules.push({
733
+ path,
734
+ value: get(data, path),
735
+ rule
736
+ });
737
+ break;
738
+ }
739
+ }
740
+ }
741
+ }
742
+ return rules;
743
+ }
744
+ /**
745
+ * Получение скомпилированных паттернов
746
+ * @private
747
+ */
748
+ _getCompiledPatterns(resource, config) {
749
+ if (!this.compiledPatterns.has(resource)) {
750
+ const compiled = /* @__PURE__ */ new Map();
751
+ for (const pattern of Object.keys(config)) {
752
+ compiled.set(pattern, this._compilePattern(pattern));
753
+ }
754
+ this.compiledPatterns.set(resource, compiled);
755
+ }
756
+ return this.compiledPatterns.get(resource);
757
+ }
758
+ /**
759
+ * Компиляция паттерна в функцию проверки
760
+ * @private
761
+ */
762
+ _compilePattern(pattern) {
763
+ if (pattern === "*") return () => true;
764
+ const escaped = pattern.replace(/\./g, "\\.").replace(/\*\*/g, ".*").replace(/\*/g, "[^.]+").replace(/\[\*\]/g, "\\[\\d+\\]");
765
+ const regex = new RegExp(`^${escaped}$`);
766
+ return (path) => regex.test(path);
767
+ }
768
+ /**
769
+ * Оптимизированное извлечение путей
770
+ * @private
771
+ */
772
+ _extractPathsOptimized(obj, prefix = "", paths = []) {
773
+ if (!obj || typeof obj !== "object") return paths;
774
+ if (Array.isArray(obj)) {
775
+ obj.forEach((item, i) => {
776
+ const path = prefix ? `${prefix}[${i}]` : `[${i}]`;
777
+ paths.push(path);
778
+ this._extractPathsOptimized(item, path, paths);
779
+ });
780
+ } else {
781
+ for (const key in obj) {
782
+ if (obj.hasOwnProperty(key)) {
783
+ const path = prefix ? `${prefix}.${key}` : key;
784
+ paths.push(path);
785
+ if (obj[key] && typeof obj[key] === "object") {
786
+ this._extractPathsOptimized(obj[key], path, paths);
787
+ }
788
+ }
789
+ }
790
+ }
791
+ return paths;
792
+ }
793
+ /**
794
+ * Получение правила для действия
795
+ * @private
796
+ */
797
+ _getRuleForAction(fieldConfig, action) {
798
+ if (fieldConfig.actions && fieldConfig.actions[action]) {
799
+ return fieldConfig.actions[action];
800
+ }
801
+ return fieldConfig.base;
802
+ }
803
+ /**
804
+ * Проверка доступа к полю
805
+ * @private
806
+ */
807
+ async _checkFieldAccess(access, context, fieldPath, fieldValue) {
808
+ if (access === "allow") return true;
809
+ if (access === "deny") return false;
810
+ if (access === "optional") return true;
811
+ if (typeof access === "function") {
812
+ try {
813
+ return !!await access(context, fieldPath, fieldValue);
814
+ } catch (e) {
815
+ this.abac.logger?.error("Field access check error", {
816
+ field: fieldPath,
817
+ error: e.message
818
+ });
819
+ return false;
820
+ }
821
+ }
822
+ return true;
823
+ }
824
+ /**
825
+ * Валидация поля
826
+ * @private
827
+ */
828
+ async _validateField(validator, value, context, fieldPath) {
829
+ if (typeof validator === "function") {
830
+ try {
831
+ const result = await validator(value, context, fieldPath);
832
+ if (typeof result === "boolean") {
833
+ return { isValid: result, errors: result ? [] : ["Validation failed"] };
834
+ }
835
+ return result;
836
+ } catch (e) {
837
+ return { isValid: false, errors: [e.message] };
838
+ }
839
+ }
840
+ if (validator && validator.validate) {
841
+ return validator.validate(value);
842
+ }
843
+ return { isValid: true, errors: [] };
844
+ }
845
+ /**
846
+ * Трансформация поля
847
+ * @private
848
+ */
849
+ async _transformField(transform, value, context, fieldPath, currentData) {
850
+ try {
851
+ return await transform(value, context, fieldPath, currentData);
852
+ } catch (error) {
853
+ this.abac.logger?.error("Field transform error", {
854
+ field: fieldPath,
855
+ error: error.message
856
+ });
857
+ return value;
858
+ }
859
+ }
860
+ /**
861
+ * Обработка отказа
862
+ * @private
863
+ */
864
+ async _handleDenied(result, path, rule) {
865
+ result.denied.push({ path, reason: rule });
866
+ if (rule === "remove") {
867
+ unset(result.allowed, path);
868
+ } else if (rule === "error") {
869
+ throw new Error(`Access denied: ${path}`);
870
+ }
871
+ }
872
+ /**
873
+ * Проверка действия
874
+ * @private
875
+ */
876
+ _matchesAction(actions, action) {
877
+ if (actions === "*") return true;
878
+ return Array.isArray(actions) ? actions.includes(action) : actions === action;
879
+ }
880
+ // Публичные методы для управления конфигами
881
+ getConfig(resourceName) {
882
+ return this.configs.get(resourceName);
883
+ }
884
+ hasConfig(resourceName) {
885
+ return this.configs.has(resourceName);
886
+ }
887
+ removeConfig(resourceName) {
888
+ this.compiledPatterns.delete(resourceName);
889
+ return this.configs.delete(resourceName);
890
+ }
891
+ }
892
+ class ABACExpressAdapter {
893
+ constructor(abac) {
894
+ this.abac = abac;
895
+ }
896
+ /**
897
+ * Основной middleware - разделен на составные части
898
+ */
899
+ middleware(resource, action, options = {}) {
900
+ const middlewares = [];
901
+ middlewares.push(this._accessMiddleware(resource, action, options));
902
+ if (options.checkFields) {
903
+ middlewares.push(this._fieldsValidationMiddleware(resource, action, options));
904
+ }
905
+ return middlewares;
906
+ }
907
+ /**
908
+ * Middleware проверки доступа
909
+ * @private
910
+ */
911
+ _accessMiddleware(resource, action, options = {}) {
912
+ return async (req, res, next) => {
913
+ try {
914
+ const context = this._buildContext(req, resource, action, options);
915
+ const accessResult = await this.abac.checkAccess(context, context.customPolicies);
916
+ if (!accessResult.allow) {
917
+ return this._sendAccessDenied(res, accessResult.reason);
918
+ }
919
+ req.abacContext = context;
920
+ req.abacAccessResult = accessResult;
921
+ next();
922
+ } catch (error) {
923
+ this.abac.logger?.error("ABAC middleware error", {
924
+ resource,
925
+ action,
926
+ error: error.message,
927
+ stack: error.stack
928
+ });
929
+ return this._sendError(res);
930
+ }
931
+ };
932
+ }
933
+ /**
934
+ * Middleware проверки полей
935
+ * @private
936
+ */
937
+ _fieldsValidationMiddleware(resource, action, options = {}) {
938
+ return async (req, res, next) => {
939
+ try {
940
+ const context = req.abacContext || this._buildContext(req, resource, action, options);
941
+ const fieldsResult = await this.abac.checkFields(context, req.body, action);
942
+ if (fieldsResult.errors.length > 0 && options.strictFieldsMode) {
943
+ return this._sendFieldError(res, fieldsResult.errors);
944
+ }
945
+ req.body = fieldsResult.allowed;
946
+ req.abacFieldsResult = fieldsResult;
947
+ next();
948
+ } catch (error) {
949
+ this.abac.logger?.error("Fields middleware error", {
950
+ resource,
951
+ action,
952
+ error: error.message
953
+ });
954
+ if (options.passErrors) {
955
+ next(error);
956
+ } else {
957
+ return this._sendError(res);
958
+ }
959
+ }
960
+ };
961
+ }
962
+ /**
963
+ * Построение контекста
964
+ * @private
965
+ */
966
+ _buildContext(req, resource, action, options = {}) {
967
+ return {
968
+ user: req.userId,
969
+ resource,
970
+ action,
971
+ req,
972
+ // НЕ смешиваем body и query - передаем структурированно
973
+ data: {
974
+ body: req.body || {},
975
+ query: req.query || {},
976
+ params: req.params || {}
977
+ },
978
+ params: req.params,
979
+ customPolicies: options.policies || {},
980
+ options
981
+ };
982
+ }
983
+ /**
984
+ * Policy middleware
985
+ */
986
+ policyMiddleware(policyNames = [], customPolicies = {}, options = {}) {
987
+ return async (req, res, next) => {
988
+ try {
989
+ const context = this._buildContext(
990
+ req,
991
+ options.resource || "custom",
992
+ options.action || "access",
993
+ options
994
+ );
995
+ const result = await this.abac.checkPolicies(context, policyNames, customPolicies);
996
+ if (!result.allow) {
997
+ return this._sendPolicyDenied(res, result.reason);
998
+ }
999
+ req.abacPolicyResult = result;
1000
+ next();
1001
+ } catch (error) {
1002
+ this.abac.logger?.error("Policy middleware error", {
1003
+ policies: policyNames,
1004
+ error: error.message
1005
+ });
1006
+ return this._sendError(res);
1007
+ }
1008
+ };
1009
+ }
1010
+ /**
1011
+ * Fields middleware для проверки/трансформации полей
1012
+ */
1013
+ fieldsMiddleware(resource, options = {}) {
1014
+ return async (req, res, next) => {
1015
+ try {
1016
+ const action = options.action || this._getActionFromMethod(req.method);
1017
+ const context = this._buildContext(req, resource, action, options);
1018
+ let dataToCheck = this._getDataToCheck(req, res, options);
1019
+ const fieldsResult = await this.abac.checkFields(context, dataToCheck, action);
1020
+ if (fieldsResult.errors.length > 0) {
1021
+ if (options.strictMode) {
1022
+ return this._sendFieldError(res, fieldsResult.errors);
1023
+ }
1024
+ this.abac.logger?.warn("Field validation errors", {
1025
+ resource,
1026
+ action,
1027
+ errors: fieldsResult.errors
1028
+ });
1029
+ }
1030
+ this._applyFieldsResult(req, res, options, fieldsResult);
1031
+ req.abacFieldsResult = fieldsResult;
1032
+ next();
1033
+ } catch (error) {
1034
+ this.abac.logger?.error("Fields middleware error", {
1035
+ resource,
1036
+ error: error.message
1037
+ });
1038
+ if (options.passErrors) {
1039
+ next(error);
1040
+ } else {
1041
+ return this._sendError(res);
1042
+ }
1043
+ }
1044
+ };
1045
+ }
1046
+ /**
1047
+ * Получение action из HTTP метода
1048
+ * @private
1049
+ */
1050
+ _getActionFromMethod(method) {
1051
+ const methodActionMap = {
1052
+ "GET": "read",
1053
+ "POST": "create",
1054
+ "PUT": "update",
1055
+ "PATCH": "update",
1056
+ "DELETE": "delete"
1057
+ };
1058
+ return methodActionMap[method] || "access";
1059
+ }
1060
+ /**
1061
+ * Определение данных для проверки
1062
+ * @private
1063
+ */
1064
+ _getDataToCheck(req, res, options) {
1065
+ if (req.method === "GET" && options.checkQuery) {
1066
+ return req.query;
1067
+ }
1068
+ if (options.checkResponse && res.locals.data) {
1069
+ return res.locals.data;
1070
+ }
1071
+ return req.body;
1072
+ }
1073
+ /**
1074
+ * Применение результатов проверки полей
1075
+ * @private
1076
+ */
1077
+ _applyFieldsResult(req, res, options, fieldsResult) {
1078
+ if (req.method === "GET" && options.checkQuery) {
1079
+ req.query = fieldsResult.allowed;
1080
+ } else if (options.checkResponse && res.locals.data) {
1081
+ res.locals.data = fieldsResult.transformed || fieldsResult.allowed;
1082
+ } else {
1083
+ req.body = fieldsResult.allowed;
1084
+ }
1085
+ }
1086
+ /**
1087
+ * Отправка ошибок - унифицированные методы
1088
+ * @private
1089
+ */
1090
+ _sendAccessDenied(res, reason) {
1091
+ return res.status(403).json({
1092
+ error: {
1093
+ code: "ACCESS_DENIED",
1094
+ message: reason
1095
+ }
1096
+ });
1097
+ }
1098
+ _sendPolicyDenied(res, reason) {
1099
+ return res.status(403).json({
1100
+ error: {
1101
+ code: "POLICY_DENIED",
1102
+ message: reason
1103
+ }
1104
+ });
1105
+ }
1106
+ _sendFieldError(res, errors) {
1107
+ return res.status(400).json({
1108
+ error: {
1109
+ code: "FIELD_VALIDATION_ERROR",
1110
+ fields: errors
1111
+ }
1112
+ });
1113
+ }
1114
+ _sendError(res) {
1115
+ return res.status(500).json({
1116
+ error: {
1117
+ code: "INTERNAL_ERROR",
1118
+ message: "Access control error"
1119
+ }
1120
+ });
1121
+ }
1122
+ }
1123
+ class ABACWebSocketAdapter {
1124
+ constructor(abac) {
1125
+ this.abac = abac;
1126
+ }
1127
+ /**
1128
+ * WebSocket handler для проверки доступа
1129
+ * @param {string} moduleName - Имя модуля
1130
+ * @param {Object} [options] - Опции
1131
+ * @returns {Function} Handler функция
1132
+ */
1133
+ handler(moduleName, options = {}) {
1134
+ return async (ws, message) => {
1135
+ try {
1136
+ const { action = "access", resource = moduleName } = options;
1137
+ const context = this._buildContext(ws, resource, action, message, options);
1138
+ const accessResult = await this.abac.checkAccess(context, context.customPolicies);
1139
+ if (!accessResult.allow) {
1140
+ await this._sendError(ws, "ACCESS_DENIED", accessResult.reason);
1141
+ return false;
1142
+ }
1143
+ if (options.checkFields && message) {
1144
+ const fieldsResult = await this.abac.checkFields(context, message, action);
1145
+ if (fieldsResult.errors.length > 0 && options.strictFieldsMode) {
1146
+ await this._sendError(ws, "FIELD_VALIDATION_ERROR", "Field validation failed", {
1147
+ fields: fieldsResult.errors
1148
+ });
1149
+ return false;
1150
+ }
1151
+ return {
1152
+ allowed: true,
1153
+ data: fieldsResult.transformed || fieldsResult.allowed,
1154
+ fieldsResult
1155
+ };
1156
+ }
1157
+ return true;
1158
+ } catch (error) {
1159
+ this.abac.logger?.error("WebSocket access control error", {
1160
+ module: moduleName,
1161
+ error: error.message,
1162
+ stack: error.stack
1163
+ });
1164
+ await this._sendError(ws, "INTERNAL_ERROR", "Access control error");
1165
+ return false;
1166
+ }
1167
+ };
1168
+ }
1169
+ /**
1170
+ * RPC handler для вызовов через WebSocket
1171
+ * @param {string} module - Модуль
1172
+ * @param {string} method - Метод
1173
+ * @param {Object} [options] - Опции
1174
+ * @returns {Function} RPC handler
1175
+ */
1176
+ rpcHandler(module, method, options = {}) {
1177
+ return async (params, rpcContext) => {
1178
+ try {
1179
+ const context = this._buildRPCContext(rpcContext, module, method, params, options);
1180
+ const accessResult = await this.abac.checkAccess(context, context.customPolicies);
1181
+ if (!accessResult.allow) {
1182
+ throw new RPCError("ACCESS_DENIED", accessResult.reason);
1183
+ }
1184
+ if (options.checkFields && params) {
1185
+ const fieldsResult = await this.abac.checkFields(context, params, method);
1186
+ if (fieldsResult.errors.length > 0) {
1187
+ if (options.strictFieldsMode) {
1188
+ throw new RPCError(
1189
+ "FIELD_VALIDATION_ERROR",
1190
+ `Fields validation failed: ${fieldsResult.errors.map((e) => e.path).join(", ")}`
1191
+ );
1192
+ }
1193
+ this.abac.logger?.warn("RPC field validation errors", {
1194
+ module,
1195
+ method,
1196
+ errors: fieldsResult.errors
1197
+ });
1198
+ }
1199
+ return fieldsResult.transformed || fieldsResult.allowed;
1200
+ }
1201
+ return params;
1202
+ } catch (error) {
1203
+ if (error instanceof RPCError) {
1204
+ throw error;
1205
+ }
1206
+ this.abac.logger?.error("RPC access control error", {
1207
+ module,
1208
+ method,
1209
+ error: error.message,
1210
+ stack: error.stack
1211
+ });
1212
+ throw new RPCError("INTERNAL_ERROR", "Access control error");
1213
+ }
1214
+ };
1215
+ }
1216
+ /**
1217
+ * Middleware для обработки WebSocket сообщений
1218
+ * @param {Object} [options] - Опции
1219
+ * @returns {Function} Middleware функция
1220
+ */
1221
+ messageMiddleware(options = {}) {
1222
+ return async (ws, message, next) => {
1223
+ try {
1224
+ const { resource = "message", action = "send" } = options;
1225
+ const context = this._buildContext(ws, resource, action, message, options);
1226
+ const accessResult = await this.abac.checkAccess(context, options.policies || {});
1227
+ if (!accessResult.allow) {
1228
+ await this._sendError(ws, "ACCESS_DENIED", accessResult.reason);
1229
+ return;
1230
+ }
1231
+ ws.abacContext = context;
1232
+ ws.abacAccessResult = accessResult;
1233
+ next();
1234
+ } catch (error) {
1235
+ this.abac.logger?.error("WebSocket middleware error", {
1236
+ error: error.message
1237
+ });
1238
+ await this._sendError(ws, "INTERNAL_ERROR", "Access control error");
1239
+ }
1240
+ };
1241
+ }
1242
+ /**
1243
+ * Построение контекста для WebSocket
1244
+ * @private
1245
+ */
1246
+ _buildContext(ws, resource, action, data, options) {
1247
+ return {
1248
+ user: ws.userId || ws.user?.id,
1249
+ resource,
1250
+ action,
1251
+ data: data || {},
1252
+ socket: ws,
1253
+ customPolicies: options.policies || {},
1254
+ options,
1255
+ // Дополнительная информация о соединении
1256
+ connectionInfo: {
1257
+ id: ws.id,
1258
+ remoteAddress: ws._socket?.remoteAddress,
1259
+ protocol: ws.protocol,
1260
+ readyState: ws.readyState
1261
+ }
1262
+ };
1263
+ }
1264
+ /**
1265
+ * Построение контекста для RPC
1266
+ * @private
1267
+ */
1268
+ _buildRPCContext(rpcContext, module, method, params, options) {
1269
+ return {
1270
+ user: rpcContext.userId || rpcContext.user?.id,
1271
+ resource: module,
1272
+ action: method,
1273
+ data: params || {},
1274
+ socket: rpcContext.ws,
1275
+ customPolicies: options.policies || {},
1276
+ options,
1277
+ rpcInfo: {
1278
+ id: rpcContext.id,
1279
+ module,
1280
+ method,
1281
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1282
+ }
1283
+ };
1284
+ }
1285
+ /**
1286
+ * Отправка ошибки через WebSocket
1287
+ * @private
1288
+ */
1289
+ async _sendError(ws, code, message, details = {}) {
1290
+ if (ws.readyState !== 1) {
1291
+ return;
1292
+ }
1293
+ try {
1294
+ const errorMessage = JSON.stringify({
1295
+ type: "error",
1296
+ error: {
1297
+ code,
1298
+ message,
1299
+ ...details
1300
+ },
1301
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1302
+ });
1303
+ ws.send(errorMessage);
1304
+ } catch (error) {
1305
+ this.abac.logger?.error("Failed to send WebSocket error", {
1306
+ originalError: { code, message },
1307
+ sendError: error.message
1308
+ });
1309
+ }
1310
+ }
1311
+ }
1312
+ class RPCError extends Error {
1313
+ constructor(code, message, details = {}) {
1314
+ super(message);
1315
+ this.name = "RPCError";
1316
+ this.code = code;
1317
+ this.details = details;
1318
+ }
1319
+ }
1320
+ class GlobalABAC {
1321
+ constructor(db, options = {}) {
1322
+ this.db = db;
1323
+ this.options = {
1324
+ strictMode: false,
1325
+ defaultDeny: false,
1326
+ serviceKey: process.env.SERVICE_KEY,
1327
+ enableAudit: true,
1328
+ cacheEnabled: true,
1329
+ cacheTTL: 300,
1330
+ concurrencyLimit: 10,
1331
+ ...options
1332
+ };
1333
+ this.cache = new CacheNamespaced({ ttlSeconds: this.options.cacheTTL });
1334
+ this.logger = this.options.logger || new LoggerNamespaced(db);
1335
+ this.core = new ABACCore(this);
1336
+ this.policies = new ABACPolicies(this);
1337
+ this.fields = new ABACFields(this);
1338
+ this.express = new ABACExpressAdapter(this);
1339
+ this.websocket = new ABACWebSocketAdapter(this);
1340
+ }
1341
+ /**
1342
+ * Регистрация глобальной политики
1343
+ * @param {string} name - Имя политики
1344
+ * @param {Function} policyFn - Функция политики (context) => boolean|{allow, force, reason}
1345
+ * @param {Object} [metadata] - Метаданные политики
1346
+ * @param {string} [metadata.type='dynamic'] - Тип (static|dynamic)
1347
+ * @param {number} [metadata.priority=0] - Приоритет
1348
+ * @returns {GlobalABAC}
1349
+ */
1350
+ registerGlobalPolicy(name, policyFn, metadata = {}) {
1351
+ return this.policies.registerGlobalPolicy(name, policyFn, metadata);
1352
+ }
1353
+ /**
1354
+ * Регистрация политики для ресурса
1355
+ * @param {string} resourceName - Имя ресурса
1356
+ * @param {Function} policyFn - Функция политики
1357
+ * @param {Object} [options] - Опции
1358
+ * @param {string} [options.modelName] - Имя модели в БД
1359
+ * @returns {GlobalABAC}
1360
+ */
1361
+ registerResourcePolicy(resourceName, policyFn, options = {}) {
1362
+ return this.policies.registerResourcePolicy(resourceName, policyFn, options);
1363
+ }
1364
+ /**
1365
+ * Регистрация политики полей
1366
+ * @param {string} resourceName - Имя ресурса
1367
+ * @param {Object} config - Конфигурация полей
1368
+ * @returns {GlobalABAC}
1369
+ *
1370
+ * @example
1371
+ * abac.registerFieldsPolicy('user', {
1372
+ * 'email': { access: 'deny', actions: ['update'] },
1373
+ * 'password': { access: 'deny', actions: '*', rule: 'remove' },
1374
+ * 'profile.*': {
1375
+ * access: async (ctx) => ctx.user === ctx.currentResource?.id,
1376
+ * transform: (value) => sanitize(value)
1377
+ * }
1378
+ * });
1379
+ */
1380
+ registerFieldsPolicy(resourceName, config) {
1381
+ return this.fields.registerFieldsPolicy(resourceName, config);
1382
+ }
1383
+ /**
1384
+ * Регистрация расширения контекста
1385
+ * @param {string} moduleName - Имя модуля
1386
+ * @param {Function} extensionFn - Функция расширения (context) => void
1387
+ * @returns {GlobalABAC}
1388
+ */
1389
+ registerExtension(moduleName, extensionFn) {
1390
+ return this.policies.registerExtension(moduleName, extensionFn);
1391
+ }
1392
+ /**
1393
+ * Проверка доступа
1394
+ * @param {ABACContext|Object} context - Контекст проверки
1395
+ * @param {Object} [customPolicies] - Дополнительные политики
1396
+ * @returns {Promise<ABACResult>}
1397
+ */
1398
+ async checkAccess(context, customPolicies = {}) {
1399
+ return this.core.checkAccess(context, customPolicies);
1400
+ }
1401
+ /**
1402
+ * Проверка доступа к полям
1403
+ * @param {ABACContext|Object} context - Контекст
1404
+ * @param {Object} data - Данные для проверки
1405
+ * @param {string} [action] - Действие
1406
+ * @returns {Promise<FieldsResult>}
1407
+ */
1408
+ async checkFields(context, data, action = null) {
1409
+ return this.fields.checkFields(context, data, action);
1410
+ }
1411
+ /**
1412
+ * Проверка конкретных политик
1413
+ * @param {ABACContext|Object} context - Контекст
1414
+ * @param {string[]} policyNames - Имена политик
1415
+ * @param {Object} [customPolicies] - Дополнительные политики
1416
+ * @returns {Promise<ABACResult>}
1417
+ */
1418
+ async checkPolicies(context, policyNames = [], customPolicies = {}) {
1419
+ return this.policies.checkPolicies(context, policyNames, customPolicies);
1420
+ }
1421
+ /**
1422
+ * Express middleware для проверки доступа
1423
+ * @param {string} resource - Ресурс
1424
+ * @param {string} action - Действие
1425
+ * @param {Object} [options] - Опции
1426
+ * @returns {Function|Function[]} Middleware функция(и)
1427
+ */
1428
+ middleware(resource, action, options = {}) {
1429
+ return this.express.middleware(resource, action, options);
1430
+ }
1431
+ /**
1432
+ * Express middleware для проверки политик
1433
+ * @param {string[]} policyNames - Имена политик
1434
+ * @param {Object} [customPolicies] - Дополнительные политики
1435
+ * @param {Object} [options] - Опции
1436
+ * @returns {Function} Middleware функция
1437
+ */
1438
+ policyMiddleware(policyNames = [], customPolicies = {}, options = {}) {
1439
+ return this.express.policyMiddleware(policyNames, customPolicies, options);
1440
+ }
1441
+ /**
1442
+ * Express middleware для проверки полей
1443
+ * @param {string} resource - Ресурс
1444
+ * @param {Object} [options] - Опции
1445
+ * @returns {Function} Middleware функция
1446
+ */
1447
+ fieldsMiddleware(resource, options = {}) {
1448
+ return this.express.fieldsMiddleware(resource, options);
1449
+ }
1450
+ /**
1451
+ * WebSocket handler
1452
+ * @param {string} moduleName - Имя модуля
1453
+ * @param {Object} [options] - Опции
1454
+ * @returns {Function} Handler функция
1455
+ */
1456
+ wsHandler(moduleName, options = {}) {
1457
+ return this.websocket.handler(moduleName, options);
1458
+ }
1459
+ /**
1460
+ * Получение модели ресурса из БД
1461
+ * @param {string} resourceName - Имя ресурса
1462
+ * @returns {Object|null} Mongoose модель или null
1463
+ */
1464
+ getResourceModel(resourceName) {
1465
+ const resourcePolicy = this.policies.resources.get(resourceName);
1466
+ if (!resourcePolicy) return null;
1467
+ const modelName = resourcePolicy.modelName || resourceName;
1468
+ return this.db[modelName] || null;
1469
+ }
1470
+ /**
1471
+ * Очистка кэша
1472
+ * @param {Object} [options] - Опции очистки
1473
+ * @param {string} [options.user] - Очистить для пользователя
1474
+ * @param {string} [options.resource] - Очистить для ресурса
1475
+ * @param {string} [options.policy] - Очистить для политики
1476
+ */
1477
+ async clearCache(options = {}) {
1478
+ if (options.user) {
1479
+ await this.cache.invalidateTag(`user_${options.user}`);
1480
+ }
1481
+ if (options.resource) {
1482
+ await this.cache.invalidateTag(`resource_${options.resource}`);
1483
+ }
1484
+ if (options.policy) {
1485
+ await this.cache.invalidateTag(`policy_${options.policy}`);
1486
+ }
1487
+ if (!options.user && !options.resource && !options.policy) {
1488
+ await this.cache.clear();
1489
+ }
1490
+ }
1491
+ /**
1492
+ * Получение статистики
1493
+ * @returns {Object} Статистика системы
1494
+ */
1495
+ getStats() {
1496
+ return {
1497
+ policies: {
1498
+ global: this.policies.global.size,
1499
+ resources: this.policies.resources.size,
1500
+ extensions: this.policies.extensions.size
1501
+ },
1502
+ fields: {
1503
+ configs: this.fields.configs.size
1504
+ },
1505
+ cache: {
1506
+ size: this.cache.size,
1507
+ hits: this.cache.hits,
1508
+ misses: this.cache.misses
1509
+ }
1510
+ };
1511
+ }
1512
+ }
1513
+ let instance = null;
1514
+ const getInstance = (db, options) => {
1515
+ if (!instance) {
1516
+ instance = new GlobalABAC(db, options);
1517
+ }
1518
+ return instance;
1519
+ };
1520
+ const resetInstance = () => {
1521
+ instance = null;
1522
+ };
1523
+ const coreabac = { getInstance, resetInstance };
1524
+ export {
1525
+ LoggerNamespaced as L,
1526
+ coreabac as c
1527
+ };