From fd38a9d7eb3383b84eb455bd754db2be7f01786b Mon Sep 17 00:00:00 2001 From: Caio Cabral Date: Thu, 31 Oct 2024 09:30:43 -0400 Subject: [PATCH] fix: backend validation password --- Client/src/Pages/Auth/Register/Register.jsx | 72 ++++++------ .../Pages/Auth/Register/StepThree/index.jsx | 10 +- Client/src/Pages/Auth/SetNewPassword.jsx | 108 +++++++++--------- .../Pages/Auth/hooks/useValidatePassword.jsx | 51 +++++---- Server/validation/joi.js | 2 +- 5 files changed, 127 insertions(+), 116 deletions(-) diff --git a/Client/src/Pages/Auth/Register/Register.jsx b/Client/src/Pages/Auth/Register/Register.jsx index b85cf89c0..628365bdf 100644 --- a/Client/src/Pages/Auth/Register/Register.jsx +++ b/Client/src/Pages/Auth/Register/Register.jsx @@ -213,44 +213,42 @@ const Register = ({ isSuperAdmin }) => { const handleStepThree = async (e) => { e.preventDefault(); const { password, confirm } = e.target.elements; - console.log(password.value); - console.log(confirm.value); - // let registerForm = { - // ...form, + let registerForm = { + ...form, + password: password.value, + confirm: confirm.value, + role: isSuperAdmin ? ["superadmin"] : form.role, + inviteToken: token ? token : "", // Add the token to the request for verification + }; + let error = validateForm(registerForm, { + context: { password: registerForm.password }, + }); + if (error) { + handleError(error); + return; + } - // role: isSuperAdmin ? ["superadmin"] : form.role, - // inviteToken: token ? token : "", // Add the token to the request for verification - // }; - // let error = validateForm(registerForm, { - // context: { password: form.password }, - // }); - // if (error) { - // handleError(error); - // return; - // } - - // delete registerForm.confirm; - // const action = await dispatch(register(registerForm)); - // if (action.payload.success) { - // const authToken = action.payload.data; - // localStorage.setItem("token", authToken); - // navigate("/"); - // createToast({ - // body: "Welcome! Your account was created successfully.", - // }); - // } else { - // if (action.payload) { - // // dispatch errors - // createToast({ - // body: action.payload.msg, - // }); - // } else { - // // unknown errors - // createToast({ - // body: "Unknown error.", - // }); - // } - // } + delete registerForm.confirm; + const action = await dispatch(register(registerForm)); + if (action.payload.success) { + const authToken = action.payload.data; + localStorage.setItem("token", authToken); + /* navigate("/"); */ + navigate("/monitors"); + createToast({ + body: "Welcome! Your account was created successfully.", + }); + } else { + if (action.payload) { + createToast({ + body: action.payload.msg, + }); + } else { + createToast({ + body: "Unknown error.", + }); + } + } }; const handleChange = (event) => { diff --git a/Client/src/Pages/Auth/Register/StepThree/index.jsx b/Client/src/Pages/Auth/Register/StepThree/index.jsx index cde86c2db..0f1e540f7 100644 --- a/Client/src/Pages/Auth/Register/StepThree/index.jsx +++ b/Client/src/Pages/Auth/Register/StepThree/index.jsx @@ -136,6 +136,10 @@ function StepThree({ onSubmit, onBack }) { "& svg.MuiSvgIcon-root": { mr: theme.spacing(3), }, + ":focus-visible": { + outline: `2px solid ${theme.palette.primary.dark}`, + outlineOffset: "4px", + }, }} props={{ tabIndex: -1 }} > @@ -147,7 +151,11 @@ function StepThree({ onSubmit, onBack }) { variant="contained" color="primary" /* onClick={onSubmit} */ - disabled={errors.email && true} + disabled={ + form.password.length === 0 || + form.confirm.length === 0 || + Object.keys(errors).length !== 0 + } sx={{ width: "30%" }} > Continue diff --git a/Client/src/Pages/Auth/SetNewPassword.jsx b/Client/src/Pages/Auth/SetNewPassword.jsx index 1cb858e11..5f0acef15 100644 --- a/Client/src/Pages/Auth/SetNewPassword.jsx +++ b/Client/src/Pages/Auth/SetNewPassword.jsx @@ -15,6 +15,7 @@ import LockIcon from "../../assets/icons/lock.svg?react"; import Logo from "../../assets/icons/bwu-icon.svg?react"; import Background from "../../assets/Images/background-grid.svg?react"; import "./index.css"; +import { useValidatePassword } from "./hooks/useValidatePassword"; const SetNewPassword = () => { const navigate = useNavigate(); @@ -24,11 +25,12 @@ const SetNewPassword = () => { const passwordId = useId(); const confirmPasswordId = useId(); - const [errors, setErrors] = useState({}); - const [form, setForm] = useState({ - password: "", - confirm: "", - }); + const { form, errors, handleChange, feedbacks } = useValidatePassword(); + // const [errors, setErrors] = useState({}); + // const [form, setForm] = useState({ + // password: "", + // confirm: "", + // }); const { isLoading } = useSelector((state) => state.auth); const { token } = useParams(); @@ -63,59 +65,59 @@ const SetNewPassword = () => { } }; - const handleChange = (event) => { - const { value, name } = event.target; - setForm((prev) => ({ ...prev, [name]: value })); + // const handleChange = (event) => { + // const { value, name } = event.target; + // setForm((prev) => ({ ...prev, [name]: value })); - const validateValue = { [name]: value }; - const validateOptions = { abortEarly: false, context: { password: form.password } }; - if (name === "password" && form.confirm.length > 0) { - validateValue.confirm = form.confirm; - validateOptions.context = { password: value }; - } else if (name === "confirm") { - validateValue.password = form.password; - } + // const validateValue = { [name]: value }; + // const validateOptions = { abortEarly: false, context: { password: form.password } }; + // if (name === "password" && form.confirm.length > 0) { + // validateValue.confirm = form.confirm; + // validateOptions.context = { password: value }; + // } else if (name === "confirm") { + // validateValue.password = form.password; + // } - const { error } = credentials.validate(validateValue, validateOptions); - const errors = error?.details.map((error) => ({ - path: error.path[0], - message: error.message, - })); - const errorsByPath = - errors && - errors.reduce((acc, { path, message }) => { - if (!acc[path]) { - acc[path] = []; - } - acc[path].push(message); - return acc; - }, {}); - setErrors(() => (errorsByPath ? { ...errorsByPath } : {})); - }; + // const { error } = credentials.validate(validateValue, validateOptions); + // const errors = error?.details.map((error) => ({ + // path: error.path[0], + // message: error.message, + // })); + // const errorsByPath = + // errors && + // errors.reduce((acc, { path, message }) => { + // if (!acc[path]) { + // acc[path] = []; + // } + // acc[path].push(message); + // return acc; + // }, {}); + // setErrors(() => (errorsByPath ? { ...errorsByPath } : {})); + // }; - const getFeedbackStatus = (field, criteria) => { - const fieldErrors = errors[field]; - const isFieldEmpty = form[field].length === 0; - const hasError = fieldErrors?.includes(criteria) || fieldErrors?.includes("empty"); - const isCorrect = !isFieldEmpty && !hasError; + // const getFeedbackStatus = (field, criteria) => { + // const fieldErrors = errors[field]; + // const isFieldEmpty = form[field].length === 0; + // const hasError = fieldErrors?.includes(criteria) || fieldErrors?.includes("empty"); + // const isCorrect = !isFieldEmpty && !hasError; - if (isCorrect) { - return "success"; - } else if (hasError) { - return "error"; - } else { - return "info"; - } - }; + // if (isCorrect) { + // return "success"; + // } else if (hasError) { + // return "error"; + // } else { + // return "info"; + // } + // }; - const feedbacks = { - length: getFeedbackStatus("password", "length"), - special: getFeedbackStatus("password", "special"), - number: getFeedbackStatus("password", "number"), - uppercase: getFeedbackStatus("password", "uppercase"), - lowercase: getFeedbackStatus("password", "lowercase"), - confirm: getFeedbackStatus("confirm", "different"), - }; + // const feedbacks = { + // length: getFeedbackStatus("password", "length"), + // special: getFeedbackStatus("password", "special"), + // number: getFeedbackStatus("password", "number"), + // uppercase: getFeedbackStatus("password", "uppercase"), + // lowercase: getFeedbackStatus("password", "lowercase"), + // confirm: getFeedbackStatus("confirm", "different"), + // }; return ( { + const fieldErrors = errors[field]; + const isFieldEmpty = form[field].length === 0; + const hasError = fieldErrors?.includes(criteria) || fieldErrors?.includes("empty"); + const isCorrect = !isFieldEmpty && !hasError; + + if (isCorrect) { + return "success"; + } else if (hasError) { + return "error"; + } else { + return "info"; + } +}; + function useValidatePassword() { const [errors, setErrors] = useState({}); const [form, setForm] = useState({ @@ -38,29 +53,17 @@ function useValidatePassword() { setErrors(() => (errorsByPath ? { ...errorsByPath } : {})); }; - const getFeedbackStatus = (field, criteria) => { - const fieldErrors = errors[field]; - const isFieldEmpty = form[field].length === 0; - const hasError = fieldErrors?.includes(criteria) || fieldErrors?.includes("empty"); - const isCorrect = !isFieldEmpty && !hasError; - - if (isCorrect) { - return "success"; - } else if (hasError) { - return "error"; - } else { - return "info"; - } - }; - - const feedbacks = { - length: getFeedbackStatus("password", "length"), - special: getFeedbackStatus("password", "special"), - number: getFeedbackStatus("password", "number"), - uppercase: getFeedbackStatus("password", "uppercase"), - lowercase: getFeedbackStatus("password", "lowercase"), - confirm: getFeedbackStatus("confirm", "different"), - }; + const feedbacks = useMemo( + () => ({ + length: getFeedbackStatus(form, errors, "password", "length"), + special: getFeedbackStatus(form, errors, "password", "special"), + number: getFeedbackStatus(form, errors, "password", "number"), + uppercase: getFeedbackStatus(form, errors, "password", "uppercase"), + lowercase: getFeedbackStatus(form, errors, "password", "lowercase"), + confirm: getFeedbackStatus(form, errors, "confirm", "different"), + }), + [form, errors] + ); return { handleChange, feedbacks, form, errors }; } diff --git a/Server/validation/joi.js b/Server/validation/joi.js index d1ba107bc..299acebb6 100644 --- a/Server/validation/joi.js +++ b/Server/validation/joi.js @@ -118,7 +118,7 @@ const newPasswordValidation = joi.object({ .min(8) .required() .pattern( - /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*()])[A-Za-z0-9!@#$%^&*()]+$/ + /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!?@#$%^&*()\-_=+[\]{};:'",.<>~`|\\/])[A-Za-z0-9!?@#$%^&*()\-_=+[\]{};:'",.<>~`|\\/]+$/ ), confirm: joi.string(), });