@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
|
@@ -2,48 +2,62 @@
|
|
|
2
2
|
export default class ABACCore {
|
|
3
3
|
constructor(abac) {
|
|
4
4
|
this.abac = abac;
|
|
5
|
-
this.runningPolicies = new Map();
|
|
5
|
+
this.runningPolicies = new Map();
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Нормализация контекста
|
|
10
|
+
*/
|
|
9
11
|
normalizeContext(input) {
|
|
10
12
|
const context = {
|
|
11
13
|
user: null,
|
|
12
14
|
action: null,
|
|
13
15
|
resource: null,
|
|
14
16
|
currentResource: null,
|
|
17
|
+
resourceId: null, // Добавляем ID ресурса для кэша
|
|
15
18
|
data: {},
|
|
16
19
|
req: null,
|
|
17
20
|
socket: null,
|
|
18
21
|
params: {},
|
|
19
22
|
_cache: new Map(),
|
|
20
23
|
_abac: this.abac,
|
|
21
|
-
// Добавляем флаг для пропуска field policies (например, для админов)
|
|
22
24
|
skipFieldPolicies: input.skipFieldPolicies || false,
|
|
23
25
|
};
|
|
24
26
|
|
|
25
27
|
if (input.req) {
|
|
26
|
-
// Express context
|
|
28
|
+
// Express context - НЕ смешиваем body и query!
|
|
27
29
|
context.user = input.user || input.req.userId;
|
|
28
30
|
context.data = {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
params: input.req.params,
|
|
31
|
+
body: input.req.body || {},
|
|
32
|
+
query: input.req.query || {},
|
|
33
|
+
params: input.req.params || {},
|
|
32
34
|
};
|
|
33
35
|
context.params = input.req.params;
|
|
34
36
|
context.req = input.req;
|
|
37
|
+
|
|
38
|
+
// Извлекаем ID ресурса для кэша
|
|
39
|
+
context.resourceId = input.req.params?._id ||
|
|
40
|
+
input.req.params?.id ||
|
|
41
|
+
input.req.body?._id ||
|
|
42
|
+
input.req.body?.id;
|
|
35
43
|
} else if (input.socket) {
|
|
36
44
|
// WebSocket context
|
|
37
45
|
context.user = input.user || input.socket.userId;
|
|
38
46
|
context.socket = input.socket;
|
|
39
47
|
context.data = input.data || {};
|
|
48
|
+
context.resourceId = input.data?._id || input.data?.id;
|
|
40
49
|
}
|
|
41
50
|
|
|
42
|
-
// Merge остальные поля
|
|
43
|
-
return Object.assign(context,
|
|
51
|
+
// Merge остальные поля (но не перезаписываем data)
|
|
52
|
+
return Object.assign(context, {
|
|
53
|
+
...input,
|
|
54
|
+
data: context.data // Сохраняем структурированную data
|
|
55
|
+
});
|
|
44
56
|
}
|
|
45
57
|
|
|
46
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Выполнение политики с кэшированием
|
|
60
|
+
*/
|
|
47
61
|
async executePolicyWithCache(policyName, policyFn, context) {
|
|
48
62
|
// Проверяем контекстный кэш
|
|
49
63
|
const contextCacheKey = `${policyName}_${context.action}`;
|
|
@@ -51,8 +65,9 @@ export default class ABACCore {
|
|
|
51
65
|
return context._cache.get(contextCacheKey);
|
|
52
66
|
}
|
|
53
67
|
|
|
54
|
-
//
|
|
55
|
-
const globalCacheKey =
|
|
68
|
+
// Улучшенный глобальный кэш-ключ с ID ресурса
|
|
69
|
+
const globalCacheKey = this._buildCacheKey(policyName, context);
|
|
70
|
+
|
|
56
71
|
if (this.abac.options.cacheEnabled) {
|
|
57
72
|
const cached = await this.abac.cache.get(globalCacheKey);
|
|
58
73
|
if (cached !== undefined) {
|
|
@@ -67,17 +82,45 @@ export default class ABACCore {
|
|
|
67
82
|
// Сохраняем в кэш
|
|
68
83
|
context._cache.set(contextCacheKey, result);
|
|
69
84
|
if (this.abac.options.cacheEnabled) {
|
|
70
|
-
|
|
85
|
+
const tags = [
|
|
71
86
|
`user_${context.user}`,
|
|
72
87
|
`resource_${context.resource}`,
|
|
73
88
|
`policy_${policyName}`
|
|
74
|
-
]
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
if (context.resourceId) {
|
|
92
|
+
tags.push(`resourceId_${context.resourceId}`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
await this.abac.cache.setWithTags(globalCacheKey, result, tags);
|
|
75
96
|
}
|
|
76
97
|
|
|
77
98
|
return result;
|
|
78
99
|
}
|
|
79
100
|
|
|
80
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Построение ключа кэша с учетом ID ресурса
|
|
103
|
+
* @private
|
|
104
|
+
*/
|
|
105
|
+
_buildCacheKey(policyName, context) {
|
|
106
|
+
const parts = [
|
|
107
|
+
'policy',
|
|
108
|
+
policyName,
|
|
109
|
+
context.user,
|
|
110
|
+
context.resource,
|
|
111
|
+
context.action
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
if (context.resourceId) {
|
|
115
|
+
parts.push(context.resourceId);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return parts.join('_');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Выполнение политик с ограничением параллельности
|
|
123
|
+
*/
|
|
81
124
|
async executePoliciesLimited(policies, context, stopOnDeny = false) {
|
|
82
125
|
const results = [];
|
|
83
126
|
const limit = this.abac.options.concurrencyLimit;
|
|
@@ -95,7 +138,12 @@ export default class ABACCore {
|
|
|
95
138
|
const result = await this.executePolicyWithCache(name, policyFn, context);
|
|
96
139
|
return { name, result: this.normalizeResult(result, name) };
|
|
97
140
|
} catch (error) {
|
|
98
|
-
|
|
141
|
+
this.abac.logger?.error('Policy execution error', {
|
|
142
|
+
policy: name,
|
|
143
|
+
error: error.message,
|
|
144
|
+
stack: error.stack
|
|
145
|
+
});
|
|
146
|
+
|
|
99
147
|
return {
|
|
100
148
|
name,
|
|
101
149
|
result: {
|
|
@@ -120,10 +168,16 @@ export default class ABACCore {
|
|
|
120
168
|
return results;
|
|
121
169
|
}
|
|
122
170
|
|
|
123
|
-
|
|
171
|
+
/**
|
|
172
|
+
* Нормализация результата политики
|
|
173
|
+
*/
|
|
124
174
|
normalizeResult(result, policyName) {
|
|
125
175
|
if (this.abac.options.strictMode && result === undefined) {
|
|
126
|
-
return {
|
|
176
|
+
return {
|
|
177
|
+
allow: false,
|
|
178
|
+
force: false,
|
|
179
|
+
reason: `UNDEFINED_IN_STRICT_MODE_${policyName.toUpperCase()}`
|
|
180
|
+
};
|
|
127
181
|
}
|
|
128
182
|
|
|
129
183
|
if (result && typeof result === 'object' && ('allow' in result || 'force' in result)) {
|
|
@@ -135,16 +189,30 @@ export default class ABACCore {
|
|
|
135
189
|
}
|
|
136
190
|
|
|
137
191
|
if (result === true) {
|
|
138
|
-
return {
|
|
192
|
+
return {
|
|
193
|
+
allow: true,
|
|
194
|
+
force: false,
|
|
195
|
+
reason: `ALLOWED_BY_${policyName.toUpperCase()}`
|
|
196
|
+
};
|
|
139
197
|
}
|
|
140
198
|
if (result === false) {
|
|
141
|
-
return {
|
|
199
|
+
return {
|
|
200
|
+
allow: false,
|
|
201
|
+
force: false,
|
|
202
|
+
reason: `DENIED_BY_${policyName.toUpperCase()}`
|
|
203
|
+
};
|
|
142
204
|
}
|
|
143
205
|
|
|
144
|
-
return {
|
|
206
|
+
return {
|
|
207
|
+
allow: !this.abac.options.strictMode,
|
|
208
|
+
force: false,
|
|
209
|
+
reason: `NEUTRAL_${policyName.toUpperCase()}`
|
|
210
|
+
};
|
|
145
211
|
}
|
|
146
212
|
|
|
147
|
-
|
|
213
|
+
/**
|
|
214
|
+
* Основной метод проверки доступа
|
|
215
|
+
*/
|
|
148
216
|
async checkAccess(rawContext, customPolicies = {}) {
|
|
149
217
|
const startTime = Date.now();
|
|
150
218
|
const context = this.normalizeContext(rawContext);
|
|
@@ -160,7 +228,7 @@ export default class ABACCore {
|
|
|
160
228
|
}
|
|
161
229
|
|
|
162
230
|
// Предзагрузка ресурса
|
|
163
|
-
if (!context.currentResource
|
|
231
|
+
if (!context.currentResource) {
|
|
164
232
|
await this.loadResource(context);
|
|
165
233
|
}
|
|
166
234
|
|
|
@@ -171,52 +239,75 @@ export default class ABACCore {
|
|
|
171
239
|
if (this.abac.options.enableAudit) {
|
|
172
240
|
await this.audit(context, result, Date.now() - startTime);
|
|
173
241
|
}
|
|
174
|
-
|
|
242
|
+
|
|
175
243
|
return result;
|
|
176
244
|
}
|
|
177
245
|
|
|
178
|
-
|
|
246
|
+
/**
|
|
247
|
+
* Загрузка ресурса
|
|
248
|
+
*/
|
|
179
249
|
async loadResource(context) {
|
|
180
250
|
const resourceModel = this.abac.getResourceModel(context.resource);
|
|
181
251
|
if (!resourceModel) return;
|
|
182
252
|
|
|
183
253
|
try {
|
|
184
254
|
let currentResource;
|
|
185
|
-
|
|
255
|
+
// Ищем ID в структурированной data
|
|
256
|
+
const id = context.resourceId ||
|
|
257
|
+
context.data?.body?._id ||
|
|
258
|
+
context.data?.params?._id;
|
|
186
259
|
|
|
187
260
|
if (id) {
|
|
188
261
|
currentResource = await resourceModel.findById(id);
|
|
189
|
-
} else if (context.data.url) {
|
|
190
|
-
|
|
262
|
+
} else if (context.data?.body?.url || context.data?.params?.url) {
|
|
263
|
+
const url = context.data.body?.url || context.data.params?.url;
|
|
264
|
+
currentResource = await resourceModel.findOne({ url });
|
|
191
265
|
}
|
|
192
266
|
|
|
193
267
|
if (currentResource) {
|
|
194
268
|
context.currentResource = currentResource;
|
|
195
269
|
context.resourceModel = resourceModel;
|
|
270
|
+
context.resourceId = currentResource._id?.toString();
|
|
196
271
|
}
|
|
197
272
|
} catch (error) {
|
|
198
|
-
|
|
273
|
+
this.abac.logger?.error('Resource loading error', {
|
|
274
|
+
resource: context.resource,
|
|
275
|
+
error: error.message
|
|
276
|
+
});
|
|
199
277
|
}
|
|
200
278
|
}
|
|
201
279
|
|
|
202
|
-
|
|
280
|
+
/**
|
|
281
|
+
* Структурированный аудит
|
|
282
|
+
*/
|
|
203
283
|
async audit(context, result, duration) {
|
|
204
284
|
try {
|
|
205
|
-
|
|
285
|
+
const auditEntry = {
|
|
206
286
|
type: 'ACCESS_CHECK',
|
|
207
|
-
timestamp: new Date(),
|
|
287
|
+
timestamp: new Date().toISOString(),
|
|
208
288
|
user: context.user,
|
|
209
289
|
resource: context.resource,
|
|
290
|
+
resourceId: context.resourceId,
|
|
210
291
|
action: context.action,
|
|
211
292
|
result: result.allow,
|
|
212
293
|
reason: result.reason,
|
|
213
294
|
duration: duration,
|
|
295
|
+
ip: context.req?.ip,
|
|
296
|
+
userAgent: context.req?.get?.('user-agent'),
|
|
214
297
|
metadata: context.auditMetadata || {}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
// Используем структурированное логирование
|
|
301
|
+
await this.abac.logger.info('Access check', auditEntry);
|
|
302
|
+
|
|
303
|
+
// Если критическое действие - дополнительный алерт
|
|
304
|
+
if (['delete', 'admin', 'export'].includes(context.action)) {
|
|
305
|
+
await this.abac.logger.warn('Critical action attempt', auditEntry);
|
|
306
|
+
}
|
|
218
307
|
} catch (error) {
|
|
219
|
-
|
|
308
|
+
this.abac.logger?.error('Audit logging error', {
|
|
309
|
+
error: error.message
|
|
310
|
+
});
|
|
220
311
|
}
|
|
221
312
|
}
|
|
222
313
|
}
|