fix(vue-starter-template): validate checkout and restore guest orders - #2724
Patryk Tomczyk (patzick) wants to merge 9 commits into
Conversation
Show client-side errors on submit even when fields were never focused, keep guest checkout as the default with a way back from create-account, and require zip/state before the register request is sent.
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
Point registration storefrontUrl at https://frontends-starter-template.vercel.app instead of the deprecated demo-store domain.
|
Browser walkthrough of the starter checkout fixes (untouched-field validation, create-account / continue-as-guest toggle, filled guest form). Empty form after Next — required errors on untouched fields, including email: Untouched checkout fields show required errors Create customer account shows the password field and Continue as guest: Create account shows password and Continue as guest Continue as guest hides the password field again: Continue as guest hides the password field Recording: |
Add the browser verification images and compressed recording so they can be shown inline on the pull request.
There was a problem hiding this comment.
Stale comment
Security review
No medium, high, or critical vulnerabilities in this change.
Reviewed the starter checkout validation/guest-toggle work and the
devStorefrontUrlupdate:
- Registration still goes to Store API
POST /account/register. Guest mode sendsguest: trueand an empty password; account mode sends the password only when the shopper opts in. Client$validate()is UX — the backend remains the auth boundary.- Place order without a session only runs register and does not call
createOrder.- Validation and API error text are Vue-interpolated (
FormInputField,LayoutNotification); nov-htmlon these paths.devStorefrontUrlis a compile-time Shopware demo origin, not attacker-controlled; Shopware allowlists sales-channel domains forstorefrontUrl.- No dependency or lockfile changes, and no secret logging.
No prior security-review threads to re-report. Slack summary was skipped (posting tool not configured).
Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
Screenshots and the recording are attached on the pull request as GitHub user-attachments so they render inline, instead of living in the repository or as external links.
|
Walkthrough screenshots and recording, attached on this issue so they render inline: Empty form after Next — required errors on untouched fields, including email: Create customer account shows the password field and Continue as guest: Continue as guest hides the password field again: Recording: checkout_untouched_validation_and_guest_toggle.mp4 |
There was a problem hiding this comment.
Stale comment
Security review
No medium, high, or critical vulnerabilities in this change.
Re-reviewed
d58f2ffafter the latest synchronize. The only delta since the previous assessment is removing walkthrough PNG/MP4 files from the repo (they now live on GitHub issue attachments). Checkout code is unchanged.
- Registration still goes to Store API
POST /account/register. Guest mode sendsguest: trueand an empty password; account mode sends the password only when the shopper opts in. Client$validate()is UX — the backend remains the auth boundary.- Place order without a session only runs register and does not call
createOrder.- Validation and API error text are Vue-interpolated (
FormInputField,LayoutNotification); nov-htmlon these paths.devStorefrontUrlis a compile-time Shopware demo origin, not attacker-controlled; Shopware allowlists sales-channel domains forstorefrontUrl.- No dependency or lockfile changes, and no secret logging.
No prior security-review finding threads to re-report. Slack summary was skipped (posting tool not configured).
Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
There was a problem hiding this comment.
Stale comment
Security review
No medium, high, or critical vulnerabilities in this change.
Re-reviewed head
d58f2ffd(walkthrough media removed from.github/pr-assets/; checkout/register code unchanged from the prior assessment):
- Registration still goes to Store API
POST /account/register. Guest mode sendsguest: trueand an empty password; account mode sends the password only when the shopper opts in. Client$validate()is UX — the backend remains the auth boundary.- Place order without a session only runs register and does not call
createOrder.- Validation and API error text are Vue-interpolated (
FormInputField,LayoutNotification); nov-htmlon these paths.devStorefrontUrlis a compile-time Shopware demo origin, not attacker-controlled; Shopware allowlists sales-channel domains forstorefrontUrl.- No dependency or lockfile changes, and no secret logging.
No prior security-review finding threads to re-report. Slack summary was skipped (posting tool not configured).
Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
Remove the extra Next button from one-page checkout. Confirm and place order now creates the guest session (Store API register with guest: true) and then calls checkout/order, instead of stopping after register.
There was a problem hiding this comment.
Stale comment
Security review
No medium, high, or critical vulnerabilities in this change.
Re-reviewed head
2353ba8bafter the latest synchronize. The new delta combines guest/account register and place order into one Confirm action (saveCustomerDetails()→ Store APIPOST /account/register, thencreateOrder()→POST /checkout/order). That restores intended guest checkout; it is not an authz bypass.createOrderstill needs a Store API customer context, which register establishes, andcanPlaceOrderplus the backend still require shipping/payment methods.
- Registration still goes to Store API
POST /account/register. Guest mode sendsguest: trueand an empty password; account mode sends the password only when the shopper opts in. Client$validate()is UX — the backend remains the auth boundary.- Validation and API error text are Vue-interpolated (
FormInputField,LayoutNotification); nov-htmlon these paths.devStorefrontUrlis a compile-time Shopware demo origin, not attacker-controlled; Shopware allowlists sales-channel domains forstorefrontUrl.- No dependency or lockfile changes, and no secret logging.
No prior security-review finding threads to re-report. Slack summary was skipped (posting tool not configured).
Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
Guest checkout still has to POST /account/register with guest: true before POST /checkout/order. Register was 400ing because devStorefrontUrl was not a Sales Channel domain, so place order never reached createOrder. getStorefrontUrl() now falls back to a domain from the current session context when the preferred URL is not listed.
There was a problem hiding this comment.
Stale comment
Security review
No medium, high, or critical vulnerabilities in this change.
Re-reviewed head
a522cbbaafter the latest synchronize. The new delta isgetStorefrontUrl()falling back to a sales-channel domain from session context whendevStorefrontUrl/window.location.originis not listed under Sales Channel → Domains.
- That value is only sent as
storefrontUrlon Store APIPOST /account/registerand newsletter subscribe. The backend still allowlists it against configured domains, so a client-side fallback cannot point confirmation/recovery links at an arbitrary host.- Combined guest register then place order remains the intended Store API flow (
guest: truethenPOST /checkout/order).createOrderstill needs a customer context;canPlaceOrderplus the backend still require shipping/payment.- Client
$validate()is UX. Guest mode sendsguest: trueand an empty password; account mode sends the password only when the shopper opts in.- Validation and API error text are Vue-interpolated (
FormInputField,Notification); nov-htmlon these paths.devStorefrontUrlis a compile-time Shopware demo origin. No dependency or lockfile changes, and no secret logging.No prior security-review finding threads to re-report. Slack summary was skipped (posting tool not configured).
Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
Validate both customer form groups and refresh shipping/payment without failing the whole place-order flow if one promise rejects.
There was a problem hiding this comment.
Stale comment
Security review
No medium, high, or critical vulnerabilities in this change.
Re-reviewed head
21772b02after the latest synchronize. The new delta switches checkout validation and post-register shipping/payment refresh toPromise.allSettled.
$validate()is fail-closed: a rejected validation is treated as invalid and blocks place-order.- Shipping/payment refresh failures no longer abort
saveCustomerDetails. Place-order is still gated bycanPlaceOrder(selected shipping and payment) and Store APIPOST /checkout/order.- Combined guest register then place order remains the intended Store API flow (
guest: truethenPOST /checkout/order).createOrderstill needs a customer context.getStorefrontUrl()is only sent asstorefrontUrlon register/newsletter subscribe. The backend still allowlists it against configured sales-channel domains.- Client
$validate()is UX. Guest mode sendsguest: trueand an empty password; account mode sends the password only when the shopper opts in.- Validation and API error text are Vue-interpolated (
FormInputField,Notification); nov-htmlon these paths.devStorefrontUrlis a compile-time Shopware demo origin. No dependency or lockfile changes, and no secret logging.No prior security-review finding threads to re-report. Slack summary was skipped (posting tool not configured).
Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
There was a problem hiding this comment.
Stale comment
Security review
No medium, high, or critical vulnerabilities in this change.
Re-reviewed head
ab3aaca9after ready_for_review. The only new commit since the last review is a merge ofmain(Cart recipe docs already on the base). Checkout validation, guest register + place order, andgetStorefrontUrl()fallback are unchanged.
- Combined guest register then place order is the intended Store API flow (
guest: truethenPOST /checkout/order).createOrderstill needs a customer context;canPlaceOrderplus the backend still require shipping/payment.$validate()viaPromise.allSettledis fail-closed. Shipping/payment refresh failures do not skip those gates.getStorefrontUrl()is only sent asstorefrontUrlon register/newsletter subscribe. The backend still allowlists it against configured sales-channel domains.- Client
$validate()is UX. Guest mode sendsguest: trueand an empty password; account mode sends the password only when the shopper opts in.- Validation and API error text are Vue-interpolated (
FormInputField,Notification); nov-htmlon these paths.devStorefrontUrlis a compile-time Shopware demo origin. No dependency or lockfile changes, and no secret logging.No prior security-review finding threads to re-report. Slack summary was skipped (posting tool not configured).
Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
There was a problem hiding this comment.
Security review
No medium, high, or critical vulnerabilities in this change.
Re-reviewed head ab3aaca9 after the latest synchronize. The only delta since 21772b02 is a merge of main (Cart recipe docs from #2722). Checkout, register, and getStorefrontUrl are unchanged.
$validate()remains fail-closed: a rejected validation is treated as invalid and blocks place-order.- Shipping/payment refresh failures still do not abort
saveCustomerDetails. Place-order is gated bycanPlaceOrder(selected shipping and payment) and Store APIPOST /checkout/order. - Combined guest register then place order remains the intended Store API flow (
guest: truethenPOST /checkout/order).createOrderstill needs a customer context. getStorefrontUrl()is only sent asstorefrontUrlon register/newsletter subscribe. Session domains come fromGET /context; the backend still allowlists the value against configured sales-channel domains.- Client
$validate()is UX. Guest mode sendsguest: trueand an empty password; account mode sends the password only when the shopper opts in. - Validation and API error text are Vue-interpolated (
FormInputField,Notification); nov-htmlon these paths. devStorefrontUrlis a compile-time Shopware demo origin. No dependency or lockfile changes, and no secret logging.
No prior security-review finding threads to re-report. Slack summary was skipped (posting tool not configured).
Sent by Cursor Automation: Review pull requests for exploitable security issues and flag only validated findings before merge
| }, | ||
| acceptedDataProtection: true, | ||
| }); | ||
| await Promise.allSettled([getShippingMethods(), getPaymentMethods()]); |
There was a problem hiding this comment.
You have to add forceReload. Without this option data are not refreshed
| let customerReady = isUserSession.value; | ||
| try { | ||
| if (!customerReady) { | ||
| await saveCustomerDetails(); |
There was a problem hiding this comment.
If the place order fails, this function will block address editing,
useUser -> register








Description
Checkout in
vue-starter-templatesent the register/order request even when required fields like email were never touched, guest checkout could not complete from the UI, and clicking Create customer account had no way back to guest mode.This change:
guest: true, empty password) and adds a Continue as guest control after the password field appearsPOST /account/registerwithguest: true, which does not create an account) and then places the order (POST /checkout/order)storefrontUrlfrom the current sales channel domains when the configureddevStorefrontUrlis not listed, so guest register can succeed against the public demo API and checkout can reachPOST /checkout/orderdevStorefrontUrlathttps://frontends-starter-template.vercel.appas the preferred storefront URLRelates to the guest/account toggle issues around #2683 and the checkout flow from #2700.
Type of change
Bug fix (non-breaking change that fixes an issue)
ToDo's
Screenshots (if applicable)
Empty form, Confirm and place order (no field focused): client-side required errors, including email.
Create customer account reveals password and a way back:
Continue as guest restores guest mode:
Walkthrough recording:
checkout_untouched_validation_and_guest_toggle.mp4
Additional context
Verified with the Store API:
POST /checkout/orderwithout a customer returnsFRAMEWORK__ROUTING_CUSTOMER_NOT_LOGGED_IN. Guest checkout must callPOST /account/registerwithguest: truefirst, thenPOST /checkout/order.The public demo sales channel currently lists only
https://demo-frontends.shopware.store/figma. Registering with the starter Vercel host asstorefrontUrlis rejected (VIOLATION::NO_SUCH_CHOICE_ERROR), which is why place-order previously never reached/checkout/order.getStorefrontUrl()now falls back to a domain from the session context in that case.