@ozdao/martyrs 0.2.563 → 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 (207) 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.vue2.js +33 -42
  13. package/dist/martyrs/src/components/Button/Button.vue2.js.map +1 -1
  14. package/dist/martyrs/src/components/EditImages/{EditImages.vue.js → EditImages.vue2.js} +2 -2
  15. package/dist/martyrs/src/components/EditImages/EditImages.vue2.js.map +1 -0
  16. package/dist/martyrs/src/components/Feed/Feed.vue.js +1 -1
  17. package/dist/martyrs/src/components/FieldPhone/FieldPhone.vue.js +1 -1
  18. package/dist/martyrs/src/components/FieldPhone/FieldPhone.vue.js.map +1 -1
  19. package/dist/martyrs/src/components/Loader/Loader.vue.js +1 -2
  20. package/dist/martyrs/src/components/Loader/Loader.vue.js.map +1 -1
  21. package/dist/martyrs/src/components/Menu/{Menu.vue.js → Menu.vue2.js} +2 -2
  22. package/dist/martyrs/src/components/Menu/Menu.vue2.js.map +1 -0
  23. package/dist/martyrs/src/components/Tab/{Tab.vue.js → Tab.vue2.js} +2 -2
  24. package/dist/martyrs/src/components/Tab/Tab.vue2.js.map +1 -0
  25. package/dist/martyrs/src/components/Tree/Tree.vue.js +6 -3
  26. package/dist/martyrs/src/components/Tree/Tree.vue.js.map +1 -1
  27. package/dist/martyrs/src/modules/auth/auth.client.js +10 -7
  28. package/dist/martyrs/src/modules/auth/auth.client.js.map +1 -1
  29. package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +1 -1
  30. package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +1 -1
  31. package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +1 -1
  32. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileBlogposts.vue.js +1 -1
  33. package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +1 -1
  34. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +12 -12
  35. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js.map +1 -1
  36. package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +1 -1
  37. package/dist/martyrs/src/modules/auth/views/router/auth.router.js +116 -0
  38. package/dist/martyrs/src/modules/auth/views/router/auth.router.js.map +1 -0
  39. package/dist/martyrs/src/modules/auth/views/router/users.router.js +180 -0
  40. package/dist/martyrs/src/modules/auth/views/router/users.router.js.map +1 -0
  41. package/dist/martyrs/src/modules/backoffice/components/partials/Sidebar.vue.js +3 -3
  42. package/dist/martyrs/src/modules/backoffice/components/partials/Sidebar.vue.js.map +1 -1
  43. package/dist/martyrs/src/modules/core/locales/en.js +45 -0
  44. package/dist/martyrs/src/modules/core/locales/en.js.map +1 -1
  45. package/dist/martyrs/src/modules/core/locales/ru.js +45 -0
  46. package/dist/martyrs/src/modules/core/locales/ru.js.map +1 -1
  47. package/dist/martyrs/src/modules/core/views/classes/i18n.manager.js +9 -0
  48. package/dist/martyrs/src/modules/core/views/classes/i18n.manager.js.map +1 -1
  49. package/dist/martyrs/src/modules/core/views/components/sections/{Filters.vue.js → Filters.vue2.js} +2 -2
  50. package/dist/martyrs/src/modules/core/views/components/sections/Filters.vue2.js.map +1 -0
  51. package/dist/martyrs/src/modules/core/views/components/sections/SectionPageTitle.vue.js +1 -1
  52. package/dist/martyrs/src/modules/core/views/mixins/mixins.js +1 -2
  53. package/dist/martyrs/src/modules/core/views/mixins/mixins.js.map +1 -1
  54. package/dist/martyrs/src/modules/core/views/router/addRoutes.js +6 -1
  55. package/dist/martyrs/src/modules/core/views/router/addRoutes.js.map +1 -1
  56. package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +1 -1
  57. package/dist/martyrs/src/modules/events/components/pages/Event.vue.js +1 -1
  58. package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.js +1 -1
  59. package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.js +1 -1
  60. package/dist/martyrs/src/modules/inventory/components/pages/InventoryEdit.vue.js +2 -2
  61. package/dist/martyrs/src/modules/inventory/components/pages/InventoryEdit.vue.js.map +1 -1
  62. package/dist/martyrs/src/modules/marketplace/views/components/pages/Marketplace.vue.js +1 -1
  63. package/dist/martyrs/src/modules/marketplace/views/store/marketplace.js +0 -16
  64. package/dist/martyrs/src/modules/marketplace/views/store/marketplace.js.map +1 -1
  65. package/dist/martyrs/src/modules/notifications/components/elements/NotificationBadge.vue.js +4 -4
  66. package/dist/martyrs/src/modules/notifications/components/elements/NotificationBadge.vue.js.map +1 -1
  67. package/dist/martyrs/src/modules/notifications/components/pages/Notifications.vue.js +1 -1
  68. package/dist/martyrs/src/modules/orders/components/elements/FieldSubscribeNewsletter.vue.js +3 -0
  69. package/dist/martyrs/src/modules/orders/components/elements/FieldSubscribeNewsletter.vue.js.map +1 -1
  70. package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +1 -1
  71. package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.js +1 -1
  72. package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js +1 -1
  73. package/dist/martyrs/src/modules/organizations/components/blocks/CardOrganization.vue.js +1 -1
  74. package/dist/martyrs/src/modules/organizations/components/blocks/CardOrganization.vue.js.map +1 -1
  75. package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js +1 -1
  76. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.js +1 -1
  77. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +2 -2
  78. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js.map +1 -1
  79. package/dist/martyrs/src/modules/organizations/components/pages/Organizations.vue.js +1 -1
  80. package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +1 -1
  81. package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.js +1 -1
  82. package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.js.map +1 -1
  83. package/dist/martyrs/src/modules/products/components/blocks/CardProduct.vue.js +15 -2
  84. package/dist/martyrs/src/modules/products/components/blocks/CardProduct.vue.js.map +1 -1
  85. package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js +9 -6
  86. package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js.map +1 -1
  87. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +4 -3
  88. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js.map +1 -1
  89. package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +11 -2
  90. package/dist/martyrs/src/modules/products/components/pages/Product.vue.js.map +1 -1
  91. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +2 -2
  92. package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +2 -2
  93. package/dist/martyrs/src/modules/products/components/sections/EditVariants.vue.js +1 -1
  94. package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js +11 -8
  95. package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js.map +1 -1
  96. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.js +1 -1
  97. package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.js +1 -1
  98. package/dist/martyrs/src/modules/rents/views/components/pages/RentsEdit.vue.js +210 -60
  99. package/dist/martyrs/src/modules/rents/views/components/pages/RentsEdit.vue.js.map +1 -1
  100. package/dist/martyrs/src/modules/spots/components/pages/Map.vue.js +3 -3
  101. package/dist/martyrs/src/modules/spots/components/pages/Map.vue.js.map +1 -1
  102. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +1 -1
  103. package/dist/martyrs.css +1 -1
  104. package/dist/martyrs.es.js +1 -1
  105. package/dist/music.server.js +11 -12
  106. package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/utils.js +1 -1
  107. package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/utils.js +1 -1
  108. package/dist/notifications.server.js +0 -3
  109. package/dist/orders.server.js +5 -6
  110. package/dist/organizations.server.js +9 -10
  111. package/dist/products.server.js +27 -26
  112. package/dist/{queryProcessor-CBQgZycY.js → queryProcessor-C_5Iipam.js} +4 -1
  113. package/dist/rents.server.js +2 -3
  114. package/dist/spots.server.js +1 -1
  115. package/dist/style.css +38 -23
  116. package/dist/{web-cNKIl_cL.js → web-BF3ijvEr.js} +1 -1
  117. package/package.json +1 -1
  118. package/src/builder/modes/ssr.rspack.dev.js +4 -3
  119. package/src/builder/rspack/rspack.config.api.js +15 -4
  120. package/src/builder/rspack/rspack.config.base.js +3 -3
  121. package/src/builder/rspack/rspack.config.ssr.client.js +28 -28
  122. package/src/builder/templates/page.js +2 -2
  123. package/src/components/Button/Button.vue +50 -37
  124. package/src/components/FieldPhone/FieldPhone.vue +1 -1
  125. package/src/components/Loader/Loader.vue +1 -1
  126. package/src/components/Tree/Tree.vue +6 -3
  127. package/src/modules/PROCESS.md +0 -0
  128. package/src/modules/TASKS.MD +17 -0
  129. package/src/modules/auth/auth.client.js +11 -7
  130. package/src/modules/auth/views/components/pages/SignIn.vue +1 -1
  131. package/src/modules/auth/views/router/auth.router.js +94 -0
  132. package/src/modules/auth/views/router/users.router.js +153 -0
  133. package/src/modules/backoffice/components/partials/Sidebar.vue +7 -7
  134. package/src/modules/community/community.server.js +8 -0
  135. package/src/modules/community/policies/blog.policies.js +55 -0
  136. package/src/modules/community/routes/blog.routes.js +1 -1
  137. package/src/modules/community/routes/comments.routes.js +1 -1
  138. package/src/modules/community/routes/reactions.routes.js +1 -4
  139. package/src/modules/core/controllers/classes/abac/abac.adapter.express.js +206 -124
  140. package/src/modules/core/controllers/classes/abac/abac.adapter.ws.js +203 -50
  141. package/src/modules/core/controllers/classes/abac/abac.core.js +127 -36
  142. package/src/modules/core/controllers/classes/abac/abac.fields.js +144 -179
  143. package/src/modules/core/controllers/classes/abac/abac.js +201 -10
  144. package/src/modules/core/controllers/classes/abac/abac.policies.js +147 -57
  145. package/src/modules/core/controllers/classes/crud/crud.policies.js +5 -5
  146. package/src/modules/core/controllers/policies/core.policies.js +5 -2
  147. package/src/modules/core/controllers/utils/queryProcessor.js +4 -1
  148. package/src/modules/core/core.server.js +1 -0
  149. package/src/modules/core/locales/en.js +45 -0
  150. package/src/modules/core/locales/ru.js +45 -0
  151. package/src/modules/core/models/schemas/common.schema.js +1 -1
  152. package/src/modules/core/views/classes/i18n.manager.js +13 -0
  153. package/src/modules/core/views/components/sections/filters/FilterPrice.vue +81 -0
  154. package/src/modules/core/views/mixins/mixins.js +1 -2
  155. package/src/modules/core/views/router/addRoutes.js +6 -1
  156. package/src/modules/events/routes/events.routes.js +1 -1
  157. package/src/modules/inventory/components/pages/InventoryEdit.vue +3 -3
  158. package/src/modules/inventory/policies/inventory.policies.js +1 -1
  159. package/src/modules/inventory/routes/inventory.routes.js +1 -1
  160. package/src/modules/marketplace/marketplace.router.js +66 -0
  161. package/src/modules/marketplace/views/components/layouts/Marketplace.vue +363 -0
  162. package/src/modules/marketplace/views/components/pages/Catalog.vue +73 -0
  163. package/src/modules/marketplace/views/store/marketplace.js +0 -16
  164. package/src/modules/music/controllers/stream.controller.js +1 -1
  165. package/src/modules/music/music.server.js +1 -1
  166. package/src/modules/music/policies/music.policies.js +3 -2
  167. package/src/modules/music/router/library.router.js +26 -0
  168. package/src/modules/music/router/music.router.js +176 -0
  169. package/src/modules/notifications/components/elements/NotificationBadge.vue +5 -6
  170. package/src/modules/notifications/notifications.server.js +1 -3
  171. package/src/modules/orders/components/elements/FieldSubscribeNewsletter.vue +5 -0
  172. package/src/modules/orders/orders.server.js +0 -1
  173. package/src/modules/organizations/components/blocks/CardOrganization.vue +2 -2
  174. package/src/modules/organizations/components/pages/DepartmentEdit.vue +2 -2
  175. package/src/modules/organizations/components/pages/OrganizationEdit.vue +2 -2
  176. package/src/modules/organizations/policies/organizations.policies.js +12 -6
  177. package/src/modules/organizations/routes/organizations.routes.js +1 -3
  178. package/src/modules/products/components/blocks/CardCategory.vue +1 -1
  179. package/src/modules/products/components/blocks/CardProduct.vue +16 -2
  180. package/src/modules/products/components/pages/Categories.vue +9 -6
  181. package/src/modules/products/components/pages/CategoryEdit.vue +8 -4
  182. package/src/modules/products/components/pages/Product.vue +11 -5
  183. package/src/modules/products/components/sections/SectionProduct.vue +11 -7
  184. package/src/modules/products/controllers/categories.controller.js +32 -27
  185. package/src/modules/products/routes/categories.routes.js +1 -1
  186. package/src/modules/rents/controllers/routes/rents.routes.js +1 -1
  187. package/src/modules/rents/views/components/pages/RentsEdit.vue +208 -49
  188. package/src/modules/spots/components/pages/Map.vue +2 -2
  189. package/dist/abac-DYoheWuc.js +0 -1031
  190. package/dist/core.abac-DUPBnlk6.js +0 -298
  191. package/dist/core.logger-C3q8A9dl.js +0 -51
  192. package/dist/martyrs/src/components/EditImages/EditImages.vue.js.map +0 -1
  193. package/dist/martyrs/src/components/Menu/Menu.vue.js.map +0 -1
  194. package/dist/martyrs/src/components/Tab/Tab.vue.js.map +0 -1
  195. package/dist/martyrs/src/modules/auth/auth.router.js +0 -342
  196. package/dist/martyrs/src/modules/auth/auth.router.js.map +0 -1
  197. package/dist/martyrs/src/modules/core/views/components/sections/Filters.vue.js.map +0 -1
  198. package/src/modules/auth/auth.router.js +0 -262
  199. package/src/modules/core/controllers/classes/abac/v2/abac-core-fixed.js +0 -313
  200. package/src/modules/core/controllers/classes/abac/v2/abac-express-fixed.js +0 -276
  201. package/src/modules/core/controllers/classes/abac/v2/abac-fields-fixed.js +0 -425
  202. package/src/modules/core/controllers/classes/abac/v2/abac-main-fixed.js +0 -295
  203. package/src/modules/core/controllers/classes/abac/v2/abac-policies-fixed.js +0 -316
  204. package/src/modules/core/controllers/classes/abac/v2/abac-ws-fixed.js +0 -237
  205. package/src/modules/core/controllers/classes/core.abac.js +0 -310
  206. package/src/modules/core/controllers/classes/core.crud.js +0 -89
  207. package/src/modules/governance/reactcode/eslint.config.js +0 -28
@@ -1,425 +0,0 @@
1
- // @martyrs/src/modules/core/controllers/classes/abac/abac.fields.js
2
- import set from 'lodash/set';
3
- import get from 'lodash/get';
4
- import unset from 'lodash/unset';
5
- import cloneDeep from 'lodash/cloneDeep';
6
-
7
- export default class ABACFields {
8
- constructor(abac) {
9
- this.abac = abac;
10
- this.configs = new Map();
11
- this.compiledPatterns = new Map(); // Кэш скомпилированных паттернов
12
- }
13
-
14
- /**
15
- * Регистрация field policies
16
- */
17
- registerFieldsPolicy(resourceName, config) {
18
- const normalized = {};
19
-
20
- for (const [pattern, conf] of Object.entries(config)) {
21
- const { actions, ...baseSettings } = conf;
22
-
23
- const base = {
24
- actions: baseSettings.actions || '*',
25
- access: baseSettings.access || 'allow',
26
- validator: baseSettings.validator || null,
27
- transform: baseSettings.transform || null,
28
- rule: baseSettings.rule || 'remove',
29
- force: baseSettings.force || false,
30
- pattern
31
- };
32
-
33
- if (actions && typeof actions === 'object') {
34
- normalized[pattern] = {
35
- base,
36
- actions: Object.entries(actions).reduce((acc, [action, override]) => {
37
- acc[action] = { ...base, ...override };
38
- return acc;
39
- }, {})
40
- };
41
- } else {
42
- normalized[pattern] = { base };
43
- }
44
- }
45
-
46
- this.configs.set(resourceName, normalized);
47
- // Очищаем кэш паттернов при изменении конфига
48
- this.compiledPatterns.delete(resourceName);
49
- return this;
50
- }
51
-
52
- /**
53
- * Проверка доступа к полям
54
- */
55
- async checkFields(context, data, action = null) {
56
- const normalizedContext = this.abac.core.normalizeContext(context);
57
-
58
- if (normalizedContext.skipFieldPolicies) {
59
- return {
60
- allowed: data,
61
- denied: [],
62
- errors: [],
63
- transformed: data
64
- };
65
- }
66
-
67
- const { resource } = normalizedContext;
68
- const fieldAction = action || normalizedContext.action;
69
- const config = normalizedContext.options?.fieldsConfig || this.configs.get(resource);
70
-
71
- if (!config) {
72
- return { allowed: data, denied: [], errors: [], transformed: data };
73
- }
74
-
75
- // Применяем расширения
76
- await this._applyExtensions(normalizedContext);
77
-
78
- // Используем structuredClone или lodash для безопасного клонирования
79
- const result = {
80
- allowed: this._deepClone(data),
81
- denied: [],
82
- errors: [],
83
- transformed: null
84
- };
85
-
86
- // Собираем правила с учетом force
87
- const rules = this._collectRulesOptimized(data, config, fieldAction, resource);
88
- const forced = rules.filter(r => r.rule.force);
89
- const regular = rules.filter(r => !r.rule.force);
90
-
91
- // Set для отслеживания обработанных путей (БЫЛ БАГ!)
92
- const processed = new Set();
93
-
94
- // Применяем правила (сначала forced, потом обычные)
95
- for (const { path, value, rule } of [...forced, ...regular]) {
96
- // Пропускаем уже обработанные пути
97
- if (processed.has(path)) continue;
98
- processed.add(path);
99
-
100
- // Проверка доступа
101
- const hasAccess = await this._checkFieldAccess(
102
- rule.access,
103
- normalizedContext,
104
- path,
105
- value
106
- );
107
-
108
- if (!hasAccess) {
109
- await this._handleDenied(result, path, rule.rule);
110
- continue;
111
- }
112
-
113
- // Валидация
114
- if (rule.validator && rule.access !== 'optional') {
115
- const validation = await this._validateField(
116
- rule.validator,
117
- value,
118
- normalizedContext,
119
- path
120
- );
121
-
122
- if (!validation.isValid) {
123
- result.errors.push({ path, errors: validation.errors });
124
-
125
- if (rule.rule === 'error') {
126
- throw new Error(`Validation failed: ${path}`);
127
- }
128
- await this._handleDenied(result, path, rule.rule);
129
- }
130
- }
131
- }
132
-
133
- // Трансформация
134
- result.transformed = this._deepClone(result.allowed);
135
-
136
- for (const { path, value, rule } of [...forced, ...regular]) {
137
- if (!rule.transform) continue;
138
-
139
- const isDenied = result.denied.some(d => d.path === path);
140
- if (isDenied) continue;
141
-
142
- const transformed = await this._transformField(
143
- rule.transform,
144
- value,
145
- normalizedContext,
146
- path,
147
- result.transformed
148
- );
149
- set(result.transformed, path, transformed);
150
- }
151
-
152
- return result;
153
- }
154
-
155
- /**
156
- * Применение расширений
157
- * @private
158
- */
159
- async _applyExtensions(context) {
160
- if (!this.abac.policies || !this.abac.policies.priorities.extensions.length) {
161
- return;
162
- }
163
-
164
- for (const [name, extensionFn] of this.abac.policies.priorities.extensions) {
165
- try {
166
- await extensionFn(context);
167
- } catch (error) {
168
- this.abac.logger?.error('Extension error', { name, error });
169
- }
170
- }
171
- }
172
-
173
- /**
174
- * Безопасное клонирование
175
- * @private
176
- */
177
- _deepClone(obj) {
178
- // Используем structuredClone если доступен (Node 17+)
179
- if (typeof structuredClone === 'function') {
180
- try {
181
- return structuredClone(obj);
182
- } catch (e) {
183
- // Fallback для циклических ссылок
184
- }
185
- }
186
- // Fallback на lodash
187
- return cloneDeep(obj);
188
- }
189
-
190
- /**
191
- * Оптимизированный сбор правил
192
- * @private
193
- */
194
- _collectRulesOptimized(data, config, action, resource) {
195
- const rules = [];
196
-
197
- // Компилируем паттерны если нужно
198
- const compiledPatterns = this._getCompiledPatterns(resource, config);
199
-
200
- // Проверяем есть ли паттерн "*" - если да, применяем его ко всем полям
201
- const hasWildcard = compiledPatterns.has('*');
202
-
203
- // Оптимизация: сначала собираем все пути
204
- const dataPaths = this._extractPathsOptimized(data);
205
-
206
- // Если есть wildcard, сразу добавляем правило для всех путей
207
- if (hasWildcard) {
208
- const wildcardConfig = config['*'];
209
- const rule = this._getRuleForAction(wildcardConfig, action);
210
-
211
- if (this._matchesAction(rule.actions, action)) {
212
- for (const path of dataPaths) {
213
- rules.push({
214
- path,
215
- value: get(data, path),
216
- rule
217
- });
218
- }
219
- // Если применили wildcard, можем не проверять другие паттерны
220
- return rules;
221
- }
222
- }
223
-
224
- // Проверяем остальные паттерны
225
- for (const path of dataPaths) {
226
- for (const [pattern, matcher] of compiledPatterns) {
227
- if (pattern === '*') continue; // Уже обработали
228
-
229
- if (matcher(path)) {
230
- const fieldConfig = config[pattern];
231
- const rule = this._getRuleForAction(fieldConfig, action);
232
-
233
- if (this._matchesAction(rule.actions, action)) {
234
- rules.push({
235
- path,
236
- value: get(data, path),
237
- rule
238
- });
239
- break; // Берем первое совпадение
240
- }
241
- }
242
- }
243
- }
244
-
245
- return rules;
246
- }
247
-
248
- /**
249
- * Получение скомпилированных паттернов
250
- * @private
251
- */
252
- _getCompiledPatterns(resource, config) {
253
- if (!this.compiledPatterns.has(resource)) {
254
- const compiled = new Map();
255
-
256
- for (const pattern of Object.keys(config)) {
257
- compiled.set(pattern, this._compilePattern(pattern));
258
- }
259
-
260
- this.compiledPatterns.set(resource, compiled);
261
- }
262
-
263
- return this.compiledPatterns.get(resource);
264
- }
265
-
266
- /**
267
- * Компиляция паттерна в функцию проверки
268
- * @private
269
- */
270
- _compilePattern(pattern) {
271
- if (pattern === '*') return () => true;
272
-
273
- // Преобразуем паттерн в регулярку
274
- const escaped = pattern
275
- .replace(/\./g, '\\.')
276
- .replace(/\*\*/g, '.*')
277
- .replace(/\*/g, '[^.]+')
278
- .replace(/\[\*\]/g, '\\[\\d+\\]');
279
-
280
- const regex = new RegExp(`^${escaped}$`);
281
-
282
- return (path) => regex.test(path);
283
- }
284
-
285
- /**
286
- * Оптимизированное извлечение путей
287
- * @private
288
- */
289
- _extractPathsOptimized(obj, prefix = '', paths = []) {
290
- if (!obj || typeof obj !== 'object') return paths;
291
-
292
- if (Array.isArray(obj)) {
293
- obj.forEach((item, i) => {
294
- const path = prefix ? `${prefix}[${i}]` : `[${i}]`;
295
- paths.push(path);
296
- this._extractPathsOptimized(item, path, paths);
297
- });
298
- } else {
299
- for (const key in obj) {
300
- if (obj.hasOwnProperty(key)) {
301
- const path = prefix ? `${prefix}.${key}` : key;
302
- paths.push(path);
303
-
304
- if (obj[key] && typeof obj[key] === 'object') {
305
- this._extractPathsOptimized(obj[key], path, paths);
306
- }
307
- }
308
- }
309
- }
310
-
311
- return paths;
312
- }
313
-
314
- /**
315
- * Получение правила для действия
316
- * @private
317
- */
318
- _getRuleForAction(fieldConfig, action) {
319
- if (fieldConfig.actions && fieldConfig.actions[action]) {
320
- return fieldConfig.actions[action];
321
- }
322
- return fieldConfig.base;
323
- }
324
-
325
- /**
326
- * Проверка доступа к полю
327
- * @private
328
- */
329
- async _checkFieldAccess(access, context, fieldPath, fieldValue) {
330
- if (access === 'allow') return true;
331
- if (access === 'deny') return false;
332
- if (access === 'optional') return true;
333
-
334
- if (typeof access === 'function') {
335
- try {
336
- return !!(await access(context, fieldPath, fieldValue));
337
- } catch (e) {
338
- this.abac.logger?.error('Field access check error', {
339
- field: fieldPath,
340
- error: e.message
341
- });
342
- return false;
343
- }
344
- }
345
-
346
- return true;
347
- }
348
-
349
- /**
350
- * Валидация поля
351
- * @private
352
- */
353
- async _validateField(validator, value, context, fieldPath) {
354
- if (typeof validator === 'function') {
355
- try {
356
- const result = await validator(value, context, fieldPath);
357
- if (typeof result === 'boolean') {
358
- return { isValid: result, errors: result ? [] : ['Validation failed'] };
359
- }
360
- return result;
361
- } catch (e) {
362
- return { isValid: false, errors: [e.message] };
363
- }
364
- }
365
-
366
- if (validator && validator.validate) {
367
- return validator.validate(value);
368
- }
369
-
370
- return { isValid: true, errors: [] };
371
- }
372
-
373
- /**
374
- * Трансформация поля
375
- * @private
376
- */
377
- async _transformField(transform, value, context, fieldPath, currentData) {
378
- try {
379
- return await transform(value, context, fieldPath, currentData);
380
- } catch (error) {
381
- this.abac.logger?.error('Field transform error', {
382
- field: fieldPath,
383
- error: error.message
384
- });
385
- return value;
386
- }
387
- }
388
-
389
- /**
390
- * Обработка отказа
391
- * @private
392
- */
393
- async _handleDenied(result, path, rule) {
394
- result.denied.push({ path, reason: rule });
395
-
396
- if (rule === 'remove') {
397
- unset(result.allowed, path);
398
- } else if (rule === 'error') {
399
- throw new Error(`Access denied: ${path}`);
400
- }
401
- }
402
-
403
- /**
404
- * Проверка действия
405
- * @private
406
- */
407
- _matchesAction(actions, action) {
408
- if (actions === '*') return true;
409
- return Array.isArray(actions) ? actions.includes(action) : actions === action;
410
- }
411
-
412
- // Публичные методы для управления конфигами
413
- getConfig(resourceName) {
414
- return this.configs.get(resourceName);
415
- }
416
-
417
- hasConfig(resourceName) {
418
- return this.configs.has(resourceName);
419
- }
420
-
421
- removeConfig(resourceName) {
422
- this.compiledPatterns.delete(resourceName);
423
- return this.configs.delete(resourceName);
424
- }
425
- }