Skip to content

Commit

Permalink
689 Run prettier and lean up auth PR
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Schroer committed Feb 9, 2024
1 parent 76f01dc commit 84b26d0
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 91 deletions.
6 changes: 4 additions & 2 deletions app/components/AppProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ export const AppProvider = ({
if (
authObject.isAuthenticated &&
authObject.accessTokenObject.expiresAt &&
AuthService.hasAccessTokenExpired(new Date(authObject.accessTokenObject.expiresAt))
AuthService.hasAccessTokenExpired(
new Date(authObject.accessTokenObject.expiresAt)
)
) {
AuthService.refreshAccessToken(contextValue.authClient)
.then((result: unknown) => {
Expand All @@ -82,7 +84,7 @@ export const AppProvider = ({
},
});
} else {
throw new Error("Token does not exist or is in unexpected token");
throw new Error("Token does not exist or is unexpected token");
}
})
.catch((err) => {
Expand Down
2 changes: 1 addition & 1 deletion app/components/ui/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ const SiteLinks = () => {
*/}
{authState.isAuthenticated && (
<li>
<Link to="/log-out">Sign Out</Link>
<Link to="/log-out">Log Out</Link>
</li>
)}
<li>
Expand Down
6 changes: 1 addition & 5 deletions app/pages/Auth/LogoutPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@ export const LogoutPage = () => {
const authClient = context.authClient as WebAuth;

useEffect(() => {
AuthService.logout(
authClient,
Config.AUTH0_CLIENT_ID,
setAuthState
);
AuthService.logout(authClient, Config.AUTH0_CLIENT_ID, setAuthState);
});

return <Redirect to="/" />;
Expand Down
25 changes: 16 additions & 9 deletions app/pages/Auth/SignUpPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,20 @@ export const SignUpPage = () => {

const signUp = (evt: React.SyntheticEvent) => {
evt.preventDefault();
initializeUserSignUp(authClient, email).then(() => {
setModalIsOpen(true);
}, (error) => {
if (error.message === 'userExists') {
// eslint-disable-next-line no-alert
// Todo: Handle this case with a proper error message
alert('Oops, there is already a user with that email in our system. Please try logging in instead.');
initializeUserSignUp(authClient, email).then(
() => {
setModalIsOpen(true);
},
(error) => {
if (error.message === "userExists") {
// eslint-disable-next-line no-alert
// TODO: Handle this case with a proper error message
alert(

Check warning on line 30 in app/pages/Auth/SignUpPage.tsx

View workflow job for this annotation

GitHub Actions / lint

Unexpected alert
"Oops, it looks like you may have already signed up. Please try logging in instead."
);
}
}
})
);
};

return (
Expand Down Expand Up @@ -71,7 +76,9 @@ export const SignUpPage = () => {
email={email}
modalIsOpen={modalIsOpen}
setModalIsOpen={setModalIsOpen}
verifyCode={(code) => completeUserSignup(authClient, code, email, name, organization)}
verifyCode={(code) =>
completeUserSignup(authClient, code, email, name, organization)
}
resendCode={() => passwordlessStart(authClient, email)}
buttonText="Sign up"
/>
Expand Down
44 changes: 12 additions & 32 deletions app/pages/Auth/VerificationModal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, createRef, useEffect } from "react";
import React, { useState, createRef } from "react";
import { Modal } from "components/ui/Modal/Modal";
import { Button } from "components/ui/inline/Button/Button";

Expand Down Expand Up @@ -98,39 +98,19 @@ export const VerificationModal = ({
};

const ResendCode = ({ resendCode }: { resendCode: () => Promise<unknown> }) => {
const [timeLeft, setTimeLeft] = useState(60);
const [codeResent, setCodeResent] = useState(false);

useEffect(() => {
const interval = setInterval(() => {
if (timeLeft === 0) {
clearInterval(interval);
resendCode();
setCodeResent(true);
return;
}

setTimeLeft(timeLeft - 1);
}, 1000);

return () => clearInterval(interval);
}, [resendCode, setTimeLeft, timeLeft]);

return (
<div>
{codeResent ? (
<p>
Didn&apos;t receive a code?
<button type="button" onClick={() => {resendCode()}}>
Resend
</button>
</p>
) : (
<>
<strong>Resend code in:</strong>
{timeLeft}
</>
)}
<p>
Didn&apos;t receive a code? Please check your spam folder.
<button
type="button"
onClick={() => {
resendCode();
}}
>
Send another code.
</button>
</p>
</div>
);
};
4 changes: 2 additions & 2 deletions app/pages/HomePage/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ export const HomePage = () => {
});

useEffect(() => {
// Todo: This effect should be moved to the case worker UI homepage when that page is created
// TODO: This effect should be moved to the case worker UI homepage when that page is created
const { hash } = window.location;
if (!hash || !hash.includes("access_token")) return;

AuthService.persistUser(
AuthService.initializeUserSession(
window.location.hash,
authClient as WebAuth,
setAuthState
Expand Down
94 changes: 55 additions & 39 deletions app/utils/AuthService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { AuthState } from "components/AppProvider";

/*
This class provides a set of methods that serve as an interface between our application
and the Auth0 servers where the user's state and data is stored.
and the Auth0 servers where the user's auth state and data is stored.
*/

export default class AuthService {
Expand All @@ -18,7 +18,11 @@ export default class AuthService {
return expirationTime;
}

static persistUser(hash: string, authClient: WebAuth, setAuthState: any) {
static initializeUserSession(
hash: string,
authClient: WebAuth,
setAuthState: any
) {
authClient.parseHash({ hash }, (err, authResult) => {
if (err) {
// TODO: Handle errors
Expand Down Expand Up @@ -49,39 +53,41 @@ export default class AuthService {
return new Promise((resolve, reject) => {
this.userExists(email).then((exists) => {
if (exists) {
reject(new Error('userExists'));
reject(new Error("userExists"));
} else {
this.passwordlessStart(authClient, email).then((result) => {
resolve(result);
})
});
}
});
});
};

// Invokes the passwordlessLogin method and following that saves the user to our database
static completeUserSignup = (authClient: WebAuth,
static completeUserSignup = (
authClient: WebAuth,
verificationCode: string,
email: string,
name: string,
organization: (string | null) = null) => {
this.passwordlessLogin(authClient, email, verificationCode);
// We need to optimistically save the user to our database here. The user is saved to the _Auth0_
// database after the passwordlessLogin method succeeds. We also want to save user data in our
// backend. This should be done after a success callback after passwordlessLogin succceds; however,
// the passwordlessLogin success callback does not fire within our app, because, upon success, Auth0
// triggers a redirect to our home page. At that point, we do not have the user's name or organization,
// which we need to save in our database. Thus, we save the user here.
//
// If for some reason, the passwordlessLogin method errors, this code still save the user in our DB.
// At that point, the worst case scenario is that the user will be informed that they have already
// signed up if they try to sign up again and to log in instead. Since the Auth0 passwordless flow
// does not have a sign-up process separate from its log-in process, and thus the user will still
// be created within Auth0 upon going through our site's log-in flow.
this.saveUser(email, name, organization);
organization: string | null = null
) => {
this.passwordlessLogin(authClient, email, verificationCode);
// We need to optimistically save the user to our database here. The user is saved to the _Auth0_
// database after the passwordlessLogin method succeeds. Following that we need to save user data in our
// backend. Ideally, this should be done after a success callback after passwordlessLogin succceds;
// however, the passwordlessLogin success callback does not fire within our app, because, upon success, Auth0
// triggers a redirect to our home page. At that point, we do not have the user's name or organization,
// which we need to save in our database. Thus, we save the user here.
//
// If for some reason, the passwordlessLogin method errors, this code still save the user in our DB.
// At that point, the worst case scenario is that the user will be informed that they have already
// signed up if they try to sign up again and to log in instead. The Auth0 passwordless flow does
// not have a sign-up process separate from its log-in process, and thus the user will still be
// created within Auth0 upon going through our site's log-in flow.
this.saveUser(email, name, organization);
};

// This method initiates the sign-in/sign-up process by sending a code
// This method initiates the log-in/sign-up process by sending a code
// to the user's inbox.
static passwordlessStart = (authClient: WebAuth, email: string) => {
return new Promise((resolve, reject) => {
Expand Down Expand Up @@ -109,7 +115,7 @@ export default class AuthService {
authClient: WebAuth,
email: string,
verificationCode: string
) => {
) => {
authClient.passwordlessLogin(
{
connection: "email",
Expand Down Expand Up @@ -138,7 +144,7 @@ export default class AuthService {
};

static hasAccessTokenExpired = (tokenExpiration: Date) => {
return !tokenExpiration || (new Date(tokenExpiration) < new Date());
return !tokenExpiration || new Date(tokenExpiration) < new Date();
};

static refreshAccessToken = (authClient: WebAuth) => {
Expand All @@ -155,28 +161,38 @@ export default class AuthService {

static userExists = (email: string) => {
return new Promise((resolve, reject) => {
post('/api/users/user_exists', {
email
}).then((resp) => {
resp.json().then(result => resolve(result.user_exists));
}, (error) => {
reject(error);
})
post("/api/users/user_exists", {
email,
}).then(
(resp) => {
resp.json().then((result) => resolve(result.user_exists));
},
(error) => {
reject(error);
}
);
});
}
};

static saveUser = (email: string, name: string, organization: (string | null) = null) => {
static saveUser = (
email: string,
name: string,
organization: string | null = null
) => {
return new Promise((resolve, reject) => {
const response = post('/api/users', {
const response = post("/api/users", {
email,
name,
organization,
});
response.then((result) => {
resolve(result);
}, (error) => {
reject(error);
})
response.then(
(result) => {
resolve(result);
},
(error) => {
reject(error);
}
);
});
}
};
}
2 changes: 1 addition & 1 deletion config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ MOHCD_SUBDOMAIN: "testing"
AUTH0_AUDIENCE: "http://localhost:8080/api"
AUTH0_CLIENT_ID: "UcnuRrX6S0SeDEhW9PRe01wEhcvIRuwc"
AUTH0_DOMAIN: "dev-nykixf8szsm220fi.us.auth0.com"
AUTH0_REDIRECT_URI: "http://localhost:8080"
AUTH0_REDIRECT_URI: "http://localhost:8080"

0 comments on commit 84b26d0

Please sign in to comment.