Skip to content

Conversation

@fahadakhan2
Copy link
Contributor

@fahadakhan2 fahadakhan2 commented Jul 2, 2024

Description:

  • Checks the email of the user that is trying to sign up. If it exists in the db than we send back a 400 and error message in the response
  • If the user doesn't already have an account than we go ahead and create and store it in our database.
  • When storing the password we are hashing and salting (using bcrypt) it and storing that product as the password in the db.
  • Reorganized the file structure for the handlers to include both the signup and in the future the signin functions to live inside user.ts.
  • Added sessions logic utilizing express-session and prisma-session-store

Happy Case:
Screenshot 2024-07-02 at 4 07 08 PM

Email Already Exists Case:
Screenshot 2024-07-02 at 4 07 54 PM

@fahadakhan2 fahadakhan2 self-assigned this Jul 3, 2024
@fahadakhan2 fahadakhan2 added the enhancement New feature or request label Jul 3, 2024
@fahadakhan2 fahadakhan2 marked this pull request as ready for review July 3, 2024 21:01
@fahadakhan2 fahadakhan2 requested a review from justinpchen94 July 8, 2024 01:31
next();
} else {
res.json({ message: 'Unauthorized access' });
res.redirect('/api/auth/sign-in');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have you tested this redirect? this should be a frontend URL not a backend API endpoint

Comment on lines +10 to +11
const THREE_DAYS = 1000 * 60 * 60 * 24 * 3;
const TWO_MINUTES = 1000 * 60 * 2;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: slightly more useful names like THREE_DAYS_IN_MS help make it clear what the units are

store: new PrismaSessionStore(new PrismaClient(), {
checkPeriod: TWO_MINUTES,
dbRecordIdIsSessionId: true,
dbRecordIdFunction: undefined,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it needed that you supply this as undefined? can we just omit?

import prisma from '../utils/prismaClient';
import { SessionData } from '../utils/types';

export const createNewUser = async (req: Request, res: Response) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generally it's good to redraw the boundaries of route handlers and controller functions such as these.

for example, idk if you're planning on adding testing, but it is a lot more annoying to test a function defined like this since you have to mock entire Request and Response arguments in order to unit test this function. generally, you'd have a light wrapper as a controller function that would only serve to pull the right arguments out of the request object and inject them into this controller fn, and then you'd update the return type of this fn in order to return the newly created User object or a boolean, depending on your exact logic

export const createNewUser = async (firstName, lastName, email, rawPassword) {...}

Comment on lines +24 to +25
req: Request,
res: Response
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar here, this fn is meant to do something very simple, there's no need to throw the entire request and response objects into here, when simply accepting an email and returning a boolean are enough.

import { NextFunction, Request, Response } from 'express';

export const getHashedPlusSaltedPassword = (password: string) => {
return bcrypt.hash(password, 5);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: make the salt rounds variable a constant, it's not clear what that value is otherwise

};

// middleware to be used to check if the user is authenticated or not on protected routes (to be used for future routes)
export const isAuth = (req: Request, res: Response, next: NextFunction) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given that your session field is isAuth i'd rename this fn to be more informative. since this is a middleware, you could do something like checkAuthenticatedSession, which is a clear enough name that you can remove the comment above

return false;
};

// sign in
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rm

export const createNewUser = async (req: Request, res: Response) => {
const emailExists: boolean = await doesEmailExistInDatabase(req, res);

if (!emailExists) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if the email exists? doesn't look like the response ever ends if it does

password: await getHashedPlusSaltedPassword(req.body.password),
},
});
req.session.isAuth = true;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if you've tested this but the express docs seem to imply that you should use the regenerate and save methods. other docs suggest that you don't have to explicitly call save though, so I'm unsure what is currently best practice

Session.save(callback)
Save the session back to the store, replacing the contents on the store with the contents in memory (though a store may do something else–consult the store’s documentation for exact behavior).

This method is automatically called at the end of the HTTP response if the session data has been altered (though this behavior can be altered with various options in the middleware constructor). Because of this, typically this method does not need to be called.

There are some cases where it is useful to call this method, for example, redirects, long-lived requests or in WebSockets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants