Skip to content

Commit e2dbfb2

Browse files
author
Abdellatif El Mizeb
committed
feat(recaptcha): add recaptcha to forgot password and register forms
1 parent e93a937 commit e2dbfb2

File tree

6 files changed

+50
-7
lines changed

6 files changed

+50
-7
lines changed

packages/api-client/src/api/requestPasswordResetEmail/index.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { FetchResult } from '@apollo/client/core';
22
import { CustomQuery, Logger } from '@vue-storefront/core';
3+
import { GraphQLError } from 'graphql';
4+
import recaptchaValidator from '../../helpers/recaptcha/recaptchaValidator';
35
import requestPasswordResetEmailMutation from './requestPasswordResetEmail';
46
import {
57
RequestPasswordResetEmailMutation,
@@ -12,10 +14,28 @@ export default async (
1214
input: RequestPasswordResetEmailMutationVariables,
1315
customQuery: CustomQuery = { requestPasswordResetEmail: 'requestPasswordResetEmail' },
1416
): Promise<FetchResult<RequestPasswordResetEmailMutation>> => {
17+
const {
18+
recaptchaToken, ...variables
19+
} = input;
20+
21+
if (context.config.recaptcha.secretkey) {
22+
/**
23+
* recaptcha token verification
24+
*/
25+
const response = await recaptchaValidator(context, recaptchaToken);
26+
27+
if (!response.success) {
28+
return {
29+
errors: [new GraphQLError('Invalid token')],
30+
data: null,
31+
};
32+
}
33+
}
34+
1535
const { requestPasswordResetEmail } = context.extendQuery(customQuery, {
1636
requestPasswordResetEmail: {
1737
query: requestPasswordResetEmailMutation,
18-
variables: { ...input },
38+
variables: { ...variables },
1939
},
2040
});
2141

packages/api-client/src/types/GraphQL.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7316,6 +7316,7 @@ export type RemoveProductsFromWishlistMutation = { removeProductsFromWishlist?:
73167316

73177317
export type RequestPasswordResetEmailMutationVariables = Exact<{
73187318
email: Scalars['String'];
7319+
recaptchaToken?: Scalars['String'];
73197320
}>;
73207321

73217322

packages/composables/src/composables/useForgotPassword/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const factoryParams: UseForgotPasswordFactoryParams<any> = {
99
resetPassword: async (context: Context, params) => {
1010
Logger.debug('[Magento]: Reset user password', { params });
1111

12-
const { data } = await context.$magento.api.requestPasswordResetEmail({ email: params.email });
12+
const { data } = await context.$magento.api.requestPasswordResetEmail({ email: params.email, recaptchaToken: params.recaptchaToken });
1313

1414
Logger.debug('[Result]:', { data });
1515

packages/composables/src/factories/useForgotPasswordFactory.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ interface SetNewPasswordParams {
1919

2020
interface ResetPasswordParams {
2121
email: string;
22+
recaptchaToken?: string;
2223
}
2324

2425
export interface UseForgotPasswordFactoryParams<RESULT> extends FactoryParams {

packages/composables/src/types/composables.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ export interface UseForgotPassword<RESULT> {
203203

204204
setNew(params: ComposableFunctionArgs<{ tokenValue: string, newPassword: string, email: string }>): Promise<void>;
205205

206-
request(params: ComposableFunctionArgs<{ email: string }>): Promise<void>;
206+
request(params: ComposableFunctionArgs<{ email: string, recaptchaToken?: string }>): Promise<void>;
207207
}
208208

209209
export interface UseRelatedProducts<PRODUCTS, RELATED_PRODUCT_SEARCH_PARAMS, API extends PlatformApi = any> extends Composable<API> {

packages/theme/components/LoginModal.vue

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@
126126
class="form__element"
127127
/>
128128
</ValidationProvider>
129+
<recaptcha v-if="isRecaptcha" />
129130
<div v-if="forgotPasswordError.request">
130131
{{ $t('It was not possible to request a new password, please check the entered email address.') }}
131132
</div>
@@ -252,6 +253,7 @@
252253
class="form__element"
253254
/>
254255
</ValidationProvider>
256+
<recaptcha v-if="isRecaptcha" />
255257
<div v-if="error.register">
256258
{{ error.register }}
257259
</div>
@@ -377,9 +379,6 @@ export default defineComponent({
377379
if (isLoginModalOpen) {
378380
form.value = {};
379381
resetErrorValues();
380-
if (isRecaptcha.value) {
381-
$recaptcha.init();
382-
}
383382
}
384383
});
385384
@@ -402,8 +401,14 @@ export default defineComponent({
402401
403402
const handleForm = (fn) => async () => {
404403
resetErrorValues();
404+
405+
if (isRecaptcha.value) {
406+
$recaptcha.init();
407+
}
408+
405409
if (isRecaptcha.value) {
406410
const recaptchaToken = await $recaptcha.getResponse();
411+
form.value.recaptchaInstance = $recaptcha;
407412
408413
await fn({
409414
user: {
@@ -441,12 +446,28 @@ export default defineComponent({
441446
442447
const handleForgotten = async () => {
443448
userEmail.value = form.value.username;
444-
await request({ email: userEmail.value });
449+
450+
if (isRecaptcha.value) {
451+
$recaptcha.init();
452+
}
453+
454+
if (isRecaptcha.value) {
455+
const recaptchaToken = await $recaptcha.getResponse();
456+
457+
await request({ email: userEmail.value, recaptchaToken });
458+
} else {
459+
await request({ email: userEmail.value });
460+
}
445461
446462
if (!forgotPasswordError.value.request) {
447463
isThankYouAfterForgotten.value = true;
448464
isForgotten.value = false;
449465
}
466+
467+
if (isRecaptcha.value) {
468+
// reset recaptcha
469+
$recaptcha.reset();
470+
}
450471
};
451472
452473
return {

0 commit comments

Comments
 (0)