finished resend email verification, reset password, and forgot password logic

This commit is contained in:
subnub
2024-12-22 18:41:39 -05:00
parent 37be61f657
commit 2e6b7c05f7
21 changed files with 386 additions and 398 deletions
-2
View File
@@ -18,7 +18,6 @@ export default {
sendgridKey: process.env.SENDGRID_KEY,
sendgridEmail: process.env.SENDGRID_EMAIL,
remoteURL: process.env.REMOTE_URL,
disableEmailVerification: process.env.DISABLE_EMAIL_VERIFICATION,
secureCookies: process.env.SECURE_COOKIES,
tempDirectory: process.env.TEMP_DIRECTORY,
emailVerification: process.env.EMAIL_VERIFICATION,
@@ -49,7 +48,6 @@ module.exports = {
sendgridKey: process.env.SENDGRID_KEY,
sendgridEmail: process.env.SENDGRID_EMAIL,
remoteURL: process.env.REMOTE_URL,
disableEmailVerification: process.env.DISABLE_EMAIL_VERIFICATION,
secureCookies: process.env.SECURE_COOKIES,
tempDirectory: process.env.TEMP_DIRECTORY,
emailVerification: process.env.EMAIL_VERIFICATION,
+16 -21
View File
@@ -1,6 +1,5 @@
import { Router } from "express";
import auth from "../middleware/auth";
import authNoEmailVerification from "../middleware/authNoEmailVerificication";
import UserController from "../controllers/user-controller";
import authRefresh from "../middleware/authRefresh";
import authLogout from "../middleware/authLogout";
@@ -15,11 +14,7 @@ const router = Router();
// GET
router.get(
"/user-service/user",
authNoEmailVerification,
userController.getUser
);
router.get("/user-service/user", auth, userController.getUser);
router.get("/user-service/user-detailed", auth, userController.getUserDetailed);
@@ -37,21 +32,6 @@ router.post(
userController.createUser
);
router.post("/user-service/verify-email", userController.verifyEmail);
router.post(
"/user-service/resend-verify-email",
authNoEmailVerification,
userController.resendVerifyEmail
);
router.post(
"/user-service/send-password-reset",
userController.sendPasswordReset
);
router.post("/user-service/reset-password", userController.resetPassword);
router.post("/user-service/get-token", authRefresh, userController.getToken);
// PATCH
@@ -63,4 +43,19 @@ router.patch(
userController.changePassword
);
router.patch(
"/user-service/resend-verify-email",
auth,
userController.resendVerifyEmail
);
router.patch("/user-service/verify-email", userController.verifyEmail);
router.patch("/user-service/reset-password", userController.resetPassword);
router.patch(
"/user-service/send-password-reset",
userController.sendPasswordReset
);
export default router;
-2
View File
@@ -33,8 +33,6 @@ const auth = async (req: RequestType, res: Response, next: NextFunction) => {
const user = decoded.user;
if (!user) throw new Error("No User");
if (!user.emailVerified && !env.disableEmailVerification)
throw new Error("Email Not Verified");
req.user = user;
-2
View File
@@ -38,8 +38,6 @@ const authFullUser = async (
const user = decoded.user;
if (!user) throw new Error("No User");
if (!user.emailVerified && !env.disableEmailVerification)
throw new Error("Email Not Verified");
const fullUser = await User.findById(user._id);
@@ -1,62 +0,0 @@
import jwt from "jsonwebtoken";
import User, { UserInterface } from "../models/user-model";
import env from "../enviroment/env";
import { Request, Response, NextFunction } from "express";
import userUpdateCheck from "../utils/userUpdateCheck";
import mongoose from "mongoose";
interface RequestType extends Request {
user?: userAccessType;
token?: string;
encryptedToken?: string;
}
type jwtType = {
iv: Buffer;
user: userAccessType;
};
type userAccessType = {
_id: mongoose.Types.ObjectId;
emailVerified: boolean;
email: string;
botChecked: boolean;
};
const auth = async (req: RequestType, res: Response, next: NextFunction) => {
try {
const accessToken = req.cookies["access-token"];
if (!accessToken) throw new Error("No Access Token");
const decoded = jwt.verify(accessToken, env.passwordAccess!) as jwtType;
let user = decoded.user;
if (!user) throw new Error("No User");
if (!user.emailVerified && !env.disableEmailVerification) {
const currentUUID = req.headers.uuid as string;
user = await userUpdateCheck(res, user._id, currentUUID);
}
req.user = user;
next();
} catch (e) {
if (
e instanceof Error &&
e.message !== "No Access Token" &&
e.message !== "No User"
) {
console.log(
"\nAuthorization No Email Verification Middleware Error:",
e.message
);
}
return res.status(401).send("Error Authenticating");
}
};
export default auth;
+7 -1
View File
@@ -154,6 +154,12 @@ userSchema.methods.toJSON = function () {
delete userObject.privateKey;
delete userObject.publicKey;
if (env.emailVerification !== "true") {
delete userObject.emailVerified;
} else {
userObject.emailVerified = user.emailVerified || false;
}
return userObject;
};
@@ -203,7 +209,7 @@ userSchema.methods.generateAuthToken = async function (
const userObj = {
_id: user._id,
emailVerified: user.emailVerified || env.disableEmailVerification,
emailVerified: user.emailVerified,
email: user.email,
};
@@ -172,9 +172,14 @@ class UserService {
const verifiedEmail = user.emailVerified;
if (env.emailVerification !== "true") {
throw new ForbiddenError("Email Verification Disabled");
}
if (!verifiedEmail) {
const emailToken = await user.generateEmailVerifyToken();
await sendVerificationEmail(user, emailToken);
const result = await sendVerificationEmail(user, emailToken);
if (!result) throw new InternalServerError("Email Verification Error");
} else {
throw new ForbiddenError("Email Already Authorized");
}
+33
View File
@@ -0,0 +1,33 @@
import env from "../enviroment/env";
import nodemailer from "nodemailer";
const createEmailTransporter = () => {
const emailVerification = env.emailVerification === "true";
const emailAPIKey = env.emailAPIKey;
const emailDomain = env.emailDomain;
const emailHost = env.emailHost;
const emailPort = env.emailPort;
const emailAddress = env.emailAddress;
if (!emailVerification) {
throw new Error("Email Verification Not Enabled");
}
if (!emailAPIKey || !emailDomain || !emailHost || !emailAddress) {
throw new Error("Email Verification Not Setup Correctly");
}
const transporter = nodemailer.createTransport({
// @ts-ignore
host: emailHost,
port: emailPort || 587,
auth: {
user: emailDomain,
pass: emailAPIKey,
},
});
return transporter;
};
export default createEmailTransporter;
+47 -20
View File
@@ -1,29 +1,56 @@
import SMTPTransport from "nodemailer/lib/smtp-transport";
import env from "../enviroment/env";
import { UserInterface } from "../models/user-model";
// import sgMail from "@sendgrid/mail";
import nodemailer from "nodemailer";
import createEmailTransporter from "./createEmailTransporter";
type MailOptionsType = {
from: string;
to: string;
subject: string;
text: string;
};
const sendEmail = (
transporter: nodemailer.Transporter<SMTPTransport.SentMessageInfo>,
mailOptions: MailOptionsType
) => {
return new Promise((resolve, reject) => {
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
reject(error);
} else {
resolve(info);
}
});
});
};
const sendPasswordResetEmail = async (
user: UserInterface,
passwordResetToken: string
resetToken: string
) => {
// if (process.env.NODE_ENV === "test") {
// return;
// }
// const apiKey: any = env.sendgridKey;
// const sendgridEmail:any = env.sendgridEmail;
// const url = env.remoteURL + `/reset-password/${passwordResetToken}`
// // console.log("send grid api key", apiKey)
// // console.log("send grid email", sendgridEmail);
// // console.log("send grid reset url", url)
// sgMail.setApiKey(apiKey);
// const msg = {
// to: user.email,
// from: sendgridEmail,
// subject: "myDrive Password Reset",
// text: `Please navigate to the following link to reset your password: ${url}`
// }
// await sgMail.send(msg);
// //console.log("Send grid email sent reset");
try {
const transporter = createEmailTransporter();
const emailAddress = env.emailAddress!;
const url = env.remoteURL + `/reset-password/${resetToken}`;
const mailOptions = {
from: emailAddress,
to: user.email,
subject: "myDrive Password Reset",
text:
"Please navigate to the following link to reset your password: " + url,
};
await sendEmail(transporter, mailOptions);
return true;
} catch (e) {
console.log("Error sending password reset email", e);
return false;
}
};
export default sendPasswordResetEmail;
+3 -33
View File
@@ -2,6 +2,7 @@ import SMTPTransport from "nodemailer/lib/smtp-transport";
import env from "../enviroment/env";
import { UserInterface } from "../models/user-model";
import nodemailer from "nodemailer";
import createEmailTransporter from "./createEmailTransporter";
type MailOptionsType = {
from: string;
@@ -30,33 +31,11 @@ const sendVerificationEmail = async (
emailToken: string
) => {
try {
const emailVerification = env.emailVerification === "true";
const emailAPIKey = env.emailAPIKey;
const emailDomain = env.emailDomain;
const emailHost = env.emailHost;
const emailPort = env.emailPort;
const emailAddress = env.emailAddress;
if (!emailVerification) {
return false;
}
if (!emailAPIKey || !emailDomain || !emailHost || !emailAddress) {
console.log("Email Verification Not Setup Correctly");
return false;
}
const transporter = createEmailTransporter();
const emailAddress = env.emailAddress!;
const url = env.remoteURL + `/verify-email/${emailToken}`;
const transporter = nodemailer.createTransport({
host: emailHost,
port: 587 || emailPort,
auth: {
user: emailDomain,
pass: emailAPIKey,
},
});
const mailOptions = {
from: emailAddress,
to: user.email,
@@ -66,15 +45,6 @@ const sendVerificationEmail = async (
url,
};
console.log("Sending email verification", mailOptions, {
host: emailHost,
port: 587 || emailPort,
auth: {
user: emailDomain,
pass: emailAPIKey,
},
});
await sendEmail(transporter, mailOptions);
return true;
+30
View File
@@ -57,3 +57,33 @@ export const changePasswordAPI = async (
});
return response.data;
};
export const resendVerifyEmailAPI = async () => {
const response = await axios.patch("/user-service/resend-verify-email");
return response.data;
};
export const verifyEmailAPI = async (emailToken: string) => {
const response = await axios.patch("/user-service/verify-email", {
emailToken,
});
return response.data;
};
export const sendPasswordResetAPI = async (email: string) => {
const response = await axios.patch("/user-service/send-password-reset", {
email,
});
return response.data;
};
export const resetPasswordAPI = async (
password: string,
passwordToken: string
) => {
const response = await axios.patch("/user-service/reset-password", {
passwordToken,
password,
});
return response.data;
};
+42 -7
View File
@@ -1,5 +1,10 @@
import React, { useEffect, useMemo, useRef, useState } from "react";
import { createAccountAPI, getUserAPI, loginAPI } from "../../api/user";
import {
createAccountAPI,
getUserAPI,
loginAPI,
sendPasswordResetAPI,
} from "../../api/user";
import { useLocation, useNavigate } from "react-router-dom";
import { setUser } from "../../reducers/user";
import { useAppDispatch } from "../../hooks/store";
@@ -8,6 +13,7 @@ import AlertIcon from "../../icons/AlertIcon";
import Spinner from "../Spinner/Spinner";
import classNames from "classnames";
import { toast, ToastContainer } from "react-toastify";
import Swal from "sweetalert2";
const LoginPage = () => {
const [email, setEmail] = useState("");
@@ -20,6 +26,7 @@ const LoginPage = () => {
const dispatch = useAppDispatch();
const location = useLocation();
const navigate = useNavigate();
const lastSentPassowordReset = useRef(0);
const attemptLoginWithToken = async () => {
setAttemptingLogin(true);
@@ -75,6 +82,37 @@ const LoginPage = () => {
}
};
const resetPassword = async () => {
try {
const currentDate = Date.now();
if (currentDate - lastSentPassowordReset.current < 1000 * 60 * 1) {
await Swal.fire({
title: "Please wait 1 minute before resending",
icon: "warning",
confirmButtonColor: "#3085d6",
confirmButtonText: "Okay",
});
return;
}
lastSentPassowordReset.current = Date.now();
setLoadingLogin(true);
await toast.promise(sendPasswordResetAPI(email), {
pending: "Sending password reset...",
success: "Password Reset Sent",
error: "Error Sending Password Reset",
});
setLoadingLogin(false);
} catch (e) {
console.log("Create Account Error", e);
setLoadingLogin(false);
setError("Create Account Failed");
}
};
const isSubmitDisabled = useMemo(() => {
switch (mode) {
case "login":
@@ -94,6 +132,8 @@ const LoginPage = () => {
login();
} else if (mode === "create") {
createAccount();
} else if (mode === "reset") {
resetPassword();
}
};
@@ -144,12 +184,7 @@ const LoginPage = () => {
return (
<div>
<div className="bg-[#F4F4F6] w-screen h-screen flex justify-center items-center">
<div
className={classNames(
"rounded-md shadow-lg bg-white p-10 relative w-[90%] sm:w-[500px] animate-height",
{}
)}
>
<div className="rounded-md shadow-lg bg-white p-10 relative w-[90%] sm:w-[500px] animate-height">
<div className="absolute -top-10 left-0 right-0 flex justify-center items-center">
<div className="flex items-center justify-center rounded-full bg-white p-3 shadow-md">
{!loadingLogin && (
@@ -1,48 +0,0 @@
import React from "react";
const ResetPasswordPage = (props) => (
<div className="modal__wrap">
<div className="inner__modal">
<div className="password__modal">
<div className="head__password">
<h2>{"Reset Password"}</h2>
<div className="close__modal"></div>
</div>
<div className="password__content">
<form onSubmit={props.resetPassword}>
<div
style={props.state.passwordChanged ? { display: "none" } : {}}
className="group__password"
>
<input
value={props.state.password}
onChange={props.passwordOnChange}
placeholder="New Password"
type="password"
/>
</div>
<div
style={props.state.passwordChanged ? { display: "none" } : {}}
className="group__password"
>
<input
value={props.state.verifyPassword}
onChange={props.verifyPasswordOnChange}
placeholder="Verify New Password"
type="password"
/>
</div>
<div className="password__submit">
<input
type="submit"
value={props.state.passwordChanged ? "Go Back" : "Submit"}
/>
</div>
</form>
</div>
</div>
</div>
</div>
);
export default ResetPasswordPage;
@@ -0,0 +1,96 @@
import { useNavigate, useParams } from "react-router-dom";
import Spinner from "../Spinner/Spinner";
import { ToastContainer, toast } from "react-toastify";
import { useState } from "react";
import { resetPasswordAPI } from "../../api/user";
import AlertIcon from "../../icons/AlertIcon";
const ResetPasswordPage = () => {
const token = useParams().token!;
const [password, setPassword] = useState("");
const [verifyPassword, setVerifyPassword] = useState("");
const [loadingLogin, setLoadingLogin] = useState(false);
const [error, setError] = useState("");
const navigate = useNavigate();
const isSubmitDisabled = password !== verifyPassword;
const onSubmit = async (e: any) => {
try {
e.preventDefault();
setLoadingLogin(true);
await toast.promise(resetPasswordAPI(password, token), {
pending: "Resetting password...",
success: "Password Reset",
error: "Error Resetting Password",
});
setTimeout(() => {
navigate("/");
}, 1500);
} catch (e) {
console.log("Reset Password Error", e);
setLoadingLogin(false);
setError("Reset Password Failed");
}
};
return (
<div>
<div className="bg-[#F4F4F6] w-screen h-screen flex justify-center items-center">
<div className="rounded-md shadow-lg bg-white p-10 relative w-[90%] sm:w-[500px] animate-height">
<div className="absolute -top-10 left-0 right-0 flex justify-center items-center">
<div className="flex items-center justify-center rounded-full bg-white p-3 shadow-md">
{!loadingLogin && (
<img src="/images/icon.png" alt="logo" className="w-[45px]" />
)}
{loadingLogin && <Spinner />}
</div>
</div>
<form onSubmit={onSubmit}>
<p className="text-[#212B36] font-medium text-[25px] mt-0 mb-[15px] text-center">
Reset password
</p>
<input
type="password"
placeholder="Password"
className="w-full h-[48px] pl-[12px] pr-[70px] text-black border border-[#637381] rounded-[5px] outline-none text-[15px] mt-4"
onChange={(e) => setPassword(e.target.value)}
value={password}
/>
<input
type="password"
placeholder="Verify Password"
className="w-full h-[48px] pl-[12px] pr-[12px] text-black border border-[#637381] rounded-[5px] outline-none text-[15px] mt-4"
onChange={(e) => setVerifyPassword(e.target.value)}
value={verifyPassword}
/>
<div className="flex justify-center items-center mt-4">
<input
type="submit"
value="Reset"
disabled={isSubmitDisabled || loadingLogin}
className="bg-[#3c85ee] border border-[#3c85ee] hover:bg-[#326bcc] rounded-[5px] text-white text-[15px] font-medium cursor-pointer py-2 px-4 disabled:opacity-50 disabled:cursor-not-allowed"
/>
</div>
{(isSubmitDisabled || error) && (
<div className="mt-4">
<div className="flex justify-center items-center">
<AlertIcon className="w-[20px] text-red-600 mr-2" />
<p className="text-[#637381] text-[15px]">
{isSubmitDisabled ? "Passwords do not match" : error}
</p>
</div>
</div>
)}
</form>
</div>
</div>
<ToastContainer position="bottom-left" />
</div>
);
};
export default ResetPasswordPage;
-107
View File
@@ -1,107 +0,0 @@
import React from "react";
import Swal from "sweetalert2";
import axios from "../../axiosInterceptor";
import env from "../../enviroment/envFrontEnd";
import ResetPasswordPage from "./ResetPasswordPage";
class ResetPasswordPageContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
password: "",
verifyPassword: "",
passwordChanged: false,
}
}
passwordOnChange = (e) => {
const value = e.target.value;
this.setState(() => {
return {
...this.state,
password: value
}
})
}
verifyPasswordOnChange = (e) => {
const value = e.target.value;
this.setState(() => {
return {
...this.state,
verifyPassword : value
}
})
}
resetPassword = (e) => {
e.preventDefault()
if (this.state.passwordChanged) {
window.location.assign(env.url);
return;
}
const id = this.props.match.params.id;
if (this.state.password === this.state.verifyPassword) {
const data = {
passwordToken: id,
password: this.state.password
}
axios.post("/user-service/reset-password", data).then((response) => {
Swal.fire(
'Password Successfully Reset',
'You Have Successfully Resetted Your Password, All Sessions Have Been Logged Out.',
'success'
)
this.setState(() => {
return {
...this.state,
passwordChanged: true
}
})
}).catch((err) => {
console.log("reset password err", err);
Swal.fire({
icon: 'error',
title: 'Error',
text: 'Passwords Reset Error',
})
});
} else {
Swal.fire({
icon: 'error',
title: 'Error',
text: 'Passwords do not match',
})
}
}
render() {
return <ResetPasswordPage
resetPassword={this.resetPassword}
passwordOnChange={this.passwordOnChange}
verifyPasswordOnChange={this.verifyPasswordOnChange}
state={this.state}
{...this.props}/>
}
}
export default ResetPasswordPageContainer;
@@ -1,7 +1,7 @@
import React, { useState } from "react";
import React, { useRef, useState } from "react";
import SettingsChangePasswordPopup from "./SettingsChangePasswordPopup";
import { toast } from "react-toastify";
import { logoutAPI } from "../../api/user";
import { logoutAPI, resendVerifyEmailAPI } from "../../api/user";
import Swal from "sweetalert2";
import { useNavigate } from "react-router-dom";
@@ -9,11 +9,17 @@ interface SettingsPageAccountProps {
user: {
_id: string;
email: string;
emailVerified: boolean;
};
getUser: () => void;
}
const SettingsPageAccount: React.FC<SettingsPageAccountProps> = ({ user }) => {
const SettingsPageAccount: React.FC<SettingsPageAccountProps> = ({
user,
getUser,
}) => {
const [showChangePasswordPopup, setShowChangePasswordPopup] = useState(false);
const lastSentEmailVerifiation = useRef(0);
const navigate = useNavigate();
const logoutClick = async () => {
@@ -59,7 +65,7 @@ const SettingsPageAccount: React.FC<SettingsPageAccountProps> = ({ user }) => {
await toast.promise(logoutAPI(), {
pending: "Logging out all...",
success: "Logged out all",
error: "Error Logging Out Al",
error: "Error Logging Out all",
});
window.localStorage.removeItem("hasPreviouslyLoggedIn");
@@ -70,6 +76,32 @@ const SettingsPageAccount: React.FC<SettingsPageAccountProps> = ({ user }) => {
}
};
const resendEmailVerification = async () => {
try {
const currentDate = Date.now();
if (currentDate - lastSentEmailVerifiation.current < 1000 * 60 * 1) {
await Swal.fire({
title: "Please wait 1 minute before resending",
icon: "warning",
confirmButtonColor: "#3085d6",
confirmButtonText: "Okay",
});
return;
}
lastSentEmailVerifiation.current = Date.now();
await toast.promise(resendVerifyEmailAPI(), {
pending: "Resending email verification...",
success: "Email Verification Resent",
error: "Error Resending Email Verification",
});
getUser();
} catch (e) {
console.log("Error resending email verification", e);
}
};
return (
<div>
{showChangePasswordPopup && (
@@ -86,6 +118,21 @@ const SettingsPageAccount: React.FC<SettingsPageAccountProps> = ({ user }) => {
<p className="text-gray-primary">Email</p>
<p>{user.email}</p>
</div>
{"emailVerified" in user && (
<div className="px-3 py-4 flex flex-row justify-between items-center border-b border-gray-secondary">
<p className="text-gray-primary">
{user.emailVerified ? "Email verified" : "Email unverified"}
</p>
{!user.emailVerified && (
<button
className="text-primary hover:text-primary-hover cursor-pointer"
onClick={resendEmailVerification}
>
Resend
</button>
)}
</div>
)}
<div className="px-3 py-4 flex flex-row justify-between items-center border-b border-gray-secondary">
<p className="text-gray-primary">Change password</p>
<button
+14 -2
View File
@@ -6,13 +6,14 @@ import AccountIcon from "../../icons/AccountIcon";
import TuneIcon from "../../icons/TuneIcon";
import { useNavigate } from "react-router-dom";
import SettingsAccountSection from "./SettingsAccountSection";
import { getUserDetailedAPI } from "../../api/user";
import { getUserDetailedAPI, logoutAPI } from "../../api/user";
import Spinner from "../Spinner/Spinner";
import Swal from "sweetalert2";
import SettingsGeneralSection from "./SettingsGeneralSection";
import { useClickOutOfBounds } from "../../hooks/utils";
import MenuIcon from "../../icons/MenuIcon";
import { ToastContainer } from "react-toastify";
import { toast } from "react-toastify";
const SettingsPage = () => {
const [user, setUser] = useState(null);
@@ -36,6 +37,15 @@ const SettingsPage = () => {
confirmButtonText: "Yes, logout",
});
if (result.value) {
await toast.promise(logoutAPI(), {
pending: "Logging out...",
success: "Logged out",
error: "Error Logging Out",
});
window.localStorage.removeItem("hasPreviouslyLoggedIn");
navigate("/");
} else {
navigate("/home");
}
@@ -111,7 +121,9 @@ const SettingsPage = () => {
onClick={() => setShowSidebarMobile(!showSidebarMobile)}
/>
</div>
{tab === "account" && <SettingsAccountSection user={user} />}
{tab === "account" && (
<SettingsAccountSection user={user} getUser={getUser} />
)}
{tab === "general" && <SettingsGeneralSection />}
</div>
)}
@@ -1,9 +0,0 @@
import React from "react";
const VerifyEmailPage = (props) => (
<div className="verify-page__wrapper">
<p className="verify-page__title">{props.state.error ? "Verification Error" : props.state.verified ? "Email Verified" : "Verifying Email..."}</p>
</div>
)
export default VerifyEmailPage;
@@ -0,0 +1,37 @@
import { useParams } from "react-router-dom";
import { verifyEmailAPI } from "../../api/user";
import { toast, ToastContainer } from "react-toastify";
import { useEffect } from "react";
const VerifyEmailPage = () => {
const token = useParams().token!;
const verifyEmail = async () => {
try {
await toast.promise(verifyEmailAPI(token), {
pending: "Verifying email...",
success: "Email Verified",
error: "Error verifying email",
});
setTimeout(() => {
window.location.assign("/");
}, 1500);
} catch (e) {
console.log("Error verifying email", e);
}
};
useEffect(() => {
verifyEmail();
}, []);
return (
<div className="w-screen h-screen flex justify-center items-center flex-col">
<h1>Verifying email...</h1>
<ToastContainer position="bottom-left" />
</div>
);
};
export default VerifyEmailPage;
-73
View File
@@ -1,73 +0,0 @@
import React from "react";
import axios from "../../axiosInterceptor";
import Swal from "sweetalert2";
import VerifyEmailPage from "./VerifyEmailPage";
class VerifiyEmailPageContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
verified: false,
error: false,
}
}
componentDidMount = () => {
this.checkEmailVerification();
}
checkEmailVerification = () => {
const id = this.props.match.params.id
if (id) {
const data = {
emailToken: id
}
axios.post("/user-service/verify-email", data).then((response) => {
this.setState(() => {
return {
...this.state,
verified: true,
error: false
}
})
Swal.fire(
'Email Address Verified',
'You Have Successfully verified your email address, you may now log into myDrive.',
'success'
)
}).catch((err) => {
this.setState(() => {
return {
...this.state,
error: true
}
})
Swal.fire(
'Email Address Verifation Error',
'Could Not Verifiy Email Address',
'error'
)
})
}
}
render() {
return <VerifyEmailPage
state={this.state}/>
}
}
export default VerifiyEmailPageContainer;
+4 -4
View File
@@ -11,9 +11,9 @@ import HomePage from "../components/Homepage/Homepage";
import PrivateRoute from "./PrivateRoute";
import PublicRoute from "./PublicRoute";
import DownloadPage from "../components/DownloadPage/DownloadPage";
import VerifyEmailPage from "../components/VerifyEmailPage";
import VerifyEmailPage from "../components/VerifyEmailPage/VerifyEmailPage";
import uuid from "uuid";
import ResetPasswordPage from "../components/ResetPasswordPage";
import ResetPasswordPage from "../components/ResetPasswordPage/ResetPasswordPage";
import SettingsPage from "../components/SettingsPage/SettingsPage";
import Homepage from "../components/Homepage/Homepage";
import { usePreferenceSetter } from "../hooks/preferenceSetter";
@@ -95,8 +95,8 @@ const AppRouter = () => {
</PrivateRoute>
}
/>
<Route path="/verify-email/:id" element={<VerifyEmailPage />} />
<Route path="/reset-password/:id" element={<ResetPasswordPage />} />
<Route path="/verify-email/:token" element={<VerifyEmailPage />} />
<Route path="/reset-password/:token" element={<ResetPasswordPage />} />
<Route
path="/settings"
element={