@open-mercato/core 0.6.6-develop.6551.1.1511bfa890 → 0.6.6
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/.turbo/turbo-build.log +2 -2
- package/dist/generated/entities.ids.generated.js +0 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +0 -12
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/api_keys/api/keys/route.js +13 -30
- package/dist/modules/api_keys/api/keys/route.js.map +2 -2
- package/dist/modules/api_keys/cli.js +1 -2
- package/dist/modules/api_keys/cli.js.map +2 -2
- package/dist/modules/attachments/api/file/[id]/route.js +7 -9
- package/dist/modules/attachments/api/file/[id]/route.js.map +2 -2
- package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js +7 -9
- package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js.map +2 -2
- package/dist/modules/attachments/api/route.js +17 -21
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentContentPreview.js +35 -6
- package/dist/modules/attachments/components/AttachmentContentPreview.js.map +2 -2
- package/dist/modules/audit_logs/backend/audit-logs/page.js +24 -14
- package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +2 -6
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/cli.js +2 -3
- package/dist/modules/auth/cli.js.map +2 -2
- package/dist/modules/configs/lib/upgrade-actions.js +0 -22
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/roles/[id]/acl.js +0 -1
- package/dist/modules/customer_accounts/api/admin/roles/[id]/acl.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/roles/[id].js +3 -17
- package/dist/modules/customer_accounts/api/admin/roles/[id].js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js +1 -6
- package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users-invite.js +1 -6
- package/dist/modules/customer_accounts/api/portal/users-invite.js.map +2 -2
- package/dist/modules/customer_accounts/services/customerInvitationService.js +0 -1
- package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
- package/dist/modules/customer_accounts/services/customerRbacService.js +1 -6
- package/dist/modules/customer_accounts/services/customerRbacService.js.map +2 -2
- package/dist/modules/customer_accounts/widgets/injection-table.js +2 -0
- package/dist/modules/customer_accounts/widgets/injection-table.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +1 -7
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js +43 -37
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/DealDetailTabs.js +35 -23
- package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/DetailTabsLayout.js +21 -6
- package/dist/modules/customers/components/detail/DetailTabsLayout.js.map +2 -2
- package/dist/modules/customers/components/detail/MobilePersonDetail.js +32 -26
- package/dist/modules/customers/components/detail/MobilePersonDetail.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonDetailTabs.js +39 -29
- package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
- package/dist/modules/dashboards/api/roles/widgets/route.js +3 -22
- package/dist/modules/dashboards/api/roles/widgets/route.js.map +2 -2
- package/dist/modules/dashboards/api/users/widgets/route.js +3 -22
- package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
- package/dist/modules/dashboards/cli.js +3 -4
- package/dist/modules/dashboards/cli.js.map +2 -2
- package/dist/modules/dashboards/lib/widgetAssignmentScope.js +1 -9
- package/dist/modules/dashboards/lib/widgetAssignmentScope.js.map +2 -2
- package/dist/modules/dictionaries/commands/entries.js +14 -7
- package/dist/modules/dictionaries/commands/entries.js.map +2 -2
- package/dist/modules/dictionaries/commands/entry-operations.js +16 -7
- package/dist/modules/dictionaries/commands/entry-operations.js.map +2 -2
- package/dist/modules/dictionaries/commands/factory.js +3 -9
- package/dist/modules/dictionaries/commands/factory.js.map +2 -2
- package/dist/modules/dictionaries/fields/dictionary.js +41 -56
- package/dist/modules/dictionaries/fields/dictionary.js.map +2 -2
- package/dist/modules/directory/utils/organizationScope.js +3 -10
- package/dist/modules/directory/utils/organizationScope.js.map +2 -2
- package/dist/modules/entities/api/records.js +4 -5
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/entities/backend/entities/system/[entityId]/page.meta.js +0 -1
- package/dist/modules/entities/backend/entities/system/[entityId]/page.meta.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/page.js +49 -49
- package/dist/modules/entities/backend/entities/user/[entityId]/page.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/page.meta.js +0 -1
- package/dist/modules/entities/backend/entities/user/[entityId]/page.meta.js.map +2 -2
- package/dist/modules/entities/cli.js +1 -2
- package/dist/modules/entities/cli.js.map +2 -2
- package/dist/modules/feature_toggles/api/check/boolean/route.js +14 -0
- package/dist/modules/feature_toggles/api/check/boolean/route.js.map +2 -2
- package/dist/modules/feature_toggles/defaults.json +0 -8
- package/dist/modules/integrations/backend/integrations/[id]/page.js +80 -9
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/payment_gateways/data/entities.js +0 -45
- package/dist/modules/payment_gateways/data/entities.js.map +2 -2
- package/dist/modules/payment_gateways/lib/gateway-service.js +38 -173
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +3 -3
- package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js +14 -16
- package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js.map +2 -2
- package/dist/modules/planner/components/AvailabilityRulesEditor.js +30 -18
- package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
- package/dist/modules/query_index/api/status.js +8 -2
- package/dist/modules/query_index/api/status.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js +24 -24
- package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/create/page.js +0 -6
- package/dist/modules/sales/backend/sales/channels/create/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/create/page.meta.js +0 -2
- package/dist/modules/sales/backend/sales/channels/create/page.meta.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +0 -6
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.meta.js +0 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.meta.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +0 -6
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.meta.js +0 -2
- package/dist/modules/sales/backend/sales/channels/page.meta.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +4 -6
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +0 -44
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/returns.js +27 -2
- package/dist/modules/sales/commands/returns.js.map +2 -2
- package/dist/modules/sales/components/documents/AddressesSection.js +2 -6
- package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +0 -1
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +0 -9
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentForm.js +3 -51
- package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +8 -10
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentDialog.js +38 -59
- package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
- package/dist/modules/sales/lib/shipments/snapshots.js +1 -27
- package/dist/modules/sales/lib/shipments/snapshots.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js +25 -22
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +14 -12
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js +29 -10
- package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js.map +2 -2
- package/dist/modules/sync_excel/lib/adapters/customers.js +20 -19
- package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
- package/dist/modules/sync_excel/lib/parser.js +0 -185
- package/dist/modules/sync_excel/lib/parser.js.map +2 -2
- package/dist/modules/sync_excel/lib/upload-storage.js +1 -20
- package/dist/modules/sync_excel/lib/upload-storage.js.map +2 -2
- package/dist/modules/workflows/frontend/checkout-demo/page.js +8 -1
- package/dist/modules/workflows/frontend/checkout-demo/page.js.map +2 -2
- package/dist/modules/workflows/lib/activity-executor.js +1 -1
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/dist/modules/workflows/lib/find-definition.js +18 -2
- package/dist/modules/workflows/lib/find-definition.js.map +2 -2
- package/dist/modules/workflows/lib/signal-handler.js +3 -2
- package/dist/modules/workflows/lib/signal-handler.js.map +2 -2
- package/dist/modules/workflows/lib/step-handler.js +4 -8
- package/dist/modules/workflows/lib/step-handler.js.map +2 -2
- package/dist/modules/workflows/lib/task-handler.js +3 -5
- package/dist/modules/workflows/lib/task-handler.js.map +2 -2
- package/dist/modules/workflows/lib/timer-handler.js +2 -1
- package/dist/modules/workflows/lib/timer-handler.js.map +2 -2
- package/dist/modules/workflows/lib/transition-handler.js +5 -13
- package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
- package/dist/modules/workflows/lib/workflow-executor.js +11 -9
- package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
- package/dist/modules/workflows/migrations/Migration20260715120000.js +68 -0
- package/dist/modules/workflows/migrations/Migration20260715120000.js.map +7 -0
- package/dist/modules/workflows/migrations/Migration20260716120000.js +24 -0
- package/dist/modules/workflows/migrations/Migration20260716120000.js.map +7 -0
- package/dist/modules/workflows/workflows.js +2 -0
- package/dist/modules/workflows/workflows.js.map +2 -2
- package/generated/entities.ids.generated.ts +0 -1
- package/generated/entity-fields-registry.ts +0 -12
- package/package.json +8 -9
- package/src/modules/api_keys/api/keys/route.ts +13 -36
- package/src/modules/api_keys/cli.ts +3 -2
- package/src/modules/attachments/api/file/[id]/route.ts +7 -11
- package/src/modules/attachments/api/image/[id]/[[...slug]]/route.ts +7 -11
- package/src/modules/attachments/api/route.ts +21 -26
- package/src/modules/attachments/components/AttachmentContentPreview.tsx +44 -9
- package/src/modules/audit_logs/backend/audit-logs/page.tsx +22 -12
- package/src/modules/auth/api/users/route.ts +2 -11
- package/src/modules/auth/cli.ts +2 -3
- package/src/modules/configs/i18n/de.json +1 -5
- package/src/modules/configs/i18n/en.json +1 -5
- package/src/modules/configs/i18n/es.json +1 -5
- package/src/modules/configs/i18n/pl.json +1 -5
- package/src/modules/configs/lib/upgrade-actions.ts +0 -24
- package/src/modules/customer_accounts/AGENTS.md +6 -8
- package/src/modules/customer_accounts/api/admin/roles/[id]/acl.ts +0 -1
- package/src/modules/customer_accounts/api/admin/roles/[id].ts +3 -17
- package/src/modules/customer_accounts/api/portal/users/[id]/roles.ts +1 -6
- package/src/modules/customer_accounts/api/portal/users-invite.ts +1 -6
- package/src/modules/customer_accounts/services/customerInvitationService.ts +0 -1
- package/src/modules/customer_accounts/services/customerRbacService.ts +2 -9
- package/src/modules/customer_accounts/widgets/injection-table.ts +2 -0
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +1 -11
- package/src/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.tsx +2 -6
- package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +55 -39
- package/src/modules/customers/components/detail/DealDetailTabs.tsx +49 -24
- package/src/modules/customers/components/detail/DetailTabsLayout.tsx +24 -13
- package/src/modules/customers/components/detail/MobilePersonDetail.tsx +31 -25
- package/src/modules/customers/components/detail/PersonDetailTabs.tsx +50 -29
- package/src/modules/dashboards/api/roles/widgets/route.ts +3 -22
- package/src/modules/dashboards/api/users/widgets/route.ts +3 -22
- package/src/modules/dashboards/cli.ts +9 -4
- package/src/modules/dashboards/lib/widgetAssignmentScope.ts +0 -18
- package/src/modules/dictionaries/commands/entries.ts +16 -7
- package/src/modules/dictionaries/commands/entry-operations.ts +18 -8
- package/src/modules/dictionaries/commands/factory.ts +2 -8
- package/src/modules/dictionaries/fields/dictionary.tsx +32 -55
- package/src/modules/dictionaries/i18n/de.json +0 -2
- package/src/modules/dictionaries/i18n/en.json +0 -2
- package/src/modules/dictionaries/i18n/es.json +0 -2
- package/src/modules/dictionaries/i18n/pl.json +0 -2
- package/src/modules/directory/utils/organizationScope.ts +2 -36
- package/src/modules/entities/api/records.ts +7 -5
- package/src/modules/entities/backend/entities/system/[entityId]/page.meta.ts +0 -1
- package/src/modules/entities/backend/entities/user/[entityId]/page.meta.ts +0 -1
- package/src/modules/entities/backend/entities/user/[entityId]/page.tsx +49 -51
- package/src/modules/entities/cli.ts +1 -2
- package/src/modules/entities/i18n/de.json +0 -34
- package/src/modules/entities/i18n/en.json +0 -34
- package/src/modules/entities/i18n/es.json +0 -34
- package/src/modules/entities/i18n/pl.json +0 -34
- package/src/modules/feature_toggles/api/check/boolean/route.ts +15 -0
- package/src/modules/feature_toggles/defaults.json +0 -8
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +59 -16
- package/src/modules/payment_gateways/data/entities.ts +0 -39
- package/src/modules/payment_gateways/lib/gateway-service.ts +40 -211
- package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +0 -236
- package/src/modules/planner/backend/planner/availability-rulesets/[id]/page.tsx +20 -14
- package/src/modules/planner/components/AvailabilityRulesEditor.tsx +34 -16
- package/src/modules/query_index/api/status.ts +8 -2
- package/src/modules/resources/backend/resources/resources/[id]/page.tsx +37 -27
- package/src/modules/sales/backend/sales/channels/create/page.meta.ts +0 -3
- package/src/modules/sales/backend/sales/channels/create/page.tsx +0 -7
- package/src/modules/sales/backend/sales/channels/offers/page.meta.ts +0 -3
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +0 -7
- package/src/modules/sales/backend/sales/channels/page.meta.ts +0 -4
- package/src/modules/sales/backend/sales/channels/page.tsx +0 -7
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +5 -7
- package/src/modules/sales/commands/documents.ts +0 -65
- package/src/modules/sales/commands/returns.ts +32 -2
- package/src/modules/sales/components/documents/AddressesSection.tsx +2 -6
- package/src/modules/sales/components/documents/ItemsSection.tsx +0 -5
- package/src/modules/sales/components/documents/LineItemDialog.tsx +0 -10
- package/src/modules/sales/components/documents/SalesDocumentForm.tsx +3 -53
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +8 -10
- package/src/modules/sales/components/documents/ShipmentDialog.tsx +40 -65
- package/src/modules/sales/i18n/de.json +0 -5
- package/src/modules/sales/i18n/en.json +0 -5
- package/src/modules/sales/i18n/es.json +0 -5
- package/src/modules/sales/i18n/pl.json +0 -5
- package/src/modules/sales/lib/shipments/snapshots.ts +0 -30
- package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +34 -25
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +17 -11
- package/src/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.tsx +28 -11
- package/src/modules/sync_excel/lib/adapters/customers.ts +22 -20
- package/src/modules/sync_excel/lib/parser.ts +0 -245
- package/src/modules/sync_excel/lib/upload-storage.ts +1 -23
- package/src/modules/workflows/frontend/checkout-demo/page.tsx +12 -1
- package/src/modules/workflows/lib/activity-executor.ts +22 -2
- package/src/modules/workflows/lib/find-definition.ts +53 -1
- package/src/modules/workflows/lib/signal-handler.ts +5 -4
- package/src/modules/workflows/lib/step-handler.ts +4 -8
- package/src/modules/workflows/lib/task-handler.ts +2 -4
- package/src/modules/workflows/lib/timer-handler.ts +3 -2
- package/src/modules/workflows/lib/transition-handler.ts +5 -13
- package/src/modules/workflows/lib/workflow-executor.ts +11 -8
- package/src/modules/workflows/migrations/Migration20260715120000.ts +114 -0
- package/src/modules/workflows/migrations/Migration20260716120000.ts +57 -0
- package/src/modules/workflows/workflows.ts +2 -0
- package/dist/generated/entities/gateway_session_initialization/index.js +0 -23
- package/dist/generated/entities/gateway_session_initialization/index.js.map +0 -7
- package/dist/modules/attachments/lib/reconcileOrganization.js +0 -110
- package/dist/modules/attachments/lib/reconcileOrganization.js.map +0 -7
- package/dist/modules/attachments/lib/requestScope.js +0 -10
- package/dist/modules/attachments/lib/requestScope.js.map +0 -7
- package/dist/modules/auth/api/autologin.js +0 -85
- package/dist/modules/auth/api/autologin.js.map +0 -7
- package/dist/modules/auth/lib/autologin.js +0 -19
- package/dist/modules/auth/lib/autologin.js.map +0 -7
- package/dist/modules/customers/components/detail/useDealsAccess.js +0 -16
- package/dist/modules/customers/components/detail/useDealsAccess.js.map +0 -7
- package/dist/modules/payment_gateways/lib/session-idempotency.js +0 -104
- package/dist/modules/payment_gateways/lib/session-idempotency.js.map +0 -7
- package/dist/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.js +0 -11
- package/dist/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.js.map +0 -7
- package/dist/modules/sales/components/SalesChannelsDisabledNotice.js +0 -15
- package/dist/modules/sales/components/SalesChannelsDisabledNotice.js.map +0 -7
- package/dist/modules/sales/components/useSalesChannelsEnabled.js +0 -44
- package/dist/modules/sales/components/useSalesChannelsEnabled.js.map +0 -7
- package/dist/modules/sales/lib/salesChannelsToggle.js +0 -18
- package/dist/modules/sales/lib/salesChannelsToggle.js.map +0 -7
- package/dist/modules/sales/lib/salesChannelsToggleId.js +0 -5
- package/dist/modules/sales/lib/salesChannelsToggleId.js.map +0 -7
- package/generated/entities/gateway_session_initialization/index.ts +0 -10
- package/src/modules/attachments/lib/reconcileOrganization.ts +0 -188
- package/src/modules/attachments/lib/requestScope.ts +0 -27
- package/src/modules/auth/api/autologin.ts +0 -100
- package/src/modules/auth/lib/autologin.ts +0 -36
- package/src/modules/customers/components/detail/useDealsAccess.ts +0 -19
- package/src/modules/payment_gateways/lib/session-idempotency.ts +0 -142
- package/src/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.ts +0 -10
- package/src/modules/sales/components/SalesChannelsDisabledNotice.tsx +0 -21
- package/src/modules/sales/components/useSalesChannelsEnabled.ts +0 -59
- package/src/modules/sales/lib/salesChannelsToggle.ts +0 -26
- package/src/modules/sales/lib/salesChannelsToggleId.ts +0 -1
|
@@ -6,8 +6,7 @@ import {
|
|
|
6
6
|
type ReorderDictionaryEntriesCommandInput,
|
|
7
7
|
type SetDefaultDictionaryEntryCommandInput,
|
|
8
8
|
} from '@open-mercato/core/modules/dictionaries/data/validators'
|
|
9
|
-
import {
|
|
10
|
-
import { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'
|
|
9
|
+
import { registerCommand, type CommandHandler, type CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
|
|
11
10
|
import { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'
|
|
12
11
|
import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
|
|
13
12
|
import { emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'
|
|
@@ -37,6 +36,17 @@ const dictionaryCrudEvents: CrudEventsConfig = {
|
|
|
37
36
|
}),
|
|
38
37
|
}
|
|
39
38
|
|
|
39
|
+
function ensureScope(ctx: CommandRuntimeContext, scope: DictionaryScope): void {
|
|
40
|
+
const tenantId = ctx.auth?.tenantId ?? null
|
|
41
|
+
if (tenantId && tenantId !== scope.tenantId) {
|
|
42
|
+
throw new CrudHttpError(403, { error: 'Forbidden' })
|
|
43
|
+
}
|
|
44
|
+
const organizationId = ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null
|
|
45
|
+
if (organizationId && organizationId !== scope.organizationId) {
|
|
46
|
+
throw new CrudHttpError(403, { error: 'Forbidden' })
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
40
50
|
async function requireDictionary(
|
|
41
51
|
em: EntityManager,
|
|
42
52
|
id: string,
|
|
@@ -74,7 +84,7 @@ const reorderDictionaryEntriesCommand: CommandHandler<
|
|
|
74
84
|
async prepare(rawInput, ctx) {
|
|
75
85
|
const parsed = reorderDictionaryEntriesCommandSchema.parse(rawInput)
|
|
76
86
|
const scope: DictionaryScope = { tenantId: parsed.tenantId, organizationId: parsed.organizationId }
|
|
77
|
-
|
|
87
|
+
ensureScope(ctx, scope)
|
|
78
88
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
79
89
|
const ids = parsed.entries.map((e) => e.id)
|
|
80
90
|
const existing = await findWithDecryption(
|
|
@@ -98,7 +108,7 @@ const reorderDictionaryEntriesCommand: CommandHandler<
|
|
|
98
108
|
async execute(rawInput, ctx) {
|
|
99
109
|
const parsed = reorderDictionaryEntriesCommandSchema.parse(rawInput)
|
|
100
110
|
const scope: DictionaryScope = { tenantId: parsed.tenantId, organizationId: parsed.organizationId }
|
|
101
|
-
|
|
111
|
+
ensureScope(ctx, scope)
|
|
102
112
|
|
|
103
113
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
104
114
|
const dictionary = await requireDictionary(em, parsed.dictionaryId, scope)
|
|
@@ -191,7 +201,7 @@ const reorderDictionaryEntriesCommand: CommandHandler<
|
|
|
191
201
|
const undo = extractUndoPayload<ReorderUndoPayload>(logEntry)
|
|
192
202
|
const before = undo?.before ?? (logEntry?.snapshotBefore as ReorderSnapshot | null | undefined) ?? null
|
|
193
203
|
if (!before) return
|
|
194
|
-
|
|
204
|
+
ensureScope(ctx, before.scope)
|
|
195
205
|
|
|
196
206
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
197
207
|
const ids = before.positions.map((p) => p.id)
|
|
@@ -255,7 +265,7 @@ const setDefaultDictionaryEntryCommand: CommandHandler<
|
|
|
255
265
|
async prepare(rawInput, ctx) {
|
|
256
266
|
const parsed = setDefaultDictionaryEntryCommandSchema.parse(rawInput)
|
|
257
267
|
const scope: DictionaryScope = { tenantId: parsed.tenantId, organizationId: parsed.organizationId }
|
|
258
|
-
|
|
268
|
+
ensureScope(ctx, scope)
|
|
259
269
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
260
270
|
const dictionary = await requireDictionary(em, parsed.dictionaryId, scope)
|
|
261
271
|
const previousDefaults = await findWithDecryption(
|
|
@@ -281,7 +291,7 @@ const setDefaultDictionaryEntryCommand: CommandHandler<
|
|
|
281
291
|
async execute(rawInput, ctx) {
|
|
282
292
|
const parsed = setDefaultDictionaryEntryCommandSchema.parse(rawInput)
|
|
283
293
|
const scope: DictionaryScope = { tenantId: parsed.tenantId, organizationId: parsed.organizationId }
|
|
284
|
-
|
|
294
|
+
ensureScope(ctx, scope)
|
|
285
295
|
|
|
286
296
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
287
297
|
const dictionary = await requireDictionary(em, parsed.dictionaryId, scope)
|
|
@@ -389,7 +399,7 @@ const setDefaultDictionaryEntryCommand: CommandHandler<
|
|
|
389
399
|
const undo = extractUndoPayload<DefaultUndoPayload>(logEntry)
|
|
390
400
|
const before = undo?.before ?? (logEntry?.snapshotBefore as DefaultSnapshot | null | undefined) ?? null
|
|
391
401
|
if (!before) return
|
|
392
|
-
|
|
402
|
+
ensureScope(ctx, before.scope)
|
|
393
403
|
|
|
394
404
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
395
405
|
const dictionary = await requireDictionary(em, before.dictionaryId, before.scope)
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
} from '@open-mercato/shared/lib/commands'
|
|
13
13
|
import { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'
|
|
14
14
|
import { buildChanges, requireId } from '@open-mercato/shared/lib/commands/helpers'
|
|
15
|
-
import { ensureOrganizationScope, ensureTenantScope } from '@open-mercato/shared/lib/commands/scope'
|
|
16
15
|
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
17
16
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
18
17
|
import type { z } from 'zod'
|
|
@@ -23,11 +22,6 @@ type DictionaryScope = {
|
|
|
23
22
|
organizationId: string
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
export function ensureDictionaryEntryScope(ctx: CommandRuntimeContext, scope: DictionaryScope): void {
|
|
27
|
-
ensureTenantScope(ctx, scope.tenantId)
|
|
28
|
-
ensureOrganizationScope(ctx, scope.organizationId)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
25
|
export type DictionaryEntrySnapshot = {
|
|
32
26
|
id: string
|
|
33
27
|
dictionaryId: string
|
|
@@ -93,8 +87,8 @@ export type DictionaryEntryCommandConfig<TCreate, TUpdate> = {
|
|
|
93
87
|
labels?: DictionaryEntryCommandLabels
|
|
94
88
|
}
|
|
95
89
|
|
|
96
|
-
|
|
97
|
-
return typeof fn === 'function' ? fn :
|
|
90
|
+
function toScopeEnsurer(fn: EnsureScopeFn | undefined): EnsureScopeFn {
|
|
91
|
+
return typeof fn === 'function' ? fn : () => {}
|
|
98
92
|
}
|
|
99
93
|
|
|
100
94
|
async function loadSnapshot(em: EntityManager, id: string): Promise<DictionaryEntrySnapshot | null> {
|
|
@@ -90,12 +90,9 @@ function DictionaryFieldDefEditor({ def, onChange }: { def: { configJson?: Dicti
|
|
|
90
90
|
const [error, setError] = React.useState<string | null>(null)
|
|
91
91
|
const multiId = React.useId()
|
|
92
92
|
const inlineCreateId = React.useId()
|
|
93
|
-
const inlineCreateHintId = React.useId()
|
|
94
|
-
const defaultValueHintId = React.useId()
|
|
95
93
|
const selectedId = typeof def?.configJson?.dictionaryId === 'string' ? def?.configJson?.dictionaryId : ''
|
|
96
94
|
const inlineCreate = def?.configJson?.dictionaryInlineCreate !== false
|
|
97
95
|
const isMulti = def?.configJson?.multi === true
|
|
98
|
-
const inlineCreateDisabled = !selectedId || isMulti
|
|
99
96
|
const errorLoadLabel = t('dictionaries.customFields.errorLoad', 'Failed to load dictionaries.')
|
|
100
97
|
|
|
101
98
|
React.useEffect(() => {
|
|
@@ -184,65 +181,45 @@ function DictionaryFieldDefEditor({ def, onChange }: { def: { configJson?: Dicti
|
|
|
184
181
|
</a>
|
|
185
182
|
</div>
|
|
186
183
|
) : null}
|
|
187
|
-
<div className="
|
|
188
|
-
<
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
{t('dictionaries.customFields.allowMultiple', 'Allow selecting multiple entries')}
|
|
204
|
-
</label>
|
|
205
|
-
</div>
|
|
206
|
-
<div className="inline-flex items-center gap-2 text-xs">
|
|
207
|
-
<Checkbox
|
|
208
|
-
id={inlineCreateId}
|
|
209
|
-
checked={!isMulti && inlineCreate}
|
|
210
|
-
onCheckedChange={(checked) => onChange({ dictionaryInlineCreate: checked === true })}
|
|
211
|
-
disabled={inlineCreateDisabled}
|
|
212
|
-
aria-describedby={isMulti ? inlineCreateHintId : undefined}
|
|
213
|
-
/>
|
|
214
|
-
<label
|
|
215
|
-
htmlFor={inlineCreateId}
|
|
216
|
-
className={!inlineCreateDisabled ? 'cursor-pointer select-none' : 'cursor-not-allowed opacity-60'}
|
|
217
|
-
>
|
|
218
|
-
{t('dictionaries.customFields.allowInlineCreate', 'Allow inline creation inside forms')}
|
|
219
|
-
</label>
|
|
220
|
-
</div>
|
|
221
|
-
</div>
|
|
222
|
-
{isMulti ? (
|
|
223
|
-
<p id={inlineCreateHintId} className="text-xs text-muted-foreground">
|
|
224
|
-
{t(
|
|
225
|
-
'dictionaries.customFields.inlineCreateSingleOnly',
|
|
226
|
-
'Inline creation is available for single-entry dictionary fields only.',
|
|
227
|
-
)}
|
|
228
|
-
</p>
|
|
229
|
-
) : null}
|
|
184
|
+
<div className="inline-flex items-center gap-2 text-xs">
|
|
185
|
+
<Checkbox
|
|
186
|
+
id={multiId}
|
|
187
|
+
checked={isMulti}
|
|
188
|
+
onCheckedChange={(checked) => {
|
|
189
|
+
const enabled = checked === true
|
|
190
|
+
onChange({ multi: enabled, defaultValue: enabled ? undefined : def?.configJson?.defaultValue })
|
|
191
|
+
}}
|
|
192
|
+
disabled={!selectedId}
|
|
193
|
+
/>
|
|
194
|
+
<label
|
|
195
|
+
htmlFor={multiId}
|
|
196
|
+
className={selectedId ? 'cursor-pointer select-none' : 'cursor-not-allowed opacity-60'}
|
|
197
|
+
>
|
|
198
|
+
{t('dictionaries.customFields.allowMultiple', 'Allow selecting multiple entries')}
|
|
199
|
+
</label>
|
|
230
200
|
</div>
|
|
201
|
+
{!isMulti ? (
|
|
202
|
+
<div className="inline-flex items-center gap-2 text-xs">
|
|
203
|
+
<Checkbox
|
|
204
|
+
id={inlineCreateId}
|
|
205
|
+
checked={inlineCreate}
|
|
206
|
+
onCheckedChange={(checked) => onChange({ dictionaryInlineCreate: checked === true })}
|
|
207
|
+
disabled={!selectedId}
|
|
208
|
+
/>
|
|
209
|
+
<label
|
|
210
|
+
htmlFor={inlineCreateId}
|
|
211
|
+
className={selectedId ? 'cursor-pointer select-none' : 'cursor-not-allowed opacity-60'}
|
|
212
|
+
>
|
|
213
|
+
{t('dictionaries.customFields.allowInlineCreate', 'Allow inline creation inside forms')}
|
|
214
|
+
</label>
|
|
215
|
+
</div>
|
|
216
|
+
) : null}
|
|
231
217
|
{selectedId && !isMulti ? (
|
|
232
218
|
<DictionaryDefaultSelector
|
|
233
219
|
dictionaryId={selectedId}
|
|
234
220
|
defaultValue={typeof def?.configJson?.defaultValue === 'string' ? def.configJson.defaultValue : ''}
|
|
235
221
|
onChange={(value) => onChange({ defaultValue: value || undefined })}
|
|
236
222
|
/>
|
|
237
|
-
) : selectedId && isMulti ? (
|
|
238
|
-
<div className="inline-flex items-center gap-2 text-xs">
|
|
239
|
-
<p id={defaultValueHintId} className="text-xs text-muted-foreground">
|
|
240
|
-
{t(
|
|
241
|
-
'dictionaries.customFields.defaultValueMultiUnavailable',
|
|
242
|
-
'Default values are not available for multi-select dictionary fields.',
|
|
243
|
-
)}
|
|
244
|
-
</p>
|
|
245
|
-
</div>
|
|
246
223
|
) : null}
|
|
247
224
|
</div>
|
|
248
225
|
)
|
|
@@ -82,7 +82,6 @@
|
|
|
82
82
|
"dictionaries.customFields.allowInlineCreate": "Inline-Erstellung in Formularen erlauben",
|
|
83
83
|
"dictionaries.customFields.allowMultiple": "Mehrere Einträge auswählen erlauben",
|
|
84
84
|
"dictionaries.customFields.defaultValue": "Standardwert",
|
|
85
|
-
"dictionaries.customFields.defaultValueMultiUnavailable": "Standardwerte sind für Wörterbuchfelder mit Mehrfachauswahl nicht verfügbar.",
|
|
86
85
|
"dictionaries.customFields.defaultValueNone": "Kein Standardwert",
|
|
87
86
|
"dictionaries.customFields.defaultValueStale": "Standardeintrag nicht gefunden — er wurde möglicherweise gelöscht oder umbenannt.",
|
|
88
87
|
"dictionaries.customFields.dictionaryLabel": "Quelle des Wörterbuchs",
|
|
@@ -90,7 +89,6 @@
|
|
|
90
89
|
"dictionaries.customFields.empty": "Noch keine Wörterbücher verfügbar. Erstellen Sie zuerst eines.",
|
|
91
90
|
"dictionaries.customFields.errorLoad": "Wörterbücher konnten nicht geladen werden.",
|
|
92
91
|
"dictionaries.customFields.inactive": "inaktiv",
|
|
93
|
-
"dictionaries.customFields.inlineCreateSingleOnly": "Inline-Erstellung ist nur für Wörterbuchfelder mit Einzelauswahl verfügbar.",
|
|
94
92
|
"dictionaries.customFields.loading": "Wörterbücher werden geladen…",
|
|
95
93
|
"dictionaries.customFields.manageLink": "Wörterbücher verwalten",
|
|
96
94
|
"dictionaries.customFields.selectedHint": "Einträge aus diesem Wörterbuch füllen das Feld.",
|
|
@@ -82,7 +82,6 @@
|
|
|
82
82
|
"dictionaries.customFields.allowInlineCreate": "Allow inline creation inside forms",
|
|
83
83
|
"dictionaries.customFields.allowMultiple": "Allow selecting multiple entries",
|
|
84
84
|
"dictionaries.customFields.defaultValue": "Default value",
|
|
85
|
-
"dictionaries.customFields.defaultValueMultiUnavailable": "Default values are not available for multi-select dictionary fields.",
|
|
86
85
|
"dictionaries.customFields.defaultValueNone": "No default",
|
|
87
86
|
"dictionaries.customFields.defaultValueStale": "Default entry not found — it may have been deleted or renamed.",
|
|
88
87
|
"dictionaries.customFields.dictionaryLabel": "Dictionary source",
|
|
@@ -90,7 +89,6 @@
|
|
|
90
89
|
"dictionaries.customFields.empty": "No dictionaries available yet. Create one first.",
|
|
91
90
|
"dictionaries.customFields.errorLoad": "Failed to load dictionaries.",
|
|
92
91
|
"dictionaries.customFields.inactive": "inactive",
|
|
93
|
-
"dictionaries.customFields.inlineCreateSingleOnly": "Inline creation is available for single-entry dictionary fields only.",
|
|
94
92
|
"dictionaries.customFields.loading": "Loading dictionaries…",
|
|
95
93
|
"dictionaries.customFields.manageLink": "Manage dictionaries",
|
|
96
94
|
"dictionaries.customFields.selectedHint": "Entries from this dictionary populate the field.",
|
|
@@ -82,7 +82,6 @@
|
|
|
82
82
|
"dictionaries.customFields.allowInlineCreate": "Permitir creación en línea dentro de los formularios",
|
|
83
83
|
"dictionaries.customFields.allowMultiple": "Permitir seleccionar varias entradas",
|
|
84
84
|
"dictionaries.customFields.defaultValue": "Valor predeterminado",
|
|
85
|
-
"dictionaries.customFields.defaultValueMultiUnavailable": "Los valores predeterminados no están disponibles para campos de diccionario con selección múltiple.",
|
|
86
85
|
"dictionaries.customFields.defaultValueNone": "Sin valor predeterminado",
|
|
87
86
|
"dictionaries.customFields.defaultValueStale": "No se encontró la entrada predeterminada; puede haber sido eliminada o renombrada.",
|
|
88
87
|
"dictionaries.customFields.dictionaryLabel": "Fuente del diccionario",
|
|
@@ -90,7 +89,6 @@
|
|
|
90
89
|
"dictionaries.customFields.empty": "Aún no hay diccionarios disponibles. Crea uno primero.",
|
|
91
90
|
"dictionaries.customFields.errorLoad": "No se pudieron cargar los diccionarios.",
|
|
92
91
|
"dictionaries.customFields.inactive": "inactivo",
|
|
93
|
-
"dictionaries.customFields.inlineCreateSingleOnly": "La creación en línea solo está disponible para campos de diccionario de una sola entrada.",
|
|
94
92
|
"dictionaries.customFields.loading": "Cargando diccionarios…",
|
|
95
93
|
"dictionaries.customFields.manageLink": "Administrar diccionarios",
|
|
96
94
|
"dictionaries.customFields.selectedHint": "Las entradas de este diccionario rellenarán el campo.",
|
|
@@ -82,7 +82,6 @@
|
|
|
82
82
|
"dictionaries.customFields.allowInlineCreate": "Zezwól na tworzenie w formularzach",
|
|
83
83
|
"dictionaries.customFields.allowMultiple": "Zezwól na wybór wielu wpisów",
|
|
84
84
|
"dictionaries.customFields.defaultValue": "Wartość domyślna",
|
|
85
|
-
"dictionaries.customFields.defaultValueMultiUnavailable": "Wartości domyślne nie są dostępne dla wielokrotnego wyboru wpisów słownika.",
|
|
86
85
|
"dictionaries.customFields.defaultValueNone": "Brak wartości domyślnej",
|
|
87
86
|
"dictionaries.customFields.defaultValueStale": "Nie znaleziono domyślnego wpisu — mógł zostać usunięty albo przemianowany.",
|
|
88
87
|
"dictionaries.customFields.dictionaryLabel": "Źródło słownika",
|
|
@@ -90,7 +89,6 @@
|
|
|
90
89
|
"dictionaries.customFields.empty": "Brak dostępnych słowników. Najpierw utwórz jeden.",
|
|
91
90
|
"dictionaries.customFields.errorLoad": "Nie udało się wczytać słowników.",
|
|
92
91
|
"dictionaries.customFields.inactive": "nieaktywne",
|
|
93
|
-
"dictionaries.customFields.inlineCreateSingleOnly": "Tworzenie wpisów w formularzu jest dostępne tylko dla pól z pojedynczym wyborem.",
|
|
94
92
|
"dictionaries.customFields.loading": "Ładowanie słowników…",
|
|
95
93
|
"dictionaries.customFields.manageLink": "Zarządzaj słownikami",
|
|
96
94
|
"dictionaries.customFields.selectedHint": "Wpisy z tego słownika uzupełnią pole.",
|
|
@@ -18,13 +18,6 @@ export type OrganizationScope = {
|
|
|
18
18
|
filterIds: string[] | null
|
|
19
19
|
allowedIds: string[] | null
|
|
20
20
|
tenantId: string | null
|
|
21
|
-
// True when the caller explicitly selected a concrete organization (cookie /
|
|
22
|
-
// selectedId param) that could not be honored — it does not exist for the
|
|
23
|
-
// tenant or is not accessible. Reads degrade gracefully (filterIds/selectedId
|
|
24
|
-
// fall back to the caller's accessible orgs), but writes MUST fail loudly on
|
|
25
|
-
// this so a record never lands under an org the caller did not intend. Absent
|
|
26
|
-
// (undefined) means the selection — if any — was honored.
|
|
27
|
-
selectionRejected?: boolean
|
|
28
21
|
}
|
|
29
22
|
|
|
30
23
|
// Phase 4 — short-TTL cache for resolveOrganizationScopeForRequest.
|
|
@@ -86,8 +79,7 @@ function isValidCachedScope(value: unknown): value is OrganizationScope {
|
|
|
86
79
|
const record = value as Partial<OrganizationScope>
|
|
87
80
|
const idOk = (v: unknown) => v === null || typeof v === 'string'
|
|
88
81
|
const arrOk = (v: unknown) => v === null || (Array.isArray(v) && v.every((entry) => typeof entry === 'string'))
|
|
89
|
-
|
|
90
|
-
return idOk(record.selectedId) && idOk(record.tenantId) && arrOk(record.filterIds) && arrOk(record.allowedIds) && flagOk
|
|
82
|
+
return idOk(record.selectedId) && idOk(record.tenantId) && arrOk(record.filterIds) && arrOk(record.allowedIds)
|
|
91
83
|
}
|
|
92
84
|
|
|
93
85
|
function resolveCacheFromContainer(container: AwilixContainer | null | undefined): CacheStrategy | null {
|
|
@@ -328,18 +320,9 @@ export async function resolveOrganizationScope({
|
|
|
328
320
|
const initialSelected =
|
|
329
321
|
normalizedSelectedId
|
|
330
322
|
?? (widenToAllOrgs ? null : accountOrgId ?? null)
|
|
331
|
-
// A selection is only honored when it resolves to a real, non-deleted org for
|
|
332
|
-
// this tenant. `orgDescendants` holds exactly the existing orgs among the
|
|
333
|
-
// candidate ids, so a stale/dead id (e.g. a selected-org cookie or JWT org
|
|
334
|
-
// that no longer resolves after a DB reset) has no entry and is dropped here.
|
|
335
|
-
// Without the existence guard an unrestricted (all-orgs) principal — whose
|
|
336
|
-
// `allowedSet` is null — would accept the dead id as `effectiveSelected`, and
|
|
337
|
-
// writes derived from `selectedId` would land under an org the read scope
|
|
338
|
-
// (`filterIds`) never filters to, silently orphaning the record.
|
|
339
|
-
const selectionResolvesToOrg = (id: string): boolean => orgDescendants.has(id)
|
|
340
323
|
let effectiveSelected: string | null = null
|
|
341
324
|
if (initialSelected) {
|
|
342
|
-
if (
|
|
325
|
+
if (allowedSet === null || allowedSet.has(initialSelected)) {
|
|
343
326
|
effectiveSelected = initialSelected
|
|
344
327
|
}
|
|
345
328
|
}
|
|
@@ -353,13 +336,6 @@ export async function resolveOrganizationScope({
|
|
|
353
336
|
filterSet = null
|
|
354
337
|
} else if (auth.orgId) {
|
|
355
338
|
filterSet = loadFallbackSet()
|
|
356
|
-
// Keep the write target (`selectedId`) aligned with the read scope
|
|
357
|
-
// (`filterIds`): when an unrestricted principal's requested selection was
|
|
358
|
-
// dropped above, fall the selection back to the account org too so a record
|
|
359
|
-
// created here is always readable back by the same caller.
|
|
360
|
-
if (!effectiveSelected && fallbackOrgId && filterSet && filterSet.size > 0) {
|
|
361
|
-
effectiveSelected = fallbackOrgId
|
|
362
|
-
}
|
|
363
339
|
}
|
|
364
340
|
|
|
365
341
|
if ((!filterSet || filterSet.size === 0) && fallbackOrgId && !widenToAllOrgs) {
|
|
@@ -372,21 +348,11 @@ export async function resolveOrganizationScope({
|
|
|
372
348
|
}
|
|
373
349
|
}
|
|
374
350
|
|
|
375
|
-
// A concrete organization was explicitly requested (`normalizedSelectedId` is
|
|
376
|
-
// null for both "no selection" and the "all organizations" token) but the
|
|
377
|
-
// resolver could not honor it — it was dropped as non-existent/inaccessible
|
|
378
|
-
// and the effective selection fell back to something else. Surface this so the
|
|
379
|
-
// write layer can reject the request instead of silently creating the record
|
|
380
|
-
// under the fallback org. Only set the field when true to keep the scope shape
|
|
381
|
-
// unchanged for the common (honored) case.
|
|
382
|
-
const selectionRejected = normalizedSelectedId !== null && effectiveSelected !== normalizedSelectedId
|
|
383
|
-
|
|
384
351
|
return {
|
|
385
352
|
selectedId: effectiveSelected,
|
|
386
353
|
filterIds: filterSet ? Array.from(filterSet) : null,
|
|
387
354
|
allowedIds: allowedSet ? Array.from(allowedSet) : null,
|
|
388
355
|
tenantId,
|
|
389
|
-
...(selectionRejected ? { selectionRejected: true } : {}),
|
|
390
356
|
}
|
|
391
357
|
}
|
|
392
358
|
|
|
@@ -8,7 +8,6 @@ import type { RbacService } from '@open-mercato/core/modules/auth/services/rbacS
|
|
|
8
8
|
import { resolveOrganizationScope, getSelectedOrganizationFromRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'
|
|
9
9
|
import { SYSTEM_ENTITY_RECORDS_BLOCKED_CODE, isOrmBackedSystemEntityId } from '@open-mercato/shared/lib/data/engine'
|
|
10
10
|
import { parseBooleanToken, parseBooleanWithDefault } from '@open-mercato/shared/lib/boolean'
|
|
11
|
-
import { parseCommaSeparatedList } from '@open-mercato/shared/lib/string'
|
|
12
11
|
import { setRecordCustomFields } from '../lib/helpers'
|
|
13
12
|
import { CustomFieldValue } from '../data/entities'
|
|
14
13
|
import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
@@ -152,7 +151,10 @@ export async function GET(req: Request) {
|
|
|
152
151
|
const sortDir = (url.searchParams.get('sortDir') || 'asc').toLowerCase() === 'desc' ? 'desc' : 'asc'
|
|
153
152
|
const withDeleted = parseBooleanWithDefault(url.searchParams.get('withDeleted'), false)
|
|
154
153
|
const searchTerm = (url.searchParams.get('search') || '').trim()
|
|
155
|
-
const searchFields =
|
|
154
|
+
const searchFields = (url.searchParams.get('searchFields') || '')
|
|
155
|
+
.split(',')
|
|
156
|
+
.map((field) => field.trim())
|
|
157
|
+
.filter(Boolean)
|
|
156
158
|
|
|
157
159
|
const qpEntries: Array<[string, string]> = []
|
|
158
160
|
for (const [key, val] of url.searchParams.entries()) {
|
|
@@ -209,11 +211,11 @@ export async function GET(req: Request) {
|
|
|
209
211
|
if (key.startsWith('cf_')) {
|
|
210
212
|
if (key.endsWith('In')) {
|
|
211
213
|
const base = key.slice(0, -2)
|
|
212
|
-
const values =
|
|
214
|
+
const values = val.split(',').map((s) => s.trim()).filter(Boolean)
|
|
213
215
|
;(filtersObj as any)[base] = { $in: values }
|
|
214
216
|
} else {
|
|
215
217
|
if (val.includes(',')) {
|
|
216
|
-
const values =
|
|
218
|
+
const values = val.split(',').map((s) => s.trim()).filter(Boolean)
|
|
217
219
|
;(filtersObj as any)[key] = { $in: values }
|
|
218
220
|
} else {
|
|
219
221
|
const parsed = parseBooleanToken(val)
|
|
@@ -222,7 +224,7 @@ export async function GET(req: Request) {
|
|
|
222
224
|
}
|
|
223
225
|
} else if (allowAnyKey) {
|
|
224
226
|
if (val.includes(',')) {
|
|
225
|
-
const values =
|
|
227
|
+
const values = val.split(',').map((s) => s.trim()).filter(Boolean)
|
|
226
228
|
;(filtersObj as any)[key] = { $in: values }
|
|
227
229
|
} else {
|
|
228
230
|
const parsed = parseBooleanToken(val)
|