@open-mercato/core 0.6.7-develop.6785.1.1dd7cfac55 → 0.6.7-develop.6795.1.8a3f27921c
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 +1 -1
- package/dist/generated/entities.ids.generated.js +1 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/modules/auth/backend/settings/page.js +14 -9
- package/dist/modules/auth/backend/settings/page.js.map +2 -2
- package/dist/modules/customers/cli.js +17 -7
- package/dist/modules/customers/cli.js.map +2 -2
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +229 -216
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
- package/dist/modules/customers/search.js +50 -29
- package/dist/modules/customers/search.js.map +2 -2
- package/dist/modules/data_sync/api/mappings/[id]/route.js +22 -9
- package/dist/modules/data_sync/api/mappings/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/mappings/route.js +13 -4
- package/dist/modules/data_sync/api/mappings/route.js.map +2 -2
- package/dist/modules/data_sync/api/options.js +7 -2
- package/dist/modules/data_sync/api/options.js.map +2 -2
- package/dist/modules/data_sync/api/run.js +7 -2
- package/dist/modules/data_sync/api/run.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/cancel.js +8 -3
- package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/retry.js +7 -2
- package/dist/modules/data_sync/api/runs/[id]/retry.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/route.js +8 -3
- package/dist/modules/data_sync/api/runs/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/runs.js +7 -2
- package/dist/modules/data_sync/api/runs.js.map +2 -2
- package/dist/modules/data_sync/api/schedules/[id]/route.js +19 -6
- package/dist/modules/data_sync/api/schedules/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/schedules/route.js +13 -4
- package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
- package/dist/modules/data_sync/api/validate.js +9 -4
- package/dist/modules/data_sync/api/validate.js.map +2 -2
- package/dist/modules/design_system/acl.js +9 -0
- package/dist/modules/design_system/acl.js.map +7 -0
- package/dist/modules/design_system/backend/design-system/page.js +11 -0
- package/dist/modules/design_system/backend/design-system/page.js.map +7 -0
- package/dist/modules/design_system/backend/design-system/page.meta.js +15 -0
- package/dist/modules/design_system/backend/design-system/page.meta.js.map +7 -0
- package/dist/modules/design_system/gallery/components/CodeSnippet.js +52 -0
- package/dist/modules/design_system/gallery/components/CodeSnippet.js.map +7 -0
- package/dist/modules/design_system/gallery/components/EntryCard.js +63 -0
- package/dist/modules/design_system/gallery/components/EntryCard.js.map +7 -0
- package/dist/modules/design_system/gallery/components/GalleryShell.js +163 -0
- package/dist/modules/design_system/gallery/components/GalleryShell.js.map +7 -0
- package/dist/modules/design_system/gallery/components/VariantPreview.js +9 -0
- package/dist/modules/design_system/gallery/components/VariantPreview.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/banners.js +186 -0
- package/dist/modules/design_system/gallery/entries/banners.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/buttons.js +361 -0
- package/dist/modules/design_system/gallery/entries/buttons.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/charts.js +457 -0
- package/dist/modules/design_system/gallery/entries/charts.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/dates.js +306 -0
- package/dist/modules/design_system/gallery/entries/dates.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/detail.js +358 -0
- package/dist/modules/design_system/gallery/entries/detail.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/display.js +785 -0
- package/dist/modules/design_system/gallery/entries/display.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/feedback.js +658 -0
- package/dist/modules/design_system/gallery/entries/feedback.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/filters.js +505 -0
- package/dist/modules/design_system/gallery/entries/filters.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/foundations.js +453 -0
- package/dist/modules/design_system/gallery/entries/foundations.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/icons.js +140 -0
- package/dist/modules/design_system/gallery/entries/icons.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/inputs.js +1217 -0
- package/dist/modules/design_system/gallery/entries/inputs.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/messages.js +334 -0
- package/dist/modules/design_system/gallery/entries/messages.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/navigation.js +475 -0
- package/dist/modules/design_system/gallery/entries/navigation.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/notifications.js +257 -0
- package/dist/modules/design_system/gallery/entries/notifications.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/overlays.js +576 -0
- package/dist/modules/design_system/gallery/entries/overlays.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/scaffolding.js +378 -0
- package/dist/modules/design_system/gallery/entries/scaffolding.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/schedule.js +297 -0
- package/dist/modules/design_system/gallery/entries/schedule.js.map +7 -0
- package/dist/modules/design_system/gallery/registry.js +139 -0
- package/dist/modules/design_system/gallery/registry.js.map +7 -0
- package/dist/modules/design_system/gallery/types.js +1 -0
- package/dist/modules/design_system/gallery/types.js.map +7 -0
- package/dist/modules/design_system/index.js +9 -0
- package/dist/modules/design_system/index.js.map +7 -0
- package/dist/modules/design_system/setup.js +14 -0
- package/dist/modules/design_system/setup.js.map +7 -0
- package/dist/modules/inbox_ops/search.js +15 -4
- package/dist/modules/inbox_ops/search.js.map +2 -2
- package/dist/modules/integrations/api/[id]/credentials/route.js +11 -5
- package/dist/modules/integrations/api/[id]/credentials/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/health/route.js +6 -3
- package/dist/modules/integrations/api/[id]/health/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/route.js +6 -3
- package/dist/modules/integrations/api/[id]/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/state/route.js +6 -3
- package/dist/modules/integrations/api/[id]/state/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/version/route.js +6 -3
- package/dist/modules/integrations/api/[id]/version/route.js.map +2 -2
- package/dist/modules/integrations/api/logs/route.js +6 -3
- package/dist/modules/integrations/api/logs/route.js.map +2 -2
- package/dist/modules/integrations/api/route.js +6 -3
- package/dist/modules/integrations/api/route.js.map +2 -2
- package/dist/modules/integrations/api/umes-read.js +2 -2
- package/dist/modules/integrations/api/umes-read.js.map +2 -2
- package/dist/modules/integrations/lib/organization-scope.js +2 -9
- package/dist/modules/integrations/lib/organization-scope.js.map +2 -2
- package/dist/modules/messages/search.js +10 -5
- package/dist/modules/messages/search.js.map +2 -2
- package/dist/modules/query_index/data/entities.js +2 -1
- package/dist/modules/query_index/data/entities.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +32 -50
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js +17 -0
- package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js.map +7 -0
- package/generated/entities.ids.generated.ts +1 -0
- package/package.json +16 -16
- package/src/modules/auth/backend/settings/page.tsx +17 -8
- package/src/modules/customers/cli.ts +17 -7
- package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +24 -13
- package/src/modules/customers/i18n/de.json +17 -0
- package/src/modules/customers/i18n/en.json +17 -0
- package/src/modules/customers/i18n/es.json +17 -0
- package/src/modules/customers/i18n/pl.json +17 -0
- package/src/modules/customers/search.ts +59 -27
- package/src/modules/data_sync/AGENTS.md +1 -0
- package/src/modules/data_sync/api/mappings/[id]/route.ts +22 -9
- package/src/modules/data_sync/api/mappings/route.ts +13 -4
- package/src/modules/data_sync/api/options.ts +7 -2
- package/src/modules/data_sync/api/run.ts +7 -2
- package/src/modules/data_sync/api/runs/[id]/cancel.ts +8 -3
- package/src/modules/data_sync/api/runs/[id]/retry.ts +7 -2
- package/src/modules/data_sync/api/runs/[id]/route.ts +8 -3
- package/src/modules/data_sync/api/runs.ts +7 -2
- package/src/modules/data_sync/api/schedules/[id]/route.ts +19 -6
- package/src/modules/data_sync/api/schedules/route.ts +13 -4
- package/src/modules/data_sync/api/validate.ts +9 -4
- package/src/modules/design_system/AGENTS.md +34 -0
- package/src/modules/design_system/acl.ts +5 -0
- package/src/modules/design_system/backend/design-system/page.meta.ts +11 -0
- package/src/modules/design_system/backend/design-system/page.tsx +14 -0
- package/src/modules/design_system/gallery/components/CodeSnippet.tsx +55 -0
- package/src/modules/design_system/gallery/components/EntryCard.tsx +95 -0
- package/src/modules/design_system/gallery/components/GalleryShell.tsx +206 -0
- package/src/modules/design_system/gallery/components/VariantPreview.tsx +15 -0
- package/src/modules/design_system/gallery/entries/banners.tsx +226 -0
- package/src/modules/design_system/gallery/entries/buttons.tsx +422 -0
- package/src/modules/design_system/gallery/entries/charts.tsx +518 -0
- package/src/modules/design_system/gallery/entries/dates.tsx +325 -0
- package/src/modules/design_system/gallery/entries/detail.tsx +403 -0
- package/src/modules/design_system/gallery/entries/display.tsx +893 -0
- package/src/modules/design_system/gallery/entries/feedback.tsx +746 -0
- package/src/modules/design_system/gallery/entries/filters.tsx +570 -0
- package/src/modules/design_system/gallery/entries/foundations.tsx +529 -0
- package/src/modules/design_system/gallery/entries/icons.tsx +168 -0
- package/src/modules/design_system/gallery/entries/inputs.tsx +1516 -0
- package/src/modules/design_system/gallery/entries/messages.tsx +339 -0
- package/src/modules/design_system/gallery/entries/navigation.tsx +573 -0
- package/src/modules/design_system/gallery/entries/notifications.tsx +285 -0
- package/src/modules/design_system/gallery/entries/overlays.tsx +677 -0
- package/src/modules/design_system/gallery/entries/scaffolding.tsx +430 -0
- package/src/modules/design_system/gallery/entries/schedule.tsx +307 -0
- package/src/modules/design_system/gallery/registry.ts +152 -0
- package/src/modules/design_system/gallery/types.ts +32 -0
- package/src/modules/design_system/i18n/.hardcoded-allowlist.json +71 -0
- package/src/modules/design_system/i18n/de.json +46 -0
- package/src/modules/design_system/i18n/en.json +46 -0
- package/src/modules/design_system/i18n/es.json +46 -0
- package/src/modules/design_system/i18n/pl.json +46 -0
- package/src/modules/design_system/index.ts +7 -0
- package/src/modules/design_system/setup.ts +12 -0
- package/src/modules/inbox_ops/i18n/de.json +3 -0
- package/src/modules/inbox_ops/i18n/en.json +3 -0
- package/src/modules/inbox_ops/i18n/es.json +3 -0
- package/src/modules/inbox_ops/i18n/pl.json +3 -0
- package/src/modules/inbox_ops/search.ts +20 -4
- package/src/modules/integrations/api/[id]/credentials/route.ts +11 -5
- package/src/modules/integrations/api/[id]/health/route.ts +6 -3
- package/src/modules/integrations/api/[id]/route.ts +6 -3
- package/src/modules/integrations/api/[id]/state/route.ts +6 -3
- package/src/modules/integrations/api/[id]/version/route.ts +6 -3
- package/src/modules/integrations/api/logs/route.ts +6 -3
- package/src/modules/integrations/api/route.ts +6 -3
- package/src/modules/integrations/api/umes-read.ts +2 -2
- package/src/modules/integrations/lib/organization-scope.ts +5 -25
- package/src/modules/messages/i18n/de.json +2 -0
- package/src/modules/messages/i18n/en.json +2 -0
- package/src/modules/messages/i18n/es.json +2 -0
- package/src/modules/messages/i18n/pl.json +2 -0
- package/src/modules/messages/search.ts +11 -5
- package/src/modules/query_index/data/entities.ts +7 -0
- package/src/modules/query_index/lib/engine.ts +40 -63
- package/src/modules/query_index/migrations/.snapshot-open-mercato.json +12 -0
- package/src/modules/query_index/migrations/Migration20260731105052_query_index.ts +35 -0
|
@@ -6,6 +6,8 @@ import type {
|
|
|
6
6
|
SearchResultLink,
|
|
7
7
|
SearchIndexSource,
|
|
8
8
|
} from '@open-mercato/shared/modules/search'
|
|
9
|
+
import type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'
|
|
10
|
+
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
9
11
|
import { CUSTOMER_INTERACTION_TASK_SOURCE, EXAMPLE_TODO_SOURCE } from './lib/interactionCompatibility'
|
|
10
12
|
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
11
13
|
|
|
@@ -480,6 +482,7 @@ function ensureFallbackLines(lines: string[], record: Record<string, unknown>, o
|
|
|
480
482
|
// =============================================================================
|
|
481
483
|
|
|
482
484
|
function resolvePersonPresenter(
|
|
485
|
+
translate: TranslateFn,
|
|
483
486
|
record: Record<string, unknown>,
|
|
484
487
|
entity: Record<string, unknown> | null,
|
|
485
488
|
customFields: Record<string, unknown>,
|
|
@@ -495,7 +498,7 @@ function resolvePersonPresenter(
|
|
|
495
498
|
(nameParts.length ? nameParts : undefined) ??
|
|
496
499
|
fallbackEntityId ??
|
|
497
500
|
(record.id as string | undefined) ??
|
|
498
|
-
'Person'
|
|
501
|
+
translate('customers.search.fallback.person', 'Person')
|
|
499
502
|
const subtitlePieces: string[] = []
|
|
500
503
|
const jobTitle = record.job_title ?? record.jobTitle ?? customFields.job_title ?? customFields.jobTitle
|
|
501
504
|
if (jobTitle) subtitlePieces.push(String(jobTitle))
|
|
@@ -515,11 +518,14 @@ function resolvePersonPresenter(
|
|
|
515
518
|
title: String(title),
|
|
516
519
|
subtitle: subtitlePieces.length ? subtitlePieces.join(' · ') : undefined,
|
|
517
520
|
icon: 'user',
|
|
518
|
-
badge: pickValue(entity, 'display_name', 'displayName')
|
|
521
|
+
badge: pickValue(entity, 'display_name', 'displayName')
|
|
522
|
+
? translate('customers.search.badge.person', 'Person')
|
|
523
|
+
: undefined,
|
|
519
524
|
}
|
|
520
525
|
}
|
|
521
526
|
|
|
522
527
|
function resolveCompanyPresenter(
|
|
528
|
+
translate: TranslateFn,
|
|
523
529
|
record: Record<string, unknown>,
|
|
524
530
|
entity: Record<string, unknown> | null,
|
|
525
531
|
customFields: Record<string, unknown>,
|
|
@@ -537,7 +543,7 @@ function resolveCompanyPresenter(
|
|
|
537
543
|
(entity?.id && entity?.display_name ? entity.display_name as string : undefined) ??
|
|
538
544
|
fallbackEntityId ??
|
|
539
545
|
(record.id as string | undefined) ??
|
|
540
|
-
'Company'
|
|
546
|
+
translate('customers.search.fallback.company', 'Company')
|
|
541
547
|
const subtitlePieces: string[] = []
|
|
542
548
|
const industry = record.industry
|
|
543
549
|
if (industry) subtitlePieces.push(String(industry))
|
|
@@ -567,7 +573,9 @@ function resolveCompanyPresenter(
|
|
|
567
573
|
title: String(title),
|
|
568
574
|
subtitle: subtitlePieces.length ? subtitlePieces.join(' · ') : undefined,
|
|
569
575
|
icon: 'building',
|
|
570
|
-
badge: pickValue(entity, 'display_name', 'displayName')
|
|
576
|
+
badge: pickValue(entity, 'display_name', 'displayName')
|
|
577
|
+
? translate('customers.search.badge.company', 'Company')
|
|
578
|
+
: undefined,
|
|
571
579
|
}
|
|
572
580
|
}
|
|
573
581
|
|
|
@@ -605,6 +613,7 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
605
613
|
|
|
606
614
|
buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {
|
|
607
615
|
assertTenantContext(ctx)
|
|
616
|
+
const { t } = await resolveTranslations()
|
|
608
617
|
const lines: string[] = []
|
|
609
618
|
const record = ctx.record
|
|
610
619
|
appendLine(lines, 'Preferred name', record.preferred_name ?? record.preferredName ?? ctx.customFields.preferred_name)
|
|
@@ -643,9 +652,9 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
643
652
|
})
|
|
644
653
|
}
|
|
645
654
|
|
|
646
|
-
const presenter = resolvePersonPresenter(record, entity, ctx.customFields)
|
|
655
|
+
const presenter = resolvePersonPresenter(t, record, entity, ctx.customFields)
|
|
647
656
|
logMissingPresenterTitle('person', record, entity, presenter)
|
|
648
|
-
const presenterLabel = pickLabel(presenter.title) ?? 'Open person'
|
|
657
|
+
const presenterLabel = pickLabel(presenter.title) ?? t('customers.search.link.openPerson', 'Open person')
|
|
649
658
|
const links: SearchResultLink[] = []
|
|
650
659
|
if (entityId) {
|
|
651
660
|
const href = buildCustomerUrl('person', entityId)
|
|
@@ -669,8 +678,9 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
669
678
|
|
|
670
679
|
formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {
|
|
671
680
|
assertTenantContext(ctx)
|
|
681
|
+
const { t } = await resolveTranslations()
|
|
672
682
|
const entity = await getCustomerEntity(ctx, resolveCustomerEntityId(ctx.record))
|
|
673
|
-
return resolvePersonPresenter(ctx.record, entity, ctx.customFields)
|
|
683
|
+
return resolvePersonPresenter(t, ctx.record, entity, ctx.customFields)
|
|
674
684
|
},
|
|
675
685
|
|
|
676
686
|
resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {
|
|
@@ -679,11 +689,12 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
679
689
|
},
|
|
680
690
|
|
|
681
691
|
resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {
|
|
692
|
+
const { t } = await resolveTranslations()
|
|
682
693
|
const entityId = resolveCustomerEntityId(ctx.record)
|
|
683
694
|
if (!entityId) return null
|
|
684
695
|
const href = buildCustomerUrl('person', entityId)
|
|
685
696
|
if (!href) return null
|
|
686
|
-
return [{ href: `${href}/edit`, label: 'Edit', kind: 'secondary' }]
|
|
697
|
+
return [{ href: `${href}/edit`, label: t('customers.search.link.edit', 'Edit'), kind: 'secondary' }]
|
|
687
698
|
},
|
|
688
699
|
|
|
689
700
|
fieldPolicy: {
|
|
@@ -714,6 +725,7 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
714
725
|
|
|
715
726
|
buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {
|
|
716
727
|
assertTenantContext(ctx)
|
|
728
|
+
const { t } = await resolveTranslations()
|
|
717
729
|
const lines: string[] = []
|
|
718
730
|
const record = ctx.record
|
|
719
731
|
appendLine(lines, 'Legal name', record.legal_name ?? record.legalName ?? ctx.customFields.legal_name)
|
|
@@ -734,9 +746,9 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
734
746
|
ensureFallbackLines(lines, record)
|
|
735
747
|
if (!lines.length) return null
|
|
736
748
|
|
|
737
|
-
const presenter = resolveCompanyPresenter(record, entity, ctx.customFields)
|
|
749
|
+
const presenter = resolveCompanyPresenter(t, record, entity, ctx.customFields)
|
|
738
750
|
logMissingPresenterTitle('company', record, entity, presenter)
|
|
739
|
-
const primaryLabel = pickLabel(presenter.title) ?? 'Open company'
|
|
751
|
+
const primaryLabel = pickLabel(presenter.title) ?? t('customers.search.link.openCompany', 'Open company')
|
|
740
752
|
const links: SearchResultLink[] = []
|
|
741
753
|
if (entityId) {
|
|
742
754
|
const href = buildCustomerUrl('company', entityId)
|
|
@@ -760,8 +772,9 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
760
772
|
|
|
761
773
|
formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {
|
|
762
774
|
assertTenantContext(ctx)
|
|
775
|
+
const { t } = await resolveTranslations()
|
|
763
776
|
const entity = await getCustomerEntity(ctx, resolveCustomerEntityId(ctx.record))
|
|
764
|
-
return resolveCompanyPresenter(ctx.record, entity, ctx.customFields)
|
|
777
|
+
return resolveCompanyPresenter(t, ctx.record, entity, ctx.customFields)
|
|
765
778
|
},
|
|
766
779
|
|
|
767
780
|
resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {
|
|
@@ -770,11 +783,12 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
770
783
|
},
|
|
771
784
|
|
|
772
785
|
resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {
|
|
786
|
+
const { t } = await resolveTranslations()
|
|
773
787
|
const entityId = resolveCustomerEntityId(ctx.record)
|
|
774
788
|
if (!entityId) return null
|
|
775
789
|
const href = buildCustomerUrl('company', entityId)
|
|
776
790
|
if (!href) return null
|
|
777
|
-
return [{ href: `${href}/edit`, label: 'Edit', kind: 'secondary' }]
|
|
791
|
+
return [{ href: `${href}/edit`, label: t('customers.search.link.edit', 'Edit'), kind: 'secondary' }]
|
|
778
792
|
},
|
|
779
793
|
|
|
780
794
|
fieldPolicy: {
|
|
@@ -832,8 +846,9 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
832
846
|
|
|
833
847
|
formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {
|
|
834
848
|
assertTenantContext(ctx)
|
|
849
|
+
const { t } = await resolveTranslations()
|
|
835
850
|
const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)
|
|
836
|
-
const title = (parent?.display_name as string | undefined) ?? 'Customer note'
|
|
851
|
+
const title = (parent?.display_name as string | undefined) ?? t('customers.search.fallback.customerNote', 'Customer note')
|
|
837
852
|
return {
|
|
838
853
|
title,
|
|
839
854
|
subtitle: snippet(ctx.record.body),
|
|
@@ -850,15 +865,16 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
850
865
|
|
|
851
866
|
resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {
|
|
852
867
|
assertTenantContext(ctx)
|
|
868
|
+
const { t } = await resolveTranslations()
|
|
853
869
|
const links: SearchResultLink[] = []
|
|
854
870
|
const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)
|
|
855
871
|
const parentUrl = buildCustomerUrl(parent?.kind as string ?? null, (parent?.id ?? ctx.record.entity_id ?? ctx.record.entityId) as string)
|
|
856
872
|
if (parentUrl) {
|
|
857
|
-
links.push({ href: parentUrl, label: (parent?.display_name as string | undefined) ?? 'View customer', kind: 'primary' })
|
|
873
|
+
links.push({ href: parentUrl, label: (parent?.display_name as string | undefined) ?? t('customers.search.link.viewCustomer', 'View customer'), kind: 'primary' })
|
|
858
874
|
}
|
|
859
875
|
if (ctx.record.deal_id) {
|
|
860
876
|
const dealUrl = `/backend/customers/deals/${encodeURIComponent(ctx.record.deal_id as string)}`
|
|
861
|
-
links.push({ href: dealUrl, label: 'Open deal', kind: 'secondary' })
|
|
877
|
+
links.push({ href: dealUrl, label: t('customers.search.link.openDeal', 'Open deal'), kind: 'secondary' })
|
|
862
878
|
}
|
|
863
879
|
return links.length ? links : null
|
|
864
880
|
},
|
|
@@ -880,6 +896,7 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
880
896
|
priority: 8,
|
|
881
897
|
|
|
882
898
|
buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {
|
|
899
|
+
const { t } = await resolveTranslations()
|
|
883
900
|
const lines: string[] = []
|
|
884
901
|
const record = ctx.record
|
|
885
902
|
appendLine(lines, 'Title', record.title)
|
|
@@ -898,10 +915,10 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
898
915
|
return {
|
|
899
916
|
text: lines,
|
|
900
917
|
presenter: {
|
|
901
|
-
title: String(record.title ?? 'Deal'),
|
|
918
|
+
title: String(record.title ?? t('customers.search.fallback.deal', 'Deal')),
|
|
902
919
|
subtitle: subtitleParts.join(' · ') || undefined,
|
|
903
920
|
icon: 'briefcase',
|
|
904
|
-
badge: 'Deal',
|
|
921
|
+
badge: t('customers.search.badge.deal', 'Deal'),
|
|
905
922
|
},
|
|
906
923
|
checksumSource: {
|
|
907
924
|
title: record.title,
|
|
@@ -913,8 +930,9 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
913
930
|
},
|
|
914
931
|
|
|
915
932
|
formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {
|
|
933
|
+
const { t } = await resolveTranslations()
|
|
916
934
|
const { record } = ctx
|
|
917
|
-
const title = pickString(record.title as string, 'Deal')
|
|
935
|
+
const title = pickString(record.title as string, t('customers.search.fallback.deal', 'Deal'))
|
|
918
936
|
const subtitleParts: string[] = []
|
|
919
937
|
if (record.pipeline_stage) subtitleParts.push(String(record.pipeline_stage))
|
|
920
938
|
if (record.status) subtitleParts.push(String(record.status))
|
|
@@ -925,10 +943,10 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
925
943
|
}
|
|
926
944
|
|
|
927
945
|
return {
|
|
928
|
-
title: title ?? 'Deal',
|
|
946
|
+
title: title ?? t('customers.search.fallback.deal', 'Deal'),
|
|
929
947
|
subtitle: subtitleParts.length ? subtitleParts.join(' · ') : undefined,
|
|
930
948
|
icon: 'briefcase',
|
|
931
|
-
badge: 'Deal',
|
|
949
|
+
badge: t('customers.search.badge.deal', 'Deal'),
|
|
932
950
|
}
|
|
933
951
|
},
|
|
934
952
|
|
|
@@ -939,12 +957,13 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
939
957
|
},
|
|
940
958
|
|
|
941
959
|
resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {
|
|
960
|
+
const { t } = await resolveTranslations()
|
|
942
961
|
const id = ctx.record.id
|
|
943
962
|
if (!id) return null
|
|
944
963
|
return [
|
|
945
964
|
{
|
|
946
965
|
href: `/backend/customers/deals/${encodeURIComponent(String(id))}/edit`,
|
|
947
|
-
label: 'Edit',
|
|
966
|
+
label: t('customers.search.link.edit', 'Edit'),
|
|
948
967
|
kind: 'secondary',
|
|
949
968
|
},
|
|
950
969
|
]
|
|
@@ -968,6 +987,7 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
968
987
|
|
|
969
988
|
buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {
|
|
970
989
|
assertTenantContext(ctx)
|
|
990
|
+
const { t } = await resolveTranslations()
|
|
971
991
|
const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)
|
|
972
992
|
const lines: string[] = []
|
|
973
993
|
if (parent?.display_name) lines.push(`Customer: ${parent.display_name}`)
|
|
@@ -976,7 +996,11 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
976
996
|
if (ctx.record.body) lines.push(`Body: ${ctx.record.body}`)
|
|
977
997
|
|
|
978
998
|
const presenter: SearchResultPresenter = {
|
|
979
|
-
title: ctx.record.subject
|
|
999
|
+
title: ctx.record.subject
|
|
1000
|
+
? String(ctx.record.subject)
|
|
1001
|
+
: t('customers.search.fallback.activity', 'Activity: {{type}}', {
|
|
1002
|
+
type: String(ctx.record.activity_type ?? t('customers.search.fallback.activityUpdate', 'update')),
|
|
1003
|
+
}),
|
|
980
1004
|
subtitle: (parent?.display_name as string | undefined) ?? snippet(ctx.record.body),
|
|
981
1005
|
icon: 'bolt',
|
|
982
1006
|
}
|
|
@@ -995,12 +1019,17 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
995
1019
|
|
|
996
1020
|
formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {
|
|
997
1021
|
assertTenantContext(ctx)
|
|
1022
|
+
const { t } = await resolveTranslations()
|
|
998
1023
|
const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)
|
|
999
1024
|
return {
|
|
1000
|
-
title: ctx.record.subject
|
|
1025
|
+
title: ctx.record.subject
|
|
1026
|
+
? String(ctx.record.subject)
|
|
1027
|
+
: t('customers.search.fallback.activity', 'Activity: {{type}}', {
|
|
1028
|
+
type: String(ctx.record.activity_type ?? t('customers.search.fallback.activityUpdate', 'update')),
|
|
1029
|
+
}),
|
|
1001
1030
|
subtitle: (parent?.display_name as string | undefined) ?? snippet(ctx.record.body),
|
|
1002
1031
|
icon: 'bolt',
|
|
1003
|
-
badge: 'Activity',
|
|
1032
|
+
badge: t('customers.search.badge.activity', 'Activity'),
|
|
1004
1033
|
}
|
|
1005
1034
|
},
|
|
1006
1035
|
|
|
@@ -1012,11 +1041,12 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
1012
1041
|
},
|
|
1013
1042
|
|
|
1014
1043
|
resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {
|
|
1044
|
+
const { t } = await resolveTranslations()
|
|
1015
1045
|
const links: SearchResultLink[] = []
|
|
1016
1046
|
if (ctx.record.deal_id) {
|
|
1017
1047
|
links.push({
|
|
1018
1048
|
href: `/backend/customers/deals/${encodeURIComponent(ctx.record.deal_id as string)}`,
|
|
1019
|
-
label: 'Open deal',
|
|
1049
|
+
label: t('customers.search.link.openDeal', 'Open deal'),
|
|
1020
1050
|
kind: 'secondary',
|
|
1021
1051
|
})
|
|
1022
1052
|
}
|
|
@@ -1064,10 +1094,11 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
1064
1094
|
|
|
1065
1095
|
formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {
|
|
1066
1096
|
assertTenantContext(ctx)
|
|
1097
|
+
const { t } = await resolveTranslations()
|
|
1067
1098
|
const todo = await getLinkedTodo(ctx) as Record<string, unknown> | null
|
|
1068
1099
|
const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)
|
|
1069
1100
|
return {
|
|
1070
|
-
title: (todo?.title as string | undefined) ?? 'Customer task',
|
|
1101
|
+
title: (todo?.title as string | undefined) ?? t('customers.search.fallback.customerTask', 'Customer task'),
|
|
1071
1102
|
subtitle: parent?.display_name as string | undefined,
|
|
1072
1103
|
icon: 'check-square',
|
|
1073
1104
|
}
|
|
@@ -1081,11 +1112,12 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
1081
1112
|
},
|
|
1082
1113
|
|
|
1083
1114
|
resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {
|
|
1115
|
+
const { t } = await resolveTranslations()
|
|
1084
1116
|
const todoId = ctx.record.todo_id ?? ctx.record.todoId
|
|
1085
1117
|
if (!todoId) return null
|
|
1086
1118
|
return [{
|
|
1087
1119
|
href: `/backend/todos/${encodeURIComponent(todoId as string)}/edit`,
|
|
1088
|
-
label: 'Open todo',
|
|
1120
|
+
label: t('customers.search.link.openTodo', 'Open todo'),
|
|
1089
1121
|
kind: 'secondary',
|
|
1090
1122
|
}]
|
|
1091
1123
|
},
|
|
@@ -9,6 +9,7 @@ The `data_sync` module provides a streaming data synchronization hub for import/
|
|
|
9
9
|
## Always
|
|
10
10
|
|
|
11
11
|
- **Always scope by organizationId + tenantId** — every entity query
|
|
12
|
+
- **Resolve the organization in API routes with `resolveActiveOrganizationId(auth)`** from `@open-mercato/shared/lib/auth/organizationScope`, never with raw `auth.orgId` — a super-admin viewing "all organizations" has `auth.orgId === null`. The fallback is tenant-aware: it never pairs the actor organization with a foreign selected tenant. When it returns `null` for an authenticated caller, answer with `organizationScopeRequiredResponse()` (400) — never 401, which sends `apiFetch` into a session-refresh loop
|
|
12
13
|
- **Use the queue system** — never run syncs inline in API handlers
|
|
13
14
|
- **New sync providers MUST support provider-owned env preconfiguration** when fresh installs need credentials or default mappings/locales/channels from deployment env
|
|
14
15
|
- **Persist cursor after each batch** — enables resume on failure
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
4
|
+
import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
4
5
|
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
5
6
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
6
7
|
import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
@@ -36,9 +37,13 @@ async function resolveParams(ctx: { params?: Promise<{ id?: string }> | { id?: s
|
|
|
36
37
|
|
|
37
38
|
export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
|
|
38
39
|
const auth = await getAuthFromRequest(req)
|
|
39
|
-
if (!auth?.tenantId
|
|
40
|
+
if (!auth?.tenantId) {
|
|
40
41
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
41
42
|
}
|
|
43
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
44
|
+
if (!organizationId) {
|
|
45
|
+
return organizationScopeRequiredResponse()
|
|
46
|
+
}
|
|
42
47
|
|
|
43
48
|
const parsedParams = await resolveParams(ctx)
|
|
44
49
|
if (!parsedParams.success) {
|
|
@@ -47,14 +52,14 @@ export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }>
|
|
|
47
52
|
|
|
48
53
|
const container = await createRequestContainer()
|
|
49
54
|
const em = container.resolve('em') as EntityManager
|
|
50
|
-
const scope = { organizationId
|
|
55
|
+
const scope = { organizationId, tenantId: auth.tenantId }
|
|
51
56
|
|
|
52
57
|
const mapping = await findOneWithDecryption(
|
|
53
58
|
em,
|
|
54
59
|
SyncMapping,
|
|
55
60
|
{
|
|
56
61
|
id: parsedParams.data.id,
|
|
57
|
-
organizationId
|
|
62
|
+
organizationId,
|
|
58
63
|
tenantId: auth.tenantId,
|
|
59
64
|
},
|
|
60
65
|
undefined,
|
|
@@ -77,9 +82,13 @@ export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }>
|
|
|
77
82
|
|
|
78
83
|
export async function PUT(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
|
|
79
84
|
const auth = await getAuthFromRequest(req)
|
|
80
|
-
if (!auth?.tenantId
|
|
85
|
+
if (!auth?.tenantId) {
|
|
81
86
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
82
87
|
}
|
|
88
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
89
|
+
if (!organizationId) {
|
|
90
|
+
return organizationScopeRequiredResponse()
|
|
91
|
+
}
|
|
83
92
|
|
|
84
93
|
const parsedParams = await resolveParams(ctx)
|
|
85
94
|
if (!parsedParams.success) {
|
|
@@ -94,14 +103,14 @@ export async function PUT(req: Request, ctx: { params?: Promise<{ id?: string }>
|
|
|
94
103
|
|
|
95
104
|
const container = await createRequestContainer()
|
|
96
105
|
const em = container.resolve('em') as EntityManager
|
|
97
|
-
const scope = { organizationId
|
|
106
|
+
const scope = { organizationId, tenantId: auth.tenantId }
|
|
98
107
|
|
|
99
108
|
const mapping = await findOneWithDecryption(
|
|
100
109
|
em,
|
|
101
110
|
SyncMapping,
|
|
102
111
|
{
|
|
103
112
|
id: parsedParams.data.id,
|
|
104
|
-
organizationId
|
|
113
|
+
organizationId,
|
|
105
114
|
tenantId: auth.tenantId,
|
|
106
115
|
},
|
|
107
116
|
undefined,
|
|
@@ -155,9 +164,13 @@ export async function PUT(req: Request, ctx: { params?: Promise<{ id?: string }>
|
|
|
155
164
|
|
|
156
165
|
export async function DELETE(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
|
|
157
166
|
const auth = await getAuthFromRequest(req)
|
|
158
|
-
if (!auth?.tenantId
|
|
167
|
+
if (!auth?.tenantId) {
|
|
159
168
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
160
169
|
}
|
|
170
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
171
|
+
if (!organizationId) {
|
|
172
|
+
return organizationScopeRequiredResponse()
|
|
173
|
+
}
|
|
161
174
|
|
|
162
175
|
const parsedParams = await resolveParams(ctx)
|
|
163
176
|
if (!parsedParams.success) {
|
|
@@ -166,14 +179,14 @@ export async function DELETE(req: Request, ctx: { params?: Promise<{ id?: string
|
|
|
166
179
|
|
|
167
180
|
const container = await createRequestContainer()
|
|
168
181
|
const em = container.resolve('em') as EntityManager
|
|
169
|
-
const scope = { organizationId
|
|
182
|
+
const scope = { organizationId, tenantId: auth.tenantId }
|
|
170
183
|
|
|
171
184
|
const mapping = await findOneWithDecryption(
|
|
172
185
|
em,
|
|
173
186
|
SyncMapping,
|
|
174
187
|
{
|
|
175
188
|
id: parsedParams.data.id,
|
|
176
|
-
organizationId
|
|
189
|
+
organizationId,
|
|
177
190
|
tenantId: auth.tenantId,
|
|
178
191
|
},
|
|
179
192
|
undefined,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
4
|
+
import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
4
5
|
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
5
6
|
import type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'
|
|
6
7
|
import { findAndCountWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
@@ -35,9 +36,13 @@ export const openApi = {
|
|
|
35
36
|
|
|
36
37
|
export async function GET(req: Request) {
|
|
37
38
|
const auth = await getAuthFromRequest(req)
|
|
38
|
-
if (!auth?.tenantId
|
|
39
|
+
if (!auth?.tenantId) {
|
|
39
40
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
40
41
|
}
|
|
42
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
43
|
+
if (!organizationId) {
|
|
44
|
+
return organizationScopeRequiredResponse()
|
|
45
|
+
}
|
|
41
46
|
|
|
42
47
|
const url = new URL(req.url)
|
|
43
48
|
const parsed = listMappingsQuerySchema.safeParse({
|
|
@@ -53,7 +58,7 @@ export async function GET(req: Request) {
|
|
|
53
58
|
|
|
54
59
|
const container = await createRequestContainer()
|
|
55
60
|
const em = container.resolve('em') as EntityManager
|
|
56
|
-
const scope = { organizationId
|
|
61
|
+
const scope = { organizationId, tenantId: auth.tenantId }
|
|
57
62
|
|
|
58
63
|
const where: FilterQuery<SyncMapping> = {
|
|
59
64
|
organizationId: scope.organizationId,
|
|
@@ -92,9 +97,13 @@ export async function GET(req: Request) {
|
|
|
92
97
|
|
|
93
98
|
export async function POST(req: Request) {
|
|
94
99
|
const auth = await getAuthFromRequest(req)
|
|
95
|
-
if (!auth?.tenantId
|
|
100
|
+
if (!auth?.tenantId) {
|
|
96
101
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
97
102
|
}
|
|
103
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
104
|
+
if (!organizationId) {
|
|
105
|
+
return organizationScopeRequiredResponse()
|
|
106
|
+
}
|
|
98
107
|
|
|
99
108
|
const payload = await req.json().catch(() => null)
|
|
100
109
|
const parsed = createMappingSchema.safeParse(payload)
|
|
@@ -104,7 +113,7 @@ export async function POST(req: Request) {
|
|
|
104
113
|
|
|
105
114
|
const container = await createRequestContainer()
|
|
106
115
|
const em = container.resolve('em') as EntityManager
|
|
107
|
-
const scope = { organizationId
|
|
116
|
+
const scope = { organizationId, tenantId: auth.tenantId }
|
|
108
117
|
|
|
109
118
|
const existing = await findOneWithDecryption(
|
|
110
119
|
em,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
3
|
+
import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
3
4
|
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
4
5
|
import { getAllIntegrations } from '@open-mercato/shared/modules/integrations/types'
|
|
5
6
|
import type { CredentialsService } from '../../integrations/lib/credentials-service'
|
|
@@ -17,14 +18,18 @@ export const openApi = {
|
|
|
17
18
|
|
|
18
19
|
export async function GET(req: Request) {
|
|
19
20
|
const auth = await getAuthFromRequest(req)
|
|
20
|
-
if (!auth?.tenantId
|
|
21
|
+
if (!auth?.tenantId) {
|
|
21
22
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
22
23
|
}
|
|
24
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
25
|
+
if (!organizationId) {
|
|
26
|
+
return organizationScopeRequiredResponse()
|
|
27
|
+
}
|
|
23
28
|
|
|
24
29
|
const container = await createRequestContainer()
|
|
25
30
|
const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService
|
|
26
31
|
const stateService = container.resolve('integrationStateService') as IntegrationStateService
|
|
27
|
-
const scope = { organizationId
|
|
32
|
+
const scope = { organizationId, tenantId: auth.tenantId }
|
|
28
33
|
|
|
29
34
|
const items = await Promise.all(
|
|
30
35
|
getAllIntegrations()
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
3
|
+
import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
3
4
|
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
4
5
|
import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
|
|
5
6
|
import { getIntegration } from '@open-mercato/shared/modules/integrations/types'
|
|
@@ -29,9 +30,13 @@ export const openApi = {
|
|
|
29
30
|
export async function POST(req: Request) {
|
|
30
31
|
try {
|
|
31
32
|
const auth = await getAuthFromRequest(req)
|
|
32
|
-
if (!auth?.tenantId
|
|
33
|
+
if (!auth?.tenantId) {
|
|
33
34
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
34
35
|
}
|
|
36
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
37
|
+
if (!organizationId) {
|
|
38
|
+
return organizationScopeRequiredResponse()
|
|
39
|
+
}
|
|
35
40
|
|
|
36
41
|
const payload = await readJsonSafe(req)
|
|
37
42
|
const parsed = runSyncSchema.safeParse(payload)
|
|
@@ -45,7 +50,7 @@ export async function POST(req: Request) {
|
|
|
45
50
|
const integrationStateService = container.resolve('integrationStateService') as IntegrationStateService
|
|
46
51
|
|
|
47
52
|
const scope = {
|
|
48
|
-
organizationId
|
|
53
|
+
organizationId,
|
|
49
54
|
tenantId: auth.tenantId,
|
|
50
55
|
}
|
|
51
56
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
4
|
+
import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
4
5
|
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
5
6
|
import type { IntegrationLogService } from '../../../../integrations/lib/log-service'
|
|
6
7
|
import type { IntegrationStateService } from '../../../../integrations/lib/state-service'
|
|
@@ -24,9 +25,13 @@ export const openApi = {
|
|
|
24
25
|
|
|
25
26
|
export async function POST(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
|
|
26
27
|
const auth = await getAuthFromRequest(req)
|
|
27
|
-
if (!auth?.tenantId
|
|
28
|
+
if (!auth?.tenantId) {
|
|
28
29
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
29
30
|
}
|
|
31
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
32
|
+
if (!organizationId) {
|
|
33
|
+
return organizationScopeRequiredResponse()
|
|
34
|
+
}
|
|
30
35
|
|
|
31
36
|
const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')
|
|
32
37
|
? await (ctx.params as Promise<{ id?: string }>)
|
|
@@ -42,7 +47,7 @@ export async function POST(req: Request, ctx: { params?: Promise<{ id?: string }
|
|
|
42
47
|
const progressService = container.resolve('progressService') as ProgressService
|
|
43
48
|
const integrationLogService = container.resolve('integrationLogService') as IntegrationLogService
|
|
44
49
|
const integrationStateService = container.resolve('integrationStateService') as IntegrationStateService
|
|
45
|
-
const scope = { organizationId
|
|
50
|
+
const scope = { organizationId, tenantId: auth.tenantId }
|
|
46
51
|
|
|
47
52
|
const run = await syncRunService.getRun(parsed.data.id, scope)
|
|
48
53
|
if (!run) {
|
|
@@ -69,7 +74,7 @@ export async function POST(req: Request, ctx: { params?: Promise<{ id?: string }
|
|
|
69
74
|
|
|
70
75
|
const progressCtx = {
|
|
71
76
|
tenantId: auth.tenantId,
|
|
72
|
-
organizationId
|
|
77
|
+
organizationId,
|
|
73
78
|
userId: auth.sub,
|
|
74
79
|
}
|
|
75
80
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
4
|
+
import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
4
5
|
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
5
6
|
import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
|
|
6
7
|
import type { ProgressService } from '../../../../progress/lib/progressService'
|
|
@@ -25,9 +26,13 @@ export const openApi = {
|
|
|
25
26
|
|
|
26
27
|
export async function POST(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
|
|
27
28
|
const auth = await getAuthFromRequest(req)
|
|
28
|
-
if (!auth?.tenantId
|
|
29
|
+
if (!auth?.tenantId) {
|
|
29
30
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
30
31
|
}
|
|
32
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
33
|
+
if (!organizationId) {
|
|
34
|
+
return organizationScopeRequiredResponse()
|
|
35
|
+
}
|
|
31
36
|
|
|
32
37
|
const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')
|
|
33
38
|
? await (ctx.params as Promise<{ id?: string }>)
|
|
@@ -47,7 +52,7 @@ export async function POST(req: Request, ctx: { params?: Promise<{ id?: string }
|
|
|
47
52
|
const container = await createRequestContainer()
|
|
48
53
|
const syncRunService = container.resolve('dataSyncRunService') as SyncRunService
|
|
49
54
|
const progressService = container.resolve('progressService') as ProgressService
|
|
50
|
-
const scope = { organizationId
|
|
55
|
+
const scope = { organizationId, tenantId: auth.tenantId }
|
|
51
56
|
|
|
52
57
|
const previous = await syncRunService.getRun(parsedParams.data.id, scope)
|
|
53
58
|
if (!previous) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
4
|
+
import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
4
5
|
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
5
6
|
import type { ProgressService } from '../../../../progress/lib/progressService'
|
|
6
7
|
import type { SyncRunService } from '../../../lib/sync-run-service'
|
|
@@ -18,9 +19,13 @@ export const openApi = {
|
|
|
18
19
|
|
|
19
20
|
export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
|
|
20
21
|
const auth = await getAuthFromRequest(req)
|
|
21
|
-
if (!auth?.tenantId
|
|
22
|
+
if (!auth?.tenantId) {
|
|
22
23
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
23
24
|
}
|
|
25
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
26
|
+
if (!organizationId) {
|
|
27
|
+
return organizationScopeRequiredResponse()
|
|
28
|
+
}
|
|
24
29
|
|
|
25
30
|
const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')
|
|
26
31
|
? await (ctx.params as Promise<{ id?: string }>)
|
|
@@ -34,7 +39,7 @@ export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }>
|
|
|
34
39
|
const container = await createRequestContainer()
|
|
35
40
|
const syncRunService = container.resolve('dataSyncRunService') as SyncRunService
|
|
36
41
|
const progressService = container.resolve('progressService') as ProgressService
|
|
37
|
-
const scope = { organizationId
|
|
42
|
+
const scope = { organizationId, tenantId: auth.tenantId }
|
|
38
43
|
|
|
39
44
|
const run = await syncRunService.getRun(parsed.data.id, scope)
|
|
40
45
|
if (!run) {
|
|
@@ -44,7 +49,7 @@ export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }>
|
|
|
44
49
|
const progressJob = run.progressJobId
|
|
45
50
|
? await progressService.getJob(run.progressJobId, {
|
|
46
51
|
tenantId: auth.tenantId,
|
|
47
|
-
organizationId
|
|
52
|
+
organizationId,
|
|
48
53
|
userId: auth.sub,
|
|
49
54
|
})
|
|
50
55
|
: null
|