@nextsparkjs/core 0.1.0-beta.194 → 0.1.0-beta.196
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/app/guards/DeveloperGuard.d.ts +8 -1
- package/dist/components/app/guards/DeveloperGuard.d.ts.map +1 -1
- package/dist/components/app/guards/DeveloperGuard.js +2 -1
- package/dist/components/app/guards/SuperAdminGuard.d.ts +8 -1
- package/dist/components/app/guards/SuperAdminGuard.d.ts.map +1 -1
- package/dist/components/app/guards/SuperAdminGuard.js +2 -1
- package/dist/components/billing/InvoicesPagination.js +2 -2
- package/dist/components/dashboard/block-editor/block-picker.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/block-picker.js +2 -1
- package/dist/components/dashboard/block-editor/builder-editor-view.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/builder-editor-view.js +39 -23
- package/dist/components/dashboard/block-editor/pattern-reference-preview.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/pattern-reference-preview.js +2 -1
- package/dist/components/dashboard/layouts/AuthGuard.d.ts.map +1 -1
- package/dist/components/dashboard/layouts/AuthGuard.js +3 -4
- package/dist/components/dashboard/layouts/AuthenticatedDashboardLayout.d.ts.map +1 -1
- package/dist/components/dashboard/layouts/AuthenticatedDashboardLayout.js +9 -10
- package/dist/components/dashboard/layouts/DashboardAuthLayout.d.ts.map +1 -1
- package/dist/components/dashboard/layouts/DashboardAuthLayout.js +3 -4
- package/dist/components/dashboard/layouts/DashboardAuthSkeleton.d.ts +2 -2
- package/dist/components/dashboard/navigation/DynamicNavigation.js +2 -2
- package/dist/components/entities/wrappers/EntityDetailWrapper.d.ts.map +1 -1
- package/dist/components/entities/wrappers/EntityDetailWrapper.js +5 -2
- package/dist/components/entities/wrappers/EntityFormWrapper.d.ts.map +1 -1
- package/dist/components/entities/wrappers/EntityFormWrapper.js +5 -2
- package/dist/components/entities/wrappers/EntityListWrapper.d.ts.map +1 -1
- package/dist/components/entities/wrappers/EntityListWrapper.js +5 -2
- package/dist/components/settings/layouts/SettingsSidebar.d.ts.map +1 -1
- package/dist/components/settings/layouts/SettingsSidebar.js +0 -1
- package/dist/components/teams/CreateTeamButton.js +2 -2
- package/dist/components/teams/CreateTeamDialog.js +1 -1
- package/dist/components/teams/InviteMemberButton.js +3 -3
- package/dist/components/teams/InviteMemberDialog.js +1 -1
- package/dist/components/teams/TeamPendingInvitations.js +2 -2
- package/dist/components/ui/relation-display.d.ts.map +1 -1
- package/dist/components/ui/relation-display.js +2 -1
- package/dist/components/ui/user-display.d.ts.map +1 -1
- package/dist/components/ui/user-display.js +2 -1
- package/dist/emails/otp-verification.d.ts.map +1 -1
- package/dist/emails/otp-verification.js +5 -3
- package/dist/emails/reset-password.d.ts.map +1 -1
- package/dist/emails/reset-password.js +5 -3
- package/dist/emails/team-invitation.d.ts.map +1 -1
- package/dist/emails/team-invitation.js +3 -2
- package/dist/emails/verify-email.d.ts.map +1 -1
- package/dist/emails/verify-email.js +5 -3
- package/dist/hooks/useAuth.d.ts.map +1 -1
- package/dist/hooks/useAuth.js +21 -4
- package/dist/hooks/usePatternUsages.d.ts.map +1 -1
- package/dist/hooks/usePatternUsages.js +3 -2
- package/dist/lib/api/api-error.d.ts +2 -0
- package/dist/lib/api/api-error.d.ts.map +1 -1
- package/dist/lib/api/api-error.js +3 -1
- package/dist/lib/api/auth/dual-auth.d.ts +2 -1
- package/dist/lib/api/auth/dual-auth.d.ts.map +1 -1
- package/dist/lib/api/auth/dual-auth.js +22 -4
- package/dist/lib/api/auth/scope-policy.d.ts +6 -3
- package/dist/lib/api/auth/scope-policy.d.ts.map +1 -1
- package/dist/lib/api/auth.d.ts +2 -0
- package/dist/lib/api/auth.d.ts.map +1 -1
- package/dist/lib/api/auth.js +10 -10
- package/dist/lib/api/client-headers.d.ts +11 -0
- package/dist/lib/api/client-headers.d.ts.map +1 -0
- package/dist/lib/api/client-headers.js +12 -0
- package/dist/lib/api/client-ip.d.ts +59 -0
- package/dist/lib/api/client-ip.d.ts.map +1 -0
- package/dist/lib/api/client-ip.js +91 -0
- package/dist/lib/api/cors-response.d.ts +55 -0
- package/dist/lib/api/cors-response.d.ts.map +1 -0
- package/dist/lib/api/cors-response.js +90 -0
- package/dist/lib/api/entities.d.ts.map +1 -1
- package/dist/lib/api/entities.js +4 -3
- package/dist/lib/api/entity/audit-log.d.ts.map +1 -1
- package/dist/lib/api/entity/audit-log.js +2 -1
- package/dist/lib/api/entity/generic-handler.d.ts.map +1 -1
- package/dist/lib/api/entity/generic-handler.js +23 -8
- package/dist/lib/api/helpers.d.ts +8 -2
- package/dist/lib/api/helpers.d.ts.map +1 -1
- package/dist/lib/api/helpers.js +32 -103
- package/dist/lib/api/keys.d.ts +6 -0
- package/dist/lib/api/keys.d.ts.map +1 -1
- package/dist/lib/api/keys.js +7 -1
- package/dist/lib/api/permission-middleware.d.ts.map +1 -1
- package/dist/lib/api/permission-middleware.js +0 -2
- package/dist/lib/api/rate-limit.d.ts +12 -0
- package/dist/lib/api/rate-limit.d.ts.map +1 -1
- package/dist/lib/api/rate-limit.js +50 -43
- package/dist/lib/api/request-origin.d.ts +16 -7
- package/dist/lib/api/request-origin.d.ts.map +1 -1
- package/dist/lib/api/request-origin.js +43 -20
- package/dist/lib/auth/load-login-page.d.ts +10 -0
- package/dist/lib/auth/load-login-page.d.ts.map +1 -0
- package/dist/lib/auth/load-login-page.js +7 -0
- package/dist/lib/auth/runtime-readiness.d.ts.map +1 -1
- package/dist/lib/auth/runtime-readiness.js +4 -0
- package/dist/lib/auth/sample-accounts.d.ts +17 -0
- package/dist/lib/auth/sample-accounts.d.ts.map +1 -0
- package/dist/lib/auth/sample-accounts.js +22 -0
- package/dist/lib/auth/security-notifications/device-fingerprint.d.ts +1 -8
- package/dist/lib/auth/security-notifications/device-fingerprint.d.ts.map +1 -1
- package/dist/lib/auth/security-notifications/device-fingerprint.js +2 -12
- package/dist/lib/auth-email-callbacks.js +3 -3
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +13 -5
- package/dist/lib/cache/public-entity-cache.d.ts +21 -0
- package/dist/lib/cache/public-entity-cache.d.ts.map +1 -0
- package/dist/lib/cache/public-entity-cache.js +25 -0
- package/dist/lib/config/config-client.d.ts.map +1 -1
- package/dist/lib/config/config-client.js +1 -1
- package/dist/lib/config/config-sync.d.ts.map +1 -1
- package/dist/lib/config/config-sync.js +1 -1
- package/dist/lib/config/public-config-client.d.ts +1 -0
- package/dist/lib/config/public-config-client.d.ts.map +1 -1
- package/dist/lib/config/public-config-client.js +3 -1
- package/dist/lib/config/types.d.ts +2 -0
- package/dist/lib/config/types.d.ts.map +1 -1
- package/dist/lib/constants/reserved-slugs.d.ts +17 -8
- package/dist/lib/constants/reserved-slugs.d.ts.map +1 -1
- package/dist/lib/constants/reserved-slugs.js +16 -52
- package/dist/lib/db.d.ts.map +1 -1
- package/dist/lib/db.js +9 -3
- package/dist/lib/entities/entity-hooks.d.ts.map +1 -1
- package/dist/lib/entities/entity-hooks.js +4 -0
- package/dist/lib/entities/external-api-generator.d.ts.map +1 -1
- package/dist/lib/entities/external-api-generator.js +2 -4
- package/dist/lib/entities/public-slug.d.ts +46 -0
- package/dist/lib/entities/public-slug.d.ts.map +1 -0
- package/dist/lib/entities/public-slug.js +39 -0
- package/dist/lib/mcp/errors.d.ts +2 -0
- package/dist/lib/mcp/errors.d.ts.map +1 -1
- package/dist/lib/mcp/errors.js +3 -1
- package/dist/lib/mcp/index.d.ts +1 -1
- package/dist/lib/mcp/index.d.ts.map +1 -1
- package/dist/lib/mcp/index.js +2 -1
- package/dist/lib/services/generic-entity.service.d.ts.map +1 -1
- package/dist/lib/services/generic-entity.service.js +2 -0
- package/dist/lib/teams/actions.d.ts.map +1 -1
- package/dist/lib/teams/actions.js +0 -1
- package/dist/messages/de/billing.json +12 -1
- package/dist/messages/de/common.json +2 -0
- package/dist/messages/de/docs.json +1 -0
- package/dist/messages/de/features.json +16 -4
- package/dist/messages/de/home.json +5 -0
- package/dist/messages/de/index.d.ts +68 -25
- package/dist/messages/de/index.d.ts.map +1 -1
- package/dist/messages/de/index.js +2 -0
- package/dist/messages/de/index.ts +2 -0
- package/dist/messages/de/settings.json +1 -0
- package/dist/messages/de/teams.json +3 -18
- package/dist/messages/en/billing.json +1 -1
- package/dist/messages/en/common.json +2 -0
- package/dist/messages/en/docs.json +1 -0
- package/dist/messages/en/features.json +16 -4
- package/dist/messages/en/home.json +5 -0
- package/dist/messages/en/index.d.ts +58 -25
- package/dist/messages/en/index.d.ts.map +1 -1
- package/dist/messages/en/index.js +2 -0
- package/dist/messages/en/index.ts +2 -0
- package/dist/messages/en/settings.json +1 -0
- package/dist/messages/en/teams.json +3 -18
- package/dist/messages/es/billing.json +1 -1
- package/dist/messages/es/common.json +2 -0
- package/dist/messages/es/docs.json +1 -0
- package/dist/messages/es/features.json +16 -4
- package/dist/messages/es/home.json +5 -0
- package/dist/messages/es/index.d.ts +41 -8
- package/dist/messages/es/index.d.ts.map +1 -1
- package/dist/messages/es/index.js +2 -0
- package/dist/messages/es/index.ts +2 -0
- package/dist/messages/es/settings.json +1 -0
- package/dist/messages/es/teams.json +3 -0
- package/dist/messages/fr/billing.json +12 -1
- package/dist/messages/fr/common.json +2 -0
- package/dist/messages/fr/docs.json +1 -0
- package/dist/messages/fr/features.json +16 -4
- package/dist/messages/fr/home.json +5 -0
- package/dist/messages/fr/index.d.ts +68 -25
- package/dist/messages/fr/index.d.ts.map +1 -1
- package/dist/messages/fr/index.js +2 -0
- package/dist/messages/fr/index.ts +2 -0
- package/dist/messages/fr/settings.json +1 -0
- package/dist/messages/fr/teams.json +3 -18
- package/dist/messages/it/billing.json +12 -1
- package/dist/messages/it/common.json +2 -0
- package/dist/messages/it/docs.json +1 -0
- package/dist/messages/it/features.json +16 -4
- package/dist/messages/it/home.json +5 -0
- package/dist/messages/it/index.d.ts +68 -25
- package/dist/messages/it/index.d.ts.map +1 -1
- package/dist/messages/it/index.js +2 -0
- package/dist/messages/it/index.ts +2 -0
- package/dist/messages/it/settings.json +1 -0
- package/dist/messages/it/teams.json +3 -18
- package/dist/messages/pt/billing.json +12 -1
- package/dist/messages/pt/common.json +2 -0
- package/dist/messages/pt/docs.json +1 -0
- package/dist/messages/pt/features.json +16 -4
- package/dist/messages/pt/home.json +5 -0
- package/dist/messages/pt/index.d.ts +68 -25
- package/dist/messages/pt/index.d.ts.map +1 -1
- package/dist/messages/pt/index.js +2 -0
- package/dist/messages/pt/index.ts +2 -0
- package/dist/messages/pt/settings.json +1 -0
- package/dist/messages/pt/teams.json +3 -18
- package/dist/migrations/029_sample_accounts_outside_development.sql +55 -0
- package/dist/migrations/090_sample_data.sql +10 -0
- package/dist/routes/(auth)/signup/page.cc.d.ts +3 -8
- package/dist/routes/(auth)/signup/page.cc.d.ts.map +1 -1
- package/dist/routes/(auth)/signup/page.cc.js +7 -1
- package/dist/routes/(auth)/verify-email/page.d.ts.map +1 -1
- package/dist/routes/(auth)/verify-email/page.js +2 -1
- package/dist/routes/(public)/page.cc.d.ts +3 -0
- package/dist/routes/(public)/page.cc.d.ts.map +1 -0
- package/dist/routes/(public)/page.cc.js +3 -0
- package/dist/routes/_internal/area-access.cc.d.ts +21 -0
- package/dist/routes/_internal/area-access.cc.d.ts.map +1 -0
- package/dist/routes/_internal/area-access.cc.js +19 -0
- package/dist/routes/_internal/auth-layout.d.ts.map +1 -1
- package/dist/routes/_internal/auth-layout.js +3 -2
- package/dist/routes/_internal/dashboard-main-shared.d.ts +7 -0
- package/dist/routes/_internal/dashboard-main-shared.d.ts.map +1 -0
- package/dist/routes/_internal/dashboard-main-shared.js +49 -0
- package/dist/routes/_internal/default-auth-layout.d.ts.map +1 -1
- package/dist/routes/_internal/default-auth-layout.js +3 -2
- package/dist/routes/_internal/devtools-layout.cc.d.ts +3 -2
- package/dist/routes/_internal/devtools-layout.cc.d.ts.map +1 -1
- package/dist/routes/_internal/devtools-layout.cc.js +1 -1
- package/dist/routes/_internal/devtools-layout.d.ts +7 -2
- package/dist/routes/_internal/devtools-layout.d.ts.map +1 -1
- package/dist/routes/_internal/devtools-layout.js +4 -4
- package/dist/routes/_internal/entity-detail-route.cc.d.ts +8 -0
- package/dist/routes/_internal/entity-detail-route.cc.d.ts.map +1 -0
- package/dist/routes/_internal/entity-detail-route.cc.js +5 -0
- package/dist/routes/_internal/entity-edit-route.cc.d.ts +8 -0
- package/dist/routes/_internal/entity-edit-route.cc.d.ts.map +1 -0
- package/dist/routes/_internal/entity-edit-route.cc.js +5 -0
- package/dist/routes/_internal/entity-permission-layout.d.ts.map +1 -1
- package/dist/routes/_internal/entity-permission-layout.js +0 -7
- package/dist/routes/_internal/public-archive-route.d.ts +1 -1
- package/dist/routes/_internal/public-archive-route.d.ts.map +1 -1
- package/dist/routes/_internal/public-archive-route.js +8 -3
- package/dist/routes/_internal/public-item-route.cc.d.ts +5 -1
- package/dist/routes/_internal/public-item-route.cc.d.ts.map +1 -1
- package/dist/routes/_internal/public-item-route.cc.js +2 -1
- package/dist/routes/_internal/public-item-route.d.ts +7 -0
- package/dist/routes/_internal/public-item-route.d.ts.map +1 -1
- package/dist/routes/_internal/public-item-route.js +6 -1
- package/dist/routes/_internal/superadmin-layout.cc.d.ts +2 -1
- package/dist/routes/_internal/superadmin-layout.cc.d.ts.map +1 -1
- package/dist/routes/_internal/superadmin-layout.cc.js +1 -1
- package/dist/routes/_internal/superadmin-layout.d.ts +7 -2
- package/dist/routes/_internal/superadmin-layout.d.ts.map +1 -1
- package/dist/routes/_internal/superadmin-layout.js +6 -6
- package/dist/routes/_internal/suspended-route.d.ts +16 -0
- package/dist/routes/_internal/suspended-route.d.ts.map +1 -0
- package/dist/routes/_internal/suspended-route.js +7 -0
- package/dist/routes/api/auth/[...all]/route.d.ts.map +1 -1
- package/dist/routes/api/auth/[...all]/route.js +4 -12
- package/dist/routes/api/csp-report/route.d.ts.map +1 -1
- package/dist/routes/api/csp-report/route.js +2 -13
- package/dist/routes/api/devtools/config/entities/route.d.ts +2 -0
- package/dist/routes/api/devtools/config/entities/route.d.ts.map +1 -1
- package/dist/routes/api/devtools/config/entities/route.js +2 -0
- package/dist/routes/api/devtools/config/theme/route.d.ts +2 -0
- package/dist/routes/api/devtools/config/theme/route.d.ts.map +1 -1
- package/dist/routes/api/devtools/config/theme/route.js +2 -0
- package/dist/routes/api/devtools/tests/[...path]/route.d.ts +2 -0
- package/dist/routes/api/devtools/tests/[...path]/route.d.ts.map +1 -1
- package/dist/routes/api/devtools/tests/[...path]/route.js +2 -0
- package/dist/routes/api/devtools/tests/route.d.ts +2 -0
- package/dist/routes/api/devtools/tests/route.d.ts.map +1 -1
- package/dist/routes/api/devtools/tests/route.js +2 -0
- package/dist/routes/api/health/route.d.ts +2 -0
- package/dist/routes/api/health/route.d.ts.map +1 -1
- package/dist/routes/api/health/route.js +2 -0
- package/dist/routes/api/internal/user-metadata/route.d.ts +2 -0
- package/dist/routes/api/internal/user-metadata/route.d.ts.map +1 -1
- package/dist/routes/api/internal/user-metadata/route.js +2 -0
- package/dist/routes/api/mcp/route.d.ts +2 -0
- package/dist/routes/api/mcp/route.d.ts.map +1 -1
- package/dist/routes/api/mcp/route.js +9 -1
- package/dist/routes/api/superadmin/subscriptions/route.d.ts +2 -0
- package/dist/routes/api/superadmin/subscriptions/route.d.ts.map +1 -1
- package/dist/routes/api/superadmin/subscriptions/route.js +2 -0
- package/dist/routes/api/superadmin/teams/[teamId]/route.d.ts +2 -0
- package/dist/routes/api/superadmin/teams/[teamId]/route.d.ts.map +1 -1
- package/dist/routes/api/superadmin/teams/[teamId]/route.js +2 -0
- package/dist/routes/api/superadmin/teams/route.d.ts +2 -0
- package/dist/routes/api/superadmin/teams/route.d.ts.map +1 -1
- package/dist/routes/api/superadmin/teams/route.js +2 -0
- package/dist/routes/api/superadmin/users/[userId]/route.d.ts +2 -0
- package/dist/routes/api/superadmin/users/[userId]/route.d.ts.map +1 -1
- package/dist/routes/api/superadmin/users/[userId]/route.js +2 -0
- package/dist/routes/api/superadmin/users/route.d.ts +2 -0
- package/dist/routes/api/superadmin/users/route.d.ts.map +1 -1
- package/dist/routes/api/superadmin/users/route.js +2 -0
- package/dist/routes/api/user/delete-account/route.d.ts +2 -0
- package/dist/routes/api/user/delete-account/route.d.ts.map +1 -1
- package/dist/routes/api/user/delete-account/route.js +2 -0
- package/dist/routes/api/user/plan-flags/route.d.ts +2 -0
- package/dist/routes/api/user/plan-flags/route.d.ts.map +1 -1
- package/dist/routes/api/user/plan-flags/route.js +2 -0
- package/dist/routes/api/user/profile/route.d.ts +2 -0
- package/dist/routes/api/user/profile/route.d.ts.map +1 -1
- package/dist/routes/api/user/profile/route.js +4 -3
- package/dist/routes/api/v1/[entity]/[id]/child/[childType]/[childId]/route.d.ts +2 -0
- package/dist/routes/api/v1/[entity]/[id]/child/[childType]/[childId]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/[entity]/[id]/child/[childType]/[childId]/route.js +2 -0
- package/dist/routes/api/v1/[entity]/[id]/child/[childType]/route.d.ts +2 -0
- package/dist/routes/api/v1/[entity]/[id]/child/[childType]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/[entity]/[id]/child/[childType]/route.js +2 -0
- package/dist/routes/api/v1/billing/cancel/route.d.ts +2 -0
- package/dist/routes/api/v1/billing/cancel/route.d.ts.map +1 -1
- package/dist/routes/api/v1/billing/cancel/route.js +2 -0
- package/dist/routes/api/v1/billing/change-plan/route.d.ts +2 -0
- package/dist/routes/api/v1/billing/change-plan/route.d.ts.map +1 -1
- package/dist/routes/api/v1/billing/change-plan/route.js +2 -0
- package/dist/routes/api/v1/billing/check-action/route.d.ts +2 -0
- package/dist/routes/api/v1/billing/check-action/route.d.ts.map +1 -1
- package/dist/routes/api/v1/billing/check-action/route.js +2 -0
- package/dist/routes/api/v1/billing/checkout/route.d.ts +2 -0
- package/dist/routes/api/v1/billing/checkout/route.d.ts.map +1 -1
- package/dist/routes/api/v1/billing/checkout/route.js +2 -0
- package/dist/routes/api/v1/billing/plans/route.d.ts +2 -0
- package/dist/routes/api/v1/billing/plans/route.d.ts.map +1 -1
- package/dist/routes/api/v1/billing/plans/route.js +2 -0
- package/dist/routes/api/v1/billing/portal/route.d.ts +2 -0
- package/dist/routes/api/v1/billing/portal/route.d.ts.map +1 -1
- package/dist/routes/api/v1/billing/portal/route.js +2 -0
- package/dist/routes/api/v1/blocks/[slug]/route.d.ts +2 -0
- package/dist/routes/api/v1/blocks/[slug]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/blocks/[slug]/route.js +2 -0
- package/dist/routes/api/v1/blocks/route.d.ts +2 -0
- package/dist/routes/api/v1/blocks/route.d.ts.map +1 -1
- package/dist/routes/api/v1/blocks/route.js +2 -0
- package/dist/routes/api/v1/blocks/validate/route.d.ts +2 -0
- package/dist/routes/api/v1/blocks/validate/route.d.ts.map +1 -1
- package/dist/routes/api/v1/blocks/validate/route.js +2 -0
- package/dist/routes/api/v1/devtools/blocks/route.d.ts +2 -1
- package/dist/routes/api/v1/devtools/blocks/route.d.ts.map +1 -1
- package/dist/routes/api/v1/devtools/blocks/route.js +2 -9
- package/dist/routes/api/v1/devtools/docs/route.d.ts +2 -0
- package/dist/routes/api/v1/devtools/docs/route.d.ts.map +1 -1
- package/dist/routes/api/v1/devtools/docs/route.js +2 -0
- package/dist/routes/api/v1/devtools/features/route.d.ts +2 -1
- package/dist/routes/api/v1/devtools/features/route.d.ts.map +1 -1
- package/dist/routes/api/v1/devtools/features/route.js +2 -9
- package/dist/routes/api/v1/devtools/flows/route.d.ts +2 -1
- package/dist/routes/api/v1/devtools/flows/route.d.ts.map +1 -1
- package/dist/routes/api/v1/devtools/flows/route.js +2 -9
- package/dist/routes/api/v1/devtools/scheduled-actions/route.d.ts +2 -1
- package/dist/routes/api/v1/devtools/scheduled-actions/route.d.ts.map +1 -1
- package/dist/routes/api/v1/devtools/scheduled-actions/route.js +2 -9
- package/dist/routes/api/v1/devtools/scheduled-actions/run/route.d.ts +2 -1
- package/dist/routes/api/v1/devtools/scheduled-actions/run/route.d.ts.map +1 -1
- package/dist/routes/api/v1/devtools/scheduled-actions/run/route.js +2 -9
- package/dist/routes/api/v1/devtools/testing/route.d.ts +2 -1
- package/dist/routes/api/v1/devtools/testing/route.d.ts.map +1 -1
- package/dist/routes/api/v1/devtools/testing/route.js +2 -9
- package/dist/routes/api/v1/media/[id]/route.d.ts +2 -0
- package/dist/routes/api/v1/media/[id]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/media/[id]/route.js +2 -0
- package/dist/routes/api/v1/media/[id]/tags/route.d.ts +2 -0
- package/dist/routes/api/v1/media/[id]/tags/route.d.ts.map +1 -1
- package/dist/routes/api/v1/media/[id]/tags/route.js +2 -0
- package/dist/routes/api/v1/media/check-duplicates/route.d.ts +2 -0
- package/dist/routes/api/v1/media/check-duplicates/route.d.ts.map +1 -1
- package/dist/routes/api/v1/media/check-duplicates/route.js +2 -0
- package/dist/routes/api/v1/media/route.d.ts +2 -0
- package/dist/routes/api/v1/media/route.d.ts.map +1 -1
- package/dist/routes/api/v1/media/route.js +2 -0
- package/dist/routes/api/v1/media/upload/route.d.ts +4 -1
- package/dist/routes/api/v1/media/upload/route.d.ts.map +1 -1
- package/dist/routes/api/v1/media/upload/route.js +12 -2
- package/dist/routes/api/v1/media-tags/route.d.ts +2 -0
- package/dist/routes/api/v1/media-tags/route.d.ts.map +1 -1
- package/dist/routes/api/v1/media-tags/route.js +2 -0
- package/dist/routes/api/v1/post-categories/[id]/route.d.ts +2 -0
- package/dist/routes/api/v1/post-categories/[id]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/post-categories/[id]/route.js +2 -0
- package/dist/routes/api/v1/post-categories/route.d.ts +2 -0
- package/dist/routes/api/v1/post-categories/route.d.ts.map +1 -1
- package/dist/routes/api/v1/post-categories/route.js +2 -0
- package/dist/routes/api/v1/teams/[teamId]/members/route.d.ts.map +1 -1
- package/dist/routes/api/v1/teams/[teamId]/members/route.js +14 -12
- package/dist/routes/api/v1/teams/[teamId]/subscription/route.d.ts +2 -0
- package/dist/routes/api/v1/teams/[teamId]/subscription/route.d.ts.map +1 -1
- package/dist/routes/api/v1/teams/[teamId]/subscription/route.js +2 -0
- package/dist/routes/api/v1/teams/[teamId]/usage/[limitSlug]/route.d.ts +2 -0
- package/dist/routes/api/v1/teams/[teamId]/usage/[limitSlug]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/teams/[teamId]/usage/[limitSlug]/route.js +2 -0
- package/dist/routes/api/v1/teams/switch/route.d.ts.map +1 -1
- package/dist/routes/api/v1/teams/switch/route.js +4 -1
- package/dist/routes/api/v1/users/[id]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/users/[id]/route.js +3 -2
- package/dist/routes/api/v1/users/docs.md +34 -19
- package/dist/routes/api/v1/users/me/route.d.ts +6 -0
- package/dist/routes/api/v1/users/me/route.d.ts.map +1 -0
- package/dist/routes/api/v1/users/me/route.js +5 -0
- package/dist/routes/api/v1/users/presets.ts +2 -2
- package/dist/routes/dashboard/(main)/layout.cc.d.ts +4 -0
- package/dist/routes/dashboard/(main)/layout.cc.d.ts.map +1 -0
- package/dist/routes/dashboard/(main)/layout.cc.js +10 -0
- package/dist/routes/dashboard/(main)/layout.d.ts.map +1 -1
- package/dist/routes/dashboard/(main)/layout.js +3 -44
- package/dist/routes/dashboard/permission-denied/page.d.ts +1 -1
- package/dist/routes/dashboard/permission-denied/page.d.ts.map +1 -1
- package/dist/routes/dashboard/permission-denied/page.js +5 -1
- package/dist/routes/dashboard/settings/password/page.d.ts.map +1 -1
- package/dist/routes/dashboard/settings/password/page.js +10 -12
- package/dist/routes/devtools/config/page.js +1 -1
- package/dist/routes/devtools/layout.cc.d.ts.map +1 -1
- package/dist/routes/devtools/layout.cc.js +5 -1
- package/dist/routes/devtools/page.js +1 -1
- package/dist/routes/devtools/scheduled-actions/page.js +1 -1
- package/dist/routes/devtools/tests/[[...path]]/page.js +1 -1
- package/dist/routes/manifest.json +10 -0
- package/dist/routes/robots.d.ts +10 -0
- package/dist/routes/robots.d.ts.map +1 -0
- package/dist/routes/robots.js +10 -0
- package/dist/routes/superadmin/layout.cc.d.ts.map +1 -1
- package/dist/routes/superadmin/layout.cc.js +5 -1
- package/dist/routes/variants.json +12 -2
- package/dist/templates/ci-workflows/github/cypress-regression.yml +1 -1
- package/dist/templates/ci-workflows/github/cypress-smoke.yml +2 -1
- package/dist/templates/next.config.mjs +2 -29
- package/dist/templates/projects/blog/api/authors/[username]/route.ts +3 -0
- package/dist/templates/projects/blog/api/authors/route.ts +3 -0
- package/dist/templates/projects/blog/api/posts/public/route.ts +3 -0
- package/dist/templates/projects/starter/README.md +2 -0
- package/dist/templates/projects/starter/docs/public/01-overview/01-introduction.md +2 -0
- package/dist/templates/projects/starter/templates/dashboard/analytics/layout.tsx +14 -0
- package/dist/templates/proxy.ts +27 -9
- package/dist/templates/public/favicon.ico +0 -0
- package/dist/templates/public/uploads/README.md +5 -94
- package/migrations/029_sample_accounts_outside_development.sql +55 -0
- package/migrations/090_sample_data.sql +10 -0
- package/package.json +2 -2
- package/scripts/build/registry/__tests__/api-docs-colocated.test.mjs +3 -0
- package/scripts/build/registry/__tests__/billing-registry.test.mjs +50 -1
- package/scripts/build/registry/__tests__/block-registry.test.mjs +3 -0
- package/scripts/build/registry/__tests__/icons-discovery.test.mjs +3 -0
- package/scripts/build/registry/__tests__/quiet-console.mjs +17 -0
- package/scripts/build/registry/__tests__/safe-fs.test.mjs +3 -0
- package/scripts/build/registry/__tests__/team-roles.test.mjs +3 -0
- package/scripts/build/registry/discovery/permissions.test.mjs +3 -0
- package/scripts/build/registry/discovery/plugin-capabilities.mjs +2 -2
- package/scripts/build/registry/generators/billing-registry.mjs +7 -3
- package/scripts/build/registry/host/README.md +25 -1
- package/scripts/build/registry/host/__tests__/host-area-access.test.mjs +32 -0
- package/scripts/build/registry/host/__tests__/host-entities.test.mjs +32 -1
- package/scripts/build/registry/host/__tests__/host-plan.test.mjs +12 -2
- package/scripts/build/registry/host/__tests__/host-proxy-areas.test.mjs +72 -1
- package/scripts/build/registry/host/entity-routes.mjs +9 -3
- package/scripts/build/registry/host/proxy-areas.mjs +65 -2
- package/scripts/build/registry/host/static-imports.mjs +4 -0
- package/scripts/build/routes-manifest.mjs +13 -1
- package/scripts/db/run-migrations.mjs +30 -10
- package/scripts/db/sample-data.mjs +44 -0
- package/scripts/db/ssl-config.mjs +12 -1
- package/scripts/db/verify-theme-migrations.mjs +6 -0
- package/templates/ci-workflows/github/cypress-regression.yml +1 -1
- package/templates/ci-workflows/github/cypress-smoke.yml +2 -1
- package/templates/next.config.mjs +2 -29
- package/templates/projects/blog/api/authors/[username]/route.ts +3 -0
- package/templates/projects/blog/api/authors/route.ts +3 -0
- package/templates/projects/blog/api/posts/public/route.ts +3 -0
- package/templates/projects/starter/README.md +2 -0
- package/templates/projects/starter/docs/public/01-overview/01-introduction.md +2 -0
- package/templates/projects/starter/templates/dashboard/analytics/layout.tsx +14 -0
- package/templates/proxy.ts +27 -9
- package/templates/public/favicon.ico +0 -0
- package/templates/public/uploads/README.md +5 -94
- package/tests/jest/__mocks__/@nextsparkjs/registries/api-presets-registry.ts +2 -0
- package/tests/jest/__mocks__/@nextsparkjs/registries/mcp-registry.ts +2 -0
- package/dist/templates/projects/starter/public/brand/.gitkeep +0 -0
- package/dist/templates/public/uploads/.gitignore +0 -6
- package/dist/templates/public/uploads/temp/.gitkeep +0 -1
- package/templates/projects/starter/public/brand/.gitkeep +0 -0
- package/templates/public/uploads/.gitignore +0 -6
- package/templates/public/uploads/temp/.gitkeep +0 -1
package/dist/lib/api/auth.js
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
import { queryOne } from "../db.js";
|
|
2
|
-
import { ApiKeyManager } from "./keys.js";
|
|
2
|
+
import { ApiKeyManager, presentedApiKey } from "./keys.js";
|
|
3
3
|
import { apiKeyCache, getCacheKey } from "./cache.js";
|
|
4
4
|
import { TeamMemberService } from "../services/team-member.service.js";
|
|
5
5
|
import { ScopeService } from "../services/scope.service.js";
|
|
6
6
|
function hasScope(auth, requiredScope) {
|
|
7
7
|
return auth.scopes.includes(requiredScope);
|
|
8
8
|
}
|
|
9
|
+
const validatedKeys = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
function getValidatedApiKey(request) {
|
|
11
|
+
return validatedKeys.get(request) ?? null;
|
|
12
|
+
}
|
|
9
13
|
async function validateApiKey(request) {
|
|
10
14
|
const startTime = Date.now();
|
|
11
15
|
try {
|
|
12
|
-
const
|
|
13
|
-
const xApiKeyHeader = request.headers.get("x-api-key");
|
|
14
|
-
let apiKey = null;
|
|
15
|
-
if (authHeader == null ? void 0 : authHeader.startsWith("Bearer ")) {
|
|
16
|
-
apiKey = authHeader.substring(7);
|
|
17
|
-
} else if (xApiKeyHeader) {
|
|
18
|
-
apiKey = xApiKeyHeader;
|
|
19
|
-
}
|
|
16
|
+
const apiKey = presentedApiKey(request.headers);
|
|
20
17
|
if (!apiKey) {
|
|
21
18
|
await constantTimeDelay(startTime);
|
|
22
19
|
return null;
|
|
@@ -72,11 +69,13 @@ async function validateApiKey(request) {
|
|
|
72
69
|
updateLastUsed(keyData.id).catch((error) => {
|
|
73
70
|
console.error("Error updating API key last used:", error);
|
|
74
71
|
});
|
|
75
|
-
|
|
72
|
+
const validated = {
|
|
76
73
|
userId: keyData.userId,
|
|
77
74
|
keyId: keyData.id,
|
|
78
75
|
scopes: keyData.scopes || []
|
|
79
76
|
};
|
|
77
|
+
validatedKeys.set(request, validated);
|
|
78
|
+
return validated;
|
|
80
79
|
} catch (error) {
|
|
81
80
|
console.error("Error validating API key:", error);
|
|
82
81
|
await constantTimeDelay(startTime);
|
|
@@ -245,6 +244,7 @@ async function validateScopesForUser(userId, teamId, requestedScopes) {
|
|
|
245
244
|
export {
|
|
246
245
|
canCreateApiKeys,
|
|
247
246
|
getApiKeyUser,
|
|
247
|
+
getValidatedApiKey,
|
|
248
248
|
hasAllScopes,
|
|
249
249
|
hasAnyScope,
|
|
250
250
|
hasScope,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The custom request headers core's own clients send to /api. The clients set them by these names and
|
|
3
|
+
* CORS_ALLOW_HEADERS (cors-response.ts) is built from this list, so a listed origin's preflight allows
|
|
4
|
+
* every header core's clients send. Client-safe: no imports.
|
|
5
|
+
*/
|
|
6
|
+
export declare const TEAM_ID_HEADER = "x-team-id";
|
|
7
|
+
export declare const BUILDER_SOURCE_HEADER = "x-builder-source";
|
|
8
|
+
export declare const SIGNUP_INTENT_HEADER = "x-signup-intent";
|
|
9
|
+
export declare const VERIFY_FROM_UI_HEADER = "x-verify-from-ui";
|
|
10
|
+
export declare const CLIENT_REQUEST_HEADERS: readonly ["x-team-id", "x-builder-source", "x-signup-intent", "x-verify-from-ui"];
|
|
11
|
+
//# sourceMappingURL=client-headers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-headers.d.ts","sourceRoot":"","sources":["../../../src/lib/api/client-headers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,cAAc,cAAc,CAAA;AACzC,eAAO,MAAM,qBAAqB,qBAAqB,CAAA;AACvD,eAAO,MAAM,oBAAoB,oBAAoB,CAAA;AACrD,eAAO,MAAM,qBAAqB,qBAAqB,CAAA;AAEvD,eAAO,MAAM,sBAAsB,mFAAgG,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const TEAM_ID_HEADER = "x-team-id";
|
|
2
|
+
const BUILDER_SOURCE_HEADER = "x-builder-source";
|
|
3
|
+
const SIGNUP_INTENT_HEADER = "x-signup-intent";
|
|
4
|
+
const VERIFY_FROM_UI_HEADER = "x-verify-from-ui";
|
|
5
|
+
const CLIENT_REQUEST_HEADERS = [TEAM_ID_HEADER, BUILDER_SOURCE_HEADER, SIGNUP_INTENT_HEADER, VERIFY_FROM_UI_HEADER];
|
|
6
|
+
export {
|
|
7
|
+
BUILDER_SOURCE_HEADER,
|
|
8
|
+
CLIENT_REQUEST_HEADERS,
|
|
9
|
+
SIGNUP_INTENT_HEADER,
|
|
10
|
+
TEAM_ID_HEADER,
|
|
11
|
+
VERIFY_FROM_UI_HEADER
|
|
12
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The client address of a request: the one place that decides it, for rate limits, audit logs,
|
|
3
|
+
* security notifications and every other reader in core.
|
|
4
|
+
*
|
|
5
|
+
* Which header can be trusted depends on what sits in front of the app, so the deployment names it:
|
|
6
|
+
*
|
|
7
|
+
* NEXTSPARK_CLIENT_IP_SOURCE=vercel x-vercel-forwarded-for, then x-real-ip (set by Vercel)
|
|
8
|
+
* NEXTSPARK_CLIENT_IP_SOURCE=cloudflare cf-connecting-ip (set by Cloudflare)
|
|
9
|
+
* NEXTSPARK_CLIENT_IP_SOURCE=header:<name> one header that your proxy sets, e.g. header:x-real-ip
|
|
10
|
+
* NEXTSPARK_CLIENT_IP_SOURCE=xff X-Forwarded-For, counting NEXTSPARK_TRUSTED_PROXY_HOPS
|
|
11
|
+
* (default 1) trusted proxies from the right
|
|
12
|
+
* NEXTSPARK_CLIENT_IP_SOURCE=none no client address: every request shares one bucket
|
|
13
|
+
*
|
|
14
|
+
* Unset keeps the order core always used (cf-connecting-ip, rightmost X-Forwarded-For, x-real-ip,
|
|
15
|
+
* true-client-ip), and production logs one warning saying what to set. Next.js gives route handlers
|
|
16
|
+
* no socket address, so 'none' cannot fall back to one.
|
|
17
|
+
* What to set per deployment: the upgrade note in CHANGELOG.md, and https://nextspark.dev/docs.
|
|
18
|
+
*/
|
|
19
|
+
export declare const UNKNOWN_CLIENT_IP = "unknown";
|
|
20
|
+
export type ClientIpSource = {
|
|
21
|
+
kind: 'default';
|
|
22
|
+
} | {
|
|
23
|
+
kind: 'vercel';
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'cloudflare';
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'header';
|
|
28
|
+
header: string;
|
|
29
|
+
} | {
|
|
30
|
+
kind: 'xff';
|
|
31
|
+
hops: number;
|
|
32
|
+
} | {
|
|
33
|
+
kind: 'none';
|
|
34
|
+
};
|
|
35
|
+
type Env = Record<string, string | undefined>;
|
|
36
|
+
/** Reads the setting. Throws on a value it does not understand: a typo must not silently trust a header. */
|
|
37
|
+
export declare function getClientIpSource(env?: Env): ClientIpSource;
|
|
38
|
+
/** The client address of a request, from the source the deployment configured (getClientIpSource). */
|
|
39
|
+
export declare function getClientIp(headers: Headers, env?: Env): string;
|
|
40
|
+
/**
|
|
41
|
+
* getClientIp for readers that only record the address (audit rows, the new-device fingerprint): an invalid
|
|
42
|
+
* setting records UNKNOWN_CLIENT_IP instead of throwing, so the row is still written. Rate limits use getClientIp,
|
|
43
|
+
* which throws.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getRecordedClientIp(headers: Headers, env?: Env): string;
|
|
46
|
+
/**
|
|
47
|
+
* The headers Better Auth's own rate limiter should read (advanced.ipAddress.ipAddressHeaders), or undefined
|
|
48
|
+
* to keep its default. Better Auth trusts only a single-valued header, so 'xff' keeps its default; 'none' names no
|
|
49
|
+
* header, so Better Auth counts every request to a path in one shared bucket.
|
|
50
|
+
*/
|
|
51
|
+
export declare function getBetterAuthIpHeaders(env?: Env): string[] | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Logs once per process when the client address source is invalid (in every environment) or, in production
|
|
54
|
+
* only, not set. Called at server start (logAuthReadinessAtStartup) and again on first use, for projects whose
|
|
55
|
+
* instrumentation does not run it; the flag lives on globalThis so both bundles share it.
|
|
56
|
+
*/
|
|
57
|
+
export declare function warnClientIpSourceAtStartup(env?: Env): void;
|
|
58
|
+
export {};
|
|
59
|
+
//# sourceMappingURL=client-ip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-ip.d.ts","sourceRoot":"","sources":["../../../src/lib/api/client-ip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,eAAO,MAAM,iBAAiB,YAAY,CAAA;AAE1C,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpB,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAI7C,4GAA4G;AAC5G,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,GAAiB,GAAG,cAAc,CAiBxE;AAWD,sGAAsG;AACtG,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,GAAE,GAAiB,GAAG,MAAM,CA2B5E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,GAAE,GAAiB,GAAG,MAAM,CAMpF;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,GAAE,GAAiB,GAAG,MAAM,EAAE,GAAG,SAAS,CAWnF;AAID;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,GAAE,GAAiB,GAAG,IAAI,CAkBxE"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const UNKNOWN_CLIENT_IP = "unknown";
|
|
2
|
+
const HEADER_NAME = /^[a-z0-9!#$%&'*+.^_`|~-]+$/;
|
|
3
|
+
function getClientIpSource(env = process.env) {
|
|
4
|
+
var _a, _b;
|
|
5
|
+
const raw = (_a = env.NEXTSPARK_CLIENT_IP_SOURCE) == null ? void 0 : _a.trim().toLowerCase();
|
|
6
|
+
if (!raw) return { kind: "default" };
|
|
7
|
+
if (raw === "vercel" || raw === "cloudflare" || raw === "none") return { kind: raw };
|
|
8
|
+
if (raw === "xff") {
|
|
9
|
+
const hopsRaw = ((_b = env.NEXTSPARK_TRUSTED_PROXY_HOPS) == null ? void 0 : _b.trim()) || "1";
|
|
10
|
+
const hops = Number(hopsRaw);
|
|
11
|
+
if (!/^\d+$/.test(hopsRaw) || hops < 1) {
|
|
12
|
+
throw new Error("[client-ip] NEXTSPARK_TRUSTED_PROXY_HOPS must be a whole number of 1 or more");
|
|
13
|
+
}
|
|
14
|
+
return { kind: "xff", hops };
|
|
15
|
+
}
|
|
16
|
+
if (raw.startsWith("header:")) {
|
|
17
|
+
const header = raw.slice("header:".length).trim();
|
|
18
|
+
if (HEADER_NAME.test(header)) return { kind: "header", header };
|
|
19
|
+
}
|
|
20
|
+
throw new Error("[client-ip] NEXTSPARK_CLIENT_IP_SOURCE must be vercel, cloudflare, xff, none or header:<name>");
|
|
21
|
+
}
|
|
22
|
+
function entries(value) {
|
|
23
|
+
return value ? value.split(",").map((ip) => ip.trim()).filter(Boolean) : [];
|
|
24
|
+
}
|
|
25
|
+
function lastEntry(value) {
|
|
26
|
+
return entries(value).at(-1) ?? null;
|
|
27
|
+
}
|
|
28
|
+
function getClientIp(headers, env = process.env) {
|
|
29
|
+
warnClientIpSourceAtStartup(env);
|
|
30
|
+
const source = getClientIpSource(env);
|
|
31
|
+
switch (source.kind) {
|
|
32
|
+
case "vercel":
|
|
33
|
+
return lastEntry(headers.get("x-vercel-forwarded-for")) ?? lastEntry(headers.get("x-real-ip")) ?? UNKNOWN_CLIENT_IP;
|
|
34
|
+
case "cloudflare":
|
|
35
|
+
return lastEntry(headers.get("cf-connecting-ip")) ?? UNKNOWN_CLIENT_IP;
|
|
36
|
+
case "header":
|
|
37
|
+
return lastEntry(headers.get(source.header)) ?? UNKNOWN_CLIENT_IP;
|
|
38
|
+
case "xff": {
|
|
39
|
+
const ips = entries(headers.get("x-forwarded-for"));
|
|
40
|
+
return ips.length >= source.hops ? ips[ips.length - source.hops] : UNKNOWN_CLIENT_IP;
|
|
41
|
+
}
|
|
42
|
+
case "none":
|
|
43
|
+
return UNKNOWN_CLIENT_IP;
|
|
44
|
+
default:
|
|
45
|
+
return headers.get("cf-connecting-ip") || lastEntry(headers.get("x-forwarded-for")) || headers.get("x-real-ip") || headers.get("true-client-ip") || UNKNOWN_CLIENT_IP;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function getRecordedClientIp(headers, env = process.env) {
|
|
49
|
+
try {
|
|
50
|
+
return getClientIp(headers, env);
|
|
51
|
+
} catch {
|
|
52
|
+
return UNKNOWN_CLIENT_IP;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function getBetterAuthIpHeaders(env = process.env) {
|
|
56
|
+
try {
|
|
57
|
+
const source = getClientIpSource(env);
|
|
58
|
+
if (source.kind === "vercel") return ["x-vercel-forwarded-for", "x-real-ip"];
|
|
59
|
+
if (source.kind === "cloudflare") return ["cf-connecting-ip"];
|
|
60
|
+
if (source.kind === "header") return [source.header];
|
|
61
|
+
if (source.kind === "none") return [];
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
return void 0;
|
|
65
|
+
}
|
|
66
|
+
const WARNED = /* @__PURE__ */ Symbol.for("nextspark.clientIpSourceWarned");
|
|
67
|
+
function warnClientIpSourceAtStartup(env = process.env) {
|
|
68
|
+
const state = globalThis;
|
|
69
|
+
if (state[WARNED]) return;
|
|
70
|
+
let source;
|
|
71
|
+
try {
|
|
72
|
+
source = getClientIpSource(env);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
state[WARNED] = true;
|
|
75
|
+
console.error(error.message);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (source.kind !== "default" || env.NODE_ENV !== "production") return;
|
|
79
|
+
state[WARNED] = true;
|
|
80
|
+
console.warn(
|
|
81
|
+
"[client-ip] NEXTSPARK_CLIENT_IP_SOURCE is not set, so rate limits and audit logs read the client address from request headers in a fixed order. Set it for your deployment: vercel, cloudflare, xff (with NEXTSPARK_TRUSTED_PROXY_HOPS) or header:<name>; none if nothing in front sets a client address."
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
export {
|
|
85
|
+
UNKNOWN_CLIENT_IP,
|
|
86
|
+
getBetterAuthIpHeaders,
|
|
87
|
+
getClientIp,
|
|
88
|
+
getClientIpSource,
|
|
89
|
+
getRecordedClientIp,
|
|
90
|
+
warnClientIpSourceAtStartup
|
|
91
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core's CORS answer for /api responses, in one place: addCorsHeaders and wrapAuthHandlerWithCors (helpers.ts)
|
|
3
|
+
* and the common route wrapper (withRateLimitTier) all use it, so every response and preflight a route gives
|
|
4
|
+
* names the same origin, with or without credentials, for the same request.
|
|
5
|
+
*/
|
|
6
|
+
import { NextResponse } from 'next/server';
|
|
7
|
+
import type { ApplicationConfig } from '../config/config-types';
|
|
8
|
+
type CorsConfig = Pick<ApplicationConfig, 'api'>;
|
|
9
|
+
export declare const CORS_ALLOW_METHODS = "GET, POST, PUT, PATCH, DELETE, OPTIONS";
|
|
10
|
+
export declare const CORS_ALLOW_HEADERS: string;
|
|
11
|
+
/**
|
|
12
|
+
* True for a path under the admin or developer areas, which answer CORS only to the app's own origin and accept
|
|
13
|
+
* cookie-authenticated writes only from it (checkRequestOrigin).
|
|
14
|
+
*/
|
|
15
|
+
export declare function isAppOnlyCorsPath(pathname: string): boolean;
|
|
16
|
+
/** A request's path, for corsGrant (undefined when its URL does not parse, which corsGrant treats as app-only). */
|
|
17
|
+
export declare function requestPathname(request: Request): string | undefined;
|
|
18
|
+
/** The app's own origins: NEXT_PUBLIC_APP_URL and BETTER_AUTH_URL. */
|
|
19
|
+
export declare function appOrigins(): string[];
|
|
20
|
+
/**
|
|
21
|
+
* Which origin a CORS response may name, and whether credentials go with it.
|
|
22
|
+
* A listed origin (getCorsOrigins, wildcard entries allowed) is echoed with
|
|
23
|
+
* credentials. In development with allowAllOrigins.development, any other
|
|
24
|
+
* origin is echoed too, but with credentials only when the cookie-write origin
|
|
25
|
+
* check trusts it (getTrustedOrigins). Any other origin gets no grant: the
|
|
26
|
+
* response names no origin and sends no credentials header.
|
|
27
|
+
* Under the admin and developer areas (isAppOnlyCorsPath, given the request's
|
|
28
|
+
* `pathname`), only the app's own origin is granted, with credentials; no
|
|
29
|
+
* other origin, listed or not. A `pathname` that is undefined (not known)
|
|
30
|
+
* gets the same answer as those areas.
|
|
31
|
+
*/
|
|
32
|
+
export declare function corsGrant(origin: string, config: CorsConfig, env: string, pathname?: string): {
|
|
33
|
+
origin: string;
|
|
34
|
+
credentials: boolean;
|
|
35
|
+
} | null;
|
|
36
|
+
/** `Vary: Origin` once, however many times CORS is applied to the same response. */
|
|
37
|
+
export declare function varyOnOrigin(headers: Headers): void;
|
|
38
|
+
/** Core's CORS headers for a request's grant (corsGrant; null for none), written onto `headers`. */
|
|
39
|
+
export declare function setCorsHeaders(headers: Headers, grant: {
|
|
40
|
+
origin: string;
|
|
41
|
+
credentials: boolean;
|
|
42
|
+
} | null): void;
|
|
43
|
+
/**
|
|
44
|
+
* `response` with core's CORS for `request`. A response that already names an origin was answered by its
|
|
45
|
+
* route (addCorsHeaders, or a CORS policy of its own) and is returned as it is. A response with read-only
|
|
46
|
+
* headers is copied first.
|
|
47
|
+
*/
|
|
48
|
+
export declare function withCors<R extends Response>(response: R, request: Request): R;
|
|
49
|
+
/**
|
|
50
|
+
* A CORS preflight answered with the same grant the route's responses get. Routes export it as their
|
|
51
|
+
* `OPTIONS`: without one, Next.js answers OPTIONS itself, with no CORS headers.
|
|
52
|
+
*/
|
|
53
|
+
export declare function corsPreflight(request: Request): NextResponse;
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=cors-response.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cors-response.d.ts","sourceRoot":"","sources":["../../../src/lib/api/cors-response.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAG/D,KAAK,UAAU,GAAG,IAAI,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAA;AAEhD,eAAO,MAAM,kBAAkB,2CAA2C,CAAA;AAC1E,eAAO,MAAM,kBAAkB,QAAuF,CAAA;AAKtH;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAM3D;AAED,mHAAmH;AACnH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAEpE;AAED,sEAAsE;AACtE,wBAAgB,UAAU,IAAI,MAAM,EAAE,CAKrC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,GAChB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAYjD;AAED,oFAAoF;AACpF,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAGnD;AAED,oGAAoG;AACpG,wBAAgB,cAAc,CAC5B,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,GACrD,IAAI,CAWN;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,CAa7E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,CAE5D"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { APP_CONFIG_MERGED } from "../config/index.js";
|
|
3
|
+
import { getCorsOrigins, getTrustedOrigins, isOriginAllowed, normalizeOrigin } from "../utils/cors.js";
|
|
4
|
+
import { CLIENT_REQUEST_HEADERS } from "./client-headers.js";
|
|
5
|
+
const CORS_ALLOW_METHODS = "GET, POST, PUT, PATCH, DELETE, OPTIONS";
|
|
6
|
+
const CORS_ALLOW_HEADERS = ["Content-Type", "Authorization", "X-API-Key", ...CLIENT_REQUEST_HEADERS].join(", ");
|
|
7
|
+
const APP_ONLY_PATH = /(^|\/)api\/(v1\/)?(superadmin|devtools)(\/|$)/;
|
|
8
|
+
function isAppOnlyCorsPath(pathname) {
|
|
9
|
+
const path = pathname.split("/").map((segment) => {
|
|
10
|
+
try {
|
|
11
|
+
return decodeURIComponent(segment);
|
|
12
|
+
} catch {
|
|
13
|
+
return segment;
|
|
14
|
+
}
|
|
15
|
+
}).join("/");
|
|
16
|
+
return APP_ONLY_PATH.test(path.toLowerCase().replace(/\/{2,}/g, "/"));
|
|
17
|
+
}
|
|
18
|
+
function requestPathname(request) {
|
|
19
|
+
try {
|
|
20
|
+
return new URL(request.url).pathname;
|
|
21
|
+
} catch {
|
|
22
|
+
return void 0;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function appOrigins() {
|
|
26
|
+
return [process.env.NEXT_PUBLIC_APP_URL, process.env.BETTER_AUTH_URL].flatMap((url) => {
|
|
27
|
+
if (!url) return [];
|
|
28
|
+
try {
|
|
29
|
+
return [new URL(url).origin];
|
|
30
|
+
} catch {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function corsGrant(origin, config, env, pathname) {
|
|
36
|
+
const normalizedOrigin = normalizeOrigin(origin);
|
|
37
|
+
if (pathname === void 0 || isAppOnlyCorsPath(pathname)) {
|
|
38
|
+
return appOrigins().includes(normalizedOrigin) ? { origin: normalizedOrigin, credentials: true } : null;
|
|
39
|
+
}
|
|
40
|
+
const listed = isOriginAllowed(normalizedOrigin, getCorsOrigins(config, env));
|
|
41
|
+
if (listed) return { origin: listed, credentials: true };
|
|
42
|
+
if (env === "development" && config.api.cors.allowAllOrigins.development) {
|
|
43
|
+
const trusted = isOriginAllowed(normalizedOrigin, getTrustedOrigins(config, normalizedOrigin, env));
|
|
44
|
+
return { origin: normalizedOrigin, credentials: trusted !== null };
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
function varyOnOrigin(headers) {
|
|
49
|
+
const vary = headers.get("vary") ?? "";
|
|
50
|
+
if (!vary.split(",").some((value) => value.trim().toLowerCase() === "origin")) headers.set("Vary", vary ? `${vary}, Origin` : "Origin");
|
|
51
|
+
}
|
|
52
|
+
function setCorsHeaders(headers, grant) {
|
|
53
|
+
if (grant) {
|
|
54
|
+
headers.set("Access-Control-Allow-Origin", grant.origin);
|
|
55
|
+
if (grant.credentials) headers.set("Access-Control-Allow-Credentials", "true");
|
|
56
|
+
}
|
|
57
|
+
varyOnOrigin(headers);
|
|
58
|
+
headers.set("Access-Control-Allow-Methods", CORS_ALLOW_METHODS);
|
|
59
|
+
headers.set("Access-Control-Allow-Headers", CORS_ALLOW_HEADERS);
|
|
60
|
+
headers.set("Access-Control-Max-Age", "86400");
|
|
61
|
+
}
|
|
62
|
+
function withCors(response, request) {
|
|
63
|
+
if (response.headers.has("access-control-allow-origin")) return response;
|
|
64
|
+
const origin = request.headers.get("origin");
|
|
65
|
+
const env = process.env.NODE_ENV || "development";
|
|
66
|
+
const grant = origin ? corsGrant(origin, APP_CONFIG_MERGED, env, requestPathname(request)) : null;
|
|
67
|
+
try {
|
|
68
|
+
setCorsHeaders(response.headers, grant);
|
|
69
|
+
return response;
|
|
70
|
+
} catch {
|
|
71
|
+
const copy = new Response(response.body, { status: response.status, statusText: response.statusText, headers: new Headers(response.headers) });
|
|
72
|
+
setCorsHeaders(copy.headers, grant);
|
|
73
|
+
return copy;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function corsPreflight(request) {
|
|
77
|
+
return withCors(new NextResponse(null, { status: 204 }), request);
|
|
78
|
+
}
|
|
79
|
+
export {
|
|
80
|
+
CORS_ALLOW_HEADERS,
|
|
81
|
+
CORS_ALLOW_METHODS,
|
|
82
|
+
appOrigins,
|
|
83
|
+
corsGrant,
|
|
84
|
+
corsPreflight,
|
|
85
|
+
isAppOnlyCorsPath,
|
|
86
|
+
requestPathname,
|
|
87
|
+
setCorsHeaders,
|
|
88
|
+
varyOnOrigin,
|
|
89
|
+
withCors
|
|
90
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../../src/lib/api/entities.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../../src/lib/api/entities.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/api/entities.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getClientEntityApiPath, getClientEntityConfigs } from "../entities/client-entity-meta.js";
|
|
2
2
|
import { withBasePath, withBasePathIfInApp } from "../base-path.js";
|
|
3
|
+
import { BUILDER_SOURCE_HEADER, TEAM_ID_HEADER } from "./client-headers.js";
|
|
3
4
|
function getApiBaseUrl() {
|
|
4
5
|
if (typeof window !== "undefined") {
|
|
5
6
|
return window.location.origin;
|
|
@@ -20,7 +21,7 @@ function buildHeaders(additionalHeaders = {}) {
|
|
|
20
21
|
};
|
|
21
22
|
const teamId = getCurrentTeamId();
|
|
22
23
|
if (teamId) {
|
|
23
|
-
headers[
|
|
24
|
+
headers[TEAM_ID_HEADER] = teamId;
|
|
24
25
|
}
|
|
25
26
|
return headers;
|
|
26
27
|
}
|
|
@@ -418,7 +419,7 @@ class EntityApiClient {
|
|
|
418
419
|
delete copyData.createdAt;
|
|
419
420
|
delete copyData.updatedAt;
|
|
420
421
|
const hasBlocks = "blocks" in copyData && Array.isArray(copyData.blocks);
|
|
421
|
-
return this.create(entityType, copyData, hasBlocks ? {
|
|
422
|
+
return this.create(entityType, copyData, hasBlocks ? { [BUILDER_SOURCE_HEADER]: "true" } : {});
|
|
422
423
|
}
|
|
423
424
|
/**
|
|
424
425
|
* Detect if entity has custom override (client-side detection)
|
|
@@ -474,7 +475,7 @@ async function fetchWithTeam(url, options = {}) {
|
|
|
474
475
|
headers.set("Content-Type", "application/json");
|
|
475
476
|
}
|
|
476
477
|
if (activeTeamId) {
|
|
477
|
-
headers.set(
|
|
478
|
+
headers.set(TEAM_ID_HEADER, activeTeamId);
|
|
478
479
|
}
|
|
479
480
|
return fetch(withBasePathIfInApp(url), {
|
|
480
481
|
...options,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-log.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/entity/audit-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"audit-log.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/entity/audit-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAG9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAEvD;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,cAAc,GAAG,IAAI,CAAA;CAC5B;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,cAAc,GAAG,IAAI,EAC3B,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAqDf"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mutateWithRLS } from "../../db.js";
|
|
2
|
+
import { getRecordedClientIp } from "../client-ip.js";
|
|
2
3
|
async function logGenericHandlerUsage(auth, request, statusCode, responseTime) {
|
|
3
4
|
var _a;
|
|
4
5
|
const userId = (_a = auth == null ? void 0 : auth.user) == null ? void 0 : _a.id;
|
|
@@ -9,7 +10,7 @@ async function logGenericHandlerUsage(auth, request, statusCode, responseTime) {
|
|
|
9
10
|
try {
|
|
10
11
|
endpoint = request.nextUrl.pathname;
|
|
11
12
|
method = request.method;
|
|
12
|
-
const ipAddress =
|
|
13
|
+
const ipAddress = getRecordedClientIp(request.headers);
|
|
13
14
|
const userAgent = request.headers.get("user-agent");
|
|
14
15
|
await mutateWithRLS(
|
|
15
16
|
`INSERT INTO "api_audit_log"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generic-handler.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/entity/generic-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"generic-handler.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/entity/generic-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AA4wBvD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAEnF;AA8lBD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAErF;AAyaD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAEpJ;AAoND;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAEtJ;AA6ZD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAEtJ;AAwKD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAEtF"}
|
|
@@ -2,6 +2,8 @@ import { NextResponse } from "next/server";
|
|
|
2
2
|
import { authenticateRequest, createAuthFailureResponse, canBypassTeamContext } from "../auth/dual-auth.js";
|
|
3
3
|
import { resolveEntityFromUrl, validateEntityOperation } from "./resolver.js";
|
|
4
4
|
import { generateEntitySchemas } from "../../entities/schema-generator.js";
|
|
5
|
+
import { publicSlugIssue, otherBasePathSegments } from "../../entities/public-slug.js";
|
|
6
|
+
import { getAllEntityConfigs } from "../../entities/registry.js";
|
|
5
7
|
import { entityResponseSystemColumns, taxonomyResponseFields } from "../../entities/portable/response-shape.js";
|
|
6
8
|
import { queryWithRLS, mutateWithRLS, queryOneWithRLS } from "../../db.js";
|
|
7
9
|
import {
|
|
@@ -348,13 +350,11 @@ async function checkAuthPermission(authResult, entitySlug, action, teamId, reque
|
|
|
348
350
|
}
|
|
349
351
|
async function validateTeamMembership(userId, teamId) {
|
|
350
352
|
try {
|
|
351
|
-
console.log("[GenericHandler] Validating team membership:", { userId, teamId, teamIdLength: teamId == null ? void 0 : teamId.length });
|
|
352
353
|
const member = await queryOneWithRLS(
|
|
353
354
|
'SELECT id FROM "team_members" WHERE "teamId" = $1 AND "userId" = $2',
|
|
354
355
|
[teamId, userId],
|
|
355
356
|
userId
|
|
356
357
|
);
|
|
357
|
-
console.log("[GenericHandler] Team membership result:", { found: !!member, memberId: member == null ? void 0 : member.id });
|
|
358
358
|
return !!member;
|
|
359
359
|
} catch (error) {
|
|
360
360
|
console.error("[GenericHandler] Error validating team membership:", error);
|
|
@@ -365,7 +365,6 @@ async function validateTeamContextWithBypass(request, authResult, userId) {
|
|
|
365
365
|
const teamId = getTeamIdFromRequest(request);
|
|
366
366
|
const canBypass = await canBypassTeamContext(authResult, request);
|
|
367
367
|
if (canBypass) {
|
|
368
|
-
console.log("[GenericHandler] Admin bypass active:", { userId, teamId: teamId || "cross-team" });
|
|
369
368
|
return { valid: true, teamId, isBypass: true };
|
|
370
369
|
}
|
|
371
370
|
if (!teamId) {
|
|
@@ -832,6 +831,10 @@ async function handleGenericCreateImpl(request, audit) {
|
|
|
832
831
|
return addCorsHeaders(response2, request);
|
|
833
832
|
}
|
|
834
833
|
let validatedData = validation.data;
|
|
834
|
+
const slugIssue = publicSlugIssue(entityConfig, validatedData, otherBasePathSegments(entityConfig, getAllEntityConfigs()));
|
|
835
|
+
if (slugIssue) {
|
|
836
|
+
return addCorsHeaders(createApiError(slugIssue.message, 400, [slugIssue], "VALIDATION_ERROR"), request);
|
|
837
|
+
}
|
|
835
838
|
const xssField = checkNameFieldXss(entityConfig, validatedData);
|
|
836
839
|
if (xssField) {
|
|
837
840
|
const xssResponse = createApiError(
|
|
@@ -1204,7 +1207,7 @@ async function handleGenericUpdate(request, { params }) {
|
|
|
1204
1207
|
return runWithAuditLog(request, (audit) => handleGenericUpdateImpl(request, audit, { params }));
|
|
1205
1208
|
}
|
|
1206
1209
|
async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
1207
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
1210
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1208
1211
|
try {
|
|
1209
1212
|
const { id } = await params;
|
|
1210
1213
|
const resolution = await resolveEntityFromUrl(request.nextUrl.pathname);
|
|
@@ -1285,6 +1288,18 @@ async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
|
1285
1288
|
return addCorsHeaders(response2, request);
|
|
1286
1289
|
}
|
|
1287
1290
|
let validatedData = validation.data;
|
|
1291
|
+
let slugIssue = publicSlugIssue(entityConfig, validatedData, otherBasePathSegments(entityConfig, getAllEntityConfigs()));
|
|
1292
|
+
if (slugIssue) {
|
|
1293
|
+
const current = await queryWithRLS(
|
|
1294
|
+
`SELECT "slug" FROM "${tableName}" WHERE id = $1 AND "teamId" = $2`,
|
|
1295
|
+
[id, teamId],
|
|
1296
|
+
authResult.user.id
|
|
1297
|
+
);
|
|
1298
|
+
if (((_d = current[0]) == null ? void 0 : _d.slug) === validatedData.slug) slugIssue = null;
|
|
1299
|
+
}
|
|
1300
|
+
if (slugIssue) {
|
|
1301
|
+
return addCorsHeaders(createApiError(slugIssue.message, 400, [slugIssue], "VALIDATION_ERROR"), request);
|
|
1302
|
+
}
|
|
1288
1303
|
const updateXssField = checkNameFieldXss(entityConfig, validatedData);
|
|
1289
1304
|
if (updateXssField) {
|
|
1290
1305
|
const updateXssResponse = createApiError(
|
|
@@ -1316,7 +1331,7 @@ async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
|
1316
1331
|
const values = [];
|
|
1317
1332
|
let paramCount = 1;
|
|
1318
1333
|
const builderRequest = isBuilderRequest(request);
|
|
1319
|
-
const entityHasBuilder = ((
|
|
1334
|
+
const entityHasBuilder = ((_e = entityConfig.builder) == null ? void 0 : _e.enabled) === true;
|
|
1320
1335
|
if (builderRequest && entityHasBuilder && "blocks" in entityData) {
|
|
1321
1336
|
let blocksData = entityData.blocks;
|
|
1322
1337
|
blocksData = await filterOrphanedPatternReferences(blocksData, authResult.user.id);
|
|
@@ -1392,7 +1407,7 @@ async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
|
1392
1407
|
whereConditions.push(`"teamId" = $${paramCount++}`);
|
|
1393
1408
|
values.push(teamId);
|
|
1394
1409
|
}
|
|
1395
|
-
if (!((
|
|
1410
|
+
if (!((_f = entityConfig.access) == null ? void 0 : _f.shared)) {
|
|
1396
1411
|
whereConditions.push(`"userId" = $${paramCount++}`);
|
|
1397
1412
|
values.push(authResult.user.id);
|
|
1398
1413
|
}
|
|
@@ -1436,7 +1451,7 @@ async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
|
1436
1451
|
}
|
|
1437
1452
|
updatedItem = result[0];
|
|
1438
1453
|
}
|
|
1439
|
-
if ((
|
|
1454
|
+
if ((_g = entityConfig.taxonomies) == null ? void 0 : _g.enabled) {
|
|
1440
1455
|
await processTaxonomyRelations(entityConfig, id, body, authResult.user.id, true);
|
|
1441
1456
|
}
|
|
1442
1457
|
if (metadataWasProvided) {
|
|
@@ -1448,7 +1463,7 @@ async function handleGenericUpdateImpl(request, audit, { params }) {
|
|
|
1448
1463
|
);
|
|
1449
1464
|
}
|
|
1450
1465
|
let responseItem = updatedItem;
|
|
1451
|
-
if ((
|
|
1466
|
+
if ((_h = entityConfig.taxonomies) == null ? void 0 : _h.enabled) {
|
|
1452
1467
|
const itemsWithTaxonomies = await includeTaxonomiesInData(
|
|
1453
1468
|
entityConfig,
|
|
1454
1469
|
[updatedItem],
|
|
@@ -46,7 +46,9 @@ export declare function validateAndAuthenticateApiRequest(request: NextRequest):
|
|
|
46
46
|
rateLimitResponse?: NextResponse;
|
|
47
47
|
}>;
|
|
48
48
|
/**
|
|
49
|
-
*
|
|
49
|
+
* The API key this request was authenticated with: the one validateApiKey accepted for it (directly, or through
|
|
50
|
+
* authenticateRequest / validateAndAuthenticateRequest). Throws when no key was validated for the request.
|
|
51
|
+
* Identity never comes from request headers.
|
|
50
52
|
* @deprecated Use validateAndAuthenticateApiRequest instead
|
|
51
53
|
*/
|
|
52
54
|
export declare function getApiAuth(request: NextRequest): ApiKeyAuth;
|
|
@@ -106,6 +108,10 @@ export declare function createPaginationMeta(page: number, limit: number, total:
|
|
|
106
108
|
export declare function logApiUsage(auth: ApiKeyAuth, request: NextRequest, statusCode: number, responseTime?: number, requestBody?: unknown): Promise<void>;
|
|
107
109
|
/**
|
|
108
110
|
* Wrapper para endpoints que agrega logging automático
|
|
111
|
+
*
|
|
112
|
+
* Writes an api_audit_log row for a request authenticated with an API key, attributed to the key the handler
|
|
113
|
+
* validated (getValidatedApiKey), never to identity headers in the request. Requests without a validated key
|
|
114
|
+
* are not logged here. The request body is not stored, as in entity/audit-log.ts: payloads carry personal data.
|
|
109
115
|
*/
|
|
110
116
|
export declare function withApiLogging<T extends unknown[]>(handler: (request: NextRequest, ...args: T) => Promise<NextResponse>): (request: NextRequest, ...args: T) => Promise<NextResponse>;
|
|
111
117
|
/**
|
|
@@ -125,7 +131,7 @@ export declare function sanitizeSearchQuery(query: string): string;
|
|
|
125
131
|
export declare function parseFilters(request: NextRequest): Record<string, string>;
|
|
126
132
|
/**
|
|
127
133
|
* Agrega headers de CORS para API externa
|
|
128
|
-
* Uses unified getCorsOrigins() for single source of truth
|
|
134
|
+
* Uses unified getCorsOrigins() for single source of truth (see corsGrant)
|
|
129
135
|
*/
|
|
130
136
|
export declare function addCorsHeaders(response: NextResponse, request?: NextRequest): Promise<NextResponse>;
|
|
131
137
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/api/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/api/helpers.ts"],"names":[],"mappings":"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"}
|