@open-mercato/core 0.6.7-develop.6795.1.8a3f27921c → 0.6.7-develop.6824.1.21fff90682
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/customer_deal_person_link/index.js +2 -0
- package/dist/generated/entities/customer_deal_person_link/index.js.map +2 -2
- package/dist/generated/entities/customer_user_invitation/index.js +2 -0
- package/dist/generated/entities/customer_user_invitation/index.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +2 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/auth/lib/backendChrome.js +10 -9
- package/dist/modules/auth/lib/backendChrome.js.map +2 -2
- package/dist/modules/auth/lib/tenantAccess.js +7 -0
- package/dist/modules/auth/lib/tenantAccess.js.map +2 -2
- package/dist/modules/business_rules/api/openmercato-call-options/route.js +85 -0
- package/dist/modules/business_rules/api/openmercato-call-options/route.js.map +7 -0
- package/dist/modules/business_rules/api/rules/route.js +71 -4
- package/dist/modules/business_rules/api/rules/route.js.map +2 -2
- package/dist/modules/business_rules/components/ActionBuilder.js +47 -4
- package/dist/modules/business_rules/components/ActionBuilder.js.map +3 -3
- package/dist/modules/business_rules/components/ActionRow.js +106 -16
- package/dist/modules/business_rules/components/ActionRow.js.map +2 -2
- package/dist/modules/business_rules/components/utils/actionValidation.js +6 -0
- package/dist/modules/business_rules/components/utils/actionValidation.js.map +2 -2
- package/dist/modules/business_rules/lib/action-executor.js +148 -0
- package/dist/modules/business_rules/lib/action-executor.js.map +2 -2
- package/dist/modules/business_rules/lib/openmercato-call-options-types.js +5 -0
- package/dist/modules/business_rules/lib/openmercato-call-options-types.js.map +7 -0
- package/dist/modules/business_rules/lib/openmercato-call-options.js +231 -0
- package/dist/modules/business_rules/lib/openmercato-call-options.js.map +7 -0
- package/dist/modules/business_rules/lib/rule-engine.js +5 -1
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js +11 -1
- package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js +11 -6
- package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js.map +2 -2
- package/dist/modules/configs/lib/upgrade-actions.js +12 -0
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/users/[id].js +10 -1
- package/dist/modules/customer_accounts/api/admin/users/[id].js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/users-invite.js +61 -4
- package/dist/modules/customer_accounts/api/admin/users-invite.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users-invite.js +20 -2
- package/dist/modules/customer_accounts/api/portal/users-invite.js.map +2 -2
- package/dist/modules/customer_accounts/data/entities.js +3 -0
- package/dist/modules/customer_accounts/data/entities.js.map +2 -2
- package/dist/modules/customer_accounts/data/validators.js +1 -0
- package/dist/modules/customer_accounts/data/validators.js.map +2 -2
- package/dist/modules/customer_accounts/emails/CustomerInvitationEmail.js +26 -0
- package/dist/modules/customer_accounts/emails/CustomerInvitationEmail.js.map +7 -0
- package/dist/modules/customer_accounts/lib/customerEntityOwnership.js +29 -3
- package/dist/modules/customer_accounts/lib/customerEntityOwnership.js.map +2 -2
- package/dist/modules/customer_accounts/lib/customerUrl.js +19 -10
- package/dist/modules/customer_accounts/lib/customerUrl.js.map +2 -2
- package/dist/modules/customer_accounts/lib/invitationEmail.js +35 -0
- package/dist/modules/customer_accounts/lib/invitationEmail.js.map +7 -0
- package/dist/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.js +13 -0
- package/dist/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.js.map +7 -0
- package/dist/modules/customer_accounts/services/customerInvitationService.js +32 -2
- package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
- package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js +47 -7
- package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js.map +2 -2
- package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +2 -2
- package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
- package/dist/modules/customer_accounts/widgets/injection-table.js +1 -1
- package/dist/modules/customer_accounts/widgets/injection-table.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js +4 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/route.js +7 -3
- package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +11 -1
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +14 -8
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +21 -6
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +48 -10
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/people.js +2 -0
- package/dist/modules/customers/commands/people.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js +26 -6
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/DealDetailTabs.js +30 -8
- package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonDetailTabs.js +30 -8
- package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
- package/dist/modules/customers/data/entities.js +8 -0
- package/dist/modules/customers/data/entities.js.map +2 -2
- package/dist/modules/customers/data/validators.js +2 -1
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/migrations/Migration20260723210000_customers.js +15 -0
- package/dist/modules/customers/migrations/Migration20260723210000_customers.js.map +7 -0
- package/dist/modules/directory/api/tenants/route.js +8 -2
- package/dist/modules/directory/api/tenants/route.js.map +2 -2
- package/dist/modules/directory/commands/tenants.js +6 -0
- package/dist/modules/directory/commands/tenants.js.map +2 -2
- package/dist/modules/entities/api/entity-settings.js +59 -9
- package/dist/modules/entities/api/entity-settings.js.map +2 -2
- package/dist/modules/entities/backend/config/settings/page.js +10 -0
- package/dist/modules/entities/backend/config/settings/page.js.map +7 -0
- package/dist/modules/entities/backend/config/settings/page.meta.js +36 -0
- package/dist/modules/entities/backend/config/settings/page.meta.js.map +7 -0
- package/dist/modules/entities/backend/entities/user/create/page.js +16 -7
- package/dist/modules/entities/backend/entities/user/create/page.js.map +2 -2
- package/dist/modules/entities/components/EntitySettingsManager.js +136 -0
- package/dist/modules/entities/components/EntitySettingsManager.js.map +7 -0
- package/dist/modules/inbox_ops/api/webhook/inbound.js +14 -10
- package/dist/modules/inbox_ops/api/webhook/inbound.js.map +2 -2
- package/dist/modules/payment_gateways/api/sessions/route.js +1 -3
- package/dist/modules/payment_gateways/api/sessions/route.js.map +2 -2
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +11 -1
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/payment_gateways/data/entities.js +4 -0
- package/dist/modules/payment_gateways/data/entities.js.map +2 -2
- package/dist/modules/payment_gateways/lib/gateway-service.js +15 -6
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
- package/dist/modules/payment_gateways/lib/session-idempotency.js +33 -0
- package/dist/modules/payment_gateways/lib/session-idempotency.js.map +2 -2
- package/dist/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.js +18 -0
- package/dist/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.js.map +7 -0
- package/dist/modules/payment_gateways/setup.js +47 -0
- package/dist/modules/payment_gateways/setup.js.map +2 -2
- package/dist/modules/payment_gateways/workers/session-initialization-prune.js +50 -0
- package/dist/modules/payment_gateways/workers/session-initialization-prune.js.map +7 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js +134 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js.map +7 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.js +11 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.js.map +7 -0
- package/dist/modules/portal/lib/navigation.js +7 -0
- package/dist/modules/portal/lib/navigation.js.map +7 -0
- package/dist/modules/query_index/lib/engine.js +43 -0
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/query_index/lib/search-tokens.js +15 -5
- package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js +11 -1
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js.map +2 -2
- package/generated/entities/customer_deal_person_link/index.ts +1 -0
- package/generated/entities/customer_user_invitation/index.ts +1 -0
- package/generated/entity-fields-registry.ts +2 -0
- package/package.json +7 -7
- package/src/modules/auth/lib/backendChrome.tsx +15 -9
- package/src/modules/auth/lib/tenantAccess.ts +8 -0
- package/src/modules/business_rules/api/openmercato-call-options/route.ts +94 -0
- package/src/modules/business_rules/api/rules/route.ts +92 -4
- package/src/modules/business_rules/components/ActionBuilder.tsx +54 -5
- package/src/modules/business_rules/components/ActionRow.tsx +156 -18
- package/src/modules/business_rules/components/utils/actionValidation.ts +6 -0
- package/src/modules/business_rules/i18n/de.json +12 -0
- package/src/modules/business_rules/i18n/en.json +12 -0
- package/src/modules/business_rules/i18n/es.json +12 -0
- package/src/modules/business_rules/i18n/pl.json +12 -0
- package/src/modules/business_rules/lib/action-executor.ts +198 -0
- package/src/modules/business_rules/lib/openmercato-call-options-types.ts +31 -0
- package/src/modules/business_rules/lib/openmercato-call-options.ts +297 -0
- package/src/modules/business_rules/lib/rule-engine.ts +4 -0
- package/src/modules/communication_channels/api/post/webhook/[provider]/route.ts +11 -1
- package/src/modules/communication_channels/api/post/webhooks/gmail/route.ts +17 -11
- package/src/modules/configs/lib/upgrade-actions.ts +14 -0
- package/src/modules/customer_accounts/api/admin/users/[id].ts +16 -1
- package/src/modules/customer_accounts/api/admin/users-invite.ts +78 -3
- package/src/modules/customer_accounts/api/portal/users-invite.ts +22 -1
- package/src/modules/customer_accounts/data/entities.ts +3 -0
- package/src/modules/customer_accounts/data/validators.ts +1 -0
- package/src/modules/customer_accounts/emails/CustomerInvitationEmail.tsx +45 -0
- package/src/modules/customer_accounts/i18n/de.json +6 -0
- package/src/modules/customer_accounts/i18n/en.json +6 -0
- package/src/modules/customer_accounts/i18n/es.json +6 -0
- package/src/modules/customer_accounts/i18n/pl.json +6 -0
- package/src/modules/customer_accounts/lib/customerEntityOwnership.ts +68 -2
- package/src/modules/customer_accounts/lib/customerUrl.ts +27 -11
- package/src/modules/customer_accounts/lib/invitationEmail.ts +42 -0
- package/src/modules/customer_accounts/migrations/.snapshot-open-mercato.json +16 -0
- package/src/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.ts +13 -0
- package/src/modules/customer_accounts/services/customerInvitationService.ts +56 -3
- package/src/modules/customer_accounts/subscribers/autoLinkCrm.ts +75 -8
- package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +2 -2
- package/src/modules/customer_accounts/widgets/injection-table.ts +4 -1
- package/src/modules/customers/api/deals/[id]/people/route.ts +3 -0
- package/src/modules/customers/api/deals/[id]/route.ts +10 -2
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +12 -1
- package/src/modules/customers/backend/customers/deals/[id]/hooks/types.ts +1 -0
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +15 -9
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +24 -6
- package/src/modules/customers/commands/deals.ts +50 -9
- package/src/modules/customers/commands/people.ts +3 -0
- package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +30 -7
- package/src/modules/customers/components/detail/DealDetailTabs.tsx +34 -9
- package/src/modules/customers/components/detail/PersonDetailTabs.tsx +34 -9
- package/src/modules/customers/data/entities.ts +9 -1
- package/src/modules/customers/data/validators.ts +1 -0
- package/src/modules/customers/i18n/de.json +1 -0
- package/src/modules/customers/i18n/en.json +1 -0
- package/src/modules/customers/i18n/es.json +1 -0
- package/src/modules/customers/i18n/pl.json +1 -0
- package/src/modules/customers/migrations/.snapshot-open-mercato.json +27 -1
- package/src/modules/customers/migrations/Migration20260723210000_customers.ts +15 -0
- package/src/modules/directory/api/tenants/route.ts +9 -1
- package/src/modules/directory/commands/tenants.ts +6 -0
- package/src/modules/entities/api/entity-settings.ts +66 -22
- package/src/modules/entities/backend/config/settings/page.meta.ts +34 -0
- package/src/modules/entities/backend/config/settings/page.tsx +12 -0
- package/src/modules/entities/backend/entities/user/create/page.tsx +16 -7
- package/src/modules/entities/components/EntitySettingsManager.tsx +160 -0
- package/src/modules/entities/i18n/de.json +9 -0
- package/src/modules/entities/i18n/en.json +9 -0
- package/src/modules/entities/i18n/es.json +9 -0
- package/src/modules/entities/i18n/pl.json +9 -0
- package/src/modules/inbox_ops/api/webhook/inbound.ts +14 -12
- package/src/modules/payment_gateways/api/sessions/route.ts +1 -3
- package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +13 -1
- package/src/modules/payment_gateways/data/entities.ts +5 -0
- package/src/modules/payment_gateways/i18n/de.json +5 -1
- package/src/modules/payment_gateways/i18n/en.json +5 -1
- package/src/modules/payment_gateways/i18n/es.json +5 -1
- package/src/modules/payment_gateways/i18n/pl.json +5 -1
- package/src/modules/payment_gateways/lib/gateway-service.ts +17 -8
- package/src/modules/payment_gateways/lib/session-idempotency.ts +36 -0
- package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +10 -1
- package/src/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.ts +17 -0
- package/src/modules/payment_gateways/setup.ts +62 -0
- package/src/modules/payment_gateways/workers/session-initialization-prune.ts +63 -0
- package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.ts +9 -0
- package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.tsx +164 -0
- package/src/modules/portal/i18n/de.json +18 -0
- package/src/modules/portal/i18n/en.json +18 -0
- package/src/modules/portal/i18n/es.json +18 -0
- package/src/modules/portal/i18n/pl.json +18 -0
- package/src/modules/portal/lib/navigation.ts +3 -0
- package/src/modules/query_index/lib/engine.ts +52 -0
- package/src/modules/query_index/lib/search-tokens.ts +16 -4
- package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +11 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/customer_accounts/api/admin/users/%5Bid%5D.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc, OpenApiMethodDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'\nimport { CustomerUser, CustomerUserRole, CustomerRole, CustomerUserSession } from '@open-mercato/core/modules/customer_accounts/data/entities'\nimport { CustomerUserService } from '@open-mercato/core/modules/customer_accounts/services/customerUserService'\nimport { CustomerSessionService } from '@open-mercato/core/modules/customer_accounts/services/customerSessionService'\nimport { CustomerRbacService } from '@open-mercato/core/modules/customer_accounts/services/customerRbacService'\nimport { adminUpdateUserSchema } from '@open-mercato/core/modules/customer_accounts/data/validators'\nimport { emitCustomerAccountsEvent } from '@open-mercato/core/modules/customer_accounts/events'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { isOwnedCompanyEntity } from '@open-mercato/core/modules/customer_accounts/lib/customerEntityOwnership'\nimport { enforceCommandOptimisticLockWithGuards } from '@open-mercato/shared/lib/crud/optimistic-lock-command'\nimport { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\n\nexport const metadata = {}\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\n\nexport async function GET(req: Request, { params }: { params: { id: string } }) {\n if (!UUID_RE.test(params.id)) {\n return NextResponse.json({ ok: false, error: 'Invalid user ID' }, { status: 400 })\n }\n\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ ok: false, error: 'Authentication required' }, { status: 401 })\n }\n\n const container = await createRequestContainer()\n const rbacService = container.resolve('rbacService') as RbacService\n const hasAccess = await rbacService.userHasAllFeatures(auth.sub, ['customer_accounts.view'], { tenantId: auth.tenantId, organizationId: auth.orgId })\n if (!hasAccess) {\n return NextResponse.json({ ok: false, error: 'Insufficient permissions' }, { status: 403 })\n }\n\n const em = container.resolve('em') as import('@mikro-orm/postgresql').EntityManager\n\n const user = await findOneWithDecryption(\n em,\n CustomerUser,\n { id: params.id, tenantId: auth.tenantId, organizationId: auth.orgId, deletedAt: null } as any,\n undefined,\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n )\n if (!user) {\n return NextResponse.json({ ok: false, error: 'User not found' }, { status: 404 })\n }\n\n const userRoles = await findWithDecryption(\n em,\n CustomerUserRole,\n { user: user.id as any, deletedAt: null } as any,\n { populate: ['role'] },\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n )\n const roles = userRoles.map((ur) => ({\n id: (ur.role as any).id,\n name: (ur.role as any).name,\n slug: (ur.role as any).slug,\n }))\n\n const activeSessions = await findWithDecryption(\n em,\n CustomerUserSession,\n {\n user: user.id as any,\n deletedAt: null,\n expiresAt: { $gt: new Date() },\n } as any,\n { orderBy: { lastUsedAt: 'DESC' } },\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n )\n\n const sessions = activeSessions.map((session) => ({\n id: session.id,\n ipAddress: (session as any).ipAddress || null,\n userAgent: (session as any).userAgent || null,\n lastUsedAt: (session as any).lastUsedAt || null,\n createdAt: session.createdAt,\n expiresAt: session.expiresAt,\n }))\n\n return NextResponse.json({\n ok: true,\n id: user.id,\n email: user.email,\n displayName: user.displayName,\n emailVerifiedAt: user.emailVerifiedAt || null,\n isActive: user.isActive,\n lockedUntil: user.lockedUntil || null,\n lastLoginAt: user.lastLoginAt || null,\n customerEntityId: user.customerEntityId || null,\n personEntityId: user.personEntityId || null,\n createdAt: user.createdAt,\n updatedAt: user.updatedAt || null,\n roles,\n sessions,\n })\n}\n\nexport async function PUT(req: Request, { params }: { params: { id: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ ok: false, error: 'Authentication required' }, { status: 401 })\n }\n\n const container = await createRequestContainer()\n const rbacService = container.resolve('rbacService') as RbacService\n const hasAccess = await rbacService.userHasAllFeatures(auth.sub, ['customer_accounts.manage'], { tenantId: auth.tenantId, organizationId: auth.orgId })\n if (!hasAccess) {\n return NextResponse.json({ ok: false, error: 'Insufficient permissions' }, { status: 403 })\n }\n\n let body: unknown\n try {\n body = await req.json()\n } catch {\n return NextResponse.json({ ok: false, error: 'Invalid request body' }, { status: 400 })\n }\n\n const parsed = adminUpdateUserSchema.safeParse(body)\n if (!parsed.success) {\n return NextResponse.json({ ok: false, error: 'Validation failed', details: parsed.error.flatten().fieldErrors }, { status: 400 })\n }\n\n const em = container.resolve('em') as import('@mikro-orm/postgresql').EntityManager\n\n const user = await findOneWithDecryption(\n em,\n CustomerUser,\n { id: params.id, tenantId: auth.tenantId, organizationId: auth.orgId, deletedAt: null } as any,\n undefined,\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n )\n if (!user) {\n return NextResponse.json({ ok: false, error: 'User not found' }, { status: 404 })\n }\n\n // Optimistic lock: refuse a stale overwrite so two admins editing the same\n // customer user in parallel cannot silently clobber each other (#2055). The\n // check is strictly additive \u2014 a no-op when the client sends no expected-version header.\n try {\n await enforceCommandOptimisticLockWithGuards(container, {\n resourceKind: 'customer_accounts.user',\n resourceId: user.id,\n current: user.updatedAt ?? null,\n request: req,\n })\n } catch (err) {\n if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })\n throw err\n }\n\n // Reject a customerEntityId the caller does not own before persisting it.\n // Without this check a mislinked company FK cross-links the user into another\n // org/company's portal context and persists indefinitely (#2693). A null value\n // (unlink) needs no ownership check.\n if (parsed.data.customerEntityId) {\n const owned = await isOwnedCompanyEntity(em, parsed.data.customerEntityId, {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n })\n if (!owned) {\n return NextResponse.json({ ok: false, error: 'Company not found' }, { status: 400 })\n }\n }\n\n // Always bump updated_at so the optimistic-lock version advances on every save.\n // `nativeUpdate` bypasses MikroORM's `onUpdate` hook, so set it explicitly \u2014 without\n // this the version never changes and concurrent edits cannot be detected (#2055).\n const nextUpdatedAt = new Date()\n const updates: Record<string, unknown> = { updatedAt: nextUpdatedAt }\n if (parsed.data.displayName !== undefined) updates.displayName = parsed.data.displayName\n if (parsed.data.isActive !== undefined) updates.isActive = parsed.data.isActive\n if (parsed.data.lockedUntil !== undefined) updates.lockedUntil = parsed.data.lockedUntil ? new Date(parsed.data.lockedUntil) : null\n if (parsed.data.personEntityId !== undefined) updates.personEntityId = parsed.data.personEntityId\n if (parsed.data.customerEntityId !== undefined) updates.customerEntityId = parsed.data.customerEntityId\n\n await em.nativeUpdate(CustomerUser, {\n id: user.id,\n tenantId: user.tenantId,\n organizationId: user.organizationId,\n }, updates)\n\n let rolesChanged = false\n if (parsed.data.roleIds !== undefined) {\n const requestedRoleIds = parsed.data.roleIds\n // Scope role resolution to the caller's organization too \u2014 CustomerRole is\n // org-scoped, so a tenant-only filter would let an admin link roles from\n // another org in the same tenant (#2693).\n const validRoles = requestedRoleIds.length > 0\n ? await findWithDecryption(\n em,\n CustomerRole,\n {\n id: { $in: requestedRoleIds } as any,\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n deletedAt: null,\n } as any,\n undefined,\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n )\n : []\n if (validRoles.length !== requestedRoleIds.length) {\n const foundIds = new Set(validRoles.map((role) => role.id))\n const missingId = requestedRoleIds.find((roleId) => !foundIds.has(roleId))\n return NextResponse.json({ ok: false, error: `Role ${missingId} not found` }, { status: 400 })\n }\n\n await em.nativeDelete(CustomerUserRole, { user: user.id } as Record<string, unknown>)\n\n for (const role of validRoles) {\n const userRole = em.create(CustomerUserRole, {\n user,\n role,\n createdAt: new Date(),\n } as any)\n em.persist(userRole)\n }\n await em.flush()\n rolesChanged = true\n }\n\n if (rolesChanged) {\n const customerRbacService = container.resolve('customerRbacService') as CustomerRbacService\n await customerRbacService.invalidateUserCache(user.id)\n }\n\n void emitCustomerAccountsEvent('customer_accounts.user.updated', {\n id: user.id,\n recipientUserId: user.id,\n email: user.email,\n tenantId: user.tenantId,\n organizationId: user.organizationId,\n updatedBy: auth.sub,\n }).catch(() => undefined)\n\n return NextResponse.json({ ok: true, updatedAt: nextUpdatedAt.toISOString() })\n}\n\nexport async function DELETE(req: Request, { params }: { params: { id: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ ok: false, error: 'Authentication required' }, { status: 401 })\n }\n\n const container = await createRequestContainer()\n const rbacService = container.resolve('rbacService') as RbacService\n const hasAccess = await rbacService.userHasAllFeatures(auth.sub, ['customer_accounts.manage'], { tenantId: auth.tenantId, organizationId: auth.orgId })\n if (!hasAccess) {\n return NextResponse.json({ ok: false, error: 'Insufficient permissions' }, { status: 403 })\n }\n\n const em = container.resolve('em') as import('@mikro-orm/postgresql').EntityManager\n\n const user = await findOneWithDecryption(\n em,\n CustomerUser,\n { id: params.id, tenantId: auth.tenantId, organizationId: auth.orgId, deletedAt: null } as any,\n undefined,\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n )\n if (!user) {\n return NextResponse.json({ ok: false, error: 'User not found' }, { status: 404 })\n }\n\n // Optimistic lock: refuse a stale delete (e.g. deleting a record another admin\n // already modified). Strictly additive \u2014 a no-op without the expected-version header.\n try {\n await enforceCommandOptimisticLockWithGuards(container, {\n resourceKind: 'customer_accounts.user',\n resourceId: user.id,\n current: user.updatedAt ?? null,\n request: req,\n })\n } catch (err) {\n if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })\n throw err\n }\n\n const customerUserService = container.resolve('customerUserService') as CustomerUserService\n const customerSessionService = container.resolve('customerSessionService') as CustomerSessionService\n\n await customerUserService.softDelete(user.id, {\n tenantId: user.tenantId,\n organizationId: user.organizationId,\n })\n await customerSessionService.revokeAllUserSessions(user.id)\n\n void emitCustomerAccountsEvent('customer_accounts.user.deleted', {\n id: user.id,\n email: user.email,\n tenantId: user.tenantId,\n organizationId: user.organizationId,\n deletedBy: auth.sub,\n }).catch(() => undefined)\n\n return NextResponse.json({ ok: true })\n}\n\nconst roleSchema = z.object({ id: z.string().uuid(), name: z.string(), slug: z.string() })\nconst userDetailSchema = z.object({\n id: z.string().uuid(),\n email: z.string(),\n displayName: z.string(),\n emailVerified: z.boolean(),\n isActive: z.boolean(),\n lockedUntil: z.string().datetime().nullable(),\n lastLoginAt: z.string().datetime().nullable(),\n failedLoginAttempts: z.number(),\n customerEntityId: z.string().uuid().nullable(),\n personEntityId: z.string().uuid().nullable(),\n createdAt: z.string().datetime(),\n updatedAt: z.string().datetime().nullable(),\n roles: z.array(roleSchema),\n activeSessionCount: z.number(),\n})\n\nconst successSchema = z.object({ ok: z.literal(true) })\nconst errorSchema = z.object({ ok: z.literal(false), error: z.string() })\n\nconst getMethodDoc: OpenApiMethodDoc = {\n summary: 'Get customer user detail (admin)',\n description: 'Returns full customer user details including CRM links, roles, and active session count.',\n tags: ['Customer Accounts Admin'],\n responses: [{\n status: 200,\n description: 'User detail',\n schema: z.object({ ok: z.literal(true), user: userDetailSchema }),\n }],\n errors: [\n { status: 401, description: 'Not authenticated', schema: errorSchema },\n { status: 403, description: 'Insufficient permissions', schema: errorSchema },\n { status: 404, description: 'User not found', schema: errorSchema },\n ],\n}\n\nconst putMethodDoc: OpenApiMethodDoc = {\n summary: 'Update customer user (admin)',\n description: 'Updates a customer user. Staff can update status, lock, CRM links, and roles. Role assignment bypasses customer_assignable check.',\n tags: ['Customer Accounts Admin'],\n requestBody: { schema: adminUpdateUserSchema },\n responses: [{ status: 200, description: 'User updated', schema: successSchema }],\n errors: [\n { status: 400, description: 'Validation failed or role not found', schema: errorSchema },\n { status: 401, description: 'Not authenticated', schema: errorSchema },\n { status: 403, description: 'Insufficient permissions', schema: errorSchema },\n { status: 404, description: 'User not found', schema: errorSchema },\n ],\n}\n\nconst deleteMethodDoc: OpenApiMethodDoc = {\n summary: 'Delete customer user (admin)',\n description: 'Soft deletes a customer user and revokes all their active sessions.',\n tags: ['Customer Accounts Admin'],\n responses: [{ status: 200, description: 'User deleted', schema: successSchema }],\n errors: [\n { status: 401, description: 'Not authenticated', schema: errorSchema },\n { status: 403, description: 'Insufficient permissions', schema: errorSchema },\n { status: 404, description: 'User not found', schema: errorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n summary: 'Customer user detail management (admin)',\n pathParams: z.object({ id: z.string().uuid() }),\n methods: {\n GET: getMethodDoc,\n PUT: putMethodDoc,\n DELETE: deleteMethodDoc,\n },\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAElB,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AAEvC,SAAS,cAAc,kBAAkB,cAAc,2BAA2B;AAIlF,SAAS,6BAA6B;AACtC,SAAS,iCAAiC;AAC1C,SAAS,uBAAuB,0BAA0B;AAC1D,SAAS,
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc, OpenApiMethodDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'\nimport { CustomerUser, CustomerUserRole, CustomerRole, CustomerUserSession } from '@open-mercato/core/modules/customer_accounts/data/entities'\nimport { CustomerUserService } from '@open-mercato/core/modules/customer_accounts/services/customerUserService'\nimport { CustomerSessionService } from '@open-mercato/core/modules/customer_accounts/services/customerSessionService'\nimport { CustomerRbacService } from '@open-mercato/core/modules/customer_accounts/services/customerRbacService'\nimport { adminUpdateUserSchema } from '@open-mercato/core/modules/customer_accounts/data/validators'\nimport { emitCustomerAccountsEvent } from '@open-mercato/core/modules/customer_accounts/events'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { isOwnedCompanyEntity, isOwnedPersonEntity } from '@open-mercato/core/modules/customer_accounts/lib/customerEntityOwnership'\nimport { enforceCommandOptimisticLockWithGuards } from '@open-mercato/shared/lib/crud/optimistic-lock-command'\nimport { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\n\nexport const metadata = {}\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\n\nexport async function GET(req: Request, { params }: { params: { id: string } }) {\n if (!UUID_RE.test(params.id)) {\n return NextResponse.json({ ok: false, error: 'Invalid user ID' }, { status: 400 })\n }\n\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ ok: false, error: 'Authentication required' }, { status: 401 })\n }\n\n const container = await createRequestContainer()\n const rbacService = container.resolve('rbacService') as RbacService\n const hasAccess = await rbacService.userHasAllFeatures(auth.sub, ['customer_accounts.view'], { tenantId: auth.tenantId, organizationId: auth.orgId })\n if (!hasAccess) {\n return NextResponse.json({ ok: false, error: 'Insufficient permissions' }, { status: 403 })\n }\n\n const em = container.resolve('em') as import('@mikro-orm/postgresql').EntityManager\n\n const user = await findOneWithDecryption(\n em,\n CustomerUser,\n { id: params.id, tenantId: auth.tenantId, organizationId: auth.orgId, deletedAt: null } as any,\n undefined,\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n )\n if (!user) {\n return NextResponse.json({ ok: false, error: 'User not found' }, { status: 404 })\n }\n\n const userRoles = await findWithDecryption(\n em,\n CustomerUserRole,\n { user: user.id as any, deletedAt: null } as any,\n { populate: ['role'] },\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n )\n const roles = userRoles.map((ur) => ({\n id: (ur.role as any).id,\n name: (ur.role as any).name,\n slug: (ur.role as any).slug,\n }))\n\n const activeSessions = await findWithDecryption(\n em,\n CustomerUserSession,\n {\n user: user.id as any,\n deletedAt: null,\n expiresAt: { $gt: new Date() },\n } as any,\n { orderBy: { lastUsedAt: 'DESC' } },\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n )\n\n const sessions = activeSessions.map((session) => ({\n id: session.id,\n ipAddress: (session as any).ipAddress || null,\n userAgent: (session as any).userAgent || null,\n lastUsedAt: (session as any).lastUsedAt || null,\n createdAt: session.createdAt,\n expiresAt: session.expiresAt,\n }))\n\n return NextResponse.json({\n ok: true,\n id: user.id,\n email: user.email,\n displayName: user.displayName,\n emailVerifiedAt: user.emailVerifiedAt || null,\n isActive: user.isActive,\n lockedUntil: user.lockedUntil || null,\n lastLoginAt: user.lastLoginAt || null,\n customerEntityId: user.customerEntityId || null,\n personEntityId: user.personEntityId || null,\n createdAt: user.createdAt,\n updatedAt: user.updatedAt || null,\n roles,\n sessions,\n })\n}\n\nexport async function PUT(req: Request, { params }: { params: { id: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ ok: false, error: 'Authentication required' }, { status: 401 })\n }\n\n const container = await createRequestContainer()\n const rbacService = container.resolve('rbacService') as RbacService\n const hasAccess = await rbacService.userHasAllFeatures(auth.sub, ['customer_accounts.manage'], { tenantId: auth.tenantId, organizationId: auth.orgId })\n if (!hasAccess) {\n return NextResponse.json({ ok: false, error: 'Insufficient permissions' }, { status: 403 })\n }\n\n let body: unknown\n try {\n body = await req.json()\n } catch {\n return NextResponse.json({ ok: false, error: 'Invalid request body' }, { status: 400 })\n }\n\n const parsed = adminUpdateUserSchema.safeParse(body)\n if (!parsed.success) {\n return NextResponse.json({ ok: false, error: 'Validation failed', details: parsed.error.flatten().fieldErrors }, { status: 400 })\n }\n\n const em = container.resolve('em') as import('@mikro-orm/postgresql').EntityManager\n\n const user = await findOneWithDecryption(\n em,\n CustomerUser,\n { id: params.id, tenantId: auth.tenantId, organizationId: auth.orgId, deletedAt: null } as any,\n undefined,\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n )\n if (!user) {\n return NextResponse.json({ ok: false, error: 'User not found' }, { status: 404 })\n }\n\n // Optimistic lock: refuse a stale overwrite so two admins editing the same\n // customer user in parallel cannot silently clobber each other (#2055). The\n // check is strictly additive \u2014 a no-op when the client sends no expected-version header.\n try {\n await enforceCommandOptimisticLockWithGuards(container, {\n resourceKind: 'customer_accounts.user',\n resourceId: user.id,\n current: user.updatedAt ?? null,\n request: req,\n })\n } catch (err) {\n if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })\n throw err\n }\n\n // Reject a customerEntityId the caller does not own before persisting it.\n // Without this check a mislinked company FK cross-links the user into another\n // org/company's portal context and persists indefinitely (#2693). A null value\n // (unlink) needs no ownership check.\n if (parsed.data.customerEntityId) {\n const owned = await isOwnedCompanyEntity(em, parsed.data.customerEntityId, {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n })\n if (!owned) {\n return NextResponse.json({ ok: false, error: 'Company not found' }, { status: 400 })\n }\n }\n\n // Same guard for the person FK. Without it the invite-side check is trivially\n // bypassable: create the user normally, then PUT an unowned personEntityId.\n // It persists (autoLinkCrm short-circuits on any non-null value) and leaks\n // account status into the other org's people list via the account-status\n // enricher. A null value (unlink) needs no ownership check.\n if (parsed.data.personEntityId) {\n const owned = await isOwnedPersonEntity(em, parsed.data.personEntityId, {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n })\n if (!owned) {\n return NextResponse.json({ ok: false, error: 'Person not found' }, { status: 400 })\n }\n }\n\n // Always bump updated_at so the optimistic-lock version advances on every save.\n // `nativeUpdate` bypasses MikroORM's `onUpdate` hook, so set it explicitly \u2014 without\n // this the version never changes and concurrent edits cannot be detected (#2055).\n const nextUpdatedAt = new Date()\n const updates: Record<string, unknown> = { updatedAt: nextUpdatedAt }\n if (parsed.data.displayName !== undefined) updates.displayName = parsed.data.displayName\n if (parsed.data.isActive !== undefined) updates.isActive = parsed.data.isActive\n if (parsed.data.lockedUntil !== undefined) updates.lockedUntil = parsed.data.lockedUntil ? new Date(parsed.data.lockedUntil) : null\n if (parsed.data.personEntityId !== undefined) updates.personEntityId = parsed.data.personEntityId\n if (parsed.data.customerEntityId !== undefined) updates.customerEntityId = parsed.data.customerEntityId\n\n await em.nativeUpdate(CustomerUser, {\n id: user.id,\n tenantId: user.tenantId,\n organizationId: user.organizationId,\n }, updates)\n\n let rolesChanged = false\n if (parsed.data.roleIds !== undefined) {\n const requestedRoleIds = parsed.data.roleIds\n // Scope role resolution to the caller's organization too \u2014 CustomerRole is\n // org-scoped, so a tenant-only filter would let an admin link roles from\n // another org in the same tenant (#2693).\n const validRoles = requestedRoleIds.length > 0\n ? await findWithDecryption(\n em,\n CustomerRole,\n {\n id: { $in: requestedRoleIds } as any,\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n deletedAt: null,\n } as any,\n undefined,\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n )\n : []\n if (validRoles.length !== requestedRoleIds.length) {\n const foundIds = new Set(validRoles.map((role) => role.id))\n const missingId = requestedRoleIds.find((roleId) => !foundIds.has(roleId))\n return NextResponse.json({ ok: false, error: `Role ${missingId} not found` }, { status: 400 })\n }\n\n await em.nativeDelete(CustomerUserRole, { user: user.id } as Record<string, unknown>)\n\n for (const role of validRoles) {\n const userRole = em.create(CustomerUserRole, {\n user,\n role,\n createdAt: new Date(),\n } as any)\n em.persist(userRole)\n }\n await em.flush()\n rolesChanged = true\n }\n\n if (rolesChanged) {\n const customerRbacService = container.resolve('customerRbacService') as CustomerRbacService\n await customerRbacService.invalidateUserCache(user.id)\n }\n\n void emitCustomerAccountsEvent('customer_accounts.user.updated', {\n id: user.id,\n recipientUserId: user.id,\n email: user.email,\n tenantId: user.tenantId,\n organizationId: user.organizationId,\n updatedBy: auth.sub,\n }).catch(() => undefined)\n\n return NextResponse.json({ ok: true, updatedAt: nextUpdatedAt.toISOString() })\n}\n\nexport async function DELETE(req: Request, { params }: { params: { id: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ ok: false, error: 'Authentication required' }, { status: 401 })\n }\n\n const container = await createRequestContainer()\n const rbacService = container.resolve('rbacService') as RbacService\n const hasAccess = await rbacService.userHasAllFeatures(auth.sub, ['customer_accounts.manage'], { tenantId: auth.tenantId, organizationId: auth.orgId })\n if (!hasAccess) {\n return NextResponse.json({ ok: false, error: 'Insufficient permissions' }, { status: 403 })\n }\n\n const em = container.resolve('em') as import('@mikro-orm/postgresql').EntityManager\n\n const user = await findOneWithDecryption(\n em,\n CustomerUser,\n { id: params.id, tenantId: auth.tenantId, organizationId: auth.orgId, deletedAt: null } as any,\n undefined,\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n )\n if (!user) {\n return NextResponse.json({ ok: false, error: 'User not found' }, { status: 404 })\n }\n\n // Optimistic lock: refuse a stale delete (e.g. deleting a record another admin\n // already modified). Strictly additive \u2014 a no-op without the expected-version header.\n try {\n await enforceCommandOptimisticLockWithGuards(container, {\n resourceKind: 'customer_accounts.user',\n resourceId: user.id,\n current: user.updatedAt ?? null,\n request: req,\n })\n } catch (err) {\n if (isCrudHttpError(err)) return NextResponse.json(err.body, { status: err.status })\n throw err\n }\n\n const customerUserService = container.resolve('customerUserService') as CustomerUserService\n const customerSessionService = container.resolve('customerSessionService') as CustomerSessionService\n\n await customerUserService.softDelete(user.id, {\n tenantId: user.tenantId,\n organizationId: user.organizationId,\n })\n await customerSessionService.revokeAllUserSessions(user.id)\n\n void emitCustomerAccountsEvent('customer_accounts.user.deleted', {\n id: user.id,\n email: user.email,\n tenantId: user.tenantId,\n organizationId: user.organizationId,\n deletedBy: auth.sub,\n }).catch(() => undefined)\n\n return NextResponse.json({ ok: true })\n}\n\nconst roleSchema = z.object({ id: z.string().uuid(), name: z.string(), slug: z.string() })\nconst userDetailSchema = z.object({\n id: z.string().uuid(),\n email: z.string(),\n displayName: z.string(),\n emailVerified: z.boolean(),\n isActive: z.boolean(),\n lockedUntil: z.string().datetime().nullable(),\n lastLoginAt: z.string().datetime().nullable(),\n failedLoginAttempts: z.number(),\n customerEntityId: z.string().uuid().nullable(),\n personEntityId: z.string().uuid().nullable(),\n createdAt: z.string().datetime(),\n updatedAt: z.string().datetime().nullable(),\n roles: z.array(roleSchema),\n activeSessionCount: z.number(),\n})\n\nconst successSchema = z.object({ ok: z.literal(true) })\nconst errorSchema = z.object({ ok: z.literal(false), error: z.string() })\n\nconst getMethodDoc: OpenApiMethodDoc = {\n summary: 'Get customer user detail (admin)',\n description: 'Returns full customer user details including CRM links, roles, and active session count.',\n tags: ['Customer Accounts Admin'],\n responses: [{\n status: 200,\n description: 'User detail',\n schema: z.object({ ok: z.literal(true), user: userDetailSchema }),\n }],\n errors: [\n { status: 401, description: 'Not authenticated', schema: errorSchema },\n { status: 403, description: 'Insufficient permissions', schema: errorSchema },\n { status: 404, description: 'User not found', schema: errorSchema },\n ],\n}\n\nconst putMethodDoc: OpenApiMethodDoc = {\n summary: 'Update customer user (admin)',\n description: 'Updates a customer user. Staff can update status, lock, CRM links, and roles. Role assignment bypasses customer_assignable check.',\n tags: ['Customer Accounts Admin'],\n requestBody: { schema: adminUpdateUserSchema },\n responses: [{ status: 200, description: 'User updated', schema: successSchema }],\n errors: [\n { status: 400, description: 'Validation failed or role not found', schema: errorSchema },\n { status: 401, description: 'Not authenticated', schema: errorSchema },\n { status: 403, description: 'Insufficient permissions', schema: errorSchema },\n { status: 404, description: 'User not found', schema: errorSchema },\n ],\n}\n\nconst deleteMethodDoc: OpenApiMethodDoc = {\n summary: 'Delete customer user (admin)',\n description: 'Soft deletes a customer user and revokes all their active sessions.',\n tags: ['Customer Accounts Admin'],\n responses: [{ status: 200, description: 'User deleted', schema: successSchema }],\n errors: [\n { status: 401, description: 'Not authenticated', schema: errorSchema },\n { status: 403, description: 'Insufficient permissions', schema: errorSchema },\n { status: 404, description: 'User not found', schema: errorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n summary: 'Customer user detail management (admin)',\n pathParams: z.object({ id: z.string().uuid() }),\n methods: {\n GET: getMethodDoc,\n PUT: putMethodDoc,\n DELETE: deleteMethodDoc,\n },\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -4,6 +4,7 @@ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
|
|
|
4
4
|
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
|
|
5
5
|
import { emitCustomerAccountsEvent } from "@open-mercato/core/modules/customer_accounts/events";
|
|
6
6
|
import { inviteUserSchema } from "@open-mercato/core/modules/customer_accounts/data/validators";
|
|
7
|
+
import { isOwnedCompanyEntity, isOwnedPersonEntity, resolveOwnedCompanyForPerson } from "@open-mercato/core/modules/customer_accounts/lib/customerEntityOwnership";
|
|
7
8
|
import { rateLimitErrorSchema } from "@open-mercato/shared/lib/ratelimit/helpers";
|
|
8
9
|
import {
|
|
9
10
|
checkAuthRateLimit,
|
|
@@ -11,7 +12,12 @@ import {
|
|
|
11
12
|
customerInviteIpRateLimitConfig
|
|
12
13
|
} from "@open-mercato/core/modules/customer_accounts/lib/rateLimiter";
|
|
13
14
|
import { readNormalizedEmailFromJsonRequest } from "@open-mercato/core/modules/customer_accounts/lib/rateLimitIdentifier";
|
|
15
|
+
import { sendCustomerInvitationEmail } from "@open-mercato/core/modules/customer_accounts/lib/invitationEmail";
|
|
14
16
|
const metadata = {};
|
|
17
|
+
function resolveInvitedByUserId(auth) {
|
|
18
|
+
if (auth.isApiKey) return auth.userId ?? null;
|
|
19
|
+
return auth.sub;
|
|
20
|
+
}
|
|
15
21
|
async function POST(req) {
|
|
16
22
|
const auth = await getAuthFromRequest(req);
|
|
17
23
|
if (!auth) {
|
|
@@ -41,17 +47,61 @@ async function POST(req) {
|
|
|
41
47
|
if (!parsed.success) {
|
|
42
48
|
return NextResponse.json({ ok: false, error: "Validation failed", details: parsed.error.flatten().fieldErrors }, { status: 400 });
|
|
43
49
|
}
|
|
50
|
+
if (parsed.data.customerEntityId) {
|
|
51
|
+
const em = container.resolve("em");
|
|
52
|
+
const owned = await isOwnedCompanyEntity(em, parsed.data.customerEntityId, {
|
|
53
|
+
tenantId: auth.tenantId,
|
|
54
|
+
organizationId: auth.orgId
|
|
55
|
+
});
|
|
56
|
+
if (!owned) {
|
|
57
|
+
return NextResponse.json({ ok: false, error: "Company not found" }, { status: 400 });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
let resolvedCustomerEntityId = parsed.data.customerEntityId || null;
|
|
61
|
+
if (parsed.data.personEntityId) {
|
|
62
|
+
const em = container.resolve("em");
|
|
63
|
+
const owned = await isOwnedPersonEntity(em, parsed.data.personEntityId, {
|
|
64
|
+
tenantId: auth.tenantId,
|
|
65
|
+
organizationId: auth.orgId
|
|
66
|
+
});
|
|
67
|
+
if (!owned) {
|
|
68
|
+
return NextResponse.json({ ok: false, error: "Person not found" }, { status: 400 });
|
|
69
|
+
}
|
|
70
|
+
if (!resolvedCustomerEntityId) {
|
|
71
|
+
resolvedCustomerEntityId = await resolveOwnedCompanyForPerson(em, parsed.data.personEntityId, {
|
|
72
|
+
tenantId: auth.tenantId,
|
|
73
|
+
organizationId: auth.orgId
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
44
77
|
const customerInvitationService = container.resolve("customerInvitationService");
|
|
45
|
-
const { invitation } = await customerInvitationService.createInvitation(
|
|
78
|
+
const { invitation, rawToken, rollbackState } = await customerInvitationService.createInvitation(
|
|
46
79
|
parsed.data.email,
|
|
47
80
|
{ tenantId: auth.tenantId, organizationId: auth.orgId },
|
|
48
81
|
{
|
|
49
|
-
customerEntityId:
|
|
82
|
+
customerEntityId: resolvedCustomerEntityId,
|
|
83
|
+
personEntityId: parsed.data.personEntityId || null,
|
|
50
84
|
roleIds: parsed.data.roleIds,
|
|
51
|
-
invitedByUserId: auth
|
|
85
|
+
invitedByUserId: resolveInvitedByUserId(auth),
|
|
52
86
|
displayName: parsed.data.displayName || null
|
|
53
87
|
}
|
|
54
88
|
);
|
|
89
|
+
try {
|
|
90
|
+
await sendCustomerInvitationEmail({
|
|
91
|
+
container,
|
|
92
|
+
organizationId: auth.orgId,
|
|
93
|
+
email: invitation.email,
|
|
94
|
+
rawToken
|
|
95
|
+
});
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.error("[customer_accounts.admin.users-invite] invitation email failed", error);
|
|
98
|
+
try {
|
|
99
|
+
await customerInvitationService.rollbackInvitation(invitation, rollbackState);
|
|
100
|
+
} catch (rollbackError) {
|
|
101
|
+
console.error("[customer_accounts.admin.users-invite] invitation rollback failed", rollbackError);
|
|
102
|
+
}
|
|
103
|
+
return NextResponse.json({ ok: false, error: "Invitation email could not be sent" }, { status: 502 });
|
|
104
|
+
}
|
|
55
105
|
void emitCustomerAccountsEvent("customer_accounts.user.invited", {
|
|
56
106
|
invitationId: invitation.id,
|
|
57
107
|
email: invitation.email,
|
|
@@ -65,6 +115,10 @@ async function POST(req) {
|
|
|
65
115
|
invitation: {
|
|
66
116
|
id: invitation.id,
|
|
67
117
|
email: invitation.email,
|
|
118
|
+
// Echo the stored CRM links so the caller can see which company the person
|
|
119
|
+
// invite resolved to. The token stays unexposed.
|
|
120
|
+
customerEntityId: invitation.customerEntityId || null,
|
|
121
|
+
personEntityId: invitation.personEntityId || null,
|
|
68
122
|
expiresAt: invitation.expiresAt
|
|
69
123
|
}
|
|
70
124
|
}, { status: 201 });
|
|
@@ -74,6 +128,8 @@ const successSchema = z.object({
|
|
|
74
128
|
invitation: z.object({
|
|
75
129
|
id: z.string().uuid(),
|
|
76
130
|
email: z.string(),
|
|
131
|
+
customerEntityId: z.string().uuid().nullable(),
|
|
132
|
+
personEntityId: z.string().uuid().nullable(),
|
|
77
133
|
expiresAt: z.string().datetime()
|
|
78
134
|
})
|
|
79
135
|
});
|
|
@@ -88,7 +144,8 @@ const methodDoc = {
|
|
|
88
144
|
{ status: 400, description: "Validation failed", schema: errorSchema },
|
|
89
145
|
{ status: 401, description: "Not authenticated", schema: errorSchema },
|
|
90
146
|
{ status: 403, description: "Insufficient permissions", schema: errorSchema },
|
|
91
|
-
{ status: 429, description: "Too many invitation requests", schema: rateLimitErrorSchema }
|
|
147
|
+
{ status: 429, description: "Too many invitation requests", schema: rateLimitErrorSchema },
|
|
148
|
+
{ status: 502, description: "Invitation email could not be sent", schema: errorSchema }
|
|
92
149
|
]
|
|
93
150
|
};
|
|
94
151
|
const openApi = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/customer_accounts/api/admin/users-invite.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc, OpenApiMethodDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'\nimport { CustomerInvitationService } from '@open-mercato/core/modules/customer_accounts/services/customerInvitationService'\nimport { emitCustomerAccountsEvent } from '@open-mercato/core/modules/customer_accounts/events'\nimport { inviteUserSchema } from '@open-mercato/core/modules/customer_accounts/data/validators'\nimport { rateLimitErrorSchema } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport {\n checkAuthRateLimit,\n customerInviteRateLimitConfig,\n customerInviteIpRateLimitConfig,\n} from '@open-mercato/core/modules/customer_accounts/lib/rateLimiter'\nimport { readNormalizedEmailFromJsonRequest } from '@open-mercato/core/modules/customer_accounts/lib/rateLimitIdentifier'\n\nexport const metadata = {}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ ok: false, error: 'Authentication required' }, { status: 401 })\n }\n\n const rateLimitEmail = await readNormalizedEmailFromJsonRequest(req)\n const { error: rateLimitError } = await checkAuthRateLimit({\n req,\n ipConfig: customerInviteIpRateLimitConfig,\n compoundConfig: customerInviteRateLimitConfig,\n compoundIdentifier: rateLimitEmail,\n })\n if (rateLimitError) return rateLimitError\n\n const container = await createRequestContainer()\n const rbacService = container.resolve('rbacService') as RbacService\n const hasAccess = await rbacService.userHasAllFeatures(auth.sub, ['customer_accounts.invite'], { tenantId: auth.tenantId, organizationId: auth.orgId })\n if (!hasAccess) {\n return NextResponse.json({ ok: false, error: 'Insufficient permissions' }, { status: 403 })\n }\n\n let body: unknown\n try {\n body = await req.json()\n } catch {\n return NextResponse.json({ ok: false, error: 'Invalid request body' }, { status: 400 })\n }\n\n const parsed = inviteUserSchema.safeParse(body)\n if (!parsed.success) {\n return NextResponse.json({ ok: false, error: 'Validation failed', details: parsed.error.flatten().fieldErrors }, { status: 400 })\n }\n\n const customerInvitationService = container.resolve('customerInvitationService') as CustomerInvitationService\n\n const { invitation } = await customerInvitationService.createInvitation(\n parsed.data.email,\n { tenantId: auth.tenantId!, organizationId: auth.orgId! },\n {\n customerEntityId: parsed.data.
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAElB,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AAGvC,SAAS,iCAAiC;AAC1C,SAAS,wBAAwB;AACjC,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,0CAA0C;
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc, OpenApiMethodDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'\nimport { CustomerInvitationService } from '@open-mercato/core/modules/customer_accounts/services/customerInvitationService'\nimport { emitCustomerAccountsEvent } from '@open-mercato/core/modules/customer_accounts/events'\nimport { inviteUserSchema } from '@open-mercato/core/modules/customer_accounts/data/validators'\nimport { isOwnedCompanyEntity, isOwnedPersonEntity, resolveOwnedCompanyForPerson } from '@open-mercato/core/modules/customer_accounts/lib/customerEntityOwnership'\nimport { rateLimitErrorSchema } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport {\n checkAuthRateLimit,\n customerInviteRateLimitConfig,\n customerInviteIpRateLimitConfig,\n} from '@open-mercato/core/modules/customer_accounts/lib/rateLimiter'\nimport { readNormalizedEmailFromJsonRequest } from '@open-mercato/core/modules/customer_accounts/lib/rateLimitIdentifier'\nimport { sendCustomerInvitationEmail } from '@open-mercato/core/modules/customer_accounts/lib/invitationEmail'\n\nexport const metadata = {}\n\nfunction resolveInvitedByUserId(auth: NonNullable<Awaited<ReturnType<typeof getAuthFromRequest>>>): string | null {\n if (auth.isApiKey) return auth.userId ?? null\n return auth.sub\n}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ ok: false, error: 'Authentication required' }, { status: 401 })\n }\n\n const rateLimitEmail = await readNormalizedEmailFromJsonRequest(req)\n const { error: rateLimitError } = await checkAuthRateLimit({\n req,\n ipConfig: customerInviteIpRateLimitConfig,\n compoundConfig: customerInviteRateLimitConfig,\n compoundIdentifier: rateLimitEmail,\n })\n if (rateLimitError) return rateLimitError\n\n const container = await createRequestContainer()\n const rbacService = container.resolve('rbacService') as RbacService\n const hasAccess = await rbacService.userHasAllFeatures(auth.sub, ['customer_accounts.invite'], { tenantId: auth.tenantId, organizationId: auth.orgId })\n if (!hasAccess) {\n return NextResponse.json({ ok: false, error: 'Insufficient permissions' }, { status: 403 })\n }\n\n let body: unknown\n try {\n body = await req.json()\n } catch {\n return NextResponse.json({ ok: false, error: 'Invalid request body' }, { status: 400 })\n }\n\n const parsed = inviteUserSchema.safeParse(body)\n if (!parsed.success) {\n return NextResponse.json({ ok: false, error: 'Validation failed', details: parsed.error.flatten().fieldErrors }, { status: 400 })\n }\n\n // Reject a customerEntityId the caller does not own. customerEntityId is the\n // CRM company FK; without this check a non-company (e.g. a person) entity id\n // or a company from another org poisons the invitation and every later user\n // edit fails with \"Company not found\" (#4362, #2693).\n if (parsed.data.customerEntityId) {\n const em = container.resolve('em') as import('@mikro-orm/postgresql').EntityManager\n const owned = await isOwnedCompanyEntity(em, parsed.data.customerEntityId, {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n })\n if (!owned) {\n return NextResponse.json({ ok: false, error: 'Company not found' }, { status: 400 })\n }\n }\n\n // Same guard for the person FK: it is copied onto the customer user on accept\n // and makes `autoLinkCrm` short-circuit, so an unowned id would permanently\n // cross-link the portal user to another org's CRM person.\n let resolvedCustomerEntityId = parsed.data.customerEntityId || null\n if (parsed.data.personEntityId) {\n const em = container.resolve('em') as import('@mikro-orm/postgresql').EntityManager\n const owned = await isOwnedPersonEntity(em, parsed.data.personEntityId, {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n })\n if (!owned) {\n return NextResponse.json({ ok: false, error: 'Person not found' }, { status: 400 })\n }\n\n // An invitation raised from a person card carries only the person FK, and the\n // accepted user then short-circuits `autoLinkCrm`. Resolve the person's company\n // here so the user lands with a company scope key: the portal Users page, portal\n // invitations, and the company detail \"Portal users\" group all filter on it.\n if (!resolvedCustomerEntityId) {\n resolvedCustomerEntityId = await resolveOwnedCompanyForPerson(em, parsed.data.personEntityId, {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n })\n }\n }\n\n const customerInvitationService = container.resolve('customerInvitationService') as CustomerInvitationService\n\n const { invitation, rawToken, rollbackState } = await customerInvitationService.createInvitation(\n parsed.data.email,\n { tenantId: auth.tenantId!, organizationId: auth.orgId! },\n {\n customerEntityId: resolvedCustomerEntityId,\n personEntityId: parsed.data.personEntityId || null,\n roleIds: parsed.data.roleIds,\n invitedByUserId: resolveInvitedByUserId(auth),\n displayName: parsed.data.displayName || null,\n },\n )\n\n try {\n await sendCustomerInvitationEmail({\n container,\n organizationId: auth.orgId!,\n email: invitation.email,\n rawToken,\n })\n } catch (error) {\n console.error('[customer_accounts.admin.users-invite] invitation email failed', error)\n try {\n await customerInvitationService.rollbackInvitation(invitation, rollbackState)\n } catch (rollbackError) {\n console.error('[customer_accounts.admin.users-invite] invitation rollback failed', rollbackError)\n }\n return NextResponse.json({ ok: false, error: 'Invitation email could not be sent' }, { status: 502 })\n }\n\n // Emit only after the email is sent, so a subscriber observing \"invited\" can\n // assume the recipient was actually notified (no event fires on the 502 path).\n void emitCustomerAccountsEvent('customer_accounts.user.invited', {\n invitationId: invitation.id,\n email: invitation.email,\n customerEntityId: invitation.customerEntityId || null,\n invitedByType: 'staff',\n tenantId: auth.tenantId!,\n organizationId: auth.orgId!,\n }).catch(() => undefined)\n\n return NextResponse.json({\n ok: true,\n invitation: {\n id: invitation.id,\n email: invitation.email,\n // Echo the stored CRM links so the caller can see which company the person\n // invite resolved to. The token stays unexposed.\n customerEntityId: invitation.customerEntityId || null,\n personEntityId: invitation.personEntityId || null,\n expiresAt: invitation.expiresAt,\n },\n }, { status: 201 })\n}\n\nconst successSchema = z.object({\n ok: z.literal(true),\n invitation: z.object({\n id: z.string().uuid(),\n email: z.string(),\n customerEntityId: z.string().uuid().nullable(),\n personEntityId: z.string().uuid().nullable(),\n expiresAt: z.string().datetime(),\n }),\n})\nconst errorSchema = z.object({ ok: z.literal(false), error: z.string() })\n\nconst methodDoc: OpenApiMethodDoc = {\n summary: 'Invite customer user (admin)',\n description: 'Creates a staff-initiated invitation for a new customer user. The invitedByUserId is set from the staff auth context.',\n tags: ['Customer Accounts Admin'],\n requestBody: { schema: inviteUserSchema },\n responses: [{ status: 201, description: 'Invitation created', schema: successSchema }],\n errors: [\n { status: 400, description: 'Validation failed', schema: errorSchema },\n { status: 401, description: 'Not authenticated', schema: errorSchema },\n { status: 403, description: 'Insufficient permissions', schema: errorSchema },\n { status: 429, description: 'Too many invitation requests', schema: rateLimitErrorSchema },\n { status: 502, description: 'Invitation email could not be sent', schema: errorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n summary: 'Invite customer user (admin)',\n methods: { POST: methodDoc },\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
customerInviteIpRateLimitConfig
|
|
14
14
|
} from "@open-mercato/core/modules/customer_accounts/lib/rateLimiter";
|
|
15
15
|
import { readNormalizedEmailFromJsonRequest } from "@open-mercato/core/modules/customer_accounts/lib/rateLimitIdentifier";
|
|
16
|
+
import { sendCustomerInvitationEmail } from "@open-mercato/core/modules/customer_accounts/lib/invitationEmail";
|
|
16
17
|
const metadata = { requireAuth: false };
|
|
17
18
|
async function POST(req) {
|
|
18
19
|
const auth = await getCustomerAuthFromRequest(req);
|
|
@@ -72,7 +73,7 @@ async function POST(req) {
|
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
const customerInvitationService = container.resolve("customerInvitationService");
|
|
75
|
-
const { invitation } = await customerInvitationService.createInvitation(
|
|
76
|
+
const { invitation, rawToken, rollbackState } = await customerInvitationService.createInvitation(
|
|
76
77
|
parsed.data.email,
|
|
77
78
|
{ tenantId: auth.tenantId, organizationId: auth.orgId },
|
|
78
79
|
{
|
|
@@ -82,6 +83,22 @@ async function POST(req) {
|
|
|
82
83
|
displayName: parsed.data.displayName || null
|
|
83
84
|
}
|
|
84
85
|
);
|
|
86
|
+
try {
|
|
87
|
+
await sendCustomerInvitationEmail({
|
|
88
|
+
container,
|
|
89
|
+
organizationId: auth.orgId,
|
|
90
|
+
email: invitation.email,
|
|
91
|
+
rawToken
|
|
92
|
+
});
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error("[customer_accounts.portal.users-invite] invitation email failed", error);
|
|
95
|
+
try {
|
|
96
|
+
await customerInvitationService.rollbackInvitation(invitation, rollbackState);
|
|
97
|
+
} catch (rollbackError) {
|
|
98
|
+
console.error("[customer_accounts.portal.users-invite] invitation rollback failed", rollbackError);
|
|
99
|
+
}
|
|
100
|
+
return NextResponse.json({ ok: false, error: "Invitation email could not be sent" }, { status: 502 });
|
|
101
|
+
}
|
|
85
102
|
void emitCustomerAccountsEvent("customer_accounts.user.invited", {
|
|
86
103
|
invitationId: invitation.id,
|
|
87
104
|
email: invitation.email,
|
|
@@ -118,7 +135,8 @@ const methodDoc = {
|
|
|
118
135
|
{ status: 400, description: "Validation failed", schema: errorSchema },
|
|
119
136
|
{ status: 401, description: "Not authenticated", schema: errorSchema },
|
|
120
137
|
{ status: 403, description: "Insufficient permissions or non-assignable role", schema: errorSchema },
|
|
121
|
-
{ status: 429, description: "Too many invitation requests", schema: rateLimitErrorSchema }
|
|
138
|
+
{ status: 429, description: "Too many invitation requests", schema: rateLimitErrorSchema },
|
|
139
|
+
{ status: 502, description: "Invitation email could not be sent", schema: errorSchema }
|
|
122
140
|
]
|
|
123
141
|
};
|
|
124
142
|
const openApi = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/customer_accounts/api/portal/users-invite.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc, OpenApiMethodDoc } from '@open-mercato/shared/lib/openapi'\nimport { getCustomerAuthFromRequest, requireCustomerFeature } from '@open-mercato/core/modules/customer_accounts/lib/customerAuth'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { CustomerInvitationService } from '@open-mercato/core/modules/customer_accounts/services/customerInvitationService'\nimport { emitCustomerAccountsEvent } from '@open-mercato/core/modules/customer_accounts/events'\nimport { CustomerRbacService } from '@open-mercato/core/modules/customer_accounts/services/customerRbacService'\nimport { CustomerRole } from '@open-mercato/core/modules/customer_accounts/data/entities'\nimport { inviteUserSchema } from '@open-mercato/core/modules/customer_accounts/data/validators'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { rateLimitErrorSchema } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport {\n checkAuthRateLimit,\n customerInviteRateLimitConfig,\n customerInviteIpRateLimitConfig,\n} from '@open-mercato/core/modules/customer_accounts/lib/rateLimiter'\nimport { readNormalizedEmailFromJsonRequest } from '@open-mercato/core/modules/customer_accounts/lib/rateLimitIdentifier'\n\nexport const metadata: { path?: string; requireAuth?: boolean } = { requireAuth: false }\n\nexport async function POST(req: Request) {\n const auth = await getCustomerAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ ok: false, error: 'Authentication required' }, { status: 401 })\n }\n\n const rateLimitEmail = await readNormalizedEmailFromJsonRequest(req)\n const { error: rateLimitError } = await checkAuthRateLimit({\n req,\n ipConfig: customerInviteIpRateLimitConfig,\n compoundConfig: customerInviteRateLimitConfig,\n compoundIdentifier: rateLimitEmail,\n })\n if (rateLimitError) return rateLimitError\n\n const container = await createRequestContainer()\n const customerRbacService = container.resolve('customerRbacService') as CustomerRbacService\n\n try {\n await requireCustomerFeature(auth, ['portal.users.manage'], customerRbacService)\n } catch (response) {\n return response as NextResponse\n }\n\n if (!auth.customerEntityId) {\n return NextResponse.json({ ok: false, error: 'No company association' }, { status: 403 })\n }\n\n let body: unknown\n try {\n body = await req.json()\n } catch {\n return NextResponse.json({ ok: false, error: 'Invalid request body' }, { status: 400 })\n }\n\n const parsed = inviteUserSchema.safeParse(body)\n if (!parsed.success) {\n return NextResponse.json({ ok: false, error: 'Validation failed', details: parsed.error.flatten().fieldErrors }, { status: 400 })\n }\n\n const em = container.resolve('em') as import('@mikro-orm/postgresql').EntityManager\n\n // Validate all roles are customer_assignable\n const requestedRoleIds = parsed.data.roleIds\n const roles = requestedRoleIds.length > 0\n ? await findWithDecryption(\n em,\n CustomerRole,\n {\n id: { $in: requestedRoleIds },\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n deletedAt: null,\n } as any,\n undefined,\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n )\n : []\n const rolesById = new Map(roles.map((role) => [role.id, role]))\n for (const roleId of requestedRoleIds) {\n const role = rolesById.get(roleId)\n if (!role) {\n return NextResponse.json({ ok: false, error: `Role ${roleId} not found` }, { status: 400 })\n }\n if (!role.customerAssignable) {\n return NextResponse.json({ ok: false, error: `Role \"${role.name}\" cannot be assigned by portal users` }, { status: 403 })\n }\n }\n\n const customerInvitationService = container.resolve('customerInvitationService') as CustomerInvitationService\n\n const { invitation } = await customerInvitationService.createInvitation(\n parsed.data.email,\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n {\n customerEntityId: auth.customerEntityId,\n roleIds: parsed.data.roleIds,\n invitedByCustomerUserId: auth.sub,\n displayName: parsed.data.displayName || null,\n },\n )\n\n void emitCustomerAccountsEvent('customer_accounts.user.invited', {\n invitationId: invitation.id,\n email: invitation.email,\n customerEntityId: invitation.customerEntityId || null,\n invitedByType: 'portal',\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n }).catch(() => undefined)\n\n return NextResponse.json({\n ok: true,\n invitation: {\n id: invitation.id,\n email: invitation.email,\n expiresAt: invitation.expiresAt,\n },\n }, { status: 201 })\n}\n\nconst successSchema = z.object({\n ok: z.literal(true),\n invitation: z.object({\n id: z.string().uuid(),\n email: z.string(),\n expiresAt: z.string().datetime(),\n }),\n})\nconst errorSchema = z.object({ ok: z.literal(false), error: z.string() })\n\nconst methodDoc: OpenApiMethodDoc = {\n summary: 'Invite a user to the company portal',\n description: 'Creates an invitation for a new user to join the company portal.',\n tags: ['Customer Portal'],\n requestBody: { schema: inviteUserSchema },\n responses: [{ status: 201, description: 'Invitation created', schema: successSchema }],\n errors: [\n { status: 400, description: 'Validation failed', schema: errorSchema },\n { status: 401, description: 'Not authenticated', schema: errorSchema },\n { status: 403, description: 'Insufficient permissions or non-assignable role', schema: errorSchema },\n { status: 429, description: 'Too many invitation requests', schema: rateLimitErrorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n summary: 'Invite portal user',\n methods: { POST: methodDoc },\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAElB,SAAS,4BAA4B,8BAA8B;AACnE,SAAS,8BAA8B;AAEvC,SAAS,iCAAiC;AAE1C,SAAS,oBAAoB;AAC7B,SAAS,wBAAwB;AACjC,SAAS,0BAA0B;AACnC,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,0CAA0C;
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc, OpenApiMethodDoc } from '@open-mercato/shared/lib/openapi'\nimport { getCustomerAuthFromRequest, requireCustomerFeature } from '@open-mercato/core/modules/customer_accounts/lib/customerAuth'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { CustomerInvitationService } from '@open-mercato/core/modules/customer_accounts/services/customerInvitationService'\nimport { emitCustomerAccountsEvent } from '@open-mercato/core/modules/customer_accounts/events'\nimport { CustomerRbacService } from '@open-mercato/core/modules/customer_accounts/services/customerRbacService'\nimport { CustomerRole } from '@open-mercato/core/modules/customer_accounts/data/entities'\nimport { inviteUserSchema } from '@open-mercato/core/modules/customer_accounts/data/validators'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { rateLimitErrorSchema } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport {\n checkAuthRateLimit,\n customerInviteRateLimitConfig,\n customerInviteIpRateLimitConfig,\n} from '@open-mercato/core/modules/customer_accounts/lib/rateLimiter'\nimport { readNormalizedEmailFromJsonRequest } from '@open-mercato/core/modules/customer_accounts/lib/rateLimitIdentifier'\nimport { sendCustomerInvitationEmail } from '@open-mercato/core/modules/customer_accounts/lib/invitationEmail'\n\nexport const metadata: { path?: string; requireAuth?: boolean } = { requireAuth: false }\n\nexport async function POST(req: Request) {\n const auth = await getCustomerAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ ok: false, error: 'Authentication required' }, { status: 401 })\n }\n\n const rateLimitEmail = await readNormalizedEmailFromJsonRequest(req)\n const { error: rateLimitError } = await checkAuthRateLimit({\n req,\n ipConfig: customerInviteIpRateLimitConfig,\n compoundConfig: customerInviteRateLimitConfig,\n compoundIdentifier: rateLimitEmail,\n })\n if (rateLimitError) return rateLimitError\n\n const container = await createRequestContainer()\n const customerRbacService = container.resolve('customerRbacService') as CustomerRbacService\n\n try {\n await requireCustomerFeature(auth, ['portal.users.manage'], customerRbacService)\n } catch (response) {\n return response as NextResponse\n }\n\n if (!auth.customerEntityId) {\n return NextResponse.json({ ok: false, error: 'No company association' }, { status: 403 })\n }\n\n let body: unknown\n try {\n body = await req.json()\n } catch {\n return NextResponse.json({ ok: false, error: 'Invalid request body' }, { status: 400 })\n }\n\n const parsed = inviteUserSchema.safeParse(body)\n if (!parsed.success) {\n return NextResponse.json({ ok: false, error: 'Validation failed', details: parsed.error.flatten().fieldErrors }, { status: 400 })\n }\n\n const em = container.resolve('em') as import('@mikro-orm/postgresql').EntityManager\n\n // Validate all roles are customer_assignable\n const requestedRoleIds = parsed.data.roleIds\n const roles = requestedRoleIds.length > 0\n ? await findWithDecryption(\n em,\n CustomerRole,\n {\n id: { $in: requestedRoleIds },\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n deletedAt: null,\n } as any,\n undefined,\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n )\n : []\n const rolesById = new Map(roles.map((role) => [role.id, role]))\n for (const roleId of requestedRoleIds) {\n const role = rolesById.get(roleId)\n if (!role) {\n return NextResponse.json({ ok: false, error: `Role ${roleId} not found` }, { status: 400 })\n }\n if (!role.customerAssignable) {\n return NextResponse.json({ ok: false, error: `Role \"${role.name}\" cannot be assigned by portal users` }, { status: 403 })\n }\n }\n\n const customerInvitationService = container.resolve('customerInvitationService') as CustomerInvitationService\n\n const { invitation, rawToken, rollbackState } = await customerInvitationService.createInvitation(\n parsed.data.email,\n { tenantId: auth.tenantId, organizationId: auth.orgId },\n {\n customerEntityId: auth.customerEntityId,\n roleIds: parsed.data.roleIds,\n invitedByCustomerUserId: auth.sub,\n displayName: parsed.data.displayName || null,\n },\n )\n\n try {\n await sendCustomerInvitationEmail({\n container,\n organizationId: auth.orgId,\n email: invitation.email,\n rawToken,\n })\n } catch (error) {\n console.error('[customer_accounts.portal.users-invite] invitation email failed', error)\n try {\n await customerInvitationService.rollbackInvitation(invitation, rollbackState)\n } catch (rollbackError) {\n console.error('[customer_accounts.portal.users-invite] invitation rollback failed', rollbackError)\n }\n return NextResponse.json({ ok: false, error: 'Invitation email could not be sent' }, { status: 502 })\n }\n\n // Emit only after the email is sent, so a subscriber observing \"invited\" can\n // assume the recipient was actually notified (no event fires on the 502 path).\n void emitCustomerAccountsEvent('customer_accounts.user.invited', {\n invitationId: invitation.id,\n email: invitation.email,\n customerEntityId: invitation.customerEntityId || null,\n invitedByType: 'portal',\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n }).catch(() => undefined)\n\n return NextResponse.json({\n ok: true,\n invitation: {\n id: invitation.id,\n email: invitation.email,\n expiresAt: invitation.expiresAt,\n },\n }, { status: 201 })\n}\n\nconst successSchema = z.object({\n ok: z.literal(true),\n invitation: z.object({\n id: z.string().uuid(),\n email: z.string(),\n expiresAt: z.string().datetime(),\n }),\n})\nconst errorSchema = z.object({ ok: z.literal(false), error: z.string() })\n\nconst methodDoc: OpenApiMethodDoc = {\n summary: 'Invite a user to the company portal',\n description: 'Creates an invitation for a new user to join the company portal.',\n tags: ['Customer Portal'],\n requestBody: { schema: inviteUserSchema },\n responses: [{ status: 201, description: 'Invitation created', schema: successSchema }],\n errors: [\n { status: 400, description: 'Validation failed', schema: errorSchema },\n { status: 401, description: 'Not authenticated', schema: errorSchema },\n { status: 403, description: 'Insufficient permissions or non-assignable role', schema: errorSchema },\n { status: 429, description: 'Too many invitation requests', schema: rateLimitErrorSchema },\n { status: 502, description: 'Invitation email could not be sent', schema: errorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n summary: 'Invite portal user',\n methods: { POST: methodDoc },\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -345,6 +345,9 @@ __decorateClass([
|
|
|
345
345
|
__decorateClass([
|
|
346
346
|
Property({ name: "customer_entity_id", type: "uuid", nullable: true })
|
|
347
347
|
], CustomerUserInvitation.prototype, "customerEntityId", 2);
|
|
348
|
+
__decorateClass([
|
|
349
|
+
Property({ name: "person_entity_id", type: "uuid", nullable: true })
|
|
350
|
+
], CustomerUserInvitation.prototype, "personEntityId", 2);
|
|
348
351
|
__decorateClass([
|
|
349
352
|
Property({ name: "role_ids_json", type: "json", nullable: true })
|
|
350
353
|
], CustomerUserInvitation.prototype, "roleIdsJson", 2);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/customer_accounts/data/entities.ts"],
|
|
4
|
-
"sourcesContent": ["import { Check, Entity, Enum, Index, ManyToOne, PrimaryKey, Property, Unique } from '@mikro-orm/decorators/legacy'\n\nexport type DomainProvider = 'traefik'\nexport type DomainStatus = 'pending' | 'verified' | 'active' | 'dns_failed' | 'tls_failed'\n\nexport const DOMAIN_PROVIDERS: readonly DomainProvider[] = ['traefik'] as const\nexport const DOMAIN_STATUSES: readonly DomainStatus[] = [\n 'pending',\n 'verified',\n 'active',\n 'dns_failed',\n 'tls_failed',\n] as const\n\n@Entity({ tableName: 'customer_users' })\n@Unique({ properties: ['tenantId', 'emailHash'], name: 'customer_users_tenant_email_hash_uniq' })\nexport class CustomerUser {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ type: 'text' })\n email!: string\n\n @Property({ name: 'email_hash', type: 'text' })\n @Index({ name: 'customer_users_email_hash_idx' })\n emailHash!: string\n\n @Property({ name: 'password_hash', type: 'text', nullable: true })\n passwordHash?: string | null\n\n @Property({ name: 'display_name', type: 'text' })\n displayName!: string\n\n @Property({ name: 'email_verified_at', type: Date, nullable: true })\n emailVerifiedAt?: Date | null\n\n @Property({ name: 'failed_login_attempts', type: 'int', default: 0 })\n failedLoginAttempts: number = 0\n\n @Property({ name: 'locked_until', type: Date, nullable: true })\n lockedUntil?: Date | null\n\n @Property({ name: 'last_login_at', type: Date, nullable: true })\n lastLoginAt?: Date | null\n\n @Property({ name: 'sessions_revoked_at', type: Date, nullable: true })\n sessionsRevokedAt?: Date | null\n\n @Property({ name: 'person_entity_id', type: 'uuid', nullable: true })\n @Index({ name: 'customer_users_person_entity_idx' })\n personEntityId?: string | null\n\n @Property({ name: 'customer_entity_id', type: 'uuid', nullable: true })\n @Index({ name: 'customer_users_customer_entity_idx' })\n customerEntityId?: string | null\n\n @Property({ name: 'is_active', type: 'boolean', default: true })\n isActive: boolean = true\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'customer_roles' })\n@Unique({ properties: ['tenantId', 'slug'], name: 'customer_roles_tenant_slug_uniq' })\nexport class CustomerRole {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ type: 'text' })\n name!: string\n\n @Property({ type: 'text' })\n slug!: string\n\n @Property({ type: 'text', nullable: true })\n description?: string | null\n\n @Property({ name: 'is_default', type: 'boolean', default: false })\n isDefault: boolean = false\n\n @Property({ name: 'is_system', type: 'boolean', default: false })\n isSystem: boolean = false\n\n @Property({ name: 'customer_assignable', type: 'boolean', default: false })\n customerAssignable: boolean = false\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'customer_role_acls' })\n@Unique({ properties: ['role', 'tenantId'], name: 'customer_role_acls_role_tenant_uniq' })\nexport class CustomerRoleAcl {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => CustomerRole)\n role!: CustomerRole\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'features_json', type: 'json', nullable: true })\n featuresJson?: string[] | null\n\n @Property({ name: 'is_portal_admin', type: 'boolean', default: false })\n isPortalAdmin: boolean = false\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'customer_user_roles' })\n@Unique({ properties: ['user', 'role'], name: 'customer_user_roles_user_role_uniq' })\nexport class CustomerUserRole {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => CustomerUser)\n user!: CustomerUser\n\n @ManyToOne(() => CustomerRole)\n role!: CustomerRole\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'customer_user_acls' })\n@Unique({ properties: ['user', 'tenantId'], name: 'customer_user_acls_user_tenant_uniq' })\nexport class CustomerUserAcl {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => CustomerUser)\n user!: CustomerUser\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'features_json', type: 'json', nullable: true })\n featuresJson?: string[] | null\n\n @Property({ name: 'is_portal_admin', type: 'boolean', default: false })\n isPortalAdmin: boolean = false\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'customer_user_sessions' })\n@Index({ properties: ['tokenHash'], name: 'customer_user_sessions_token_hash_idx' })\nexport class CustomerUserSession {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => CustomerUser)\n user!: CustomerUser\n\n @Property({ name: 'token_hash', type: 'text' })\n tokenHash!: string\n\n @Property({ name: 'ip_address', type: 'text', nullable: true })\n ipAddress?: string | null\n\n @Property({ name: 'user_agent', type: 'text', nullable: true })\n userAgent?: string | null\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'last_used_at', type: Date, nullable: true })\n lastUsedAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'customer_user_email_verifications' })\n@Index({ properties: ['token'], name: 'customer_user_email_verifications_token_idx' })\nexport class CustomerUserEmailVerification {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => CustomerUser)\n user!: CustomerUser\n\n @Property({ type: 'text' })\n token!: string\n\n @Property({ type: 'text', default: 'email_verification' })\n purpose: string = 'email_verification'\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'used_at', type: Date, nullable: true })\n usedAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n}\n\n@Entity({ tableName: 'customer_user_password_resets' })\n@Index({ properties: ['token'], name: 'customer_user_password_resets_token_idx' })\nexport class CustomerUserPasswordReset {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => CustomerUser)\n user!: CustomerUser\n\n @Property({ type: 'text' })\n token!: string\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'used_at', type: Date, nullable: true })\n usedAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n}\n\n@Entity({ tableName: 'customer_user_invitations' })\n@Index({ properties: ['token'], name: 'customer_user_invitations_token_idx' })\n@Index({ properties: ['tenantId', 'emailHash'], name: 'customer_user_invitations_tenant_email_hash_idx' })\nexport class CustomerUserInvitation {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ type: 'text' })\n email!: string\n\n @Property({ name: 'email_hash', type: 'text' })\n emailHash!: string\n\n @Property({ type: 'text' })\n token!: string\n\n @Property({ name: 'customer_entity_id', type: 'uuid', nullable: true })\n customerEntityId?: string | null\n\n @Property({ name: 'role_ids_json', type: 'json', nullable: true })\n roleIdsJson?: string[] | null\n\n @Property({ name: 'invited_by_user_id', type: 'uuid', nullable: true })\n invitedByUserId?: string | null\n\n @Property({ name: 'invited_by_customer_user_id', type: 'uuid', nullable: true })\n invitedByCustomerUserId?: string | null\n\n @Property({ name: 'display_name', type: 'text', nullable: true })\n displayName?: string | null\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'accepted_at', type: Date, nullable: true })\n acceptedAt?: Date | null\n\n @Property({ name: 'cancelled_at', type: Date, nullable: true })\n cancelledAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n}\n\n@Entity({ tableName: 'domain_mappings' })\n@Unique({ properties: ['hostname'], name: 'domain_mappings_hostname_unique' })\n@Index({ properties: ['organizationId'], name: 'domain_mappings_organization_id_idx' })\n@Index({ properties: ['tenantId'], name: 'domain_mappings_tenant_id_idx' })\n@Unique({\n name: 'domain_mappings_replaces_domain_id_unique',\n expression:\n `create unique index \"domain_mappings_replaces_domain_id_unique\" on \"domain_mappings\" (\"replaces_domain_id\") where \"replaces_domain_id\" is not null`,\n})\n@Index({\n name: 'domain_mappings_pending_verification_idx',\n expression:\n `create index \"domain_mappings_pending_verification_idx\" on \"domain_mappings\" (\"status\", \"last_dns_check_at\") where \"status\" in ('pending', 'dns_failed')`,\n})\n@Index({\n name: 'domain_mappings_pending_tls_idx',\n expression:\n `create index \"domain_mappings_pending_tls_idx\" on \"domain_mappings\" (\"status\", \"updated_at\") where \"status\" in ('verified', 'tls_failed')`,\n})\n@Check({\n name: 'domain_mappings_hostname_normalized_chk',\n expression: `\"hostname\" = lower(\"hostname\") and \"hostname\" not like '%.'`,\n})\nexport class DomainMapping {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ type: 'text' })\n hostname!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @ManyToOne(() => DomainMapping, { fieldName: 'replaces_domain_id', nullable: true })\n replacesDomain?: DomainMapping | null\n\n @Enum({ items: () => DOMAIN_PROVIDERS as unknown as string[], type: 'text', name: 'provider' })\n provider: DomainProvider = 'traefik'\n\n @Enum({ items: () => DOMAIN_STATUSES as unknown as string[], type: 'text', name: 'status' })\n status: DomainStatus = 'pending'\n\n @Property({ name: 'verified_at', type: Date, nullable: true })\n verifiedAt?: Date | null\n\n @Property({ name: 'last_dns_check_at', type: Date, nullable: true })\n lastDnsCheckAt?: Date | null\n\n @Property({ name: 'dns_failure_reason', type: 'text', nullable: true, length: 500 })\n dnsFailureReason?: string | null\n\n @Property({ name: 'tls_failure_reason', type: 'text', nullable: true, length: 500 })\n tlsFailureReason?: string | null\n\n @Property({ name: 'tls_retry_count', type: 'int', default: 0 })\n tlsRetryCount: number = 0\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date | null\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { Check, Entity, Enum, Index, ManyToOne, PrimaryKey, Property, Unique } from '@mikro-orm/decorators/legacy'\n\nexport type DomainProvider = 'traefik'\nexport type DomainStatus = 'pending' | 'verified' | 'active' | 'dns_failed' | 'tls_failed'\n\nexport const DOMAIN_PROVIDERS: readonly DomainProvider[] = ['traefik'] as const\nexport const DOMAIN_STATUSES: readonly DomainStatus[] = [\n 'pending',\n 'verified',\n 'active',\n 'dns_failed',\n 'tls_failed',\n] as const\n\n@Entity({ tableName: 'customer_users' })\n@Unique({ properties: ['tenantId', 'emailHash'], name: 'customer_users_tenant_email_hash_uniq' })\nexport class CustomerUser {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ type: 'text' })\n email!: string\n\n @Property({ name: 'email_hash', type: 'text' })\n @Index({ name: 'customer_users_email_hash_idx' })\n emailHash!: string\n\n @Property({ name: 'password_hash', type: 'text', nullable: true })\n passwordHash?: string | null\n\n @Property({ name: 'display_name', type: 'text' })\n displayName!: string\n\n @Property({ name: 'email_verified_at', type: Date, nullable: true })\n emailVerifiedAt?: Date | null\n\n @Property({ name: 'failed_login_attempts', type: 'int', default: 0 })\n failedLoginAttempts: number = 0\n\n @Property({ name: 'locked_until', type: Date, nullable: true })\n lockedUntil?: Date | null\n\n @Property({ name: 'last_login_at', type: Date, nullable: true })\n lastLoginAt?: Date | null\n\n @Property({ name: 'sessions_revoked_at', type: Date, nullable: true })\n sessionsRevokedAt?: Date | null\n\n @Property({ name: 'person_entity_id', type: 'uuid', nullable: true })\n @Index({ name: 'customer_users_person_entity_idx' })\n personEntityId?: string | null\n\n @Property({ name: 'customer_entity_id', type: 'uuid', nullable: true })\n @Index({ name: 'customer_users_customer_entity_idx' })\n customerEntityId?: string | null\n\n @Property({ name: 'is_active', type: 'boolean', default: true })\n isActive: boolean = true\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'customer_roles' })\n@Unique({ properties: ['tenantId', 'slug'], name: 'customer_roles_tenant_slug_uniq' })\nexport class CustomerRole {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ type: 'text' })\n name!: string\n\n @Property({ type: 'text' })\n slug!: string\n\n @Property({ type: 'text', nullable: true })\n description?: string | null\n\n @Property({ name: 'is_default', type: 'boolean', default: false })\n isDefault: boolean = false\n\n @Property({ name: 'is_system', type: 'boolean', default: false })\n isSystem: boolean = false\n\n @Property({ name: 'customer_assignable', type: 'boolean', default: false })\n customerAssignable: boolean = false\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'customer_role_acls' })\n@Unique({ properties: ['role', 'tenantId'], name: 'customer_role_acls_role_tenant_uniq' })\nexport class CustomerRoleAcl {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => CustomerRole)\n role!: CustomerRole\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'features_json', type: 'json', nullable: true })\n featuresJson?: string[] | null\n\n @Property({ name: 'is_portal_admin', type: 'boolean', default: false })\n isPortalAdmin: boolean = false\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'customer_user_roles' })\n@Unique({ properties: ['user', 'role'], name: 'customer_user_roles_user_role_uniq' })\nexport class CustomerUserRole {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => CustomerUser)\n user!: CustomerUser\n\n @ManyToOne(() => CustomerRole)\n role!: CustomerRole\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'customer_user_acls' })\n@Unique({ properties: ['user', 'tenantId'], name: 'customer_user_acls_user_tenant_uniq' })\nexport class CustomerUserAcl {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => CustomerUser)\n user!: CustomerUser\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'features_json', type: 'json', nullable: true })\n featuresJson?: string[] | null\n\n @Property({ name: 'is_portal_admin', type: 'boolean', default: false })\n isPortalAdmin: boolean = false\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'customer_user_sessions' })\n@Index({ properties: ['tokenHash'], name: 'customer_user_sessions_token_hash_idx' })\nexport class CustomerUserSession {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => CustomerUser)\n user!: CustomerUser\n\n @Property({ name: 'token_hash', type: 'text' })\n tokenHash!: string\n\n @Property({ name: 'ip_address', type: 'text', nullable: true })\n ipAddress?: string | null\n\n @Property({ name: 'user_agent', type: 'text', nullable: true })\n userAgent?: string | null\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'last_used_at', type: Date, nullable: true })\n lastUsedAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'customer_user_email_verifications' })\n@Index({ properties: ['token'], name: 'customer_user_email_verifications_token_idx' })\nexport class CustomerUserEmailVerification {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => CustomerUser)\n user!: CustomerUser\n\n @Property({ type: 'text' })\n token!: string\n\n @Property({ type: 'text', default: 'email_verification' })\n purpose: string = 'email_verification'\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'used_at', type: Date, nullable: true })\n usedAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n}\n\n@Entity({ tableName: 'customer_user_password_resets' })\n@Index({ properties: ['token'], name: 'customer_user_password_resets_token_idx' })\nexport class CustomerUserPasswordReset {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => CustomerUser)\n user!: CustomerUser\n\n @Property({ type: 'text' })\n token!: string\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'used_at', type: Date, nullable: true })\n usedAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n}\n\n@Entity({ tableName: 'customer_user_invitations' })\n@Index({ properties: ['token'], name: 'customer_user_invitations_token_idx' })\n@Index({ properties: ['tenantId', 'emailHash'], name: 'customer_user_invitations_tenant_email_hash_idx' })\nexport class CustomerUserInvitation {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ type: 'text' })\n email!: string\n\n @Property({ name: 'email_hash', type: 'text' })\n emailHash!: string\n\n @Property({ type: 'text' })\n token!: string\n\n @Property({ name: 'customer_entity_id', type: 'uuid', nullable: true })\n customerEntityId?: string | null\n\n @Property({ name: 'person_entity_id', type: 'uuid', nullable: true })\n personEntityId?: string | null\n\n @Property({ name: 'role_ids_json', type: 'json', nullable: true })\n roleIdsJson?: string[] | null\n\n @Property({ name: 'invited_by_user_id', type: 'uuid', nullable: true })\n invitedByUserId?: string | null\n\n @Property({ name: 'invited_by_customer_user_id', type: 'uuid', nullable: true })\n invitedByCustomerUserId?: string | null\n\n @Property({ name: 'display_name', type: 'text', nullable: true })\n displayName?: string | null\n\n @Property({ name: 'expires_at', type: Date })\n expiresAt!: Date\n\n @Property({ name: 'accepted_at', type: Date, nullable: true })\n acceptedAt?: Date | null\n\n @Property({ name: 'cancelled_at', type: Date, nullable: true })\n cancelledAt?: Date | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n}\n\n@Entity({ tableName: 'domain_mappings' })\n@Unique({ properties: ['hostname'], name: 'domain_mappings_hostname_unique' })\n@Index({ properties: ['organizationId'], name: 'domain_mappings_organization_id_idx' })\n@Index({ properties: ['tenantId'], name: 'domain_mappings_tenant_id_idx' })\n@Unique({\n name: 'domain_mappings_replaces_domain_id_unique',\n expression:\n `create unique index \"domain_mappings_replaces_domain_id_unique\" on \"domain_mappings\" (\"replaces_domain_id\") where \"replaces_domain_id\" is not null`,\n})\n@Index({\n name: 'domain_mappings_pending_verification_idx',\n expression:\n `create index \"domain_mappings_pending_verification_idx\" on \"domain_mappings\" (\"status\", \"last_dns_check_at\") where \"status\" in ('pending', 'dns_failed')`,\n})\n@Index({\n name: 'domain_mappings_pending_tls_idx',\n expression:\n `create index \"domain_mappings_pending_tls_idx\" on \"domain_mappings\" (\"status\", \"updated_at\") where \"status\" in ('verified', 'tls_failed')`,\n})\n@Check({\n name: 'domain_mappings_hostname_normalized_chk',\n expression: `\"hostname\" = lower(\"hostname\") and \"hostname\" not like '%.'`,\n})\nexport class DomainMapping {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ type: 'text' })\n hostname!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @ManyToOne(() => DomainMapping, { fieldName: 'replaces_domain_id', nullable: true })\n replacesDomain?: DomainMapping | null\n\n @Enum({ items: () => DOMAIN_PROVIDERS as unknown as string[], type: 'text', name: 'provider' })\n provider: DomainProvider = 'traefik'\n\n @Enum({ items: () => DOMAIN_STATUSES as unknown as string[], type: 'text', name: 'status' })\n status: DomainStatus = 'pending'\n\n @Property({ name: 'verified_at', type: Date, nullable: true })\n verifiedAt?: Date | null\n\n @Property({ name: 'last_dns_check_at', type: Date, nullable: true })\n lastDnsCheckAt?: Date | null\n\n @Property({ name: 'dns_failure_reason', type: 'text', nullable: true, length: 500 })\n dnsFailureReason?: string | null\n\n @Property({ name: 'tls_failure_reason', type: 'text', nullable: true, length: 500 })\n tlsFailureReason?: string | null\n\n @Property({ name: 'tls_retry_count', type: 'int', default: 0 })\n tlsRetryCount: number = 0\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date(), nullable: true })\n updatedAt?: Date | null\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -66,6 +66,7 @@ const updateRoleAclSchema = z.object({
|
|
|
66
66
|
const inviteUserSchema = z.object({
|
|
67
67
|
email: emailField,
|
|
68
68
|
customerEntityId: z.string().uuid().optional(),
|
|
69
|
+
personEntityId: z.string().uuid().optional(),
|
|
69
70
|
roleIds: z.array(z.string().uuid()).min(1),
|
|
70
71
|
displayName: displayNameField.optional()
|
|
71
72
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/customer_accounts/data/validators.ts"],
|
|
4
|
-
"sourcesContent": ["import { z } from 'zod'\nimport { normalizeHostname } from '@open-mercato/core/modules/customer_accounts/lib/hostname'\n\nconst emailField = z.string().email().max(255)\nconst passwordField = z.string().min(8).max(128)\nconst displayNameField = z.string().min(1).max(255)\n\nexport const signupSchema = z.object({\n email: emailField,\n password: passwordField,\n displayName: displayNameField,\n tenantId: z.string().uuid().optional(),\n organizationId: z.string().uuid().optional(),\n})\n\nexport const loginSchema = z.object({\n email: emailField,\n password: z.string().min(1).max(128),\n tenantId: z.string().uuid().optional(),\n organizationId: z.string().uuid().optional(),\n})\n\nexport const emailVerifySchema = z.object({\n token: z.string().min(1).max(512),\n})\n\nexport const passwordResetRequestSchema = z.object({\n email: emailField,\n tenantId: z.string().uuid().optional(),\n})\n\nexport const passwordResetConfirmSchema = z.object({\n token: z.string().min(1).max(512),\n password: passwordField,\n})\n\nexport const magicLinkRequestSchema = z.object({\n email: emailField,\n tenantId: z.string().uuid().optional(),\n})\n\nexport const magicLinkVerifySchema = z.object({\n token: z.string().min(1).max(512),\n})\n\nexport const invitationAcceptSchema = z.object({\n token: z.string().min(1).max(512),\n password: passwordField,\n displayName: displayNameField,\n})\n\nexport const profileUpdateSchema = z.object({\n displayName: displayNameField.optional(),\n})\n\nexport const passwordChangeSchema = z.object({\n currentPassword: z.string().min(1).max(128),\n newPassword: passwordField,\n})\n\nexport const createRoleSchema = z.object({\n name: z.string().min(1).max(255),\n slug: z.string().min(1).max(255).regex(/^[a-z0-9_-]+$/),\n description: z.string().max(1000).optional(),\n isDefault: z.boolean().optional(),\n customerAssignable: z.boolean().optional(),\n})\n\nexport const updateRoleSchema = z.object({\n name: z.string().min(1).max(255).optional(),\n description: z.string().max(1000).optional(),\n isDefault: z.boolean().optional(),\n customerAssignable: z.boolean().optional(),\n})\n\nexport const updateRoleAclSchema = z.object({\n features: z.array(z.string().min(1).max(255)),\n isPortalAdmin: z.boolean().optional(),\n})\n\nexport const inviteUserSchema = z.object({\n email: emailField,\n customerEntityId: z.string().uuid().optional(),\n roleIds: z.array(z.string().uuid()).min(1),\n displayName: displayNameField.optional(),\n})\n\nexport const assignRolesSchema = z.object({\n roleIds: z.array(z.string().uuid()).min(1),\n})\n\nexport const adminCreateUserSchema = z.object({\n email: emailField,\n password: passwordField,\n displayName: displayNameField,\n roleIds: z.array(z.string().uuid()).optional(),\n customerEntityId: z.string().uuid().optional(),\n})\n\nexport const adminUpdateUserSchema = z.object({\n displayName: displayNameField.optional(),\n isActive: z.boolean().optional(),\n lockedUntil: z.string().datetime().nullable().optional(),\n personEntityId: z.string().uuid().nullable().optional(),\n customerEntityId: z.string().uuid().nullable().optional(),\n roleIds: z.array(z.string().uuid()).optional(),\n})\n\nexport const adminResetPasswordSchema = z.object({\n newPassword: passwordField,\n})\n\nexport type AdminCreateUserInput = z.infer<typeof adminCreateUserSchema>\nexport type AdminResetPasswordInput = z.infer<typeof adminResetPasswordSchema>\nexport type SignupInput = z.infer<typeof signupSchema>\nexport type LoginInput = z.infer<typeof loginSchema>\nexport type EmailVerifyInput = z.infer<typeof emailVerifySchema>\nexport type PasswordResetRequestInput = z.infer<typeof passwordResetRequestSchema>\nexport type PasswordResetConfirmInput = z.infer<typeof passwordResetConfirmSchema>\nexport type MagicLinkRequestInput = z.infer<typeof magicLinkRequestSchema>\nexport type MagicLinkVerifyInput = z.infer<typeof magicLinkVerifySchema>\nexport type InvitationAcceptInput = z.infer<typeof invitationAcceptSchema>\nexport type ProfileUpdateInput = z.infer<typeof profileUpdateSchema>\nexport type PasswordChangeInput = z.infer<typeof passwordChangeSchema>\nexport type CreateRoleInput = z.infer<typeof createRoleSchema>\nexport type UpdateRoleInput = z.infer<typeof updateRoleSchema>\nexport type UpdateRoleAclInput = z.infer<typeof updateRoleAclSchema>\nexport type InviteUserInput = z.infer<typeof inviteUserSchema>\nexport type AssignRolesInput = z.infer<typeof assignRolesSchema>\nexport type AdminUpdateUserInput = z.infer<typeof adminUpdateUserSchema>\n\n// Custom domain mapping\nexport const hostnameSchema = z\n .string()\n .min(1, 'Hostname is required')\n .max(512, 'Hostname is too long')\n .transform((value, ctx) => {\n try {\n return normalizeHostname(value)\n } catch (err) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: err instanceof Error ? err.message : 'Invalid hostname',\n })\n return z.NEVER\n }\n })\n\nexport const registerDomainSchema = z.object({\n hostname: hostnameSchema,\n organizationId: z.string().uuid(),\n replacesDomainId: z.string().uuid().optional(),\n})\n\nexport type RegisterDomainInput = z.infer<typeof registerDomainSchema>\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\nimport { normalizeHostname } from '@open-mercato/core/modules/customer_accounts/lib/hostname'\n\nconst emailField = z.string().email().max(255)\nconst passwordField = z.string().min(8).max(128)\nconst displayNameField = z.string().min(1).max(255)\n\nexport const signupSchema = z.object({\n email: emailField,\n password: passwordField,\n displayName: displayNameField,\n tenantId: z.string().uuid().optional(),\n organizationId: z.string().uuid().optional(),\n})\n\nexport const loginSchema = z.object({\n email: emailField,\n password: z.string().min(1).max(128),\n tenantId: z.string().uuid().optional(),\n organizationId: z.string().uuid().optional(),\n})\n\nexport const emailVerifySchema = z.object({\n token: z.string().min(1).max(512),\n})\n\nexport const passwordResetRequestSchema = z.object({\n email: emailField,\n tenantId: z.string().uuid().optional(),\n})\n\nexport const passwordResetConfirmSchema = z.object({\n token: z.string().min(1).max(512),\n password: passwordField,\n})\n\nexport const magicLinkRequestSchema = z.object({\n email: emailField,\n tenantId: z.string().uuid().optional(),\n})\n\nexport const magicLinkVerifySchema = z.object({\n token: z.string().min(1).max(512),\n})\n\nexport const invitationAcceptSchema = z.object({\n token: z.string().min(1).max(512),\n password: passwordField,\n displayName: displayNameField,\n})\n\nexport const profileUpdateSchema = z.object({\n displayName: displayNameField.optional(),\n})\n\nexport const passwordChangeSchema = z.object({\n currentPassword: z.string().min(1).max(128),\n newPassword: passwordField,\n})\n\nexport const createRoleSchema = z.object({\n name: z.string().min(1).max(255),\n slug: z.string().min(1).max(255).regex(/^[a-z0-9_-]+$/),\n description: z.string().max(1000).optional(),\n isDefault: z.boolean().optional(),\n customerAssignable: z.boolean().optional(),\n})\n\nexport const updateRoleSchema = z.object({\n name: z.string().min(1).max(255).optional(),\n description: z.string().max(1000).optional(),\n isDefault: z.boolean().optional(),\n customerAssignable: z.boolean().optional(),\n})\n\nexport const updateRoleAclSchema = z.object({\n features: z.array(z.string().min(1).max(255)),\n isPortalAdmin: z.boolean().optional(),\n})\n\nexport const inviteUserSchema = z.object({\n email: emailField,\n customerEntityId: z.string().uuid().optional(),\n personEntityId: z.string().uuid().optional(),\n roleIds: z.array(z.string().uuid()).min(1),\n displayName: displayNameField.optional(),\n})\n\nexport const assignRolesSchema = z.object({\n roleIds: z.array(z.string().uuid()).min(1),\n})\n\nexport const adminCreateUserSchema = z.object({\n email: emailField,\n password: passwordField,\n displayName: displayNameField,\n roleIds: z.array(z.string().uuid()).optional(),\n customerEntityId: z.string().uuid().optional(),\n})\n\nexport const adminUpdateUserSchema = z.object({\n displayName: displayNameField.optional(),\n isActive: z.boolean().optional(),\n lockedUntil: z.string().datetime().nullable().optional(),\n personEntityId: z.string().uuid().nullable().optional(),\n customerEntityId: z.string().uuid().nullable().optional(),\n roleIds: z.array(z.string().uuid()).optional(),\n})\n\nexport const adminResetPasswordSchema = z.object({\n newPassword: passwordField,\n})\n\nexport type AdminCreateUserInput = z.infer<typeof adminCreateUserSchema>\nexport type AdminResetPasswordInput = z.infer<typeof adminResetPasswordSchema>\nexport type SignupInput = z.infer<typeof signupSchema>\nexport type LoginInput = z.infer<typeof loginSchema>\nexport type EmailVerifyInput = z.infer<typeof emailVerifySchema>\nexport type PasswordResetRequestInput = z.infer<typeof passwordResetRequestSchema>\nexport type PasswordResetConfirmInput = z.infer<typeof passwordResetConfirmSchema>\nexport type MagicLinkRequestInput = z.infer<typeof magicLinkRequestSchema>\nexport type MagicLinkVerifyInput = z.infer<typeof magicLinkVerifySchema>\nexport type InvitationAcceptInput = z.infer<typeof invitationAcceptSchema>\nexport type ProfileUpdateInput = z.infer<typeof profileUpdateSchema>\nexport type PasswordChangeInput = z.infer<typeof passwordChangeSchema>\nexport type CreateRoleInput = z.infer<typeof createRoleSchema>\nexport type UpdateRoleInput = z.infer<typeof updateRoleSchema>\nexport type UpdateRoleAclInput = z.infer<typeof updateRoleAclSchema>\nexport type InviteUserInput = z.infer<typeof inviteUserSchema>\nexport type AssignRolesInput = z.infer<typeof assignRolesSchema>\nexport type AdminUpdateUserInput = z.infer<typeof adminUpdateUserSchema>\n\n// Custom domain mapping\nexport const hostnameSchema = z\n .string()\n .min(1, 'Hostname is required')\n .max(512, 'Hostname is too long')\n .transform((value, ctx) => {\n try {\n return normalizeHostname(value)\n } catch (err) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: err instanceof Error ? err.message : 'Invalid hostname',\n })\n return z.NEVER\n }\n })\n\nexport const registerDomainSchema = z.object({\n hostname: hostnameSchema,\n organizationId: z.string().uuid(),\n replacesDomainId: z.string().uuid().optional(),\n})\n\nexport type RegisterDomainInput = z.infer<typeof registerDomainSchema>\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|