From 130f514b0db6ec32d0bbc201b1f9ffa509ada3dd Mon Sep 17 00:00:00 2001 From: Gauravtb2253 Date: Fri, 11 Oct 2024 11:47:30 +0530 Subject: [PATCH] added input validations --- client/package-lock.json | 50 ++++++++- client/package.json | 4 +- client/src/component/Login.jsx | 154 +++++++++++++++++++-------- client/src/component/Signup.jsx | 99 +++++++++++------ client/src/component/css/Login.css | 5 +- client/src/validations/validation.js | 25 +++++ server/package-lock.json | 5 + server/package.json | 1 + 8 files changed, 260 insertions(+), 83 deletions(-) create mode 100644 client/src/validations/validation.js diff --git a/client/package-lock.json b/client/package-lock.json index babcc53..1b51a49 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -27,6 +27,7 @@ "lucide-react": "^0.447.0", "match-sorter": "^6.3.4", "mdb-react-ui-kit": "^7.2.0", + "open-source": "file:", "otp-input-react": "^0.3.0", "prop-types": "^15.8.1", "react": "^18.2.0", @@ -42,7 +43,8 @@ "react-top-loading-bar": "^2.3.1", "socket.io": "^4.7.5", "socket.io-client": "^4.7.5", - "sort-by": "^1.2.0" + "sort-by": "^1.2.0", + "yup": "^1.4.0" }, "devDependencies": { "@types/react": "^18.2.55", @@ -5621,6 +5623,10 @@ "wrappy": "1" } }, + "node_modules/open-source": { + "resolved": "", + "link": true + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -6020,6 +6026,12 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", + "license": "MIT" + }, "node_modules/protobufjs": { "version": "7.2.6", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", @@ -7071,6 +7083,12 @@ "node": ">=0.8" } }, + "node_modules/tiny-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", + "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==", + "license": "MIT" + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -7093,6 +7111,12 @@ "node": ">=8.0" } }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", + "license": "MIT" + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -7682,6 +7706,30 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/yup": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.4.0.tgz", + "integrity": "sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==", + "license": "MIT", + "dependencies": { + "property-expr": "^2.0.5", + "tiny-case": "^1.0.3", + "toposort": "^2.0.2", + "type-fest": "^2.19.0" + } + }, + "node_modules/yup/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/client/package.json b/client/package.json index 22e9a7e..5526cf6 100644 --- a/client/package.json +++ b/client/package.json @@ -29,6 +29,7 @@ "lucide-react": "^0.447.0", "match-sorter": "^6.3.4", "mdb-react-ui-kit": "^7.2.0", + "open-source": "file:", "otp-input-react": "^0.3.0", "prop-types": "^15.8.1", "react": "^18.2.0", @@ -44,7 +45,8 @@ "react-top-loading-bar": "^2.3.1", "socket.io": "^4.7.5", "socket.io-client": "^4.7.5", - "sort-by": "^1.2.0" + "sort-by": "^1.2.0", + "yup": "^1.4.0" }, "devDependencies": { "@types/react": "^18.2.55", diff --git a/client/src/component/Login.jsx b/client/src/component/Login.jsx index 7efca1f..569a7c1 100644 --- a/client/src/component/Login.jsx +++ b/client/src/component/Login.jsx @@ -1,40 +1,61 @@ -import PropTypes from 'prop-types'; -import { useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { Link } from 'react-router-dom'; +import PropTypes from "prop-types"; +import { useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { Link } from "react-router-dom"; // import './css/Auth.css'; -import './css/Login.css' +import "./css/Login.css"; +import { loginValidation } from "../validations/validation"; const host = "http://localhost:5000"; const Login = (props) => { - const [credentials, setCredentials] = useState({ email: "", password: "" }); + // const [credentials, setCredentials] = useState({ email: "", password: "" }); + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [errors, setErrors] = useState({}); let navigate = useNavigate(); const handleSubmit = async (e) => { - // To not Reload after click submit + // To not Reload after click submit e.preventDefault(); + + try { + await loginValidation.validate( + { email, password }, + { abortEarly: false } + ); + setErrors({}); + } catch (error) { + const newErrors = {}; + error.inner.forEach((err) => { + newErrors[err.path] = err.message; + // newErrors[err.path] = err.errors[0]; + }); + + setErrors(newErrors); + return; + } + const response = await fetch(`${host}/api/auth/login`, { method: "POST", headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ email: credentials.email, password: credentials.password }), + body: JSON.stringify({ email: email, password: password }), }); const json = await response.json(); console.log(json); if (json.success) { // Save the auth token and redirect - localStorage.setItem('token', json.authtoken); - props.showAlert("Logged in Successfully", "success") + localStorage.setItem("token", json.authtoken); + props.showAlert("Logged in Successfully", "success"); navigate("/"); + } else { + props.showAlert("Invalid Credentials", "danger"); } - else { - props.showAlert("Invalid Credentials", "danger") - } - } + }; const onChange = (e) => { - setCredentials({ ...credentials, [e.target.name]: e.target.value }) - } + setCredentials({ ...credentials, [e.target.name]: e.target.value }); + }; // return ( //
@@ -57,7 +78,7 @@ const Login = (props) => { //
// //
- //
Don't have an account? + //
Don't have an account? // Signup //
// {/* Or Sign in with */} @@ -85,41 +106,82 @@ const Login = (props) => { //
// ) - return ( -
-
- -

Login

- -
- + return ( +
+ +

Login

+ +
+ setEmail(e.target.value)} + id="email" + name="email" + aria-describedby="emailHelp" + autoComplete="on" + /> + {errors.email &&
{errors.email}
} -
-
- +
+
+ setPassword(e.target.value)} + name="password" + autoComplete="on" + /> + {errors.password && ( +
{errors.password}
+ )} -
- -

Dont have an account? Please Sign Up

- - Forgot Password ? - - -
-
-

WELCOME
BACK !

-

Please Sign In here
with your some
-- real info

-
-
- - ) +
+ +

+ Dont have an account?{" "} + + {" "} + Please Sign Up + +

- -} + Forgot Password ? + +
+
+

+ WELCOME +
+ BACK ! +

+

+ Please Sign In here +
+ with your some +
+ -- real info +

+
+
+ ); +}; // Props Vadilation Login.propTypes = { showAlert: PropTypes.func, }; -export default Login \ No newline at end of file +export default Login; diff --git a/client/src/component/Signup.jsx b/client/src/component/Signup.jsx index 0529304..6ea1a77 100644 --- a/client/src/component/Signup.jsx +++ b/client/src/component/Signup.jsx @@ -3,6 +3,7 @@ import PropTypes from "prop-types"; import { useState } from "react"; import { Link, useNavigate } from "react-router-dom"; import "./css/Login.css"; +import { registerValidation } from "../validations/validation"; // import { signInWithPopup, GoogleAuthProvider } from 'firebase/auth'; // import { auth } from '../component/Firebase/Setup'; @@ -51,25 +52,47 @@ const Signup = (props) => { } }; - const [credentials, setCredentials] = useState({ - name: "", - email: "", - password: "", - cpassword: "", - }); + // const [credentials, setCredentials] = useState({ + // name: "", + // email: "", + // password: "", + // cpassword: "", + // }); + const [name, setName] = useState(""); + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [cpassword, setCPassword] = useState(""); + const [errors, setErrors] = useState({}); const handleSubmit = async (e) => { e.preventDefault(); - const { name, email, password } = credentials; + try { + await registerValidation.validate( + { name, email, password, cpassword }, + { abortEarly: false } + ); + setErrors({}); + } catch (error) { + const newErrors = {}; + error.inner.forEach((err) => { + newErrors[err.path] = err.message; + // newErrors[err.path] = err.errors[0]; + }); + + setErrors(newErrors); + return; + } + + // const { name, email, password, cpassword } = credentials; // Perform signup with email and password await signUpWithGoogle(email, name, password); }; - const onChange = (e) => { - setCredentials({ ...credentials, [e.target.name]: e.target.value }); - }; + // const onChange = (e) => { + // setCredentials({ ...credentials, [e.target.name]: e.target.value }); + // }; // return ( //
@@ -236,7 +259,7 @@ const Signup = (props) => {

-
+

Sign Up

@@ -246,11 +269,12 @@ const Signup = (props) => { placeholder="Name" name="name" aria-describedby="emailHelp" - onChange={onChange} + onChange={(e) => setName(e.target.value)} id="name" autoComplete="on" - required + value={name} /> + {errors.name &&
{errors.name}
}
@@ -258,13 +282,14 @@ const Signup = (props) => { type="email" className="input" placeholder="Email" - onChange={onChange} + onChange={(e) => setEmail(e.target.value)} id="email" name="email" aria-describedby="emailHelp" autoComplete="on" - required + value={email} /> + {errors.email &&
{errors.email}
}
@@ -272,13 +297,16 @@ const Signup = (props) => { type={showPassword ? "text" : "password"} className="input" placeholder="Password" - onChange={onChange} + onChange={(e) => setPassword(e.target.value)} id="password" name="password" minLength={5} autoComplete="on" - required + value={password} /> + {errors.password && ( +
{errors.password}
+ )} + autoComplete="on" + value={cpassword} + /> + {errors.cpassword && ( +
{errors.cpassword}
+ )} +
-

diff --git a/client/src/component/css/Login.css b/client/src/component/css/Login.css index aa75a19..2fc7699 100644 --- a/client/src/component/css/Login.css +++ b/client/src/component/css/Login.css @@ -6,7 +6,7 @@ } body{ width: 100vw; - height: 100vh; + /* height: 100vh; */ background:white; display: grid; justify-content: center; @@ -20,7 +20,7 @@ body{ .wrapper{ position: relative; width: 100vw; - height: 100vh; + /* height: 100vh; */ display: grid; grid-template-columns: 1fr 1fr; } @@ -31,6 +31,7 @@ body{ align-items: center; } .title{ + margin-top: 50px; font-size: 4rem; color:#6366F1 ; font-weight:bolder; diff --git a/client/src/validations/validation.js b/client/src/validations/validation.js new file mode 100644 index 0000000..8c0b6a7 --- /dev/null +++ b/client/src/validations/validation.js @@ -0,0 +1,25 @@ +import * as yup from "yup"; + +export const loginValidation = yup.object().shape({ + email: yup + .string() + .email("Email format invalid") + .required("Email is required"), + password: yup.string().required("Password is required"), +}); + +export const registerValidation = yup.object().shape({ + name: yup.string().required("Name is required"), + email: yup + .string() + .email("Invalid email format") + .required("Email is required"), + password: yup + .string() + .min(6, "Password should be at least 6 characters") + .required("Password is required"), + cpassword: yup + .string() + .oneOf([yup.ref('password'), null], "Passwords must match") + .required("Confirm password is required"), + }); diff --git a/server/package-lock.json b/server/package-lock.json index 3cc514a..c8846c6 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -21,6 +21,7 @@ "mongoose": "^8.7.0", "multer": "^1.4.5-lts.1", "nodemailer": "^6.9.15", + "opensource-backend": "file:", "socket.io": "^4.7.5" }, "devDependencies": { @@ -2581,6 +2582,10 @@ "wrappy": "1" } }, + "node_modules/opensource-backend": { + "resolved": "", + "link": true + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", diff --git a/server/package.json b/server/package.json index 122064d..099a3f3 100644 --- a/server/package.json +++ b/server/package.json @@ -26,6 +26,7 @@ "mongoose": "^8.7.0", "multer": "^1.4.5-lts.1", "nodemailer": "^6.9.15", + "opensource-backend": "file:", "socket.io": "^4.7.5" }, "devDependencies": {