@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
@@ -38,14 +38,14 @@ export default `
38
38
  requestIdleCallback(() => {
39
39
  const link = document.createElement('link');
40
40
  link.rel = 'manifest';
41
- link.href = '/manifest.json';
41
+ link.href = '/pwa-manifest.json';
42
42
  document.head.appendChild(link);
43
43
  });
44
44
  } else {
45
45
  setTimeout(() => {
46
46
  const link = document.createElement('link');
47
47
  link.rel = 'manifest';
48
- link.href = '/manifest.json';
48
+ link.href = '/pwa-manifest.json';
49
49
  document.head.appendChild(link);
50
50
  }, 0);
51
51
  }
@@ -89,6 +89,7 @@ async function Submit() {
89
89
  if (props.callback) setTimeout(() => props.callback(), props.callbackDelay)
90
90
 
91
91
  } catch (err) {
92
+ console.error('=== BUTTON ERROR ===', err)
92
93
  emits('error', err)
93
94
  // Если возникла ошибка, мы изменяем стили и устанавливаем сообщение об ошибке
94
95
  button.value.classList.replace('bg-main', 'bg-fourth-nano')
@@ -113,28 +114,23 @@ async function Submit() {
113
114
  class="button"
114
115
  :class="{ 'button--disabled': loading || validation }"
115
116
  >
116
- <Transition name="content" mode="out-in">
117
- <!-- Default slot content -->
118
- <span v-if="!loading && !error && !finished || !showLoader" class="button-content">
119
- <slot></slot>
120
- </span>
121
- <!-- Loading state -->
122
- <Loader v-else-if="loading && !error && showLoader" class="icon button-content pos-relative pos-t-0 pos-l-0 loading"/>
123
- <!-- Success state -->
124
- <span v-else-if="finished && showSucces" class="button-content t-semi t-center w-100 loading t-black">
125
- <template v-if="text.success">
126
- {{ text.success }}
127
- </template>
128
- <IconCheckmark v-else class="icon" />
129
- </span>
130
- <!-- Error state -->
131
- <span v-else-if="error" class="button-content t-center w-100 error">
132
- <template v-if="text.error">
133
- {{ text.error }}
134
- </template>
135
- <IconCross v-else class="icon" />
136
- </span>
137
- </Transition>
117
+ <span class="button-content" :class="{ 'hidden': loading || error || finished }">
118
+ <slot></slot>
119
+ </span>
120
+
121
+ <span class="button-loader" :class="{ 'active': loading && showLoader }">
122
+ <Loader class=""/>
123
+ </span>
124
+
125
+ <span class="button-success" :class="{ 'active': finished && showSucces }">
126
+ <template v-if="text.success">{{ text.success }}</template>
127
+ <IconCheckmark v-else class="i-regular" />
128
+ </span>
129
+
130
+ <span class="button-error" :class="{ 'active': error }">
131
+ <template v-if="text.error">{{ text.error }}</template>
132
+ <IconCross v-else class="i-regular" />
133
+ </span>
138
134
 
139
135
  <!-- Counter -->
140
136
  <div v-if="counter" class="button-counter font-second flex flex-center">
@@ -157,6 +153,7 @@ a.button {
157
153
  }
158
154
 
159
155
  .button {
156
+ position: relative;
160
157
  display: flex;
161
158
  padding: var(--small);
162
159
  border-radius: var(--small);
@@ -206,32 +203,48 @@ a.button {
206
203
  align-items: center;
207
204
  justify-content: center;
208
205
  gap: 8px;
206
+ transition: opacity 0.3s ease;
209
207
  }
210
208
 
211
- .icon {
212
- width: 1rem;
213
- height: 1rem;
214
- }
215
209
 
216
- /* Vue Transitions */
217
- .content-enter-active,
218
- .content-leave-active {
219
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
210
+ .button-loader {
211
+ position: absolute;
212
+ inset: 0;
213
+ display: flex;
214
+ align-items: center;
215
+ justify-content: center;
216
+ opacity: 0;
217
+ transition: opacity 0.3s ease;
218
+ pointer-events: none;
220
219
  }
221
220
 
222
- .content-enter-from {
221
+ .button-success {
222
+ position: absolute;
223
+ inset: 0;
224
+ display: flex;
225
+ align-items: center;
226
+ justify-content: center;
223
227
  opacity: 0;
224
- transform: translateY(8px) scale(0.95);
228
+ transition: opacity 0.3s ease;
229
+ pointer-events: none;
225
230
  }
226
231
 
227
- .content-leave-to {
232
+ .button-error {
233
+ position: absolute;
234
+ inset: 0;
235
+ display: flex;
236
+ align-items: center;
237
+ justify-content: center;
228
238
  opacity: 0;
229
- transform: translateY(-8px) scale(0.95);
239
+ transition: opacity 0.3s ease;
240
+ pointer-events: none;
230
241
  }
231
242
 
232
- .content-enter-to,
233
- .content-leave-from {
243
+ .active {
234
244
  opacity: 1;
235
- transform: translateY(0) scale(1);
245
+ }
246
+
247
+ .hidden {
248
+ opacity: 0;
236
249
  }
237
250
  </style>
@@ -404,7 +404,7 @@
404
404
  }
405
405
 
406
406
  // Разрешаем только + и цифры
407
- dialCodeInput.value = dialCodeInput.value.replace(/[^\+\d]/g, '');
407
+ dialCodeInput.value = dialCodeInput.value.replace(/[^+\d]/g, '');
408
408
 
409
409
  // Убеждаемся что + только в начале
410
410
  const plusCount = (dialCodeInput.value.match(/\+/g) || []).length;
@@ -22,7 +22,7 @@ export default {
22
22
  },
23
23
  centered: {
24
24
  type: Boolean,
25
- default: true, // По умолчанию лоадер центрирован (для обратной совместимости)
25
+ default: false
26
26
  },
27
27
  },
28
28
  };
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <VueDraggableNext
3
- v-bind="dragOptions"
3
+ v-bind="dragOptions"
4
+ :disabled="!dragndrop"
4
5
  class="dragArea list-group w-full"
5
6
  :list="items"
6
7
  :handle="'.my-handle'"
@@ -11,10 +12,11 @@
11
12
  :item="item"
12
13
  >
13
14
  </slot>
14
- <Tree
15
+ <Tree
15
16
  :items="item.children"
16
17
  :state="state"
17
18
  :parent-id="item._id"
19
+ :dragndrop="dragndrop"
18
20
  @update="emitChange"
19
21
  class="pd-l-medium"
20
22
  v-slot="{ item }"
@@ -36,7 +38,8 @@ import Tree from './Tree.vue';
36
38
  const props = defineProps({
37
39
  items: Array,
38
40
  state: Array,
39
- parentId: { type: String, default: null }
41
+ parentId: { type: String, default: null },
42
+ dragndrop: { type: Boolean, default: true }
40
43
  });
41
44
 
42
45
  const emits = defineEmits(['update']);
File without changes
@@ -0,0 +1,17 @@
1
+ ## TODO: Архитектурные задачи
2
+
3
+ ### Рефакторинг featured в категориях
4
+
5
+ **Проблема**: `featured` находится в enum статусов категории, но это архитектурная ошибка.
6
+
7
+ **Решение**: Вынести `featured` из статусов в отдельное поле:
8
+ - Удалить `featured` из `enum: ['draft', 'published', 'internal', 'archived', 'removed']`
9
+ - Добавить в модель категории: `featured: { type: Boolean, default: false }`
10
+ - Обновить все контроллеры и компоненты, использующие `status: 'featured'`
11
+ - Добавить фильтрацию по `featured: true/false`
12
+
13
+ **Затронутые файлы**:
14
+ - `/Users/magicofoz/Development/OZDAO/ozdao.dev/app/martyrs/src/modules/core/models/schemas/common.schema.js`
15
+ - `/Users/magicofoz/Development/OZDAO/ozdao.dev/app/martyrs/src/modules/products/models/category.model.js`
16
+ - `/Users/magicofoz/Development/OZDAO/ozdao.dev/app/martyrs/src/modules/products/controllers/categories.controller.js`
17
+ - Все компоненты фронтенда, использующие статус 'featured'
@@ -13,7 +13,8 @@ console.log(`[LOADING 36] Store imports completed in ${storesTime.duration.toFix
13
13
 
14
14
  // Router
15
15
  import addRoutes from '@martyrs/src/modules/core/views/router/addRoutes.js';
16
- import { getRoutes } from './auth.router.js';
16
+ import { getAuthRoutes } from './views/router/auth.router.js';
17
+ import { getUsersRoutes } from './views/router/users.router.js';
17
18
 
18
19
  // Middlewares
19
20
  import * as validationAuth from '@martyrs/src/modules/auth/views/middlewares/auth.validation.js';
@@ -43,10 +44,11 @@ export { default as SliderFeatures } from './views/components/sections/SliderFea
43
44
  function initializeAuth(app, store, router, options = {}) {
44
45
  i18nManager.register('auth', locales);
45
46
 
46
- const routes = getRoutes(options);
47
- routes.forEach(({ parentName, config }) => {
48
- addRoutes(router, { ...config, parentName });
49
- });
47
+ const authRoute = getAuthRoutes(options);
48
+ const usersRoute = getUsersRoutes(options);
49
+
50
+ addRoutes(router, { ...authRoute.config, parentName: authRoute.parentName });
51
+ addRoutes(router, { ...usersRoute.config, parentName: usersRoute.parentName });
50
52
 
51
53
  store.addStore('auth', storeAuth);
52
54
  store.addStore('twofa', storeTwofa);
@@ -64,7 +66,8 @@ const ModuleAuth = {
64
66
  storeUsers,
65
67
  },
66
68
  router: {
67
- getRoutes,
69
+ getAuthRoutes,
70
+ getUsersRoutes,
68
71
  },
69
72
  middlewares: {
70
73
  validationAuth,
@@ -77,7 +80,8 @@ export {
77
80
  storeAuth,
78
81
  storeTwofa,
79
82
  storeUsers,
80
- getRoutes,
83
+ getAuthRoutes,
84
+ getUsersRoutes,
81
85
  validationAuth,
82
86
  initializeAuth as initialize,
83
87
  };
@@ -113,12 +113,12 @@ import { useRoute, useRouter } from 'vue-router'
113
113
  import { useI18n } from 'vue-i18n'
114
114
  // Import store
115
115
  import { useStore } from '@martyrs/src/modules/core/views/store/core.store.js'
116
+ import * as auth from '@martyrs/src/modules/auth/views/store/auth.js'
116
117
  // Import validation
117
118
  import * as inputsValidation from '@martyrs/src/modules/auth/views/validations/inputs.validation'
118
119
 
119
120
  // Get store
120
121
  const store = useStore()
121
- const auth = store.auth
122
122
  const core = store.core
123
123
 
124
124
  // Init validation
@@ -0,0 +1,94 @@
1
+ // auth.router.js - Authentication routes
2
+ import { requiresNoAuth, resetUser, checkUser } from '../middlewares/auth.validation.js';
3
+
4
+ export function getAuthRoutes(options = {}) {
5
+ const route = options.route || 'Home';
6
+
7
+ return {
8
+ parentName: route,
9
+ config: {
10
+ basePath: 'auth',
11
+ component: () => import(/* webpackChunkName: "auth-layout" */ '../components/layouts/Auth.vue'),
12
+ meta: {
13
+ title: {
14
+ en: 'Аутентификация',
15
+ ru: 'Authentication',
16
+ },
17
+ },
18
+ routes: [
19
+ {
20
+ path: 'signin',
21
+ name: 'Sign In',
22
+ beforeEnter: [requiresNoAuth, resetUser],
23
+ meta: {
24
+ title: {
25
+ en: 'Sign In',
26
+ ru: 'Вход',
27
+ },
28
+ },
29
+ component: () => import(/* webpackChunkName: "signin" */ '../components/pages/SignIn.vue'),
30
+ },
31
+ {
32
+ path: 'reset-password',
33
+ name: 'Reset Password',
34
+ beforeEnter: [requiresNoAuth, resetUser],
35
+ meta: {
36
+ title: {
37
+ en: 'Reset Password',
38
+ ru: 'Сбросить Пароль',
39
+ },
40
+ },
41
+ component: () => import(/* webpackChunkName: "reset-password" */ '../components/pages/ResetPassword.vue'),
42
+ },
43
+ {
44
+ path: 'signup',
45
+ name: 'Sign Up',
46
+ beforeEnter: [requiresNoAuth, resetUser],
47
+ meta: {
48
+ title: {
49
+ en: 'Sign Up',
50
+ ru: 'Регистрация',
51
+ },
52
+ },
53
+ component: () => import(/* webpackChunkName: "signup" */ '../components/pages/SignUp.vue'),
54
+ },
55
+ {
56
+ path: 'enter-code',
57
+ name: 'Enter Code',
58
+ beforeEnter: [requiresNoAuth, checkUser],
59
+ meta: {
60
+ title: {
61
+ en: 'Enter Code',
62
+ ru: 'Введите Код',
63
+ },
64
+ },
65
+ component: () => import(/* webpackChunkName: "signup" */ '../components/pages/EnterCode.vue'),
66
+ },
67
+ {
68
+ path: 'enter-password',
69
+ name: 'Enter Password',
70
+ beforeEnter: [requiresNoAuth, checkUser],
71
+ meta: {
72
+ title: {
73
+ en: 'Enter Password',
74
+ ru: 'Введите Пароль',
75
+ },
76
+ },
77
+ component: () => import(/* webpackChunkName: "signup" */ '../components/pages/EnterPassword.vue'),
78
+ },
79
+ {
80
+ path: 'invite',
81
+ name: 'Invite',
82
+ beforeEnter: [requiresNoAuth, resetUser],
83
+ meta: {
84
+ title: {
85
+ en: 'Invite',
86
+ ru: 'Приглашение',
87
+ },
88
+ },
89
+ component: () => import(/* webpackChunkName: "signup" */ '../components/pages/Invite.vue'),
90
+ },
91
+ ],
92
+ }
93
+ };
94
+ }
@@ -0,0 +1,153 @@
1
+ // users.router.js - User profile routes
2
+ import * as auth from '@martyrs/src/modules/auth/views/store/auth.js';
3
+ import { useGlobalMixins } from '@martyrs/src/modules/core/views/mixins/mixins.js';
4
+ import { requiresAuth } from '../middlewares/auth.validation.js';
5
+ import IconPlus from '@martyrs/src/modules/icons/navigation/IconPlus.vue';
6
+ import { navigationItems } from '@martyrs/src/modules/auth/views/configs/navigation.user.config.js';
7
+ import ProfileCard from '@martyrs/src/modules/auth/views/components/blocks/ProfileCard.vue';
8
+ import HelpCard from '@martyrs/src/modules/core/views/components/blocks/HelpCard.vue';
9
+
10
+ const { isPhone, isTablet } = useGlobalMixins();
11
+
12
+ export function getUsersRoutes(options = {}) {
13
+ const route = options.route || 'Home';
14
+
15
+ return {
16
+ parentName: route,
17
+ config: {
18
+ basePath: 'users',
19
+ meta: {
20
+ title: {
21
+ en: 'Users',
22
+ ru: 'Пользователи',
23
+ },
24
+ },
25
+ routes: [
26
+ {
27
+ path: ':_id',
28
+ name: 'User Profile Root',
29
+ meta: {
30
+ title: {
31
+ en: 'Profile',
32
+ ru: 'Профиль',
33
+ },
34
+ sidebar_hover: false,
35
+ sidebar_navigation_items: navigationItems,
36
+ sidebar_header_component: ProfileCard,
37
+ sidebar_footer_component: HelpCard,
38
+ sidebarOpenOnEnter: true,
39
+ sidebarCloseOnLeave: true
40
+ },
41
+ children: [
42
+ {
43
+ path: '',
44
+ name: 'User Profile',
45
+ meta: {
46
+ title: {
47
+ en: 'Profile',
48
+ ru: 'Профиль',
49
+ },
50
+ title_hide: true,
51
+ hideNavigationBar: route => route.params._id === auth.state.user._id,
52
+ },
53
+ component: () => import(/* webpackChunkName: "profile" */ '../components/pages/Profile.vue'),
54
+ children: [
55
+ {
56
+ path: 'edit',
57
+ name: 'User Edit Profile',
58
+ beforeEnter: [requiresAuth],
59
+ component: () => import(/* webpackChunkName: "profile-edit" */ '../components/pages/ProfileEdit.vue'),
60
+ children: [
61
+ {
62
+ path: 'profile',
63
+ name: 'Profile Edit Profile',
64
+ component: () => import(/* webpackChunkName: "profile-edit-profile" */ '../components/pages/ProfileEditProfile.vue')
65
+ },
66
+ {
67
+ path: 'account',
68
+ name: 'Profile Edit Account',
69
+ component: () => import(/* webpackChunkName: "profile-edit-account" */ '../components/pages/ProfileEditAccount.vue')
70
+ }
71
+ ]
72
+ }
73
+ ]
74
+ },
75
+ {
76
+ path: 'dashboard',
77
+ name: 'User Dashboard',
78
+ beforeEnter: [
79
+ requiresAuth,
80
+ (to) => {
81
+ if (to.params._id !== auth.state.user._id) {
82
+ return { name: 'User Profile', params: { _id: to.params._id } };
83
+ }
84
+ }
85
+ ],
86
+ meta: {
87
+ title: {
88
+ en: 'Dashboard',
89
+ ru: 'Дашборд',
90
+ },
91
+ },
92
+ component: () => import(/* webpackChunkName: "profile-dashboard" */ '../components/pages/UserDashboard.vue'),
93
+ },
94
+ {
95
+ path: 'blogposts',
96
+ name: 'User Posts',
97
+ meta: {
98
+ title: {
99
+ en: 'Posts',
100
+ ru: 'Посты',
101
+ },
102
+ },
103
+ component: () => import(/* webpackChunkName: "profile" */ '../components/pages/ProfileBlogposts.vue'),
104
+ },
105
+ {
106
+ path: 'events',
107
+ name: 'User Events',
108
+ meta: {
109
+ title: {
110
+ en: 'Events',
111
+ ru: 'События',
112
+ },
113
+ },
114
+ component: () => import(/* webpackChunkName: "profile" */ '@martyrs/src/modules/events/components/pages/EventsBackoffice.vue'),
115
+ },
116
+ {
117
+ path: 'organizations',
118
+ name: 'User Organizations',
119
+ meta: {
120
+ title: {
121
+ en: 'Groups',
122
+ ru: 'Группы',
123
+ },
124
+ actions: [
125
+ {
126
+ component: IconPlus,
127
+ props: {
128
+ fill: 'rgb(var(--main))',
129
+ },
130
+ condition: () => auth.state.user && auth.state.user._id,
131
+ action: router => router.push({ name: 'Create Organization' }),
132
+ },
133
+ ],
134
+ },
135
+ component: () => import(/* webpackChunkName: "profile" */ '@martyrs/src/modules/organizations/components/pages/Organizations.vue'),
136
+ },
137
+ {
138
+ path: 'wallet',
139
+ name: 'User Wallet',
140
+ meta: {
141
+ title: {
142
+ en: 'Wallet',
143
+ ru: 'Кошелек',
144
+ },
145
+ },
146
+ component: () => import(/* webpackChunkName: "profile" */ '@martyrs/src/modules/wallet/views/components/pages/Wallet.vue'),
147
+ },
148
+ ],
149
+ },
150
+ ],
151
+ }
152
+ };
153
+ }
@@ -3,10 +3,10 @@
3
3
  <div class="br-b h3 h-4r pd-semi br-solid br-black-transp-10">Backoffice</div>
4
4
  <div class="pd-semi">
5
5
  <span class="pd-thin uppercase t-medium t-transp">Menu</span>
6
- <div
7
- v-for="item in menuItems"
6
+ <div
7
+ v-for="item in menuItems"
8
8
  :key="item.name"
9
- @click="router.push({ name: item.routeName })"
9
+ @click="router.push(item.to || { name: item.routeName })"
10
10
  class="flex pd-thin flex-v-center cursor-pointer">
11
11
  <component
12
12
  v-if="item.icon"
@@ -19,10 +19,10 @@
19
19
  </div>
20
20
 
21
21
  <span class="pd-thin d-block mn-t-medium uppercase t-medium t-transp">General</span>
22
- <div
23
- v-for="item in generalItems"
22
+ <div
23
+ v-for="item in generalItems"
24
24
  :key="item.name"
25
- @click="router.push({ name: item.routeName })"
25
+ @click="router.push(item.to || { name: item.routeName })"
26
26
  class="flex pd-thin flex-v-center cursor-pointer">
27
27
  <component
28
28
  v-if="item.icon"
@@ -79,7 +79,7 @@ const menuItems = [
79
79
  {
80
80
  name: 'organizations',
81
81
  title: 'Organizations',
82
- routeName: 'Backoffice Organizations',
82
+ to: '/backoffice/organizations',
83
83
  icon: IconGroups
84
84
  },
85
85
  {
@@ -7,11 +7,19 @@ import ReactionModel from './models/reaction.model.js';
7
7
  import blogRoutes from './routes/blog.routes.js';
8
8
  import commentsRoutes from './routes/comments.routes.js';
9
9
  import reactionsRoutes from './routes/reactions.routes.js';
10
+ import coreabac from '@martyrs/src/modules/core/controllers/classes/abac/abac.js';
11
+ import initBlogPolicies from './policies/blog.policies.js';
10
12
  function initializeCommunity(app, db, origins, publicPath) {
11
13
  // Настраиваем модели в объекте базы данных
12
14
  db.blogpost = BlogpostModel(db);
13
15
  db.comment = CommentModel(db);
14
16
  db.reaction = ReactionModel(db);
17
+
18
+ // Инициализируем политики ABAC
19
+ const { getInstance } = coreabac;
20
+ const abac = getInstance(db);
21
+ initBlogPolicies(abac, db);
22
+
15
23
  // Настраиваем маршруты, если объект приложения передан
16
24
  if (app) {
17
25
  blogRoutes(app, db, origins, publicPath);
@@ -0,0 +1,55 @@
1
+ export default function initBlogPolicies(abac, db) {
2
+ abac.registerResourcePolicy(
3
+ 'blogposts',
4
+ async context => {
5
+ const allowed = ['published', 'active', 'featured'];
6
+
7
+ // 1. Анонимный read — обрезаем статусы прямо в политике
8
+ if (
9
+ context.action === 'read' &&
10
+ !context.user &&
11
+ (context.options?.allowPublished || context.req?.method === 'GET')
12
+ ) {
13
+ const current = context.data?.query?.status;
14
+ const list = Array.isArray(current) ? current : (current ? [current] : []);
15
+ const filtered = list.filter(s => allowed.includes(s));
16
+ context.req.query.status = filtered.length ? filtered : allowed;
17
+ context.data.query.status = context.req.query.status;
18
+ }
19
+
20
+ // 2. Проверка доступа к draft/archived постам
21
+ if (context.action === 'read' && context.currentResource) {
22
+ const status = context.currentResource.status;
23
+ if (!allowed.includes(status)) {
24
+ // Если статус draft/archived, проверяем права доступа
25
+ if (!context.user) {
26
+ return { allow: false, reason: 'DRAFT_POST_REQUIRES_AUTH' };
27
+ }
28
+
29
+ const ownerId = context.currentResource.owner?.target || context.currentResource.creator?.target;
30
+
31
+ // Проверяем владельца
32
+ if (String(ownerId) === String(context.user)) {
33
+ return { allow: true };
34
+ }
35
+
36
+ // Проверяем права организации
37
+ if (context.currentResource.owner?.type === 'organization' && context.checkOrganizationRight) {
38
+ const hasOrgAccess = await context.checkOrganizationRight('blogposts', 'read');
39
+ if (hasOrgAccess) {
40
+ return { allow: true, reason: 'ORGANIZATION_MEMBER_ACCESS' };
41
+ }
42
+ }
43
+
44
+ return { allow: false, reason: 'DRAFT_POST_ACCESS_DENIED' };
45
+ }
46
+ }
47
+
48
+ // 3. Остальные проверки можешь расширять позже
49
+ return { allow: true };
50
+ },
51
+ { modelName: 'blogpost' } // важно для loadResource
52
+ );
53
+
54
+ return abac;
55
+ }
@@ -1,5 +1,5 @@
1
1
  import middlewareFactoryAuth from '@martyrs/src/modules/auth/controllers/middlewares/index.js';
2
- import coreabac from '@martyrs/src/modules/core/controllers/classes/core.abac.js';
2
+ import coreabac from '@martyrs/src/modules/core/controllers/classes/abac/abac.js';
3
3
  import controllerFactory from '../controllers/blog.controller.js';
4
4
  import middlewareFactoryCommunity from '../middlewares/server/index.js';
5
5
  // ABAC
@@ -1,5 +1,5 @@
1
1
  import middlewareFactoryAuth from '@martyrs/src/modules/auth/controllers/middlewares/index.js';
2
- import coreabac from '@martyrs/src/modules/core/controllers/classes/core.abac.js';
2
+ import coreabac from '@martyrs/src/modules/core/controllers/classes/abac/abac.js';
3
3
  import controllerFactory from '../controllers/comments.controller.js';
4
4
  // ABAC
5
5
  const { getInstance } = coreabac;
@@ -1,11 +1,8 @@
1
1
  import middlewareFactoryAuth from '@martyrs/src/modules/auth/controllers/middlewares/index.js';
2
- import coreabac from '@martyrs/src/modules/core/controllers/classes/core.abac.js';
3
2
  import controllerFactory from '../controllers/reactions.controller.js';
4
- // ABAC
5
- const { getInstance } = coreabac;
3
+
6
4
  export default (function (app, db) {
7
5
  const controller = controllerFactory(db);
8
- const abac = getInstance(db);
9
6
  const { authJwt } = middlewareFactoryAuth(db);
10
7
  app.get('/api/reactions/read', [authJwt.verifyToken(true)], controller.read);
11
8
  app.post('/api/reactions/create', [authJwt.verifyToken()], controller.create);