@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.
- package/dist/abac-BPl9Bmf9.js +1527 -0
- package/dist/builder.js +51 -39
- package/dist/{common.schema-GFSlNJo7.js → common.schema-DswiUXKB.js} +1 -1
- package/dist/community.server.js +48 -9
- package/dist/core.server.js +6 -4
- package/dist/{crud-C7FSTUes.js → crud-q1ye5IhV.js} +7 -7
- package/dist/events.server.js +3 -3
- package/dist/gallery.server.js +2 -2
- package/dist/inventory.server.js +4 -6
- package/dist/{main-CmjWiDVF.js → main-B9o1iBAZ.js} +1279 -1287
- package/dist/marketplace.server.js +1 -1
- package/dist/martyrs/src/components/Button/Button.vue2.js +33 -42
- package/dist/martyrs/src/components/Button/Button.vue2.js.map +1 -1
- package/dist/martyrs/src/components/EditImages/{EditImages.vue.js → EditImages.vue2.js} +2 -2
- package/dist/martyrs/src/components/EditImages/EditImages.vue2.js.map +1 -0
- package/dist/martyrs/src/components/Feed/Feed.vue.js +1 -1
- package/dist/martyrs/src/components/FieldPhone/FieldPhone.vue.js +1 -1
- package/dist/martyrs/src/components/FieldPhone/FieldPhone.vue.js.map +1 -1
- package/dist/martyrs/src/components/Loader/Loader.vue.js +1 -2
- package/dist/martyrs/src/components/Loader/Loader.vue.js.map +1 -1
- package/dist/martyrs/src/components/Menu/{Menu.vue.js → Menu.vue2.js} +2 -2
- package/dist/martyrs/src/components/Menu/Menu.vue2.js.map +1 -0
- package/dist/martyrs/src/components/Tab/{Tab.vue.js → Tab.vue2.js} +2 -2
- package/dist/martyrs/src/components/Tab/Tab.vue2.js.map +1 -0
- package/dist/martyrs/src/components/Tree/Tree.vue.js +6 -3
- package/dist/martyrs/src/components/Tree/Tree.vue.js.map +1 -1
- package/dist/martyrs/src/modules/auth/auth.client.js +10 -7
- package/dist/martyrs/src/modules/auth/auth.client.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileBlogposts.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +12 -12
- package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/router/auth.router.js +116 -0
- package/dist/martyrs/src/modules/auth/views/router/auth.router.js.map +1 -0
- package/dist/martyrs/src/modules/auth/views/router/users.router.js +180 -0
- package/dist/martyrs/src/modules/auth/views/router/users.router.js.map +1 -0
- package/dist/martyrs/src/modules/backoffice/components/partials/Sidebar.vue.js +3 -3
- package/dist/martyrs/src/modules/backoffice/components/partials/Sidebar.vue.js.map +1 -1
- package/dist/martyrs/src/modules/core/locales/en.js +45 -0
- package/dist/martyrs/src/modules/core/locales/en.js.map +1 -1
- package/dist/martyrs/src/modules/core/locales/ru.js +45 -0
- package/dist/martyrs/src/modules/core/locales/ru.js.map +1 -1
- package/dist/martyrs/src/modules/core/views/classes/i18n.manager.js +9 -0
- package/dist/martyrs/src/modules/core/views/classes/i18n.manager.js.map +1 -1
- package/dist/martyrs/src/modules/core/views/components/sections/{Filters.vue.js → Filters.vue2.js} +2 -2
- package/dist/martyrs/src/modules/core/views/components/sections/Filters.vue2.js.map +1 -0
- package/dist/martyrs/src/modules/core/views/components/sections/SectionPageTitle.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/mixins/mixins.js +1 -2
- package/dist/martyrs/src/modules/core/views/mixins/mixins.js.map +1 -1
- package/dist/martyrs/src/modules/core/views/router/addRoutes.js +6 -1
- package/dist/martyrs/src/modules/core/views/router/addRoutes.js.map +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/Event.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.js +1 -1
- package/dist/martyrs/src/modules/inventory/components/pages/InventoryEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/inventory/components/pages/InventoryEdit.vue.js.map +1 -1
- package/dist/martyrs/src/modules/marketplace/views/components/pages/Marketplace.vue.js +1 -1
- package/dist/martyrs/src/modules/marketplace/views/store/marketplace.js +0 -16
- package/dist/martyrs/src/modules/marketplace/views/store/marketplace.js.map +1 -1
- package/dist/martyrs/src/modules/notifications/components/elements/NotificationBadge.vue.js +4 -4
- package/dist/martyrs/src/modules/notifications/components/elements/NotificationBadge.vue.js.map +1 -1
- package/dist/martyrs/src/modules/notifications/components/pages/Notifications.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/elements/FieldSubscribeNewsletter.vue.js +3 -0
- package/dist/martyrs/src/modules/orders/components/elements/FieldSubscribeNewsletter.vue.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/blocks/CardOrganization.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/blocks/CardOrganization.vue.js.map +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js.map +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Organizations.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/blocks/CardProduct.vue.js +15 -2
- package/dist/martyrs/src/modules/products/components/blocks/CardProduct.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js +9 -6
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +4 -3
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +11 -2
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +2 -2
- package/dist/martyrs/src/modules/products/components/sections/EditVariants.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js +11 -8
- package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js.map +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.js +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.js +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/RentsEdit.vue.js +210 -60
- package/dist/martyrs/src/modules/rents/views/components/pages/RentsEdit.vue.js.map +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/Map.vue.js +3 -3
- package/dist/martyrs/src/modules/spots/components/pages/Map.vue.js.map +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +1 -1
- package/dist/martyrs.css +1 -1
- package/dist/martyrs.es.js +1 -1
- package/dist/music.server.js +11 -12
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/utils.js +1 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/utils.js +1 -1
- package/dist/notifications.server.js +0 -3
- package/dist/orders.server.js +5 -6
- package/dist/organizations.server.js +9 -10
- package/dist/products.server.js +27 -26
- package/dist/{queryProcessor-CBQgZycY.js → queryProcessor-C_5Iipam.js} +4 -1
- package/dist/rents.server.js +2 -3
- package/dist/spots.server.js +1 -1
- package/dist/style.css +38 -23
- package/dist/{web-cNKIl_cL.js → web-BF3ijvEr.js} +1 -1
- package/package.json +1 -1
- package/src/builder/modes/ssr.rspack.dev.js +4 -3
- package/src/builder/rspack/rspack.config.api.js +15 -4
- package/src/builder/rspack/rspack.config.base.js +3 -3
- package/src/builder/rspack/rspack.config.ssr.client.js +28 -28
- package/src/builder/templates/page.js +2 -2
- package/src/components/Button/Button.vue +50 -37
- package/src/components/FieldPhone/FieldPhone.vue +1 -1
- package/src/components/Loader/Loader.vue +1 -1
- package/src/components/Tree/Tree.vue +6 -3
- package/src/modules/PROCESS.md +0 -0
- package/src/modules/TASKS.MD +17 -0
- package/src/modules/auth/auth.client.js +11 -7
- package/src/modules/auth/views/components/pages/SignIn.vue +1 -1
- package/src/modules/auth/views/router/auth.router.js +94 -0
- package/src/modules/auth/views/router/users.router.js +153 -0
- package/src/modules/backoffice/components/partials/Sidebar.vue +7 -7
- package/src/modules/community/community.server.js +8 -0
- package/src/modules/community/policies/blog.policies.js +55 -0
- package/src/modules/community/routes/blog.routes.js +1 -1
- package/src/modules/community/routes/comments.routes.js +1 -1
- package/src/modules/community/routes/reactions.routes.js +1 -4
- package/src/modules/core/controllers/classes/abac/abac.adapter.express.js +206 -124
- package/src/modules/core/controllers/classes/abac/abac.adapter.ws.js +203 -50
- package/src/modules/core/controllers/classes/abac/abac.core.js +127 -36
- package/src/modules/core/controllers/classes/abac/abac.fields.js +144 -179
- package/src/modules/core/controllers/classes/abac/abac.js +201 -10
- package/src/modules/core/controllers/classes/abac/abac.policies.js +147 -57
- package/src/modules/core/controllers/classes/crud/crud.policies.js +5 -5
- package/src/modules/core/controllers/policies/core.policies.js +5 -2
- package/src/modules/core/controllers/utils/queryProcessor.js +4 -1
- package/src/modules/core/core.server.js +1 -0
- package/src/modules/core/locales/en.js +45 -0
- package/src/modules/core/locales/ru.js +45 -0
- package/src/modules/core/models/schemas/common.schema.js +1 -1
- package/src/modules/core/views/classes/i18n.manager.js +13 -0
- package/src/modules/core/views/components/sections/filters/FilterPrice.vue +81 -0
- package/src/modules/core/views/mixins/mixins.js +1 -2
- package/src/modules/core/views/router/addRoutes.js +6 -1
- package/src/modules/events/routes/events.routes.js +1 -1
- package/src/modules/inventory/components/pages/InventoryEdit.vue +3 -3
- package/src/modules/inventory/policies/inventory.policies.js +1 -1
- package/src/modules/inventory/routes/inventory.routes.js +1 -1
- package/src/modules/marketplace/marketplace.router.js +66 -0
- package/src/modules/marketplace/views/components/layouts/Marketplace.vue +363 -0
- package/src/modules/marketplace/views/components/pages/Catalog.vue +73 -0
- package/src/modules/marketplace/views/store/marketplace.js +0 -16
- package/src/modules/music/controllers/stream.controller.js +1 -1
- package/src/modules/music/music.server.js +1 -1
- package/src/modules/music/policies/music.policies.js +3 -2
- package/src/modules/music/router/library.router.js +26 -0
- package/src/modules/music/router/music.router.js +176 -0
- package/src/modules/notifications/components/elements/NotificationBadge.vue +5 -6
- package/src/modules/notifications/notifications.server.js +1 -3
- package/src/modules/orders/components/elements/FieldSubscribeNewsletter.vue +5 -0
- package/src/modules/orders/orders.server.js +0 -1
- package/src/modules/organizations/components/blocks/CardOrganization.vue +2 -2
- package/src/modules/organizations/components/pages/DepartmentEdit.vue +2 -2
- package/src/modules/organizations/components/pages/OrganizationEdit.vue +2 -2
- package/src/modules/organizations/policies/organizations.policies.js +12 -6
- package/src/modules/organizations/routes/organizations.routes.js +1 -3
- package/src/modules/products/components/blocks/CardCategory.vue +1 -1
- package/src/modules/products/components/blocks/CardProduct.vue +16 -2
- package/src/modules/products/components/pages/Categories.vue +9 -6
- package/src/modules/products/components/pages/CategoryEdit.vue +8 -4
- package/src/modules/products/components/pages/Product.vue +11 -5
- package/src/modules/products/components/sections/SectionProduct.vue +11 -7
- package/src/modules/products/controllers/categories.controller.js +32 -27
- package/src/modules/products/routes/categories.routes.js +1 -1
- package/src/modules/rents/controllers/routes/rents.routes.js +1 -1
- package/src/modules/rents/views/components/pages/RentsEdit.vue +208 -49
- package/src/modules/spots/components/pages/Map.vue +2 -2
- package/dist/abac-DYoheWuc.js +0 -1031
- package/dist/core.abac-DUPBnlk6.js +0 -298
- package/dist/core.logger-C3q8A9dl.js +0 -51
- package/dist/martyrs/src/components/EditImages/EditImages.vue.js.map +0 -1
- package/dist/martyrs/src/components/Menu/Menu.vue.js.map +0 -1
- package/dist/martyrs/src/components/Tab/Tab.vue.js.map +0 -1
- package/dist/martyrs/src/modules/auth/auth.router.js +0 -342
- package/dist/martyrs/src/modules/auth/auth.router.js.map +0 -1
- package/dist/martyrs/src/modules/core/views/components/sections/Filters.vue.js.map +0 -1
- package/src/modules/auth/auth.router.js +0 -262
- package/src/modules/core/controllers/classes/abac/v2/abac-core-fixed.js +0 -313
- package/src/modules/core/controllers/classes/abac/v2/abac-express-fixed.js +0 -276
- package/src/modules/core/controllers/classes/abac/v2/abac-fields-fixed.js +0 -425
- package/src/modules/core/controllers/classes/abac/v2/abac-main-fixed.js +0 -295
- package/src/modules/core/controllers/classes/abac/v2/abac-policies-fixed.js +0 -316
- package/src/modules/core/controllers/classes/abac/v2/abac-ws-fixed.js +0 -237
- package/src/modules/core/controllers/classes/core.abac.js +0 -310
- package/src/modules/core/controllers/classes/core.crud.js +0 -89
- 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
|
-
}
|