recaptcha

master
alex 2024-02-04 15:38:28 +01:00
parent 84467df09f
commit df39e164f6
7 changed files with 77 additions and 4 deletions

2
.gitignore vendored
View File

@ -21,3 +21,5 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.env

1
env.example Normal file
View File

@ -0,0 +1 @@
REACT_APP_RECAPTCHA_SITE_KEY=

38
package-lock.json generated
View File

@ -22,6 +22,7 @@
"react": "^18.2.0",
"react-countup": "^6.5.0",
"react-dom": "^18.2.0",
"react-google-recaptcha": "^3.1.0",
"react-i18next": "^13.0.1",
"react-microsoft-clarity": "^1.2.0",
"react-qr-scanner": "^1.0.0-alpha.11",
@ -11180,6 +11181,19 @@
"he": "bin/he"
}
},
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/hoist-non-react-statics/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/hoopy": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
@ -18496,6 +18510,18 @@
"node": ">=14"
}
},
"node_modules/react-async-script": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/react-async-script/-/react-async-script-1.2.0.tgz",
"integrity": "sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q==",
"dependencies": {
"hoist-non-react-statics": "^3.3.0",
"prop-types": "^15.5.0"
},
"peerDependencies": {
"react": ">=16.4.1"
}
},
"node_modules/react-countup": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/react-countup/-/react-countup-6.5.0.tgz",
@ -18664,6 +18690,18 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
},
"node_modules/react-google-recaptcha": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-3.1.0.tgz",
"integrity": "sha512-cYW2/DWas8nEKZGD7SCu9BSuVz8iOcOLHChHyi7upUuVhkpkhYG/6N3KDiTQ3XAiZ2UAZkfvYKMfAHOzBOcGEg==",
"dependencies": {
"prop-types": "^15.5.0",
"react-async-script": "^1.2.0"
},
"peerDependencies": {
"react": ">=16.4.1"
}
},
"node_modules/react-hook-form": {
"version": "7.48.2",
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.48.2.tgz",

View File

@ -17,6 +17,7 @@
"react": "^18.2.0",
"react-countup": "^6.5.0",
"react-dom": "^18.2.0",
"react-google-recaptcha": "^3.1.0",
"react-i18next": "^13.0.1",
"react-microsoft-clarity": "^1.2.0",
"react-qr-scanner": "^1.0.0-alpha.11",

View File

@ -62,7 +62,8 @@
"calendarMaxFutureBookingDaysRequired": "Maximaler Buchungszeitraum ist erforderlich",
"calendarMinEarliestBookingTimeRequired": "Minimaler frühester Buchungszeitpunkt ist erforderlich",
"companyNameRequired": "Firmenname ist erforderlich",
"companyNameMinLength": "Firmenname muss mindestens {{minLength}} Zeichen lang sein"
"companyNameMinLength": "Firmenname muss mindestens {{minLength}} Zeichen lang sein",
"recaptchaRequired": "Bitte bestätigen Sie, dass Sie kein Roboter sind"
},
"request": {
"inputsInvalid": {

View File

@ -62,7 +62,8 @@
"calendarMaxFutureBookingDaysRequired": "Please enter the max. future booking days",
"calendarMinEarliestBookingTimeRequired": "Please enter the min. earliest booking time",
"companyNameRequired": "Please enter the company name",
"companyNameMinLength": "Company name must be at least {{minLength}} characters"
"companyNameMinLength": "Company name must be at least {{minLength}} characters",
"recaptchaRequired": "Please confirm that you are not a robot"
},
"request": {
"inputsInvalid": {

View File

@ -17,7 +17,7 @@ import {
showInputsInvalidNotification,
showUnkownErrorNotification,
} from "../../utils";
import { useEffect, useState } from "react";
import { useEffect, useRef, useState } from "react";
import {
MyAccountNameFormInput,
MyCompanyNameFormInput,
@ -27,6 +27,7 @@ import {
import { useTranslation } from "react-i18next";
import MyAppLogo from "../../Components/MyAppLogo";
import { useNavigate } from "react-router-dom";
import ReCAPTCHA from "react-google-recaptcha";
export const AuthenticationMethod = {
LOGIN: 1,
@ -95,6 +96,7 @@ function Login({ notificationApi }) {
const [isRequesting, setIsRequesting] = useState(false);
const [step, setStep] = useState(LoginStep.ACCOUNT_NAME);
const recaptchaValueRef = useRef(null);
const [form] = Form.useForm();
@ -212,6 +214,21 @@ function Login({ notificationApi }) {
<MyPasswordFormInput />
<RememberMeCheckbox />
<Form.Item
name="recaptcha"
rules={[
{
required: true,
message: t("common.inputRules.recaptchaRequired"),
},
]}
>
<ReCAPTCHA
sitekey={process.env.REACT_APP_RECAPTCHA_SITE_KEY}
onChange={(value) => (recaptchaValueRef.current = value)}
/>
</Form.Item>
</div>
<Button
@ -226,7 +243,12 @@ function Login({ notificationApi }) {
if (step === LoginStep.ACCOUNT_NAME) {
validateFields = ["accountName"];
} else {
validateFields = ["accountName", "password", "rememberMe"];
validateFields = [
"accountName",
"password",
"rememberMe",
"recaptcha",
];
}
form
@ -244,6 +266,7 @@ function Login({ notificationApi }) {
) {
body.password = EncodeStringToBase64(values.password);
body.rememberMe = values.rememberMe;
body.recaptcha = recaptchaValueRef.current;
}
myFetch({
@ -392,6 +415,12 @@ function SignUp({ notificationApi }) {
<RememberMeCheckbox />
<ReCAPTCHA
style={{ paddingBottom: 16 }}
sitekey={process.env.REACT_APP_RECAPTCHA_SITE_KEY}
onChange={(value) => console.log("Captcha value:", value)}
/>
<Button
type="primary"
size="large"