Skip to content

Commit

Permalink
[feat] refines the auth flows (#76)
Browse files Browse the repository at this point in the history
* creates password complexity component and adds it to the signup and reset password pages

* adds error message for not-complex-enough password to reset password page

* adds confirm password input to the signup screen

* adds existing user check (doesn't work)

* fixes user already exists check

* fixes type error (jinkang is not gonna like this)

* adds password cannot be same as previous check, cleans up error messages

* makes changes to fix the console error for PasswordComplexity

* fixes the documentation for the Supabase password verification query

* me when i move the formdiv from the layout to every file

* rebases, replaces all FormDivs with SmallCardForm

* makes changes in response to feedback

* replaces all SpacerDiv with Flex

* makes changes in response to feedback

* switches back from testing link

* fixes ts compiler errors

* uses CONFIG.onboardingHome instead of /onboarding

* addresses nits

* updates error messages

* fixes hacky email wxists check

* addresses nits

* removes punctuation from email/password error messages
  • Loading branch information
pragyakallanagoudar authored May 19, 2024
1 parent c24ce44 commit eed1657
Show file tree
Hide file tree
Showing 12 changed files with 280 additions and 213 deletions.
17 changes: 17 additions & 0 deletions src/api/supabase/queries/email.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import supabase from '../createClient';

/**
* Checks if the current email is already tied to a user account.
* @returns a Promise of whether the email is already in use
*/
export async function checkEmailExists(email: string): Promise<boolean> {
const { data, error } = await supabase.rpc('check_email_exists', {
p_email: email,
});

if (error) {
throw new Error(`Error checking email existence: ${error.message}`);
}

return data;
}
4 changes: 4 additions & 0 deletions src/api/supabase/queries/limitedCaseAssignments.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { LimitedCaseAssignment } from '@/types/schema';
import supabase from '../createClient';

/**
* Fetches all non-case-specific language support entries from the database
* @returns a Promise of all non-case-specific language support objects
*/
export async function getAllLCA(): Promise<LimitedCaseAssignment[]> {
const { data, error } = await supabase.rpc('get_lca');

Expand Down
17 changes: 17 additions & 0 deletions src/api/supabase/queries/password.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import supabase from '../createClient';

/**
* Checks if the current password is different from the current user's password
* @returns a Promise of whether the password is different
*/
export async function verifyUserPassword(password: string): Promise<boolean> {
const { data, error } = await supabase.rpc('verify_user_password', {
password,
});

if (error) {
throw new Error(`Error verifying user password: ${error.message}`);
}

return data;
}
18 changes: 10 additions & 8 deletions src/app/(auth)/confirm-reset-password/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
'use client';

import { BigBlueLinkButton } from '@/components/Buttons';
import { H2Centered, H4 } from '@/styles/text';
import { SpacerDiv } from '../styles';
import { Flex, SmallCard } from '@/styles/containers';
import { H2, H4 } from '@/styles/text';

export default function ConfirmResetPassword() {
return (
<SpacerDiv>
<H2Centered>Your password has been reset!</H2Centered>
<BigBlueLinkButton href="/login">
<H4 $color="white">Go to Log In</H4>
</BigBlueLinkButton>
</SpacerDiv>
<SmallCard>
<Flex $direction="column" $gap="20px">
<H2>Your password has been reset.</H2>
<BigBlueLinkButton href="/login">
<H4 $color="white">Go to Log In</H4>
</BigBlueLinkButton>
</Flex>
</SmallCard>
);
}
19 changes: 11 additions & 8 deletions src/app/(auth)/email-verified/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
'use client';

import { SpacerDiv } from '@/app/(auth)/styles';
import { BigBlueLinkButton } from '@/components/Buttons';
import { H2Centered } from '@/styles/text';
import CONFIG from '@/lib/configs';
import { Flex, SmallCard } from '@/styles/containers';
import { H2 } from '@/styles/text';

export default function EmailVerified() {
return (
<SpacerDiv>
<H2Centered>Your email has been verified!</H2Centered>
<BigBlueLinkButton type="button" href="/onboarding/roles">
Go to Onboarding
</BigBlueLinkButton>
</SpacerDiv>
<SmallCard>
<Flex $direction="column" $gap="20px">
<H2>Your email has been verified!</H2>
<BigBlueLinkButton type="button" href={CONFIG.onboardingHome}>
Go to Onboarding
</BigBlueLinkButton>
</Flex>
</SmallCard>
);
}
87 changes: 43 additions & 44 deletions src/app/(auth)/forgot-password/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,69 +3,68 @@
import { useState } from 'react';
import isEmail from 'validator/lib/isEmail';
import supabase from '@/api/supabase/createClient';
import { HorizontalDiv, SpacerDiv } from '@/app/(auth)/styles';
import { HorizontalDiv } from '@/app/(auth)/styles';
import { BigBlueButton, Button } from '@/components/Buttons';
import TextInput from '@/components/TextInput/index';
import COLORS from '@/styles/colors';
import { Flex, SmallCardForm } from '@/styles/containers';
import { H1, H2, H4, P } from '@/styles/text';

export default function ForgotPassword() {
const [email, setEmail] = useState('');
const [emailSentCount, setEmailSentCount] = useState(0);
const [emailError, setEmailError] = useState('');

const sendPasswordResetLink = async () => {
const handleForgotPassword = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!isEmail(email)) {
setEmailError('Could not find email');
setEmailError('Email not found');
return;
}
await supabase.auth.resetPasswordForEmail(email, {
const { error } = await supabase.auth.resetPasswordForEmail(email, {
redirectTo:
'https://immigration-justice-project.vercel.app/reset-password',
});
if (error) {
setEmailError('Something went wrong. Please try again later.');
return;
}
setEmailSentCount(emailSentCount + 1);
};

return (
<>
{!emailSentCount && (
<>
<H1>Forgot Password</H1>
<TextInput
label="Email"
placeholder="[email protected]"
type="email"
id="email"
errorText={emailError}
value={email}
setValue={setEmail}
/>
<BigBlueButton type="button" onClick={sendPasswordResetLink}>
<H4 $color="white">Send link to email</H4>
return emailSentCount === 0 ? (
<SmallCardForm onSubmit={handleForgotPassword}>
<H1>Forgot Password</H1>
<TextInput
label="Email"
placeholder="[email protected]"
type="email"
id="email"
errorText={emailError}
value={email}
setValue={setEmail}
/>
<BigBlueButton type="submit">
<H4 $color="white">Send link to email</H4>
</BigBlueButton>
</SmallCardForm>
) : (
<SmallCardForm onSubmit={handleForgotPassword}>
<Flex $direction="column" $gap="20px">
<H2>A password reset link has been sent to your email.</H2>
<H4 $color={COLORS.greyDark}>
This link will direct you to the next step. If you didn’t receive an
email, please click Resend Email.
</H4>
<HorizontalDiv>
<BigBlueButton type="submit">
<H4 $color="white">Resend Email</H4>
</BigBlueButton>
</>
)}
{emailSentCount > 0 && (
<SpacerDiv>
<H2>A password reset link has been sent to your email.</H2>
<H4 $color={COLORS.greyDark}>
This link will direct you to the next step. If you didn’t receive an
email, please click Resend Email.
</H4>
<HorizontalDiv>
<Button
$primaryColor={COLORS.blueMid}
$secondaryColor={COLORS.blueDark}
onClick={sendPasswordResetLink}
>
<H4 $color="white">Resend Email</H4>
</Button>
{emailSentCount > 1 && (
<P $color={COLORS.greyMid}>Email has been resent!</P>
)}
</HorizontalDiv>
</SpacerDiv>
)}
</>
{emailSentCount > 1 && (
<P $color={COLORS.greyMid}>Email has been resent!</P>
)}
</HorizontalDiv>
</Flex>
</SmallCardForm>
);
}
6 changes: 1 addition & 5 deletions src/app/(auth)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,5 @@ import { ReactNode } from 'react';
import { FormDiv, OuterDiv } from './styles';

export default function layout({ children }: { children: ReactNode }) {
return (
<OuterDiv>
<FormDiv>{children}</FormDiv>
</OuterDiv>
);
return <OuterDiv>{children}</OuterDiv>;
}
39 changes: 22 additions & 17 deletions src/app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
import { useContext, useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import isEmail from 'validator/lib/isEmail';
import { H4Centered, SpacerDiv } from '@/app/(auth)/styles';
import { H4Centered } from '@/app/(auth)/styles';
import { BigBlueButton } from '@/components/Buttons';
import TextInput from '@/components/TextInput/index';
import CONFIG from '@/lib/configs';
import COLORS from '@/styles/colors';
import { Flex, SmallCardForm } from '@/styles/containers';
import { H1, LinkColored, P } from '@/styles/text';
import { useAuth } from '@/utils/AuthProvider';
import { ProfileContext } from '@/utils/ProfileProvider';
Expand All @@ -33,9 +34,15 @@ export default function Login() {
if (auth.userId && !isLoggingIn) push(CONFIG.settings);
}, [auth, profile, push, isLoggingIn]);

const handleSignIn = async () => {
setEmailError(validEmail(email) ? '' : 'Invalid Email');
setPasswordError(password !== '' ? '' : 'Invalid Password');
const handleSignIn = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!auth) {
setErrorMessage('');
return;
}

setEmailError(validEmail(email) ? '' : 'Email not found');
setPasswordError(password !== '' ? '' : 'Password is incorrect');
if (!validEmail(email) || password === '') {
setErrorMessage('');
return;
Expand Down Expand Up @@ -68,13 +75,13 @@ export default function Login() {
};

return (
<>
<SpacerDiv $gap={0.625}>
<SmallCardForm onSubmit={handleSignIn}>
<Flex $direction="column" $gap="10px">
<H1>Log In</H1>
{errorMessage !== '' && <P $color={COLORS.redMid}>{errorMessage}</P>}
</SpacerDiv>
<SpacerDiv $gap={0.8125}>
<SpacerDiv>
</Flex>
<Flex $direction="column" $gap="13px">
<Flex $direction="column" $gap="20px">
<TextInput
label="Email"
placeholder="[email protected]"
Expand All @@ -93,24 +100,22 @@ export default function Login() {
value={password}
setValue={setPassword}
/>
</SpacerDiv>
</Flex>
<P>
<LinkColored href="/forgot-password" $color={COLORS.greyMid}>
Forgot your password?
</LinkColored>
</P>
</SpacerDiv>
<SpacerDiv>
<BigBlueButton type="button" onClick={handleSignIn}>
Log in
</BigBlueButton>
</Flex>
<Flex $direction="column" $gap="20px">
<BigBlueButton type="submit">Log In</BigBlueButton>
<H4Centered>
Don’t have an account yet?{' '}
<LinkColored $color={COLORS.greyDark} href="/signup">
Sign up
</LinkColored>
</H4Centered>
</SpacerDiv>
</>
</Flex>
</SmallCardForm>
);
}
Loading

0 comments on commit eed1657

Please sign in to comment.