@ozdao/martyrs 0.2.564 → 0.2.565

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 (279) 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/src/components/Button/{Button.vue.js → Button.vue2.js} +36 -45
  13. package/dist/martyrs/src/components/Button/Button.vue2.js.map +1 -0
  14. package/dist/martyrs/src/components/Feed/Carousel.vue.js +1 -1
  15. package/dist/martyrs/src/components/Feed/Feed.vue.js +1 -1
  16. package/dist/martyrs/src/components/Field/{Field.vue2.js → Field.vue.js} +2 -2
  17. package/dist/martyrs/src/components/Field/Field.vue.js.map +1 -0
  18. package/dist/martyrs/src/components/FieldBig/FieldBig.vue.js +2 -2
  19. package/dist/martyrs/src/components/FieldPhone/FieldPhone.vue.js +1 -1
  20. package/dist/martyrs/src/components/FieldPhone/FieldPhone.vue.js.map +1 -1
  21. package/dist/martyrs/src/components/Loader/{Loader.vue2.js → Loader.vue.js} +3 -4
  22. package/dist/martyrs/src/components/Loader/Loader.vue.js.map +1 -0
  23. package/dist/martyrs/src/components/LocationMarker/LocationMarker.vue.js +1 -1
  24. package/dist/martyrs/src/components/Media/Media.vue.js +1 -1
  25. package/dist/martyrs/src/components/Menu/{Menu.vue.js → Menu.vue2.js} +2 -2
  26. package/dist/martyrs/src/components/Menu/Menu.vue2.js.map +1 -0
  27. package/dist/martyrs/src/components/Select/{Select.vue2.js → Select.vue.js} +2 -2
  28. package/dist/martyrs/src/components/Select/Select.vue.js.map +1 -0
  29. package/dist/martyrs/src/components/SelectMulti/{SelectMulti.vue.js → SelectMulti.vue2.js} +2 -2
  30. package/dist/martyrs/src/components/SelectMulti/SelectMulti.vue2.js.map +1 -0
  31. package/dist/martyrs/src/components/Tree/Tree.vue.js +6 -3
  32. package/dist/martyrs/src/components/Tree/Tree.vue.js.map +1 -1
  33. package/dist/martyrs/src/components/UploadImage/UploadImage.vue.js +1 -1
  34. package/dist/martyrs/src/components/UploadImageMultiple/UploadImageMultiple.vue.js +1 -1
  35. package/dist/martyrs/src/modules/auth/auth.client.js +10 -7
  36. package/dist/martyrs/src/modules/auth/auth.client.js.map +1 -1
  37. package/dist/martyrs/src/modules/auth/views/components/pages/EnterCode.vue.js +1 -1
  38. package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +2 -2
  39. package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +2 -2
  40. package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +3 -3
  41. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEdit.vue.js +1 -1
  42. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditAccount.vue.js +1 -1
  43. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditProfile.vue.js +2 -2
  44. package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +2 -2
  45. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +13 -13
  46. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js.map +1 -1
  47. package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +2 -2
  48. package/dist/martyrs/src/modules/auth/views/components/sections/ProfileEditCredentials.vue.js +2 -2
  49. package/dist/martyrs/src/modules/auth/views/router/auth.router.js +116 -0
  50. package/dist/martyrs/src/modules/auth/views/router/auth.router.js.map +1 -0
  51. package/dist/martyrs/src/modules/auth/views/router/users.router.js +180 -0
  52. package/dist/martyrs/src/modules/auth/views/router/users.router.js.map +1 -0
  53. package/dist/martyrs/src/modules/backoffice/components/partials/Sidebar.vue.js +4 -4
  54. package/dist/martyrs/src/modules/backoffice/components/partials/Sidebar.vue.js.map +1 -1
  55. package/dist/martyrs/src/modules/community/components/layouts/Community.vue.js +1 -1
  56. package/dist/martyrs/src/modules/community/components/pages/BlogPost.vue.js +2 -2
  57. package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.js +2 -2
  58. package/dist/martyrs/src/modules/constructor/components/elements/Card.vue.js +1 -1
  59. package/dist/martyrs/src/modules/constructor/components/elements/Embed.vue.js +1 -1
  60. package/dist/martyrs/src/modules/core/locales/en.js +45 -0
  61. package/dist/martyrs/src/modules/core/locales/en.js.map +1 -1
  62. package/dist/martyrs/src/modules/core/locales/ru.js +45 -0
  63. package/dist/martyrs/src/modules/core/locales/ru.js.map +1 -1
  64. package/dist/martyrs/src/modules/core/views/classes/i18n.manager.js +9 -0
  65. package/dist/martyrs/src/modules/core/views/classes/i18n.manager.js.map +1 -1
  66. package/dist/martyrs/src/modules/core/views/components/blocks/BlockSearch.vue.js +1 -1
  67. package/dist/martyrs/src/modules/core/views/components/blocks/CardHeader.vue.js +1 -1
  68. package/dist/martyrs/src/modules/core/views/components/blocks/PopupAuth.vue.js +1 -1
  69. package/dist/martyrs/src/modules/core/views/components/blocks/PopupDateSelector.vue.js +2 -2
  70. package/dist/martyrs/src/modules/core/views/components/layouts/Client.vue.js +2 -2
  71. package/dist/martyrs/src/modules/core/views/components/partials/Header.vue.js +2 -2
  72. package/dist/martyrs/src/modules/core/views/components/partials/NavigationBar.vue.js +1 -1
  73. package/dist/martyrs/src/modules/core/views/components/sections/filters/FilterRange.vue.js +1 -1
  74. package/dist/martyrs/src/modules/core/views/mixins/mixins.js +1 -2
  75. package/dist/martyrs/src/modules/core/views/mixins/mixins.js.map +1 -1
  76. package/dist/martyrs/src/modules/core/views/router/addRoutes.js +6 -1
  77. package/dist/martyrs/src/modules/core/views/router/addRoutes.js.map +1 -1
  78. package/dist/martyrs/src/modules/events/components/elements/ButtonCheck.vue.js +1 -1
  79. package/dist/martyrs/src/modules/events/components/elements/ButtonJoin.vue.js +1 -1
  80. package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +4 -4
  81. package/dist/martyrs/src/modules/events/components/pages/EditEventTickets.vue.js +2 -2
  82. package/dist/martyrs/src/modules/events/components/pages/Event.vue.js +2 -2
  83. package/dist/martyrs/src/modules/events/components/sections/EditTickets.vue.js +2 -2
  84. package/dist/martyrs/src/modules/events/components/sections/Feed.vue.js +1 -1
  85. package/dist/martyrs/src/modules/events/components/sections/List.vue.js +1 -1
  86. package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.js +4 -4
  87. package/dist/martyrs/src/modules/inventory/components/forms/AdjustmentForm.vue.js +3 -3
  88. package/dist/martyrs/src/modules/inventory/components/forms/ColumnSettingsMenu.vue.js +1 -1
  89. package/dist/martyrs/src/modules/inventory/components/forms/HistoryView.vue.js +1 -1
  90. package/dist/martyrs/src/modules/inventory/components/forms/StockAlertsForm.vue.js +3 -3
  91. package/dist/martyrs/src/modules/inventory/components/pages/InventoryEdit.vue.js +5 -5
  92. package/dist/martyrs/src/modules/inventory/components/pages/InventoryEdit.vue.js.map +1 -1
  93. package/dist/martyrs/src/modules/marketplace/views/components/pages/Marketplace.vue.js +1 -1
  94. package/dist/martyrs/src/modules/marketplace/views/components/sections/SectionMenu.vue.js +1 -1
  95. package/dist/martyrs/src/modules/music/components/cards/AlbumCard.vue.js +1 -1
  96. package/dist/martyrs/src/modules/music/components/cards/ArtistCardSmall.vue.js +1 -1
  97. package/dist/martyrs/src/modules/music/components/cards/PlaylistCard.vue.js +1 -1
  98. package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.js +1 -1
  99. package/dist/martyrs/src/modules/music/components/forms/AlbumForm.vue.js +3 -3
  100. package/dist/martyrs/src/modules/music/components/forms/ArtistForm.vue.js +4 -4
  101. package/dist/martyrs/src/modules/music/components/forms/PlaylistForm.vue.js +2 -2
  102. package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.js +1 -1
  103. package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.js +3 -3
  104. package/dist/martyrs/src/modules/music/components/pages/Album.vue.js +2 -2
  105. package/dist/martyrs/src/modules/music/components/pages/Artist.vue.js +2 -2
  106. package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.js +1 -1
  107. package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.js +2 -2
  108. package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.js +2 -2
  109. package/dist/martyrs/src/modules/music/components/pages/Track.vue.js +2 -2
  110. package/dist/martyrs/src/modules/music/components/pages/TrackCreate.vue.js +1 -1
  111. package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.js +1 -1
  112. package/dist/martyrs/src/modules/notifications/components/elements/NotificationBadge.vue.js +4 -4
  113. package/dist/martyrs/src/modules/notifications/components/elements/NotificationBadge.vue.js.map +1 -1
  114. package/dist/martyrs/src/modules/orders/components/elements/FieldSubscribeNewsletter.vue.js +3 -0
  115. package/dist/martyrs/src/modules/orders/components/elements/FieldSubscribeNewsletter.vue.js.map +1 -1
  116. package/dist/martyrs/src/modules/orders/components/forms/FormApplicationDetails.vue.js +3 -3
  117. package/dist/martyrs/src/modules/orders/components/forms/FormCustomerDetails.vue.js +3 -3
  118. package/dist/martyrs/src/modules/orders/components/forms/FormSelectCustomer.vue.js +2 -2
  119. package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.js +2 -2
  120. package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.js +1 -1
  121. package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +2 -2
  122. package/dist/martyrs/src/modules/orders/components/sections/ApplicationDetails.vue.js +1 -1
  123. package/dist/martyrs/src/modules/orders/components/sections/CustomerDetails.vue.js +1 -1
  124. package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js +2 -2
  125. package/dist/martyrs/src/modules/orders/components/sections/FormPayment.vue.js +1 -1
  126. package/dist/martyrs/src/modules/organizations/components/blocks/CardOrganization.vue.js +1 -1
  127. package/dist/martyrs/src/modules/organizations/components/blocks/CardOrganization.vue.js.map +1 -1
  128. package/dist/martyrs/src/modules/organizations/components/elements/ButtonToggleMembership.vue.js +1 -1
  129. package/dist/martyrs/src/modules/organizations/components/forms/AddExistingMembersForm.vue.js +1 -1
  130. package/dist/martyrs/src/modules/organizations/components/forms/DepartmentForm.vue.js +2 -2
  131. package/dist/martyrs/src/modules/organizations/components/forms/InviteForm.vue.js +2 -2
  132. package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js +1 -1
  133. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.js +2 -2
  134. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +5 -5
  135. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js.map +1 -1
  136. package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.js +3 -3
  137. package/dist/martyrs/src/modules/organizations/components/sections/MembersAdd.vue.js +3 -3
  138. package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +3 -3
  139. package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.js +2 -2
  140. package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.js +2 -2
  141. package/dist/martyrs/src/modules/pages/views/components/partials/SidebarPages.vue.js +1 -1
  142. package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.js +1 -1
  143. package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.js.map +1 -1
  144. package/dist/martyrs/src/modules/products/components/blocks/CardProduct.vue.js +15 -2
  145. package/dist/martyrs/src/modules/products/components/blocks/CardProduct.vue.js.map +1 -1
  146. package/dist/martyrs/src/modules/products/components/elements/Image360.vue.js +1 -1
  147. package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js +10 -7
  148. package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js.map +1 -1
  149. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +7 -6
  150. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js.map +1 -1
  151. package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +11 -2
  152. package/dist/martyrs/src/modules/products/components/pages/Product.vue.js.map +1 -1
  153. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +4 -4
  154. package/dist/martyrs/src/modules/products/components/pages/ProductRecommmendation.vue.js +1 -1
  155. package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +1 -1
  156. package/dist/martyrs/src/modules/products/components/sections/EditAttributes.vue.js +2 -2
  157. package/dist/martyrs/src/modules/products/components/sections/EditDiscounts.vue.js +3 -3
  158. package/dist/martyrs/src/modules/products/components/sections/EditVariants.vue.js +3 -3
  159. package/dist/martyrs/src/modules/products/components/sections/ProductConfigurator.vue.js +1 -1
  160. package/dist/martyrs/src/modules/products/components/sections/ProductsRecommended.vue.js +1 -1
  161. package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js +11 -8
  162. package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js.map +1 -1
  163. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.js +1 -1
  164. package/dist/martyrs/src/modules/rents/views/components/pages/RentsEdit.vue.js +211 -61
  165. package/dist/martyrs/src/modules/rents/views/components/pages/RentsEdit.vue.js.map +1 -1
  166. package/dist/martyrs/src/modules/reports/components/sections/FormReport.vue.js +2 -2
  167. package/dist/martyrs/src/modules/spots/components/blocks/SpotMemberModify.vue.js +2 -2
  168. package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.js +1 -1
  169. package/dist/martyrs/src/modules/spots/components/pages/Map.vue.js +4 -4
  170. package/dist/martyrs/src/modules/spots/components/pages/Map.vue.js.map +1 -1
  171. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +3 -3
  172. package/dist/martyrs/src/modules/spots/components/sections/WorktimeEdit.vue.js +3 -3
  173. package/dist/martyrs/src/modules/wallet/views/components/blocks/CardDeposit.vue.js +1 -1
  174. package/dist/martyrs/src/modules/wallet/views/components/blocks/CryptoDeposit.vue.js +2 -2
  175. package/dist/martyrs/src/modules/wallet/views/components/pages/Wallet.vue.js +2 -2
  176. package/dist/martyrs.css +1 -1
  177. package/dist/martyrs.es.js +1 -1
  178. package/dist/music.server.js +11 -12
  179. package/dist/notifications.server.js +0 -3
  180. package/dist/orders.server.js +5 -6
  181. package/dist/organizations.server.js +9 -10
  182. package/dist/products.server.js +27 -26
  183. package/dist/{queryProcessor-CBQgZycY.js → queryProcessor-C_5Iipam.js} +4 -1
  184. package/dist/rents.server.js +2 -3
  185. package/dist/spots.server.js +1 -1
  186. package/dist/style.css +38 -23
  187. package/dist/{web-cNKIl_cL.js → web-BF3ijvEr.js} +1 -1
  188. package/package.json +1 -1
  189. package/src/builder/modes/ssr.rspack.dev.js +4 -3
  190. package/src/builder/rspack/rspack.config.api.js +15 -4
  191. package/src/builder/rspack/rspack.config.base.js +3 -3
  192. package/src/builder/rspack/rspack.config.ssr.client.js +28 -28
  193. package/src/builder/templates/page.js +2 -2
  194. package/src/components/Button/Button.vue +50 -37
  195. package/src/components/FieldPhone/FieldPhone.vue +1 -1
  196. package/src/components/Loader/Loader.vue +1 -1
  197. package/src/components/Tree/Tree.vue +6 -3
  198. package/src/modules/PROCESS.md +0 -0
  199. package/src/modules/TASKS.MD +17 -0
  200. package/src/modules/auth/auth.client.js +11 -7
  201. package/src/modules/auth/views/components/pages/SignIn.vue +1 -1
  202. package/src/modules/auth/views/router/auth.router.js +94 -0
  203. package/src/modules/auth/views/router/users.router.js +153 -0
  204. package/src/modules/backoffice/components/partials/Sidebar.vue +7 -7
  205. package/src/modules/community/community.server.js +8 -0
  206. package/src/modules/community/policies/blog.policies.js +55 -0
  207. package/src/modules/community/routes/blog.routes.js +1 -1
  208. package/src/modules/community/routes/comments.routes.js +1 -1
  209. package/src/modules/community/routes/reactions.routes.js +1 -4
  210. package/src/modules/core/controllers/classes/abac/abac.adapter.express.js +206 -124
  211. package/src/modules/core/controllers/classes/abac/abac.adapter.ws.js +203 -50
  212. package/src/modules/core/controllers/classes/abac/abac.core.js +127 -36
  213. package/src/modules/core/controllers/classes/abac/abac.fields.js +144 -179
  214. package/src/modules/core/controllers/classes/abac/abac.js +201 -10
  215. package/src/modules/core/controllers/classes/abac/abac.policies.js +147 -57
  216. package/src/modules/core/controllers/classes/crud/crud.policies.js +5 -5
  217. package/src/modules/core/controllers/policies/core.policies.js +5 -2
  218. package/src/modules/core/controllers/utils/queryProcessor.js +4 -1
  219. package/src/modules/core/core.server.js +1 -0
  220. package/src/modules/core/locales/en.js +45 -0
  221. package/src/modules/core/locales/ru.js +45 -0
  222. package/src/modules/core/models/schemas/common.schema.js +1 -1
  223. package/src/modules/core/views/classes/i18n.manager.js +13 -0
  224. package/src/modules/core/views/components/sections/filters/FilterPrice.vue +81 -0
  225. package/src/modules/core/views/mixins/mixins.js +1 -2
  226. package/src/modules/core/views/router/addRoutes.js +6 -1
  227. package/src/modules/events/routes/events.routes.js +1 -1
  228. package/src/modules/inventory/components/pages/InventoryEdit.vue +3 -3
  229. package/src/modules/inventory/policies/inventory.policies.js +1 -1
  230. package/src/modules/inventory/routes/inventory.routes.js +1 -1
  231. package/src/modules/marketplace/marketplace.router.js +66 -0
  232. package/src/modules/marketplace/views/components/layouts/Marketplace.vue +363 -0
  233. package/src/modules/marketplace/views/components/pages/Catalog.vue +73 -0
  234. package/src/modules/music/controllers/stream.controller.js +1 -1
  235. package/src/modules/music/music.server.js +1 -1
  236. package/src/modules/music/policies/music.policies.js +3 -2
  237. package/src/modules/music/router/library.router.js +26 -0
  238. package/src/modules/music/router/music.router.js +176 -0
  239. package/src/modules/notifications/components/elements/NotificationBadge.vue +5 -6
  240. package/src/modules/notifications/notifications.server.js +1 -3
  241. package/src/modules/orders/components/elements/FieldSubscribeNewsletter.vue +5 -0
  242. package/src/modules/orders/orders.server.js +0 -1
  243. package/src/modules/organizations/components/blocks/CardOrganization.vue +2 -2
  244. package/src/modules/organizations/components/pages/DepartmentEdit.vue +2 -2
  245. package/src/modules/organizations/components/pages/OrganizationEdit.vue +2 -2
  246. package/src/modules/organizations/policies/organizations.policies.js +12 -6
  247. package/src/modules/organizations/routes/organizations.routes.js +1 -3
  248. package/src/modules/products/components/blocks/CardCategory.vue +1 -1
  249. package/src/modules/products/components/blocks/CardProduct.vue +16 -2
  250. package/src/modules/products/components/pages/Categories.vue +9 -6
  251. package/src/modules/products/components/pages/CategoryEdit.vue +8 -4
  252. package/src/modules/products/components/pages/Product.vue +11 -5
  253. package/src/modules/products/components/sections/SectionProduct.vue +11 -7
  254. package/src/modules/products/controllers/categories.controller.js +32 -27
  255. package/src/modules/products/routes/categories.routes.js +1 -1
  256. package/src/modules/rents/controllers/routes/rents.routes.js +1 -1
  257. package/src/modules/rents/views/components/pages/RentsEdit.vue +208 -49
  258. package/src/modules/spots/components/pages/Map.vue +2 -2
  259. package/dist/abac-DYoheWuc.js +0 -1031
  260. package/dist/core.abac-DUPBnlk6.js +0 -298
  261. package/dist/core.logger-C3q8A9dl.js +0 -51
  262. package/dist/martyrs/src/components/Button/Button.vue.js.map +0 -1
  263. package/dist/martyrs/src/components/Field/Field.vue2.js.map +0 -1
  264. package/dist/martyrs/src/components/Loader/Loader.vue2.js.map +0 -1
  265. package/dist/martyrs/src/components/Menu/Menu.vue.js.map +0 -1
  266. package/dist/martyrs/src/components/Select/Select.vue2.js.map +0 -1
  267. package/dist/martyrs/src/components/SelectMulti/SelectMulti.vue.js.map +0 -1
  268. package/dist/martyrs/src/modules/auth/auth.router.js +0 -342
  269. package/dist/martyrs/src/modules/auth/auth.router.js.map +0 -1
  270. package/src/modules/auth/auth.router.js +0 -262
  271. package/src/modules/core/controllers/classes/abac/v2/abac-core-fixed.js +0 -313
  272. package/src/modules/core/controllers/classes/abac/v2/abac-express-fixed.js +0 -276
  273. package/src/modules/core/controllers/classes/abac/v2/abac-fields-fixed.js +0 -425
  274. package/src/modules/core/controllers/classes/abac/v2/abac-main-fixed.js +0 -295
  275. package/src/modules/core/controllers/classes/abac/v2/abac-policies-fixed.js +0 -316
  276. package/src/modules/core/controllers/classes/abac/v2/abac-ws-fixed.js +0 -237
  277. package/src/modules/core/controllers/classes/core.abac.js +0 -310
  278. package/src/modules/core/controllers/classes/core.crud.js +0 -89
  279. package/src/modules/governance/reactcode/eslint.config.js +0 -28
@@ -1,1031 +0,0 @@
1
- import { C as CacheNamespaced } from "./core.cache-DALYFDdy.js";
2
- import { L as LoggerNamespaced } from "./core.logger-C3q8A9dl.js";
3
- class ABACCore {
4
- constructor(abac) {
5
- this.abac = abac;
6
- this.runningPolicies = /* @__PURE__ */ new Map();
7
- }
8
- // Нормализация контекста
9
- normalizeContext(input) {
10
- const context = {
11
- user: null,
12
- action: null,
13
- resource: null,
14
- currentResource: null,
15
- data: {},
16
- req: null,
17
- socket: null,
18
- params: {},
19
- _cache: /* @__PURE__ */ new Map(),
20
- _abac: this.abac,
21
- // Добавляем флаг для пропуска field policies (например, для админов)
22
- skipFieldPolicies: input.skipFieldPolicies || false
23
- };
24
- if (input.req) {
25
- context.user = input.user || input.req.userId;
26
- context.data = {
27
- ...input.req.body,
28
- ...input.req.query,
29
- params: input.req.params
30
- };
31
- context.params = input.req.params;
32
- context.req = input.req;
33
- } else if (input.socket) {
34
- context.user = input.user || input.socket.userId;
35
- context.socket = input.socket;
36
- context.data = input.data || {};
37
- }
38
- return Object.assign(context, input);
39
- }
40
- // Выполнение политики с кэшированием
41
- async executePolicyWithCache(policyName, policyFn, context) {
42
- const contextCacheKey = `${policyName}_${context.action}`;
43
- if (context._cache.has(contextCacheKey)) {
44
- return context._cache.get(contextCacheKey);
45
- }
46
- const globalCacheKey = `policy_${policyName}_${context.user}_${context.resource}_${context.action}`;
47
- if (this.abac.options.cacheEnabled) {
48
- const cached = await this.abac.cache.get(globalCacheKey);
49
- if (cached !== void 0) {
50
- context._cache.set(contextCacheKey, cached);
51
- return cached;
52
- }
53
- }
54
- const result = await policyFn(context);
55
- context._cache.set(contextCacheKey, result);
56
- if (this.abac.options.cacheEnabled) {
57
- await this.abac.cache.setWithTags(globalCacheKey, result, [
58
- `user_${context.user}`,
59
- `resource_${context.resource}`,
60
- `policy_${policyName}`
61
- ]);
62
- }
63
- return result;
64
- }
65
- // Выполнение политик с ограничением параллельности
66
- async executePoliciesLimited(policies, context, stopOnDeny = false) {
67
- const results = [];
68
- const limit = this.abac.options.concurrencyLimit;
69
- const batches = [];
70
- for (let i = 0; i < policies.length; i += limit) {
71
- batches.push(policies.slice(i, i + limit));
72
- }
73
- for (const batch of batches) {
74
- const batchPromises = batch.map(async ([name, policy]) => {
75
- try {
76
- const policyFn = typeof policy === "function" ? policy : policy.fn;
77
- const result = await this.executePolicyWithCache(name, policyFn, context);
78
- return { name, result: this.normalizeResult(result, name) };
79
- } catch (error) {
80
- console.error(`Error in policy ${name}:`, error);
81
- return {
82
- name,
83
- result: {
84
- allow: !this.abac.options.strictMode,
85
- reason: `POLICY_ERROR_${name.toUpperCase()}`
86
- },
87
- error
88
- };
89
- }
90
- });
91
- const batchResults = await Promise.all(batchPromises);
92
- results.push(...batchResults);
93
- if (stopOnDeny) {
94
- const shouldStop = batchResults.some((r) => !r.result.allow || r.result.force);
95
- if (shouldStop) break;
96
- }
97
- }
98
- return results;
99
- }
100
- // Нормализация результата политики
101
- normalizeResult(result, policyName) {
102
- if (this.abac.options.strictMode && result === void 0) {
103
- return { allow: false, force: false, reason: `UNDEFINED_IN_STRICT_MODE_${policyName.toUpperCase()}` };
104
- }
105
- if (result && typeof result === "object" && ("allow" in result || "force" in result)) {
106
- return {
107
- allow: result.allow !== void 0 ? !!result.allow : true,
108
- force: !!result.force,
109
- reason: result.reason || `POLICY_${policyName.toUpperCase()}`
110
- };
111
- }
112
- if (result === true) {
113
- return { allow: true, force: false, reason: `ALLOWED_BY_${policyName.toUpperCase()}` };
114
- }
115
- if (result === false) {
116
- return { allow: false, force: false, reason: `DENIED_BY_${policyName.toUpperCase()}` };
117
- }
118
- return { allow: !this.abac.options.strictMode, force: false, reason: `NEUTRAL_${policyName.toUpperCase()}` };
119
- }
120
- // Основной метод проверки доступа
121
- async checkAccess(rawContext, customPolicies = {}) {
122
- const startTime = Date.now();
123
- const context = this.normalizeContext(rawContext);
124
- if (context.isServiceRequest) {
125
- return { allow: true, reason: "SERVICE_REQUEST_ALLOWED" };
126
- }
127
- if (!context.user && !context.options?.allowUnauthenticated) {
128
- return { allow: false, reason: "UNAUTHENTICATED_ACCESS_DENIED" };
129
- }
130
- if (!context.currentResource && (context.data?._id || context.data?.params?._id || context.data?.url)) {
131
- await this.loadResource(context);
132
- }
133
- const result = await this.abac.policies.evaluate(context, customPolicies);
134
- if (this.abac.options.enableAudit) {
135
- await this.audit(context, result, Date.now() - startTime);
136
- }
137
- console.error("result logging:", result);
138
- return result;
139
- }
140
- // Загрузка ресурса
141
- async loadResource(context) {
142
- const resourceModel = this.abac.getResourceModel(context.resource);
143
- if (!resourceModel) return;
144
- try {
145
- let currentResource;
146
- const id = context.data._id || context.data.params?._id;
147
- if (id) {
148
- currentResource = await resourceModel.findById(id);
149
- } else if (context.data.url) {
150
- currentResource = await resourceModel.findOne({ url: context.data.url });
151
- }
152
- if (currentResource) {
153
- context.currentResource = currentResource;
154
- context.resourceModel = resourceModel;
155
- }
156
- } catch (error) {
157
- console.error("Resource loading error:", error);
158
- }
159
- }
160
- // Аудит
161
- async audit(context, result, duration) {
162
- try {
163
- let info = JSON.stringify({
164
- type: "ACCESS_CHECK",
165
- timestamp: /* @__PURE__ */ new Date(),
166
- user: context.user,
167
- resource: context.resource,
168
- action: context.action,
169
- result: result.allow,
170
- reason: result.reason,
171
- duration,
172
- metadata: context.auditMetadata || {}
173
- });
174
- await this.abac.logger.log("info", info);
175
- console.error("Audit logging:", info);
176
- } catch (error) {
177
- console.error("Audit logging error:", error);
178
- }
179
- }
180
- }
181
- class ABACPolicies {
182
- constructor(abac) {
183
- this.abac = abac;
184
- this.global = /* @__PURE__ */ new Map();
185
- this.resources = /* @__PURE__ */ new Map();
186
- this.extensions = /* @__PURE__ */ new Map();
187
- this.priorities = {
188
- static: [],
189
- dynamic: [],
190
- extensions: []
191
- };
192
- }
193
- registerGlobalPolicy(name, policyFn, metadata = {}) {
194
- if (typeof policyFn !== "function") {
195
- throw new Error(`Global policy "${name}" must be a function`);
196
- }
197
- const policy = {
198
- fn: policyFn,
199
- type: metadata.type || "dynamic",
200
- ...metadata
201
- };
202
- this.global.set(name, policy);
203
- this.updatePriorities();
204
- return this.abac;
205
- }
206
- registerResourcePolicy(resourceName, policyFn, options = {}) {
207
- if (typeof policyFn !== "function") {
208
- throw new Error(`Resource policy for "${resourceName}" must be a function`);
209
- }
210
- this.resources.set(resourceName, {
211
- fn: policyFn,
212
- modelName: options.modelName || options.model || resourceName,
213
- ...options
214
- });
215
- return this.abac;
216
- }
217
- registerExtension(moduleName, extensionFn) {
218
- if (typeof extensionFn !== "function") {
219
- throw new Error(`Extension "${moduleName}" must be a function`);
220
- }
221
- this.extensions.set(moduleName, extensionFn);
222
- this.updatePriorities();
223
- return this.abac;
224
- }
225
- updatePriorities() {
226
- this.priorities = {
227
- static: [],
228
- dynamic: [],
229
- extensions: []
230
- };
231
- for (const [name, policy] of this.global) {
232
- const type = policy.type || "dynamic";
233
- this.priorities[type].push([name, policy]);
234
- }
235
- this.priorities.extensions = Array.from(this.extensions.entries());
236
- }
237
- async evaluate(context, customPolicies = {}) {
238
- const core = this.abac.core;
239
- let hasForceAllow = false;
240
- let hasForceDisallow = false;
241
- let hasDeny = false;
242
- let denyReason = "";
243
- let allowReason = "";
244
- const processResult = (result) => {
245
- if (result.force) {
246
- if (result.allow) {
247
- hasForceAllow = true;
248
- allowReason = result.reason;
249
- } else {
250
- hasForceDisallow = true;
251
- denyReason = result.reason;
252
- }
253
- } else if (!result.allow) {
254
- hasDeny = true;
255
- if (!denyReason) denyReason = result.reason;
256
- }
257
- };
258
- const checkForceFlags = () => {
259
- if (hasForceDisallow) {
260
- return {
261
- allow: false,
262
- reason: denyReason || "FORCE_DENIED_BY_POLICY"
263
- };
264
- }
265
- if (hasForceAllow) {
266
- return {
267
- allow: true,
268
- reason: allowReason || "FORCE_ALLOWED_BY_POLICY"
269
- };
270
- }
271
- return null;
272
- };
273
- for (const type of ["static", "dynamic"]) {
274
- const policies = [...this.priorities[type]];
275
- if (type === "dynamic") {
276
- for (const [name, fn] of Object.entries(customPolicies)) {
277
- policies.push([name, { fn, type: "dynamic" }]);
278
- }
279
- }
280
- const results = await core.executePoliciesLimited(
281
- policies,
282
- context,
283
- type === "static"
284
- // Для static останавливаемся на deny
285
- );
286
- for (const { result, error } of results) {
287
- if (error) continue;
288
- processResult(result);
289
- }
290
- const forceResult = checkForceFlags();
291
- if (forceResult) return forceResult;
292
- }
293
- const resourcePolicy = this.resources.get(context.resource);
294
- if (resourcePolicy) {
295
- const results = await core.executePoliciesLimited(
296
- [[`RESOURCE_${context.resource}`, resourcePolicy]],
297
- context
298
- );
299
- if (!results[0].error) {
300
- processResult(results[0].result);
301
- }
302
- const forceResult = checkForceFlags();
303
- if (forceResult) return forceResult;
304
- }
305
- if (hasDeny) {
306
- return {
307
- allow: false,
308
- reason: denyReason || "DENIED_BY_POLICY"
309
- };
310
- }
311
- const extensionResults = await core.executePoliciesLimited(
312
- this.priorities.extensions,
313
- context
314
- );
315
- for (const { result } of extensionResults) {
316
- if (result.allow) {
317
- return { allow: true, reason: result.reason };
318
- }
319
- }
320
- const defaultAllow = !this.abac.options.defaultDeny;
321
- return {
322
- allow: defaultAllow,
323
- reason: defaultAllow ? "DEFAULT_ALLOW" : "DEFAULT_DENY"
324
- };
325
- }
326
- // Проверка конкретных политик
327
- async checkPolicies(rawContext, policyNames = [], customPolicies = {}) {
328
- const context = this.abac.core.normalizeContext(rawContext);
329
- const policies = this.getPoliciesByNames(policyNames, customPolicies);
330
- const results = await this.abac.core.executePoliciesLimited(
331
- Object.entries(policies),
332
- context,
333
- this.abac.options.strictMode
334
- );
335
- for (const { result } of results) {
336
- if (result.force) return { allow: result.allow, reason: result.reason };
337
- if (!result.allow && this.abac.options.strictMode) {
338
- return { allow: false, reason: result.reason };
339
- }
340
- }
341
- return { allow: true, reason: "POLICIES_PASSED" };
342
- }
343
- getPoliciesByNames(names, customPolicies = {}) {
344
- const policies = {};
345
- for (const name of names) {
346
- if (this.global.has(name)) {
347
- policies[name] = this.global.get(name);
348
- } else if (this.extensions.has(name)) {
349
- policies[name] = { fn: this.extensions.get(name), type: "extension" };
350
- }
351
- }
352
- Object.assign(policies, customPolicies);
353
- return policies;
354
- }
355
- }
356
- class ABACFields {
357
- constructor(abac) {
358
- this.abac = abac;
359
- this.configs = /* @__PURE__ */ new Map();
360
- }
361
- /**
362
- * Регистрация field policies
363
- */
364
- registerFieldsPolicy(resourceName, config) {
365
- const normalized = {};
366
- for (const [pattern, conf] of Object.entries(config)) {
367
- const { actions, ...baseSettings } = conf;
368
- const base = {
369
- actions: baseSettings.actions || "*",
370
- access: baseSettings.access || "allow",
371
- validator: baseSettings.validator || null,
372
- transform: baseSettings.transform || null,
373
- rule: baseSettings.rule || "remove",
374
- force: baseSettings.force || false,
375
- pattern
376
- };
377
- if (actions && typeof actions === "object") {
378
- normalized[pattern] = {
379
- base,
380
- actions: Object.entries(actions).reduce((acc, [action, override]) => {
381
- acc[action] = { ...base, ...override };
382
- return acc;
383
- }, {})
384
- };
385
- } else {
386
- normalized[pattern] = { base };
387
- }
388
- }
389
- this.configs.set(resourceName, normalized);
390
- return this;
391
- }
392
- /**
393
- * Проверка доступа к полям
394
- */
395
- async checkFields(context, data, action = null) {
396
- const normalizedContext = this.abac.core.normalizeContext(context);
397
- if (normalizedContext.skipFieldPolicies) {
398
- return {
399
- allowed: data,
400
- denied: [],
401
- errors: [],
402
- transformed: data
403
- };
404
- }
405
- const { resource } = normalizedContext;
406
- const fieldAction = action || normalizedContext.action;
407
- const config = normalizedContext.options?.fieldsConfig || this.configs.get(resource);
408
- if (!config) {
409
- return { allowed: data, denied: [], errors: [], transformed: data };
410
- }
411
- if (this.abac.policies && this.abac.policies.priorities.extensions.length > 0) {
412
- for (const [name, extensionFn] of this.abac.policies.priorities.extensions) {
413
- try {
414
- await extensionFn(normalizedContext);
415
- } catch (error) {
416
- console.error(`Extension ${name} error:`, error);
417
- }
418
- }
419
- }
420
- const result = {
421
- allowed: JSON.parse(JSON.stringify(data)),
422
- denied: [],
423
- errors: [],
424
- transformed: null
425
- };
426
- const rules = this._collectRules(data, config, fieldAction);
427
- const forced = rules.filter((r) => r.rule.force);
428
- const regular = rules.filter((r) => !r.rule.force);
429
- for (const { path, value, rule } of [...forced, ...regular]) {
430
- const processed = /* @__PURE__ */ new Set();
431
- if (processed.has(path)) continue;
432
- processed.add(path);
433
- const hasAccess = await this._checkFieldAccess(
434
- rule.access,
435
- normalizedContext,
436
- path,
437
- value
438
- );
439
- if (!hasAccess) {
440
- await this._handleDenied(result, path, rule.rule);
441
- continue;
442
- }
443
- if (rule.validator && rule.access !== "optional") {
444
- const validation = await this._validateField(
445
- rule.validator,
446
- value,
447
- normalizedContext,
448
- path
449
- );
450
- if (!validation.isValid) {
451
- result.errors.push({ path, errors: validation.errors });
452
- if (rule.rule === "error") {
453
- throw new Error(`Validation failed: ${path}`);
454
- }
455
- await this._handleDenied(result, path, rule.rule);
456
- }
457
- }
458
- }
459
- result.transformed = JSON.parse(JSON.stringify(result.allowed));
460
- for (const { path, value, rule } of [...forced, ...regular]) {
461
- if (!rule.transform) continue;
462
- const isDenied = result.denied.some((d) => d.path === path);
463
- if (isDenied) continue;
464
- const transformed = await this._transformField(
465
- rule.transform,
466
- value,
467
- normalizedContext,
468
- path,
469
- result.transformed
470
- );
471
- this._setValue(result.transformed, path, transformed);
472
- }
473
- return result;
474
- }
475
- /**
476
- * Проверка доступа к полю
477
- * @private
478
- */
479
- async _checkFieldAccess(access, context, fieldPath, fieldValue) {
480
- if (access === "allow") return true;
481
- if (access === "deny") return false;
482
- if (access === "optional") return true;
483
- if (typeof access === "function") {
484
- try {
485
- return !!await access(context, fieldPath, fieldValue);
486
- } catch (e) {
487
- console.error("Field access check error:", e);
488
- return false;
489
- }
490
- }
491
- return true;
492
- }
493
- /**
494
- * Валидация поля
495
- * @private
496
- */
497
- async _validateField(validator, value, context, fieldPath) {
498
- if (typeof validator === "function") {
499
- try {
500
- const result = await validator(value, context, fieldPath);
501
- if (typeof result === "boolean") {
502
- return { isValid: result, errors: result ? [] : ["Validation failed"] };
503
- }
504
- return result;
505
- } catch (e) {
506
- return { isValid: false, errors: [e.message] };
507
- }
508
- }
509
- if (validator && validator.validate) {
510
- return validator.validate(value);
511
- }
512
- return { isValid: true, errors: [] };
513
- }
514
- /**
515
- * Трансформация поля
516
- * @private
517
- */
518
- async _transformField(transform, value, context, fieldPath, currentData) {
519
- try {
520
- return await transform(value, context, fieldPath, currentData);
521
- } catch (error) {
522
- console.error("Field transform error:", error);
523
- return value;
524
- }
525
- }
526
- /**
527
- * Сбор применимых правил
528
- * @private
529
- */
530
- _collectRules(data, config, action) {
531
- const rules = [];
532
- const patterns = Object.keys(config);
533
- const dataPaths = this._extractPaths(data);
534
- for (const path of dataPaths) {
535
- for (const pattern of patterns) {
536
- if (this._matchesPattern(path, pattern)) {
537
- const fieldConfig = config[pattern];
538
- let rule;
539
- if (fieldConfig.actions && fieldConfig.actions[action]) {
540
- rule = fieldConfig.actions[action];
541
- } else {
542
- rule = fieldConfig.base;
543
- }
544
- if (this._matchesAction(rule.actions, action)) {
545
- rules.push({
546
- path,
547
- value: this._getValue(data, path),
548
- rule
549
- });
550
- break;
551
- }
552
- }
553
- }
554
- }
555
- return rules;
556
- }
557
- /**
558
- * Проверка паттерна
559
- * @private
560
- */
561
- _matchesPattern(path, pattern) {
562
- if (pattern === path) return true;
563
- if (pattern === "*") return true;
564
- const pathParts = path.split(".");
565
- const patternParts = pattern.split(".");
566
- for (let i = 0; i < patternParts.length; i++) {
567
- const pp = patternParts[i];
568
- const pathPart = pathParts[i];
569
- if (pp === "**") return true;
570
- if (pp === "*" && pathPart !== void 0) continue;
571
- if (pp === "[*]" && /^\[\d+\]$/.test(pathPart)) continue;
572
- if (pp !== pathPart) return false;
573
- }
574
- return pathParts.length === patternParts.length;
575
- }
576
- /**
577
- * Извлечение путей
578
- * @private
579
- */
580
- _extractPaths(obj, prefix = "") {
581
- const paths = [];
582
- if (!obj || typeof obj !== "object") return paths;
583
- if (Array.isArray(obj)) {
584
- obj.forEach((item, i) => {
585
- const path = prefix ? `${prefix}[${i}]` : `[${i}]`;
586
- paths.push(path);
587
- paths.push(...this._extractPaths(item, path));
588
- });
589
- } else {
590
- for (const key in obj) {
591
- if (obj.hasOwnProperty(key)) {
592
- const path = prefix ? `${prefix}.${key}` : key;
593
- paths.push(path);
594
- if (obj[key] && typeof obj[key] === "object") {
595
- paths.push(...this._extractPaths(obj[key], path));
596
- }
597
- }
598
- }
599
- }
600
- return paths;
601
- }
602
- /**
603
- * Проверка доступа
604
- * @private
605
- */
606
- async _checkAccess(access, ctx) {
607
- if (access === "allow") return true;
608
- if (access === "deny") return false;
609
- if (access === "optional") return true;
610
- if (typeof access === "function") {
611
- try {
612
- return !!await access(ctx);
613
- } catch (e) {
614
- console.error("Access check error:", e);
615
- return false;
616
- }
617
- }
618
- return true;
619
- }
620
- /**
621
- * Валидация
622
- * @private
623
- */
624
- async _validate(validator, value, ctx) {
625
- if (typeof validator === "function") {
626
- try {
627
- const result = await validator(value, ctx);
628
- if (typeof result === "boolean") {
629
- return { isValid: result, errors: result ? [] : ["Validation failed"] };
630
- }
631
- return result;
632
- } catch (e) {
633
- return { isValid: false, errors: [e.message] };
634
- }
635
- }
636
- if (validator && validator.validate) {
637
- return validator.validate(value);
638
- }
639
- return { isValid: true, errors: [] };
640
- }
641
- /**
642
- * Обработка отказа
643
- * @private
644
- */
645
- async _handleDenied(result, path, rule, ctx) {
646
- result.denied.push({ path, reason: rule });
647
- if (rule === "remove") {
648
- this._removePath(result.allowed, path);
649
- } else if (rule === "error") {
650
- throw new Error(`Access denied: ${path}`);
651
- }
652
- }
653
- /**
654
- * Проверка действия
655
- * @private
656
- */
657
- _matchesAction(actions, action) {
658
- if (actions === "*") return true;
659
- return Array.isArray(actions) ? actions.includes(action) : actions === action;
660
- }
661
- /**
662
- * Получение значения
663
- * @private
664
- */
665
- _getValue(obj, path) {
666
- const parts = path.split(/\.|\[|\]/).filter(Boolean);
667
- let current = obj;
668
- for (const part of parts) {
669
- if (!current) return void 0;
670
- current = /^\d+$/.test(part) ? current[parseInt(part)] : current[part];
671
- }
672
- return current;
673
- }
674
- /**
675
- * Установка значения
676
- * @private
677
- */
678
- _setValue(obj, path, value) {
679
- const parts = path.split(/\.|\[|\]/).filter(Boolean);
680
- let current = obj;
681
- for (let i = 0; i < parts.length - 1; i++) {
682
- const part = parts[i];
683
- const next = parts[i + 1];
684
- const isArray = /^\d+$/.test(next);
685
- if (!current[part]) {
686
- current[part] = isArray ? [] : {};
687
- }
688
- current = current[part];
689
- }
690
- const last = parts[parts.length - 1];
691
- if (/^\d+$/.test(last)) {
692
- current[parseInt(last)] = value;
693
- } else {
694
- current[last] = value;
695
- }
696
- }
697
- /**
698
- * Удаление пути
699
- * @private
700
- */
701
- _removePath(obj, path) {
702
- const parts = path.split(/\.|\[|\]/).filter(Boolean);
703
- let current = obj;
704
- for (let i = 0; i < parts.length - 1; i++) {
705
- const part = /^\d+$/.test(parts[i]) ? parseInt(parts[i]) : parts[i];
706
- if (!current[part]) return;
707
- current = current[part];
708
- }
709
- const last = parts[parts.length - 1];
710
- if (/^\d+$/.test(last)) {
711
- current.splice(parseInt(last), 1);
712
- } else {
713
- delete current[last];
714
- }
715
- }
716
- getConfig(resourceName) {
717
- return this.configs.get(resourceName);
718
- }
719
- hasConfig(resourceName) {
720
- return this.configs.has(resourceName);
721
- }
722
- removeConfig(resourceName) {
723
- return this.configs.delete(resourceName);
724
- }
725
- }
726
- class ABACExpressAdapter {
727
- constructor(abac) {
728
- this.abac = abac;
729
- }
730
- middleware(resource, action, options = {}) {
731
- return async (req, res, next) => {
732
- try {
733
- const context = {
734
- user: req.userId,
735
- resource,
736
- action,
737
- req,
738
- data: {
739
- ...req.body,
740
- ...req.query,
741
- params: req.params
742
- },
743
- params: req.params,
744
- customPolicies: options.policies || {},
745
- options
746
- };
747
- const accessResult = await this.abac.checkAccess(context, context.customPolicies);
748
- if (!accessResult.allow) {
749
- return res.status(403).json({
750
- error: {
751
- code: "ACCESS_DENIED",
752
- message: accessResult.reason
753
- }
754
- });
755
- }
756
- if (options.checkFields) {
757
- const fieldsResult = await this.abac.checkFields(context, req.body, action);
758
- if (fieldsResult.errors.length > 0 && options.strictFieldsMode) {
759
- return res.status(400).json({
760
- error: {
761
- code: "FIELD_VALIDATION_ERROR",
762
- fields: fieldsResult.errors
763
- }
764
- });
765
- }
766
- req.body = fieldsResult.allowed;
767
- req.abacFieldsResult = fieldsResult;
768
- }
769
- next();
770
- } catch (error) {
771
- console.error("ABAC middleware error:", error);
772
- res.status(500).json({
773
- error: {
774
- code: "INTERNAL_ERROR",
775
- message: "Access control error"
776
- }
777
- });
778
- }
779
- };
780
- }
781
- policyMiddleware(policyNames = [], customPolicies = {}, options = {}) {
782
- return async (req, res, next) => {
783
- try {
784
- const context = {
785
- user: req.userId,
786
- resource: options.resource || "custom",
787
- action: options.action || "access",
788
- req,
789
- data: {
790
- ...req.body,
791
- ...req.query,
792
- params: req.params
793
- },
794
- params: req.params,
795
- options
796
- };
797
- const result = await this.abac.checkPolicies(context, policyNames, customPolicies);
798
- if (!result.allow) {
799
- return res.status(403).json({
800
- error: {
801
- code: "POLICY_DENIED",
802
- message: result.reason
803
- }
804
- });
805
- }
806
- next();
807
- } catch (error) {
808
- console.error("Policy middleware error:", error);
809
- res.status(500).json({
810
- error: {
811
- code: "INTERNAL_ERROR",
812
- message: "Policy check error"
813
- }
814
- });
815
- }
816
- };
817
- }
818
- fieldsMiddleware(resource, options = {}) {
819
- return async (req, res, next) => {
820
- try {
821
- const methodActionMap = {
822
- "GET": "read",
823
- "POST": "create",
824
- "PUT": "update",
825
- "PATCH": "update",
826
- "DELETE": "delete"
827
- };
828
- const action = options.action || methodActionMap[req.method] || "access";
829
- const context = {
830
- user: req.userId,
831
- resource,
832
- action,
833
- req,
834
- data: {
835
- ...req.body,
836
- ...req.query,
837
- params: req.params
838
- },
839
- params: req.params,
840
- options
841
- };
842
- let dataToCheck = req.body;
843
- if (req.method === "GET" && options.checkQuery) {
844
- dataToCheck = req.query;
845
- }
846
- if (options.checkResponse && res.locals.data) {
847
- dataToCheck = res.locals.data;
848
- }
849
- const fieldsResult = await this.abac.checkFields(context, dataToCheck, action);
850
- if (fieldsResult.errors.length > 0) {
851
- if (options.strictMode) {
852
- return res.status(400).json({
853
- error: {
854
- code: "FIELD_VALIDATION_ERROR",
855
- fields: fieldsResult.errors
856
- }
857
- });
858
- }
859
- console.warn("Field validation errors:", fieldsResult.errors);
860
- }
861
- if (req.method === "GET" && options.checkQuery) {
862
- req.query = fieldsResult.allowed;
863
- } else if (options.checkResponse && res.locals.data) {
864
- res.locals.data = fieldsResult.transformed || fieldsResult.allowed;
865
- } else {
866
- req.body = fieldsResult.allowed;
867
- }
868
- req.abacFieldsResult = fieldsResult;
869
- next();
870
- } catch (error) {
871
- console.error("Fields middleware error:", error);
872
- if (options.passErrors) {
873
- next(error);
874
- } else {
875
- res.status(500).json({
876
- error: {
877
- code: "INTERNAL_ERROR",
878
- message: "Field check error"
879
- }
880
- });
881
- }
882
- }
883
- };
884
- }
885
- }
886
- class ABACWebSocketAdapter {
887
- constructor(abac) {
888
- this.abac = abac;
889
- }
890
- handler(moduleName, options = {}) {
891
- return async (ws, message) => {
892
- try {
893
- const { action = "access", resource = moduleName } = options;
894
- const context = {
895
- user: ws.userId,
896
- resource,
897
- action,
898
- data: message,
899
- socket: ws,
900
- customPolicies: options.policies || {}
901
- };
902
- const accessResult = await this.abac.checkAccess(context, context.customPolicies);
903
- if (!accessResult.allow) {
904
- ws.send(JSON.stringify({
905
- type: "error",
906
- error: {
907
- code: "ACCESS_DENIED",
908
- message: accessResult.reason
909
- }
910
- }));
911
- return false;
912
- }
913
- return true;
914
- } catch (error) {
915
- console.error("WebSocket access control error:", error);
916
- ws.send(JSON.stringify({
917
- type: "error",
918
- error: {
919
- code: "INTERNAL_ERROR",
920
- message: "Access control error"
921
- }
922
- }));
923
- return false;
924
- }
925
- };
926
- }
927
- // Метод для RPC вызовов через WebSocket
928
- rpcHandler(module, method, options = {}) {
929
- return async (params, context) => {
930
- const abacContext = {
931
- user: context.userId,
932
- resource: module,
933
- action: method,
934
- data: params,
935
- socket: context.ws,
936
- customPolicies: options.policies || {}
937
- };
938
- const accessResult = await this.abac.checkAccess(abacContext, abacContext.customPolicies);
939
- if (!accessResult.allow) {
940
- throw new Error(accessResult.reason);
941
- }
942
- if (options.checkFields && params) {
943
- const fieldsResult = await this.abac.checkFields(abacContext, params, method);
944
- if (fieldsResult.denied.length > 0) {
945
- if (options.strictFieldsMode) {
946
- throw new Error(`Fields access denied: ${fieldsResult.denied.map((d) => d.path).join(", ")}`);
947
- }
948
- return fieldsResult.allowed;
949
- }
950
- return fieldsResult.transformed || params;
951
- }
952
- return params;
953
- };
954
- }
955
- }
956
- class GlobalABAC {
957
- constructor(db, options = {}) {
958
- this.db = db;
959
- this.options = {
960
- strictMode: false,
961
- defaultDeny: false,
962
- serviceKey: process.env.SERVICE_KEY,
963
- enableAudit: true,
964
- cacheEnabled: true,
965
- cacheTTL: 300,
966
- // 5 минут
967
- concurrencyLimit: 10,
968
- ...options
969
- };
970
- this.cache = new CacheNamespaced({ ttlSeconds: this.options.cacheTTL });
971
- this.logger = options.auditLogger || new LoggerNamespaced(db);
972
- this.core = new ABACCore(this);
973
- this.policies = new ABACPolicies(this);
974
- this.fields = new ABACFields(this);
975
- this.express = new ABACExpressAdapter(this);
976
- this.websocket = new ABACWebSocketAdapter(this);
977
- }
978
- // API методы для регистрации политик
979
- registerGlobalPolicy(name, policyFn, metadata = {}) {
980
- return this.policies.registerGlobalPolicy(name, policyFn, metadata);
981
- }
982
- registerResourcePolicy(resourceName, policyFn, options = {}) {
983
- return this.policies.registerResourcePolicy(resourceName, policyFn, options);
984
- }
985
- registerFieldsPolicy(resourceName, builderFn) {
986
- return this.fields.registerFieldsPolicy(resourceName, builderFn);
987
- }
988
- registerExtension(moduleName, extensionFn) {
989
- return this.policies.registerExtension(moduleName, extensionFn);
990
- }
991
- // Основные методы проверки
992
- async checkAccess(context, customPolicies = {}) {
993
- return this.core.checkAccess(context, customPolicies);
994
- }
995
- async checkFields(context, data, action = null, isQuery = false) {
996
- return this.fields.checkFields(context, data, action, isQuery);
997
- }
998
- async checkPolicies(context, policyNames = [], customPolicies = {}) {
999
- return this.policies.checkPolicies(context, policyNames, customPolicies);
1000
- }
1001
- // Адаптеры
1002
- middleware(resource, action, options = {}) {
1003
- return this.express.middleware(resource, action, options);
1004
- }
1005
- policyMiddleware(policyNames = [], customPolicies = {}, options = {}) {
1006
- return this.express.policyMiddleware(policyNames, customPolicies, options);
1007
- }
1008
- fieldsMiddleware(resource, options = {}) {
1009
- return this.express.fieldsMiddleware(resource, options);
1010
- }
1011
- wsHandler(moduleName, options = {}) {
1012
- return this.websocket.handler(moduleName, options);
1013
- }
1014
- getResourceModel(resourceName) {
1015
- const resourcePolicy = this.policies.resources.get(resourceName);
1016
- if (!resourcePolicy) return null;
1017
- const modelName = resourcePolicy.modelName || resourceName;
1018
- return this.db[modelName] || null;
1019
- }
1020
- }
1021
- let instance = null;
1022
- const getInstance = (db, options) => {
1023
- if (!instance) {
1024
- instance = new GlobalABAC(db, options);
1025
- }
1026
- return instance;
1027
- };
1028
- const ABAC = { getInstance };
1029
- export {
1030
- ABAC as A
1031
- };