@open-mercato/core 0.10.1-develop.7761.1.9dfaf470ed → 0.10.1-develop.7763.1.caea616ebf

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/auth/api/profile/route.js +16 -2
  3. package/dist/modules/auth/api/profile/route.js.map +2 -2
  4. package/dist/modules/auth/lib/userDataSubject.js +26 -0
  5. package/dist/modules/auth/lib/userDataSubject.js.map +7 -0
  6. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +1 -0
  7. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
  8. package/dist/modules/customers/api/companies/[id]/route.js +3 -2
  9. package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
  10. package/dist/modules/customers/api/deals/[id]/route.js +11 -12
  11. package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
  12. package/dist/modules/customers/api/people/[id]/route.js +3 -2
  13. package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
  14. package/dist/modules/customers/backend/customers/companies/create/page.js +6 -0
  15. package/dist/modules/customers/backend/customers/companies/create/page.js.map +2 -2
  16. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +25 -25
  17. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  18. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.js +8 -27
  19. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.js.map +2 -2
  20. package/dist/modules/customers/backend/customers/deals/[id]/page.js +175 -171
  21. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  22. package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js +25 -24
  23. package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js.map +2 -2
  24. package/dist/modules/customers/backend/customers/people/create/page.js +9 -0
  25. package/dist/modules/customers/backend/customers/people/create/page.js.map +2 -2
  26. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +140 -144
  27. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  28. package/dist/modules/customers/components/detail/CompanyDetailHeader.js +2 -0
  29. package/dist/modules/customers/components/detail/CompanyDetailHeader.js.map +2 -2
  30. package/dist/modules/customers/components/detail/CompanyDetailTabs.js +13 -4
  31. package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
  32. package/dist/modules/customers/components/detail/CreatePersonDialog.js +13 -3
  33. package/dist/modules/customers/components/detail/CreatePersonDialog.js.map +2 -2
  34. package/dist/modules/customers/components/detail/CustomerDetailSidebar.js +29 -0
  35. package/dist/modules/customers/components/detail/CustomerDetailSidebar.js.map +7 -0
  36. package/dist/modules/customers/components/detail/DealDetailHeader.js +4 -2
  37. package/dist/modules/customers/components/detail/DealDetailHeader.js.map +2 -2
  38. package/dist/modules/customers/components/detail/DealDetailTabs.js +9 -1
  39. package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
  40. package/dist/modules/customers/components/detail/DealForm.js +5 -0
  41. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  42. package/dist/modules/customers/components/detail/PersonDetailHeader.js +2 -0
  43. package/dist/modules/customers/components/detail/PersonDetailHeader.js.map +2 -2
  44. package/dist/modules/customers/components/detail/PersonDetailTabs.js +9 -1
  45. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
  46. package/dist/modules/customers/components/detail/create/CreateDealForm.js +160 -176
  47. package/dist/modules/customers/components/detail/create/CreateDealForm.js.map +2 -2
  48. package/dist/modules/customers/components/detail/useCustomerInjectedTabs.js +47 -0
  49. package/dist/modules/customers/components/detail/useCustomerInjectedTabs.js.map +7 -0
  50. package/dist/modules/customers/components/formConfig.js +3 -0
  51. package/dist/modules/customers/components/formConfig.js.map +2 -2
  52. package/dist/modules/customers/extension-points.js +14 -4
  53. package/dist/modules/customers/extension-points.js.map +2 -2
  54. package/dist/modules/customers/lib/detailResponseEnrichment.js +38 -0
  55. package/dist/modules/customers/lib/detailResponseEnrichment.js.map +7 -0
  56. package/dist/modules/dashboards/api/layout/[itemId]/route.js +11 -4
  57. package/dist/modules/dashboards/api/layout/[itemId]/route.js.map +2 -2
  58. package/dist/modules/dashboards/api/layout/route.js +25 -13
  59. package/dist/modules/dashboards/api/layout/route.js.map +2 -2
  60. package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js +4 -4
  61. package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js.map +2 -2
  62. package/package.json +7 -7
  63. package/src/modules/auth/api/profile/route.ts +15 -1
  64. package/src/modules/auth/lib/userDataSubject.ts +30 -0
  65. package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +2 -0
  66. package/src/modules/customers/api/companies/[id]/route.ts +3 -2
  67. package/src/modules/customers/api/deals/[id]/route.ts +12 -12
  68. package/src/modules/customers/api/people/[id]/route.ts +3 -2
  69. package/src/modules/customers/backend/customers/companies/create/page.tsx +6 -0
  70. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +27 -30
  71. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.tsx +9 -44
  72. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +7 -3
  73. package/src/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.tsx +25 -27
  74. package/src/modules/customers/backend/customers/people/create/page.tsx +9 -0
  75. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +21 -33
  76. package/src/modules/customers/components/detail/CompanyDetailHeader.tsx +3 -0
  77. package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +15 -4
  78. package/src/modules/customers/components/detail/CreatePersonDialog.tsx +15 -4
  79. package/src/modules/customers/components/detail/CustomerDetailSidebar.tsx +41 -0
  80. package/src/modules/customers/components/detail/DealDetailHeader.tsx +4 -1
  81. package/src/modules/customers/components/detail/DealDetailTabs.tsx +11 -1
  82. package/src/modules/customers/components/detail/DealForm.tsx +5 -0
  83. package/src/modules/customers/components/detail/PersonDetailHeader.tsx +3 -0
  84. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +11 -1
  85. package/src/modules/customers/components/detail/create/CreateDealForm.tsx +126 -209
  86. package/src/modules/customers/components/detail/useCustomerInjectedTabs.tsx +64 -0
  87. package/src/modules/customers/components/formConfig.tsx +3 -0
  88. package/src/modules/customers/extension-points.ts +14 -4
  89. package/src/modules/customers/lib/detailResponseEnrichment.ts +53 -0
  90. package/src/modules/dashboards/api/layout/[itemId]/route.ts +12 -4
  91. package/src/modules/dashboards/api/layout/route.ts +25 -12
  92. package/src/modules/integrations/widgets/injection/external-ids/widget.client.tsx +4 -4
@@ -9,6 +9,8 @@ import { resolveAllowedWidgetIds } from '@open-mercato/core/modules/dashboards/l
9
9
  import { authorizeFeatures } from '@open-mercato/shared/security/featurePolicy'
10
10
  import { User } from '@open-mercato/core/modules/auth/data/entities'
11
11
  import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
12
+ import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
13
+ import { resolveUserDataSubject } from '@open-mercato/core/modules/auth/lib/userDataSubject'
12
14
  import {
13
15
  runCrudMutationGuardAfterSuccess,
14
16
  validateCrudMutationGuard,
@@ -80,15 +82,19 @@ export async function GET(req: Request) {
80
82
  // Use a fresh fork to avoid carrying over pending entities from other operations
81
83
  const em = (container.resolve('em') as any).fork({ clear: true, freshEventManager: true, useContext: true })
82
84
  const rbac = container.resolve('rbacService') as any
83
- const url = new URL(req.url)
85
+ const userId = await resolveUserDataSubject(em, auth)
86
+ if (!userId) {
87
+ const { translate } = await resolveTranslations()
88
+ return NextResponse.json({ error: translate('api.errors.forbidden', 'Forbidden') }, { status: 403 })
89
+ }
84
90
 
85
91
  const scope: LayoutScope = {
86
- userId: String(auth.sub),
92
+ userId,
87
93
  tenantId: auth.tenantId ?? null,
88
94
  organizationId: auth.orgId ?? null,
89
95
  }
90
96
 
91
- const effectiveFeatures = await rbac.getEffectiveFeatures(scope.userId, {
97
+ const effectiveFeatures = await rbac.getEffectiveFeatures(auth.sub, {
92
98
  tenantId: scope.tenantId,
93
99
  organizationId: scope.organizationId,
94
100
  })
@@ -128,7 +134,7 @@ export async function GET(req: Request) {
128
134
  size: widget.metadata.defaultSize ?? DEFAULT_SIZE,
129
135
  settings: widget.metadata.defaultSettings ?? undefined,
130
136
  }))
131
- if (hasRegisteredWidgets) {
137
+ if (hasRegisteredWidgets && !auth.isApiKey) {
132
138
  layout = em.create(DashboardLayout, {
133
139
  userId: scope.userId,
134
140
  tenantId: scope.tenantId,
@@ -138,7 +144,7 @@ export async function GET(req: Request) {
138
144
  em.persist(layout)
139
145
  hasChanged = true
140
146
  }
141
- } else if (hasRegisteredWidgets) {
147
+ } else if (hasRegisteredWidgets || auth.isApiKey) {
142
148
  const existingLayout = layout
143
149
  const filtered = items.filter((item) => allowedIds.includes(item.widgetId))
144
150
  if (filtered.length !== items.length) {
@@ -152,11 +158,11 @@ export async function GET(req: Request) {
152
158
  ) {
153
159
  hasChanged = true
154
160
  }
155
- existingLayout.layoutJson = items
161
+ if (!auth.isApiKey) existingLayout.layoutJson = items
156
162
  layout = existingLayout
157
163
  }
158
164
 
159
- if (hasChanged) {
165
+ if (hasChanged && !auth.isApiKey) {
160
166
  await em.flush()
161
167
  }
162
168
 
@@ -231,14 +237,20 @@ export async function PUT(req: Request) {
231
237
  const em = (resolve('em') as any).fork({ clear: true, freshEventManager: true, useContext: true })
232
238
  const rbac = resolve('rbacService') as any
233
239
 
240
+ const userId = await resolveUserDataSubject(em, auth)
241
+ if (!userId) {
242
+ const { translate } = await resolveTranslations()
243
+ return NextResponse.json({ error: translate('api.errors.forbidden', 'Forbidden') }, { status: 403 })
244
+ }
245
+
234
246
  const scope: LayoutScope = {
235
- userId: String(auth.sub),
247
+ userId,
236
248
  tenantId: auth.tenantId ?? null,
237
249
  organizationId: auth.orgId ?? null,
238
250
  }
239
251
 
240
252
  const canConfigure = await rbac.userHasAllFeatures(
241
- scope.userId,
253
+ auth.sub,
242
254
  ['dashboards.configure'],
243
255
  { tenantId: scope.tenantId, organizationId: scope.organizationId },
244
256
  )
@@ -249,7 +261,7 @@ export async function PUT(req: Request) {
249
261
  const guardResult = await validateCrudMutationGuard(container, {
250
262
  tenantId: scope.tenantId ?? '',
251
263
  organizationId: scope.organizationId,
252
- userId: scope.userId,
264
+ userId: auth.sub,
253
265
  resourceKind: RESOURCE_KIND,
254
266
  resourceId: scope.userId,
255
267
  operation: 'update',
@@ -271,7 +283,7 @@ export async function PUT(req: Request) {
271
283
  if (widgets.length === 0) {
272
284
  return NextResponse.json({ error: 'Widget registry unavailable' }, { status: 503 })
273
285
  }
274
- const effectiveFeatures = await rbac.getEffectiveFeatures(scope.userId, {
286
+ const effectiveFeatures = await rbac.getEffectiveFeatures(auth.sub, {
275
287
  tenantId: scope.tenantId,
276
288
  organizationId: scope.organizationId,
277
289
  })
@@ -323,7 +335,7 @@ export async function PUT(req: Request) {
323
335
  await runCrudMutationGuardAfterSuccess(container, {
324
336
  tenantId: scope.tenantId ?? '',
325
337
  organizationId: scope.organizationId,
326
- userId: scope.userId,
338
+ userId: auth.sub,
327
339
  resourceKind: RESOURCE_KIND,
328
340
  resourceId: scope.userId,
329
341
  operation: 'update',
@@ -349,6 +361,7 @@ const layoutGetDoc: OpenApiMethodDoc = {
349
361
  ],
350
362
  errors: [
351
363
  { status: 401, description: 'Authentication required', schema: dashboardsErrorSchema },
364
+ { status: 403, description: 'No user binding in the authenticated scope', schema: dashboardsErrorSchema },
352
365
  ],
353
366
  }
354
367
 
@@ -22,7 +22,7 @@ function SyncStatusBadge({ status, lastSynced }: { status: ExternalIdMapping['sy
22
22
  const label = t(config.label, status)
23
23
 
24
24
  return (
25
- <span className="inline-flex items-center gap-1 text-xs text-muted-foreground">
25
+ <span className="inline-flex shrink-0 items-center gap-1 text-xs text-muted-foreground">
26
26
  <span className={cn('inline-block size-1.5 rounded-full', config.dot)} aria-hidden="true" />
27
27
  <span>{label}</span>
28
28
  {lastSynced && (
@@ -60,11 +60,11 @@ export default function ExternalIdsWidget({ data }: InjectionWidgetComponentProp
60
60
  key={integrationId}
61
61
  className="flex items-center justify-between gap-2 rounded-md bg-muted/50 px-3 py-2"
62
62
  >
63
- <div className="flex items-center gap-2 min-w-0">
63
+ <div className="flex min-w-0 flex-1 flex-wrap items-center gap-2">
64
64
  <span className="text-sm font-medium truncate">
65
65
  {getIntegrationTitle(integrationId)}
66
66
  </span>
67
- <code className="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-muted-foreground">
67
+ <code className="min-w-0 max-w-full break-all rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-muted-foreground">
68
68
  {mapping.externalId}
69
69
  </code>
70
70
  {mapping.externalUrl && (
@@ -72,7 +72,7 @@ export default function ExternalIdsWidget({ data }: InjectionWidgetComponentProp
72
72
  href={mapping.externalUrl}
73
73
  target="_blank"
74
74
  rel="noopener noreferrer"
75
- className="text-muted-foreground hover:text-foreground transition-colors"
75
+ className="shrink-0 text-muted-foreground hover:text-foreground transition-colors"
76
76
  aria-label={t('integrations.externalIds.openExternal', 'Open in external system')}
77
77
  >
78
78
  <ExternalLinkIcon />