feat(core): enable recaptcha in forms#2896
Conversation
🦋 Changeset detectedLatest commit: 901b3c8 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
matthewvolk
left a comment
There was a problem hiding this comment.
High level, I think this is pretty good - the main "architectural" feedback I have is that it looks like you introduce two ways to get the recaptcha key but are only using one of them... wondering if that's redundant. I could be misunderstanding intent here, so I definitely encourage a second reviewer to weigh in!
Outside of this, my only other concern is the library is a bit old... not sure if it's being maintained, especially looking at some of the recent issues: dozoisch/react-google-recaptcha#301
Bundle Size ReportComparing against baseline from
Per-Route First Load JS
|
| const token = recaptchaRef.current.getValue(); | ||
|
|
||
| if (!token || typeof token !== 'string') { | ||
| setRecaptchaError(t('recaptchaRequired')); |
There was a problem hiding this comment.
Is there no way to validate for recaptcha within the form action? And return the errors accordingly? 🤔
There was a problem hiding this comment.
Good call. Refactored to move that logic to the server and create utility functions to parse and validate the token.
There was a problem hiding this comment.
Even with the refactor this is still present. I think we can remove all client facing logic for showing the errors and validating.
There was a problem hiding this comment.
Got it. Removed all client logic in lieu of leveraging logic on the server
jorgemoya
left a comment
There was a problem hiding this comment.
Thanks for looking into validating and erroring from the actions, but I still see some leftover logic from the previous implementation. Should be easy to clean up, I believe.
Another question, should we include reCaptcha in other pages? Login, reset password? I forget if once we enable reCaptcha on a storefront, forms automatically require a token to succeed?
Another detail missing is how to make sure the forms still succeed in our e2e tests when reCaptcha is enabled. Our old approach was to use the X-Vercel-Set-Bypass-Cookie: true, however another approach is to make sure the E2E test store has Google's test key 🤔? This would work now since our E2E test store is separate from our demo sites.
core/lib/recaptcha.ts
Outdated
| failedLoginLockoutDurationSeconds | ||
| isEnabledOnCheckout |
There was a problem hiding this comment.
I don't think these two are being used. Can we use it for something here? I would remove if not needed.
There was a problem hiding this comment.
Great catch. Removed.
core/lib/recaptcha.ts
Outdated
| return { siteKey, token }; | ||
| } | ||
|
|
||
| export function validateRecaptchaToken( |
There was a problem hiding this comment.
Maybe change to assertRecaptchaTokenPresent since it's not really validating anything (this happens server side)?
| setRecaptchaError(null); | ||
|
|
||
| let payload: FormData = formData; | ||
|
|
||
| if (recaptchaSiteKey && recaptchaRef.current) { | ||
| const token = recaptchaRef.current.getValue(); | ||
|
|
||
| if (!token || typeof token !== 'string') { | ||
| setRecaptchaError(t('recaptchaRequired')); | ||
|
|
||
| return; | ||
| } | ||
|
|
||
| payload = new FormData(event.currentTarget); | ||
| payload.set(RECAPTCHA_TOKEN_FORM_KEY, token); | ||
| recaptchaRef.current.reset(); | ||
| } |
There was a problem hiding this comment.
The cool thing about validating on the server is that we no longer need this.
There was a problem hiding this comment.
Removed. Great call.
| {submitLabel} | ||
| </SubmitButton> | ||
| </div> | ||
| {recaptchaError ? <FormStatus type="error">{recaptchaError}</FormStatus> : null} |
| export function DynamicForm<F extends Field>(props: DynamicFormProps<F>) { | ||
| return <DynamicFormInner {...props} />; | ||
| } |
There was a problem hiding this comment.
Why did we add this Inner component? 🤔
| const token = recaptchaRef.current.getValue(); | ||
|
|
||
| if (!token || typeof token !== 'string') { | ||
| setRecaptchaError(t('recaptchaRequired')); |
There was a problem hiding this comment.
Even with the refactor this is still present. I think we can remove all client facing logic for showing the errors and validating.
Made-with: Cursor
…ut from getReCaptchaSettings Made-with: Cursor
I'm not sure what we want to do for forms on other pages. I started with mirroring the Stencil functionality which is specific to these forms and not all of them. |
Jira CATALYST-1806
What/Why?
Match functionality of Stencil with regards to reCAPTCHA. Catalyst should respect the reCAPTCHA settings from the Control Panel and apply reCAPTCHA to forms appropriately based on those settings.
Forms that should support reCAPTCHA if enabled include:
Testing
with reCAPTCHA enabled in the Control Panel
Register & contact
Product review
without reCAPTCHA enabled in the Control Panel
When reCAPTCHA is disabled in the control panel, all three forms submit without a reCAPTCHA widget or “complete reCAPTCHA” errors.
Migration