@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,237 +0,0 @@
1
- // @martyrs/src/modules/core/controllers/classes/abac/abac.adapter.ws.js
2
- export default class ABACWebSocketAdapter {
3
- constructor(abac) {
4
- this.abac = abac;
5
- }
6
-
7
- /**
8
- * WebSocket handler для проверки доступа
9
- * @param {string} moduleName - Имя модуля
10
- * @param {Object} [options] - Опции
11
- * @returns {Function} Handler функция
12
- */
13
- handler(moduleName, options = {}) {
14
- return async (ws, message) => {
15
- try {
16
- const { action = 'access', resource = moduleName } = options;
17
-
18
- const context = this._buildContext(ws, resource, action, message, options);
19
- const accessResult = await this.abac.checkAccess(context, context.customPolicies);
20
-
21
- if (!accessResult.allow) {
22
- await this._sendError(ws, 'ACCESS_DENIED', accessResult.reason);
23
- return false;
24
- }
25
-
26
- // Проверка полей если включена
27
- if (options.checkFields && message) {
28
- const fieldsResult = await this.abac.checkFields(context, message, action);
29
-
30
- if (fieldsResult.errors.length > 0 && options.strictFieldsMode) {
31
- await this._sendError(ws, 'FIELD_VALIDATION_ERROR', 'Field validation failed', {
32
- fields: fieldsResult.errors
33
- });
34
- return false;
35
- }
36
-
37
- // Возвращаем отфильтрованные данные
38
- return {
39
- allowed: true,
40
- data: fieldsResult.transformed || fieldsResult.allowed,
41
- fieldsResult
42
- };
43
- }
44
-
45
- return true;
46
- } catch (error) {
47
- this.abac.logger?.error('WebSocket access control error', {
48
- module: moduleName,
49
- error: error.message,
50
- stack: error.stack
51
- });
52
-
53
- await this._sendError(ws, 'INTERNAL_ERROR', 'Access control error');
54
- return false;
55
- }
56
- };
57
- }
58
-
59
- /**
60
- * RPC handler для вызовов через WebSocket
61
- * @param {string} module - Модуль
62
- * @param {string} method - Метод
63
- * @param {Object} [options] - Опции
64
- * @returns {Function} RPC handler
65
- */
66
- rpcHandler(module, method, options = {}) {
67
- return async (params, rpcContext) => {
68
- try {
69
- const context = this._buildRPCContext(rpcContext, module, method, params, options);
70
- const accessResult = await this.abac.checkAccess(context, context.customPolicies);
71
-
72
- if (!accessResult.allow) {
73
- throw new RPCError('ACCESS_DENIED', accessResult.reason);
74
- }
75
-
76
- // Проверка полей если нужно
77
- if (options.checkFields && params) {
78
- const fieldsResult = await this.abac.checkFields(context, params, method);
79
-
80
- if (fieldsResult.errors.length > 0) {
81
- if (options.strictFieldsMode) {
82
- throw new RPCError(
83
- 'FIELD_VALIDATION_ERROR',
84
- `Fields validation failed: ${fieldsResult.errors.map(e => e.path).join(', ')}`
85
- );
86
- }
87
-
88
- // Логируем ошибки в нестрогом режиме
89
- this.abac.logger?.warn('RPC field validation errors', {
90
- module,
91
- method,
92
- errors: fieldsResult.errors
93
- });
94
- }
95
-
96
- // Возвращаем трансформированные данные
97
- return fieldsResult.transformed || fieldsResult.allowed;
98
- }
99
-
100
- return params;
101
- } catch (error) {
102
- // Пробрасываем RPC ошибки как есть
103
- if (error instanceof RPCError) {
104
- throw error;
105
- }
106
-
107
- this.abac.logger?.error('RPC access control error', {
108
- module,
109
- method,
110
- error: error.message,
111
- stack: error.stack
112
- });
113
-
114
- throw new RPCError('INTERNAL_ERROR', 'Access control error');
115
- }
116
- };
117
- }
118
-
119
- /**
120
- * Middleware для обработки WebSocket сообщений
121
- * @param {Object} [options] - Опции
122
- * @returns {Function} Middleware функция
123
- */
124
- messageMiddleware(options = {}) {
125
- return async (ws, message, next) => {
126
- try {
127
- const { resource = 'message', action = 'send' } = options;
128
- const context = this._buildContext(ws, resource, action, message, options);
129
-
130
- const accessResult = await this.abac.checkAccess(context, options.policies || {});
131
-
132
- if (!accessResult.allow) {
133
- await this._sendError(ws, 'ACCESS_DENIED', accessResult.reason);
134
- return;
135
- }
136
-
137
- // Сохраняем результат в контексте WS
138
- ws.abacContext = context;
139
- ws.abacAccessResult = accessResult;
140
-
141
- next();
142
- } catch (error) {
143
- this.abac.logger?.error('WebSocket middleware error', {
144
- error: error.message
145
- });
146
-
147
- await this._sendError(ws, 'INTERNAL_ERROR', 'Access control error');
148
- }
149
- };
150
- }
151
-
152
- /**
153
- * Построение контекста для WebSocket
154
- * @private
155
- */
156
- _buildContext(ws, resource, action, data, options) {
157
- return {
158
- user: ws.userId || ws.user?.id,
159
- resource,
160
- action,
161
- data: data || {},
162
- socket: ws,
163
- customPolicies: options.policies || {},
164
- options,
165
- // Дополнительная информация о соединении
166
- connectionInfo: {
167
- id: ws.id,
168
- remoteAddress: ws._socket?.remoteAddress,
169
- protocol: ws.protocol,
170
- readyState: ws.readyState
171
- }
172
- };
173
- }
174
-
175
- /**
176
- * Построение контекста для RPC
177
- * @private
178
- */
179
- _buildRPCContext(rpcContext, module, method, params, options) {
180
- return {
181
- user: rpcContext.userId || rpcContext.user?.id,
182
- resource: module,
183
- action: method,
184
- data: params || {},
185
- socket: rpcContext.ws,
186
- customPolicies: options.policies || {},
187
- options,
188
- rpcInfo: {
189
- id: rpcContext.id,
190
- module,
191
- method,
192
- timestamp: new Date().toISOString()
193
- }
194
- };
195
- }
196
-
197
- /**
198
- * Отправка ошибки через WebSocket
199
- * @private
200
- */
201
- async _sendError(ws, code, message, details = {}) {
202
- if (ws.readyState !== 1) { // WebSocket.OPEN
203
- return;
204
- }
205
-
206
- try {
207
- const errorMessage = JSON.stringify({
208
- type: 'error',
209
- error: {
210
- code,
211
- message,
212
- ...details
213
- },
214
- timestamp: new Date().toISOString()
215
- });
216
-
217
- ws.send(errorMessage);
218
- } catch (error) {
219
- this.abac.logger?.error('Failed to send WebSocket error', {
220
- originalError: { code, message },
221
- sendError: error.message
222
- });
223
- }
224
- }
225
- }
226
-
227
- /**
228
- * Класс для RPC ошибок
229
- */
230
- class RPCError extends Error {
231
- constructor(code, message, details = {}) {
232
- super(message);
233
- this.name = 'RPCError';
234
- this.code = code;
235
- this.details = details;
236
- }
237
- }
@@ -1,310 +0,0 @@
1
- class GlobalABAC {
2
- constructor(db, options = {}) {
3
- // Основные политики и обработчики
4
- this.policies = {
5
- global: {}, // Глобальные политики
6
- resources: {}, // Политики для ресурсов
7
- extensions: {}, // Расширения от внешних модулей
8
- };
9
- // Настройки по умолчанию
10
- this.options = {
11
- strictMode: false,
12
- defaultDeny: false,
13
- serviceKey: process.env.SERVICE_KEY, // Добавляем ключ сервиса из env
14
- ...options,
15
- };
16
- // Сохраняем ссылку на базу данных
17
- this.db = db;
18
- }
19
- // Регистрация глобальной политики
20
- registerGlobalPolicy(name, policyFn) {
21
- this.policies.global[name] = policyFn;
22
- return this;
23
- }
24
- // Регистрация политики для ресурса
25
- registerResourcePolicy(resourceName, policyFn) {
26
- this.policies.resources[resourceName] = policyFn;
27
- return this;
28
- }
29
- // Метод для регистрации расширений от внешних модулей
30
- registerExtension(moduleName, extensionFn) {
31
- // Если расширение уже существует, объединяем функции
32
- if (this.policies.extensions[moduleName]) {
33
- const existingExtension = this.policies.extensions[moduleName];
34
- this.policies.extensions[moduleName] = async context => {
35
- const existingResult = await existingExtension(context);
36
- if (existingResult) return existingResult;
37
- return await extensionFn(context);
38
- };
39
- } else {
40
- this.policies.extensions[moduleName] = extensionFn;
41
- }
42
- return this;
43
- }
44
- // Автоматическое определение модели по имени ресурса
45
- getResourceModel(resourceName) {
46
- if (resourceName === 'posts') resourceName = 'blogposts';
47
- // Преобразуем название ресурса в singural форму модели
48
- const modelName = resourceName.endsWith('s') ? resourceName.slice(0, -1) : resourceName;
49
- // Ищем модель в базе данных
50
- const model = this.db[modelName];
51
- if (!model) {
52
- throw new Error(`Model for resource ${resourceName} not found`);
53
- }
54
- return model;
55
- }
56
- /**
57
- * Нормализация результата политики для единообразной обработки
58
- * @param {any} result - Результат выполнения политики
59
- * @param {string} policyName - Имя политики для формирования причины
60
- * @returns {Object} Нормализованный результат
61
- */
62
- _normalizeResult(result, policyName) {
63
- // Результат уже в формате объекта с нужными полями
64
- if (result && typeof result === 'object' && ('allow' in result || 'force' in result)) {
65
- return {
66
- allow: !!result.allow,
67
- force: !!result.force,
68
- reason: result.reason || `POLICY_${policyName.toUpperCase()}`,
69
- };
70
- }
71
- // Boolean результаты
72
- if (result === true) {
73
- return { allow: true, force: false, reason: `ALLOWED_BY_${policyName.toUpperCase()}` };
74
- }
75
- if (result === false) {
76
- return { allow: false, force: false, reason: `DENIED_BY_${policyName.toUpperCase()}` };
77
- }
78
- // Специальные случаи для adminAccessGranted и подобных
79
- if (result === undefined && policyName === 'AdminModeratorAccessPolicy' && this._context && this._context.adminAccessGranted) {
80
- return { allow: true, force: true, reason: 'ADMIN_MODERATOR_ACCESS_GRANTED' };
81
- }
82
- // Нейтральный результат (пропуск политики)
83
- return { allow: true, force: false, reason: `NEUTRAL_${policyName.toUpperCase()}` };
84
- }
85
- // Базовый метод проверки доступа
86
- async checkAccess(context) {
87
- this._context = context; // Сохраняем контекст для использования в _normalizeResult
88
- const {
89
- user, // Пользователь
90
- resource, // Тип ресурса
91
- action, // Действие
92
- data, // Данные ресурса
93
- options = {}, // Добавляем опции
94
- isServiceRequest, // Флаг сервисного запроса
95
- } = context;
96
- // Если это сервисный запрос, пропускаем проверки
97
- if (isServiceRequest) {
98
- return {
99
- allow: true,
100
- reason: 'SERVICE_REQUEST_ALLOWED',
101
- };
102
- }
103
- // Проверка базовой аутентификации
104
- if (!user && !options.allowUnauthenticated) {
105
- return {
106
- allow: false,
107
- reason: 'UNAUTHENTICATED_ACCESS_DENIED',
108
- };
109
- }
110
- // Предзагрузка ресурса
111
- if ((action !== 'create') && (data._id || data.params?._id || data.url)) {
112
- try {
113
- const resourceModel = this.getResourceModel(resource);
114
- let currentResource;
115
- if (data._id || data.params?._id) {
116
- currentResource = await resourceModel.findById(data._id || data.params._id);
117
- } else if (data.url) {
118
- currentResource = await resourceModel.findOne({ url: data.url });
119
- }
120
- if (!currentResource) {
121
- return {
122
- allow: false,
123
- reason: 'RESOURCE_NOT_FOUND',
124
- };
125
- }
126
- // Добавляем загруженный ресурс в контекст
127
- context.currentResource = currentResource;
128
- // Добавляем модель ресурса в контекст
129
- context.resourceModel = resourceModel;
130
- } catch (error) {
131
- console.error('Resource loading error:', error);
132
- return {
133
- allow: false,
134
- reason: 'RESOURCE_LOAD_ERROR',
135
- };
136
- }
137
- }
138
- // Выполнение всех глобальных политик параллельно
139
- const policyEntries = Object.entries(this.policies.global);
140
- const policyPromises = policyEntries.map(async ([policyName, policyFn]) => {
141
- try {
142
- const result = await policyFn(context);
143
- return { policyName, result };
144
- } catch (error) {
145
- console.error(`Error in policy ${policyName}:`, error);
146
- // При ошибке возвращаем нейтральный результат
147
- return { policyName, result: undefined, error };
148
- }
149
- });
150
- // Ожидаем выполнения всех политик
151
- const policyResults = await Promise.all(policyPromises);
152
- // Обработка результатов глобальных политик
153
- let hasForceAllow = false;
154
- let hasForceDisallow = false;
155
- let hasDeny = false;
156
- let denyReason = '';
157
- let allowReason = '';
158
- for (const { policyName, result, error } of policyResults) {
159
- if (error) continue; // Пропускаем политики с ошибками
160
- // Нормализуем результат для унифицированной обработки
161
- const normalizedResult = this._normalizeResult(result, policyName);
162
- if (normalizedResult.force) {
163
- if (normalizedResult.allow) {
164
- hasForceAllow = true;
165
- allowReason = normalizedResult.reason;
166
- } else {
167
- hasForceDisallow = true;
168
- denyReason = normalizedResult.reason;
169
- }
170
- } else if (!normalizedResult.allow) {
171
- hasDeny = true;
172
- if (!denyReason) denyReason = normalizedResult.reason;
173
- }
174
- }
175
- // Принятие решения на основе результатов
176
- // 1. Проверка на стопроцентный запрет
177
- if (hasForceDisallow) {
178
- return {
179
- allow: false,
180
- reason: denyReason || 'FORCE_DENIED_BY_POLICY',
181
- };
182
- }
183
- // 2. Проверка на стопроцентный доступ
184
- if (hasForceAllow) {
185
- return {
186
- allow: true,
187
- reason: allowReason || 'FORCE_ALLOWED_BY_POLICY',
188
- };
189
- }
190
- // 3. Проверка на обычный запрет
191
- if (hasDeny) {
192
- return {
193
- allow: false,
194
- reason: denyReason || 'DENIED_BY_POLICY',
195
- };
196
- }
197
- // 4. Проверка политик ресурсов (возможно асинхронное выполнение)
198
- if (this.policies.resources[resource]) {
199
- try {
200
- const resourceResult = await this.policies.resources[resource](context);
201
- const normalizedResult = this._normalizeResult(resourceResult, `RESOURCE_${resource}`);
202
- if (normalizedResult.force) {
203
- return {
204
- allow: normalizedResult.allow,
205
- reason: normalizedResult.reason,
206
- };
207
- }
208
- if (!normalizedResult.allow) {
209
- return {
210
- allow: false,
211
- reason: normalizedResult.reason,
212
- };
213
- }
214
- if (normalizedResult.allow) {
215
- return {
216
- allow: true,
217
- reason: normalizedResult.reason,
218
- };
219
- }
220
- } catch (error) {
221
- console.error(`Error in resource policy for ${resource}:`, error);
222
- }
223
- }
224
- // 5. Выполнение расширений от внешних модулей
225
- const extensionPromises = Object.entries(this.policies.extensions).map(async ([moduleName, extensionFn]) => {
226
- try {
227
- const extensionResult = await extensionFn(context);
228
- return { moduleName, result: extensionResult };
229
- } catch (error) {
230
- console.error(`Error in extension ${moduleName}:`, error);
231
- return { moduleName, result: null, error };
232
- }
233
- });
234
- const extensionResults = await Promise.all(extensionPromises);
235
- for (const { moduleName, result, error } of extensionResults) {
236
- if (error) continue;
237
- if (result && result.allow) {
238
- return {
239
- allow: true,
240
- reason: `ALLOWED_BY_${moduleName.toUpperCase()}_EXTENSION`,
241
- };
242
- }
243
- }
244
- // 6. Финальное решение на основе настроек
245
- return {
246
- allow: !this.options.defaultDeny,
247
- reason: this.options.defaultDeny ? 'ACCESS_DENIED' : 'ACCESS_ALLOWED',
248
- };
249
- }
250
- // Проверка сервисного ключа
251
- validateServiceKey(providedKey) {
252
- return providedKey && providedKey === this.options.serviceKey;
253
- }
254
- // Middleware для Express
255
- middleware(resource, action, options = {}) {
256
- return async (req, res, next) => {
257
- try {
258
- // Проверка сервисного ключа
259
- const serviceKey = req.headers['x-service-key'];
260
- if (serviceKey && this.validateServiceKey(serviceKey)) {
261
- req.isServiceRequest = true; // Помечаем, что это запрос от другого сервиса
262
- return next();
263
- }
264
- const context = {
265
- user: req.userId,
266
- resource,
267
- action,
268
- data: {
269
- ...req.body,
270
- ...req.query,
271
- params: req.params,
272
- },
273
- options, // Передаем опции в контекст
274
- req, // Передаем весь объект запроса для максимальной гибкости
275
- res, // И объект ответа
276
- isServiceRequest: req.isServiceRequest, // Передаем флаг сервисного запроса
277
- };
278
- const accessResult = await this.checkAccess(context);
279
- if (context.req?.body) req.body = context.req.body;
280
- if (context.req?.query) req.query = context.req.query;
281
- if (context.data?.params) req.params = context.data.params;
282
- if (accessResult.allow) {
283
- req.accessResult = accessResult;
284
- return next();
285
- }
286
- return res.status(403).json({
287
- errorCode: accessResult.reason,
288
- message: 'Access Denied',
289
- });
290
- } catch (error) {
291
- console.error('Access control error:', error);
292
- return res.status(500).json({
293
- errorCode: 'INTERNAL_ACCESS_CONTROL_ERROR',
294
- message: 'Internal Server Error',
295
- });
296
- }
297
- };
298
- }
299
- }
300
- // Экспорт синглтона
301
- let instance = null;
302
- export const getInstance = (db, options) => {
303
- if (!instance) {
304
- instance = new GlobalABAC(db, options);
305
- }
306
- return instance;
307
- };
308
- export default {
309
- getInstance,
310
- };
@@ -1,89 +0,0 @@
1
- import Cache from '@martyrs/src/modules/core/controllers/classes/core.cache.js';
2
- import Logger from '@martyrs/src/modules/core/controllers/classes/core.logger.js';
3
- import coreQuery from '@martyrs/src/modules/core/controllers/utils/queryProcessor.js';
4
- class CRUD {
5
- constructor(basePath, app, db, model, options) {
6
- this.model = model;
7
- this.cache = new Cache();
8
- this.logger = new Logger(db);
9
- this.app = app;
10
- this.basePath = basePath;
11
- if (!options || (options && !options.disableDefaultRoutes)) this.registerRoutes();
12
- }
13
- registerRoutes() {
14
- this.app.post(`${this.basePath}/create`, this.create.bind(this));
15
- this.app.get(`${this.basePath}/read`, this.read.bind(this));
16
- this.app.put(`${this.basePath}/update`, this.update.bind(this));
17
- this.app.delete(`${this.basePath}/delete`, this.delete.bind(this));
18
- }
19
- async create(req, res) {
20
- try {
21
- const createdData = await this.model.create(req.body);
22
- await this.cache.flush();
23
- res.status(201).json(createdData);
24
- } catch (error) {
25
- console.log(error);
26
- this.logger.error('Ошибка создания данных', error);
27
- res.status(500).json({ error: error.message });
28
- }
29
- }
30
- async read(req, res) {
31
- try {
32
- let stages = [];
33
- stages = [
34
- ...coreQuery.getBasicOptions(req.query),
35
- // For creator
36
- coreQuery.getCreatorUserLookupStage(),
37
- coreQuery.getCreatorOrganizationLookupStage(),
38
- // For owner
39
- coreQuery.getOwnerUserLookupStage(),
40
- coreQuery.getOwnerOrganizationLookupStage(),
41
- coreQuery.getAddFieldsCreatorOwnerStage(),
42
- // Pagination
43
- ...coreQuery.getSortingOptions(req.query.sortParam, req.query.sortOrder),
44
- ...coreQuery.getPaginationOptions(req.query.skip, req.query.limit),
45
- coreQuery.removeTempPropeties(),
46
- ];
47
- const cacheKey = JSON.stringify({ stages });
48
- let data = await this.cache.get(cacheKey);
49
- if (!data) {
50
- data = await this.model.aggregate(stages).exec();
51
- await this.cache.set(cacheKey, data);
52
- }
53
- res.json(data);
54
- } catch (error) {
55
- this.logger.error(error);
56
- res.status(500).json({ error: error.message });
57
- }
58
- }
59
- async update(req, res) {
60
- try {
61
- const updatedData = await this.model.findOneAndUpdate({ _id: req.body._id }, req.body, {
62
- new: true,
63
- runValidators: true,
64
- });
65
- if (!updatedData) {
66
- throw new Error('Документ не найден.');
67
- }
68
- await this.cache.flush();
69
- res.json(updatedData);
70
- } catch (error) {
71
- this.logger.error('Ошибка обновления данных', error);
72
- res.status(404).json({ error: error.message });
73
- }
74
- }
75
- async delete(req, res) {
76
- try {
77
- const deletedData = await this.model.findOneAndDelete({ _id: req.body._id });
78
- if (!deletedData) {
79
- throw new Error('Документ не найден.');
80
- }
81
- await this.cache.flush();
82
- res.status(204).send();
83
- } catch (error) {
84
- this.logger.error('Ошибка удаления данных', error);
85
- res.status(404).json({ error: error.message });
86
- }
87
- }
88
- }
89
- export default CRUD;
@@ -1,28 +0,0 @@
1
- import js from '@eslint/js';
2
- import globals from 'globals';
3
- import reactHooks from 'eslint-plugin-react-hooks';
4
- import reactRefresh from 'eslint-plugin-react-refresh';
5
- import tseslint from 'typescript-eslint';
6
-
7
- export default tseslint.config(
8
- { ignores: ['dist'] },
9
- {
10
- extends: [js.configs.recommended, ...tseslint.configs.recommended],
11
- files: ['**/*.{ts,tsx}'],
12
- languageOptions: {
13
- ecmaVersion: 2020,
14
- globals: core.browser,
15
- },
16
- plugins: {
17
- 'react-hooks': reactHooks,
18
- 'react-refresh': reactRefresh,
19
- },
20
- rules: {
21
- ...reactHooks.configs.recommended.rules,
22
- 'react-refresh/only-export-components': [
23
- 'warn',
24
- { allowConstantExport: true },
25
- ],
26
- },
27
- }
28
- );