@open-mercato/core 0.4.2-canary-3b5064ce72 → 0.4.2-canary-15e78de280
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/generated/entities/api_key/index.js +2 -0
- package/dist/generated/entities/api_key/index.js.map +2 -2
- package/dist/generated/entities.ids.generated.js +1 -5
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +0 -2
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/api_docs/frontend/docs/api/page.js +2 -3
- package/dist/modules/api_docs/frontend/docs/api/page.js.map +2 -2
- package/dist/modules/api_keys/backend/api-keys/page.js +1 -1
- package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
- package/dist/modules/api_keys/data/entities.js +3 -0
- package/dist/modules/api_keys/data/entities.js.map +2 -2
- package/dist/modules/api_keys/migrations/Migration20260125204102.js +13 -0
- package/dist/modules/api_keys/migrations/Migration20260125204102.js.map +7 -0
- package/dist/modules/api_keys/services/apiKeyService.js +41 -0
- package/dist/modules/api_keys/services/apiKeyService.js.map +3 -3
- package/dist/modules/attachments/components/AttachmentLibrary.js +0 -4
- package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js +0 -2
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
- package/dist/modules/auth/api/admin/nav.js +3 -4
- package/dist/modules/auth/api/admin/nav.js.map +2 -2
- package/dist/modules/auth/api/login.js +6 -25
- package/dist/modules/auth/api/login.js.map +2 -2
- package/dist/modules/auth/api/reset/confirm.js +2 -25
- package/dist/modules/auth/api/reset/confirm.js.map +2 -2
- package/dist/modules/auth/api/reset.js +0 -23
- package/dist/modules/auth/api/reset.js.map +2 -2
- package/dist/modules/auth/api/sidebar/preferences/route.js +9 -14
- package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +2 -4
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/roles/[id]/edit/page.js +1 -4
- package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/roles/page.js +3 -3
- package/dist/modules/auth/backend/roles/page.js.map +2 -2
- package/dist/modules/auth/backend/users/[id]/edit/page.js +3 -18
- package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/users/create/page.js +2 -15
- package/dist/modules/auth/backend/users/create/page.js.map +2 -2
- package/dist/modules/auth/backend/users/page.js +3 -3
- package/dist/modules/auth/backend/users/page.js.map +2 -2
- package/dist/modules/auth/cli.js +11 -25
- package/dist/modules/auth/cli.js.map +2 -2
- package/dist/modules/auth/commands/users.js +2 -59
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/auth/data/validators.js +3 -6
- package/dist/modules/auth/data/validators.js.map +2 -2
- package/dist/modules/auth/frontend/login.js +3 -112
- package/dist/modules/auth/frontend/login.js.map +2 -2
- package/dist/modules/auth/frontend/reset/[token]/page.js +10 -20
- package/dist/modules/auth/frontend/reset/[token]/page.js.map +2 -2
- package/dist/modules/auth/lib/setup-app.js +8 -42
- package/dist/modules/auth/lib/setup-app.js.map +2 -2
- package/dist/modules/auth/services/authService.js +3 -24
- package/dist/modules/auth/services/authService.js.map +2 -2
- package/dist/modules/auth/services/rbacService.js.map +2 -2
- package/dist/modules/business_rules/api/execute/route.js +1 -7
- package/dist/modules/business_rules/api/execute/route.js.map +2 -2
- package/dist/modules/business_rules/backend/rules/page.js +0 -4
- package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
- package/dist/modules/business_rules/backend/sets/page.js +0 -3
- package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
- package/dist/modules/business_rules/cli.js +1 -2
- package/dist/modules/business_rules/cli.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-engine.js +3 -33
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/catalog/components/PriceKindSettings.js +0 -2
- package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js +0 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
- package/dist/modules/configs/cli.js +0 -6
- package/dist/modules/configs/cli.js.map +2 -2
- package/dist/modules/configs/components/CachePanel.js +4 -4
- package/dist/modules/configs/components/CachePanel.js.map +2 -2
- package/dist/modules/configs/lib/system-status.js +1 -48
- package/dist/modules/configs/lib/system-status.js.map +2 -2
- package/dist/modules/configs/lib/upgrade-actions.js +0 -18
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/page.js +0 -3
- package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js +0 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +0 -3
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +0 -3
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/page.js +0 -3
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +0 -31
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/components/CustomerTodosTable.js +0 -1
- package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js +1 -2
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.js +1 -2
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.js +1 -2
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js +1 -2
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js.map +2 -2
- package/dist/modules/dashboards/cli.js +5 -44
- package/dist/modules/dashboards/cli.js.map +2 -2
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +11 -16
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +3 -3
- package/dist/modules/dashboards/services/widgetDataService.js +3 -139
- package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js +1 -2
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryTable.js +0 -2
- package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
- package/dist/modules/directory/backend/directory/organizations/page.js +2 -2
- package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
- package/dist/modules/entities/components/SystemEntitiesTable.js +1 -1
- package/dist/modules/entities/components/SystemEntitiesTable.js.map +2 -2
- package/dist/modules/entities/components/UserEntitiesTable.js +2 -2
- package/dist/modules/entities/components/UserEntitiesTable.js.map +2 -2
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +3 -3
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
- package/dist/modules/feature_toggles/components/OverridesTable.js +1 -1
- package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js +2 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
- package/dist/modules/query_index/cli.js +7 -63
- package/dist/modules/query_index/cli.js.map +2 -2
- package/dist/modules/query_index/components/QueryIndexesTable.js +1 -7
- package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +0 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +0 -2
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +0 -53
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +0 -26
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/dist/modules/sales/components/AdjustmentKindSettings.js +2 -2
- package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
- package/dist/modules/sales/components/PaymentMethodsSettings.js +2 -2
- package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
- package/dist/modules/sales/components/ShippingMethodsSettings.js +2 -2
- package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
- package/dist/modules/sales/components/TaxRatesSettings.js +2 -2
- package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +0 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
- package/dist/modules/sales/components/documents/AdjustmentsSection.js +0 -2
- package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js +1 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +0 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/page.js +1 -1
- package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js +2 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/page.js +2 -2
- package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
- package/dist/modules/staff/commands/leave-requests.js +0 -79
- package/dist/modules/staff/commands/leave-requests.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/page.js +0 -5
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/page.js +0 -3
- package/dist/modules/workflows/backend/instances/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +0 -3
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/cli.js +12 -12
- package/dist/modules/workflows/cli.js.map +2 -2
- package/dist/modules/workflows/lib/transition-handler.js +6 -14
- package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
- package/generated/entities/api_key/index.ts +1 -0
- package/generated/entities.ids.generated.ts +1 -5
- package/generated/entity-fields-registry.ts +0 -2
- package/package.json +2 -2
- package/src/modules/api_docs/frontend/docs/api/page.tsx +2 -3
- package/src/modules/api_keys/backend/api-keys/page.tsx +1 -1
- package/src/modules/api_keys/data/entities.ts +4 -0
- package/src/modules/api_keys/migrations/.snapshot-open-mercato.json +9 -0
- package/src/modules/api_keys/migrations/Migration20260125204102.ts +13 -0
- package/src/modules/api_keys/services/apiKeyService.ts +85 -0
- package/src/modules/attachments/components/AttachmentLibrary.tsx +0 -4
- package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +0 -2
- package/src/modules/auth/README.md +1 -1
- package/src/modules/auth/__tests__/cli-setup-acl.test.ts +1 -1
- package/src/modules/auth/api/__tests__/login.test.ts +0 -2
- package/src/modules/auth/api/admin/nav.ts +6 -10
- package/src/modules/auth/api/login.ts +7 -26
- package/src/modules/auth/api/reset/confirm.ts +2 -25
- package/src/modules/auth/api/reset.ts +0 -23
- package/src/modules/auth/api/sidebar/preferences/route.ts +12 -21
- package/src/modules/auth/api/users/route.ts +2 -5
- package/src/modules/auth/backend/roles/[id]/edit/page.tsx +1 -4
- package/src/modules/auth/backend/roles/page.tsx +3 -3
- package/src/modules/auth/backend/users/[id]/edit/page.tsx +3 -22
- package/src/modules/auth/backend/users/create/page.tsx +2 -19
- package/src/modules/auth/backend/users/page.tsx +3 -3
- package/src/modules/auth/cli.ts +11 -38
- package/src/modules/auth/commands/users.ts +2 -73
- package/src/modules/auth/data/validators.ts +2 -6
- package/src/modules/auth/frontend/login.tsx +5 -134
- package/src/modules/auth/frontend/reset/[token]/page.tsx +11 -24
- package/src/modules/auth/i18n/de.json +1 -48
- package/src/modules/auth/i18n/en.json +1 -48
- package/src/modules/auth/i18n/es.json +1 -48
- package/src/modules/auth/i18n/pl.json +1 -48
- package/src/modules/auth/lib/setup-app.ts +9 -58
- package/src/modules/auth/services/authService.ts +4 -27
- package/src/modules/auth/services/rbacService.ts +1 -1
- package/src/modules/business_rules/api/execute/route.ts +1 -8
- package/src/modules/business_rules/backend/rules/page.tsx +0 -4
- package/src/modules/business_rules/backend/sets/page.tsx +0 -3
- package/src/modules/business_rules/cli.ts +1 -2
- package/src/modules/business_rules/i18n/en.json +1 -3
- package/src/modules/business_rules/lib/__tests__/rule-engine.test.ts +0 -51
- package/src/modules/business_rules/lib/rule-engine.ts +3 -57
- package/src/modules/catalog/components/PriceKindSettings.tsx +0 -2
- package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +2 -2
- package/src/modules/catalog/components/products/ProductsDataTable.tsx +0 -2
- package/src/modules/catalog/i18n/en.json +1 -3
- package/src/modules/configs/cli.ts +0 -6
- package/src/modules/configs/components/CachePanel.tsx +4 -4
- package/src/modules/configs/i18n/en.json +2 -12
- package/src/modules/configs/i18n/pl.json +2 -12
- package/src/modules/configs/lib/system-status.ts +1 -48
- package/src/modules/configs/lib/system-status.types.ts +0 -1
- package/src/modules/configs/lib/upgrade-actions.ts +0 -18
- package/src/modules/currencies/backend/currencies/page.tsx +0 -3
- package/src/modules/currencies/backend/exchange-rates/page.tsx +0 -2
- package/src/modules/customers/backend/customers/companies/page.tsx +0 -3
- package/src/modules/customers/backend/customers/deals/page.tsx +0 -3
- package/src/modules/customers/backend/customers/people/page.tsx +0 -3
- package/src/modules/customers/commands/deals.ts +0 -39
- package/src/modules/customers/components/CustomerTodosTable.tsx +0 -1
- package/src/modules/customers/i18n/en.json +1 -5
- package/src/modules/customers/widgets/dashboard/customer-todos/widget.ts +2 -2
- package/src/modules/customers/widgets/dashboard/new-customers/widget.ts +2 -2
- package/src/modules/customers/widgets/dashboard/new-deals/widget.ts +2 -2
- package/src/modules/customers/widgets/dashboard/next-interactions/widget.ts +2 -2
- package/src/modules/dashboards/cli.ts +5 -55
- package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +11 -22
- package/src/modules/dashboards/services/widgetDataService.ts +4 -164
- package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/orders-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/top-customers/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/top-products/widget.ts +2 -2
- package/src/modules/dictionaries/components/DictionaryTable.tsx +0 -2
- package/src/modules/directory/backend/directory/organizations/page.tsx +2 -2
- package/src/modules/directory/backend/directory/tenants/page.tsx +2 -2
- package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +2 -2
- package/src/modules/entities/components/SystemEntitiesTable.tsx +1 -1
- package/src/modules/entities/components/UserEntitiesTable.tsx +2 -2
- package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +4 -3
- package/src/modules/feature_toggles/components/OverridesTable.tsx +1 -1
- package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +2 -2
- package/src/modules/query_index/cli.ts +13 -82
- package/src/modules/query_index/components/QueryIndexesTable.tsx +2 -8
- package/src/modules/resources/backend/resources/resource-types/page.tsx +2 -2
- package/src/modules/resources/backend/resources/resources/page.tsx +2 -2
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +0 -2
- package/src/modules/sales/backend/sales/channels/page.tsx +0 -2
- package/src/modules/sales/commands/documents.ts +0 -65
- package/src/modules/sales/commands/payments.ts +0 -33
- package/src/modules/sales/components/AdjustmentKindSettings.tsx +2 -2
- package/src/modules/sales/components/PaymentMethodsSettings.tsx +2 -2
- package/src/modules/sales/components/ShippingMethodsSettings.tsx +2 -2
- package/src/modules/sales/components/TaxRatesSettings.tsx +2 -2
- package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +0 -2
- package/src/modules/sales/components/documents/AdjustmentsSection.tsx +0 -2
- package/src/modules/sales/components/documents/PaymentsSection.tsx +1 -2
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +0 -2
- package/src/modules/sales/i18n/de.json +0 -20
- package/src/modules/sales/i18n/en.json +1 -25
- package/src/modules/sales/i18n/es.json +0 -20
- package/src/modules/sales/i18n/pl.json +0 -20
- package/src/modules/staff/backend/staff/team-members/page.tsx +1 -1
- package/src/modules/staff/backend/staff/team-roles/page.tsx +2 -2
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +2 -2
- package/src/modules/staff/backend/staff/teams/page.tsx +2 -2
- package/src/modules/staff/commands/leave-requests.ts +0 -94
- package/src/modules/staff/i18n/de.json +0 -4
- package/src/modules/staff/i18n/en.json +1 -9
- package/src/modules/staff/i18n/es.json +0 -4
- package/src/modules/staff/i18n/pl.json +0 -4
- package/src/modules/workflows/backend/definitions/page.tsx +0 -5
- package/src/modules/workflows/backend/instances/page.tsx +1 -4
- package/src/modules/workflows/backend/tasks/page.tsx +1 -4
- package/src/modules/workflows/cli.ts +12 -12
- package/src/modules/workflows/i18n/en.json +1 -3
- package/src/modules/workflows/lib/transition-handler.ts +6 -18
- package/dist/generated/entities/notification/index.js +0 -57
- package/dist/generated/entities/notification/index.js.map +0 -7
- package/dist/modules/auth/api/profile/route.js +0 -157
- package/dist/modules/auth/api/profile/route.js.map +0 -7
- package/dist/modules/auth/backend/auth/profile/page.js +0 -141
- package/dist/modules/auth/backend/auth/profile/page.js.map +0 -7
- package/dist/modules/auth/backend/auth/profile/page.meta.js +0 -13
- package/dist/modules/auth/backend/auth/profile/page.meta.js.map +0 -7
- package/dist/modules/auth/notifications.js +0 -112
- package/dist/modules/auth/notifications.js.map +0 -7
- package/dist/modules/business_rules/notifications.js +0 -28
- package/dist/modules/business_rules/notifications.js.map +0 -7
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +0 -37
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +0 -7
- package/dist/modules/catalog/notifications.js +0 -28
- package/dist/modules/catalog/notifications.js.map +0 -7
- package/dist/modules/catalog/subscribers/low-stock-notification.js +0 -38
- package/dist/modules/catalog/subscribers/low-stock-notification.js.map +0 -7
- package/dist/modules/customers/notifications.js +0 -48
- package/dist/modules/customers/notifications.js.map +0 -7
- package/dist/modules/dashboards/lib/role-widgets.js +0 -58
- package/dist/modules/dashboards/lib/role-widgets.js.map +0 -7
- package/dist/modules/directory/api/get/tenants/lookup.js +0 -70
- package/dist/modules/directory/api/get/tenants/lookup.js.map +0 -7
- package/dist/modules/notifications/acl.js +0 -11
- package/dist/modules/notifications/acl.js.map +0 -7
- package/dist/modules/notifications/api/[id]/action/route.js +0 -74
- package/dist/modules/notifications/api/[id]/action/route.js.map +0 -7
- package/dist/modules/notifications/api/[id]/dismiss/route.js +0 -15
- package/dist/modules/notifications/api/[id]/dismiss/route.js.map +0 -7
- package/dist/modules/notifications/api/[id]/read/route.js +0 -15
- package/dist/modules/notifications/api/[id]/read/route.js.map +0 -7
- package/dist/modules/notifications/api/[id]/restore/route.js +0 -53
- package/dist/modules/notifications/api/[id]/restore/route.js.map +0 -7
- package/dist/modules/notifications/api/batch/route.js +0 -17
- package/dist/modules/notifications/api/batch/route.js.map +0 -7
- package/dist/modules/notifications/api/feature/route.js +0 -17
- package/dist/modules/notifications/api/feature/route.js.map +0 -7
- package/dist/modules/notifications/api/mark-all-read/route.js +0 -35
- package/dist/modules/notifications/api/mark-all-read/route.js.map +0 -7
- package/dist/modules/notifications/api/openapi.js +0 -76
- package/dist/modules/notifications/api/openapi.js.map +0 -7
- package/dist/modules/notifications/api/role/route.js +0 -17
- package/dist/modules/notifications/api/role/route.js.map +0 -7
- package/dist/modules/notifications/api/route.js +0 -85
- package/dist/modules/notifications/api/route.js.map +0 -7
- package/dist/modules/notifications/api/settings/route.js +0 -155
- package/dist/modules/notifications/api/settings/route.js.map +0 -7
- package/dist/modules/notifications/api/unread-count/route.js +0 -38
- package/dist/modules/notifications/api/unread-count/route.js.map +0 -7
- package/dist/modules/notifications/backend/config/notifications/page.js +0 -10
- package/dist/modules/notifications/backend/config/notifications/page.js.map +0 -7
- package/dist/modules/notifications/backend/config/notifications/page.meta.js +0 -24
- package/dist/modules/notifications/backend/config/notifications/page.meta.js.map +0 -7
- package/dist/modules/notifications/cli.js +0 -16
- package/dist/modules/notifications/cli.js.map +0 -7
- package/dist/modules/notifications/data/entities.js +0 -112
- package/dist/modules/notifications/data/entities.js.map +0 -7
- package/dist/modules/notifications/data/validators.js +0 -98
- package/dist/modules/notifications/data/validators.js.map +0 -7
- package/dist/modules/notifications/di.js +0 -13
- package/dist/modules/notifications/di.js.map +0 -7
- package/dist/modules/notifications/emails/NotificationEmail.js +0 -58
- package/dist/modules/notifications/emails/NotificationEmail.js.map +0 -7
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js +0 -44
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js.map +0 -7
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +0 -220
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +0 -7
- package/dist/modules/notifications/index.js +0 -14
- package/dist/modules/notifications/index.js.map +0 -7
- package/dist/modules/notifications/lib/deliveryConfig.js +0 -107
- package/dist/modules/notifications/lib/deliveryConfig.js.map +0 -7
- package/dist/modules/notifications/lib/deliveryStrategies.js +0 -14
- package/dist/modules/notifications/lib/deliveryStrategies.js.map +0 -7
- package/dist/modules/notifications/lib/events.js +0 -12
- package/dist/modules/notifications/lib/events.js.map +0 -7
- package/dist/modules/notifications/lib/notificationBuilder.js +0 -66
- package/dist/modules/notifications/lib/notificationBuilder.js.map +0 -7
- package/dist/modules/notifications/lib/notificationFactory.js +0 -54
- package/dist/modules/notifications/lib/notificationFactory.js.map +0 -7
- package/dist/modules/notifications/lib/notificationMapper.js +0 -34
- package/dist/modules/notifications/lib/notificationMapper.js.map +0 -7
- package/dist/modules/notifications/lib/notificationRecipients.js +0 -35
- package/dist/modules/notifications/lib/notificationRecipients.js.map +0 -7
- package/dist/modules/notifications/lib/notificationService.js +0 -279
- package/dist/modules/notifications/lib/notificationService.js.map +0 -7
- package/dist/modules/notifications/lib/routeHelpers.js +0 -101
- package/dist/modules/notifications/lib/routeHelpers.js.map +0 -7
- package/dist/modules/notifications/lib/safeHref.js +0 -24
- package/dist/modules/notifications/lib/safeHref.js.map +0 -7
- package/dist/modules/notifications/migrations/Migration20260123000001.js +0 -70
- package/dist/modules/notifications/migrations/Migration20260123000001.js.map +0 -7
- package/dist/modules/notifications/migrations/Migration20260126150000.js +0 -37
- package/dist/modules/notifications/migrations/Migration20260126150000.js.map +0 -7
- package/dist/modules/notifications/migrations/Migration20260129082610.js +0 -13
- package/dist/modules/notifications/migrations/Migration20260129082610.js.map +0 -7
- package/dist/modules/notifications/subscribers/deliver-notification.js +0 -165
- package/dist/modules/notifications/subscribers/deliver-notification.js.map +0 -7
- package/dist/modules/notifications/workers/create-notification.worker.js +0 -70
- package/dist/modules/notifications/workers/create-notification.worker.js.map +0 -7
- package/dist/modules/sales/notifications.client.js +0 -51
- package/dist/modules/sales/notifications.client.js.map +0 -7
- package/dist/modules/sales/notifications.js +0 -88
- package/dist/modules/sales/notifications.js.map +0 -7
- package/dist/modules/sales/subscribers/quote-expiring-notification.js +0 -38
- package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +0 -137
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +0 -137
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/index.js +0 -7
- package/dist/modules/sales/widgets/notifications/index.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js +0 -60
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js.map +0 -7
- package/dist/modules/staff/notifications.js +0 -75
- package/dist/modules/staff/notifications.js.map +0 -7
- package/dist/modules/workflows/notifications.js +0 -28
- package/dist/modules/workflows/notifications.js.map +0 -7
- package/dist/modules/workflows/subscribers/task-assigned-notification.js +0 -38
- package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +0 -7
- package/generated/entities/notification/index.ts +0 -27
- package/src/modules/auth/api/profile/route.ts +0 -163
- package/src/modules/auth/backend/auth/profile/page.meta.ts +0 -9
- package/src/modules/auth/backend/auth/profile/page.tsx +0 -174
- package/src/modules/auth/notifications.ts +0 -109
- package/src/modules/business_rules/notifications.ts +0 -25
- package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +0 -50
- package/src/modules/catalog/notifications.ts +0 -25
- package/src/modules/catalog/subscribers/low-stock-notification.ts +0 -52
- package/src/modules/customers/notifications.ts +0 -44
- package/src/modules/dashboards/lib/role-widgets.ts +0 -80
- package/src/modules/directory/api/get/tenants/lookup.ts +0 -75
- package/src/modules/notifications/__tests__/deliver-notification.test.ts +0 -195
- package/src/modules/notifications/__tests__/deliveryStrategies.test.ts +0 -19
- package/src/modules/notifications/__tests__/notificationService.test.ts +0 -208
- package/src/modules/notifications/acl.ts +0 -7
- package/src/modules/notifications/api/[id]/action/route.ts +0 -75
- package/src/modules/notifications/api/[id]/dismiss/route.ts +0 -12
- package/src/modules/notifications/api/[id]/read/route.ts +0 -12
- package/src/modules/notifications/api/[id]/restore/route.ts +0 -53
- package/src/modules/notifications/api/batch/route.ts +0 -14
- package/src/modules/notifications/api/feature/route.ts +0 -14
- package/src/modules/notifications/api/mark-all-read/route.ts +0 -34
- package/src/modules/notifications/api/openapi.ts +0 -76
- package/src/modules/notifications/api/role/route.ts +0 -14
- package/src/modules/notifications/api/route.ts +0 -92
- package/src/modules/notifications/api/settings/route.ts +0 -157
- package/src/modules/notifications/api/unread-count/route.ts +0 -38
- package/src/modules/notifications/backend/config/notifications/page.meta.ts +0 -22
- package/src/modules/notifications/backend/config/notifications/page.tsx +0 -12
- package/src/modules/notifications/cli.ts +0 -18
- package/src/modules/notifications/data/entities.ts +0 -99
- package/src/modules/notifications/data/validators.ts +0 -115
- package/src/modules/notifications/di.ts +0 -11
- package/src/modules/notifications/emails/NotificationEmail.tsx +0 -98
- package/src/modules/notifications/frontend/NotificationInboxPageClient.tsx +0 -42
- package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +0 -233
- package/src/modules/notifications/i18n/de.json +0 -50
- package/src/modules/notifications/i18n/en.json +0 -50
- package/src/modules/notifications/i18n/es.json +0 -50
- package/src/modules/notifications/i18n/pl.json +0 -50
- package/src/modules/notifications/index.ts +0 -12
- package/src/modules/notifications/lib/deliveryConfig.ts +0 -153
- package/src/modules/notifications/lib/deliveryStrategies.ts +0 -50
- package/src/modules/notifications/lib/events.ts +0 -48
- package/src/modules/notifications/lib/notificationBuilder.ts +0 -121
- package/src/modules/notifications/lib/notificationFactory.ts +0 -76
- package/src/modules/notifications/lib/notificationMapper.ts +0 -33
- package/src/modules/notifications/lib/notificationRecipients.ts +0 -83
- package/src/modules/notifications/lib/notificationService.ts +0 -414
- package/src/modules/notifications/lib/routeHelpers.ts +0 -151
- package/src/modules/notifications/lib/safeHref.ts +0 -29
- package/src/modules/notifications/migrations/.snapshot-open-mercato.json +0 -336
- package/src/modules/notifications/migrations/Migration20260123000001.ts +0 -73
- package/src/modules/notifications/migrations/Migration20260126150000.ts +0 -39
- package/src/modules/notifications/migrations/Migration20260129082610.ts +0 -13
- package/src/modules/notifications/subscribers/deliver-notification.ts +0 -204
- package/src/modules/notifications/workers/create-notification.worker.ts +0 -122
- package/src/modules/sales/notifications.client.ts +0 -65
- package/src/modules/sales/notifications.ts +0 -82
- package/src/modules/sales/subscribers/quote-expiring-notification.ts +0 -53
- package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +0 -156
- package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +0 -156
- package/src/modules/sales/widgets/notifications/index.ts +0 -2
- package/src/modules/sales/widgets/notifications/useSalesDocumentTotals.ts +0 -81
- package/src/modules/staff/notifications.ts +0 -71
- package/src/modules/workflows/notifications.ts +0 -25
- package/src/modules/workflows/subscribers/task-assigned-notification.ts +0 -53
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/core",
|
|
3
|
-
"version": "0.4.2-canary-
|
|
3
|
+
"version": "0.4.2-canary-15e78de280",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
}
|
|
208
208
|
},
|
|
209
209
|
"dependencies": {
|
|
210
|
-
"@open-mercato/shared": "0.4.2-canary-
|
|
210
|
+
"@open-mercato/shared": "0.4.2-canary-15e78de280",
|
|
211
211
|
"@xyflow/react": "^12.6.0",
|
|
212
212
|
"date-fns": "^4.1.0",
|
|
213
213
|
"date-fns-tz": "^3.2.0"
|
|
@@ -2,7 +2,6 @@ import ApiDocsExplorer from './Explorer'
|
|
|
2
2
|
import { getModules } from '@open-mercato/shared/lib/i18n/server'
|
|
3
3
|
import { buildOpenApiDocument } from '@open-mercato/shared/lib/openapi'
|
|
4
4
|
import { resolveApiDocsBaseUrl } from '@open-mercato/core/modules/api_docs/lib/resources'
|
|
5
|
-
import { APP_VERSION } from '@open-mercato/shared/lib/version'
|
|
6
5
|
|
|
7
6
|
type ExplorerOperation = {
|
|
8
7
|
id: string
|
|
@@ -55,7 +54,7 @@ export default async function ApiDocsViewerPage() {
|
|
|
55
54
|
const modules = getModules()
|
|
56
55
|
const doc = buildOpenApiDocument(modules, {
|
|
57
56
|
title: 'Open Mercato API',
|
|
58
|
-
version:
|
|
57
|
+
version: '1.0.0',
|
|
59
58
|
description: 'Auto-generated OpenAPI definition for all enabled modules.',
|
|
60
59
|
servers: [{ url: baseUrl, description: 'Default environment' }],
|
|
61
60
|
baseUrlForExamples: baseUrl,
|
|
@@ -68,7 +67,7 @@ export default async function ApiDocsViewerPage() {
|
|
|
68
67
|
return (
|
|
69
68
|
<ApiDocsExplorer
|
|
70
69
|
title={doc.info?.title ?? 'Open Mercato API'}
|
|
71
|
-
version={doc.info?.version ??
|
|
70
|
+
version={doc.info?.version ?? '1.0.0'}
|
|
72
71
|
description={doc.info?.description}
|
|
73
72
|
operations={operations}
|
|
74
73
|
tagOrder={tagOrder}
|
|
@@ -175,7 +175,7 @@ export default function ApiKeysListPage() {
|
|
|
175
175
|
perspective={{ tableId: 'api_keys.list' }}
|
|
176
176
|
rowActions={(row) => (
|
|
177
177
|
<RowActions items={[
|
|
178
|
-
{
|
|
178
|
+
{ label: t('common.delete'), destructive: true, onSelect: () => { void handleDelete(row) } },
|
|
179
179
|
]} />
|
|
180
180
|
)}
|
|
181
181
|
pagination={{ page, pageSize: 20, total, totalPages, onPageChange: setPage }}
|
|
@@ -38,6 +38,10 @@ export class ApiKey {
|
|
|
38
38
|
@Property({ name: 'session_user_id', type: 'uuid', nullable: true })
|
|
39
39
|
sessionUserId?: string | null
|
|
40
40
|
|
|
41
|
+
/** Encrypted API key secret for session keys (recoverable for API calls) */
|
|
42
|
+
@Property({ name: 'session_secret_encrypted', type: 'text', nullable: true })
|
|
43
|
+
sessionSecretEncrypted?: string | null
|
|
44
|
+
|
|
41
45
|
@Property({ name: 'last_used_at', type: Date, nullable: true })
|
|
42
46
|
lastUsedAt?: Date | null
|
|
43
47
|
|
|
@@ -106,6 +106,15 @@
|
|
|
106
106
|
"nullable": true,
|
|
107
107
|
"mappedType": "uuid"
|
|
108
108
|
},
|
|
109
|
+
"session_secret_encrypted": {
|
|
110
|
+
"name": "session_secret_encrypted",
|
|
111
|
+
"type": "text",
|
|
112
|
+
"unsigned": false,
|
|
113
|
+
"autoincrement": false,
|
|
114
|
+
"primary": false,
|
|
115
|
+
"nullable": true,
|
|
116
|
+
"mappedType": "text"
|
|
117
|
+
},
|
|
109
118
|
"last_used_at": {
|
|
110
119
|
"name": "last_used_at",
|
|
111
120
|
"type": "timestamptz",
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Migration } from '@mikro-orm/migrations';
|
|
2
|
+
|
|
3
|
+
export class Migration20260125204102 extends Migration {
|
|
4
|
+
|
|
5
|
+
override async up(): Promise<void> {
|
|
6
|
+
this.addSql(`alter table "api_keys" add column "session_secret_encrypted" text null;`);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
override async down(): Promise<void> {
|
|
10
|
+
this.addSql(`alter table "api_keys" drop column "session_secret_encrypted";`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
}
|
|
@@ -4,9 +4,60 @@ import { hash, compare } from 'bcryptjs'
|
|
|
4
4
|
import type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'
|
|
5
5
|
import { Role } from '@open-mercato/core/modules/auth/data/entities'
|
|
6
6
|
import { ApiKey } from '../data/entities'
|
|
7
|
+
import { createKmsService } from '@open-mercato/shared/lib/encryption/kms'
|
|
8
|
+
import { encryptWithAesGcm, decryptWithAesGcm } from '@open-mercato/shared/lib/encryption/aes'
|
|
7
9
|
|
|
8
10
|
const BCRYPT_COST = 10
|
|
9
11
|
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Session Secret Encryption Helpers
|
|
14
|
+
// =============================================================================
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Encrypt an API key secret for storage.
|
|
18
|
+
* Uses tenant-specific DEK if available, otherwise returns null.
|
|
19
|
+
*/
|
|
20
|
+
async function encryptSessionSecret(
|
|
21
|
+
secret: string,
|
|
22
|
+
tenantId: string | null
|
|
23
|
+
): Promise<string | null> {
|
|
24
|
+
if (!tenantId) return null
|
|
25
|
+
|
|
26
|
+
const kms = createKmsService()
|
|
27
|
+
if (!kms.isHealthy()) return null
|
|
28
|
+
|
|
29
|
+
const dek = await kms.getTenantDek(tenantId)
|
|
30
|
+
if (!dek) {
|
|
31
|
+
// Try to create a DEK if one doesn't exist
|
|
32
|
+
const created = await kms.createTenantDek(tenantId)
|
|
33
|
+
if (!created) return null
|
|
34
|
+
const encrypted = encryptWithAesGcm(secret, created.key)
|
|
35
|
+
return encrypted.value
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const encrypted = encryptWithAesGcm(secret, dek.key)
|
|
39
|
+
return encrypted.value
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Decrypt an API key secret from storage.
|
|
44
|
+
* Returns null if decryption fails or no DEK available.
|
|
45
|
+
*/
|
|
46
|
+
async function decryptSessionSecret(
|
|
47
|
+
encrypted: string,
|
|
48
|
+
tenantId: string | null
|
|
49
|
+
): Promise<string | null> {
|
|
50
|
+
if (!tenantId || !encrypted) return null
|
|
51
|
+
|
|
52
|
+
const kms = createKmsService()
|
|
53
|
+
if (!kms.isHealthy()) return null
|
|
54
|
+
|
|
55
|
+
const dek = await kms.getTenantDek(tenantId)
|
|
56
|
+
if (!dek) return null
|
|
57
|
+
|
|
58
|
+
return decryptWithAesGcm(encrypted, dek.key)
|
|
59
|
+
}
|
|
60
|
+
|
|
10
61
|
export type CreateApiKeyInput = {
|
|
11
62
|
name: string
|
|
12
63
|
description?: string | null
|
|
@@ -117,6 +168,7 @@ export function generateSessionToken(): string {
|
|
|
117
168
|
/**
|
|
118
169
|
* Create an ephemeral API key scoped to a chat session.
|
|
119
170
|
* The key inherits the user's roles and expires after ttlMinutes (default 30).
|
|
171
|
+
* The API key secret is encrypted and stored so it can be recovered for API calls.
|
|
120
172
|
*/
|
|
121
173
|
export async function createSessionApiKey(
|
|
122
174
|
em: EntityManager,
|
|
@@ -127,6 +179,9 @@ export async function createSessionApiKey(
|
|
|
127
179
|
const expiresAt = new Date(Date.now() + ttl * 60 * 1000)
|
|
128
180
|
const keyHash = await hashApiKey(secret)
|
|
129
181
|
|
|
182
|
+
// Encrypt the secret for later retrieval (used by MCP server for API calls)
|
|
183
|
+
const encryptedSecret = await encryptSessionSecret(secret, input.tenantId ?? null)
|
|
184
|
+
|
|
130
185
|
const record = em.create(ApiKey, {
|
|
131
186
|
name: `__session_${input.sessionToken}__`,
|
|
132
187
|
description: 'Ephemeral session API key for AI chat',
|
|
@@ -138,6 +193,7 @@ export async function createSessionApiKey(
|
|
|
138
193
|
createdBy: input.userId,
|
|
139
194
|
sessionToken: input.sessionToken,
|
|
140
195
|
sessionUserId: input.userId,
|
|
196
|
+
sessionSecretEncrypted: encryptedSecret,
|
|
141
197
|
expiresAt,
|
|
142
198
|
createdAt: new Date(),
|
|
143
199
|
})
|
|
@@ -172,6 +228,35 @@ export async function findApiKeyBySessionToken(
|
|
|
172
228
|
return record
|
|
173
229
|
}
|
|
174
230
|
|
|
231
|
+
/**
|
|
232
|
+
* Find a session API key with its decrypted secret.
|
|
233
|
+
* Returns null if not found, expired, deleted, or decryption fails.
|
|
234
|
+
* This is used by the MCP server to recover the API key secret for making
|
|
235
|
+
* authenticated API calls on behalf of the user.
|
|
236
|
+
*/
|
|
237
|
+
export async function findSessionApiKeyWithSecret(
|
|
238
|
+
em: EntityManager,
|
|
239
|
+
sessionToken: string
|
|
240
|
+
): Promise<{ key: ApiKey; secret: string } | null> {
|
|
241
|
+
const record = await findApiKeyBySessionToken(em, sessionToken)
|
|
242
|
+
if (!record) return null
|
|
243
|
+
|
|
244
|
+
// If no encrypted secret stored, cannot recover
|
|
245
|
+
if (!record.sessionSecretEncrypted) {
|
|
246
|
+
console.warn('[ApiKeyService] Session key has no encrypted secret:', sessionToken.slice(0, 12))
|
|
247
|
+
return null
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Decrypt the secret
|
|
251
|
+
const secret = await decryptSessionSecret(record.sessionSecretEncrypted, record.tenantId ?? null)
|
|
252
|
+
if (!secret) {
|
|
253
|
+
console.warn('[ApiKeyService] Failed to decrypt session secret:', sessionToken.slice(0, 12))
|
|
254
|
+
return null
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return { key: record, secret }
|
|
258
|
+
}
|
|
259
|
+
|
|
175
260
|
/**
|
|
176
261
|
* Delete an ephemeral API key by its session token.
|
|
177
262
|
*/
|
|
@@ -1056,7 +1056,6 @@ export function AttachmentLibrary() {
|
|
|
1056
1056
|
<RowActions
|
|
1057
1057
|
items={[
|
|
1058
1058
|
{
|
|
1059
|
-
id: 'open',
|
|
1060
1059
|
label: t('attachments.library.actions.open', 'Open'),
|
|
1061
1060
|
onSelect: () => {
|
|
1062
1061
|
if (!row.url) return
|
|
@@ -1064,12 +1063,10 @@ export function AttachmentLibrary() {
|
|
|
1064
1063
|
},
|
|
1065
1064
|
},
|
|
1066
1065
|
{
|
|
1067
|
-
id: 'edit',
|
|
1068
1066
|
label: t('attachments.library.actions.edit', 'Edit metadata'),
|
|
1069
1067
|
onSelect: () => openMetadataDialog(row),
|
|
1070
1068
|
},
|
|
1071
1069
|
{
|
|
1072
|
-
id: 'copy-url',
|
|
1073
1070
|
label: t('attachments.library.actions.copyUrl', 'Copy URL'),
|
|
1074
1071
|
onSelect: () => {
|
|
1075
1072
|
if (!row.url) {
|
|
@@ -1094,7 +1091,6 @@ export function AttachmentLibrary() {
|
|
|
1094
1091
|
},
|
|
1095
1092
|
},
|
|
1096
1093
|
{
|
|
1097
|
-
id: 'delete',
|
|
1098
1094
|
label: t('attachments.library.actions.delete', 'Delete'),
|
|
1099
1095
|
destructive: true,
|
|
1100
1096
|
onSelect: () => openDeleteDialog(row),
|
|
@@ -305,12 +305,10 @@ export function AttachmentPartitionSettings() {
|
|
|
305
305
|
<RowActions
|
|
306
306
|
items={[
|
|
307
307
|
{
|
|
308
|
-
id: 'edit',
|
|
309
308
|
label: t('attachments.partitions.actions.edit', 'Edit'),
|
|
310
309
|
onSelect: () => openDialog({ mode: 'edit', entry }),
|
|
311
310
|
},
|
|
312
311
|
{
|
|
313
|
-
id: 'delete',
|
|
314
312
|
label: t('attachments.partitions.actions.delete', 'Delete'),
|
|
315
313
|
destructive: true,
|
|
316
314
|
onSelect: () => { void handleDelete(entry) },
|
|
@@ -8,7 +8,7 @@ Features:
|
|
|
8
8
|
- `mercato auth add-user --email <e> --password <p> --organizationId <id> [--roles r1,r2]`
|
|
9
9
|
- `mercato auth seed-roles`
|
|
10
10
|
- `mercato auth add-org --name <org>`
|
|
11
|
-
- `mercato auth setup --orgName <org> --email <e> --password <p> [--roles superadmin,admin]
|
|
11
|
+
- `mercato auth setup --orgName <org> --email <e> --password <p> [--roles superadmin,admin]`
|
|
12
12
|
|
|
13
13
|
DB entities used (defined in root schema):
|
|
14
14
|
- `users` with: `email`, `password_hash`, `is_confirmed`, `last_login_at`, `organization_id`, timestamps.
|
|
@@ -46,7 +46,7 @@ describe('auth CLI setup seeds ACLs', () => {
|
|
|
46
46
|
findOneOrFail.mockImplementation(async (_: any, where: any) => ({ id: 'role-' + where.name, name: where.name }))
|
|
47
47
|
|
|
48
48
|
// Act
|
|
49
|
-
await setup.run(['--orgName', 'Acme', '--email', 'root@acme.com', '--password', 'secret'
|
|
49
|
+
await setup.run(['--orgName', 'Acme', '--email', 'root@acme.com', '--password', 'secret'])
|
|
50
50
|
|
|
51
51
|
// Assert: persistAndFlush was called to create three RoleAcl rows with expected flags/features
|
|
52
52
|
const calls = persistAndFlush.mock.calls.map((c) => c[0])
|
|
@@ -15,8 +15,6 @@ jest.mock('@open-mercato/shared/lib/di/container', () => ({
|
|
|
15
15
|
createRequestContainer: async () => ({
|
|
16
16
|
resolve: (_: string) => ({
|
|
17
17
|
findUserByEmail: async (email: string) => ({ id: 1, email, passwordHash: 'hash', tenantId: tenantId, organizationId: orgId }),
|
|
18
|
-
findUsersByEmail: async (email: string) => ([{ id: 1, email, passwordHash: 'hash', tenantId: tenantId, organizationId: orgId }]),
|
|
19
|
-
findUserByEmailAndTenant: async (email: string) => ({ id: 1, email, passwordHash: 'hash', tenantId: tenantId, organizationId: orgId }),
|
|
20
18
|
verifyPassword: async () => true,
|
|
21
19
|
getUserRoles: async (_user: any, _tenant: string | null | undefined) => ['admin'],
|
|
22
20
|
updateLastLoginAt: async () => undefined,
|
|
@@ -297,16 +297,12 @@ export async function GET(req: Request) {
|
|
|
297
297
|
const groupsWithRole = rolePreference ? applySidebarPreference(groups, rolePreference) : groups
|
|
298
298
|
const baseForUser = adoptSidebarDefaults(groupsWithRole)
|
|
299
299
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
organizationId: auth.orgId ?? null,
|
|
307
|
-
locale,
|
|
308
|
-
})
|
|
309
|
-
: null
|
|
300
|
+
const preference = await loadSidebarPreference(em, {
|
|
301
|
+
userId: auth.sub,
|
|
302
|
+
tenantId: auth.tenantId ?? null,
|
|
303
|
+
organizationId: auth.orgId ?? null,
|
|
304
|
+
locale,
|
|
305
|
+
})
|
|
310
306
|
|
|
311
307
|
const withPreference = applySidebarPreference(baseForUser, preference)
|
|
312
308
|
|
|
@@ -17,33 +17,15 @@ export async function POST(req: Request) {
|
|
|
17
17
|
const email = String(form.get('email') ?? '')
|
|
18
18
|
const password = String(form.get('password') ?? '')
|
|
19
19
|
const remember = parseBooleanToken(form.get('remember')?.toString()) === true
|
|
20
|
-
const tenantIdRaw = String(form.get('tenantId') ?? form.get('tenant') ?? '').trim()
|
|
21
20
|
const requireRoleRaw = (String(form.get('requireRole') ?? form.get('role') ?? '')).trim()
|
|
22
21
|
const requiredRoles = requireRoleRaw ? requireRoleRaw.split(',').map((s) => s.trim()).filter(Boolean) : []
|
|
23
|
-
const parsed = userLoginSchema.pick({ email: true, password: true
|
|
24
|
-
email,
|
|
25
|
-
password,
|
|
26
|
-
tenantId: tenantIdRaw || undefined,
|
|
27
|
-
})
|
|
22
|
+
const parsed = userLoginSchema.pick({ email: true, password: true }).safeParse({ email, password })
|
|
28
23
|
if (!parsed.success) {
|
|
29
24
|
return NextResponse.json({ ok: false, error: translate('auth.login.errors.invalidCredentials', 'Invalid credentials') }, { status: 400 })
|
|
30
25
|
}
|
|
31
26
|
const container = await createRequestContainer()
|
|
32
27
|
const auth = (container.resolve('authService') as AuthService)
|
|
33
|
-
const
|
|
34
|
-
let user = null
|
|
35
|
-
if (tenantId) {
|
|
36
|
-
user = await auth.findUserByEmailAndTenant(parsed.data.email, tenantId)
|
|
37
|
-
} else {
|
|
38
|
-
const users = await auth.findUsersByEmail(parsed.data.email)
|
|
39
|
-
if (users.length > 1) {
|
|
40
|
-
return NextResponse.json({
|
|
41
|
-
ok: false,
|
|
42
|
-
error: translate('auth.login.errors.tenantRequired', 'Use the login link provided with your tenant activation to continue.'),
|
|
43
|
-
}, { status: 400 })
|
|
44
|
-
}
|
|
45
|
-
user = users[0] ?? null
|
|
46
|
-
}
|
|
28
|
+
const user = await auth.findUserByEmail(parsed.data.email)
|
|
47
29
|
if (!user || !user.passwordHash) {
|
|
48
30
|
return NextResponse.json({ ok: false, error: translate('auth.login.errors.invalidCredentials', 'Invalid email or password') }, { status: 401 })
|
|
49
31
|
}
|
|
@@ -53,27 +35,26 @@ export async function POST(req: Request) {
|
|
|
53
35
|
}
|
|
54
36
|
// Optional role requirement
|
|
55
37
|
if (requiredRoles.length) {
|
|
56
|
-
const userRoleNames = await auth.getUserRoles(user,
|
|
38
|
+
const userRoleNames = await auth.getUserRoles(user, user.tenantId ? String(user.tenantId) : null)
|
|
57
39
|
const authorized = requiredRoles.some(r => userRoleNames.includes(r))
|
|
58
40
|
if (!authorized) {
|
|
59
41
|
return NextResponse.json({ ok: false, error: translate('auth.login.errors.permissionDenied', 'Not authorized for this area') }, { status: 403 })
|
|
60
42
|
}
|
|
61
43
|
}
|
|
62
44
|
await auth.updateLastLoginAt(user)
|
|
63
|
-
const
|
|
64
|
-
const userRoleNames = await auth.getUserRoles(user, resolvedTenantId)
|
|
45
|
+
const userRoleNames = await auth.getUserRoles(user, user.tenantId ? String(user.tenantId) : null)
|
|
65
46
|
try {
|
|
66
47
|
const eventBus = (container.resolve('eventBus') as EventBus)
|
|
67
48
|
void eventBus.emitEvent('query_index.coverage.warmup', {
|
|
68
|
-
tenantId:
|
|
49
|
+
tenantId: user.tenantId ? String(user.tenantId) : null,
|
|
69
50
|
}).catch(() => undefined)
|
|
70
51
|
} catch {
|
|
71
52
|
// optional warmup
|
|
72
53
|
}
|
|
73
54
|
const token = signJwt({
|
|
74
55
|
sub: String(user.id),
|
|
75
|
-
tenantId:
|
|
76
|
-
orgId: user.organizationId ? String(user.organizationId) : null,
|
|
56
|
+
tenantId: user.tenantId ? String(user.tenantId) : null,
|
|
57
|
+
orgId: user.organizationId ? String(user.organizationId) : null,
|
|
77
58
|
email: user.email,
|
|
78
59
|
roles: userRoleNames
|
|
79
60
|
})
|
|
@@ -3,9 +3,6 @@ import { NextResponse } from 'next/server'
|
|
|
3
3
|
import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
4
4
|
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
5
5
|
import { AuthService } from '@open-mercato/core/modules/auth/services/authService'
|
|
6
|
-
import { buildNotificationFromType } from '@open-mercato/core/modules/notifications/lib/notificationBuilder'
|
|
7
|
-
import { resolveNotificationService } from '@open-mercato/core/modules/notifications/lib/notificationService'
|
|
8
|
-
import notificationTypes from '@open-mercato/core/modules/auth/notifications'
|
|
9
6
|
import { z } from 'zod'
|
|
10
7
|
|
|
11
8
|
// validation via confirmPasswordResetSchema
|
|
@@ -18,28 +15,8 @@ export async function POST(req: Request) {
|
|
|
18
15
|
if (!parsed.success) return NextResponse.json({ ok: false, error: 'Invalid request' }, { status: 400 })
|
|
19
16
|
const c = await createRequestContainer()
|
|
20
17
|
const auth = c.resolve<AuthService>('authService')
|
|
21
|
-
const
|
|
22
|
-
if (!
|
|
23
|
-
try {
|
|
24
|
-
const tenantId = user.tenantId ? String(user.tenantId) : null
|
|
25
|
-
if (tenantId) {
|
|
26
|
-
const notificationService = resolveNotificationService(c)
|
|
27
|
-
const typeDef = notificationTypes.find((type) => type.type === 'auth.password_reset.completed')
|
|
28
|
-
if (typeDef) {
|
|
29
|
-
const notificationInput = buildNotificationFromType(typeDef, {
|
|
30
|
-
recipientUserId: String(user.id),
|
|
31
|
-
sourceEntityType: 'auth:user',
|
|
32
|
-
sourceEntityId: String(user.id),
|
|
33
|
-
})
|
|
34
|
-
await notificationService.create(notificationInput, {
|
|
35
|
-
tenantId,
|
|
36
|
-
organizationId: user.organizationId ? String(user.organizationId) : null,
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
} catch (err) {
|
|
41
|
-
console.error('[auth.reset.confirm] Failed to create notification:', err)
|
|
42
|
-
}
|
|
18
|
+
const ok = await auth.confirmPasswordReset(parsed.data.token, parsed.data.password)
|
|
19
|
+
if (!ok) return NextResponse.json({ ok: false, error: 'Invalid or expired token' }, { status: 400 })
|
|
43
20
|
return NextResponse.json({ ok: true, redirect: '/login' })
|
|
44
21
|
}
|
|
45
22
|
|
|
@@ -6,9 +6,6 @@ import { AuthService } from '@open-mercato/core/modules/auth/services/authServic
|
|
|
6
6
|
import { sendEmail } from '@open-mercato/shared/lib/email/send'
|
|
7
7
|
import ResetPasswordEmail from '@open-mercato/core/modules/auth/emails/ResetPasswordEmail'
|
|
8
8
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
9
|
-
import { buildNotificationFromType } from '@open-mercato/core/modules/notifications/lib/notificationBuilder'
|
|
10
|
-
import { resolveNotificationService } from '@open-mercato/core/modules/notifications/lib/notificationService'
|
|
11
|
-
import notificationTypes from '@open-mercato/core/modules/auth/notifications'
|
|
12
9
|
import { z } from 'zod'
|
|
13
10
|
|
|
14
11
|
// validation via requestPasswordResetSchema
|
|
@@ -38,26 +35,6 @@ export async function POST(req: Request) {
|
|
|
38
35
|
}
|
|
39
36
|
|
|
40
37
|
await sendEmail({ to: user.email, subject, react: ResetPasswordEmail({ resetUrl, copy }) })
|
|
41
|
-
try {
|
|
42
|
-
const tenantId = user.tenantId ? String(user.tenantId) : null
|
|
43
|
-
if (tenantId) {
|
|
44
|
-
const notificationService = resolveNotificationService(c)
|
|
45
|
-
const typeDef = notificationTypes.find((type) => type.type === 'auth.password_reset.requested')
|
|
46
|
-
if (typeDef) {
|
|
47
|
-
const notificationInput = buildNotificationFromType(typeDef, {
|
|
48
|
-
recipientUserId: String(user.id),
|
|
49
|
-
sourceEntityType: 'auth:user',
|
|
50
|
-
sourceEntityId: String(user.id),
|
|
51
|
-
})
|
|
52
|
-
await notificationService.create(notificationInput, {
|
|
53
|
-
tenantId,
|
|
54
|
-
organizationId: user.organizationId ? String(user.organizationId) : null,
|
|
55
|
-
})
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
} catch (err) {
|
|
59
|
-
console.error('[auth.reset] Failed to create notification:', err)
|
|
60
|
-
}
|
|
61
38
|
return NextResponse.json({ ok: true })
|
|
62
39
|
}
|
|
63
40
|
|
|
@@ -64,16 +64,12 @@ export async function GET(req: Request) {
|
|
|
64
64
|
{ tenantId: auth.tenantId ?? null, organizationId: auth.orgId ?? null },
|
|
65
65
|
) ?? false
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
organizationId: auth.orgId ?? null,
|
|
74
|
-
locale,
|
|
75
|
-
})
|
|
76
|
-
: null
|
|
67
|
+
const settings = await loadSidebarPreference(em, {
|
|
68
|
+
userId: auth.sub,
|
|
69
|
+
tenantId: auth.tenantId ?? null,
|
|
70
|
+
organizationId: auth.orgId ?? null,
|
|
71
|
+
locale,
|
|
72
|
+
})
|
|
77
73
|
|
|
78
74
|
let rolesPayload: Array<{ id: string; name: string; hasPreference: boolean }> = []
|
|
79
75
|
if (canApplyToRoles) {
|
|
@@ -96,11 +92,11 @@ export async function GET(req: Request) {
|
|
|
96
92
|
return NextResponse.json({
|
|
97
93
|
locale,
|
|
98
94
|
settings: {
|
|
99
|
-
version: settings
|
|
100
|
-
groupOrder: settings
|
|
101
|
-
groupLabels: settings
|
|
102
|
-
itemLabels: settings
|
|
103
|
-
hiddenItems: settings
|
|
95
|
+
version: settings.version ?? SIDEBAR_PREFERENCES_VERSION,
|
|
96
|
+
groupOrder: settings.groupOrder ?? [],
|
|
97
|
+
groupLabels: settings.groupLabels ?? {},
|
|
98
|
+
itemLabels: settings.itemLabels ?? {},
|
|
99
|
+
hiddenItems: settings.hiddenItems ?? [],
|
|
104
100
|
},
|
|
105
101
|
canApplyToRoles,
|
|
106
102
|
roles: rolesPayload,
|
|
@@ -110,11 +106,6 @@ export async function GET(req: Request) {
|
|
|
110
106
|
export async function PUT(req: Request) {
|
|
111
107
|
const auth = await getAuthFromRequest(req)
|
|
112
108
|
if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
113
|
-
// For API key auth, use userId (the actual user) if available
|
|
114
|
-
const effectiveUserId = auth.isApiKey ? auth.userId : auth.sub
|
|
115
|
-
if (!effectiveUserId) {
|
|
116
|
-
return NextResponse.json({ error: 'Cannot save preferences: no user associated with this API key' }, { status: 403 })
|
|
117
|
-
}
|
|
118
109
|
|
|
119
110
|
let parsedBody: unknown
|
|
120
111
|
try {
|
|
@@ -191,7 +182,7 @@ export async function PUT(req: Request) {
|
|
|
191
182
|
}
|
|
192
183
|
|
|
193
184
|
const settings = await saveSidebarPreference(em, {
|
|
194
|
-
userId:
|
|
185
|
+
userId: auth.sub,
|
|
195
186
|
tenantId: auth.tenantId ?? null,
|
|
196
187
|
organizationId: auth.orgId ?? null,
|
|
197
188
|
locale,
|
|
@@ -15,7 +15,6 @@ import type { EntityManager } from '@mikro-orm/postgresql'
|
|
|
15
15
|
import { userCrudEvents, userCrudIndexer } from '@open-mercato/core/modules/auth/commands/users'
|
|
16
16
|
import { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
17
17
|
import { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'
|
|
18
|
-
import { buildPasswordSchema } from '@open-mercato/shared/lib/auth/passwordPolicy'
|
|
19
18
|
|
|
20
19
|
const querySchema = z.object({
|
|
21
20
|
id: z.string().uuid().optional(),
|
|
@@ -28,11 +27,9 @@ const querySchema = z.object({
|
|
|
28
27
|
|
|
29
28
|
const rawBodySchema = z.object({}).passthrough()
|
|
30
29
|
|
|
31
|
-
const passwordSchema = buildPasswordSchema()
|
|
32
|
-
|
|
33
30
|
const userCreateSchema = z.object({
|
|
34
31
|
email: z.string().email(),
|
|
35
|
-
password:
|
|
32
|
+
password: z.string().min(6),
|
|
36
33
|
organizationId: z.string().uuid(),
|
|
37
34
|
roles: z.array(z.string()).optional(),
|
|
38
35
|
})
|
|
@@ -40,7 +37,7 @@ const userCreateSchema = z.object({
|
|
|
40
37
|
const userUpdateSchema = z.object({
|
|
41
38
|
id: z.string().uuid(),
|
|
42
39
|
email: z.string().email().optional(),
|
|
43
|
-
password:
|
|
40
|
+
password: z.string().min(6).optional(),
|
|
44
41
|
organizationId: z.string().uuid().optional(),
|
|
45
42
|
roles: z.array(z.string()).optional(),
|
|
46
43
|
})
|
|
@@ -6,7 +6,7 @@ import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
|
|
|
6
6
|
import { deleteCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'
|
|
7
7
|
import { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'
|
|
8
8
|
import { AclEditor, type AclData } from '@open-mercato/core/modules/auth/components/AclEditor'
|
|
9
|
-
import { WidgetVisibilityEditor
|
|
9
|
+
import { WidgetVisibilityEditor } from '@open-mercato/core/modules/dashboards/components/WidgetVisibilityEditor'
|
|
10
10
|
import { E } from '#generated/entities.ids.generated'
|
|
11
11
|
import { TenantSelect } from '@open-mercato/core/modules/directory/components/TenantSelect'
|
|
12
12
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
@@ -37,7 +37,6 @@ export default function EditRolePage({ params }: { params?: { id?: string } }) {
|
|
|
37
37
|
const [aclData, setAclData] = React.useState<AclData>({ isSuperAdmin: false, features: [], organizations: null })
|
|
38
38
|
const [actorIsSuperAdmin, setActorIsSuperAdmin] = React.useState(false)
|
|
39
39
|
const [selectedTenantId, setSelectedTenantId] = React.useState<string | null>(null)
|
|
40
|
-
const widgetEditorRef = React.useRef<WidgetVisibilityEditorHandle | null>(null)
|
|
41
40
|
|
|
42
41
|
React.useEffect(() => {
|
|
43
42
|
if (!id) return
|
|
@@ -154,7 +153,6 @@ export default function EditRolePage({ params }: { params?: { id?: string } }) {
|
|
|
154
153
|
kind="role"
|
|
155
154
|
targetId={String(id)}
|
|
156
155
|
tenantId={selectedTenantId ?? (initial?.tenantId ?? null)}
|
|
157
|
-
ref={widgetEditorRef}
|
|
158
156
|
/>
|
|
159
157
|
)
|
|
160
158
|
: null),
|
|
@@ -193,7 +191,6 @@ export default function EditRolePage({ params }: { params?: { id?: string } }) {
|
|
|
193
191
|
await updateCrud('auth/roles/acl', { roleId: id, tenantId: effectiveTenantId, ...aclData }, {
|
|
194
192
|
errorMessage: t('auth.roles.form.errors.aclUpdate', 'Failed to update role access control'),
|
|
195
193
|
})
|
|
196
|
-
await widgetEditorRef.current?.save()
|
|
197
194
|
try { window.dispatchEvent(new Event('om:refresh-sidebar')) } catch {}
|
|
198
195
|
}}
|
|
199
196
|
onDelete={async () => {
|
|
@@ -117,9 +117,9 @@ export default function RolesListPage() {
|
|
|
117
117
|
onSearchChange={(v) => { setSearch(v); setPage(1) }}
|
|
118
118
|
rowActions={(row) => (
|
|
119
119
|
<RowActions items={[
|
|
120
|
-
{
|
|
121
|
-
{
|
|
122
|
-
{
|
|
120
|
+
{ label: t('common.edit', 'Edit'), href: `/backend/roles/${row.id}/edit` },
|
|
121
|
+
{ label: t('auth.roles.list.actions.showUsers', 'Show users'), href: `/backend/users?roleId=${encodeURIComponent(row.id)}` },
|
|
122
|
+
{ label: t('common.delete', 'Delete'), destructive: true, onSelect: () => { void handleDelete(row) } },
|
|
123
123
|
]} />
|
|
124
124
|
)}
|
|
125
125
|
sortable
|