@teleporthq/teleport-plugin-next-workflows 0.43.67 → 0.43.69
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/__tests__/_helpers/bind-workflow-utils.ts +16 -1
- package/__tests__/_helpers/fake-fetch.ts +96 -0
- package/__tests__/_helpers/fake-stripe.ts +52 -0
- package/__tests__/_helpers/load-handler.ts +22 -3
- package/__tests__/_helpers/load-invoice-route.ts +75 -0
- package/__tests__/_helpers/load-payment-drivers.ts +69 -0
- package/__tests__/_helpers/load-server-runtime.ts +33 -0
- package/__tests__/_helpers/run-generated-middleware.ts +50 -9
- package/__tests__/admin-form-hydration-target.test.ts +39 -0
- package/__tests__/admin-form-row-hydration.test.ts +58 -0
- package/__tests__/ai-select-database-data-handler.test.ts +14 -3
- package/__tests__/api-route-file-name-segments.test.ts +33 -0
- package/__tests__/app-secret-env.test.ts +55 -0
- package/__tests__/auth-env-secret-preservation.test.ts +22 -3
- package/__tests__/auth-nextauth-url.test.ts +134 -50
- package/__tests__/cart-add-item-kinds.test.ts +259 -0
- package/__tests__/cart-add-item-line-fields.test.ts +328 -0
- package/__tests__/cart-availability-add-to-cart.test.ts +108 -0
- package/__tests__/cart-get-total-discounts.test.ts +499 -0
- package/__tests__/cart-get-total-product-options.test.ts +195 -0
- package/__tests__/cart-get-total-subscriptions.test.ts +221 -0
- package/__tests__/cart-price-order.test.ts +283 -0
- package/__tests__/cart-update-item-quantity-recurring.test.ts +75 -0
- package/__tests__/client-loop-current-item.test.ts +164 -0
- package/__tests__/cron-route-loop-custom-node.test.ts +123 -0
- package/__tests__/cron-route-loop-templateparams.test.ts +7 -0
- package/__tests__/cron-route-verification.test.ts +252 -0
- package/__tests__/custom-js-runtime-base-url.test.ts +64 -0
- package/__tests__/custom-nodes-admin-module.test.ts +310 -0
- package/__tests__/data-api-browser-reads.test.ts +341 -0
- package/__tests__/data-api-low-stock-autofire.test.ts +67 -17
- package/__tests__/data-api-optional-feature-columns.test.ts +240 -0
- package/__tests__/data-api-protected-tables.test.ts +948 -0
- package/__tests__/data-node-not-awaited.test.ts +7 -3
- package/__tests__/data-write-missing-filter.test.ts +119 -0
- package/__tests__/ecommerce-rewriter-product-options.test.ts +143 -0
- package/__tests__/email-locale-senders.test.ts +1 -1
- package/__tests__/file-storage-upload-picked-files.test.ts +20 -0
- package/__tests__/input-debounce-per-field.test.ts +141 -0
- package/__tests__/internal-request-headers.test.ts +7 -3
- package/__tests__/invoice-data-access-replace.test.ts +340 -0
- package/__tests__/invoice-delivery-fee.test.ts +3 -2
- package/__tests__/invoice-generate-hydration.test.ts +20 -12
- package/__tests__/invoice-order-items-settle.test.ts +51 -46
- package/__tests__/invoice-product-options.test.ts +177 -0
- package/__tests__/invoice-regenerate-route.test.ts +488 -0
- package/__tests__/invoice-regional-tax.test.ts +3 -2
- package/__tests__/invoice-reservation.test.ts +195 -0
- package/__tests__/invoice-route-access.test.ts +275 -0
- package/__tests__/invoice-self-call-origin.test.ts +117 -0
- package/__tests__/invoice-tender.test.ts +550 -0
- package/__tests__/legacy-webhook-self-calls.test.ts +187 -0
- package/__tests__/locale-aware-redirects.test.ts +55 -26
- package/__tests__/loop-collection-unwrap.test.ts +6 -1
- package/__tests__/middleware-subscriber-access.test.ts +269 -0
- package/__tests__/payment-charge-user-earlier-attempt.test.ts +267 -0
- package/__tests__/payment-charge-user-handler-serialization.test.ts +47 -82
- package/__tests__/payment-charge-user-line-descriptions.test.ts +124 -0
- package/__tests__/payment-charge-user-report-refusal.test.ts +105 -0
- package/__tests__/payment-close-checkout-node.test.ts +127 -0
- package/__tests__/payment-driver-close-checkout.test.ts +1163 -0
- package/__tests__/payment-driver-coingate.test.ts +470 -0
- package/__tests__/payment-driver-inspect-checkout.test.ts +648 -0
- package/__tests__/payment-driver-mollie.test.ts +864 -0
- package/__tests__/payment-driver-paddle.test.ts +870 -0
- package/__tests__/payment-driver-paypal-capture.test.ts +158 -0
- package/__tests__/payment-driver-paypal-webhook.test.ts +367 -0
- package/__tests__/payment-driver-razorpay.test.ts +895 -0
- package/__tests__/payment-driver-square.test.ts +977 -0
- package/__tests__/payment-driver-stripe.test.ts +267 -0
- package/__tests__/payment-drivers-module.test.ts +429 -0
- package/__tests__/payment-legacy-webhook-routes.test.ts +588 -0
- package/__tests__/payment-redirect-and-order-notification.test.ts +98 -39
- package/__tests__/payment-refund.test.ts +523 -22
- package/__tests__/payment-subscription-nodes.test.ts +1360 -0
- package/__tests__/payment-webhook-route.test.ts +523 -0
- package/__tests__/paypal-webhook-signature-verification.test.ts +205 -0
- package/__tests__/prune-context-oversized-leaf.test.ts +1 -0
- package/__tests__/prune-context-state-keys.test.ts +89 -0
- package/__tests__/push-node-handlers.test.ts +291 -0
- package/__tests__/route-changed-trigger.test.ts +40 -0
- package/__tests__/runtime-storage-upload-access.test.ts +255 -0
- package/__tests__/security-runtime-shadow.test.ts +103 -1
- package/__tests__/segment-reply-changed-keys.test.ts +146 -0
- package/__tests__/segment-state-keys-emission.test.ts +185 -0
- package/__tests__/segment-state-needs.test.ts +102 -0
- package/__tests__/server-segment-context-integrity.test.ts +210 -0
- package/__tests__/server-step-signing.test.ts +371 -0
- package/__tests__/session-cookie-resolver.test.ts +59 -0
- package/__tests__/stock-decrement-audit.test.ts +17 -0
- package/__tests__/subscriber-access-route.test.ts +406 -0
- package/__tests__/webhook-delivery-lease.test.ts +316 -0
- package/__tests__/workflow-auth-guard.test.ts +253 -2
- package/dist/cjs/admin-form-hydration.d.ts +10 -0
- package/dist/cjs/admin-form-hydration.d.ts.map +1 -0
- package/dist/cjs/admin-form-hydration.js +25 -0
- package/dist/cjs/admin-form-hydration.js.map +1 -0
- package/dist/cjs/api-route-generator.d.ts +19 -3
- package/dist/cjs/api-route-generator.d.ts.map +1 -1
- package/dist/cjs/api-route-generator.js +190 -70
- package/dist/cjs/api-route-generator.js.map +1 -1
- package/dist/cjs/auth-generator.d.ts +4 -1
- package/dist/cjs/auth-generator.d.ts.map +1 -1
- package/dist/cjs/auth-generator.js +241 -62
- package/dist/cjs/auth-generator.js.map +1 -1
- package/dist/cjs/auth-return/signed-in-destination-code.d.ts +17 -0
- package/dist/cjs/auth-return/signed-in-destination-code.d.ts.map +1 -0
- package/dist/cjs/auth-return/signed-in-destination-code.js +37 -0
- package/dist/cjs/auth-return/signed-in-destination-code.js.map +1 -0
- package/dist/cjs/cart-pricing-preamble.d.ts +12 -0
- package/dist/cjs/cart-pricing-preamble.d.ts.map +1 -0
- package/dist/cjs/cart-pricing-preamble.js +23 -0
- package/dist/cjs/cart-pricing-preamble.js.map +1 -0
- package/dist/cjs/cron-request-verification.d.ts +24 -0
- package/dist/cjs/cron-request-verification.d.ts.map +1 -0
- package/dist/cjs/cron-request-verification.js +84 -0
- package/dist/cjs/cron-request-verification.js.map +1 -0
- package/dist/cjs/custom-node-modules.d.ts +30 -0
- package/dist/cjs/custom-node-modules.d.ts.map +1 -0
- package/dist/cjs/custom-node-modules.js +90 -0
- package/dist/cjs/custom-node-modules.js.map +1 -0
- package/dist/cjs/data-api-route-generator.d.ts +27 -0
- package/dist/cjs/data-api-route-generator.d.ts.map +1 -1
- package/dist/cjs/data-api-route-generator.js +366 -29
- package/dist/cjs/data-api-route-generator.js.map +1 -1
- package/dist/cjs/ecommerce/cart-availability.d.ts.map +1 -1
- package/dist/cjs/ecommerce/cart-availability.js +22 -13
- package/dist/cjs/ecommerce/cart-availability.js.map +1 -1
- package/dist/cjs/ecommerce/stock-decrement.d.ts +2 -1
- package/dist/cjs/ecommerce/stock-decrement.d.ts.map +1 -1
- package/dist/cjs/ecommerce/stock-decrement.js +6 -0
- package/dist/cjs/ecommerce/stock-decrement.js.map +1 -1
- package/dist/cjs/executor-generator.d.ts +0 -1
- package/dist/cjs/executor-generator.d.ts.map +1 -1
- package/dist/cjs/executor-generator.js +213 -20
- package/dist/cjs/executor-generator.js.map +1 -1
- package/dist/cjs/index.d.ts +12 -4
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +25 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/invoice/api-routes-code.d.ts +26 -0
- package/dist/cjs/invoice/api-routes-code.d.ts.map +1 -1
- package/dist/cjs/invoice/api-routes-code.js +423 -391
- package/dist/cjs/invoice/api-routes-code.js.map +1 -1
- package/dist/cjs/invoice/data-access-code.d.ts.map +1 -1
- package/dist/cjs/invoice/data-access-code.js +420 -107
- package/dist/cjs/invoice/data-access-code.js.map +1 -1
- package/dist/cjs/invoice/index.d.ts.map +1 -1
- package/dist/cjs/invoice/index.js +24 -0
- package/dist/cjs/invoice/index.js.map +1 -1
- package/dist/cjs/invoice/invoice-assembly-code.d.ts +12 -0
- package/dist/cjs/invoice/invoice-assembly-code.d.ts.map +1 -0
- package/dist/cjs/invoice/invoice-assembly-code.js +517 -0
- package/dist/cjs/invoice/invoice-assembly-code.js.map +1 -0
- package/dist/cjs/invoice/invoice-html-code.d.ts.map +1 -1
- package/dist/cjs/invoice/invoice-html-code.js +111 -9
- package/dist/cjs/invoice/invoice-html-code.js.map +1 -1
- package/dist/cjs/invoice/pdf-service-client-code.d.ts.map +1 -1
- package/dist/cjs/invoice/pdf-service-client-code.js +3 -4
- package/dist/cjs/invoice/pdf-service-client-code.js.map +1 -1
- package/dist/cjs/nodes/account/account-login.d.ts.map +1 -1
- package/dist/cjs/nodes/account/account-login.js +4 -3
- package/dist/cjs/nodes/account/account-login.js.map +1 -1
- package/dist/cjs/nodes/account/account-signup.d.ts.map +1 -1
- package/dist/cjs/nodes/account/account-signup.js +7 -4
- package/dist/cjs/nodes/account/account-signup.js.map +1 -1
- package/dist/cjs/nodes/ai/ai-select-database-data.d.ts.map +1 -1
- package/dist/cjs/nodes/ai/ai-select-database-data.js +6 -1
- package/dist/cjs/nodes/ai/ai-select-database-data.js.map +1 -1
- package/dist/cjs/nodes/browser/browser-get-push-subscription.d.ts +9 -0
- package/dist/cjs/nodes/browser/browser-get-push-subscription.d.ts.map +1 -0
- package/dist/cjs/nodes/browser/browser-get-push-subscription.js +25 -0
- package/dist/cjs/nodes/browser/browser-get-push-subscription.js.map +1 -0
- package/dist/cjs/nodes/browser/browser-show-notification.d.ts +10 -0
- package/dist/cjs/nodes/browser/browser-show-notification.d.ts.map +1 -1
- package/dist/cjs/nodes/browser/browser-show-notification.js +65 -40
- package/dist/cjs/nodes/browser/browser-show-notification.js.map +1 -1
- package/dist/cjs/nodes/browser/browser-subscribe-to-push.d.ts +11 -0
- package/dist/cjs/nodes/browser/browser-subscribe-to-push.d.ts.map +1 -1
- package/dist/cjs/nodes/browser/browser-subscribe-to-push.js +21 -31
- package/dist/cjs/nodes/browser/browser-subscribe-to-push.js.map +1 -1
- package/dist/cjs/nodes/browser/browser-unsubscribe-from-push.d.ts +8 -0
- package/dist/cjs/nodes/browser/browser-unsubscribe-from-push.d.ts.map +1 -0
- package/dist/cjs/nodes/browser/browser-unsubscribe-from-push.js +24 -0
- package/dist/cjs/nodes/browser/browser-unsubscribe-from-push.js.map +1 -0
- package/dist/cjs/nodes/browser/push-api-access.d.ts +12 -0
- package/dist/cjs/nodes/browser/push-api-access.d.ts.map +1 -0
- package/dist/cjs/nodes/browser/push-api-access.js +19 -0
- package/dist/cjs/nodes/browser/push-api-access.js.map +1 -0
- package/dist/cjs/nodes/cart/cart-add-item.d.ts.map +1 -1
- package/dist/cjs/nodes/cart/cart-add-item.js +174 -10
- package/dist/cjs/nodes/cart/cart-add-item.js.map +1 -1
- package/dist/cjs/nodes/cart/cart-clear.d.ts.map +1 -1
- package/dist/cjs/nodes/cart/cart-clear.js +11 -0
- package/dist/cjs/nodes/cart/cart-clear.js.map +1 -1
- package/dist/cjs/nodes/cart/cart-get-total.d.ts.map +1 -1
- package/dist/cjs/nodes/cart/cart-get-total.js +260 -3
- package/dist/cjs/nodes/cart/cart-get-total.js.map +1 -1
- package/dist/cjs/nodes/cart/cart-price-order.d.ts +3 -0
- package/dist/cjs/nodes/cart/cart-price-order.d.ts.map +1 -0
- package/dist/cjs/nodes/cart/cart-price-order.js +281 -0
- package/dist/cjs/nodes/cart/cart-price-order.js.map +1 -0
- package/dist/cjs/nodes/cart/cart-update-item-quantity.d.ts.map +1 -1
- package/dist/cjs/nodes/cart/cart-update-item-quantity.js +7 -0
- package/dist/cjs/nodes/cart/cart-update-item-quantity.js.map +1 -1
- package/dist/cjs/nodes/data/data-count.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-count.js +6 -1
- package/dist/cjs/nodes/data/data-count.js.map +1 -1
- package/dist/cjs/nodes/data/data-create-item.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-create-item.js +11 -1
- package/dist/cjs/nodes/data/data-create-item.js.map +1 -1
- package/dist/cjs/nodes/data/data-delete-item.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-delete-item.js +29 -0
- package/dist/cjs/nodes/data/data-delete-item.js.map +1 -1
- package/dist/cjs/nodes/data/data-raw-query.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-raw-query.js +6 -1
- package/dist/cjs/nodes/data/data-raw-query.js.map +1 -1
- package/dist/cjs/nodes/data/data-select.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-select.js +6 -1
- package/dist/cjs/nodes/data/data-select.js.map +1 -1
- package/dist/cjs/nodes/data/data-update-item.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-update-item.js +29 -0
- package/dist/cjs/nodes/data/data-update-item.js.map +1 -1
- package/dist/cjs/nodes/ecommerce/ecommerce-generate-invoice.d.ts.map +1 -1
- package/dist/cjs/nodes/ecommerce/ecommerce-generate-invoice.js +7 -1
- package/dist/cjs/nodes/ecommerce/ecommerce-generate-invoice.js.map +1 -1
- package/dist/cjs/nodes/file-storage/file-storage-upload.d.ts.map +1 -1
- package/dist/cjs/nodes/file-storage/file-storage-upload.js +7 -0
- package/dist/cjs/nodes/file-storage/file-storage-upload.js.map +1 -1
- package/dist/cjs/nodes/general/general-custom-js.d.ts.map +1 -1
- package/dist/cjs/nodes/general/general-custom-js.js +21 -5
- package/dist/cjs/nodes/general/general-custom-js.js.map +1 -1
- package/dist/cjs/nodes/index.d.ts.map +1 -1
- package/dist/cjs/nodes/index.js +9 -4
- package/dist/cjs/nodes/index.js.map +1 -1
- package/dist/cjs/nodes/payment/payment-billing-portal.d.ts +3 -0
- package/dist/cjs/nodes/payment/payment-billing-portal.d.ts.map +1 -0
- package/dist/cjs/nodes/payment/payment-billing-portal.js +52 -0
- package/dist/cjs/nodes/payment/payment-billing-portal.js.map +1 -0
- package/dist/cjs/nodes/payment/payment-charge-user.d.ts.map +1 -1
- package/dist/cjs/nodes/payment/payment-charge-user.js +227 -360
- package/dist/cjs/nodes/payment/payment-charge-user.js.map +1 -1
- package/dist/cjs/nodes/payment/payment-close-checkout.d.ts +3 -0
- package/dist/cjs/nodes/payment/payment-close-checkout.d.ts.map +1 -0
- package/dist/cjs/nodes/payment/payment-close-checkout.js +141 -0
- package/dist/cjs/nodes/payment/payment-close-checkout.js.map +1 -0
- package/dist/cjs/nodes/payment/payment-ensure-subscription-plan.d.ts +3 -0
- package/dist/cjs/nodes/payment/payment-ensure-subscription-plan.d.ts.map +1 -0
- package/dist/cjs/nodes/payment/payment-ensure-subscription-plan.js +67 -0
- package/dist/cjs/nodes/payment/payment-ensure-subscription-plan.js.map +1 -0
- package/dist/cjs/nodes/payment/payment-manage-subscription.d.ts +3 -0
- package/dist/cjs/nodes/payment/payment-manage-subscription.d.ts.map +1 -0
- package/dist/cjs/nodes/payment/payment-manage-subscription.js +89 -0
- package/dist/cjs/nodes/payment/payment-manage-subscription.js.map +1 -0
- package/dist/cjs/nodes/payment/payment-refund.d.ts.map +1 -1
- package/dist/cjs/nodes/payment/payment-refund.js +50 -404
- package/dist/cjs/nodes/payment/payment-refund.js.map +1 -1
- package/dist/cjs/nodes/push/push-send-notification.d.ts +14 -0
- package/dist/cjs/nodes/push/push-send-notification.d.ts.map +1 -0
- package/dist/cjs/nodes/push/push-send-notification.js +83 -0
- package/dist/cjs/nodes/push/push-send-notification.js.map +1 -0
- package/dist/cjs/payments/drivers/coingate-driver-code.d.ts +16 -0
- package/dist/cjs/payments/drivers/coingate-driver-code.d.ts.map +1 -0
- package/dist/cjs/payments/drivers/coingate-driver-code.js +471 -0
- package/dist/cjs/payments/drivers/coingate-driver-code.js.map +1 -0
- package/dist/cjs/payments/drivers/mollie-driver-code.d.ts +16 -0
- package/dist/cjs/payments/drivers/mollie-driver-code.d.ts.map +1 -0
- package/dist/cjs/payments/drivers/mollie-driver-code.js +623 -0
- package/dist/cjs/payments/drivers/mollie-driver-code.js.map +1 -0
- package/dist/cjs/payments/drivers/paddle-driver-code.d.ts +12 -0
- package/dist/cjs/payments/drivers/paddle-driver-code.d.ts.map +1 -0
- package/dist/cjs/payments/drivers/paddle-driver-code.js +683 -0
- package/dist/cjs/payments/drivers/paddle-driver-code.js.map +1 -0
- package/dist/cjs/payments/drivers/paypal-driver-code.d.ts +12 -0
- package/dist/cjs/payments/drivers/paypal-driver-code.d.ts.map +1 -0
- package/dist/cjs/payments/drivers/paypal-driver-code.js +1261 -0
- package/dist/cjs/payments/drivers/paypal-driver-code.js.map +1 -0
- package/dist/cjs/payments/drivers/razorpay-driver-code.d.ts +12 -0
- package/dist/cjs/payments/drivers/razorpay-driver-code.d.ts.map +1 -0
- package/dist/cjs/payments/drivers/razorpay-driver-code.js +732 -0
- package/dist/cjs/payments/drivers/razorpay-driver-code.js.map +1 -0
- package/dist/cjs/payments/drivers/square-driver-code.d.ts +14 -0
- package/dist/cjs/payments/drivers/square-driver-code.d.ts.map +1 -0
- package/dist/cjs/payments/drivers/square-driver-code.js +931 -0
- package/dist/cjs/payments/drivers/square-driver-code.js.map +1 -0
- package/dist/cjs/payments/drivers/stripe-driver-code.d.ts +12 -0
- package/dist/cjs/payments/drivers/stripe-driver-code.d.ts.map +1 -0
- package/dist/cjs/payments/drivers/stripe-driver-code.js +778 -0
- package/dist/cjs/payments/drivers/stripe-driver-code.js.map +1 -0
- package/dist/cjs/payments/index.d.ts +66 -0
- package/dist/cjs/payments/index.d.ts.map +1 -0
- package/dist/cjs/payments/index.js +175 -0
- package/dist/cjs/payments/index.js.map +1 -0
- package/dist/cjs/payments/payment-core-code.d.ts +19 -0
- package/dist/cjs/payments/payment-core-code.d.ts.map +1 -0
- package/dist/cjs/payments/payment-core-code.js +422 -0
- package/dist/cjs/payments/payment-core-code.js.map +1 -0
- package/dist/cjs/payments/payment-driver-code-map.d.ts +4 -0
- package/dist/cjs/payments/payment-driver-code-map.d.ts.map +1 -0
- package/dist/cjs/payments/payment-driver-code-map.js +21 -0
- package/dist/cjs/payments/payment-driver-code-map.js.map +1 -0
- package/dist/cjs/payments/payment-drivers-scope.d.ts +35 -0
- package/dist/cjs/payments/payment-drivers-scope.d.ts.map +1 -0
- package/dist/cjs/payments/payment-drivers-scope.js +56 -0
- package/dist/cjs/payments/payment-drivers-scope.js.map +1 -0
- package/dist/cjs/payments/payment-registry-code.d.ts +8 -0
- package/dist/cjs/payments/payment-registry-code.d.ts.map +1 -0
- package/dist/cjs/payments/payment-registry-code.js +41 -0
- package/dist/cjs/payments/payment-registry-code.js.map +1 -0
- package/dist/cjs/pg-client-code.d.ts +10 -0
- package/dist/cjs/pg-client-code.d.ts.map +1 -1
- package/dist/cjs/pg-client-code.js +27 -1
- package/dist/cjs/pg-client-code.js.map +1 -1
- package/dist/cjs/runtime-storage-generator.d.ts +28 -0
- package/dist/cjs/runtime-storage-generator.d.ts.map +1 -1
- package/dist/cjs/runtime-storage-generator.js +240 -5
- package/dist/cjs/runtime-storage-generator.js.map +1 -1
- package/dist/cjs/secret-collector.d.ts.map +1 -1
- package/dist/cjs/secret-collector.js +8 -3
- package/dist/cjs/secret-collector.js.map +1 -1
- package/dist/cjs/security-scanner.d.ts +10 -1
- package/dist/cjs/security-scanner.d.ts.map +1 -1
- package/dist/cjs/security-scanner.js +19 -1
- package/dist/cjs/security-scanner.js.map +1 -1
- package/dist/cjs/segment-context-needs.d.ts +38 -0
- package/dist/cjs/segment-context-needs.d.ts.map +1 -0
- package/dist/cjs/segment-context-needs.js +129 -0
- package/dist/cjs/segment-context-needs.js.map +1 -0
- package/dist/cjs/segment-splitter.d.ts.map +1 -1
- package/dist/cjs/segment-splitter.js +6 -1
- package/dist/cjs/segment-splitter.js.map +1 -1
- package/dist/cjs/segment-trust.d.ts +50 -0
- package/dist/cjs/segment-trust.d.ts.map +1 -0
- package/dist/cjs/segment-trust.js +115 -0
- package/dist/cjs/segment-trust.js.map +1 -0
- package/dist/cjs/sent-email-log/sent-email-log-code.d.ts +19 -0
- package/dist/cjs/sent-email-log/sent-email-log-code.d.ts.map +1 -1
- package/dist/cjs/sent-email-log/sent-email-log-code.js +1 -24
- package/dist/cjs/sent-email-log/sent-email-log-code.js.map +1 -1
- package/dist/cjs/server-runtime-code.d.ts +34 -0
- package/dist/cjs/server-runtime-code.d.ts.map +1 -0
- package/dist/cjs/server-runtime-code.js +303 -0
- package/dist/cjs/server-runtime-code.js.map +1 -0
- package/dist/cjs/session-cookie-resolver.d.ts +3 -78
- package/dist/cjs/session-cookie-resolver.d.ts.map +1 -1
- package/dist/cjs/session-cookie-resolver.js +7 -276
- package/dist/cjs/session-cookie-resolver.js.map +1 -1
- package/dist/cjs/subscriber-access-route-generator.d.ts +71 -0
- package/dist/cjs/subscriber-access-route-generator.d.ts.map +1 -0
- package/dist/cjs/subscriber-access-route-generator.js +301 -0
- package/dist/cjs/subscriber-access-route-generator.js.map +1 -0
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/types.d.ts +6 -0
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/webhook-delivery-lease/index.d.ts +8 -0
- package/dist/cjs/webhook-delivery-lease/index.d.ts.map +1 -0
- package/dist/cjs/webhook-delivery-lease/index.js +41 -0
- package/dist/cjs/webhook-delivery-lease/index.js.map +1 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-code.d.ts +26 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-code.d.ts.map +1 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-code.js +151 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-code.js.map +1 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-scope.d.ts +16 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-scope.d.ts.map +1 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-scope.js +19 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-scope.js.map +1 -0
- package/dist/cjs/webhook-generator.d.ts +1 -1
- package/dist/cjs/webhook-generator.d.ts.map +1 -1
- package/dist/cjs/webhook-generator.js +342 -254
- package/dist/cjs/webhook-generator.js.map +1 -1
- package/dist/cjs/webhook-signature-verification.d.ts +17 -1
- package/dist/cjs/webhook-signature-verification.d.ts.map +1 -1
- package/dist/cjs/webhook-signature-verification.js +182 -27
- package/dist/cjs/webhook-signature-verification.js.map +1 -1
- package/dist/cjs/workflow-auth-generator.d.ts +9 -6
- package/dist/cjs/workflow-auth-generator.d.ts.map +1 -1
- package/dist/cjs/workflow-auth-generator.js +133 -29
- package/dist/cjs/workflow-auth-generator.js.map +1 -1
- package/dist/cjs/workflow-component-plugin.d.ts.map +1 -1
- package/dist/cjs/workflow-component-plugin.js +65 -28
- package/dist/cjs/workflow-component-plugin.js.map +1 -1
- package/dist/cjs/workflow-project-plugin.d.ts +13 -0
- package/dist/cjs/workflow-project-plugin.d.ts.map +1 -1
- package/dist/cjs/workflow-project-plugin.js +215 -65
- package/dist/cjs/workflow-project-plugin.js.map +1 -1
- package/dist/esm/admin-form-hydration.d.ts +10 -0
- package/dist/esm/admin-form-hydration.d.ts.map +1 -0
- package/dist/esm/admin-form-hydration.js +21 -0
- package/dist/esm/admin-form-hydration.js.map +1 -0
- package/dist/esm/api-route-generator.d.ts +19 -3
- package/dist/esm/api-route-generator.d.ts.map +1 -1
- package/dist/esm/api-route-generator.js +189 -70
- package/dist/esm/api-route-generator.js.map +1 -1
- package/dist/esm/auth-generator.d.ts +4 -1
- package/dist/esm/auth-generator.d.ts.map +1 -1
- package/dist/esm/auth-generator.js +241 -62
- package/dist/esm/auth-generator.js.map +1 -1
- package/dist/esm/auth-return/signed-in-destination-code.d.ts +17 -0
- package/dist/esm/auth-return/signed-in-destination-code.d.ts.map +1 -0
- package/dist/esm/auth-return/signed-in-destination-code.js +33 -0
- package/dist/esm/auth-return/signed-in-destination-code.js.map +1 -0
- package/dist/esm/cart-pricing-preamble.d.ts +12 -0
- package/dist/esm/cart-pricing-preamble.d.ts.map +1 -0
- package/dist/esm/cart-pricing-preamble.js +19 -0
- package/dist/esm/cart-pricing-preamble.js.map +1 -0
- package/dist/esm/cron-request-verification.d.ts +24 -0
- package/dist/esm/cron-request-verification.d.ts.map +1 -0
- package/dist/esm/cron-request-verification.js +80 -0
- package/dist/esm/cron-request-verification.js.map +1 -0
- package/dist/esm/custom-node-modules.d.ts +30 -0
- package/dist/esm/custom-node-modules.d.ts.map +1 -0
- package/dist/esm/custom-node-modules.js +84 -0
- package/dist/esm/custom-node-modules.js.map +1 -0
- package/dist/esm/data-api-route-generator.d.ts +27 -0
- package/dist/esm/data-api-route-generator.d.ts.map +1 -1
- package/dist/esm/data-api-route-generator.js +365 -28
- package/dist/esm/data-api-route-generator.js.map +1 -1
- package/dist/esm/ecommerce/cart-availability.d.ts.map +1 -1
- package/dist/esm/ecommerce/cart-availability.js +22 -13
- package/dist/esm/ecommerce/cart-availability.js.map +1 -1
- package/dist/esm/ecommerce/stock-decrement.d.ts +2 -1
- package/dist/esm/ecommerce/stock-decrement.d.ts.map +1 -1
- package/dist/esm/ecommerce/stock-decrement.js +6 -0
- package/dist/esm/ecommerce/stock-decrement.js.map +1 -1
- package/dist/esm/executor-generator.d.ts +0 -1
- package/dist/esm/executor-generator.d.ts.map +1 -1
- package/dist/esm/executor-generator.js +212 -18
- package/dist/esm/executor-generator.js.map +1 -1
- package/dist/esm/index.d.ts +12 -4
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +10 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/invoice/api-routes-code.d.ts +26 -0
- package/dist/esm/invoice/api-routes-code.d.ts.map +1 -1
- package/dist/esm/invoice/api-routes-code.js +421 -390
- package/dist/esm/invoice/api-routes-code.js.map +1 -1
- package/dist/esm/invoice/data-access-code.d.ts.map +1 -1
- package/dist/esm/invoice/data-access-code.js +420 -107
- package/dist/esm/invoice/data-access-code.js.map +1 -1
- package/dist/esm/invoice/index.d.ts.map +1 -1
- package/dist/esm/invoice/index.js +25 -1
- package/dist/esm/invoice/index.js.map +1 -1
- package/dist/esm/invoice/invoice-assembly-code.d.ts +12 -0
- package/dist/esm/invoice/invoice-assembly-code.d.ts.map +1 -0
- package/dist/esm/invoice/invoice-assembly-code.js +513 -0
- package/dist/esm/invoice/invoice-assembly-code.js.map +1 -0
- package/dist/esm/invoice/invoice-html-code.d.ts.map +1 -1
- package/dist/esm/invoice/invoice-html-code.js +111 -9
- package/dist/esm/invoice/invoice-html-code.js.map +1 -1
- package/dist/esm/invoice/pdf-service-client-code.d.ts.map +1 -1
- package/dist/esm/invoice/pdf-service-client-code.js +3 -4
- package/dist/esm/invoice/pdf-service-client-code.js.map +1 -1
- package/dist/esm/nodes/account/account-login.d.ts.map +1 -1
- package/dist/esm/nodes/account/account-login.js +4 -3
- package/dist/esm/nodes/account/account-login.js.map +1 -1
- package/dist/esm/nodes/account/account-signup.d.ts.map +1 -1
- package/dist/esm/nodes/account/account-signup.js +7 -4
- package/dist/esm/nodes/account/account-signup.js.map +1 -1
- package/dist/esm/nodes/ai/ai-select-database-data.d.ts.map +1 -1
- package/dist/esm/nodes/ai/ai-select-database-data.js +6 -1
- package/dist/esm/nodes/ai/ai-select-database-data.js.map +1 -1
- package/dist/esm/nodes/browser/browser-get-push-subscription.d.ts +9 -0
- package/dist/esm/nodes/browser/browser-get-push-subscription.d.ts.map +1 -0
- package/dist/esm/nodes/browser/browser-get-push-subscription.js +22 -0
- package/dist/esm/nodes/browser/browser-get-push-subscription.js.map +1 -0
- package/dist/esm/nodes/browser/browser-show-notification.d.ts +10 -0
- package/dist/esm/nodes/browser/browser-show-notification.d.ts.map +1 -1
- package/dist/esm/nodes/browser/browser-show-notification.js +65 -40
- package/dist/esm/nodes/browser/browser-show-notification.js.map +1 -1
- package/dist/esm/nodes/browser/browser-subscribe-to-push.d.ts +11 -0
- package/dist/esm/nodes/browser/browser-subscribe-to-push.d.ts.map +1 -1
- package/dist/esm/nodes/browser/browser-subscribe-to-push.js +21 -31
- package/dist/esm/nodes/browser/browser-subscribe-to-push.js.map +1 -1
- package/dist/esm/nodes/browser/browser-unsubscribe-from-push.d.ts +8 -0
- package/dist/esm/nodes/browser/browser-unsubscribe-from-push.d.ts.map +1 -0
- package/dist/esm/nodes/browser/browser-unsubscribe-from-push.js +21 -0
- package/dist/esm/nodes/browser/browser-unsubscribe-from-push.js.map +1 -0
- package/dist/esm/nodes/browser/push-api-access.d.ts +12 -0
- package/dist/esm/nodes/browser/push-api-access.d.ts.map +1 -0
- package/dist/esm/nodes/browser/push-api-access.js +13 -0
- package/dist/esm/nodes/browser/push-api-access.js.map +1 -0
- package/dist/esm/nodes/cart/cart-add-item.d.ts.map +1 -1
- package/dist/esm/nodes/cart/cart-add-item.js +174 -10
- package/dist/esm/nodes/cart/cart-add-item.js.map +1 -1
- package/dist/esm/nodes/cart/cart-clear.d.ts.map +1 -1
- package/dist/esm/nodes/cart/cart-clear.js +11 -0
- package/dist/esm/nodes/cart/cart-clear.js.map +1 -1
- package/dist/esm/nodes/cart/cart-get-total.d.ts.map +1 -1
- package/dist/esm/nodes/cart/cart-get-total.js +261 -4
- package/dist/esm/nodes/cart/cart-get-total.js.map +1 -1
- package/dist/esm/nodes/cart/cart-price-order.d.ts +3 -0
- package/dist/esm/nodes/cart/cart-price-order.d.ts.map +1 -0
- package/dist/esm/nodes/cart/cart-price-order.js +278 -0
- package/dist/esm/nodes/cart/cart-price-order.js.map +1 -0
- package/dist/esm/nodes/cart/cart-update-item-quantity.d.ts.map +1 -1
- package/dist/esm/nodes/cart/cart-update-item-quantity.js +7 -0
- package/dist/esm/nodes/cart/cart-update-item-quantity.js.map +1 -1
- package/dist/esm/nodes/data/data-count.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-count.js +6 -1
- package/dist/esm/nodes/data/data-count.js.map +1 -1
- package/dist/esm/nodes/data/data-create-item.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-create-item.js +11 -1
- package/dist/esm/nodes/data/data-create-item.js.map +1 -1
- package/dist/esm/nodes/data/data-delete-item.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-delete-item.js +29 -0
- package/dist/esm/nodes/data/data-delete-item.js.map +1 -1
- package/dist/esm/nodes/data/data-raw-query.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-raw-query.js +6 -1
- package/dist/esm/nodes/data/data-raw-query.js.map +1 -1
- package/dist/esm/nodes/data/data-select.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-select.js +6 -1
- package/dist/esm/nodes/data/data-select.js.map +1 -1
- package/dist/esm/nodes/data/data-update-item.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-update-item.js +29 -0
- package/dist/esm/nodes/data/data-update-item.js.map +1 -1
- package/dist/esm/nodes/ecommerce/ecommerce-generate-invoice.d.ts.map +1 -1
- package/dist/esm/nodes/ecommerce/ecommerce-generate-invoice.js +7 -1
- package/dist/esm/nodes/ecommerce/ecommerce-generate-invoice.js.map +1 -1
- package/dist/esm/nodes/file-storage/file-storage-upload.d.ts.map +1 -1
- package/dist/esm/nodes/file-storage/file-storage-upload.js +7 -0
- package/dist/esm/nodes/file-storage/file-storage-upload.js.map +1 -1
- package/dist/esm/nodes/general/general-custom-js.d.ts.map +1 -1
- package/dist/esm/nodes/general/general-custom-js.js +21 -5
- package/dist/esm/nodes/general/general-custom-js.js.map +1 -1
- package/dist/esm/nodes/index.d.ts.map +1 -1
- package/dist/esm/nodes/index.js +9 -4
- package/dist/esm/nodes/index.js.map +1 -1
- package/dist/esm/nodes/payment/payment-billing-portal.d.ts +3 -0
- package/dist/esm/nodes/payment/payment-billing-portal.d.ts.map +1 -0
- package/dist/esm/nodes/payment/payment-billing-portal.js +49 -0
- package/dist/esm/nodes/payment/payment-billing-portal.js.map +1 -0
- package/dist/esm/nodes/payment/payment-charge-user.d.ts.map +1 -1
- package/dist/esm/nodes/payment/payment-charge-user.js +227 -360
- package/dist/esm/nodes/payment/payment-charge-user.js.map +1 -1
- package/dist/esm/nodes/payment/payment-close-checkout.d.ts +3 -0
- package/dist/esm/nodes/payment/payment-close-checkout.d.ts.map +1 -0
- package/dist/esm/nodes/payment/payment-close-checkout.js +138 -0
- package/dist/esm/nodes/payment/payment-close-checkout.js.map +1 -0
- package/dist/esm/nodes/payment/payment-ensure-subscription-plan.d.ts +3 -0
- package/dist/esm/nodes/payment/payment-ensure-subscription-plan.d.ts.map +1 -0
- package/dist/esm/nodes/payment/payment-ensure-subscription-plan.js +64 -0
- package/dist/esm/nodes/payment/payment-ensure-subscription-plan.js.map +1 -0
- package/dist/esm/nodes/payment/payment-manage-subscription.d.ts +3 -0
- package/dist/esm/nodes/payment/payment-manage-subscription.d.ts.map +1 -0
- package/dist/esm/nodes/payment/payment-manage-subscription.js +86 -0
- package/dist/esm/nodes/payment/payment-manage-subscription.js.map +1 -0
- package/dist/esm/nodes/payment/payment-refund.d.ts.map +1 -1
- package/dist/esm/nodes/payment/payment-refund.js +50 -404
- package/dist/esm/nodes/payment/payment-refund.js.map +1 -1
- package/dist/esm/nodes/push/push-send-notification.d.ts +14 -0
- package/dist/esm/nodes/push/push-send-notification.d.ts.map +1 -0
- package/dist/esm/nodes/push/push-send-notification.js +80 -0
- package/dist/esm/nodes/push/push-send-notification.js.map +1 -0
- package/dist/esm/payments/drivers/coingate-driver-code.d.ts +16 -0
- package/dist/esm/payments/drivers/coingate-driver-code.d.ts.map +1 -0
- package/dist/esm/payments/drivers/coingate-driver-code.js +467 -0
- package/dist/esm/payments/drivers/coingate-driver-code.js.map +1 -0
- package/dist/esm/payments/drivers/mollie-driver-code.d.ts +16 -0
- package/dist/esm/payments/drivers/mollie-driver-code.d.ts.map +1 -0
- package/dist/esm/payments/drivers/mollie-driver-code.js +619 -0
- package/dist/esm/payments/drivers/mollie-driver-code.js.map +1 -0
- package/dist/esm/payments/drivers/paddle-driver-code.d.ts +12 -0
- package/dist/esm/payments/drivers/paddle-driver-code.d.ts.map +1 -0
- package/dist/esm/payments/drivers/paddle-driver-code.js +679 -0
- package/dist/esm/payments/drivers/paddle-driver-code.js.map +1 -0
- package/dist/esm/payments/drivers/paypal-driver-code.d.ts +12 -0
- package/dist/esm/payments/drivers/paypal-driver-code.d.ts.map +1 -0
- package/dist/esm/payments/drivers/paypal-driver-code.js +1257 -0
- package/dist/esm/payments/drivers/paypal-driver-code.js.map +1 -0
- package/dist/esm/payments/drivers/razorpay-driver-code.d.ts +12 -0
- package/dist/esm/payments/drivers/razorpay-driver-code.d.ts.map +1 -0
- package/dist/esm/payments/drivers/razorpay-driver-code.js +728 -0
- package/dist/esm/payments/drivers/razorpay-driver-code.js.map +1 -0
- package/dist/esm/payments/drivers/square-driver-code.d.ts +14 -0
- package/dist/esm/payments/drivers/square-driver-code.d.ts.map +1 -0
- package/dist/esm/payments/drivers/square-driver-code.js +927 -0
- package/dist/esm/payments/drivers/square-driver-code.js.map +1 -0
- package/dist/esm/payments/drivers/stripe-driver-code.d.ts +12 -0
- package/dist/esm/payments/drivers/stripe-driver-code.d.ts.map +1 -0
- package/dist/esm/payments/drivers/stripe-driver-code.js +774 -0
- package/dist/esm/payments/drivers/stripe-driver-code.js.map +1 -0
- package/dist/esm/payments/index.d.ts +66 -0
- package/dist/esm/payments/index.d.ts.map +1 -0
- package/dist/esm/payments/index.js +164 -0
- package/dist/esm/payments/index.js.map +1 -0
- package/dist/esm/payments/payment-core-code.d.ts +19 -0
- package/dist/esm/payments/payment-core-code.d.ts.map +1 -0
- package/dist/esm/payments/payment-core-code.js +418 -0
- package/dist/esm/payments/payment-core-code.js.map +1 -0
- package/dist/esm/payments/payment-driver-code-map.d.ts +4 -0
- package/dist/esm/payments/payment-driver-code-map.d.ts.map +1 -0
- package/dist/esm/payments/payment-driver-code-map.js +18 -0
- package/dist/esm/payments/payment-driver-code-map.js.map +1 -0
- package/dist/esm/payments/payment-drivers-scope.d.ts +35 -0
- package/dist/esm/payments/payment-drivers-scope.d.ts.map +1 -0
- package/dist/esm/payments/payment-drivers-scope.js +51 -0
- package/dist/esm/payments/payment-drivers-scope.js.map +1 -0
- package/dist/esm/payments/payment-registry-code.d.ts +8 -0
- package/dist/esm/payments/payment-registry-code.d.ts.map +1 -0
- package/dist/esm/payments/payment-registry-code.js +37 -0
- package/dist/esm/payments/payment-registry-code.js.map +1 -0
- package/dist/esm/pg-client-code.d.ts +10 -0
- package/dist/esm/pg-client-code.d.ts.map +1 -1
- package/dist/esm/pg-client-code.js +25 -0
- package/dist/esm/pg-client-code.js.map +1 -1
- package/dist/esm/runtime-storage-generator.d.ts +28 -0
- package/dist/esm/runtime-storage-generator.d.ts.map +1 -1
- package/dist/esm/runtime-storage-generator.js +239 -4
- package/dist/esm/runtime-storage-generator.js.map +1 -1
- package/dist/esm/secret-collector.d.ts.map +1 -1
- package/dist/esm/secret-collector.js +8 -3
- package/dist/esm/secret-collector.js.map +1 -1
- package/dist/esm/security-scanner.d.ts +10 -1
- package/dist/esm/security-scanner.d.ts.map +1 -1
- package/dist/esm/security-scanner.js +18 -0
- package/dist/esm/security-scanner.js.map +1 -1
- package/dist/esm/segment-context-needs.d.ts +38 -0
- package/dist/esm/segment-context-needs.d.ts.map +1 -0
- package/dist/esm/segment-context-needs.js +125 -0
- package/dist/esm/segment-context-needs.js.map +1 -0
- package/dist/esm/segment-splitter.d.ts.map +1 -1
- package/dist/esm/segment-splitter.js +6 -1
- package/dist/esm/segment-splitter.js.map +1 -1
- package/dist/esm/segment-trust.d.ts +50 -0
- package/dist/esm/segment-trust.d.ts.map +1 -0
- package/dist/esm/segment-trust.js +111 -0
- package/dist/esm/segment-trust.js.map +1 -0
- package/dist/esm/sent-email-log/sent-email-log-code.d.ts +19 -0
- package/dist/esm/sent-email-log/sent-email-log-code.d.ts.map +1 -1
- package/dist/esm/sent-email-log/sent-email-log-code.js +2 -25
- package/dist/esm/sent-email-log/sent-email-log-code.js.map +1 -1
- package/dist/esm/server-runtime-code.d.ts +34 -0
- package/dist/esm/server-runtime-code.d.ts.map +1 -0
- package/dist/esm/server-runtime-code.js +299 -0
- package/dist/esm/server-runtime-code.js.map +1 -0
- package/dist/esm/session-cookie-resolver.d.ts +3 -78
- package/dist/esm/session-cookie-resolver.d.ts.map +1 -1
- package/dist/esm/session-cookie-resolver.js +7 -274
- package/dist/esm/session-cookie-resolver.js.map +1 -1
- package/dist/esm/subscriber-access-route-generator.d.ts +71 -0
- package/dist/esm/subscriber-access-route-generator.d.ts.map +1 -0
- package/dist/esm/subscriber-access-route-generator.js +292 -0
- package/dist/esm/subscriber-access-route-generator.js.map +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/types.d.ts +6 -0
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/webhook-delivery-lease/index.d.ts +8 -0
- package/dist/esm/webhook-delivery-lease/index.d.ts.map +1 -0
- package/dist/esm/webhook-delivery-lease/index.js +37 -0
- package/dist/esm/webhook-delivery-lease/index.js.map +1 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-code.d.ts +26 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-code.d.ts.map +1 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-code.js +147 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-code.js.map +1 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-scope.d.ts +16 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-scope.d.ts.map +1 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-scope.js +16 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-scope.js.map +1 -0
- package/dist/esm/webhook-generator.d.ts +1 -1
- package/dist/esm/webhook-generator.d.ts.map +1 -1
- package/dist/esm/webhook-generator.js +342 -254
- package/dist/esm/webhook-generator.js.map +1 -1
- package/dist/esm/webhook-signature-verification.d.ts +17 -1
- package/dist/esm/webhook-signature-verification.d.ts.map +1 -1
- package/dist/esm/webhook-signature-verification.js +179 -25
- package/dist/esm/webhook-signature-verification.js.map +1 -1
- package/dist/esm/workflow-auth-generator.d.ts +9 -6
- package/dist/esm/workflow-auth-generator.d.ts.map +1 -1
- package/dist/esm/workflow-auth-generator.js +132 -28
- package/dist/esm/workflow-auth-generator.js.map +1 -1
- package/dist/esm/workflow-component-plugin.d.ts.map +1 -1
- package/dist/esm/workflow-component-plugin.js +65 -28
- package/dist/esm/workflow-component-plugin.js.map +1 -1
- package/dist/esm/workflow-project-plugin.d.ts +13 -0
- package/dist/esm/workflow-project-plugin.d.ts.map +1 -1
- package/dist/esm/workflow-project-plugin.js +212 -63
- package/dist/esm/workflow-project-plugin.js.map +1 -1
- package/package.json +4 -4
- package/src/admin-form-hydration.ts +28 -0
- package/src/api-route-generator.ts +251 -64
- package/src/auth-generator.ts +273 -53
- package/src/auth-return/signed-in-destination-code.ts +32 -0
- package/src/cart-pricing-preamble.ts +22 -0
- package/src/cron-request-verification.ts +79 -0
- package/src/custom-node-modules.ts +102 -0
- package/src/data-api-route-generator.ts +370 -28
- package/src/ecommerce/cart-availability.ts +22 -13
- package/src/ecommerce/stock-decrement.ts +13 -1
- package/src/executor-generator.ts +212 -19
- package/src/index.ts +28 -7
- package/src/invoice/api-routes-code.ts +424 -391
- package/src/invoice/data-access-code.ts +431 -110
- package/src/invoice/index.ts +31 -1
- package/src/invoice/invoice-assembly-code.ts +514 -0
- package/src/invoice/invoice-html-code.ts +111 -9
- package/src/invoice/pdf-service-client-code.ts +3 -4
- package/src/nodes/account/account-login.ts +4 -3
- package/src/nodes/account/account-signup.ts +7 -4
- package/src/nodes/ai/ai-select-database-data.ts +10 -1
- package/src/nodes/browser/browser-get-push-subscription.ts +23 -0
- package/src/nodes/browser/browser-show-notification.ts +61 -38
- package/src/nodes/browser/browser-subscribe-to-push.ts +26 -36
- package/src/nodes/browser/browser-unsubscribe-from-push.ts +22 -0
- package/src/nodes/browser/push-api-access.ts +20 -0
- package/src/nodes/cart/cart-add-item.ts +200 -9
- package/src/nodes/cart/cart-clear.ts +11 -0
- package/src/nodes/cart/cart-get-total.ts +279 -7
- package/src/nodes/cart/cart-price-order.ts +351 -0
- package/src/nodes/cart/cart-update-item-quantity.ts +7 -0
- package/src/nodes/data/data-count.ts +9 -1
- package/src/nodes/data/data-create-item.ts +15 -1
- package/src/nodes/data/data-delete-item.ts +32 -0
- package/src/nodes/data/data-raw-query.ts +9 -1
- package/src/nodes/data/data-select.ts +9 -1
- package/src/nodes/data/data-update-item.ts +32 -0
- package/src/nodes/ecommerce/ecommerce-generate-invoice.ts +11 -1
- package/src/nodes/file-storage/file-storage-upload.ts +8 -0
- package/src/nodes/general/general-custom-js.ts +21 -5
- package/src/nodes/index.ts +16 -6
- package/src/nodes/payment/payment-billing-portal.ts +51 -0
- package/src/nodes/payment/payment-charge-user.ts +236 -442
- package/src/nodes/payment/payment-close-checkout.ts +137 -0
- package/src/nodes/payment/payment-ensure-subscription-plan.ts +66 -0
- package/src/nodes/payment/payment-manage-subscription.ts +89 -0
- package/src/nodes/payment/payment-refund.ts +52 -467
- package/src/nodes/payment-drivers-global.d.ts +13 -0
- package/src/nodes/push/push-send-notification.ts +83 -0
- package/src/nodes/workflow-utils-global.d.ts +5 -0
- package/src/payments/drivers/coingate-driver-code.ts +466 -0
- package/src/payments/drivers/mollie-driver-code.ts +618 -0
- package/src/payments/drivers/paddle-driver-code.ts +678 -0
- package/src/payments/drivers/paypal-driver-code.ts +1256 -0
- package/src/payments/drivers/razorpay-driver-code.ts +727 -0
- package/src/payments/drivers/square-driver-code.ts +926 -0
- package/src/payments/drivers/stripe-driver-code.ts +773 -0
- package/src/payments/index.ts +204 -0
- package/src/payments/payment-core-code.ts +421 -0
- package/src/payments/payment-driver-code-map.ts +19 -0
- package/src/payments/payment-drivers-scope.ts +66 -0
- package/src/payments/payment-registry-code.ts +38 -0
- package/src/pg-client-code.ts +30 -0
- package/src/runtime-storage-generator.ts +241 -4
- package/src/secret-collector.ts +8 -3
- package/src/security-scanner.ts +22 -0
- package/src/segment-context-needs.ts +148 -0
- package/src/segment-splitter.ts +6 -1
- package/src/segment-trust.ts +170 -0
- package/src/sent-email-log/sent-email-log-code.ts +2 -32
- package/src/server-runtime-code.ts +298 -0
- package/src/session-cookie-resolver.ts +9 -277
- package/src/subscriber-access-route-generator.ts +351 -0
- package/src/types.ts +6 -0
- package/src/webhook-delivery-lease/index.ts +44 -0
- package/src/webhook-delivery-lease/webhook-delivery-lease-code.ts +151 -0
- package/src/webhook-delivery-lease/webhook-delivery-lease-scope.ts +18 -0
- package/src/webhook-generator.ts +359 -260
- package/src/webhook-signature-verification.ts +180 -25
- package/src/workflow-auth-generator.ts +137 -28
- package/src/workflow-component-plugin.ts +77 -20
- package/src/workflow-project-plugin.ts +247 -44
- package/dist/cjs/nodes/payment/payment-cancel-plan.d.ts +0 -3
- package/dist/cjs/nodes/payment/payment-cancel-plan.d.ts.map +0 -1
- package/dist/cjs/nodes/payment/payment-cancel-plan.js +0 -33
- package/dist/cjs/nodes/payment/payment-cancel-plan.js.map +0 -1
- package/dist/cjs/nodes/payment/payment-create-subscription.d.ts +0 -3
- package/dist/cjs/nodes/payment/payment-create-subscription.d.ts.map +0 -1
- package/dist/cjs/nodes/payment/payment-create-subscription.js +0 -41
- package/dist/cjs/nodes/payment/payment-create-subscription.js.map +0 -1
- package/dist/cjs/nodes/payment/payment-subscribe-to-plan.d.ts +0 -3
- package/dist/cjs/nodes/payment/payment-subscribe-to-plan.d.ts.map +0 -1
- package/dist/cjs/nodes/payment/payment-subscribe-to-plan.js +0 -45
- package/dist/cjs/nodes/payment/payment-subscribe-to-plan.js.map +0 -1
- package/dist/esm/nodes/payment/payment-cancel-plan.d.ts +0 -3
- package/dist/esm/nodes/payment/payment-cancel-plan.d.ts.map +0 -1
- package/dist/esm/nodes/payment/payment-cancel-plan.js +0 -30
- package/dist/esm/nodes/payment/payment-cancel-plan.js.map +0 -1
- package/dist/esm/nodes/payment/payment-create-subscription.d.ts +0 -3
- package/dist/esm/nodes/payment/payment-create-subscription.d.ts.map +0 -1
- package/dist/esm/nodes/payment/payment-create-subscription.js +0 -38
- package/dist/esm/nodes/payment/payment-create-subscription.js.map +0 -1
- package/dist/esm/nodes/payment/payment-subscribe-to-plan.d.ts +0 -3
- package/dist/esm/nodes/payment/payment-subscribe-to-plan.d.ts.map +0 -1
- package/dist/esm/nodes/payment/payment-subscribe-to-plan.js +0 -42
- package/dist/esm/nodes/payment/payment-subscribe-to-plan.js.map +0 -1
- package/src/nodes/payment/payment-cancel-plan.ts +0 -33
- package/src/nodes/payment/payment-create-subscription.ts +0 -42
- package/src/nodes/payment/payment-subscribe-to-plan.ts +0 -46
|
@@ -0,0 +1,948 @@
|
|
|
1
|
+
/* tslint:disable:function-constructor */
|
|
2
|
+
import { parse } from '@babel/parser'
|
|
3
|
+
import { generateDataAPIRoute } from '../src/data-api-route-generator'
|
|
4
|
+
import { dataSelect } from '../src/nodes/data/data-select'
|
|
5
|
+
import { dataCount } from '../src/nodes/data/data-count'
|
|
6
|
+
import { dataCreateItem } from '../src/nodes/data/data-create-item'
|
|
7
|
+
import { dataRawQuery } from '../src/nodes/data/data-raw-query'
|
|
8
|
+
import { dataUpdateItem } from '../src/nodes/data/data-update-item'
|
|
9
|
+
import { dataDeleteItem } from '../src/nodes/data/data-delete-item'
|
|
10
|
+
import { accountSignup } from '../src/nodes/account/account-signup'
|
|
11
|
+
import { generateSignupRouteFile } from '../src/auth-generator'
|
|
12
|
+
import { resolveAuthUsersTableName } from '../src/workflow-project-plugin'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The generated `/api/data/<ds>/<op>` route is reachable from any browser, so
|
|
16
|
+
* the tables that ARE money (gift cards and their ledger) are refused to it
|
|
17
|
+
* outright, and the tables that decide how much money is given away
|
|
18
|
+
* (vouchers, automatic discounts, the redemption ledger) are refused every
|
|
19
|
+
* write — unless the request carries the app's internal secret, which only a
|
|
20
|
+
* server-side workflow node can read. Executed against a fake pg client: the
|
|
21
|
+
* verdict is a status code, not a substring.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const SECRET = 'server-secret'
|
|
25
|
+
|
|
26
|
+
interface RouteResult {
|
|
27
|
+
status: number
|
|
28
|
+
body: any
|
|
29
|
+
queries: string[]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type RouteRunner = (
|
|
33
|
+
operation: string,
|
|
34
|
+
body: Record<string, unknown>,
|
|
35
|
+
headers?: Record<string, string>
|
|
36
|
+
) => Promise<RouteResult>
|
|
37
|
+
|
|
38
|
+
function bootRoute(
|
|
39
|
+
secret: string | undefined,
|
|
40
|
+
options: { authUsersTableName?: string; rows?: any[] } = {}
|
|
41
|
+
): RouteRunner {
|
|
42
|
+
const code = generateDataAPIRoute(options)
|
|
43
|
+
const queries: string[] = []
|
|
44
|
+
class FakeClient {
|
|
45
|
+
public async connect(): Promise<void> {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
public async end(): Promise<void> {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
public async query(sql: string): Promise<{ rows: any[]; rowCount: number }> {
|
|
52
|
+
queries.push(sql)
|
|
53
|
+
if (/information_schema/i.test(sql)) {
|
|
54
|
+
return { rows: [], rowCount: 0 }
|
|
55
|
+
}
|
|
56
|
+
if (/^SELECT COUNT/i.test(sql)) {
|
|
57
|
+
return { rows: [{ count: '0' }], rowCount: 1 }
|
|
58
|
+
}
|
|
59
|
+
const rows = options.rows || []
|
|
60
|
+
return { rows, rowCount: rows.length }
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const moduleObj: { exports: any } = { exports: {} }
|
|
64
|
+
const fakeRequire = (name: string): any => {
|
|
65
|
+
if (name === 'pg') {
|
|
66
|
+
return { Client: FakeClient }
|
|
67
|
+
}
|
|
68
|
+
// The users-row guard resolves the caller's session; nobody is signed in
|
|
69
|
+
// in these tests.
|
|
70
|
+
if (name === 'next-auth/jwt') {
|
|
71
|
+
return { getToken: async () => null }
|
|
72
|
+
}
|
|
73
|
+
throw new Error('unexpected require: ' + name)
|
|
74
|
+
}
|
|
75
|
+
new Function('require', 'module', 'exports', 'process', 'console', code)(
|
|
76
|
+
fakeRequire,
|
|
77
|
+
moduleObj,
|
|
78
|
+
moduleObj.exports,
|
|
79
|
+
{ env: { NEXTAUTH_SECRET: secret, TELEPORT_DB_CONNECTION_STRING: 'postgresql://x' } },
|
|
80
|
+
{ error: () => undefined, warn: () => undefined, log: () => undefined }
|
|
81
|
+
)
|
|
82
|
+
const handler = moduleObj.exports
|
|
83
|
+
return async (operation, body, headers = {}) => {
|
|
84
|
+
queries.length = 0
|
|
85
|
+
let status = 0
|
|
86
|
+
let responseBody: any = null
|
|
87
|
+
const res = {
|
|
88
|
+
status(statusCode: number) {
|
|
89
|
+
status = statusCode
|
|
90
|
+
return this
|
|
91
|
+
},
|
|
92
|
+
json(payload: any) {
|
|
93
|
+
responseBody = payload
|
|
94
|
+
return this
|
|
95
|
+
},
|
|
96
|
+
}
|
|
97
|
+
await handler({ method: 'POST', query: { params: ['ds-1', operation] }, headers, body }, res)
|
|
98
|
+
return { status, body: responseBody, queries: queries.slice() }
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const internal = { 'x-internal-data-secret': SECRET }
|
|
103
|
+
// The AI data-query node: server-side, so it may run raw SQL, but the SQL is a
|
|
104
|
+
// model's answer to a visitor — the statement scan still applies to it.
|
|
105
|
+
const restricted = { 'x-internal-data-secret': SECRET, 'x-tq-restricted-sql': '1' }
|
|
106
|
+
|
|
107
|
+
describe('data API — money tables are server-only', () => {
|
|
108
|
+
const run = bootRoute(SECRET)
|
|
109
|
+
|
|
110
|
+
it('still emits the whole route — a stray backtick would cut the file off', () => {
|
|
111
|
+
const code = generateDataAPIRoute()
|
|
112
|
+
expect(code).toContain('module.exports = async function handler(req, res)')
|
|
113
|
+
expect(() => parse(code, { sourceType: 'script' })).not.toThrow()
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it('refuses a browser every operation on the gift-card, voucher and customer-record tables', async () => {
|
|
117
|
+
for (const tableName of [
|
|
118
|
+
'teleport_gift_cards',
|
|
119
|
+
'teleport_gift_card_transactions',
|
|
120
|
+
'teleport_vouchers',
|
|
121
|
+
'teleport_voucher_redemptions',
|
|
122
|
+
// A customer's own records reach a browser only through a server
|
|
123
|
+
// segment (their order page) or the admin's session — the list is
|
|
124
|
+
// every buyer's name, address and email.
|
|
125
|
+
'users',
|
|
126
|
+
'teleport_orders',
|
|
127
|
+
'teleport_order_items',
|
|
128
|
+
'teleport_invoices',
|
|
129
|
+
'teleport_events',
|
|
130
|
+
'teleport_shipments',
|
|
131
|
+
'teleport_withdrawal_requests',
|
|
132
|
+
'teleport_abandoned_carts',
|
|
133
|
+
'teleport_cart',
|
|
134
|
+
'teleport_favourites',
|
|
135
|
+
'teleport_product_reviews',
|
|
136
|
+
]) {
|
|
137
|
+
for (const [operation, body] of [
|
|
138
|
+
['select', { tableName }],
|
|
139
|
+
['count', { tableName }],
|
|
140
|
+
['create', { tableName, columnMappings: { balance: 1 } }],
|
|
141
|
+
['update', { tableName, columnMappings: { balance: 1 }, filters: [] }],
|
|
142
|
+
['delete', { tableName, filters: [] }],
|
|
143
|
+
] as Array<[string, Record<string, unknown>]>) {
|
|
144
|
+
const result = await run(operation, body)
|
|
145
|
+
expect(result.status).toBe(403)
|
|
146
|
+
if (operation === 'select' || operation === 'count') {
|
|
147
|
+
expect(result.body.error).toContain(tableName)
|
|
148
|
+
}
|
|
149
|
+
// Refused BEFORE the database is touched.
|
|
150
|
+
expect(result.queries).toEqual([])
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
it('refuses the same however the table is spelled', async () => {
|
|
156
|
+
for (const tableName of [
|
|
157
|
+
'"teleport_gift_cards"',
|
|
158
|
+
'public.teleport_gift_cards',
|
|
159
|
+
'TELEPORT_GIFT_CARDS',
|
|
160
|
+
]) {
|
|
161
|
+
expect((await run('select', { tableName })).status).toBe(403)
|
|
162
|
+
}
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
it('lets a server-side node through with the internal secret', async () => {
|
|
166
|
+
const result = await run('select', { tableName: 'teleport_gift_cards' }, internal)
|
|
167
|
+
expect(result.status).toBe(200)
|
|
168
|
+
expect(result.queries[0]).toContain('FROM teleport_gift_cards')
|
|
169
|
+
expect(
|
|
170
|
+
(
|
|
171
|
+
await run(
|
|
172
|
+
'update',
|
|
173
|
+
{
|
|
174
|
+
tableName: 'teleport_vouchers',
|
|
175
|
+
columnMappings: { usage_count: 1 },
|
|
176
|
+
filters: [{ field: 'id', value: 'v1' }],
|
|
177
|
+
},
|
|
178
|
+
internal
|
|
179
|
+
)
|
|
180
|
+
).status
|
|
181
|
+
).toBe(200)
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
it('does not take a wrong secret, nor an empty one when none is configured', async () => {
|
|
185
|
+
expect(
|
|
186
|
+
(
|
|
187
|
+
await run(
|
|
188
|
+
'select',
|
|
189
|
+
{ tableName: 'teleport_gift_cards' },
|
|
190
|
+
{ 'x-internal-data-secret': 'nope' }
|
|
191
|
+
)
|
|
192
|
+
).status
|
|
193
|
+
).toBe(403)
|
|
194
|
+
const unconfigured = bootRoute(undefined)
|
|
195
|
+
expect(
|
|
196
|
+
(
|
|
197
|
+
await unconfigured(
|
|
198
|
+
'select',
|
|
199
|
+
{ tableName: 'teleport_gift_cards' },
|
|
200
|
+
{ 'x-internal-data-secret': '' }
|
|
201
|
+
)
|
|
202
|
+
).status
|
|
203
|
+
).toBe(403)
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
it('refuses a browser every write on the automatic-discount table, but not a read', async () => {
|
|
207
|
+
const tableName = 'teleport_discounts'
|
|
208
|
+
expect((await run('create', { tableName, columnMappings: { name: 'X' } })).status).toBe(403)
|
|
209
|
+
expect(
|
|
210
|
+
(await run('update', { tableName, columnMappings: { name: 'X' }, filters: [] })).status
|
|
211
|
+
).toBe(403)
|
|
212
|
+
expect((await run('delete', { tableName, filters: [] })).status).toBe(403)
|
|
213
|
+
// The storefront provider reads the active rules from the browser.
|
|
214
|
+
expect((await run('select', { tableName })).status).toBe(200)
|
|
215
|
+
expect((await run('count', { tableName })).status).toBe(200)
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
it('serves the discount table to a browser only as the live-rule feed', async () => {
|
|
219
|
+
const tableName = 'teleport_discounts'
|
|
220
|
+
const live =
|
|
221
|
+
"status = 'active' AND (starts_at IS NULL OR starts_at <= NOW()) AND (ends_at IS NULL OR ends_at > NOW())"
|
|
222
|
+
|
|
223
|
+
// What the storefront provider sends: the merchant's campaign plan is
|
|
224
|
+
// narrowed to the rules that price an order right now.
|
|
225
|
+
const feed = await run('select', {
|
|
226
|
+
tableName,
|
|
227
|
+
filters: [{ field: 'status', value: 'active', operator: '=' }],
|
|
228
|
+
limit: 500,
|
|
229
|
+
})
|
|
230
|
+
expect(feed.status).toBe(200)
|
|
231
|
+
const select = feed.queries.find((sql) => /^SELECT /.test(sql) && !/^SELECT COUNT/i.test(sql))
|
|
232
|
+
expect(select).toContain('SELECT id, name, status, priority, discount_type')
|
|
233
|
+
// The window is the database's judgement, and when a campaign ends is the
|
|
234
|
+
// merchant's business.
|
|
235
|
+
expect(select).not.toContain('starts_at,')
|
|
236
|
+
expect(select).not.toContain('ends_at,')
|
|
237
|
+
expect(select).toContain(' AND ' + live)
|
|
238
|
+
// Drafts, paused rules, how often a campaign ran: none of it is the
|
|
239
|
+
// shopper's business.
|
|
240
|
+
expect(select).not.toContain('*')
|
|
241
|
+
expect(select).not.toContain('description')
|
|
242
|
+
expect(select).not.toContain('usage_count')
|
|
243
|
+
// The count beside the rows counts the same rows.
|
|
244
|
+
expect(feed.queries.find((sql) => /^SELECT COUNT/i.test(sql))).toContain(' AND ' + live)
|
|
245
|
+
|
|
246
|
+
// No filters at all: the window is still the database's.
|
|
247
|
+
const unfiltered = await run('select', { tableName })
|
|
248
|
+
expect(unfiltered.queries[0]).toContain(' WHERE ' + live)
|
|
249
|
+
expect((await run('count', { tableName })).queries[0]).toContain(' WHERE ' + live)
|
|
250
|
+
|
|
251
|
+
// A caller cannot ask for the columns back, nor widen the window.
|
|
252
|
+
const asked = await run('select', {
|
|
253
|
+
tableName,
|
|
254
|
+
selectedColumns: ['id', 'description', 'usage_count'],
|
|
255
|
+
filters: [{ field: 'status', value: 'draft', operator: '=' }],
|
|
256
|
+
})
|
|
257
|
+
expect(asked.queries[0]).not.toContain('description')
|
|
258
|
+
expect(asked.queries[0]).toContain(' AND ' + live)
|
|
259
|
+
|
|
260
|
+
// A server segment prices the order from the whole table.
|
|
261
|
+
const server = await run('select', { tableName }, internal)
|
|
262
|
+
expect(server.queries[0]).toBe('SELECT * FROM teleport_discounts')
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
it('refuses a feed filter or sort on a column the feed does not serve — a filter is an oracle', async () => {
|
|
266
|
+
const tableName = 'teleport_discounts'
|
|
267
|
+
for (const [operation, body] of [
|
|
268
|
+
['select', { tableName, filters: [{ field: 'usage_count', operator: '>', value: 100 }] }],
|
|
269
|
+
[
|
|
270
|
+
'select',
|
|
271
|
+
{
|
|
272
|
+
tableName,
|
|
273
|
+
filters: [{ source: 'description', operand: 'contains', destination: 'launch' }],
|
|
274
|
+
},
|
|
275
|
+
],
|
|
276
|
+
[
|
|
277
|
+
'select',
|
|
278
|
+
{ tableName, filters: [{ field: 'length(description)', operator: '>', value: 3 }] },
|
|
279
|
+
],
|
|
280
|
+
['select', { tableName, sorts: [{ field: 'usage_count', order: 'desc' }] }],
|
|
281
|
+
['select', { tableName, sorts: [{ field: 'ends_at', order: 'asc' }] }],
|
|
282
|
+
['count', { tableName, filters: [{ field: 'usage_count', operator: '>', value: 100 }] }],
|
|
283
|
+
] as Array<[string, Record<string, unknown>]>) {
|
|
284
|
+
const result = await run(operation, body)
|
|
285
|
+
expect(result.status).toBe(403)
|
|
286
|
+
expect(result.queries).toEqual([])
|
|
287
|
+
}
|
|
288
|
+
// The storefront's own read, and any filter or sort over served columns.
|
|
289
|
+
expect(
|
|
290
|
+
(
|
|
291
|
+
await run('select', {
|
|
292
|
+
tableName,
|
|
293
|
+
filters: [{ field: '"status"', value: 'active', operator: '=' }],
|
|
294
|
+
sorts: [{ field: 'priority', order: 'asc' }],
|
|
295
|
+
})
|
|
296
|
+
).status
|
|
297
|
+
).toBe(200)
|
|
298
|
+
// A server segment filters however it likes.
|
|
299
|
+
expect(
|
|
300
|
+
(
|
|
301
|
+
await run(
|
|
302
|
+
'select',
|
|
303
|
+
{ tableName, filters: [{ field: 'usage_count', operator: '>', value: 1 }] },
|
|
304
|
+
internal
|
|
305
|
+
)
|
|
306
|
+
).status
|
|
307
|
+
).toBe(200)
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
it('serves a browser the storefront catalogue to READ, and nothing more', async () => {
|
|
311
|
+
// Generated browser code only reads here (the storefront feeds); every
|
|
312
|
+
// write and every raw statement comes from a server segment presenting
|
|
313
|
+
// the secret. So a browser that writes is not the store: it could mark
|
|
314
|
+
// its own order paid. And it reads only the catalogue tables the
|
|
315
|
+
// storefront itself reads — any other table is refused (see
|
|
316
|
+
// data-api-browser-reads.test.ts).
|
|
317
|
+
expect((await run('select', { tableName: 'teleport_products' })).status).toBe(200)
|
|
318
|
+
expect((await run('count', { tableName: 'teleport_products' })).status).toBe(200)
|
|
319
|
+
expect((await run('select', { tableName: 'teleport_gift_cards_archive' })).status).toBe(403)
|
|
320
|
+
for (const [operation, body] of [
|
|
321
|
+
['create', { tableName: 'teleport_orders', columnMappings: { status: 'pending' } }],
|
|
322
|
+
[
|
|
323
|
+
'update',
|
|
324
|
+
{
|
|
325
|
+
tableName: 'teleport_orders',
|
|
326
|
+
columnMappings: { payment_status: 'paid' },
|
|
327
|
+
filters: [{ field: 'id', value: 'o1' }],
|
|
328
|
+
},
|
|
329
|
+
],
|
|
330
|
+
['delete', { tableName: 'teleport_orders', filters: [{ field: 'id', value: 'o1' }] }],
|
|
331
|
+
['raw-query', { query: 'SELECT 1 FROM teleport_products', params: [] }],
|
|
332
|
+
[
|
|
333
|
+
'select',
|
|
334
|
+
{ tableName: 'teleport_products', rawQueryUserPart: 'SELECT * FROM teleport_products' },
|
|
335
|
+
],
|
|
336
|
+
] as Array<[string, Record<string, unknown>]>) {
|
|
337
|
+
const result = await run(operation, body)
|
|
338
|
+
expect(result.status).toBe(403)
|
|
339
|
+
expect(result.queries).toEqual([])
|
|
340
|
+
}
|
|
341
|
+
expect(
|
|
342
|
+
(
|
|
343
|
+
await run(
|
|
344
|
+
'create',
|
|
345
|
+
{ tableName: 'teleport_orders', columnMappings: { status: 'pending' } },
|
|
346
|
+
internal
|
|
347
|
+
)
|
|
348
|
+
).status
|
|
349
|
+
).toBe(200)
|
|
350
|
+
})
|
|
351
|
+
|
|
352
|
+
it('keeps the old scan for an app with no secret to tell its own calls apart', async () => {
|
|
353
|
+
// No authentication, hence no store: nothing identifies a server call, so
|
|
354
|
+
// writes and raw statements stay open and only the money tables are held back.
|
|
355
|
+
const open = bootRoute(undefined)
|
|
356
|
+
expect(
|
|
357
|
+
(await open('create', { tableName: 'teleport_posts', columnMappings: { status: 'draft' } }))
|
|
358
|
+
.status
|
|
359
|
+
).toBe(200)
|
|
360
|
+
expect(
|
|
361
|
+
(await open('raw-query', { query: 'SELECT 1 FROM teleport_products', params: [] })).status
|
|
362
|
+
).toBe(200)
|
|
363
|
+
expect(
|
|
364
|
+
(await open('raw-query', { query: 'SELECT code FROM teleport_gift_cards', params: [] }))
|
|
365
|
+
.status
|
|
366
|
+
).toBe(403)
|
|
367
|
+
expect((await open('select', { tableName: 'teleport_orders' })).status).toBe(403)
|
|
368
|
+
})
|
|
369
|
+
|
|
370
|
+
it('refuses a raw query that mentions the ledger, quoted or schema-qualified', async () => {
|
|
371
|
+
for (const query of [
|
|
372
|
+
'SELECT balance FROM teleport_gift_cards WHERE code = $1',
|
|
373
|
+
'SELECT * FROM "teleport_gift_card_transactions"',
|
|
374
|
+
'SELECT 1 FROM public.teleport_gift_cards',
|
|
375
|
+
'WITH c AS (SELECT id FROM Teleport_Gift_Cards) SELECT * FROM c',
|
|
376
|
+
"SELECT 1 /* teleport_products */ FROM teleport_gift_cards -- 'x'",
|
|
377
|
+
]) {
|
|
378
|
+
const result = await run('raw-query', { query, params: [] }, restricted)
|
|
379
|
+
expect(result.status).toBe(403)
|
|
380
|
+
expect(result.queries).toEqual([])
|
|
381
|
+
}
|
|
382
|
+
// A table name inside a string literal is data, not a reference.
|
|
383
|
+
expect(
|
|
384
|
+
(
|
|
385
|
+
await run(
|
|
386
|
+
'raw-query',
|
|
387
|
+
{ query: "SELECT 1 FROM teleport_products WHERE name = 'teleport_gift_cards'" },
|
|
388
|
+
restricted
|
|
389
|
+
)
|
|
390
|
+
).status
|
|
391
|
+
).toBe(200)
|
|
392
|
+
})
|
|
393
|
+
|
|
394
|
+
it('refuses a raw write on the discount table, a raw read of the voucher tables, and lets a discount read through', async () => {
|
|
395
|
+
expect(
|
|
396
|
+
(
|
|
397
|
+
await run(
|
|
398
|
+
'raw-query',
|
|
399
|
+
{
|
|
400
|
+
query: 'UPDATE teleport_vouchers SET usage_count = usage_count + 1 WHERE id = $1',
|
|
401
|
+
params: ['v1'],
|
|
402
|
+
},
|
|
403
|
+
restricted
|
|
404
|
+
)
|
|
405
|
+
).status
|
|
406
|
+
).toBe(403)
|
|
407
|
+
expect(
|
|
408
|
+
(
|
|
409
|
+
await run(
|
|
410
|
+
'raw-query',
|
|
411
|
+
{
|
|
412
|
+
query:
|
|
413
|
+
'WITH bump AS (SELECT 1) INSERT INTO teleport_voucher_redemptions (voucher_id) SELECT 1',
|
|
414
|
+
},
|
|
415
|
+
restricted
|
|
416
|
+
)
|
|
417
|
+
).status
|
|
418
|
+
).toBe(403)
|
|
419
|
+
expect(
|
|
420
|
+
(await run('raw-query', { query: 'DELETE FROM teleport_discounts' }, restricted)).status
|
|
421
|
+
).toBe(403)
|
|
422
|
+
expect(
|
|
423
|
+
(await run('raw-query', { query: 'TRUNCATE teleport_discounts' }, restricted)).status
|
|
424
|
+
).toBe(403)
|
|
425
|
+
// A generated batch is a list of single-use coupons: no browser lists it.
|
|
426
|
+
expect(
|
|
427
|
+
(
|
|
428
|
+
await run(
|
|
429
|
+
'raw-query',
|
|
430
|
+
{
|
|
431
|
+
query: "SELECT * FROM teleport_vouchers WHERE code = $1 AND status = 'active'",
|
|
432
|
+
params: ['X'],
|
|
433
|
+
},
|
|
434
|
+
restricted
|
|
435
|
+
)
|
|
436
|
+
).status
|
|
437
|
+
).toBe(403)
|
|
438
|
+
// The feed is the ONE shape a browser reads the rule table in, and a
|
|
439
|
+
// statement the caller wrote is not it.
|
|
440
|
+
expect(
|
|
441
|
+
(
|
|
442
|
+
await run(
|
|
443
|
+
'raw-query',
|
|
444
|
+
{ query: "SELECT * FROM teleport_discounts WHERE status = 'active'", params: [] },
|
|
445
|
+
restricted
|
|
446
|
+
)
|
|
447
|
+
).status
|
|
448
|
+
).toBe(403)
|
|
449
|
+
expect(
|
|
450
|
+
(
|
|
451
|
+
await run(
|
|
452
|
+
'select',
|
|
453
|
+
{ tableName: 'teleport_products', rawQueryUserPart: 'SELECT * FROM teleport_discounts' },
|
|
454
|
+
restricted
|
|
455
|
+
)
|
|
456
|
+
).status
|
|
457
|
+
).toBe(403)
|
|
458
|
+
expect(
|
|
459
|
+
(
|
|
460
|
+
await run(
|
|
461
|
+
'raw-query',
|
|
462
|
+
{ query: "SELECT * FROM teleport_discounts WHERE status = 'active'", params: [] },
|
|
463
|
+
internal
|
|
464
|
+
)
|
|
465
|
+
).status
|
|
466
|
+
).toBe(200)
|
|
467
|
+
// Deliberately coarse: a statement that writes AND mentions a protected
|
|
468
|
+
// table is refused without working out which table the write lands on —
|
|
469
|
+
// parsing that is exactly the kind of guard that can be talked around.
|
|
470
|
+
expect(
|
|
471
|
+
(
|
|
472
|
+
await run(
|
|
473
|
+
'raw-query',
|
|
474
|
+
{
|
|
475
|
+
query:
|
|
476
|
+
'UPDATE teleport_orders SET discount_details = (SELECT name FROM teleport_discounts WHERE id = $1)',
|
|
477
|
+
params: ['d1'],
|
|
478
|
+
},
|
|
479
|
+
restricted
|
|
480
|
+
)
|
|
481
|
+
).status
|
|
482
|
+
).toBe(403)
|
|
483
|
+
expect(
|
|
484
|
+
(
|
|
485
|
+
await run(
|
|
486
|
+
'raw-query',
|
|
487
|
+
{ query: 'UPDATE teleport_vouchers SET usage_count = 1', params: [] },
|
|
488
|
+
internal
|
|
489
|
+
)
|
|
490
|
+
).status
|
|
491
|
+
).toBe(200)
|
|
492
|
+
})
|
|
493
|
+
|
|
494
|
+
it("checks a select's raw override like a raw query", async () => {
|
|
495
|
+
expect(
|
|
496
|
+
(
|
|
497
|
+
await run(
|
|
498
|
+
'select',
|
|
499
|
+
{
|
|
500
|
+
tableName: 'teleport_products',
|
|
501
|
+
rawQueryUserPart: 'SELECT code FROM teleport_gift_cards',
|
|
502
|
+
},
|
|
503
|
+
restricted
|
|
504
|
+
)
|
|
505
|
+
).status
|
|
506
|
+
).toBe(403)
|
|
507
|
+
})
|
|
508
|
+
|
|
509
|
+
it('refuses a statement that can reach a protected table without spelling its name', async () => {
|
|
510
|
+
for (const query of [
|
|
511
|
+
// A Unicode-escaped identifier: \005f is the underscore.
|
|
512
|
+
'SELECT * FROM U&"teleport\\005fgift_cards"',
|
|
513
|
+
'select code from u&"teleport\\005fvouchers"',
|
|
514
|
+
'SELECT * FROM U&"teleport\\005fdiscounts"',
|
|
515
|
+
// Quote and comment markers inside a quoted identifier, `$` and `E`
|
|
516
|
+
// inside an identifier: the scan lexes them as Postgres does.
|
|
517
|
+
'SELECT code AS "x\'", balance FROM teleport_gift_cards -- \'',
|
|
518
|
+
'SELECT 1 AS "--", code, balance FROM teleport_gift_cards',
|
|
519
|
+
'SELECT code AS a$b$, balance FROM teleport_gift_cards AS g$b$',
|
|
520
|
+
"SELECT CASE WHEN true THEN 'a' ELSE'\\' END, code FROM teleport_vouchers -- '",
|
|
521
|
+
// The planner statistics hold sampled values of every column.
|
|
522
|
+
"SELECT histogram_bounds::text FROM pg_stats WHERE tablename = 'teleport_vouchers'",
|
|
523
|
+
// Functions that run SQL text, or dump whole tables and schemas.
|
|
524
|
+
"SELECT query_to_xml('select code from teleport_gift_cards', true, false, '')",
|
|
525
|
+
"SELECT table_to_xml('teleport_' || 'gift_cards', true, false, '')",
|
|
526
|
+
"SELECT pg_catalog.schema_to_xml('public', true, false, '')",
|
|
527
|
+
"SELECT database_to_xml(true, false, '')",
|
|
528
|
+
"SELECT * FROM ts_stat('select to_tsvector(code) from teleport_gift_cards')",
|
|
529
|
+
]) {
|
|
530
|
+
const raw = await run('raw-query', { query, params: [] }, restricted)
|
|
531
|
+
expect(raw.status).toBe(403)
|
|
532
|
+
expect(raw.queries).toEqual([])
|
|
533
|
+
const override = await run(
|
|
534
|
+
'select',
|
|
535
|
+
{ tableName: 'teleport_products', rawQueryUserPart: query },
|
|
536
|
+
restricted
|
|
537
|
+
)
|
|
538
|
+
expect(override.status).toBe(403)
|
|
539
|
+
expect(override.queries).toEqual([])
|
|
540
|
+
}
|
|
541
|
+
// The server keeps every spelling it writes.
|
|
542
|
+
expect(
|
|
543
|
+
(
|
|
544
|
+
await run(
|
|
545
|
+
'raw-query',
|
|
546
|
+
{ query: 'SELECT * FROM U&"teleport\\005fgift_cards"', params: [] },
|
|
547
|
+
internal
|
|
548
|
+
)
|
|
549
|
+
).status
|
|
550
|
+
).toBe(200)
|
|
551
|
+
})
|
|
552
|
+
|
|
553
|
+
it('keeps password reset tokens server-only — reading one is taking the account', async () => {
|
|
554
|
+
expect((await run('select', { tableName: 'password_reset_tokens' })).status).toBe(403)
|
|
555
|
+
for (const headers of [{}, restricted]) {
|
|
556
|
+
expect(
|
|
557
|
+
(
|
|
558
|
+
await run(
|
|
559
|
+
'raw-query',
|
|
560
|
+
{
|
|
561
|
+
query: 'SELECT token FROM password_reset_tokens WHERE email = $1',
|
|
562
|
+
params: ['a@b.c'],
|
|
563
|
+
},
|
|
564
|
+
headers
|
|
565
|
+
)
|
|
566
|
+
).status
|
|
567
|
+
).toBe(403)
|
|
568
|
+
}
|
|
569
|
+
expect((await run('select', { tableName: 'password_reset_tokens' }, internal)).status).toBe(200)
|
|
570
|
+
})
|
|
571
|
+
|
|
572
|
+
it('keeps push subscriptions server-only — an endpoint and its keys can notify that device', async () => {
|
|
573
|
+
expect((await run('select', { tableName: 'teleport_push_subscriptions' })).status).toBe(403)
|
|
574
|
+
for (const headers of [{}, restricted]) {
|
|
575
|
+
expect(
|
|
576
|
+
(
|
|
577
|
+
await run(
|
|
578
|
+
'raw-query',
|
|
579
|
+
{ query: 'SELECT endpoint, p256dh, auth FROM teleport_push_subscriptions', params: [] },
|
|
580
|
+
headers
|
|
581
|
+
)
|
|
582
|
+
).status
|
|
583
|
+
).toBe(403)
|
|
584
|
+
}
|
|
585
|
+
expect(
|
|
586
|
+
(await run('select', { tableName: 'teleport_push_subscriptions' }, internal)).status
|
|
587
|
+
).toBe(200)
|
|
588
|
+
})
|
|
589
|
+
})
|
|
590
|
+
|
|
591
|
+
describe('data API — a browser cannot grant itself a role', () => {
|
|
592
|
+
// The money-table guard admits a browser whose session token says `admin`,
|
|
593
|
+
// and that role is a column of the user's OWN row. The same route exposes an
|
|
594
|
+
// update of that row, so without a column check the trust boundary is
|
|
595
|
+
// self-service.
|
|
596
|
+
const run = bootRoute(SECRET, { authUsersTableName: 'users' })
|
|
597
|
+
|
|
598
|
+
it('refuses an update that writes a role column, before the database is touched', async () => {
|
|
599
|
+
for (const columnMappings of [
|
|
600
|
+
{ role: 'admin' },
|
|
601
|
+
{ Role: 'admin' },
|
|
602
|
+
{ role_name: 'admin' },
|
|
603
|
+
{ roles: ['admin'] },
|
|
604
|
+
{ name: 'Mallory', role: 'admin' },
|
|
605
|
+
] as Array<Record<string, unknown>>) {
|
|
606
|
+
const result = await run('update', {
|
|
607
|
+
tableName: 'users',
|
|
608
|
+
columnMappings,
|
|
609
|
+
filters: [{ field: 'id', value: 'u1' }],
|
|
610
|
+
})
|
|
611
|
+
expect(result.status).toBe(403)
|
|
612
|
+
expect(result.queries).toEqual([])
|
|
613
|
+
}
|
|
614
|
+
// The column-mapping list shape the update node also sends.
|
|
615
|
+
const mapped = await run('update', {
|
|
616
|
+
tableName: 'users',
|
|
617
|
+
columnMappings: [{ source: 'role', destination: 'admin' }],
|
|
618
|
+
filters: [{ field: 'id', value: 'u1' }],
|
|
619
|
+
})
|
|
620
|
+
expect(mapped.status).toBe(403)
|
|
621
|
+
})
|
|
622
|
+
|
|
623
|
+
it('refuses it however the table is spelled, and leaves profile columns alone', async () => {
|
|
624
|
+
for (const tableName of ['public.users', '"users"', 'USERS']) {
|
|
625
|
+
expect(
|
|
626
|
+
(
|
|
627
|
+
await run('update', {
|
|
628
|
+
tableName,
|
|
629
|
+
columnMappings: { role: 'admin' },
|
|
630
|
+
filters: [{ field: 'id', value: 'u1' }],
|
|
631
|
+
})
|
|
632
|
+
).status
|
|
633
|
+
).toBe(403)
|
|
634
|
+
}
|
|
635
|
+
// A browser writes no row at all: a profile edit runs in a server segment,
|
|
636
|
+
// which presents the secret.
|
|
637
|
+
const profile = await run('update', {
|
|
638
|
+
tableName: 'users',
|
|
639
|
+
columnMappings: { name: 'Mallory' },
|
|
640
|
+
filters: [{ field: 'id', value: 'u1' }],
|
|
641
|
+
})
|
|
642
|
+
expect(profile.status).toBe(403)
|
|
643
|
+
expect(profile.queries).toEqual([])
|
|
644
|
+
})
|
|
645
|
+
|
|
646
|
+
it('refuses a create that writes a role column — a new row with a known password is a new admin', async () => {
|
|
647
|
+
for (const columnMappings of [
|
|
648
|
+
{ email: 'm@x.io', password: 'hash', role: 'admin' },
|
|
649
|
+
[
|
|
650
|
+
{ column: 'email', value: 'm@x.io' },
|
|
651
|
+
{ column: '"role"', value: 'admin' },
|
|
652
|
+
],
|
|
653
|
+
{ email: 'm@x.io', 'users.roles': ['admin'] },
|
|
654
|
+
{ email: 'm@x.io', roleName: 'admin' },
|
|
655
|
+
] as unknown[]) {
|
|
656
|
+
const result = await run('create', { tableName: 'users', columnMappings })
|
|
657
|
+
expect(result.status).toBe(403)
|
|
658
|
+
expect(result.queries).toEqual([])
|
|
659
|
+
}
|
|
660
|
+
// The anonymous-visitor row the resolve-user node ensures — from its
|
|
661
|
+
// server segment, which presents the secret.
|
|
662
|
+
expect(
|
|
663
|
+
(
|
|
664
|
+
await run(
|
|
665
|
+
'create',
|
|
666
|
+
{
|
|
667
|
+
tableName: 'users',
|
|
668
|
+
onConflictDoNothing: true,
|
|
669
|
+
columnMappings: [
|
|
670
|
+
{ column: 'id', value: '0b8e9f1e-0000-4000-8000-000000000000' },
|
|
671
|
+
{ column: 'email', value: 'anon@x.io' },
|
|
672
|
+
{ column: 'name', value: '' },
|
|
673
|
+
{ column: 'image', value: '' },
|
|
674
|
+
],
|
|
675
|
+
},
|
|
676
|
+
internal
|
|
677
|
+
)
|
|
678
|
+
).status
|
|
679
|
+
).toBe(200)
|
|
680
|
+
})
|
|
681
|
+
|
|
682
|
+
it('refuses an update that spells the role column quoted or table-qualified', async () => {
|
|
683
|
+
for (const column of ['"role"', 'users.role', '"ROLES"', 'public.users.rolename']) {
|
|
684
|
+
const result = await run('update', {
|
|
685
|
+
tableName: 'users',
|
|
686
|
+
columnMappings: { [column]: 'admin' },
|
|
687
|
+
filters: [{ field: 'id', value: 'u1' }],
|
|
688
|
+
})
|
|
689
|
+
expect(result.status).toBe(403)
|
|
690
|
+
expect(result.queries).toEqual([])
|
|
691
|
+
}
|
|
692
|
+
})
|
|
693
|
+
|
|
694
|
+
it('refuses a browser raw statement that writes the users table, whatever it names', async () => {
|
|
695
|
+
for (const query of [
|
|
696
|
+
// (`SET role` right after SET is the validator's SET ROLE refusal, so
|
|
697
|
+
// these lead with another column to reach the role guard itself.)
|
|
698
|
+
"UPDATE users SET name = name, role = 'admin' WHERE id = $1",
|
|
699
|
+
'UPDATE "users" SET (name, "role") = ROW(name, $1) WHERE id = $2',
|
|
700
|
+
"INSERT INTO public.users VALUES (gen_random_uuid(), 'm@x.io', 'hash', 'admin')",
|
|
701
|
+
'WITH promoted AS (UPDATE users SET name = name RETURNING id) SELECT * FROM promoted',
|
|
702
|
+
// \0075 is the u: the same table, spelled where a name scan cannot see it.
|
|
703
|
+
'UPDATE U&"\\0075sers" SET name = name, role = \'admin\' WHERE id = $1',
|
|
704
|
+
// `$` inside identifiers opens no dollar quote.
|
|
705
|
+
"UPDATE users AS a$z$ SET email = email, role = 'admin' WHERE id = $1 AND 1 = (SELECT 1 AS b$z$)",
|
|
706
|
+
]) {
|
|
707
|
+
for (const headers of [{}, restricted]) {
|
|
708
|
+
const result = await run('raw-query', { query, params: ['u1', 'u1'] }, headers)
|
|
709
|
+
expect(result.status).toBe(403)
|
|
710
|
+
expect(result.queries).toEqual([])
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
expect(
|
|
714
|
+
(
|
|
715
|
+
await run('select', {
|
|
716
|
+
tableName: 'teleport_products',
|
|
717
|
+
rawQueryUserPart: "UPDATE users SET name = name, role = 'admin' RETURNING id",
|
|
718
|
+
})
|
|
719
|
+
).status
|
|
720
|
+
).toBe(403)
|
|
721
|
+
// The one caller allowed raw SQL at all never reaches the users table — a
|
|
722
|
+
// statement can hand back a whole row without naming a credential column —
|
|
723
|
+
// nor the customers' orders (its statement is a model's answer to a
|
|
724
|
+
// visitor), while writing a catalogue table is not a role grant.
|
|
725
|
+
expect(
|
|
726
|
+
(
|
|
727
|
+
await run(
|
|
728
|
+
'raw-query',
|
|
729
|
+
{ query: 'SELECT id, name FROM users WHERE id = $1', params: ['u1'] },
|
|
730
|
+
restricted
|
|
731
|
+
)
|
|
732
|
+
).status
|
|
733
|
+
).toBe(403)
|
|
734
|
+
expect(
|
|
735
|
+
(
|
|
736
|
+
await run(
|
|
737
|
+
'raw-query',
|
|
738
|
+
{ query: 'SELECT shipping_address FROM teleport_orders WHERE id = $1', params: ['o1'] },
|
|
739
|
+
restricted
|
|
740
|
+
)
|
|
741
|
+
).status
|
|
742
|
+
).toBe(403)
|
|
743
|
+
expect(
|
|
744
|
+
(
|
|
745
|
+
await run(
|
|
746
|
+
'raw-query',
|
|
747
|
+
{ query: 'UPDATE teleport_products SET status = $1 WHERE id = $2', params: ['x', 'p1'] },
|
|
748
|
+
restricted
|
|
749
|
+
)
|
|
750
|
+
).status
|
|
751
|
+
).toBe(200)
|
|
752
|
+
// The server may.
|
|
753
|
+
expect(
|
|
754
|
+
(
|
|
755
|
+
await run(
|
|
756
|
+
'raw-query',
|
|
757
|
+
{ query: "UPDATE users SET name = name, role = 'admin' WHERE id = $1", params: ['u1'] },
|
|
758
|
+
internal
|
|
759
|
+
)
|
|
760
|
+
).status
|
|
761
|
+
).toBe(200)
|
|
762
|
+
})
|
|
763
|
+
|
|
764
|
+
it('guards the users table the session role is read from even when the identity table has another name', async () => {
|
|
765
|
+
const customers = bootRoute(SECRET, { authUsersTableName: 'customers' })
|
|
766
|
+
for (const tableName of ['customers', 'users']) {
|
|
767
|
+
expect(
|
|
768
|
+
(
|
|
769
|
+
await customers('update', {
|
|
770
|
+
tableName,
|
|
771
|
+
columnMappings: { role: 'admin' },
|
|
772
|
+
filters: [{ field: 'id', value: 'u1' }],
|
|
773
|
+
})
|
|
774
|
+
).status
|
|
775
|
+
).toBe(403)
|
|
776
|
+
}
|
|
777
|
+
expect(
|
|
778
|
+
(
|
|
779
|
+
await customers('raw-query', {
|
|
780
|
+
query: "UPDATE users SET name = name, role = 'admin'",
|
|
781
|
+
params: [],
|
|
782
|
+
})
|
|
783
|
+
).status
|
|
784
|
+
).toBe(403)
|
|
785
|
+
})
|
|
786
|
+
|
|
787
|
+
it('lets a server-side segment set a role, and leaves other tables untouched', async () => {
|
|
788
|
+
expect(
|
|
789
|
+
(
|
|
790
|
+
await run(
|
|
791
|
+
'update',
|
|
792
|
+
{
|
|
793
|
+
tableName: 'users',
|
|
794
|
+
columnMappings: { role: 'admin' },
|
|
795
|
+
filters: [{ field: 'id', value: 'u1' }],
|
|
796
|
+
},
|
|
797
|
+
internal
|
|
798
|
+
)
|
|
799
|
+
).status
|
|
800
|
+
).toBe(200)
|
|
801
|
+
expect(
|
|
802
|
+
(
|
|
803
|
+
await run(
|
|
804
|
+
'update',
|
|
805
|
+
{
|
|
806
|
+
tableName: 'teleport_product_reviews',
|
|
807
|
+
columnMappings: { role: 'admin' },
|
|
808
|
+
filters: [{ field: 'id', value: 'r1' }],
|
|
809
|
+
},
|
|
810
|
+
internal
|
|
811
|
+
)
|
|
812
|
+
).status
|
|
813
|
+
).toBe(200)
|
|
814
|
+
})
|
|
815
|
+
})
|
|
816
|
+
|
|
817
|
+
describe('the other ways a browser could write its own role', () => {
|
|
818
|
+
const signupWith = async (
|
|
819
|
+
body: Record<string, unknown>,
|
|
820
|
+
customUserProperties: Array<{ key: string }> = []
|
|
821
|
+
): Promise<Record<string, unknown>> => {
|
|
822
|
+
const code = generateSignupRouteFile({
|
|
823
|
+
enabled: true,
|
|
824
|
+
dataSourceType: 'postgresql',
|
|
825
|
+
customUserProperties,
|
|
826
|
+
} as any)
|
|
827
|
+
let created: Record<string, unknown> = {}
|
|
828
|
+
const fakeRequire = (name: string): any => {
|
|
829
|
+
if (name.endsWith('/hash-password')) {
|
|
830
|
+
return (password: string) => 'hashed:' + password
|
|
831
|
+
}
|
|
832
|
+
if (name.endsWith('/auth-options')) {
|
|
833
|
+
return {
|
|
834
|
+
userExistsByEmail: async () => false,
|
|
835
|
+
createUser: async (userData: Record<string, unknown>) => {
|
|
836
|
+
created = userData
|
|
837
|
+
return { id: 'u1', ...userData }
|
|
838
|
+
},
|
|
839
|
+
sanitizeUser: (user: unknown) => user,
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
return { resolveRequestLocale: () => 'en' }
|
|
843
|
+
}
|
|
844
|
+
const moduleObj: { exports: any } = { exports: {} }
|
|
845
|
+
new Function('require', 'module', 'exports', 'console', code)(
|
|
846
|
+
fakeRequire,
|
|
847
|
+
moduleObj,
|
|
848
|
+
moduleObj.exports,
|
|
849
|
+
{ error: () => undefined, warn: () => undefined, log: () => undefined }
|
|
850
|
+
)
|
|
851
|
+
const res = {
|
|
852
|
+
status() {
|
|
853
|
+
return this
|
|
854
|
+
},
|
|
855
|
+
json() {
|
|
856
|
+
return this
|
|
857
|
+
},
|
|
858
|
+
}
|
|
859
|
+
await moduleObj.exports({ method: 'POST', headers: {}, body }, res)
|
|
860
|
+
return created
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
it('signs a new account up as a plain user whatever role-bearing property the body names', async () => {
|
|
864
|
+
const created = await signupWith(
|
|
865
|
+
{
|
|
866
|
+
email: 'm@x.io',
|
|
867
|
+
password: 'secret1',
|
|
868
|
+
role: 'admin',
|
|
869
|
+
roles: ['admin'],
|
|
870
|
+
Role: 'admin',
|
|
871
|
+
company: 'ACME',
|
|
872
|
+
},
|
|
873
|
+
[{ key: 'roles' }, { key: 'Role' }, { key: 'company' }]
|
|
874
|
+
)
|
|
875
|
+
expect(created.role).toBe('user')
|
|
876
|
+
expect(created.roles).toBeUndefined()
|
|
877
|
+
expect(created.Role).toBeUndefined()
|
|
878
|
+
// An ordinary custom property still lands.
|
|
879
|
+
expect(created.company).toBe('ACME')
|
|
880
|
+
})
|
|
881
|
+
|
|
882
|
+
it('keeps the server signup node from copying a role-bearing config key onto the new row', () => {
|
|
883
|
+
const source = accountSignup.generateServerHandler!()
|
|
884
|
+
expect(source).toContain('const roleBearingKey = /^(roles?|role_?name)$/i;')
|
|
885
|
+
expect(source).toContain(
|
|
886
|
+
'if (!reservedKeys[configKeys[i]] && !roleBearingKey.test(configKeys[i])) {'
|
|
887
|
+
)
|
|
888
|
+
})
|
|
889
|
+
|
|
890
|
+
it('guards the users table on an auth config that declares no tables', () => {
|
|
891
|
+
expect(resolveAuthUsersTableName({ enabled: true })).toBe('users')
|
|
892
|
+
expect(resolveAuthUsersTableName({ enabled: true, tables: {} })).toBe('users')
|
|
893
|
+
expect(resolveAuthUsersTableName({ enabled: false })).toBeUndefined()
|
|
894
|
+
expect(resolveAuthUsersTableName(undefined)).toBeUndefined()
|
|
895
|
+
})
|
|
896
|
+
})
|
|
897
|
+
|
|
898
|
+
describe('server-side data nodes present the internal secret', () => {
|
|
899
|
+
it('is sent by every node that reaches the route from a server segment', () => {
|
|
900
|
+
for (const node of [
|
|
901
|
+
dataSelect,
|
|
902
|
+
dataCount,
|
|
903
|
+
dataCreateItem,
|
|
904
|
+
dataRawQuery,
|
|
905
|
+
dataUpdateItem,
|
|
906
|
+
dataDeleteItem,
|
|
907
|
+
]) {
|
|
908
|
+
const source = node.generateHandler()
|
|
909
|
+
expect(source).toContain("'x-internal-data-secret': (__env && __env.NEXTAUTH_SECRET) || ''")
|
|
910
|
+
// Read off the process, which only exists server-side.
|
|
911
|
+
expect(source).toContain('const __env = globalThis.process && globalThis.process.env')
|
|
912
|
+
}
|
|
913
|
+
})
|
|
914
|
+
})
|
|
915
|
+
|
|
916
|
+
describe('data API — the users table never serves its credentials to a browser', () => {
|
|
917
|
+
const userRow = {
|
|
918
|
+
id: 'u1',
|
|
919
|
+
name: 'Ada',
|
|
920
|
+
email: 'ada@shop.test',
|
|
921
|
+
role: 'user',
|
|
922
|
+
password: '$2b$10$hash',
|
|
923
|
+
access_token: 'ya29.token',
|
|
924
|
+
refresh_token: '1//refresh',
|
|
925
|
+
id_token: 'eyJ.id',
|
|
926
|
+
session_state: 's',
|
|
927
|
+
token_type: 'Bearer',
|
|
928
|
+
scope: 'email',
|
|
929
|
+
expires_at: 1790000000,
|
|
930
|
+
}
|
|
931
|
+
const run = bootRoute(SECRET, { authUsersTableName: 'users', rows: [userRow] })
|
|
932
|
+
|
|
933
|
+
it('refuses a browser the users table outright — the list is every customer', async () => {
|
|
934
|
+
for (const body of [
|
|
935
|
+
{ tableName: 'users' },
|
|
936
|
+
{ tableName: 'users', selectedColumns: ['id', 'password'] },
|
|
937
|
+
]) {
|
|
938
|
+
const result = await run('select', body)
|
|
939
|
+
expect(result.status).toBe(403)
|
|
940
|
+
expect(result.queries).toEqual([])
|
|
941
|
+
}
|
|
942
|
+
})
|
|
943
|
+
|
|
944
|
+
it('serves the whole row to a server segment, which checks a password or refreshes a token', async () => {
|
|
945
|
+
const result = await run('select', { tableName: 'users' }, internal)
|
|
946
|
+
expect(result.body.rows).toEqual([userRow])
|
|
947
|
+
})
|
|
948
|
+
})
|