Skip to content

Commit

Permalink
Resend verify email functionality (#231)
Browse files Browse the repository at this point in the history
* resend verify email functionality

* run ze linter
  • Loading branch information
Connor Bechthold authored Feb 4, 2024
1 parent 354a64c commit c65109b
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 9 deletions.
15 changes: 15 additions & 0 deletions backend/app/rest/auth_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,3 +271,18 @@ def is_verified():
except Exception as e:
error_message = getattr(e, "message", None)
return jsonify({"error": (error_message if error_message else str(e))}), 500


@blueprint.route(
"/resend-verify/<string:email>", methods=["POST"], strict_slashes=False
)
def resend_verify(email):
"""
Resends a verification email to a specific email
"""
try:
auth_service.send_email_verification_link(email)
return "", 200
except Exception as e:
error_message = getattr(e, "message", None)
return jsonify({"error": (error_message if error_message else str(e))}), 500
2 changes: 1 addition & 1 deletion backend/app/services/implementations/auth_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,5 +253,5 @@ def is_authorized_by_token(self, access_token):
firebase_user = firebase_admin.auth.get_user(decoded_id_token["uid"])
return firebase_user.email_verified
except Exception as e:
print(e)
self.logger.error(e)
return False
16 changes: 16 additions & 0 deletions frontend/src/APIClients/AuthAPIClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,21 @@ const isVerified = async (): Promise<boolean> => {
}
};

const resendVerify = async (email: string): Promise<boolean> => {
const bearerToken = `Bearer ${getLocalStorageObjProperty(
AUTHENTICATED_USER_KEY,
"accessToken",
)}`;
try {
await baseAPIClient.post(`/auth/resend-verify/${email}`, {
headers: { Authorization: bearerToken },
});
return true;
} catch (error) {
return false;
}
};

// for testing only, refresh does not need to be exposed in the client
const refresh = async (): Promise<boolean> => {
try {
Expand Down Expand Up @@ -202,5 +217,6 @@ export default {
register,
resetPassword,
isVerified,
resendVerify,
refresh,
};
57 changes: 49 additions & 8 deletions frontend/src/components/pages/Auth/VerificationPage.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
import React, { useState, useContext } from "react";
import { useHistory } from "react-router-dom";
import { Box, Button, Flex, Spinner, Text } from "@chakra-ui/react";
import authAPIClient from "../../../APIClients/AuthAPIClient";
import CreateToast from "../../common/Toasts";
import AuthContext from "../../../contexts/AuthContext";
import { HOME_PAGE } from "../../../constants/Routes";
import AUTHENTICATED_USER_KEY from "../../../constants/AuthConstants";
import { AuthenticatedUser } from "../../../types/AuthTypes";
import AuthAPIClient from "../../../APIClients/AuthAPIClient";

const VerificationPage = (): React.ReactElement => {
const newToast = CreateToast();
const history = useHistory();
const { authenticatedUser, setAuthenticatedUser } = useContext(AuthContext);

const [isLoading, setIsLoading] = useState<boolean>(false);
const [isVerifyLoading, setIsVerifyLoading] = useState<boolean>(false);
const [isResendLoading, setIsResendLoading] = useState<boolean>(false);

const handleVerification = async () => {
if (authenticatedUser) {
setIsLoading(true);
const isVerified = await authAPIClient.isVerified();
setIsVerifyLoading(true);
const isVerified = await AuthAPIClient.isVerified();

if (isVerified === false) {
setIsLoading(false);
setIsVerifyLoading(false);
newToast(
"Not Verified",
"Please check your email for the verification email.",
Expand All @@ -44,6 +45,26 @@ const VerificationPage = (): React.ReactElement => {
}
};

const resendVerify = async () => {
if (authenticatedUser) {
const { email } = authenticatedUser;
setIsResendLoading(true);

const success = await AuthAPIClient.resendVerify(email);

if (success) {
newToast("Success", `An email has been resent to ${email}.`, "success");
} else {
newToast(
"Error",
`Unable to resend an email to ${email}. Please try again.`,
"error",
);
}
setIsResendLoading(false);
}
};

return (
<Flex h="100vh">
<Box w="47%">
Expand All @@ -60,13 +81,14 @@ const VerificationPage = (): React.ReactElement => {

<Box w="80%" textAlign="left">
<Text variant="loginSecondary">
In order to start using your SHOW account, you need to confirm
your email address.
To verify your email address, a verification link has been sent to
your inbox. After clicking the link in the email, click the button
below to proceed.
</Text>
</Box>

<Box w="80%">
{isLoading ? (
{isVerifyLoading ? (
<Flex flexDirection="column" alignItems="center">
<Spinner
thickness="4px"
Expand All @@ -91,6 +113,25 @@ const VerificationPage = (): React.ReactElement => {
</Button>
)}
</Box>

<Box w="80%">
<Flex gap="10px">
<Text variant="loginSecondary">
Didn&apos;t recieve an email?
</Text>
<Text variant="loginTertiary" onClick={() => resendVerify()}>
Click here to resend
</Text>
{isResendLoading && (
<Spinner
thickness="4px"
speed="0.65s"
emptyColor="gray.200"
size="md"
/>
)}
</Flex>
</Box>
</Flex>
</Box>

Expand Down

0 comments on commit c65109b

Please sign in to comment.