Merge branch 'master' of ssh://gitlab.chiefsoft.net:10222/WrenchBoard/Users-Wrench

This commit is contained in:
2023-08-06 10:14:17 +08:00
7 changed files with 278 additions and 178 deletions
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" id="error"><path fill="#ff1d25" d="M29.75,25.73,18.68,3.59a3,3,0,0,0-4-1.33,3.05,3.05,0,0,0-1.33,1.33L2.25,25.73a3,3,0,0,0,2.68,4.34H27.07a3,3,0,0,0,3-3A2.88,2.88,0,0,0,29.75,25.73ZM16,25.38a.94.94,0,1,1,.94-.94A.94.94,0,0,1,16,25.38Zm.94-4.69a.94.94,0,1,1-1.88,0V11.31a.94.94,0,1,1,1.88,0Z"></path></svg>

After

Width:  |  Height:  |  Size: 365 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" id="success"><path fill="#80af52" d="M256 26c127.03 0 230 102.97 230 230S383.03 486 256 486 26 383.03 26 256 128.97 26 256 26z"></path><path fill="#fff" d="M215.999 386a9.998 9.998 0 0 1-7.525-3.415l-70-80c-3.637-4.156-3.215-10.474.941-14.11s10.475-3.217 14.111.94l60.961 69.67 142.938-238.23c2.842-4.736 8.983-6.273 13.72-3.43 4.736 2.841 6.271 8.984 3.431 13.72l-150 250a9.998 9.998 0 0 1-8.577 4.855z"></path></svg>

After

Width:  |  Height:  |  Size: 483 B

@@ -0,0 +1,37 @@
import React from 'react'
import { useNavigate } from 'react-router-dom'
import localImgLoad from '../../lib/localImgLoad'
const ForgetPwdResponse = ({title, message, type}) => {
const navigate = useNavigate()
return (
<>
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
<h1 className={`${type ? 'text-black' : 'text-red-500'}text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]`}>
{title}
</h1>
</div>
<div className="title-area w-[100px] h-[100px] mx-auto flex flex-col justify-center items-center relative text-center mb-7">
<img className='w-full h-full' src={`${type ? localImgLoad('images/icons/success.svg') : localImgLoad('images/icons/error.svg')}`} alt='alert-banner' />
</div>
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
<p className={`${type ? 'text-sky-blue' : 'text-red-500'} font-semibold dark:text-white mb-3 leading-[27.3px] text-[18px]`}>
{message}
</p>
</div>
<div className="signin-area mb-3.5">
<div className="flex justify-center items-center gap-2">
<button
type="button"
onClick={() => navigate("/login")}
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
>
<span>Home</span>
</button>
</div>
</div>
</>
)
}
export default ForgetPwdResponse
+108 -96
View File
@@ -4,6 +4,8 @@ import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import usersService from "../../../services/UsersService"; import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom"; import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout"; import AuthLayout from "../AuthLayout";
import EmailValidator from "../../../lib/EmailValidator";
import ForgetPwdResponse from "../ForgetPwdResponse";
export default function ForgotPassword() { export default function ForgotPassword() {
const [checked, setValue] = useState(false); const [checked, setValue] = useState(false);
@@ -11,7 +13,7 @@ export default function ForgotPassword() {
// email // email
const [email, setMail] = useState(""); const [email, setMail] = useState("");
const [msgError, setMsgError] = useState(""); const [msgError, setMsgError] = useState("");
const [msgSuccess, setMsgSuccess] = useState(false); const [msgSuccess, setMsgSuccess] = useState(null);
const navigate = useNavigate(); const navigate = useNavigate();
const userApi = new usersService(); const userApi = new usersService();
@@ -27,12 +29,26 @@ export default function ForgotPassword() {
const resetHandler = async () => { const resetHandler = async () => {
if (email == "") { if (email == "") {
setMsgError("An email is required"); setMsgError("An email is required");
} else if (!checked) { return setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}
if (!checked) {
setMsgError("Check if you are human"); setMsgError("Check if you are human");
return setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}
if(!EmailValidator(email)){ // CHECKS IF EMAIL IS VALID
setMsgError("Invalid Email");
return setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
} }
if (email !== "" && checked) { if (email !== "" && checked) {
const reqData = { email }; const reqData = { email, action:11013 };
setResetLoading(true); setResetLoading(true);
try { try {
const res = await userApi.StartResetPassword(reqData); const res = await userApi.StartResetPassword(reqData);
@@ -41,8 +57,11 @@ export default function ForgotPassword() {
setMail(""); setMail("");
setValue(false); setValue(false);
setResetLoading(false); setResetLoading(false);
}else{
setMsgSuccess(false);
} }
} catch (error) { } catch (error) {
setMsgSuccess(false);
setResetLoading(false); setResetLoading(false);
setMail(""); setMail("");
setMsgError("An error occurred"); setMsgError("An error occurred");
@@ -53,9 +72,6 @@ export default function ForgotPassword() {
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT); }, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
} }
} }
setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}; };
return ( return (
@@ -73,106 +89,102 @@ export default function ForgotPassword() {
</div> </div>
<div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5"> <div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5">
<div className="flex flex-col justify-center w-full h-full px-5"> <div className="flex flex-col justify-center w-full h-full px-5">
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7"> {msgSuccess == null ?
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]"> <>
Forget Password <div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
</h1> <h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]"> Forget Password
Enter your email to reset your password. </h1>
</span> <span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
</div> Enter your email to reset your password.
<div className="input-area"> </span>
<div className="input-item mb-10">
<InputCom
fieldClass="px-6"
placeholder="Your Username/Email"
label="Email"
name="email"
type="email"
value={email}
inputHandler={handleEmail}
iconName="message"
/>
</div> </div>
{/* hCaptha clone for the time being */} <div className="input-area">
<div className="mb-10"> <div className="input-item mb-10">
<div className="w-[303px] h-[78px] mx-auto overflow-hidden"> <InputCom
<div className="w-[300px] h-[74px] bg-white bottom-[1px] rounded border-gray-100 overflow-hidden cursor-pointer"> fieldClass="px-6"
{/* Checkbox */} placeholder="Your Username/Email"
<div className="h-full relative inline-block"> label="Email"
<div className="relative table top-0 h-full"> name="email"
<div className="table-cell align-middle"> type="email"
<div className="relative w-[30px] h-[30px] mx-[15px]"> value={email}
<input inputHandler={handleEmail}
type="checkbox" iconName="message"
name="human-checkbox" />
id="human-checkbox" </div>
className="w-[28px] h-[28px] border-[1px] rounded border-gray-400 checked:bg-white" {/* hCaptha clone for the time being */}
checked={checked} <div className="mb-10">
onChange={humanChecker} <div className="w-[303px] h-[78px] mx-auto overflow-hidden">
/> <div className="w-[300px] h-[74px] bg-white bottom-[1px] rounded border-gray-100 overflow-hidden cursor-pointer">
{/* Checkbox */}
<div className="h-full relative inline-block">
<div className="relative table top-0 h-full">
<div className="table-cell align-middle">
<div className="relative w-[30px] h-[30px] mx-[15px]">
<input
type="checkbox"
name="human-checkbox"
id="human-checkbox"
className="w-[28px] h-[28px] border-[1px] rounded border-gray-400 checked:bg-white"
checked={checked}
onChange={humanChecker}
/>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> <div className="h-full relative inline-block w-[170px]">
<div className="h-full relative inline-block w-[170px]"> <label className="relative table top-0 h-full">
<label className="relative table top-0 h-full"> <label className="table-cell align-middle">
<label className="table-cell align-middle"> <label
<label className="text-800 text-sm"
className="text-800 text-sm" htmlFor="human-checkbox"
htmlFor="human-checkbox" >
> I am human
I am human </label>
</label> </label>
</label> </label>
</label> </div>
<div className="h-full relative inline-block w-16"></div>
</div> </div>
<div className="h-full relative inline-block w-16"></div> </div>
</div>
{msgError && (
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]">
{msgError}
</div>
)}
<div className="signin-area mb-3.5">
<div className="flex justify-center items-center gap-2">
<button
type="button"
onClick={resetHandler}
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
>
{resetLoading ? (
<div className="signup btn-loader"></div>
) : (
<span>Send Code</span>
)}
</button>
<button
type="button"
onClick={() => navigate("/login")}
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.8125rem] `}
>
Cancel
</button>
</div> </div>
</div> </div>
</div> </div>
{msgError && ( </>
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]"> :
{msgError} <ForgetPwdResponse
</div> title={'Forget Password'}
)} message={msgSuccess? `Check your email for the link to continue password reset. Note the reset link will expire short time` : 'We are unable to continue with your request. Please try another username or contact us for help'}
{msgSuccess && ( type={msgSuccess}
<div className="relative p-4 text-[#44228c] bg-[#e3d7fb] border-[#d5c4f9] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]"> />
If we find your email, you will receive a link to reset your }
password. Please use or{" "}
<Link
to="/contact"
className="text-[#4687ba] hover:text-[#009ef7]"
>
contact form
</Link>{" "}
if you did not get our message after few minutes.
</div>
)}
<div className="signin-area mb-3.5">
<div className="flex justify-center items-center gap-2">
<button
type="button"
onClick={resetHandler}
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
>
{resetLoading ? (
<div className="signup btn-loader"></div>
) : (
<span>Send Code</span>
)}
</button>
<button
type="button"
onClick={() => navigate("/login")}
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.8125rem] `}
>
Cancel
</button>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
+113 -82
View File
@@ -1,16 +1,20 @@
import { useState } from "react"; import { useEffect, useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom"; import { Link, useLocation, useNavigate } from "react-router-dom";
import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png"; import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import usersService from "../../../services/UsersService"; import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom"; import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout"; import AuthLayout from "../AuthLayout";
import ForgetPwdResponse from "../ForgetPwdResponse";
import PasswordValidator from "../../../lib/PasswordValidator";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
const VerifyPassword = () => { const VerifyPassword = () => {
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState("");
const [requestStatus, setRequestStatus] = useState({loading: true, status:false, data: []})
const [msgError, setMsgError] = useState(""); const [msgError, setMsgError] = useState("");
const [linkLoader, setLinkLoader] = useState(false); const [linkLoader, setLinkLoader] = useState(false);
const [linkSuccess, setLinkSuccess] = useState(true); const [linkSuccess, setLinkSuccess] = useState(null);
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
@@ -23,11 +27,6 @@ const VerifyPassword = () => {
setShowPassword(!showPassword); setShowPassword(!showPassword);
}; };
// little checker for the validity of the token
if (token?.length != 64) {
setLinkSuccess(false);
}
// Password // Password
const handlePassword = (e) => { const handlePassword = (e) => {
let { name, value } = e?.target; let { name, value } = e?.target;
@@ -36,46 +35,60 @@ const VerifyPassword = () => {
}; };
const completeReset = async () => { const completeReset = async () => {
if(!password || !confirmPassword){ // CHECKS IF PASSWORD IS EMPTY
setMsgError("Please fill in fields");
return setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}
if(password != confirmPassword){ // CHECKS IF PASSWORD EQUALS CONFIRM PASSWORD
setMsgError("Passwords does not match");
return setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}
if(password.length < 6){ // CHECKS IF PASSWORD LENGTH IS UPTO 6 CHARACTERS
setMsgError("Password must be upto six characters");
return setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}
if(!PasswordValidator(password)){ // CHECKS IF PASSWORD IS VALID
setMsgError("Password must contain alphanumeric, uppercase and special character: eg: Password1@");
return setTimeout(() => {
setMsgError(null);
}, process.env.REACT_APP_RESET_START_ERROR_TIMEOUT);
}
try { try {
if (password !== "" && confirmPassword !== "") {
if (password === confirmPassword) {
setLinkLoader(true); setLinkLoader(true);
var reqData = { var reqData = {
sessionid: "DUMMY-CANNOT_BE_EMPTY", sessionid: "DUMMY-CANNOT_BE_EMPTY",
reset_link: token, reset_link: token,
newpass: password, newpass: password,
m_uid: requestStatus.data?.m_uid || '',
reset_uid: requestStatus.data?.reset_uid || '',
step: 300, step: 300,
action: 730, action: 730,
}; };
const res = await userApi?.CompleteResetPassword(reqData); const res = await userApi?.CompleteResetPassword(reqData);
if (res.status === 200) { if (res.status == 200) {
const { data } = res; const { data } = res;
if (data?.internal_return >= 0) {
if (data?.status > 0 && data?.email) { // setTimeout(() => {
setTimeout(() => { // navigate("/login", { replace: true });
navigate("/login", { replace: true }); // setLinkLoader(false);
setLinkLoader(false); // }, 2000);
}, 2000); setLinkSuccess(true);
} else if (data && data?.status == "Invalid Request") {
setLinkLoader(false);
setLinkSuccess(false);
} else { } else {
setLinkLoader(false); setLinkLoader(false);
setMsgError("An error occurred"); setMsgError("An error occurred");
setLinkSuccess(false);
} }
} else { } else {
setLinkLoader(false); setLinkLoader(false);
setLinkSuccess(false); setLinkSuccess(false);
} }
} else {
setLinkLoader(false);
setMsgError("Passwords does not match");
}
} else {
setMsgError("Please fill in fields");
}
} catch (error) { } catch (error) {
setLinkLoader(false); setLinkLoader(false);
setLinkSuccess(false); setLinkSuccess(false);
@@ -87,6 +100,31 @@ const VerifyPassword = () => {
} }
}; };
const verifyResetPwd = () => { // FUNCTION TO VERIFY RESET PASSWORD LINK
setRequestStatus({loading: true, status:false, data: []})
var reqData = {
sessionid: "DUMMY-CANNOT_BE_EMPTY",
reset_link: token,
step: 200,
action: 730,
};
userApi.CompleteResetPassword(reqData).then(res => {
if(res.status != 200 || res.data.internal_return < 0){
return setRequestStatus({loading: false, status:false, data: []})
}
setRequestStatus({loading: false, status:true, data: res.data})
}).catch(error => {
setRequestStatus({loading: false, status:false, data: []})
})
}
useEffect(()=>{
// little checker for the validity of the token
if (token==null || token?.length != 64) {
return setRequestStatus({loading: false, status:false, data: []});
}
verifyResetPwd()
},[])
return ( return (
<> <>
<AuthLayout slogan="Welcome to WrenchBoard"> <AuthLayout slogan="Welcome to WrenchBoard">
@@ -101,39 +139,54 @@ const VerifyPassword = () => {
</Link> </Link>
</div> </div>
<div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5"> <div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5">
{requestStatus.loading ?
<LoadingSpinner color='sky-blue' size='16' height='h-300px' />
:
!requestStatus.loading && requestStatus.status ?
<div className="w-full"> <div className="w-full">
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7"> {linkSuccess == null ?
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]"> <>
{linkSuccess ? "Password Reset" : "Invalid verification link"} <div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
</h1> <h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
{linkSuccess && ( Password Reset
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]"> </h1>
Enter a new password to reset <span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
</span> Enter a new password to reset
)} </span>
{linkSuccess && ( <span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]"> We'll send an email to confirm reset
We'll send an email to confirm reset </span>
</span> </div>
)} <SuccessfulComponent
</div> password={password}
{/* If the verification was a success */} confirmPassword={confirmPassword}
{linkSuccess ? ( handlePassword={handlePassword}
<SuccessfulComponent onSubmit={completeReset}
password={password} msgErr={msgError}
confirmPassword={confirmPassword} loader={linkLoader}
handlePassword={handlePassword} showPassword={showPassword}
onSubmit={completeReset} onClick={togglePasswordVisibility}
msgErr={msgError} navigateHandler={() => navigate("/login")}
loader={linkLoader} />
showPassword={showPassword} </>
onClick={togglePasswordVisibility} :
navigateHandler={() => navigate("/login")} <ForgetPwdResponse
/> title={linkSuccess? 'Password Reset Complete' : 'Password Reset Error'}
) : ( message={linkSuccess? 'Password Reset Complete. You can login now with your new credentials' : 'Password Reset Error. Please get in touch with support for further support'
<ErrorComponent onClick={() => navigate("/login")} /> }
)} type={linkSuccess}
/>
}
</div> </div>
:
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
<ForgetPwdResponse
title={'Forget Password'}
message={'We are unable to continue to reset process. This error is usually due to expired links. Please start all over or contact us'}
type={requestStatus.status}
/>
</div>
}
</div> </div>
</div> </div>
</AuthLayout> </AuthLayout>
@@ -159,7 +212,7 @@ const SuccessfulComponent = ({
<div className="mb-5"> <div className="mb-5">
<InputCom <InputCom
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl" fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
value={password?.replace(/./g, "●")} value={password}
inputHandler={handlePassword} inputHandler={handlePassword}
placeholder="● ● ● ● ● ●" placeholder="● ● ● ● ● ●"
label="Password" label="Password"
@@ -172,7 +225,7 @@ const SuccessfulComponent = ({
<div className="mb-5"> <div className="mb-5">
<InputCom <InputCom
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl" fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
value={confirmPassword?.replace(/./g, "●")} value={confirmPassword}
inputHandler={handlePassword} inputHandler={handlePassword}
placeholder="● ● ● ● ● ●" placeholder="● ● ● ● ● ●"
label="Confirm Password" label="Confirm Password"
@@ -209,25 +262,3 @@ const SuccessfulComponent = ({
</div> </div>
</div> </div>
); );
const ErrorComponent = ({ onClick }) => (
<div className="input-area">
<div className="my-5">
<p className="text-[14px] leading-[19px] text-center text-[#181c32]">
This error occurs because you have already used this link or the link
has broken/expired. Start with the reset process again. If it doesn't
work, try to create the account from the start.
</p>
</div>
<div className="signin-area flex justify-center mb-3.5">
<button
onClick={onClick}
type="button"
className={`rounded-[0.475rem] mb-6 text-[15px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.81rem]`}
>
<span>Return Home</span>
</button>
</div>
</div>
);
+9
View File
@@ -0,0 +1,9 @@
export default function EmailValidator(email) {
let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/;
if (regEx.test(email) == false) {
return false
}else{
return true
}
}
+9
View File
@@ -0,0 +1,9 @@
export default function PasswordValidator(password) {
const regEx = /^[a-zA-Z0-9!@#$%^&*()_+{}\[\]:;<>,.?~\\/\-='"`|]+$/;
if (/[!@#$%^&*()_+{}\[\]:;<>,.?~\\/\-='"`|]/.test(password) == false || /[0-9]/.test(password)==false || /[A-Z]/.test(password)==false || /[a-z]/.test(password)==false) {
return false
}else{
return true
}
}